Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox