* [PATCH v4] ARM: mxs: Change duart device to use amba-pl011
From: Wolfram Sang @ 2011-01-10 13:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294122052-18329-1-git-send-email-shawn.guo@freescale.com>
On Tue, Jan 04, 2011 at 02:20:52PM +0800, Shawn Guo wrote:
> The mxs duart is actually an amba-pl011 device. This commit changes
> the duart device code to dynamically allocate amba-pl011 device,
> so that drivers/serial/amba-pl011.c can be used on mxs.
>
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110110/ea3d0e4f/attachment-0001.sig>
^ permalink raw reply
* [PATCH] watchdog: add support for the Synopsys DesignWare WDT
From: Jamie Iles @ 2011-01-10 13:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110110132115.GM3801@infomag.iguana.be>
On Mon, Jan 10, 2011 at 02:21:15PM +0100, Wim Van Sebroeck wrote:
> Hi Jamie,
>
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index 8a3aa2f..0981aae 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -331,6 +331,15 @@ config IMX2_WDT
> > To compile this driver as a module, choose M here: the
> > module will be called imx2_wdt.
> >
> > +config DW_WATCHDOG
> > + tristate "Synopsys DesignWare watchdog"
> > + select WATCHDOG_NOWAYOUT
> > + help
> > + Say Y here if to include support for the Synopsys DesignWare
> > + watchdog timer found in many ARM chips.
> > + To compile this driver as a module, choose M here: the
> > + module will be called dw_wdt.
> > +
> > # AVR32 Architecture
> >
> > config AT32AP700X_WDT
>
> Could you add the correct dependancy also in Kconfig?
Sure, updated patch below with a dependency on ARM.
Jamie
8<----------------------------------------------------------------------
^ permalink raw reply
* [PATCH 3/3] omap3: igep2: Add keypad support.
From: Enric Balletbo i Serra @ 2011-01-10 13:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294665974-10590-1-git-send-email-eballetbo@gmail.com>
Support twl4030 keypad and gpio keys on IGEP v2.
Signed-off-by: Enric Balletbo i Serra <eballetbo@gmail.com>
---
arch/arm/mach-omap2/board-igep0020.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0afa301..3a6cce5 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
+#include <linux/input.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
@@ -535,6 +536,37 @@ static struct twl4030_codec_data igep2_codec_data = {
.audio = &igep2_audio_data,
};
+static int igep2_keymap[] = {
+ KEY(0, 0, KEY_LEFT),
+ KEY(0, 1, KEY_RIGHT),
+ KEY(0, 2, KEY_A),
+ KEY(0, 3, KEY_B),
+ KEY(1, 0, KEY_DOWN),
+ KEY(1, 1, KEY_UP),
+ KEY(1, 2, KEY_E),
+ KEY(1, 3, KEY_F),
+ KEY(2, 0, KEY_ENTER),
+ KEY(2, 1, KEY_I),
+ KEY(2, 2, KEY_J),
+ KEY(2, 3, KEY_K),
+ KEY(3, 0, KEY_M),
+ KEY(3, 1, KEY_N),
+ KEY(3, 2, KEY_O),
+ KEY(3, 3, KEY_P)
+};
+
+static struct matrix_keymap_data igep2_keymap_data = {
+ .keymap = igep2_keymap,
+ .keymap_size = ARRAY_SIZE(igep2_keymap),
+};
+
+static struct twl4030_keypad_data igep2_keypad_pdata = {
+ .keymap_data = &igep2_keymap_data,
+ .rows = 4,
+ .cols = 4,
+ .rep = 1,
+};
+
static struct twl4030_platform_data igep2_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
@@ -543,6 +575,7 @@ static struct twl4030_platform_data igep2_twldata = {
.usb = &igep2_usb_data,
.codec = &igep2_codec_data,
.gpio = &igep2_twl4030_gpio_pdata,
+ .keypad = &igep2_keypad_pdata,
.vmmc1 = &igep2_vmmc1,
.vpll2 = &igep2_vpll2,
.vio = &igep2_vio,
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/3] omap3: igep3: Fix IGEP module second MMC channel power supply.
From: Enric Balletbo i Serra @ 2011-01-10 13:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294665974-10590-1-git-send-email-eballetbo@gmail.com>
The second MMC channel (used by the WLAN/BT module) is not linked to
power regulator. This causes the WLAN/BT module to fail being detected if
CONFIG_REGULATOR_DUMMY is not set.
This patch adds the two regulators that actually feed the WLAN/BT module
(1v8 from the TWL4030 VIO LDO, and a fixed 3v3). With that patch, the
second channel is properly detected.
Also change vmmc1 to use symbolic names instead of direct device
reference.
Signed-off-by: Enric Balletbo i Serra <eballetbo@gmail.com>
---
arch/arm/mach-omap2/board-igep0030.c | 65 ++++++++++++++++++++++++++++-----
1 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index f0a85c1..8ddd45c 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <linux/i2c/twl.h>
#include <linux/mmc/host.h>
@@ -140,9 +141,8 @@ static void __init igep3_flash_init(void)
static void __init igep3_flash_init(void) {}
#endif
-static struct regulator_consumer_supply igep3_vmmc1_supply = {
- .supply = "vmmc",
-};
+static struct regulator_consumer_supply igep3_vmmc1_supply =
+ REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
static struct regulator_init_data igep3_vmmc1 = {
@@ -159,6 +159,52 @@ static struct regulator_init_data igep3_vmmc1 = {
.consumer_supplies = &igep3_vmmc1_supply,
};
+static struct regulator_consumer_supply igep3_vio_supply =
+ REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep3_vio = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .apply_uV = 1,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
+ | REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &igep3_vio_supply,
+};
+
+static struct regulator_consumer_supply igep3_vmmc2_supply =
+ REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+
+static struct regulator_init_data igep3_vmmc2 = {
+ .constraints = {
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .always_on = 1,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &igep3_vmmc2_supply,
+};
+
+static struct fixed_voltage_config igep3_vwlan = {
+ .supply_name = "vwlan",
+ .microvolts = 3300000,
+ .gpio = -EINVAL,
+ .enabled_at_boot = 1,
+ .init_data = &igep3_vmmc2,
+};
+
+static struct platform_device igep3_vwlan_device = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &igep3_vwlan,
+ },
+};
+
static struct omap2_hsmmc_info mmc[] = {
[0] = {
.mmc = 1,
@@ -254,12 +300,6 @@ static int igep3_twl4030_gpio_setup(struct device *dev,
mmc[0].gpio_cd = gpio + 0;
omap2_hsmmc_init(mmc);
- /*
- * link regulators to MMC adapters ... we "know" the
- * regulators will be set up only *after* we return.
- */
- igep3_vmmc1_supply.dev = mmc[0].dev;
-
/* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
@@ -287,6 +327,10 @@ static struct twl4030_usb_data igep3_twl4030_usb_data = {
.usb_mode = T2_USB_MODE_ULPI,
};
+static struct platform_device *igep3_devices[] __initdata = {
+ &igep3_vwlan_device,
+};
+
static void __init igep3_init_irq(void)
{
omap2_init_common_infrastructure();
@@ -303,6 +347,7 @@ static struct twl4030_platform_data igep3_twl4030_pdata = {
.usb = &igep3_twl4030_usb_data,
.gpio = &igep3_twl4030_gpio_pdata,
.vmmc1 = &igep3_vmmc1,
+ .vio = &igep3_vio,
};
static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
@@ -387,7 +432,7 @@ static void __init igep3_init(void)
/* Register I2C busses and drivers */
igep3_i2c_init();
-
+ platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
omap_serial_init();
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/3] omap3: igep3: Add USB EHCI support for IGEP module.
From: Enric Balletbo i Serra @ 2011-01-10 13:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294665974-10590-1-git-send-email-eballetbo@gmail.com>
The OMAP3 IGEP module has one EHCI interface on board using
USB2HS port. GPIO183 is used as PHY reset.
Signed-off-by: Enric Balletbo i Serra <eballetbo@gmail.com>
---
arch/arm/mach-omap2/board-igep0030.c | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index c88e8f7..f0a85c1 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -43,7 +43,7 @@
#define IGEP3_GPIO_WIFI_NRESET 139
#define IGEP3_GPIO_BT_NRESET 137
-#define IGEP3_GPIO_USBH_NRESET 115
+#define IGEP3_GPIO_USBH_NRESET 183
#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -363,8 +363,20 @@ static void __init igep3_wifi_bt_init(void)
void __init igep3_wifi_bt_init(void) {}
#endif
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+ .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+ .phy_reset = true,
+ .reset_gpio_port[0] = -EINVAL,
+ .reset_gpio_port[1] = IGEP3_GPIO_USBH_NRESET,
+ .reset_gpio_port[2] = -EINVAL,
+};
+
#ifdef CONFIG_OMAP_MUX
static struct omap_board_mux board_mux[] __initdata = {
+ OMAP3_MUX(I2C2_SDA, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
#endif
@@ -378,6 +390,7 @@ static void __init igep3_init(void)
omap_serial_init();
usb_musb_init(&musb_board_data);
+ usb_ehci_init(&ehci_pdata);
igep3_flash_init();
igep3_leds_init();
--
1.7.0.4
^ permalink raw reply related
* [PATCH 0/3] IGEP board changes for .38 merge window
From: Enric Balletbo i Serra @ 2011-01-10 13:26 UTC (permalink / raw)
To: linux-arm-kernel
Hi Tony,
Here's a new patches for IGEP boards. These patches are rebased on top of your
for-next tree. Please consider adding for .38 merge window. Thanks.
Cheers,
Enric Balletbo i Serra (3):
omap3: igep3: Add USB EHCI support for IGEP module.
omap3: igep3: Fix IGEP module second MMC channel power supply.
omap3: igep2: Add keypad support.
arch/arm/mach-omap2/board-igep0020.c | 33 ++++++++++++++
arch/arm/mach-omap2/board-igep0030.c | 80 +++++++++++++++++++++++++++++-----
2 files changed, 102 insertions(+), 11 deletions(-)
^ permalink raw reply
* [PATCH] dmaengine: at_hdmac: use dma_address to program DMA hardware
From: Nicolas Ferre @ 2011-01-10 13:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1292435416-16927-1-git-send-email-nicolas.ferre@atmel.com>
Le 15/12/2010 18:50, Nicolas Ferre :
> In atc_prep_slave_sg() function we use dma_address field of scatterlist with
> sg_dma_address() macro instead of sg_phys(). DMA address is already computed
> by dma_map_sg() or another mapping function in calling driver.
Ping?
> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> ---
> drivers/dma/at_hdmac.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
> index ea0ee81..ee7dacd 100644
> --- a/drivers/dma/at_hdmac.c
> +++ b/drivers/dma/at_hdmac.c
> @@ -670,7 +670,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
> if (!desc)
> goto err_desc_get;
>
> - mem = sg_phys(sg);
> + mem = sg_dma_address(sg);
> len = sg_dma_len(sg);
> mem_width = 2;
> if (unlikely(mem & 3 || len & 3))
> @@ -712,7 +712,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
> if (!desc)
> goto err_desc_get;
>
> - mem = sg_phys(sg);
> + mem = sg_dma_address(sg);
> len = sg_dma_len(sg);
> mem_width = 2;
> if (unlikely(mem & 3 || len & 3))
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] watchdog: add support for the Synopsys DesignWare WDT
From: Wim Van Sebroeck @ 2011-01-10 13:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294656906-24239-1-git-send-email-jamie@jamieiles.com>
Hi Jamie,
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index 8a3aa2f..0981aae 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -331,6 +331,15 @@ config IMX2_WDT
> To compile this driver as a module, choose M here: the
> module will be called imx2_wdt.
>
> +config DW_WATCHDOG
> + tristate "Synopsys DesignWare watchdog"
> + select WATCHDOG_NOWAYOUT
> + help
> + Say Y here if to include support for the Synopsys DesignWare
> + watchdog timer found in many ARM chips.
> + To compile this driver as a module, choose M here: the
> + module will be called dw_wdt.
> +
> # AVR32 Architecture
>
> config AT32AP700X_WDT
Could you add the correct dependancy also in Kconfig?
Thanks in advance,
Wim.
^ permalink raw reply
* [PATCH v4 3/3] omap3: beaglexm: fix power on of DVI
From: Aaro Koskinen @ 2011-01-10 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294441282-17986-4-git-send-email-nm@ti.com>
Hi,
On Fri, 7 Jan 2011, Nishanth Menon wrote:
> From: Koen Kooi <koen@beagleboard.org>
>
> TFP410 DVI chip is used to provide display out.
> This chip is controlled by 2 lines:
> LDO which supplies the power is controlled over gpio + 2
> and the enable of the chip itself is done over gpio + 1
> NOTE: the LDO is necessary for LED, serial blocks as well.
>
> gpio + 1 was used to sense USB overcurrent in vanilla beagle.
>
> Without this fix, the display would not function as the LDO
> remains shut down.
>
> [nm at ti.com: split up, added descriptive changelogs]
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Koen Kooi <koen@beagleboard.org>
> ---
> arch/arm/mach-omap2/board-omap3beagle.c | 20 +++++++++++++++++---
> 1 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index d628f5e..7c82730 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -293,9 +293,10 @@ static int beagle_twl_gpio_setup(struct device *dev,
> /* REVISIT: need ehci-omap hooks for external VBUS
> * power switch and overcurrent detect
> */
> -
> - gpio_request(gpio + 1, "EHCI_nOC");
> - gpio_direction_input(gpio + 1);
> + if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
> + gpio_request(gpio + 1, "EHCI_nOC");
> + gpio_direction_input(gpio + 1);
> + }
>
> /*
> * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
> @@ -317,6 +318,19 @@ static int beagle_twl_gpio_setup(struct device *dev,
> /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
> gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
>
> + /*
> + * gpio + 1 on Xm controls the TFP410's enable line (active low)
> + * gpio + 2 control varies depending on the board rev as follows:
> + * P7/P8 revisions(prototype): Camera EN
> + * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
> + */
> + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
> + gpio_request(gpio + 1, "nDVI_PWR_EN");
> + gpio_direction_output(gpio + 1, 0);
> + gpio_request(gpio + 2, "DVI_LDO_EN");
> + gpio_direction_output(gpio + 2, 1);
FYI, gpiolib provides gpio_request_one() and gpio_request_array() calls
which make code simpler. I think any new code should use those _and_
do proper error checking.
> + }
> +
> return 0;
> }
>
> --
> 1.6.3.3
>
^ permalink raw reply
* still nfs problems [Was: Linux 2.6.37-rc8]
From: Marc Kleine-Budde @ 2011-01-10 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294528551.4181.19.camel@heimdal.trondhjem.org>
On 01/09/2011 12:15 AM, Trond Myklebust wrote:
> From 8b2e60cef5c65eef41ab61286f62dec6bfb1ac27 Mon Sep 17 00:00:00 2001
> From: Trond Myklebust <Trond.Myklebust@netapp.com>
> Date: Sat, 8 Jan 2011 17:45:38 -0500
> Subject: [PATCH] NFS: Don't use vm_map_ram() in readdir
>
> vm_map_ram() is not available on NOMMU platforms, and causes trouble
> on incoherrent architectures such as ARM when we access the page data
> through both the direct and the virtual mapping.
>
> The alternative is to use the direct mapping to access page data
> for the case when we are not crossing a page boundary, but to copy
> the data into a linear scratch buffer when we are accessing data
> that spans page boundaries.
>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Tested-by: Marc Kleine-Budde <mkl@pengutronix.de>
..on AT91 (armv5)
regards, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 262 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110110/f1fdce67/attachment.sig>
^ permalink raw reply
* [PATCH v4 1/3] omap3: beaglexm: fix EHCI power up GPIO dir
From: Aaro Koskinen @ 2011-01-10 12:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294441282-17986-2-git-send-email-nm@ti.com>
Hi,
On Fri, 7 Jan 2011, Nishanth Menon wrote:
> From: Koen Kooi <koen@beagleboard.org>
>
> EHCI enable power pin is inverted (active high) in comparison
> to vanilla beagle which is active low. Handle this case conditionally.
>
> Without this fix, Beagle XM 4 port EHCI will not function and no
> networking will be available
>
> [nm at ti.com: split up, added descriptive changelogs]
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Koen Kooi <koen@beagleboard.org>
> ---
> arch/arm/mach-omap2/board-omap3beagle.c | 9 ++++++++-
> 1 files changed, 8 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
> index 6c12760..1b5aa7a 100644
> --- a/arch/arm/mach-omap2/board-omap3beagle.c
> +++ b/arch/arm/mach-omap2/board-omap3beagle.c
> @@ -297,9 +297,16 @@ static int beagle_twl_gpio_setup(struct device *dev,
> gpio_request(gpio + 1, "EHCI_nOC");
> gpio_direction_input(gpio + 1);
>
> - /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
> + /*
> + * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
> + * high / others active low)
> + */
> gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
> gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
This call should be deleted.
> + if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
> + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
> + else
> + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
>
> /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
> gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
> --
> 1.6.3.3
>
^ permalink raw reply
* [PATCH v5 3/3] ahci_platforms: add support for CNS3xxx SoC devices
From: Basheer, Mansoor Ahamed @ 2011-01-10 12:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294557970-654-4-git-send-email-mkl0301@gmail.com>
> From: Mac Lin <mkl0301@gmail.com>
>
> CNS3xxx override the softreset function of ahci_platform
> ahci_softreset by cns3xxx_ahci_softreset, which would retry
> ahci_do_softreset again with pmp=0 if
> pmp=15 failed, for the controller has problem receiving D2H
> Reg FIS of the different PMP setting of the previous sent H2D Reg FIS.
>
Is this issue only with your ahci platform controller? I came across another
thread here,
http://www.spinics.net/lists/linux-ide/msg39865.html
Also, the ahci platform controller on Texas Instruments OMAP L138 platform
behaves in a similar fashion.
Currently I see only Cavium Networks, Faraday and TI using ahci platform
controller and all 3 facing same issue.
Hence, should we fix this in ahci_platform.c conditionally using platform data,
otherwise we will end-up adding file for every platform (just for one
function).
Thanks
Mansoor Ahamed
^ permalink raw reply
* [PATCH 4/5] ARM: pxa: Fix suspend/resume array index miscalculation
From: Sergei Shtylyov @ 2011-01-10 12:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294615746-27668-4-git-send-email-marek.vasut@gmail.com>
On 10-01-2011 2:29, Marek Vasut wrote:
> Signed-off-by: Marek Vasut<marek.vasut@gmail.com>
> ---
> arch/arm/mach-pxa/irq.c | 10 +++++-----
> 1 files changed, 5 insertions(+), 5 deletions(-)
> diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
> index 78f0e0c..81edf97 100644
> --- a/arch/arm/mach-pxa/irq.c
> +++ b/arch/arm/mach-pxa/irq.c
> @@ -194,14 +194,14 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn)
>
> #ifdef CONFIG_PM
> static unsigned long saved_icmr[MAX_INTERNAL_IRQS/32];
> -static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
> +static unsigned long saved_ipr[MAX_INTERNAL_IRQS/32];
>
> static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
> {
> int i;
>
> - for (i = 0; i < pxa_internal_irq_nr; i += 32) {
> - void __iomem *base = irq_base(i);
> + for (i = 0; i < pxa_internal_irq_nr; i++) {
Won't the loop condition also have to change?
> + void __iomem *base = irq_base(i << 5);
>
> saved_icmr[i] = __raw_readl(base + ICMR);
> __raw_writel(0, base + ICMR);
> @@ -219,8 +219,8 @@ static int pxa_irq_resume(struct sys_device *dev)
> {
> int i;
>
> - for (i = 0; i < pxa_internal_irq_nr; i += 32) {
> - void __iomem *base = irq_base(i);
> + for (i = 0; i < pxa_internal_irq_nr; i++) {
Same question here...
> + void __iomem *base = irq_base(i << 5);
>
> __raw_writel(saved_icmr[i], base + ICMR);
> __raw_writel(0, base + ICLR);
WBR, Sergei
^ permalink raw reply
* [PATCH 3/3] ARM i.MX5 uart clock bug fix
From: yong.shen at freescale.com @ 2011-01-10 12:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294661334-7826-1-git-send-email-yong.shen@freescale.com>
From: Yong Shen <yong.shen@freescale.com>
uart clk is from pll3 on mx53 instead of mx51
Signed-off-by: Yong Shen <yong.shen@freescale.com>
---
arch/arm/mach-mx5/clock-mx51-mx53.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index a20d0c0..3fb7ff8 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1370,7 +1370,6 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
clk_tree_init();
- clk_set_parent(&uart_root_clk, &pll3_sw_clk);
clk_enable(&cpu_clk);
clk_enable(&main_bus_clk);
@@ -1413,6 +1412,7 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
clk_tree_init();
+ clk_set_parent(&uart_root_clk, &pll3_sw_clk);
clk_enable(&cpu_clk);
clk_enable(&main_bus_clk);
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] ARM i.MX53 enable spi on EVK board
From: yong.shen at freescale.com @ 2011-01-10 12:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294661334-7826-1-git-send-email-yong.shen@freescale.com>
From: Yong Shen <yong.shen@freescale.com>
1. some macro definitions fix
2. add platform data for spi device
3. register spi clocks
Signed-off-by: Yong Shen <yong.shen@freescale.com>
---
arch/arm/mach-mx5/Kconfig | 1 +
arch/arm/mach-mx5/board-mx53_evk.c | 14 ++++++++++++++
arch/arm/mach-mx5/clock-mx51-mx53.c | 3 +++
arch/arm/mach-mx5/devices-imx53.h | 4 ++++
arch/arm/plat-mxc/devices/platform-spi_imx.c | 12 ++++++++++++
arch/arm/plat-mxc/include/mach/mx53.h | 10 +++++-----
6 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 23b0e3f..777740b 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -126,6 +126,7 @@ config MACH_MX53_EVK
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+ select IMX_HAVE_PLATFORM_SPI_IMX
help
Include support for MX53 EVK platform. This includes specific
configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
index 4043451..8017d68 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -33,6 +33,8 @@
#include <mach/iomux-mx53.h>
#define SMD_FEC_PHY_RST IMX_GPIO_NR(7, 6)
+#define EVK_ECSPI1_CS0 IMX_GPIO_NR(3, 19)
+#define EVK_ECSPI1_CS1 IMX_GPIO_NR(2, 30)
#include "crm_regs.h"
#include "devices-imx53.h"
@@ -89,6 +91,16 @@ static struct fec_platform_data mx53_evk_fec_pdata = {
.phy = PHY_INTERFACE_MODE_RMII,
};
+static int mx53_evk_spi_cs[] = {
+ EVK_ECSPI1_CS0,
+ EVK_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx53_evk_spi_data __initconst = {
+ .chipselect = mx53_evk_spi_cs,
+ .num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
+};
+
static void __init mx53_evk_board_init(void)
{
mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
@@ -102,6 +114,8 @@ static void __init mx53_evk_board_init(void)
imx53_add_sdhci_esdhc_imx(0, NULL);
imx53_add_sdhci_esdhc_imx(1, NULL);
+
+ imx53_add_ecspi(0, &mx53_evk_spi_data);
}
static void __init mx53_evk_timer_init(void)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index d0f58a3..a20d0c0 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1330,6 +1330,9 @@ static struct clk_lookup mx53_lookups[] = {
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+ _REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
+ _REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
+ _REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
};
static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index f7c89ef..8639735 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -25,3 +25,7 @@ extern const struct imx_sdhci_esdhc_imx_data
imx53_sdhci_esdhc_imx_data[] __initconst;
#define imx53_add_sdhci_esdhc_imx(id, pdata) \
imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx53_ecspi_data[] __initconst;
+#define imx53_add_ecspi(id, pdata) \
+ imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index 8ea49ad..013c85f 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -81,6 +81,18 @@ const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX51 */
+#ifdef CONFIG_SOC_IMX53
+const struct imx_spi_imx_data imx53_cspi_data __initconst =
+ imx_spi_imx_data_entry_single(MX53, CSPI, "imx53-cspi", 0, , SZ_4K);
+
+const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
+#define imx53_ecspi_data_entry(_id, _hwid) \
+ imx_spi_imx_data_entry(MX53, ECSPI, "imx53-ecspi", _id, _hwid, SZ_4K)
+ imx53_ecspi_data_entry(0, 1),
+ imx53_ecspi_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
struct platform_device *__init imx_add_spi_imx(
const struct imx_spi_imx_data *data,
const struct spi_imx_master *pdata)
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index 340937f..d7a8e52 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -56,7 +56,7 @@
#define MX53_ESDHC1_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00004000)
#define MX53_ESDHC2_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00008000)
#define MX53_UART3_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x0000C000)
-#define MX53_CSPI1_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00010000)
+#define MX53_ECSPI1_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00010000)
#define MX53_SSI2_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00014000)
#define MX53_ESDHC3_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00020000)
#define MX53_ESDHC4_BASE_ADDR (MX53_SPBA0_BASE_ADDR + 0x00024000)
@@ -117,12 +117,12 @@
#define MX53_ARM_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A0000)
#define MX53_OWIRE_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A4000)
#define MX53_FIRI_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000A8000)
-#define MX53_CSPI2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000AC000)
+#define MX53_ECSPI2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000AC000)
#define MX53_SDMA_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B0000)
#define MX53_SCC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B4000)
#define MX53_ROMCP_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000B8000)
#define MX53_RTIC_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000BC000)
-#define MX53_CSPI3_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C0000)
+#define MX53_CSPI_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C0000)
#define MX53_I2C2_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C4000)
#define MX53_I2C1_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000C8000)
#define MX53_SSI1_BASE_ADDR (MX53_AIPS2_BASE_ADDR + 0x000CC000)
@@ -264,8 +264,8 @@
#define MX53_INT_UART3 33
#define MX53_INT_RESV34 34
#define MX53_INT_RESV35 35
-#define MX53_INT_CSPI1 36
-#define MX53_INT_CSPI2 37
+#define MX53_INT_ECSPI1 36
+#define MX53_INT_ECSPI2 37
#define MX53_INT_CSPI 38
#define MX53_INT_GPT 39
#define MX53_INT_EPIT1 40
--
1.7.1
^ permalink raw reply related
* [PATCH 1/3] ARM i.MX SPI driver changes for i.MX53 support
From: yong.shen at freescale.com @ 2011-01-10 12:08 UTC (permalink / raw)
To: linux-arm-kernel
From: Yong Shen <yong.shen@freescale.com>
1. Change the Kconfig to include i.MX53
2. add devtype entry for i.MX53
Signed-off-by: Yong Shen <yong.shen@freescale.com>
---
drivers/spi/Kconfig | 4 ++--
drivers/spi/spi_imx.c | 6 ++++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd0..04965e2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -153,10 +153,10 @@ config SPI_IMX_VER_0_4
def_bool y if ARCH_MX31
config SPI_IMX_VER_0_7
- def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51
+ def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51 || ARCH_MX53
config SPI_IMX_VER_2_3
- def_bool y if ARCH_MX51
+ def_bool y if ARCH_MX51 || ARCH_MX53
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 55a38e2..9b8a733 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -747,6 +747,12 @@ static struct platform_device_id spi_imx_devtype[] = {
.name = "imx51-ecspi",
.driver_data = SPI_IMX_VER_2_3,
}, {
+ .name = "imx53-cspi",
+ .driver_data = SPI_IMX_VER_0_7,
+ }, {
+ .name = "imx53-ecspi",
+ .driver_data = SPI_IMX_VER_2_3,
+ }, {
/* sentinel */
}
};
--
1.7.1
^ permalink raw reply related
* [PATCH 5/5] ARM: pxa: Fix recursive call of pxa_(un)mask_low_gpio()
From: Sergei Shtylyov @ 2011-01-10 12:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294615746-27668-5-git-send-email-marek.vasut@gmail.com>
Hello.
On 10-01-2011 2:29, Marek Vasut wrote:
> Signed-off-by: Marek Vasut<marek.vasut@gmail.com>
[...]
> diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
> index 81edf97..96571fe 100644
> --- a/arch/arm/mach-pxa/irq.c
> +++ b/arch/arm/mach-pxa/irq.c
> @@ -112,14 +112,14 @@ static void pxa_mask_low_gpio(unsigned int irq)
> {
> struct irq_desc *desc = irq_to_desc(irq);
You should have removed that variable too as it's not unused.
> - desc->chip->mask(irq);
> + pxa_mask_irq(irq);
> }
>
> static void pxa_unmask_low_gpio(unsigned int irq)
> {
> struct irq_desc *desc = irq_to_desc(irq);
Same here...
> - desc->chip->unmask(irq);
> + pxa_unmask_irq(irq);
> }
WBR, Sergei
^ permalink raw reply
* [PATCH V2] ST SPEAr: PCIE gadget suppport
From: pratyush @ 2011-01-10 11:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201101072332.16985.arnd@arndb.de>
Hello Arnd,
Thanks for the comments!!!
On 1/8/2011 4:02 AM, Arnd Bergmann wrote:
> On Thursday 06 January 2011, Viresh Kumar wrote:
>> From: Pratyush Anand <pratyush.anand@st.com>
>>
>> This is a configurable gadget. can be configured by sysfs interface. Any
>> IP available at PCIE bus can be programmed to be used by host
>> controller.It supoorts both INTX and MSI.
>> By default, gadget is configured for INTX and SYSRAM1 is mapped to BAR0
>> with size 0x1000
>
> The code looks reasonably clean, but I don't yet understand how you would
> use this device for the interesting case of communicating with the host
> side. I've put a lot of thought into similar hardware designs before, but
> never got an implementation done myself.
This driver has been developed just to show spear's capability to work as dual
mode pcie controller.
>
> Forwarding devices that don't need interrupts with your driver seems to
> be the only case that will easily work, but that is also rather limited
> in what you can use it for.
>
Off-course, it will work best with non interrupting devices. One can use
INTA assertion/de-assertion by software, but it would be very slow.
> One concept that people have played with before is to export a virtio
> channel through PCI that you can use with e.g. virtio-net or virtfs.
> This is very powerful and has a lot of possible applications because
> we have support for virtio drivers across a number of operating systems
> and platforms already.
>
>> Documentation/misc-devices/spear-pcie-gadget.txt | 125 ++++
>> drivers/misc/Kconfig | 10 +
>> drivers/misc/Makefile | 1 +
>> drivers/misc/spear13xx_pcie_gadget.c | 856 ++++++++++++++++++++++
>
> Why would you put this under drivers/misc?
>
> I think drivers/pci/gadget/ would be a better place. I would also
> recommend splitting the user interface from the hardware dependent
> parts, so someone else can easily do another gadget driver for
> different hardware.
>
Yes, can be done, if the interfaces which I have made is
acceptable to community.
>> +/*wait till link is up*/
>> +# cat sys/devices/platform/pcie-gadget-spear.0/link
>> +wait till it returns UP.
>
> A blocking sysfs read is not a nice interface. This is probably where
> the sysfs abstraction for your hardware stops making sense.
>
This call is not blocking. User will have to recheck link status till he
finds it UP. He may put some delay between two successive read. I will
modify documentation to be more explicit.
>> +To assert INTA
>> +# echo 1 >> sys/devices/platform/pcie-gadget-spear.0/inta
>> +
>> +To de-assert INTA
>> +# echo 0 >> sys/devices/platform/pcie-gadget-spear.0/inta
>
> And this looks somewhat impractical and slow.
>
Yes, it will be slow.
>> +to send msi vector 2
>> +# echo 2 >> sys/devices/platform/pcie-gadget-spear.0/send_msi
>
> Using a sysfs file only for its side-effect is not very nice either.
>
> The user interface for the interrupts looks to me like it should really
> be based around a character device and either read/write/poll or
> ioctl and poll. Using an eventfd might be cool here, because then you
> can combine this with other devices by passing the event file to
> an interface that operates on eventfd. This would e.g. make it possible
> to combine a UIO device generating interrupts with a PCIe gadget
> sending the interrupts somewhere else, without leaving kernel
> space.
>
I do not have much idea about eventfd mechanism. But if we decide to
split it in two layers (generic pcie gadget and HW specific) then I
might try to do it in this way.
Regards
Pratyush
> For setting up the basic parameters, sysfs (or configfs, as Greg suggested)
> is a reasonable choice, so there is no need to change that.
>
> I don't know what the rules for configfs are though, i.e. if eventfd
> files or ioctls are ok or not.
>
> Arnd
>
> .
>
^ permalink raw reply
* [PATCH] spi: tegra: don't treat NULL clk as an error
From: Jamie Iles @ 2011-01-10 11:05 UTC (permalink / raw)
To: linux-arm-kernel
Some platforms have been known to return NULL from clk_get() if they
support only a single struct clk. Whilst tegra doesn't do this, make
the drivers consistent with others.
Cc: Erik Gilling <konkers@android.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
drivers/spi/spi_tegra.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
index bb7df02..891e590 100644
--- a/drivers/spi/spi_tegra.c
+++ b/drivers/spi/spi_tegra.c
@@ -513,7 +513,7 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
}
tspi->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR_OR_NULL(tspi->clk)) {
+ if (IS_ERR(tspi->clk)) {
dev_err(&pdev->dev, "can not get clock\n");
ret = PTR_ERR(tspi->clk);
goto err2;
--
1.7.3.4
^ permalink raw reply related
* [PATCH 1/2] Add a common struct clk
From: Russell King - ARM Linux @ 2011-01-10 11:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110110104122.GI12078@pengutronix.de>
On Mon, Jan 10, 2011 at 11:41:22AM +0100, Sascha Hauer wrote:
> This branch must be reworked because the correct locking is missing, but
> the first branch should be ready for merging once your clk-common
> patches are merged. I'll post the patches for review soon. I hope it's
> clear soon that your clk-common patches get merged.
Unless the locking problems can be resolved, the patches aren't ready.
^ permalink raw reply
* [PATCH] watchdog: add support for the Synopsys DesignWare WDT
From: Jamie Iles @ 2011-01-10 10:55 UTC (permalink / raw)
To: linux-arm-kernel
The Synopsys DesignWare watchdog is found in several ARM based systems
and provides a choice of 16 timeout periods depending on the clock
input. The watchdog cannot be disabled once started.
If the platform does not provide a clk for the watchdog then the user
can specify the input frequency with the struct dw_wdt_platform_data in
<linux/platform_data/dw_wdt.h>
v4:
- cleanups as suggested by Viresh Kumar and Wim
- provide a mechanism to handle NULL clks and allow
platform_data to specify the clk_rate
- provide open-once protection
v3:
- convert pm to dev_pm_ops
- use devres for resource allocation
v2:
- constify fops
- request_mem_region() before ioremap()
- disable clk if misc_register() fails
Cc: Wim Van Sebroeck <wim@iguana.be>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
Viresh, Russell, Wim - thanks for your feedback.
include/linux/platform_data is used for the platform data as suggested
by Greg K-H in [1].
1. https://lkml.org/lkml/2011/1/7/323
drivers/watchdog/Kconfig | 9 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/dw_wdt.c | 329 ++++++++++++++++++++++++++++++++++
include/linux/platform_data/dw_wdt.h | 27 +++
4 files changed, 366 insertions(+), 0 deletions(-)
create mode 100644 drivers/watchdog/dw_wdt.c
create mode 100644 include/linux/platform_data/dw_wdt.h
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8a3aa2f..0981aae 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -331,6 +331,15 @@ config IMX2_WDT
To compile this driver as a module, choose M here: the
module will be called imx2_wdt.
+config DW_WATCHDOG
+ tristate "Synopsys DesignWare watchdog"
+ select WATCHDOG_NOWAYOUT
+ help
+ Say Y here if to include support for the Synopsys DesignWare
+ watchdog timer found in many ARM chips.
+ To compile this driver as a module, choose M here: the
+ module will be called dw_wdt.
+
# AVR32 Architecture
config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 4b0ef38..3b3da4a 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_DW_WATCHDOG) += dw_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
new file mode 100644
index 0000000..b6d9b6e
--- /dev/null
+++ b/drivers/watchdog/dw_wdt.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2010-2011 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ */
+#define pr_fmt(fmt) "dw_wdt: " fmt
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+
+#include <linux/platform_data/dw_wdt.h>
+
+#define WDOG_CONTROL_REG_OFFSET 0x00
+#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
+#define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04
+#define WDOG_CURRENT_COUNT_REG_OFFSET 0x08
+#define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c
+#define WDOG_COUNTER_RESTART_KICK_VALUE 0x76
+
+/* The maximum TOP (timeout period) value that can be set in the watchdog. */
+#define DW_WDT_MAX_TOP 15
+
+static struct {
+ spinlock_t lock;
+ void __iomem *regs;
+ struct clk *clk;
+ unsigned long clk_rate;
+ unsigned long in_use;
+} dw_wdt;
+
+static inline int dw_wdt_is_enabled(void)
+{
+ return readl(dw_wdt.regs + WDOG_CONTROL_REG_OFFSET) &
+ WDOG_CONTROL_REG_WDT_EN_MASK;
+}
+
+static inline int dw_wdt_top_in_seconds(unsigned top)
+{
+ /*
+ * There are 16 possible timeout values in 0..15 where the number of
+ * cycles is 2 ^ (16 + i) and the watchdog counts down.
+ */
+ return (1 << (16 + top)) / dw_wdt.clk_rate;
+}
+
+static int dw_wdt_set_top(unsigned top_s)
+{
+ int i, top_val = -1;
+
+ /*
+ * Iterate over the timeout values until we find the closest match. We
+ * always look for >=.
+ */
+ for (i = 0; i <= DW_WDT_MAX_TOP; ++i)
+ if (dw_wdt_top_in_seconds(i) >= top_s) {
+ top_val = i;
+ break;
+ }
+
+ /*
+ * If we didn't find a suitable value, it must have been too large. Go
+ * with the biggest that we can.
+ */
+ if (top_val < 0)
+ top_val = DW_WDT_MAX_TOP;
+
+ /* Set the new value in the watchdog. */
+ writel(top_val, dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+
+ return dw_wdt_top_in_seconds(top_val);
+}
+
+static int dw_wdt_get_top(void)
+{
+ int top = readl(dw_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF;
+
+ return dw_wdt_top_in_seconds(top);
+}
+
+static void dw_wdt_keepalive(void)
+{
+ writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt.regs +
+ WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
+static int dw_wdt_open(struct inode *inode, struct file *filp)
+{
+ if (test_and_set_bit(0, &dw_wdt.in_use))
+ return -EBUSY;
+
+ /* Make sure we don't get unloaded. */
+ __module_get(THIS_MODULE);
+
+ spin_lock(&dw_wdt.lock);
+ if (!dw_wdt_is_enabled()) {
+ /*
+ * The watchdog is not currently enabled. Set the timeout to
+ * the maximum and then start it.
+ */
+ dw_wdt_set_top(DW_WDT_MAX_TOP);
+ writel(WDOG_CONTROL_REG_WDT_EN_MASK,
+ dw_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+ }
+ spin_unlock(&dw_wdt.lock);
+
+ return nonseekable_open(inode, filp);
+}
+
+ssize_t dw_wdt_write(struct file *filp, const char __user *buf, size_t len,
+ loff_t *offset)
+{
+ dw_wdt_keepalive();
+
+ return len;
+}
+
+static u32 dw_wdt_time_left(void)
+{
+ return readl(dw_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
+ dw_wdt.clk_rate;
+}
+
+static const struct watchdog_info dw_wdt_ident = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+ .identity = "Synopsys DesignWare Watchdog",
+};
+
+static long dw_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ unsigned long val;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *)arg, &dw_wdt_ident,
+ sizeof(dw_wdt_ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *)arg);
+
+ case WDIOC_KEEPALIVE:
+ dw_wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_set_top(val), (int __user *)arg);
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(dw_wdt_get_top(), (int __user *)arg);
+
+ case WDIOC_GETTIMELEFT:
+ /* Get the time left until expiry. */
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+ return put_user(dw_wdt_time_left(), (int __user *)arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static int dw_wdt_release(struct inode *inode, struct file *filp)
+{
+ pr_crit("WATCHDOG: device closed - timer will not stop\n");
+
+ clear_bit(0, &dw_wdt.in_use);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int dw_wdt_suspend(struct device *dev)
+{
+ clk_disable(dw_wdt.clk);
+
+ return 0;
+}
+
+static int dw_wdt_resume(struct device *dev)
+{
+ int err = clk_enable(dw_wdt.clk);
+
+ if (err)
+ return err;
+
+ dw_wdt_keepalive();
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_wdt_pm_ops = {
+ .suspend = dw_wdt_suspend,
+ .resume = dw_wdt_resume,
+};
+#endif /* CONFIG_PM */
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = dw_wdt_open,
+ .write = dw_wdt_write,
+ .unlocked_ioctl = dw_wdt_ioctl,
+ .release = dw_wdt_release
+};
+
+static struct miscdevice dw_wdt_miscdev = {
+ .fops = &wdt_fops,
+ .name = "watchdog",
+ .minor = WATCHDOG_MINOR,
+};
+
+static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct dw_wdt_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!mem)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+ "dw_wdt"))
+ return -ENOMEM;
+
+ dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
+ if (!dw_wdt.regs)
+ return -ENOMEM;
+
+ dw_wdt.clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dw_wdt.clk))
+ return -ENODEV;
+
+ ret = clk_enable(dw_wdt.clk);
+ if (ret)
+ goto out_put_clk;
+
+ /*
+ * The timeout period of the watchdog is derived from the input clock
+ * frequency. For platforms that don't have a clk for the watchdog,
+ * they can specify the WDT clock rate through the clk_rate field of
+ * the struct dw_wdt_platform_data platform data.
+ */
+ if (pdata && pdata->clk_rate > 0)
+ dw_wdt.clk_rate = pdata->clk_rate;
+ else
+ dw_wdt.clk_rate = clk_get_rate(dw_wdt.clk);
+
+ if (!dw_wdt.clk_rate) {
+ dev_err(&pdev->dev, "no clk rate defined for watchdog, cannot enable\n");
+ ret = -EINVAL;
+ goto out_disable_clk;
+ }
+
+ spin_lock_init(&dw_wdt.lock);
+
+ ret = misc_register(&dw_wdt_miscdev);
+ if (ret)
+ goto out_put_clk;
+
+ return 0;
+
+out_disable_clk:
+ clk_disable(dw_wdt.clk);
+out_put_clk:
+ clk_put(dw_wdt.clk);
+
+ return ret;
+}
+
+static int __devexit dw_wdt_drv_remove(struct platform_device *pdev)
+{
+ misc_deregister(&dw_wdt_miscdev);
+
+ clk_disable(dw_wdt.clk);
+ clk_put(dw_wdt.clk);
+
+ return 0;
+}
+
+static struct platform_driver dw_wdt_driver = {
+ .probe = dw_wdt_drv_probe,
+ .remove = __devexit_p(dw_wdt_drv_remove),
+ .driver = {
+ .name = "dw_wdt",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &dw_wdt_pm_ops,
+#endif /* CONFIG_PM */
+ },
+};
+
+static int __init dw_wdt_watchdog_init(void)
+{
+ return platform_driver_register(&dw_wdt_driver);
+}
+module_init(dw_wdt_watchdog_init);
+
+static void __exit dw_wdt_watchdog_exit(void)
+{
+ platform_driver_unregister(&dw_wdt_driver);
+}
+module_exit(dw_wdt_watchdog_exit);
+
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/dw_wdt.h b/include/linux/platform_data/dw_wdt.h
new file mode 100644
index 0000000..0af10ef
--- /dev/null
+++ b/include/linux/platform_data/dw_wdt.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Picochip Ltd., Jamie Iles
+ * http://www.picochip.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This file implements a driver for the Synopsys DesignWare watchdog device
+ * in the many ARM subsystems. The watchdog has 16 different timeout periods
+ * and these are a function of the input clock frequency.
+ */
+#ifndef __DW_WDT_H__
+#define __DW_WDT_H__
+
+/**
+ * struct dw_wdt_platform_data - DesignWare WDT platform data
+ *
+ * @clk_rate: The frequency (HZ) at which the watchdog is driven. The timeout
+ * periods are derived from this frequency.
+ */
+struct dw_wdt_platform_data {
+ unsigned long clk_rate;
+};
+
+#endif /* __DW_WDT_H__ */
--
1.7.3.4
^ permalink raw reply related
* [PATCH] ARM: sched_clock: improve mult/shift accuracy with high frequency clocks
From: Russell King - ARM Linux @ 2011-01-10 10:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1101092224320.3455@xanadu.home>
On Sun, Jan 09, 2011 at 10:55:04PM -0500, Nicolas Pitre wrote:
> However this begs the question about the actual meaning of the value for
> the minsec argument to clocks_calc_mult_shift() (which IMHO should be
> renamed to maxsec instead). In the ARM sched_clock code the value of 60
> is totally arbitrary and may happen to be good enough, but a value of 0
> would also be totally arbitrary and also work fine. But at least a 0
> value wouldn't imply any false meaning. And in the case of the
> sched_clock support code, we know the value we need: 90%
> of the actual hardware clock period, so using that would at least make
> the code self consistent even if in practice this doesn't change the
> final results.
Actually, minsec is utterly wrong.
minsec is there to clamp the conversion from the N-bit cyclecounter to
a 64-bit nanosecond value to ensure that there isn't a 64-bit overflow
within the 'minsec' period.
With a 32-bit or smaller cyclecounter, as 32-bit x 32-bit can never
overflow a 64-bit destination, so if anything zero should be passed in
this case.
If larger than 32-bit, then a value may be needed to clamp it. However,
wrap = (1 << bits) / freq
ns = (mult * cnt) >> shift
mult = (NSEC_PER_SEC (a 30-bit number) << 32) / freq (32-bit max)
A 33-bit counter would need a 32-bit multiplier to wrap-around within
the 64-bit maths. The frequency which produces a 32-bit multiplier is
2GHz, which gives a wrap period of 4.29s. Above this frequency, the
64-bit math can't overflow as the multiplier becomes smaller. Below
this frequency, counter wrap periods get longer and the multiplier
becomes larger up to 32 bits - and this is where the 64-bit math problem
starts.
A 33-bit counter with a 1.8GHz clock gives a multiplier of 2386092942
(0x8E38E38E). Such a multiplier wraps 64-bit maths@7730941133 and
it takes the counter 4.29s to get there.
1 << bits / freq gives a counter wrap period of 4.77s, which is
over-estimating the 64-bit math wrap.
I question whether using 1 << bits / freq is valid for minsec - does
there exist a frequency where an integer minsec is larger than required.
Luckily the maths is safe as it'll produce a smaller mult.
However, I question whether using 1 << bits / freq is any arbitary than
a 60 or 0 value - it's certainly mathematically the wrong wrap period.
So, in summary I'd suggest using a value of 0 for sched_clock() if we're
going to change it - we don't accept more than 32-bits from the counter
at present, so the whole minsec thing really isn't needed to prevent
wrap. If we ever allow more than 32-bits then yes it will.
^ permalink raw reply
* still nfs problems [Was: Linux 2.6.37-rc8]
From: Uwe Kleine-König @ 2011-01-10 10:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294528551.4181.19.camel@heimdal.trondhjem.org>
Hi Trond,
On Sat, Jan 08, 2011 at 06:15:51PM -0500, Trond Myklebust wrote:
> -----------------------------------------------------------------------------------
It would be great if you could add a "8<" in the line above next time.
Then git-am -c does the right thing (at least I think so).
> From 8b2e60cef5c65eef41ab61286f62dec6bfb1ac27 Mon Sep 17 00:00:00 2001
> From: Trond Myklebust <Trond.Myklebust@netapp.com>
> Date: Sat, 8 Jan 2011 17:45:38 -0500
> Subject: [PATCH] NFS: Don't use vm_map_ram() in readdir
>
> vm_map_ram() is not available on NOMMU platforms, and causes trouble
> on incoherrent architectures such as ARM when we access the page data
> through both the direct and the virtual mapping.
>
> The alternative is to use the direct mapping to access page data
> for the case when we are not crossing a page boundary, but to copy
> the data into a linear scratch buffer when we are accessing data
> that spans page boundaries.
>
> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Tested-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
on tx28.
Thanks
Uwe
> ---
> fs/nfs/dir.c | 44 ++++++-------
> fs/nfs/nfs2xdr.c | 6 --
> fs/nfs/nfs3xdr.c | 6 --
> fs/nfs/nfs4xdr.c | 6 --
> include/linux/sunrpc/xdr.h | 4 +-
> net/sunrpc/xdr.c | 155 +++++++++++++++++++++++++++++++++++---------
> 6 files changed, 148 insertions(+), 73 deletions(-)
>
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 996dd89..0108cf4 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -33,7 +33,6 @@
> #include <linux/namei.h>
> #include <linux/mount.h>
> #include <linux/sched.h>
> -#include <linux/vmalloc.h>
> #include <linux/kmemleak.h>
>
> #include "delegation.h"
> @@ -459,25 +458,26 @@ out:
> /* Perform conversion from xdr to cache array */
> static
> int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
> - void *xdr_page, struct page *page, unsigned int buflen)
> + struct page **xdr_pages, struct page *page, unsigned int buflen)
> {
> struct xdr_stream stream;
> - struct xdr_buf buf;
> - __be32 *ptr = xdr_page;
> + struct xdr_buf buf = {
> + .pages = xdr_pages,
> + .page_len = buflen,
> + .buflen = buflen,
> + .len = buflen,
> + };
> + struct page *scratch;
> struct nfs_cache_array *array;
> unsigned int count = 0;
> int status;
>
> - buf.head->iov_base = xdr_page;
> - buf.head->iov_len = buflen;
> - buf.tail->iov_len = 0;
> - buf.page_base = 0;
> - buf.page_len = 0;
> - buf.buflen = buf.head->iov_len;
> - buf.len = buf.head->iov_len;
> -
> - xdr_init_decode(&stream, &buf, ptr);
> + scratch = alloc_page(GFP_KERNEL);
> + if (scratch == NULL)
> + return -ENOMEM;
>
> + xdr_init_decode(&stream, &buf, NULL);
> + xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
>
> do {
> status = xdr_decode(desc, entry, &stream);
> @@ -506,6 +506,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
> } else
> status = PTR_ERR(array);
> }
> +
> + put_page(scratch);
> return status;
> }
>
> @@ -521,7 +523,6 @@ static
> void nfs_readdir_free_large_page(void *ptr, struct page **pages,
> unsigned int npages)
> {
> - vm_unmap_ram(ptr, npages);
> nfs_readdir_free_pagearray(pages, npages);
> }
>
> @@ -530,9 +531,8 @@ void nfs_readdir_free_large_page(void *ptr, struct page **pages,
> * to nfs_readdir_free_large_page
> */
> static
> -void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
> +int nfs_readdir_large_page(struct page **pages, unsigned int npages)
> {
> - void *ptr;
> unsigned int i;
>
> for (i = 0; i < npages; i++) {
> @@ -541,13 +541,11 @@ void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
> goto out_freepages;
> pages[i] = page;
> }
> + return 0;
>
> - ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
> - if (!IS_ERR_OR_NULL(ptr))
> - return ptr;
> out_freepages:
> nfs_readdir_free_pagearray(pages, i);
> - return NULL;
> + return -ENOMEM;
> }
>
> static
> @@ -577,8 +575,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
> memset(array, 0, sizeof(struct nfs_cache_array));
> array->eof_index = -1;
>
> - pages_ptr = nfs_readdir_large_page(pages, array_size);
> - if (!pages_ptr)
> + status = nfs_readdir_large_page(pages, array_size);
> + if (status < 0)
> goto out_release_array;
> do {
> unsigned int pglen;
> @@ -587,7 +585,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
> if (status < 0)
> break;
> pglen = status;
> - status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen);
> + status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen);
> if (status < 0) {
> if (status == -ENOSPC)
> status = 0;
> diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
> index 5914a19..b382a1b 100644
> --- a/fs/nfs/nfs2xdr.c
> +++ b/fs/nfs/nfs2xdr.c
> @@ -487,12 +487,6 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se
>
> entry->d_type = DT_UNKNOWN;
>
> - p = xdr_inline_peek(xdr, 8);
> - if (p != NULL)
> - entry->eof = !p[0] && p[1];
> - else
> - entry->eof = 0;
> -
> return p;
>
> out_overflow:
> diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
> index f6cc60f..ba91236 100644
> --- a/fs/nfs/nfs3xdr.c
> +++ b/fs/nfs/nfs3xdr.c
> @@ -647,12 +647,6 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s
> memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
> }
>
> - p = xdr_inline_peek(xdr, 8);
> - if (p != NULL)
> - entry->eof = !p[0] && p[1];
> - else
> - entry->eof = 0;
> -
> return p;
>
> out_overflow:
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 9f1826b..0662a98 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -6215,12 +6215,6 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
> if (verify_attr_len(xdr, p, len) < 0)
> goto out_overflow;
>
> - p = xdr_inline_peek(xdr, 8);
> - if (p != NULL)
> - entry->eof = !p[0] && p[1];
> - else
> - entry->eof = 0;
> -
> return p;
>
> out_overflow:
> diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
> index 498ab93..7783c68 100644
> --- a/include/linux/sunrpc/xdr.h
> +++ b/include/linux/sunrpc/xdr.h
> @@ -201,6 +201,8 @@ struct xdr_stream {
>
> __be32 *end; /* end of available buffer space */
> struct kvec *iov; /* pointer to the current kvec */
> + struct kvec scratch; /* Scratch buffer */
> + struct page **page_ptr; /* pointer to the current page */
> };
>
> extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
> @@ -208,7 +210,7 @@ extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
> extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
> unsigned int base, unsigned int len);
> extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
> -extern __be32 *xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes);
> +extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
> extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
> extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
> extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
> diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
> index cd9e841..679cd67 100644
> --- a/net/sunrpc/xdr.c
> +++ b/net/sunrpc/xdr.c
> @@ -552,6 +552,74 @@ void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int b
> }
> EXPORT_SYMBOL_GPL(xdr_write_pages);
>
> +static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov,
> + __be32 *p, unsigned int len)
> +{
> + if (len > iov->iov_len)
> + len = iov->iov_len;
> + if (p == NULL)
> + p = (__be32*)iov->iov_base;
> + xdr->p = p;
> + xdr->end = (__be32*)(iov->iov_base + len);
> + xdr->iov = iov;
> + xdr->page_ptr = NULL;
> +}
> +
> +static int xdr_set_page_base(struct xdr_stream *xdr,
> + unsigned int base, unsigned int len)
> +{
> + unsigned int pgnr;
> + unsigned int maxlen;
> + unsigned int pgoff;
> + unsigned int pgend;
> + void *kaddr;
> +
> + maxlen = xdr->buf->page_len;
> + if (base >= maxlen)
> + return -EINVAL;
> + maxlen -= base;
> + if (len > maxlen)
> + len = maxlen;
> +
> + base += xdr->buf->page_base;
> +
> + pgnr = base >> PAGE_SHIFT;
> + xdr->page_ptr = &xdr->buf->pages[pgnr];
> + kaddr = page_address(*xdr->page_ptr);
> +
> + pgoff = base & ~PAGE_MASK;
> + xdr->p = (__be32*)(kaddr + pgoff);
> +
> + pgend = pgoff + len;
> + if (pgend > PAGE_SIZE)
> + pgend = PAGE_SIZE;
> + xdr->end = (__be32*)(kaddr + pgend);
> + xdr->iov = NULL;
> + return 0;
> +}
> +
> +static void xdr_set_next_page(struct xdr_stream *xdr)
> +{
> + unsigned int newbase;
> +
> + newbase = (1 + xdr->page_ptr - xdr->buf->pages) << PAGE_SHIFT;
> + newbase -= xdr->buf->page_base;
> +
> + if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0)
> + xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len);
> +}
> +
> +static bool xdr_set_next_buffer(struct xdr_stream *xdr)
> +{
> + if (xdr->page_ptr != NULL)
> + xdr_set_next_page(xdr);
> + else if (xdr->iov == xdr->buf->head) {
> + if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0)
> + xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len);
> + }
> + return xdr->p != xdr->end;
> +}
> +
> /**
> * xdr_init_decode - Initialize an xdr_stream for decoding data.
> * @xdr: pointer to xdr_stream struct
> @@ -560,41 +628,67 @@ EXPORT_SYMBOL_GPL(xdr_write_pages);
> */
> void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
> {
> - struct kvec *iov = buf->head;
> - unsigned int len = iov->iov_len;
> -
> - if (len > buf->len)
> - len = buf->len;
> xdr->buf = buf;
> - xdr->iov = iov;
> - xdr->p = p;
> - xdr->end = (__be32 *)((char *)iov->iov_base + len);
> + xdr->scratch.iov_base = NULL;
> + xdr->scratch.iov_len = 0;
> + if (buf->head[0].iov_len != 0)
> + xdr_set_iov(xdr, buf->head, p, buf->len);
> + else if (buf->page_len != 0)
> + xdr_set_page_base(xdr, 0, buf->len);
> }
> EXPORT_SYMBOL_GPL(xdr_init_decode);
>
> -/**
> - * xdr_inline_peek - Allow read-ahead in the XDR data stream
> - * @xdr: pointer to xdr_stream struct
> - * @nbytes: number of bytes of data to decode
> - *
> - * Check if the input buffer is long enough to enable us to decode
> - * 'nbytes' more bytes of data starting at the current position.
> - * If so return the current pointer without updating the current
> - * pointer position.
> - */
> -__be32 * xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes)
> +static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
> {
> __be32 *p = xdr->p;
> __be32 *q = p + XDR_QUADLEN(nbytes);
>
> if (unlikely(q > xdr->end || q < p))
> return NULL;
> + xdr->p = q;
> return p;
> }
> -EXPORT_SYMBOL_GPL(xdr_inline_peek);
>
> /**
> - * xdr_inline_decode - Retrieve non-page XDR data to decode
> + * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data.
> + * @xdr: pointer to xdr_stream struct
> + * @buf: pointer to an empty buffer
> + * @buflen: size of 'buf'
> + *
> + * The scratch buffer is used when decoding from an array of pages.
> + * If an xdr_inline_decode() call spans across page boundaries, then
> + * we copy the data into the scratch buffer in order to allow linear
> + * access.
> + */
> +void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen)
> +{
> + xdr->scratch.iov_base = buf;
> + xdr->scratch.iov_len = buflen;
> +}
> +EXPORT_SYMBOL_GPL(xdr_set_scratch_buffer);
> +
> +static __be32 *xdr_copy_to_scratch(struct xdr_stream *xdr, size_t nbytes)
> +{
> + __be32 *p;
> + void *cpdest = xdr->scratch.iov_base;
> + size_t cplen = (char *)xdr->end - (char *)xdr->p;
> +
> + if (nbytes > xdr->scratch.iov_len)
> + return NULL;
> + memcpy(cpdest, xdr->p, cplen);
> + cpdest += cplen;
> + nbytes -= cplen;
> + if (!xdr_set_next_buffer(xdr))
> + return NULL;
> + p = __xdr_inline_decode(xdr, nbytes);
> + if (p == NULL)
> + return NULL;
> + memcpy(cpdest, p, nbytes);
> + return xdr->scratch.iov_base;
> +}
> +
> +/**
> + * xdr_inline_decode - Retrieve XDR data to decode
> * @xdr: pointer to xdr_stream struct
> * @nbytes: number of bytes of data to decode
> *
> @@ -605,13 +699,16 @@ EXPORT_SYMBOL_GPL(xdr_inline_peek);
> */
> __be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
> {
> - __be32 *p = xdr->p;
> - __be32 *q = p + XDR_QUADLEN(nbytes);
> + __be32 *p;
>
> - if (unlikely(q > xdr->end || q < p))
> + if (nbytes == 0)
> + return xdr->p;
> + if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr))
> return NULL;
> - xdr->p = q;
> - return p;
> + p = __xdr_inline_decode(xdr, nbytes);
> + if (p != NULL)
> + return p;
> + return xdr_copy_to_scratch(xdr, nbytes);
> }
> EXPORT_SYMBOL_GPL(xdr_inline_decode);
>
> @@ -671,16 +768,12 @@ EXPORT_SYMBOL_GPL(xdr_read_pages);
> */
> void xdr_enter_page(struct xdr_stream *xdr, unsigned int len)
> {
> - char * kaddr = page_address(xdr->buf->pages[0]);
> xdr_read_pages(xdr, len);
> /*
> * Position current pointer at beginning of tail, and
> * set remaining message length.
> */
> - if (len > PAGE_CACHE_SIZE - xdr->buf->page_base)
> - len = PAGE_CACHE_SIZE - xdr->buf->page_base;
> - xdr->p = (__be32 *)(kaddr + xdr->buf->page_base);
> - xdr->end = (__be32 *)((char *)xdr->p + len);
> + xdr_set_page_base(xdr, 0, len);
> }
> EXPORT_SYMBOL_GPL(xdr_enter_page);
>
> --
> 1.7.3.4
>
>
>
> --
> Trond Myklebust
> Linux NFS client maintainer
>
> NetApp
> Trond.Myklebust at netapp.com
> www.netapp.com
>
>
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH 1/2] Add a common struct clk
From: Sascha Hauer @ 2011-01-10 10:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201101101043.05406.jeremy.kerr@canonical.com>
On Mon, Jan 10, 2011 at 10:43:04AM +0800, Jeremy Kerr wrote:
> Hi Sascha,
>
> > I'm currently thinking about how to get the locking right with this
> > approach. In the current i.MX implementation we have a global lock which
> > protects the clock enable counter and also the register accesses in the
> > clock code. With the common struct clock we have a lock per clock which
> > only protects the enable counter, so we have to introduce a second lock
> > to protect the register accesses.
>
> Are the registers shared between clocks? If not, you can just use the existing
> per-clk lock. Otherwise it'd be reasonable to add a global register lock,
> protecting accesses to the shared register set (and *only* protecting these
> registers).
Yes, the registers are shared between clocks.
>
> > The problem comes with nested calls to for example clk_enable which
> > happens when the parent clock gets enabled. currently we do this with
> > clk->enable(clk->parent) which results in an unlocked clk_enable of the
> > parent. With common struct clk we would have to call
> > clk_enable(clk_get_parent(clk) which results in taking the lock a second
> > time.
> > Any ideas how to solve this?
>
> With the shared register lock, you just need to make sure that you don't
> recurse to the parent while holding the lock.
>
> For clocks with a shared register set, the general pattern would be something
> like:
>
> struct clk_foo {
> struct clk clk;
> u32 enable_reg;
> u32 enable_mask;
> struct clk *parent;
> };
>
> static DEFINE_SPINLOCK(clk_foo_register_lock);
>
> /* called with _clk->lock held */
> static int clk_foo_enable(struct clk *_clk)
> {
> struct clk_foo *clk = to_clk_foo(_clk);
> int reg, rc;
>
> /* enable parent - will acquire and release the parent's per-clk lock */
> rc = clk_enable(clk->parent);
> if (rc)
> return rc;
>
> /* do register update, under global register lock */
> spin_lock(&clk_foo_register_lock);
>
> reg = __raw_readl(clk->reg);
> __raw_writel(clk->reg, reg | clk->enable_mask);
>
> spin_unlock(&clk_foo_register_lock);
>
> return 0;
> }
>
> struct clk_foo_ops = {
> .enable = clk_foo_enable;
> [...]
> };
Ok, that should do it. Unfortunately this requires pushing the lock down
to the individual functions instead of taking it in some global place.
>
> However, because clk_mxc introduces its own set of abstractions, there may be
> some merging to do here. For my work on mx51, I've done a very basic port:
>
> * changed plat-mxc's struct clk to struct clk_mxc
> * embedded struct clk into struct clk_mxc (ie, making it use the common API)
> * separated some of the simpler clocks to separate types (eg clk_fixed,
> clk_pll, clk_ccgr).
>
> The goal here is to separate all of the clocks into their most basic types,
> leaving no clk_mxc clocks remaining, then the locking should be much simpler.
I am aware of your work. In fact, I already did some work upon this. See
git://git.pengutronix.de/git/imx/linux-2.6.git clk-common
and
git://git.pengutronix.de/git/imx/linux-2.6.git clk-common-wip
The first branch converts the whole i.MX architecture to clk-common.
The second branch converts i.MX51 into the basic building blocks. See
how i.MX51 clock support looks like after the conversion:
http://git.pengutronix.de/?p=imx/linux-2.6.git;a=blob;f=arch/arm/mach-mx5/clock-mx51-mx53.c;h=60c05c9b8916ebcb856f1e3f4e8c419f878c13a3;hb=refs/heads/clk-common-wip
The following shows the basic building blocks I used:
http://git.pengutronix.de/?p=imx/linux-2.6.git;a=commitdiff;h=b2f7ef29c8d56ef3574a5040890ea0edc14dae7f
This branch must be reworked because the correct locking is missing, but
the first branch should be ready for merging once your clk-common
patches are merged. I'll post the patches for review soon. I hope it's
clear soon that your clk-common patches get merged.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH] mmc, ARM: Add zboot from MMC support for SuperH Mobile ARM
From: Pawel Moll @ 2011-01-10 10:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110109225042.GB29257@verge.net.au>
On Mon, 10 Jan 2011 07:50:42 +0900, Simon Horman <horms@verge.net.au>
wrote:
>> > Documentation/arm/SH-Mobile/Makefile | 8 +
>> > Documentation/arm/SH-Mobile/vrl4.c | 169
>> +++++++++++++++++++++
>> How about putting those two into "tools" (in particular "tools/arm")
>> instead of "Documentation"?
>> Just a thought... ;-)
>
> Thats fine by me except that tools/arm doesn't exist yet.
> It would be good to get some consensus before creating it.
I think there is consensus regarding "tools" as a place for user-space
tools - eg. perf tools used to live in "Documentation/..." and then were
moved to "tools/perf".
Now, whether your stuff should be in "tools/SH-Mobile" or
"tools/arm/SH-Mobile", I have no opinion ;-)
Cheers!
Pawe?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox