Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/5] ARM: AT91: Add AT91RM9200 DT board
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  6:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350251199-28065-5-git-send-email-manabian@gmail.com>

On 23:46 Sun 14 Oct     , Joachim Eastwood wrote:
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
>  arch/arm/mach-at91/Kconfig           |  8 +++++
>  arch/arm/mach-at91/Makefile          |  1 +
>  arch/arm/mach-at91/board-rm9200-dt.c | 59 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-at91/generic.h         |  1 +
>  arch/arm/mach-at91/setup.c           | 14 +++++++++
>  5 files changed, 83 insertions(+)
>  create mode 100644 arch/arm/mach-at91/board-rm9200-dt.c
> 
> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
> index d9b0546..3f45906 100644
> --- a/arch/arm/mach-at91/Kconfig
> +++ b/arch/arm/mach-at91/Kconfig
> @@ -505,6 +505,14 @@ endif
>  
>  comment "Generic Board Type"
>  
> +config MACH_AT91RM9200_DT
> +	bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
> +	select SOC_AT91RM9200
depends on
> +	select USE_OF
> +	help
> +	  Select this if you want to experiment device-tree with
> +	  an Atmel RM9200 Evaluation Kit.
> +

Best Regards,
J.

^ permalink raw reply

* [PATCH 5/5] ARM: AT91: Add AT91RM9200 device tree
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  6:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350251199-28065-6-git-send-email-manabian@gmail.com>

 +
> +			pinctrl at fffff400 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
> +				ranges = <0xfffff400 0xfffff400 0x800>;
> +
> +				atmel,mux-mask = <
> +					/*    A         B     */
> +					 0xffffffff 0xffffffff  /* pioA */
> +					 0xffffffff 0x083fffff  /* pioB */
> +					 0xffff3fff 0x00000000  /* pioC */
> +					 0x03ff87ff 0x0fffff80  /* pioD */
> +					>;
> +
> +				/* shared pinctrl settings */
> +				dbgu {
> +					pinctrl_dbgu: dbgu-0 {
> +						atmel,pins =
> +							<0 30 0x1 0x0	/* PA30 periph A */
> +							 0 31 0x1 0x1>;	/* PA31 periph with pullup */
> +					};
> +				};
> +
> +				uart0 {
> +					pinctrl_uart0: uart0-0 {
> +						atmel,pins =
> +							<0 17 0x1 0x0	/* PA17 periph A */
> +							 0 18 0x1 0x0>;	/* PA18 periph A */
> +					};
> +
> +					pinctrl_uart0_rts_cts: uart0_rts_cts-0 {
> +						atmel,pins =
> +							<0 20 0x1 0x0	/* PA20 periph A */
> +							 0 21 0x1 0x0>;	/* PA21 periph A */
> +					};
> +				};
> +
> +				uart1 {
> +					pinctrl_uart1: uart1-0 {
> +						atmel,pins =
> +							<1 20 0x1 0x1	/* PB20 periph A with pullup */
> +							 1 21 0x1 0x0>;	/* PB21 periph A */
> +					};
> +
> +					pinctrl_uart1_rts_cts: uart1_rts_cts-0 {
> +						atmel,pins =
> +							<1 24 0x1 0x0	/* PB24 periph A */
> +							 1 26 0x1 0x0>;	/* PB26 periph A */
> +					};
> +
> +					pinctrl_uart1_dtr_dsr: uart1_dtr_dsr-0 {
> +						atmel,pins =
> +							<1 19 0x1 0x0	/* PB19 periph A */
> +							 1 25 0x1 0x0>;	/* PB25 periph A */
> +					};
> +
> +					pinctrl_uart1_dcd: uart1_dcd-0 {
> +						atmel,pins =
> +							<1 23 0x1 0x0>;	/* PB23 periph A */
> +					};
> +
> +					pinctrl_uart1_ri: uart1_ri-0 {
> +						atmel,pins =
> +							<1 18 0x1 0x0>;	/* PB18 periph A */
> +					};
> +				};
> +
> +				uart2 {
> +					pinctrl_uart2: uart2-0 {
> +						atmel,pins =
> +							<0 22 0x1 0x0	/* PA22 periph A */
> +							 0 23 0x1 0x1>;	/* PA23 periph A with pullup */
> +					};
> +
> +					pinctrl_uart2_rts_cts: uart2_rts_cts-0 {
> +						atmel,pins =
> +							<0 30 0x2 0x0	/* PA30 periph B */
> +							 0 31 0x2 0x0>;	/* PA31 periph B */
> +					};
> +				};
> +
> +				uart3 {
> +					pinctrl_uart3: uart3-0 {
> +						atmel,pins =
> +							<0 5 0x2 0x1	/* PA5 periph B with pullup */
> +							 0 6 0x2 0x0>;	/* PA6 periph B */
> +					};
> +
> +					pinctrl_uart3_rts_cts: uart3_rts_cts-0 {
> +						atmel,pins =
> +							<1 0 0x2 0x0	/* PB0 periph B */
> +							 1 1 0x2 0x0>;	/* PB1 periph B */
> +					};
> +				};
> +
> +				nand {
> +					pinctrl_nand: nand-0 {
> +						atmel,pins =
> +							<2 2 0x0 0x1	/* PC2 gpio RDY pin pull_up */
> +							 1 1 0x0 0x1>;	/* PB1 gpio CD pin pull_up */
> +					};
I do not yet check the pin I'll do it later

but look ok

please a board so we can test it the rm9200ek at least

Best Regards,
J.

^ permalink raw reply

* [PATCH 1/5] ARM: AT91: Fix build failure on board-dt
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350251199-28065-2-git-send-email-manabian@gmail.com>

On 23:46 Sun 14 Oct     , Joachim Eastwood wrote:
> We need CONFIG_SOC_AT91SAM9 to get the at91sam926x_timer
> symbol used in board-dt.
as I said before you can not do a select you need to do a depends

as you will have no clock as you select no SoC

Best Regards,
J.
> 
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
>  arch/arm/mach-at91/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
> index 0fafb6a..d9b0546 100644
> --- a/arch/arm/mach-at91/Kconfig
> +++ b/arch/arm/mach-at91/Kconfig
> @@ -507,6 +507,7 @@ comment "Generic Board Type"
>  
>  config MACH_AT91SAM_DT
>  	bool "Atmel AT91SAM Evaluation Kits with device-tree support"
> +	select SOC_AT91SAM9
>  	select USE_OF
>  	help
>  	  Select this if you want to experiment device-tree with
> -- 
> 1.7.12.3
> 

^ permalink raw reply

* [PATCH 0/5] Add DT support for AT91RM9200
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  5:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350251199-28065-1-git-send-email-manabian@gmail.com>

On 23:46 Sun 14 Oct     , Joachim Eastwood wrote:
> Hi
> 
> This patch series add support for devicetree on AT91RM9200. Series is dependent upon at91-pinctrl.
> 
> There isn't support for any boards yet, but I am working on one now. I will submit it once I have a couple of more bindings in place.
> 
> Patch 1 is a fixfor a build failure which can happen if board-dt is enabled when no AT91SAM machines are enabled.
> 

next time put the version number in subject

Best Regards,
J.

^ permalink raw reply

* dts: question about how to configure PIO used as i2c irq
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  5:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507B7AC3.7090904@gmail.com>

On 10:53 Mon 15 Oct     , Bo Shen wrote:
> Hi All,
>   When moving atmel qt1070 linux driver with DT support. The atmel
> qt1070 is an I2C device. I meet the following questions.
> 
>   The qt1070 DT node
>   --<--------------
>   qt1070: keyboard at 1b {
>         compatible = "atmel,qt1070";
>         reg = <0x1b>;
>         interrupt-parent = <&pioA>;
>         interrupts = <7 0x0>;
>   };
>   -->--------------
> 
>   DT will parse this node and map irq, the i2c_client->irq. This can
> be used directly in atmel qt1070 driver. However, the PIO which used
> as irq need configure as a PIO input. Now, we can not use
> irq_to_gpio() function to convert irq to gpio. So, if we can not
> configure this gpio.
> 
>   If we configure the pio in board-dt.c, I think this is not a good
> place. For example, if the kernel image support multiplatform, while
> on these platform, using different pio for qt1070, so this will
> cause only one platform can use qt1070.
> 
>   So, for this question, how should I solve it? Would you please
> give me some advice?
I already reply you in private 4 times

you have only 2 choice pass the gpio and manage in c
or configure the gpio as input in the xlate or map of the gpio drivers and the
mux via pinctrl

Best Regards,
J.

^ permalink raw reply

* [PATCH] i2c: i2c-gpio: fix issue when DT node greater than 1
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-15  5:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507B7C07.3070702@atmel.com>

On 10:59 Mon 15 Oct     , Bo Shen wrote:
> Hi Jean Delvare,
> 
> On 10/10/2012 10:54, Bo Shen wrote:
> >
> >Hi Jean Delvare,
> >
> >On 9/19/2012 23:54, Jean Delvare wrote:
> >>On Wed, 19 Sep 2012 09:28:04 -0600, Stephen Warren wrote:
> >>>On 09/18/2012 07:15 PM, Bo Shen wrote:
> >>>>I add the debug info, and it give the following error without this
> >>>>patch.
> >>>>
> >>>>--<8----------------------------------
> >>>>adap->name = i2c-gpio-1
> >>>>i2c-gpio i2c.2: using pins 30 (SDA) and 31 (SCL)
> >>>>adap->name = i2c-gpio-1
> >>>>i2c-gpio: probe of i2c.3 failed with error -16
> >>>>-->8----------------------------------
> >>>>
> >>>>With this patch, it successfully registered.
> >>>>--<8----------------------------------
> >>>>adap->name = i2c-gpio0
> >>>>i2c-gpio i2c.2: using pins 30 (SDA) and 31 (SCL)
> >>>>adap->name = i2c-gpio1
> >>>>i2c-gpio i2c.3: using pins 90 (SDA) and 91 (SCL)
> >>>>-->8----------------------------------
> >>>
> >>>Yes, that explains why the registration fails, but not why this patch is
> >>>the correct solution to the problem.
> >>>
> >>>The problematic code appears to be:
> >>>
> >>>snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
> >>>
> >>>Instead, I think that should be something more like:
> >>>
> >>>adap->name = dev_name(&pdev->dev);
> >>
> >>strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name))
> >> if anything, as adap->name is a buffer, not a pointer.
> >
> >I am sorry for late. I have tested with DT, it works.
> >
> >Please send this patch to fix the issue.
> >Thanks.
> 
> Ping?
> 
> Will you send this patch? Or, I send this patch and add your S.O.B,
> which do you prefer?

do it

Best Regards,
J.

^ permalink raw reply

* [PATCH] ARM: OMAP4: hwmod data: gpmc main clk
From: Afzal Mohammed @ 2012-10-15  5:47 UTC (permalink / raw)
  To: linux-arm-kernel

gpmc has been converted to a driver. It requests clock with
con-id "fck", if not available, probe fails. Clock for gpmc
device with con-id "fck" is created (aliased) along with
hwmod device, and for that to happen, main_clk needs to be
specified in hwmod entry, add it for OMAP4.

Note that the corresponding clock is dummy.

Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 652d028..ce04002 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1363,6 +1363,7 @@ static struct omap_hwmod omap44xx_gpmc_hwmod = {
 	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_gpmc_irqs,
 	.sdma_reqs	= omap44xx_gpmc_sdma_reqs,
+	.main_clk	= "gpmc_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET,
-- 
1.7.12

^ permalink raw reply related

* [PATCH RFC 2/6 v3] gpio: Add sysfs support to block GPIO API
From: Ryan Mallon @ 2012-10-15  5:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350069085-13283-3-git-send-email-stigge@antcom.de>

On 13/10/12 06:11, Roland Stigge wrote:
> This patch adds sysfs support to the block GPIO API.
> 
> Signed-off-by: Roland Stigge <stigge@antcom.de>

Hi Roland,

Some comments below,

~Ryan

> 
> ---
>  Documentation/ABI/testing/sysfs-gpio |    6 
>  drivers/gpio/gpiolib.c               |  226 ++++++++++++++++++++++++++++++++++-
>  include/asm-generic/gpio.h           |   11 +
>  include/linux/gpio.h                 |   13 ++
>  4 files changed, 254 insertions(+), 2 deletions(-)
> 
> --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio
> +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio
> @@ -24,4 +24,8 @@ Description:
>  	    /base ... (r/o) same as N
>  	    /label ... (r/o) descriptive, not necessarily unique
>  	    /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
> -
> +	/blockN ... for each GPIO block #N
> +	    /ngpio ... (r/o) number of GPIOs in this group
> +	    /exported ... sysfs export state of this group (0, 1)
> +	    /value ... current value as 32 or 64 bit integer in decimal
> +                       (only available if /exported is 1)
> --- linux-2.6.orig/drivers/gpio/gpiolib.c
> +++ linux-2.6/drivers/gpio/gpiolib.c
> @@ -974,6 +974,218 @@ static void gpiochip_unexport(struct gpi
>  				chip->label, status);
>  }
>  
> +static ssize_t gpio_block_ngpio_show(struct device *dev,
> +				     struct device_attribute *attr, char *buf)
> +{
> +	const struct gpio_block	*block = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", block->ngpio);
> +}
> +static struct device_attribute
> +dev_attr_block_ngpio = __ATTR(ngpio, 0444, gpio_block_ngpio_show, NULL);

static DEVICE_ATTR(ngpio, S_IRUGO, gpio_block_ngpio_show, NULL);

> +
> +static ssize_t gpio_block_value_show(struct device *dev,
> +				     struct device_attribute *attr, char *buf)
> +{
> +	const struct gpio_block *block = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", gpio_block_get(block));

Printing the value of a bunch of pins as a decimal is a bit odd. Hex, or
a bitmap would be more appropriate.

> +}
> +
> +static bool gpio_block_is_output(struct gpio_block *block)
> +{
> +	int i;
> +
> +	for (i = 0; i < block->ngpio; i++)
> +		if (!test_bit(FLAG_IS_OUT, &gpio_desc[block->gpio[i]].flags))
> +			return false;

Shouldn't a block force all of the pins to be the same direction? Or at
least have gpio_block_set skip pins which aren't outputs.

> +	return true;
> +}
> +
> +static ssize_t gpio_block_value_store(struct device *dev,
> +				      struct device_attribute *attr,
> +				      const char *buf, size_t size)
> +{
> +	ssize_t			status;
> +	struct gpio_block	*block = dev_get_drvdata(dev);
> +	unsigned long		value;
> +
> +	mutex_lock(&sysfs_lock);
> +
> +	status = kstrtoul(buf, 0, &value);
> +	if (status == 0) {

You don't need to do the kstrtoul under the lock:

	err = kstrtoul(buf, 0, &value);
	if (err)
		return err;

	mutex_lock(&sysfs_lock);
	...

Global lock is a bit lame, it serialises all of your bitbanged busses
against each other. Why is it not part of the gpio_block structure?


> +		if (gpio_block_is_output(block)) {
> +			gpio_block_set(block, value);
> +			status = size;
> +		} else {
> +			status = -EPERM;
> +		}
> +	}
> +
> +	mutex_unlock(&sysfs_lock);
> +	return status;
> +}
> +
> +static struct device_attribute
> +dev_attr_block_value = __ATTR(value, 0644, gpio_block_value_show,
> +			      gpio_block_value_store);

Use DEVICE_ATTR and S_IWUSR | S_IRUGO permission macros.

> +
> +static int gpio_block_value_is_exported(struct gpio_block *block)
> +{
> +	struct device		*dev;
> +	struct sysfs_dirent	*sd = NULL;
> +
> +	mutex_lock(&sysfs_lock);
> +	dev = class_find_device(&gpio_class, NULL, block, match_export);
> +	if (!dev)
> +		goto out;
> +
> +	sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
> +
> +out:
> +	mutex_unlock(&sysfs_lock);
> +	return sd ? 1 : 0;

  return sd;

or:

  return !!sd;

> +}
> +
> +static ssize_t gpio_block_exported_show(struct device *dev,
> +					struct device_attribute *attr,
> +					char *buf)
> +{
> +	struct gpio_block	*block = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", gpio_block_value_is_exported(block));
> +}
> +
> +static int gpio_block_value_export(struct gpio_block *block)
> +{
> +	struct device	*dev;
> +	int		status;
> +	int		i;
> +
> +	mutex_lock(&sysfs_lock);
> +
> +	for (i = 0; i < block->ngpio; i++) {
> +		status = gpio_request(block->gpio[i], "sysfs");
> +		if (status)
> +			goto out;
> +	}
> +
> +	dev = class_find_device(&gpio_class, NULL, block, match_export);
> +	if (!dev) {
> +		status = -ENODEV;
> +		goto out;
> +	}
> +
> +	status = device_create_file(dev, &dev_attr_block_value);
> +	if (status)
> +		goto out;
> +
> +	mutex_unlock(&sysfs_lock);
> +	return 0;
> +
> +out:
> +	while (i > 0) {
> +		i--;
> +		gpio_free(block->gpio[i]);
> +	}

Nitpick:

	while (--i >= 0)
		gpio_free(block->gpio[i]);

> +
> +	mutex_unlock(&sysfs_lock);
> +	return status;
> +}
> +
> +static int gpio_block_value_unexport(struct gpio_block *block)
> +{
> +	struct device	*dev;
> +	int		i;
> +
> +	dev = class_find_device(&gpio_class, NULL, block, match_export);
> +	if (!dev)
> +		return -ENODEV;
> +
> +	for (i = 0; i < block->ngpio; i++)
> +		gpio_free(block->gpio[i]);
> +
> +	device_remove_file(dev, &dev_attr_block_value);
> +
> +	return 0;
> +}
> +
> +static ssize_t gpio_block_exported_store(struct device *dev,
> +					 struct device_attribute *attr,
> +					 const char *buf, size_t size)
> +{
> +	long	value;
> +	int	status;
> +	struct	gpio_block *block = dev_get_drvdata(dev);
> +	int	exported = gpio_block_value_is_exported(block);
> +
> +	status = kstrtoul(buf, 0, &value);
> +	if (status < 0)
> +		goto err;
> +
> +	if (value != exported) {
> +		if (value)
> +			status = gpio_block_value_export(block);
> +		else
> +			status = gpio_block_value_unexport(block);
> +		if (!status)
> +			status = size;
> +	} else {
> +		status = size;
> +	}
> +err:
> +	return status;
> +}
> +
> +static DEVICE_ATTR(exported, 0644, gpio_block_exported_show,
> +		   gpio_block_exported_store);
> +
> +static const struct attribute *gpio_block_attrs[] = {
> +	&dev_attr_block_ngpio.attr,
> +	&dev_attr_exported.attr,
> +	NULL,
> +};
> +
> +static const struct attribute_group gpio_block_attr_group = {
> +	.attrs = (struct attribute **) gpio_block_attrs,
> +};
> +
> +int gpio_block_export(struct gpio_block *block)
> +{
> +	int		status;
> +	struct device	*dev;
> +
> +	/* can't export until sysfs is available ... */
> +	if (!gpio_class.p) {
> +		pr_debug("%s: called too early!\n", __func__);
> +		return -ENOENT;
> +	}
> +
> +	mutex_lock(&sysfs_lock);
> +	dev = device_create(&gpio_class, NULL, MKDEV(0, 0), block,
> +			    block->name);
> +	if (!IS_ERR(dev))
> +		status = sysfs_create_group(&dev->kobj, &gpio_block_attr_group);
> +	else
> +		status = PTR_ERR(dev);
> +	mutex_unlock(&sysfs_lock);
> +
> +	return status;
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_export);
> +
> +void gpio_block_unexport(struct gpio_block *block)
> +{
> +	struct device *dev;
> +
> +	mutex_lock(&sysfs_lock);
> +	dev = class_find_device(&gpio_class, NULL, block, match_export);
> +	if (dev)
> +		device_unregister(dev);
> +	mutex_unlock(&sysfs_lock);
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_unexport);
> +
>  static int __init gpiolib_sysfs_init(void)
>  {
>  	int		status;
> @@ -1882,7 +2094,14 @@ int gpio_block_register(struct gpio_bloc
>  			break;
>  		}
>  	}
> -	return i == NR_GPIO_BLOCKS ? -EBUSY : 0;
> +	if (i == NR_GPIO_BLOCKS)
> +		goto err;
> +
> +	gpio_block_export(block);
> +
> +	return 0;
> +err:
> +	return -EBUSY;
>  }
>  EXPORT_SYMBOL_GPL(gpio_block_register);
>  
> @@ -1896,6 +2115,11 @@ void gpio_block_unregister(struct gpio_b
>  			break;
>  		}
>  	}
> +
> +	if (i == NR_GPIO_BLOCKS)
> +		return;
> +
> +	gpio_block_unexport(block);
>  }
>  EXPORT_SYMBOL_GPL(gpio_block_unregister);
>  
> --- linux-2.6.orig/include/asm-generic/gpio.h
> +++ linux-2.6/include/asm-generic/gpio.h
> @@ -210,6 +210,8 @@ extern int gpio_export_link(struct devic
>  			unsigned gpio);
>  extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
>  extern void gpio_unexport(unsigned gpio);
> +extern int gpio_block_export(struct gpio_block *block);
> +extern void gpio_block_unexport(struct gpio_block *block);
>  
>  #endif	/* CONFIG_GPIO_SYSFS */
>  
> @@ -269,6 +271,15 @@ static inline int gpio_sysfs_set_active_
>  static inline void gpio_unexport(unsigned gpio)
>  {
>  }
> +
> +static inline int gpio_block_export(struct gpio_block *block)
> +{
> +	return -ENOSYS;
> +}
> +
> +static inline void gpio_block_unexport(struct gpio_block *block)
> +{
> +}
>  #endif	/* CONFIG_GPIO_SYSFS */
>  
>  #endif /* _ASM_GENERIC_GPIO_H */
> --- linux-2.6.orig/include/linux/gpio.h
> +++ linux-2.6/include/linux/gpio.h
> @@ -278,6 +278,19 @@ static inline void gpio_unexport(unsigne
>  	WARN_ON(1);
>  }
>  
> +static inline int gpio_block_export(struct gpio_block *block)
> +{
> +	/* GPIO block can never have been requested or set as {in,out}put */
> +	WARN_ON(1);
> +	return -EINVAL;
> +}
> +
> +static inline void gpio_block_unexport(struct gpio_block *block)
> +{
> +	/* GPIO block can never have been exported */
> +	WARN_ON(1);
> +}
> +
>  static inline int gpio_to_irq(unsigned gpio)
>  {
>  	/* GPIO can never have been requested or set as input */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply

* [PATCH v3] ARM: vfp: fix save and restore when running on pre-VFPv3 and CONFIG_VFPv3 set
From: Paul Walmsley @ 2012-10-15  5:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAG5Tg6XqpeRppWbr9-yBmsf+2TobhE5ateMX4crs10grn-tuAA@mail.gmail.com>


After commit 846a136881b8f73c1f74250bf6acfaa309cab1f2 ("ARM: vfp: fix
saving d16-d31 vfp registers on v6+ kernels"), the OMAP 2430SDP board
started crashing during boot with omap2plus_defconfig:

[    3.875122] mmcblk0: mmc0:e624 SD04G 3.69 GiB
[    3.915954]  mmcblk0: p1
[    4.086639] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM
[    4.093719] Modules linked in:
[    4.096954] CPU: 0    Not tainted  (3.6.0-02232-g759e00b #570)
[    4.103149] PC is at vfp_reload_hw+0x1c/0x44
[    4.107666] LR is at __und_usr_fault_32+0x0/0x8

It turns out that the context save/restore fix unmasked a latent bug
in commit 5aaf254409f8d58229107b59507a8235b715a960 ("ARM: 6203/1: Make
VFPv3 usable on ARMv6").  When CONFIG_VFPv3 is set, but the kernel is
booted on a pre-VFPv3 core, the code attempts to save and restore the
d16-d31 VFP registers.  These are only present on non-D16 VFPv3+, so
this results in an undefined instruction exception.  The code didn't
crash before commit 846a136 because the save and restore code was
only touching d0-d15, present on all VFP.

Fix by implementing a request from Russell King to add a new HWCAP
flag that affirmatively indicates the presence of the d16-d31
registers:

   http://marc.info/?l=linux-arm-kernel&m=135013547905283&w=2

and some feedback from M?ns to clarify the name of the HWCAP flag.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@linaro.org>
Cc: M?ns Rullg?rd <mans.rullgard@linaro.org>
---
Thanks for the suggestion, M?ns; certainly a readability improvement.

 arch/arm/include/asm/vfpmacros.h  |   12 ++++++------
 arch/arm/include/uapi/asm/hwcap.h |    3 ++-
 arch/arm/vfp/vfpmodule.c          |    9 ++++++---
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h
index 6a6f1e4..301c1db 100644
--- a/arch/arm/include/asm/vfpmacros.h
+++ b/arch/arm/include/asm/vfpmacros.h
@@ -27,9 +27,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
-	tst	\tmp, #HWCAP_VFPv3D16
-	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
-	addne	\base, \base, #32*4		    @ step over unused register space
+	tst	\tmp, #HWCAP_VFPD32
+	ldcnel	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
+	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
@@ -51,9 +51,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
-	tst	\tmp, #HWCAP_VFPv3D16
-	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
-	addne	\base, \base, #32*4		    @ step over unused register space
+	tst	\tmp, #HWCAP_VFPD32
+	stcnel	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
+	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index f254f65..3688fd1 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -18,11 +18,12 @@
 #define HWCAP_THUMBEE	(1 << 11)
 #define HWCAP_NEON	(1 << 12)
 #define HWCAP_VFPv3	(1 << 13)
-#define HWCAP_VFPv3D16	(1 << 14)
+#define HWCAP_VFPv3D16	(1 << 14)	/* also set for VFPv4-D16 */
 #define HWCAP_TLS	(1 << 15)
 #define HWCAP_VFPv4	(1 << 16)
 #define HWCAP_IDIVA	(1 << 17)
 #define HWCAP_IDIVT	(1 << 18)
+#define HWCAP_VFPD32	(1 << 19)	/* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT)
 
 
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index c834b32..3b44e0d 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -701,11 +701,14 @@ static int __init vfp_init(void)
 			elf_hwcap |= HWCAP_VFPv3;
 
 			/*
-			 * Check for VFPv3 D16. CPUs in this configuration
-			 * only have 16 x 64bit registers.
+			 * Check for VFPv3 D16 and VFPv4 D16.  CPUs in
+			 * this configuration only have 16 x 64bit
+			 * registers.
 			 */
 			if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
-				elf_hwcap |= HWCAP_VFPv3D16;
+				elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
+			else
+				elf_hwcap |= HWCAP_VFPD32;
 		}
 #endif
 		/*
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib
From: Ryan Mallon @ 2012-10-15  5:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350069085-13283-2-git-send-email-stigge@antcom.de>

On 13/10/12 06:11, Roland Stigge wrote:
> The recurring task of providing simultaneous access to GPIO lines (especially
> for bit banging protocols) needs an appropriate API.
> 
> This patch adds a kernel internal "Block GPIO" API that enables simultaneous
> access to several GPIOs. This is done by abstracting GPIOs to an n-bit word:
> Once requested, it provides access to a group of GPIOs which can range over
> multiple GPIO chips.
> 
> Signed-off-by: Roland Stigge <stigge@antcom.de>

Hi Roland,

Some comments below.

~Ryan

> ---
> 
>  Documentation/gpio.txt     |   45 +++++++++
>  drivers/gpio/gpiolib.c     |  223 +++++++++++++++++++++++++++++++++++++++++++++
>  include/asm-generic/gpio.h |   14 ++
>  include/linux/gpio.h       |   61 ++++++++++++
>  4 files changed, 343 insertions(+)
> 
> --- linux-2.6.orig/Documentation/gpio.txt
> +++ linux-2.6/Documentation/gpio.txt
> @@ -439,6 +439,51 @@ slower clock delays the rising edge of S
>  signaling rate accordingly.
>  
>  
> +Block GPIO
> +----------
> +
> +The above described interface concentrates on handling single GPIOs.  However,
> +in applications where it is critical to set several GPIOs at once, this
> +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines.
> +Consider a GPIO controller that is connected via a slow I2C line. When
> +switching two or more GPIOs one after another, there can be considerable time
> +between those events. This is solved by an interface called Block GPIO:

The emulate behaviour of gpio block switches gpios one after the other.
Is the problem only solved if the block_get/block_set callbacks can be
implemented?

> +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size);
> +
> +This creates a new block of GPIOs as a list of GPIO numbers with the specified
> +size which are accessible via the returned struct gpio_block and the accessor
> +functions described below. Please note that you need to request the GPIOs
> +separately via gpio_request(). An arbitrary list of globally valid GPIOs can be
> +specified, even ranging over several gpio_chips. Actual handling of I/O
> +operations will be done on a best effort base, i.e. simultaneous I/O only where
> +possible by hardware and implemented in the respective GPIO driver. The number
> +of GPIOs in one block is limited to 32 on a 32 bit system, and 64 on a 64 bit
> +system. However, several blocks can be defined at once.
> +
> +unsigned gpio_block_get(struct gpio_block *block);
> +void gpio_block_set(struct gpio_block *block, unsigned value);
> +
> +With those accessor functions, setting and getting the GPIO values is possible,
> +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return
> +value of gpio_block_get() and in the value argument of gpio_block_set()
> +corresponds to a bit specified on gpio_block_create(). Block operations in
> +hardware are only possible where the respective GPIO driver implements it,
> +falling back to using single GPIO operations where the driver only implements
> +single GPIO access.
> +
> +void gpio_block_free(struct gpio_block *block);
> +
> +After the GPIO block isn't used anymore, it should be free'd via
> +gpio_block_free().
> +
> +int gpio_block_register(struct gpio_block *block);
> +void gpio_block_unregister(struct gpio_block *block);
> +
> +These functions can be used to register a GPIO block. Blocks registered this
> +way will be available via sysfs.
> +
> +
>  What do these conventions omit?
>  ===============================
>  One of the biggest things these conventions omit is pin multiplexing, since
> --- linux-2.6.orig/drivers/gpio/gpiolib.c
> +++ linux-2.6/drivers/gpio/gpiolib.c
> @@ -83,6 +83,10 @@ static inline void desc_set_label(struct
>  #endif
>  }
>  
> +#define NR_GPIO_BLOCKS	16
> +
> +static struct gpio_block *gpio_block[NR_GPIO_BLOCKS];
> +
>  /* Warn when drivers omit gpio_request() calls -- legal but ill-advised
>   * when setting direction, and otherwise illegal.  Until board setup code
>   * and drivers use explicit requests everywhere (which won't happen when
> @@ -1676,6 +1680,225 @@ void __gpio_set_value(unsigned gpio, int
>  }
>  EXPORT_SYMBOL_GPL(__gpio_set_value);
>  
> +static inline

Nitpick - don't need the inline, the compiler will do so for you.

> +int gpio_block_chip_index(struct gpio_block *block, struct gpio_chip *gc)

Should be static?

> +{
> +	int i;
> +
> +	for (i = 0; i < block->nchip; i++) {
> +		if (block->gbc[i].gc == gc)
> +			return i;
> +	}
> +	return -1;
> +}
> +
> +struct gpio_block *gpio_block_create(unsigned *gpios, size_t size,
> +				     const char *name)
> +{
> +	struct gpio_block *block;
> +	struct gpio_block_chip *gbc;
> +	struct gpio_remap *remap;
> +	int i;
> +
> +	if (size < 1 || size > sizeof(unsigned) * 8)
> +		return ERR_PTR(-EINVAL);
> +
> +	block = kzalloc(sizeof(struct gpio_block), GFP_KERNEL);
> +	if (!block)
> +		return ERR_PTR(-ENOMEM);
> +
> +	block->name = name;
> +	block->ngpio = size;
> +	block->gpio = kzalloc(sizeof(*block->gpio) * size, GFP_KERNEL);
> +	if (!block->gpio)
> +		goto err1;
> +
> +	memcpy(block->gpio, gpios, sizeof(*block->gpio) * size);
> +
> +	for (i = 0; i < size; i++)
> +		if (!gpio_is_valid(gpios[i]))
> +			goto err2;

This loop should probably go at the start of the function, so you can
avoid doing the kzalloc/memcpy if it fails.

This function doesn't call gpio_request. Either it should, or it should
rely on the caller to have already done so, and call
gpio_ensure_requested here. There is also an implicit rule that any
gpios inside a block must not be freed as long as the block exists. The
code can't easily prevent this since gpios aren't refcounted. The rule
should be documented.

> +
> +	for (i = 0; i < size; i++) {
> +		struct gpio_chip *gc = gpio_to_chip(gpios[i]);
> +		int bit = gpios[i] - gc->base;
> +		int index = gpio_block_chip_index(block, gc);
> +
> +		if (index < 0) {
> +			block->nchip++;
> +			block->gbc = krealloc(block->gbc,
> +					      sizeof(struct gpio_block_chip) *
> +					      block->nchip, GFP_KERNEL);

krealloc is a bit nasty. Can't you add a struct list_head to struct
gpio_block_chip or something?

This also leaks memory if the krealloc fails, since the original pointer
is lost. You need to use a temporary for the re-allocation.

> +			if (!block->gbc)
> +				goto err2;
> +			gbc = &block->gbc[block->nchip - 1];
> +			gbc->gc = gc;
> +			gbc->remap = NULL;
> +			gbc->nremap = 0;
> +			gbc->mask = 0;
> +		} else {
> +			gbc = &block->gbc[index];
> +		}
> +		/* represents the mask necessary on calls to the driver's
> +		 * .get_block() and .set_block()
> +		 */

  /*
   * Nitpick - multi-line comment style looks like this.
   * However, other comments in this file use this style
   * so maybe keep for consistency.
   */

> +		gbc->mask |= BIT(bit);
> +
> +		/* collect gpios that are specified together, represented by
> +		 * neighboring bits
> +		 */
> +		remap = &gbc->remap[gbc->nremap - 1];

This looks broken. If gbc was re-alloced above (index < 0) then
gbc->remap == NULL and this will oops?

> +		if (!gbc->nremap || (bit - i != remap->offset)) {

gbc->nremap would have to be non-zero here, otherwise you have:

  gbc->remap[0 - 1]

above.

> +			gbc->nremap++;
> +			gbc->remap = krealloc(gbc->remap,
> +					      sizeof(struct gpio_remap) *
> +					      gbc->nremap, GFP_KERNEL);

Memory leak on failure. Also, is an alternative to krealloc possible.
Maybe a list?

> +			if (!gbc->remap)
> +				goto err3;
> +			remap = &gbc->remap[gbc->nremap - 1];
> +			remap->offset = bit - i;
> +			remap->mask = 0;
> +		}
> +
> +		/* represents the mask necessary for bit reordering between
> +		 * gpio_block (i.e. as specified on gpio_block_get() and
> +		 * gpio_block_set()) and gpio_chip domain (i.e. as specified on
> +		 * the driver's .set_block() and .get_block())
> +		 */
> +		remap->mask |= BIT(i);
> +	}

The remap functionality isn't very well explained (and looks like it
doesn't work properly anyway). Some comments explaining what the remap
does and how it works would be useful.

> +	return block;
> +err3:
> +	for (i = 0; i < block->nchip - 1; i++)
> +		kfree(block->gbc[i].remap);
> +	kfree(block->gbc);
> +err2:
> +	kfree(block->gpio);
> +err1:
> +	kfree(block);
> +	return ERR_PTR(-ENOMEM);
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_create);
> +
> +void gpio_block_free(struct gpio_block *block)
> +{
> +	int i;
> +
> +	for (i = 0; i < block->nchip; i++)
> +		kfree(block->gbc[i].remap);
> +	kfree(block->gpio);
> +	kfree(block->gbc);
> +	kfree(block);
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_free);
> +
> +unsigned gpio_block_get(const struct gpio_block *block)
> +{
> +	struct gpio_block_chip *gbc;
> +	int i, j;
> +	unsigned values = 0;
> +
> +	for (i = 0; i < block->nchip; i++) {
> +		unsigned remapped = 0;
> +
> +		gbc = &block->gbc[i];
> +
> +		if (gbc->gc->get_block) {
> +			remapped = gbc->gc->get_block(gbc->gc, gbc->mask);
> +		} else { /* emulate */
> +			unsigned bit = 1;
> +
> +			for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
> +				if (gbc->mask & bit)

A proper bitmask might be more ideal for this. It would remove the
sizeof(unsigned) restriction and allow you to use for_each_set_bit for
these loops.

> +					remapped |= gbc->gc->get(gbc->gc,
> +							gbc->gc->base + j) << j;
> +			}
> +		}
> +
> +		for (j = 0; j < gbc->nremap; j++) {
> +			struct gpio_remap *gr = &gbc->remap[j];
> +
> +			values |= (remapped >> gr->offset) & gr->mask;
> +		}
> +	}
> +
> +	return values;
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_get);
> +
> +void gpio_block_set(struct gpio_block *block, unsigned values)
> +{
> +	struct gpio_block_chip *gbc;
> +	int i, j;
> +
> +	for (i = 0; i < block->nchip; i++) {
> +		unsigned remapped = 0;
> +
> +		gbc = &block->gbc[i];
> +
> +		for (j = 0; j < gbc->nremap; j++) {
> +			struct gpio_remap *gr = &gbc->remap[j];
> +
> +			remapped |= (values & gr->mask) << gr->offset;
> +		}
> +		if (gbc->gc->set_block) {
> +			gbc->gc->set_block(gbc->gc, gbc->mask, remapped);
> +		} else { /* emulate */

Nitpick - Put the comment on a line by itself.

> +			unsigned bit = 1;
> +
> +			for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
> +				if (gbc->mask & bit)
> +					gbc->gc->set(gbc->gc, gbc->gc->base + j,
> +						     (remapped >> j) & 1);
> +			}

This doesn't clear pins which are set to zero? If you are using
gpio_block to bit-bang a bus then you probably want that to happen.
Probably you want three functions, gpio_block_set (set only),
gpio_block_clear (clear only) and gpio_block_drive (set/clear).

> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_set);
> +
> +struct gpio_block *gpio_block_find_by_name(const char *name)
> +{
> +	int i;
> +
> +	for (i = 0; i < NR_GPIO_BLOCKS; i++) {

A static limit is lame. Make it a list.

> +		if (gpio_block[i] && !strcmp(gpio_block[i]->name, name))
> +			return gpio_block[i];
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_find_by_name);
> +
> +int gpio_block_register(struct gpio_block *block)
> +{
> +	int i;
> +
> +	if (gpio_block_find_by_name(block->name))
> +		return -EBUSY;
> +
> +	for (i = 0; i < NR_GPIO_BLOCKS; i++) {
> +		if (!gpio_block[i]) {
> +			gpio_block[i] = block;
> +			break;
> +		}
> +	}
> +	return i == NR_GPIO_BLOCKS ? -EBUSY : 0;
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_register);
> +
> +void gpio_block_unregister(struct gpio_block *block)
> +{
> +	int i;
> +
> +	for (i = 0; i < NR_GPIO_BLOCKS; i++) {
> +		if (gpio_block[i] == block) {
> +			gpio_block[i] = NULL;
> +			break;
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(gpio_block_unregister);
> +
>  /**
>   * __gpio_cansleep() - report whether gpio value access will sleep
>   * @gpio: gpio in question
> --- linux-2.6.orig/include/asm-generic/gpio.h
> +++ linux-2.6/include/asm-generic/gpio.h
> @@ -43,6 +43,7 @@ static inline bool gpio_is_valid(int num
>  
>  struct device;
>  struct gpio;
> +struct gpio_block;
>  struct seq_file;
>  struct module;
>  struct device_node;
> @@ -105,6 +106,8 @@ struct gpio_chip {
>  						unsigned offset);
>  	int			(*get)(struct gpio_chip *chip,
>  						unsigned offset);
> +	unsigned		(*get_block)(struct gpio_chip *chip,
> +					     unsigned mask);
>  	int			(*direction_output)(struct gpio_chip *chip,
>  						unsigned offset, int value);
>  	int			(*set_debounce)(struct gpio_chip *chip,
> @@ -112,6 +115,8 @@ struct gpio_chip {
>  
>  	void			(*set)(struct gpio_chip *chip,
>  						unsigned offset, int value);
> +	void			(*set_block)(struct gpio_chip *chip,
> +					     unsigned mask, unsigned values);
>  
>  	int			(*to_irq)(struct gpio_chip *chip,
>  						unsigned offset);
> @@ -171,6 +176,15 @@ extern void gpio_set_value_cansleep(unsi
>  extern int __gpio_get_value(unsigned gpio);
>  extern void __gpio_set_value(unsigned gpio, int value);
>  
> +extern struct gpio_block *gpio_block_create(unsigned *gpio, size_t size,
> +					    const char *name);
> +extern void gpio_block_free(struct gpio_block *block);
> +extern unsigned gpio_block_get(const struct gpio_block *block);
> +extern void gpio_block_set(struct gpio_block *block, unsigned values);
> +extern struct gpio_block *gpio_block_find_by_name(const char *name);
> +extern int gpio_block_register(struct gpio_block *block);
> +extern void gpio_block_unregister(struct gpio_block *block);
> +
>  extern int __gpio_cansleep(unsigned gpio);
>  
>  extern int __gpio_to_irq(unsigned gpio);
> --- linux-2.6.orig/include/linux/gpio.h
> +++ linux-2.6/include/linux/gpio.h
> @@ -2,6 +2,7 @@
>  #define __LINUX_GPIO_H
>  
>  #include <linux/errno.h>
> +#include <linux/types.h>
>  
>  /* see Documentation/gpio.txt */
>  
> @@ -39,6 +40,31 @@ struct gpio {
>  	const char	*label;
>  };
>  
> +struct gpio_remap {
> +	int	mask;
> +	int	offset;
> +};
> +
> +struct gpio_block_chip {
> +	struct gpio_chip	*gc;
> +	struct gpio_remap	*remap;
> +	int			nremap;
> +	unsigned		mask;
> +};
> +
> +/**
> + * struct gpio_block - a structure describing a list of GPIOs for simultaneous
> + *                     operations
> + */
> +struct gpio_block {
> +	struct gpio_block_chip	*gbc;
> +	size_t			nchip;
> +	const char		*name;
> +
> +	int			ngpio;
> +	unsigned		*gpio;
> +};
> +
>  #ifdef CONFIG_GENERIC_GPIO
>  
>  #ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H
> @@ -169,6 +195,41 @@ static inline void gpio_set_value(unsign
>  	WARN_ON(1);
>  }
>  
> +static inline
> +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size,
> +				     const char *name)
> +{
> +	WARN_ON(1);
> +	return NULL;
> +}
> +
> +static inline void gpio_block_free(struct gpio_block *block)
> +{
> +	WARN_ON(1);
> +}
> +
> +static inline unsigned gpio_block_get(const struct gpio_block *block)
> +{
> +	WARN_ON(1);
> +	return 0;
> +}
> +
> +static inline void gpio_block_set(struct gpio_block *block, unsigned value)
> +{
> +	WARN_ON(1);
> +}
> +
> +static inline int gpio_block_register(struct gpio_block *block)
> +{
> +	WARN_ON(1);
> +	return 0;
> +}
> +
> +static inline void gpio_block_unregister(struct gpio_block *block)
> +{
> +	WARN_ON(1);
> +}
> +
>  static inline int gpio_cansleep(unsigned gpio)
>  {
>  	/* GPIO can never have been requested or set as {in,out}put */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

^ permalink raw reply

* [GIT PULL] imx multi-platform support
From: Shawn Guo @ 2012-10-15  3:40 UTC (permalink / raw)
  To: linux-arm-kernel

Arnd, Olof,

Here is the imx multi-platform support [1] that missed 3.7 merge window.
Please pull it for 3.8 and exposing on linux-next.  As it touches a lot
of files, I send it early, so that people can base their works off it
to avoid conflicts.

Sascha, please base your 3.8 branches off this one.

Subsystem maintainers,

We will keep this topic branch stable (non-rebase), so you are free
to merge it to solve conflicts or dependency if necessary.

Shawn

[1] http://thread.gmane.org/gmane.linux.alsa.devel/101419

-----

The following changes since commit ddffeb8c4d0331609ef2581d84de4d763607bd37:

  Linux 3.7-rc1 (2012-10-14 14:41:04 -0700)

are available in the git repository at:

  git://git.linaro.org/people/shawnguo/linux-2.6.git imx/multi-platform

for you to fetch changes up to c5a0d4977f00ca18c49d46fdaff4b2cfeaa4eb28:

  ARM: imx: enable multi-platform build (2012-10-15 10:10:15 +0800)

----------------------------------------------------------------
Shawn Guo (31):
      ARM: imx: include board headers in the same folder
      ARM: imx: move iomux drivers and headers into mach-imx
      ARM: imx: remove unnecessary inclusion from device-imx*.h
      ARM: imx: move platform device code into mach-imx
      ARM: imx: merge plat-mxc into mach-imx
      ARM: imx: include common.h rather than mach/common.h
      ARM: imx: ARM: imx: include cpuidle.h rather than mach/cpuidle.h
      ARM: imx: include iim.h rather than mach/iim.h
      ARM: imx: include iram.h rather than mach/iram.h
      ARM: imx: include ulpi.h rather than mach/ulpi.h
      ARM: imx: remove mach/dma-mx1-mx2.h
      dma: ipu: rename mach/ipu.h to include/linux/dma/ipu-dma.h
      dma: imx-sdma: remove unneeded mach/hardware.h inclusion
      ASoC: imx-ssi: remove unneeded mach/hardware.h inclusion
      usb: ehci-mxc: remove unneeded mach/hardware.h inclusion
      video: mx3fb: remove unneeded mach/hardware.h inclusion
      watchdog: imx2_wdt: remove unneeded mach/hardware.h inclusion
      i2c: imx: remove cpu_is_xxx by using platform_device_id
      mtd: mxc_nand: remove cpu_is_xxx by using platform_device_id
      rtc: mxc_rtc: remove cpu_is_xxx by using platform_device_id
      dma: imx-dma: use devm_kzalloc and devm_request_irq
      dma: imx-dma: retrieve MEM and IRQ from resources
      dma: imx-dma: remove cpu_is_xxx by using platform_device_id
      media: mx2_camera: remove cpu_is_xxx by using platform_device_id
      mmc: mxcmmc: remove cpu_is_xxx by using platform_device_id
      video: imxfb: remove cpu_is_xxx by using platform_device_id
      ARM: imx: move debug macros to include/debug
      ARM: imx: include hardware.h rather than mach/hardware.h
      ARM: imx: remove header file mach/irqs.h
      ARM: imx: call mxc_device_init() in soc specific function
      ARM: imx: enable multi-platform build

 .../devicetree/bindings/i2c/fsl-imx-i2c.txt        |    4 +-
 MAINTAINERS                                        |    1 -
 arch/arm/Kconfig                                   |   15 +--
 arch/arm/Kconfig.debug                             |    8 ++
 arch/arm/Makefile                                  |    1 -
 arch/arm/boot/dts/imx27.dtsi                       |    4 +-
 arch/arm/boot/dts/imx51.dtsi                       |    4 +-
 arch/arm/boot/dts/imx53.dtsi                       |    6 +-
 arch/arm/boot/dts/imx6q.dtsi                       |    6 +-
 arch/arm/configs/imx_v4_v5_defconfig               |    5 +-
 arch/arm/configs/imx_v6_v7_defconfig               |    3 +-
 .../mach/debug-macro.S => include/debug/imx.S}     |   33 +++--
 arch/arm/{plat-mxc => mach-imx}/3ds_debugboard.c   |    2 +-
 .../include/mach => mach-imx}/3ds_debugboard.h     |    0
 arch/arm/mach-imx/Kconfig                          |   89 ++++++++++++-
 arch/arm/mach-imx/Makefile                         |   22 ++++
 arch/arm/{plat-mxc => mach-imx}/avic.c             |    5 +-
 .../include/mach => mach-imx}/board-mx31lilly.h    |    0
 .../include/mach => mach-imx}/board-mx31lite.h     |    0
 .../include/mach => mach-imx}/board-mx31moboard.h  |    0
 .../include/mach => mach-imx}/board-pcm038.h       |    0
 arch/arm/mach-imx/clk-imx1.c                       |   17 +--
 arch/arm/mach-imx/clk-imx21.c                      |   18 +--
 arch/arm/mach-imx/clk-imx25.c                      |   26 ++--
 arch/arm/mach-imx/clk-imx27.c                      |   40 +++---
 arch/arm/mach-imx/clk-imx31.c                      |   21 ++-
 arch/arm/mach-imx/clk-imx35.c                      |   13 +-
 arch/arm/mach-imx/clk-imx51-imx53.c                |   15 +--
 arch/arm/mach-imx/clk-imx6q.c                      |    3 +-
 arch/arm/mach-imx/clk-pllv1.c                      |    4 +-
 .../{plat-mxc/include/mach => mach-imx}/common.h   |    1 +
 arch/arm/mach-imx/cpu-imx25.c                      |    5 +-
 arch/arm/mach-imx/cpu-imx27.c                      |    2 +-
 arch/arm/mach-imx/cpu-imx31.c                      |    7 +-
 arch/arm/mach-imx/cpu-imx35.c                      |    5 +-
 arch/arm/mach-imx/cpu-imx5.c                       |    3 +-
 arch/arm/{plat-mxc => mach-imx}/cpu.c              |    3 +-
 arch/arm/mach-imx/cpu_op-mx51.c                    |    3 +-
 arch/arm/{plat-mxc => mach-imx}/cpufreq.c          |    3 +-
 arch/arm/{plat-mxc => mach-imx}/cpuidle.c          |    0
 .../{plat-mxc/include/mach => mach-imx}/cpuidle.h  |    0
 arch/arm/mach-imx/devices-imx1.h                   |    3 +-
 arch/arm/mach-imx/devices-imx21.h                  |    3 +-
 arch/arm/mach-imx/devices-imx25.h                  |    3 +-
 arch/arm/mach-imx/devices-imx27.h                  |    3 +-
 arch/arm/mach-imx/devices-imx31.h                  |    3 +-
 arch/arm/mach-imx/devices-imx35.h                  |    3 +-
 arch/arm/mach-imx/devices-imx50.h                  |    3 +-
 arch/arm/mach-imx/devices-imx51.h                  |    3 +-
 arch/arm/{plat-mxc => mach-imx}/devices/Kconfig    |    0
 arch/arm/{plat-mxc => mach-imx}/devices/Makefile   |    2 +
 .../mach => mach-imx/devices}/devices-common.h     |    9 +-
 arch/arm/{plat-mxc => mach-imx/devices}/devices.c  |    4 +-
 .../devices/platform-ahci-imx.c                    |    5 +-
 .../{plat-mxc => mach-imx}/devices/platform-fec.c  |    5 +-
 .../devices/platform-flexcan.c                     |    4 +-
 .../devices/platform-fsl-usb2-udc.c                |    5 +-
 .../devices/platform-gpio-mxc.c                    |    2 +-
 .../devices/platform-gpio_keys.c                   |    5 +-
 .../devices/platform-imx-dma.c                     |   23 +++-
 .../devices/platform-imx-fb.c                      |   16 ++-
 .../devices/platform-imx-i2c.c                     |   32 ++---
 .../devices/platform-imx-keypad.c                  |    4 +-
 .../devices/platform-imx-ssi.c                     |    4 +-
 .../devices/platform-imx-uart.c                    |    4 +-
 .../devices/platform-imx2-wdt.c                    |    5 +-
 .../devices/platform-imx21-hcd.c                   |    4 +-
 .../devices/platform-imx27-coda.c                  |    4 +-
 .../devices/platform-imx_udc.c                     |    4 +-
 .../devices/platform-imxdi_rtc.c                   |    5 +-
 .../devices/platform-ipu-core.c                    |    5 +-
 .../devices/platform-mx1-camera.c                  |    4 +-
 .../devices/platform-mx2-camera.c                  |   16 ++-
 .../devices/platform-mxc-ehci.c                    |    5 +-
 .../devices/platform-mxc-mmc.c                     |   20 +--
 .../devices/platform-mxc_nand.c                    |   25 ++--
 .../devices/platform-mxc_pwm.c                     |    4 +-
 .../devices/platform-mxc_rnga.c                    |    4 +-
 .../devices/platform-mxc_rtc.c                     |   13 +-
 .../devices/platform-mxc_w1.c                      |    4 +-
 .../devices/platform-pata_imx.c                    |    4 +-
 .../devices/platform-sdhci-esdhc-imx.c             |    5 +-
 .../devices/platform-spi_imx.c                     |    4 +-
 arch/arm/mach-imx/ehci-imx25.c                     |    4 +-
 arch/arm/mach-imx/ehci-imx27.c                     |    4 +-
 arch/arm/mach-imx/ehci-imx31.c                     |    4 +-
 arch/arm/mach-imx/ehci-imx35.c                     |    4 +-
 arch/arm/mach-imx/ehci-imx5.c                      |    4 +-
 arch/arm/{plat-mxc => mach-imx}/epit.c             |    6 +-
 .../include/mach => mach-imx}/eukrea-baseboards.h  |    0
 arch/arm/mach-imx/eukrea_mbimx27-baseboard.c       |    7 +-
 arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c     |    8 +-
 arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c     |    7 +-
 arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c     |    7 +-
 .../{plat-mxc/include/mach => mach-imx}/hardware.h |   26 ++--
 arch/arm/mach-imx/hotplug.c                        |    3 +-
 arch/arm/{plat-mxc/include/mach => mach-imx}/iim.h |    0
 arch/arm/mach-imx/imx27-dt.c                       |   11 +-
 arch/arm/mach-imx/imx31-dt.c                       |    5 +-
 arch/arm/mach-imx/imx51-dt.c                       |    9 +-
 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h       |   10 --
 arch/arm/mach-imx/iomux-imx31.c                    |    5 +-
 .../include/mach => mach-imx}/iomux-mx1.h          |    2 +-
 .../include/mach => mach-imx}/iomux-mx21.h         |    4 +-
 .../include/mach => mach-imx}/iomux-mx25.h         |    2 +-
 .../include/mach => mach-imx}/iomux-mx27.h         |    4 +-
 .../include/mach => mach-imx}/iomux-mx2x.h         |    0
 .../include/mach => mach-imx}/iomux-mx3.h          |    0
 .../include/mach => mach-imx}/iomux-mx35.h         |    2 +-
 .../include/mach => mach-imx}/iomux-mx50.h         |    2 +-
 .../include/mach => mach-imx}/iomux-mx51.h         |    2 +-
 arch/arm/{plat-mxc => mach-imx}/iomux-v1.c         |    5 +-
 .../{plat-mxc/include/mach => mach-imx}/iomux-v1.h |    0
 arch/arm/{plat-mxc => mach-imx}/iomux-v3.c         |    5 +-
 .../{plat-mxc/include/mach => mach-imx}/iomux-v3.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/iram.h |    0
 arch/arm/{plat-mxc => mach-imx}/iram_alloc.c       |    3 +-
 arch/arm/{plat-mxc => mach-imx}/irq-common.c       |    0
 arch/arm/{plat-mxc => mach-imx}/irq-common.h       |    3 +
 arch/arm/mach-imx/lluart.c                         |    3 +-
 arch/arm/mach-imx/mach-apf9328.c                   |    7 +-
 arch/arm/mach-imx/mach-armadillo5x0.c              |    9 +-
 arch/arm/mach-imx/mach-bug.c                       |    7 +-
 arch/arm/mach-imx/mach-cpuimx27.c                  |   11 +-
 arch/arm/mach-imx/mach-cpuimx35.c                  |    9 +-
 arch/arm/mach-imx/mach-cpuimx51sd.c                |    9 +-
 arch/arm/mach-imx/mach-eukrea_cpuimx25.c           |   10 +-
 arch/arm/mach-imx/mach-imx27_visstrim_m10.c        |    6 +-
 arch/arm/mach-imx/mach-imx27ipcam.c                |    6 +-
 arch/arm/mach-imx/mach-imx27lite.c                 |    6 +-
 arch/arm/mach-imx/mach-imx53.c                     |   11 +-
 arch/arm/mach-imx/mach-imx6q.c                     |    6 +-
 arch/arm/mach-imx/mach-kzm_arm11_01.c              |    7 +-
 arch/arm/mach-imx/mach-mx1ads.c                    |    7 +-
 arch/arm/mach-imx/mach-mx21ads.c                   |    6 +-
 arch/arm/mach-imx/mach-mx25_3ds.c                  |    8 +-
 arch/arm/mach-imx/mach-mx27_3ds.c                  |   10 +-
 arch/arm/mach-imx/mach-mx27ads.c                   |    6 +-
 arch/arm/mach-imx/mach-mx31_3ds.c                  |   12 +-
 arch/arm/mach-imx/mach-mx31ads.c                   |    5 +-
 arch/arm/mach-imx/mach-mx31lilly.c                 |   11 +-
 arch/arm/mach-imx/mach-mx31lite.c                  |   11 +-
 arch/arm/mach-imx/mach-mx31moboard.c               |   14 +-
 arch/arm/mach-imx/mach-mx35_3ds.c                  |    8 +-
 arch/arm/mach-imx/mach-mx50_rdp.c                  |    7 +-
 arch/arm/mach-imx/mach-mx51_3ds.c                  |    9 +-
 arch/arm/mach-imx/mach-mx51_babbage.c              |    7 +-
 arch/arm/mach-imx/mach-mxt_td60.c                  |    6 +-
 arch/arm/mach-imx/mach-pca100.c                    |    8 +-
 arch/arm/mach-imx/mach-pcm037.c                    |    8 +-
 arch/arm/mach-imx/mach-pcm037_eet.c                |    5 +-
 arch/arm/mach-imx/mach-pcm038.c                    |   13 +-
 arch/arm/mach-imx/mach-pcm043.c                    |    9 +-
 arch/arm/mach-imx/mach-qong.c                      |    6 +-
 arch/arm/mach-imx/mach-scb9328.c                   |    7 +-
 arch/arm/mach-imx/mach-vpr200.c                    |    7 +-
 arch/arm/mach-imx/mm-imx1.c                        |    9 +-
 arch/arm/mach-imx/mm-imx21.c                       |   14 +-
 arch/arm/mach-imx/mm-imx25.c                       |   12 +-
 arch/arm/mach-imx/mm-imx27.c                       |   14 +-
 arch/arm/mach-imx/mm-imx3.c                        |   13 +-
 arch/arm/mach-imx/mm-imx5.c                        |   12 +-
 arch/arm/{plat-mxc/include/mach => mach-imx}/mx1.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx21.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx25.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx27.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx2x.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx31.h |    0
 arch/arm/mach-imx/mx31lilly-db.c                   |    9 +-
 arch/arm/mach-imx/mx31lite-db.c                    |    9 +-
 arch/arm/mach-imx/mx31moboard-devboard.c           |    9 +-
 arch/arm/mach-imx/mx31moboard-marxbot.c            |    9 +-
 arch/arm/mach-imx/mx31moboard-smartbot.c           |   11 +-
 .../arm/{plat-mxc/include/mach => mach-imx}/mx35.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx3x.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx50.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx51.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx53.h |    0
 .../arm/{plat-mxc/include/mach => mach-imx}/mx6q.h |    0
 arch/arm/{plat-mxc/include/mach => mach-imx}/mxc.h |    0
 arch/arm/mach-imx/pcm970-baseboard.c               |    7 +-
 arch/arm/mach-imx/platsmp.c                        |    5 +-
 arch/arm/mach-imx/pm-imx27.c                       |    3 +-
 arch/arm/mach-imx/pm-imx3.c                        |    7 +-
 arch/arm/mach-imx/pm-imx5.c                        |    7 +-
 arch/arm/mach-imx/pm-imx6q.c                       |    5 +-
 arch/arm/{plat-mxc => mach-imx}/ssi-fiq-ksym.c     |    0
 arch/arm/{plat-mxc => mach-imx}/ssi-fiq.S          |    0
 arch/arm/{plat-mxc => mach-imx}/system.c           |    5 +-
 arch/arm/{plat-mxc => mach-imx}/time.c             |    5 +-
 arch/arm/{plat-mxc => mach-imx}/tzic.c             |    6 +-
 arch/arm/{plat-mxc => mach-imx}/ulpi.c             |    2 +-
 .../arm/{plat-mxc/include/mach => mach-imx}/ulpi.h |    0
 arch/arm/plat-mxc/Kconfig                          |   89 -------------
 arch/arm/plat-mxc/Makefile                         |   24 ----
 arch/arm/plat-mxc/include/mach/irqs.h              |   21 ---
 arch/arm/plat-mxc/include/mach/timex.h             |   22 ----
 arch/arm/plat-mxc/include/mach/uncompress.h        |  132 -------------------
 drivers/dma/imx-dma.c                              |  137 ++++++++++++--------
 drivers/dma/imx-sdma.c                             |    1 -
 drivers/dma/ipu/ipu_idmac.c                        |    3 +-
 drivers/dma/ipu/ipu_irq.c                          |    3 +-
 drivers/i2c/busses/i2c-imx.c                       |   40 +++++-
 drivers/media/platform/soc_camera/mx2_camera.c     |   95 ++++++++++----
 drivers/media/platform/soc_camera/mx3_camera.c     |    2 +-
 drivers/mmc/host/mxcmmc.c                          |   31 ++++-
 drivers/mtd/nand/mxc_nand.c                        |   96 +++++++++-----
 drivers/rtc/rtc-mxc.c                              |   34 ++++-
 drivers/usb/host/ehci-mxc.c                        |    1 -
 drivers/video/imxfb.c                              |   38 +++++-
 drivers/video/mx3fb.c                              |    3 +-
 drivers/watchdog/imx2_wdt.c                        |    1 -
 .../mach/ipu.h => include/linux/dma/ipu-dma.h      |    6 +-
 include/linux/platform_data/asoc-imx-ssi.h         |    2 +
 include/linux/platform_data/dma-imx.h              |    4 +-
 sound/soc/fsl/imx-pcm-fiq.c                        |    1 -
 sound/soc/fsl/imx-ssi.c                            |    1 -
 217 files changed, 1083 insertions(+), 1012 deletions(-)
 rename arch/arm/{plat-mxc/include/mach/debug-macro.S => include/debug/imx.S} (59%)
 rename arch/arm/{plat-mxc => mach-imx}/3ds_debugboard.c (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/3ds_debugboard.h (100%)
 rename arch/arm/{plat-mxc => mach-imx}/avic.c (98%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31lilly.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31lite.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-mx31moboard.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/board-pcm038.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/common.h (99%)
 rename arch/arm/{plat-mxc => mach-imx}/cpu.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/cpufreq.c (99%)
 rename arch/arm/{plat-mxc => mach-imx}/cpuidle.c (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/cpuidle.h (100%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/Kconfig (100%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/Makefile (98%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx/devices}/devices-common.h (97%)
 rename arch/arm/{plat-mxc => mach-imx/devices}/devices.c (92%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-ahci-imx.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-fec.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-flexcan.c (96%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-fsl-usb2-udc.c (96%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-gpio-mxc.c (96%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-gpio_keys.c (94%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-dma.c (63%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-fb.c (79%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-i2c.c (76%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-keypad.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-ssi.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx-uart.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx2-wdt.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx21-hcd.c (94%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx27-coda.c (93%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imx_udc.c (96%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-imxdi_rtc.c (94%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-ipu-core.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mx1-camera.c (94%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mx2-camera.c (83%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc-ehci.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc-mmc.c (76%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_nand.c (74%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_pwm.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_rnga.c (95%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_rtc.c (77%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-mxc_w1.c (95%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-pata_imx.c (96%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-sdhci-esdhc-imx.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/devices/platform-spi_imx.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/epit.c (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/eukrea-baseboards.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/hardware.h (94%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iim.h (100%)
 delete mode 100644 arch/arm/mach-imx/include/mach/dma-mx1-mx2.h
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx1.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx21.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx25.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx27.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx2x.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx3.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx35.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx50.h (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-mx51.h (99%)
 rename arch/arm/{plat-mxc => mach-imx}/iomux-v1.c (98%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-v1.h (100%)
 rename arch/arm/{plat-mxc => mach-imx}/iomux-v3.c (97%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iomux-v3.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/iram.h (100%)
 rename arch/arm/{plat-mxc => mach-imx}/iram_alloc.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/irq-common.c (100%)
 rename arch/arm/{plat-mxc => mach-imx}/irq-common.h (94%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx1.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx21.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx25.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx27.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx2x.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx31.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx35.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx3x.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx50.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx51.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx53.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mx6q.h (100%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/mxc.h (100%)
 rename arch/arm/{plat-mxc => mach-imx}/ssi-fiq-ksym.c (100%)
 rename arch/arm/{plat-mxc => mach-imx}/ssi-fiq.S (100%)
 rename arch/arm/{plat-mxc => mach-imx}/system.c (97%)
 rename arch/arm/{plat-mxc => mach-imx}/time.c (99%)
 rename arch/arm/{plat-mxc => mach-imx}/tzic.c (98%)
 rename arch/arm/{plat-mxc => mach-imx}/ulpi.c (99%)
 rename arch/arm/{plat-mxc/include/mach => mach-imx}/ulpi.h (100%)
 delete mode 100644 arch/arm/plat-mxc/Kconfig
 delete mode 100644 arch/arm/plat-mxc/Makefile
 delete mode 100644 arch/arm/plat-mxc/include/mach/irqs.h
 delete mode 100644 arch/arm/plat-mxc/include/mach/timex.h
 delete mode 100644 arch/arm/plat-mxc/include/mach/uncompress.h
 rename arch/arm/plat-mxc/include/mach/ipu.h => include/linux/dma/ipu-dma.h (97%)

^ permalink raw reply

* [PATCH] ARM: imx: enable cpufreq for imx6q
From: Shawn Guo @ 2012-10-15  3:29 UTC (permalink / raw)
  To: linux-arm-kernel

It enables cpufreq support for imx6q with generic cpufreq-cpu0 driver.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/boot/dts/imx6q.dtsi  |   10 +++++++++-
 arch/arm/mach-imx/Kconfig     |    3 +++
 arch/arm/mach-imx/clk-imx6q.c |    1 +
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 255f56b..1565aea 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -36,6 +36,14 @@
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 			next-level-cache = <&L2>;
+			operating-points = <
+				/* kHz    uV */
+				792000  1100000
+				396000  950000
+				198000  850000
+			>;
+			clock-latency = <61036>; /* two CLK32 periods */
+			cpu0-supply = <&reg_cpu>;
 		};
 
 		cpu at 1 {
@@ -447,7 +455,7 @@
 					anatop-max-voltage = <2750000>;
 				};
 
-				regulator-vddcore at 140 {
+				reg_cpu: regulator-vddcore at 140 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "cpu";
 					regulator-min-microvolt = <725000>;
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 017296f..e1f78f5 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -829,6 +829,8 @@ config	SOC_IMX53
 
 config SOC_IMX6Q
 	bool "i.MX6 Quad support"
+	select ARCH_HAS_CPUFREQ
+	select ARCH_HAS_OPP
 	select ARM_CPU_SUSPEND if PM
 	select ARM_GIC
 	select COMMON_CLK
@@ -842,6 +844,7 @@ config SOC_IMX6Q
 	select MFD_SYSCON
 	select PINCTRL
 	select PINCTRL_IMX6Q
+	select PM_OPP if PM
 
 	help
 	  This enables support for Freescale i.MX6 Quad processor.
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index e5a82bb..5f9f591 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -406,6 +406,7 @@ int __init mx6q_clocks_init(void)
 	clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
 	clk_register_clkdev(clk[ahb], "ahb", NULL);
 	clk_register_clkdev(clk[cko1], "cko1", NULL);
+	clk_register_clkdev(clk[arm], NULL, "cpu0");
 
 	/*
 	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH V2 2/3] dmaengine: dw_dmac: Enhance device tree support
From: Viresh Kumar @ 2012-10-15  3:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350053897.10584.172.camel@smile>

On 12 October 2012 20:28, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>> +     if (last_dw) {
>> +             if ((last_bus_id == param) && (last_dw == dw))
>> +                     return false;
>> +     }
> Just came to my mind.
> dw can't be NULL, can't it?
> Then
> if (last_dw) {
> ...
> }
> is unneeded.

Fixup for this:

diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index d72c26f..764c159 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -1196,11 +1196,8 @@ bool dw_dma_generic_filter(struct dma_chan
*chan, void *param)
         * failure. If dw and param are same, i.e. trying on same dw with
         * different channel, return false.
         */
-       if (last_dw) {
-               if ((last_bus_id == param) && (last_dw == dw))
-                       return false;
-       }
-
+       if ((last_dw == dw) && (last_bus_id == param))
+               return false;
        /*
         * Return true:
         * - If dw_dma's platform data is not filled with slave info, then all

^ permalink raw reply related

* [PATCH V2 3/3] ARM: SPEAr13xx: Pass DW DMAC platform data from DT
From: Viresh Kumar @ 2012-10-15  3:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121014100130.GM12801@game.jcrosoft.org>

On 14 October 2012 15:31, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
> On 19:40 Sat 13 Oct     , Viresh Kumar wrote:
>> On 13 October 2012 19:38, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> > On 13 October 2012 17:52, Jean-Christophe PLAGNIOL-VILLARD
>> > <plagnioj@jcrosoft.com> wrote:
>> >> On 14:18 Sat 13 Oct     , Viresh Kumar wrote:
>> >>>    On Oct 13, 2012 12:16 PM, "Jean-Christophe PLAGNIOL-VILLARD"
>> >>>    <plagnioj@jcrosoft.com> wrote:
>> >>>    >
>> >>>    > On 22:42 Fri 12 Oct     , Viresh Kumar wrote:
>> >>>    > > On 12 October 2012 21:51, Jean-Christophe PLAGNIOL-VILLARD
>> >>>    > > <plagnioj@jcrosoft.com> wrote:
>> >>>    > > >> >> +     OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL,
>> >>>    "cf"),
>> >>>    > > >> > ?/
>> >>>    > > >>
>> >>>    > > >> Sorry. can't get it :(
>> >>>    > > > what is the "cf" as paltfrom data
>> >>>    > >
>> >>>    > > This is dma bus_id string, which matches with what is passed from dtb.
>> >>>    > so pass if via dtb too
>> >>>
>> >>>    Yes. Already passed in 13xx.dtsi.
>>
>> Probably some confusion here. What i meant to say here is, dmac's
>> DT slave info has a node for cf and cf driver expects this string to come
>> via platform data currently.
>
> so use a phandle to connect them

The purpose of this patchset wasn't to fix how CF driver sends its filter
routine and its parameter. CF driver would be fixed later by ST guys.

--
viresh

^ permalink raw reply

* [PATCH] i2c: i2c-gpio: fix issue when DT node greater than 1
From: Bo Shen @ 2012-10-15  2:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5074E349.30605@atmel.com>

Hi Jean Delvare,

On 10/10/2012 10:54, Bo Shen wrote:
>
> Hi Jean Delvare,
>
> On 9/19/2012 23:54, Jean Delvare wrote:
>> On Wed, 19 Sep 2012 09:28:04 -0600, Stephen Warren wrote:
>>> On 09/18/2012 07:15 PM, Bo Shen wrote:
>>>> I add the debug info, and it give the following error without this
>>>> patch.
>>>>
>>>> --<8----------------------------------
>>>> adap->name = i2c-gpio-1
>>>> i2c-gpio i2c.2: using pins 30 (SDA) and 31 (SCL)
>>>> adap->name = i2c-gpio-1
>>>> i2c-gpio: probe of i2c.3 failed with error -16
>>>> -->8----------------------------------
>>>>
>>>> With this patch, it successfully registered.
>>>> --<8----------------------------------
>>>> adap->name = i2c-gpio0
>>>> i2c-gpio i2c.2: using pins 30 (SDA) and 31 (SCL)
>>>> adap->name = i2c-gpio1
>>>> i2c-gpio i2c.3: using pins 90 (SDA) and 91 (SCL)
>>>> -->8----------------------------------
>>>
>>> Yes, that explains why the registration fails, but not why this patch is
>>> the correct solution to the problem.
>>>
>>> The problematic code appears to be:
>>>
>>> snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
>>>
>>> Instead, I think that should be something more like:
>>>
>>> adap->name = dev_name(&pdev->dev);
>>
>> strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name))
 >> if anything, as adap->name is a buffer, not a pointer.
>
> I am sorry for late. I have tested with DT, it works.
>
> Please send this patch to fix the issue.
> Thanks.

Ping?

Will you send this patch? Or, I send this patch and add your S.O.B, 
which do you prefer?

BRs,
Bo Shen

>>
>>> or perhaps:
>>>
>>> if (pdev->dev.of_node)
>>>    /* named will be based on DT node name */
>>>    adap->name = dev_name(&pdev->dev);
>>> else
>>>    snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
>>>
>>> ?
>>
>

^ permalink raw reply

* [PATCH] ARM: dts: imx6q: enable snvs lp rtc
From: Shawn Guo @ 2012-10-15  2:57 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/boot/dts/imx6q.dtsi |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 663fb86..255f56b 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -505,8 +505,16 @@
 			};
 
 			snvs at 020cc000 {
-				reg = <0x020cc000 0x4000>;
-				interrupts = <0 19 0x04 0 20 0x04>;
+				compatible = "fsl,sec-v4.0-mon", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x020cc000 0x4000>;
+
+				snvs-rtc-lp at 34 {
+					compatible = "fsl,sec-v4.0-mon-rtc-lp";
+					reg = <0x34 0x58>;
+					interrupts = <0 19 0x04 0 20 0x04>;
+				};
 			};
 
 			epit at 020d0000 { /* EPIT1 */
-- 
1.7.9.5

^ permalink raw reply related

* dts: question about how to configure PIO used as i2c irq
From: Bo Shen @ 2012-10-15  2:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi All,
   When moving atmel qt1070 linux driver with DT support. The atmel 
qt1070 is an I2C device. I meet the following questions.

   The qt1070 DT node
   --<--------------
   qt1070: keyboard@1b {
         compatible = "atmel,qt1070";
         reg = <0x1b>;
         interrupt-parent = <&pioA>;
         interrupts = <7 0x0>;
   };
   -->--------------

   DT will parse this node and map irq, the i2c_client->irq. This can be 
used directly in atmel qt1070 driver. However, the PIO which used as irq 
need configure as a PIO input. Now, we can not use irq_to_gpio() 
function to convert irq to gpio. So, if we can not configure this gpio.

   If we configure the pio in board-dt.c, I think this is not a good 
place. For example, if the kernel image support multiplatform, while on 
these platform, using different pio for qt1070, so this will cause only 
one platform can use qt1070.

   So, for this question, how should I solve it? Would you please give 
me some advice?

^ permalink raw reply

* [PATCH] ARM: vfp: fix save and restore when running on pre-VFPv3 and CONFIG_VFPv3 set
From: Mans Rullgard @ 2012-10-15  2:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210150157400.16624@utopia.booyaka.com>

On 15 October 2012 02:58, Paul Walmsley <paul@pwsan.com> wrote:
>
> Fix by implementing a request from Russell King to add a new HWCAP
> flag that affirmatively indicates the presence of the d16-d31
> registers:

[...]

> diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
> index f254f65..b1555d0 100644
> --- a/arch/arm/include/uapi/asm/hwcap.h
> +++ b/arch/arm/include/uapi/asm/hwcap.h
> @@ -18,11 +18,12 @@
>  #define HWCAP_THUMBEE  (1 << 11)
>  #define HWCAP_NEON     (1 << 12)
>  #define HWCAP_VFPv3    (1 << 13)
> -#define HWCAP_VFPv3D16 (1 << 14)
> +#define HWCAP_VFPv3D16 (1 << 14)       /* also set for VFPv4-D16 */
>  #define HWCAP_TLS      (1 << 15)
>  #define HWCAP_VFPv4    (1 << 16)
>  #define HWCAP_IDIVA    (1 << 17)
>  #define HWCAP_IDIVT    (1 << 18)
> +#define HWCAP_VFPD16   (1 << 19)       /* set if VFP has 32 regs (not 16) */
>  #define HWCAP_IDIV     (HWCAP_IDIVA | HWCAP_IDIVT)

Please consider calling the new flag VFPD32 or so instead.  The D16 suffix
usually signifies an implementation with 16 registers, i.e. the opposite of
what this flag does.  Using the same tag to mean both things depending on
whether there's a 'v3' before it is nothing but confusing.

-- 
Mans Rullgard / mru

^ permalink raw reply

* [PATCH v2] i2c: change the id to let the i2c-gpio work
From: Bo Shen @ 2012-10-15  2:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGhQ9VxRGQ8JAygxJreNDJY=tJ67yt2CM9NHvW3VyhjxooXuig@mail.gmail.com>

Hi Joachim Eastwood,

On 10/13/2012 1:42, Joachim Eastwood wrote:
> Hi Bo Shen,
>
> On Fri, Oct 12, 2012 at 11:42 AM, Bo Shen <voice.shen@atmel.com> wrote:
>> The i2c-gpio driver will turn the platform device ID to busnum.
>> When using platfrom device ID as -1, it means dynamically assigned
>> the busnum. When writing code, we need to make sure the busnum,
>> and call i2c_register_board_info(int busnum, ...) to register device
>> if using -1, we do not know the value of busnum.
>>
>> In order to solve this issue, set the platform device ID as a fix number
>> Here using 0 to match the busnum used in i2c_regsiter_board_info().
>
> I have been bitten by this myself on RM9200.
>
>> Signed-off-by: Bo Shen <voice.shen@atmel.com>
>> ---
>> Change since v1
>>    Make the commit message more clear
>> ---
>>   arch/arm/mach-at91/at91sam9260_devices.c |    2 +-
>
> This pattern exist in at91rm9200_devices.c, at91sam9261_devices.c,
> at91sam9263_devices.c and at91sam9rl_devices.c you might want to fix
> them as well.

Thanks for your information.
After I test these boards, I will send patches to fix them, while not in 
this patch.

>
> I assume we have the same problem if CONFIG_I2C_AT91 is set?
> See further down in at91sam9260_devices.c we have another:  ".id = -1,"

Maybe Nikolaus Voss will deal with this case.

>
> regards
> Joachim Eastwood
>
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
>> index 0f24cfb..805ef95 100644
>> --- a/arch/arm/mach-at91/at91sam9260_devices.c
>> +++ b/arch/arm/mach-at91/at91sam9260_devices.c
>> @@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
>>
>>   static struct platform_device at91sam9260_twi_device = {
>>          .name                   = "i2c-gpio",
>> -       .id                     = -1,
>> +       .id                     = 0,
>>          .dev.platform_data      = &pdata,
>>   };
>>
>> --
>> 1.7.9.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH] ARM: vfp: fix save and restore when running on pre-VFPv3 and CONFIG_VFPv3 set
From: Paul Walmsley @ 2012-10-15  1:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121013133654.GU28061@n2100.arm.linux.org.uk>


After commit 846a136881b8f73c1f74250bf6acfaa309cab1f2 ("ARM: vfp: fix
saving d16-d31 vfp registers on v6+ kernels"), the OMAP 2430SDP board
started crashing during boot with omap2plus_defconfig:

[    3.875122] mmcblk0: mmc0:e624 SD04G 3.69 GiB
[    3.915954]  mmcblk0: p1
[    4.086639] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM
[    4.093719] Modules linked in:
[    4.096954] CPU: 0    Not tainted  (3.6.0-02232-g759e00b #570)
[    4.103149] PC is at vfp_reload_hw+0x1c/0x44
[    4.107666] LR is at __und_usr_fault_32+0x0/0x8

It turns out that the context save/restore fix unmasked a latent bug
in commit 5aaf254409f8d58229107b59507a8235b715a960 ("ARM: 6203/1: Make
VFPv3 usable on ARMv6").  When CONFIG_VFPv3 is set, but the kernel is
booted on a pre-VFPv3 core, the code attempts to save and restore the
d16-d31 VFP registers.  These are only present on non-D16 VFPv3+, so
this results in an undefined instruction exception.  The code didn't
crash before commit 846a136 because the save and restore code was
only touching d0-d15, present on all VFP.

Fix by implementing a request from Russell King to add a new HWCAP
flag that affirmatively indicates the presence of the d16-d31
registers:

   http://marc.info/?l=linux-arm-kernel&m=135013547905283&w=2

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Martin <dave.martin@linaro.org>
Cc: M?ns Rullg?rd <mans.rullgard@linaro.org>
---
Applies on v3.7-rc1.

 arch/arm/include/asm/vfpmacros.h  |   12 ++++++------
 arch/arm/include/uapi/asm/hwcap.h |    3 ++-
 arch/arm/vfp/vfpmodule.c          |    9 ++++++---
 3 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h
index 6a6f1e4..77f40ea 100644
--- a/arch/arm/include/asm/vfpmacros.h
+++ b/arch/arm/include/asm/vfpmacros.h
@@ -27,9 +27,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
-	tst	\tmp, #HWCAP_VFPv3D16
-	ldceql	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
-	addne	\base, \base, #32*4		    @ step over unused register space
+	tst	\tmp, #HWCAP_VFPD16
+	ldcnel	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
+	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
@@ -51,9 +51,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
-	tst	\tmp, #HWCAP_VFPv3D16
-	stceql	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
-	addne	\base, \base, #32*4		    @ step over unused register space
+	tst	\tmp, #HWCAP_VFPD16
+	stcnel	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
+	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index f254f65..b1555d0 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -18,11 +18,12 @@
 #define HWCAP_THUMBEE	(1 << 11)
 #define HWCAP_NEON	(1 << 12)
 #define HWCAP_VFPv3	(1 << 13)
-#define HWCAP_VFPv3D16	(1 << 14)
+#define HWCAP_VFPv3D16	(1 << 14)	/* also set for VFPv4-D16 */
 #define HWCAP_TLS	(1 << 15)
 #define HWCAP_VFPv4	(1 << 16)
 #define HWCAP_IDIVA	(1 << 17)
 #define HWCAP_IDIVT	(1 << 18)
+#define HWCAP_VFPD16	(1 << 19)	/* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV	(HWCAP_IDIVA | HWCAP_IDIVT)
 
 
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index c834b32..f3e611c 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -701,11 +701,14 @@ static int __init vfp_init(void)
 			elf_hwcap |= HWCAP_VFPv3;
 
 			/*
-			 * Check for VFPv3 D16. CPUs in this configuration
-			 * only have 16 x 64bit registers.
+			 * Check for VFPv3 D16 and VFPv4 D16.  CPUs in
+			 * this configuration only have 16 x 64bit
+			 * registers.
 			 */
 			if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
-				elf_hwcap |= HWCAP_VFPv3D16;
+				elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
+			else
+				elf_hwcap |= HWCAP_VFPD16;
 		}
 #endif
 		/*
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] i2c: omap: revert "i2c: omap: switch to threaded IRQ support"
From: Paul Walmsley @ 2012-10-15  1:51 UTC (permalink / raw)
  To: linux-arm-kernel


Commit 3b2f8f82dad7d1f79cdc8fc05bd1c94baf109bde ("i2c: omap: switch to
threaded IRQ support") causes communication with I2C devices to fail
after system suspend/resume on all OMAP3 devices:

...
[   40.228576] PM: noirq resume of devices complete after 3.723 msecs
[   40.233184] PM: early resume of devices complete after 3.173 msecs
[   40.242736] [sched_delayed] sched: RT throttling activated
[   41.235046] omap_i2c omap_i2c.1: controller timed out
[   41.235351] twl: i2c_read failed to transfer all messages
[   41.235382] omap_hsmmc omap_hsmmc.0: could not set regulator OCR (-110)
[   41.396453] mmc0: error -110 during resume (card was removed?)
[   42.391754] omap_i2c omap_i2c.1: controller timed out
[   42.391876] twl: i2c_write failed to transfer all messages
[   42.391906] twl_rtc: Could not write TWLregister F - error -110
[   43.391326] omap_i2c omap_i2c.1: controller timed out
[   43.391479] twl: i2c_read failed to transfer all messages
[   43.391510] twl_rtc: Could not read TWLregister D - error -110
[   43.391540] twl_rtc twl_rtc: twl_rtc_read_time: reading CTRL_REG, error -110
[   43.392364] PM: resume of devices complete after 3158.935 msecs

When the root filesystem is on MMC, as in the above example, the
card's voltage regulator is not re-enabled and the filesystem becomes
inaccessible after resume.

Fix by reverting the conversion to a threaded IRQ handler.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Felipe Balbi <balbi@ti.com>
Cc: Shubhrajyoti D <shubhrajyoti@ti.com>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: Ben Dooks <ben-linux@fluff.org>
---
 drivers/i2c/busses/i2c-omap.c |   44 +++++++----------------------------------
 1 file changed, 7 insertions(+), 37 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index db31eae..e001c2a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -180,7 +180,6 @@ enum {
 #define I2C_OMAP_ERRATA_I462		(1 << 1)
 
 struct omap_i2c_dev {
-	spinlock_t		lock;		/* IRQ synchronization */
 	struct device		*dev;
 	void __iomem		*base;		/* virtual */
 	int			irq;
@@ -865,35 +864,13 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
 }
 
 static irqreturn_t
-omap_i2c_isr(int irq, void *dev_id)
+omap_i2c_isr(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
-	irqreturn_t ret = IRQ_HANDLED;
-	u16 mask;
-	u16 stat;
-
-	spin_lock(&dev->lock);
-	mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-	stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
-
-	if (stat & mask)
-		ret = IRQ_WAKE_THREAD;
-
-	spin_unlock(&dev->lock);
-
-	return ret;
-}
-
-static irqreturn_t
-omap_i2c_isr_thread(int this_irq, void *dev_id)
-{
-	struct omap_i2c_dev *dev = dev_id;
-	unsigned long flags;
 	u16 bits;
 	u16 stat;
 	int err = 0, count = 0;
 
-	spin_lock_irqsave(&dev->lock, flags);
 	do {
 		bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
 		stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
@@ -907,7 +884,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
 
 		if (!stat) {
 			/* my work here is done */
-			goto out;
+			return IRQ_HANDLED;
 		}
 
 		dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
@@ -1016,8 +993,6 @@ omap_i2c_isr_thread(int this_irq, void *dev_id)
 	omap_i2c_complete_cmd(dev, err);
 
 out:
-	spin_unlock_irqrestore(&dev->lock, flags);
-
 	return IRQ_HANDLED;
 }
 
@@ -1062,6 +1037,7 @@ omap_i2c_probe(struct platform_device *pdev)
 		pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 	const struct of_device_id *match;
+	irq_handler_t isr;
 	int irq;
 	int r;
 
@@ -1110,8 +1086,6 @@ omap_i2c_probe(struct platform_device *pdev)
 	dev->dev = &pdev->dev;
 	dev->irq = irq;
 
-	spin_lock_init(&dev->lock);
-
 	platform_set_drvdata(pdev, dev);
 	init_completion(&dev->cmd_complete);
 
@@ -1166,14 +1140,10 @@ omap_i2c_probe(struct platform_device *pdev)
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	if (dev->rev < OMAP_I2C_OMAP1_REV_2)
-		r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
-				IRQF_NO_SUSPEND, pdev->name, dev);
-	else
-		r = devm_request_threaded_irq(&pdev->dev, dev->irq,
-				omap_i2c_isr, omap_i2c_isr_thread,
-				IRQF_NO_SUSPEND | IRQF_ONESHOT,
-				pdev->name, dev);
+	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
+								   omap_i2c_isr;
+	r = devm_request_irq(&pdev->dev, dev->irq, isr, IRQF_NO_SUSPEND,
+			     pdev->name, dev);
 
 	if (r) {
 		dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] ARM: imx6q: remove imx_src_prepare_restart() call
From: Shawn Guo @ 2012-10-15  1:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121013180512.24ac6c59@wker>

On Sat, Oct 13, 2012 at 06:05:12PM +0200, Anatolij Gustschin wrote:
> Hi Shawn,
> 
> On Fri, 17 Aug 2012 13:11:56 +0800
> Shawn Guo <shawn.guo@linaro.org> wrote:
> 
> > Currently, imx_src_prepare_restart which is called by imx6q_restart
> > assumes that cpu0 must be the running cpu, so it disables all secondary
> > cpus.  However this is not the case, the restart routine could possibly
> > running on cpu1 or any other secondary cores.  In that case, disabling
> > the cpu that runs restart routine will hang up system.
> > 
> > Also it turns out that everything that is done by imx_src_prepare_restart
> > is not really necessary, because the watchdog reset will have those
> > registers reset properly.  So let's remove the imx_src_prepare_restart
> > call completely.
> 
> What is the fate of this patch?
> 
Discarded.

Further testing suggests that imx_src_prepare_restart call is needed,
otherwise secondary cores will fail to come online, though system
reboot works with core0.

The issue has been solved at kernel core level by the following patch.

  a985941 kernel/sys.c: call disable_nonboot_cpus() in kernel_restart()

Shawn

^ permalink raw reply

* [PULL REQUEST] ARM: vt8500: Cleanup for 3.8
From: Tony Prisk @ 2012-10-15  1:19 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit
ddffeb8c4d0331609ef2581d84de4d763607bd37:

  Linux 3.7-rc1 (2012-10-14 14:41:04 -0700)

are available in the git repository at:

  git://server.prisktech.co.nz/git/linuxwmt.git/ tags/cleanup-for-3.8

for you to fetch changes up to 83cc76909622a4ee21f750148e779104d0606e9f:

  vt8500: Fix header in mach-vt8500/timer.c (2012-10-15 14:04:41 +1300)

----------------------------------------------------------------
Cleanup for 3.8

Removes a few unused headers from include/mach
Removes unused arm/boot/compressed/head-vt8500.S
Fixes header text in mach-vt8500/timer.c

Signed-off-by: Tony Prisk <linux@prisktech.co.nz>

----------------------------------------------------------------
Tony Prisk (3):
      vt8500: Remove unused headers from include/mach/
      vt8500: Remove arm/boot/compressed/head-vt8500.S
      vt8500: Fix header in mach-vt8500/timer.c

 arch/arm/boot/compressed/Makefile            |    4 ---
 arch/arm/boot/compressed/head-vt8500.S       |   46
--------------------------
 arch/arm/mach-vt8500/include/mach/hardware.h |   12 -------
 arch/arm/mach-vt8500/include/mach/i8042.h    |   18 ----------
 arch/arm/mach-vt8500/include/mach/restart.h  |   17 ----------
 arch/arm/mach-vt8500/timer.c                 |    2 +-
 arch/arm/mach-vt8500/vt8500.c                |    2 --
 7 files changed, 1 insertion(+), 100 deletions(-)
 delete mode 100644 arch/arm/boot/compressed/head-vt8500.S
 delete mode 100644 arch/arm/mach-vt8500/include/mach/hardware.h
 delete mode 100644 arch/arm/mach-vt8500/include/mach/i8042.h
 delete mode 100644 arch/arm/mach-vt8500/include/mach/restart.h

^ permalink raw reply

* [git pull] signals pile 3
From: Russell King - ARM Linux @ 2012-10-14 23:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507B3F2C.1090500@gmail.com>

On Mon, Oct 15, 2012 at 12:39:40AM +0200, Daniel Mack wrote:
> Tested-by: Daniel Mack <zonque@gmail.com>
> 
> Many thanks for the very prompt response!

Thanks Daniel.

I've also tested this on my OMAP4430 board running in ARM mode, so that
still works - we've covered the possibilities between us here between
ARM mode and Thumb mode, so...

Linus, could you merge this patch please, thanks.

8<===
From: Russell King <rmk+kernel@arm.linux.org.uk>
Subject: [PATCH] ARM: fix oops on initial entry to userspace with Thumb2 kernels

Daniel Mack reports an oops at boot with the latest kernels:

[    4.896717] Internal error: Oops - undefined instruction: 0 [#1] SMP THUMB2
[    4.904034] Modules linked in:
[    4.907253] CPU: 0    Not tainted  (3.6.0-11057-g584df1d #145)
[    4.913372] PC is at cpsw_probe+0x45a/0x9ac
[    4.917760] LR is at trace_hardirqs_on_caller+0x8f/0xfc
[    4.923235] pc : [<c03493de>]    lr : [<c005e81f>]    psr: 60000113
[    4.923235] sp : cf055fb0  ip : 00000000  fp : 00000000
[    4.935246] r10: 00000000  r9 : 00000000  r8 : 00000000
[    4.940715] r7 : 00000000  r6 : 00000000  r5 : c0344555  r4 : 00000000
[    4.947548] r3 : cf057a40  r2 : 00000000  r1 : 00000001  r0 : 00000000
[    4.954383] Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM Segment user
[    4.961853] Control: 50c5387d  Table: 8f3f4019  DAC: 00000015
[    4.967868] Process init (pid: 1, stack limit = 0xcf054240)
[    4.973702] Stack: (0xcf055fb0 to 0xcf056000)
[    4.978269] 5fa0:                                     00000001 00000000 00000000 00000000
[    4.986836] 5fc0: cf055fb0 c000d1a8 00000000 00000000 00000000 00000000 00000000 00000000
[    4.995403] 5fe0: 00000000 be9b3f10 00000000 b6f6add0 00000010 00000000 aaaabfaf a8babbaa

The analysis of this is as follows.  In init/main.c, we issue:

	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

This creates a new thread, which falls through to the ret_from_fork
assembly, with r4 set NULL and r5 set to kernel_init.  You can see
this in your oops dump register set - r5 is 0xc0344555, which is the
address of kernel_init plus 1 which marks the function as Thumb code.

Now, let's look at this code a little closer - this is what the
disassembly looks like:

c000d180 <ret_from_fork>:
c000d180:       f03a fe08       bl      c0047d94 <schedule_tail>
c000d184:       2d00            cmp     r5, #0
c000d186:       bf1e            ittt    ne
c000d188:       4620            movne   r0, r4
c000d18a:       46fe            movne   lr, pc <-- XXXXXXX
c000d18c:       46af            movne   pc, r5
c000d18e:       46e9            mov     r9, sp
c000d190:       ea4f 3959       mov.w   r9, r9, lsr #13
c000d194:       ea4f 3949       mov.w   r9, r9, lsl #13
c000d198:       e7c8            b.n     c000d12c <ret_to_user>
c000d19a:       bf00            nop
c000d19c:       f3af 8000       nop.w

This code was introduced in 9fff2fa0db911 (arm: switch to saner
kernel_execve() semantics).  I have marked one instruction, and it's
the significant one - I'll come back to that later.

Eventually, having had a successful call to kernel_execve(), kernel_init()
returns zero.

In returning, it uses the value in 'lr' which was set by the instruction
I marked above.  Unfortunately, this causes lr to contain 0xc000d18e -
an even address.  This switches the ISA to ARM on return but with a non
word aligned PC value.

So, what do we end up executing?  Well, not the instructions above - yes
the opcodes, but they don't mean the same thing in ARM mode.  In ARM mode,
it looks like this instead:

c000d18c:       46e946af        strbtmi r4, [r9], pc, lsr #13
c000d190:       3959ea4f        ldmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
c000d194:       3949ea4f        stmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
c000d198:       bf00e7c8        svclt   0x0000e7c8
c000d19c:       8000f3af        andhi   pc, r0, pc, lsr #7
c000d1a0:       e88db092        stm     sp, {r1, r4, r7, ip, sp, pc}
c000d1a4:       46e81fff                        ; <UNDEFINED> instruction: 0x46e81fff
c000d1a8:       8a00f3ef        bhi     0xc004a16c
c000d1ac:       0a0cf08a        beq     0xc03493dc

I have included more above, because it's relevant.  The PSR flags which we
can see in the oops dump are nZCv, so Z and C are set.

All the above ARM instructions are not executed, except for two.  c000d1a0,
which has no writeback, and writes below the current stack pointer (and
that data is lost when we take the next exception.)  The other instruction
which is executed is c000d1ac, which takes us to... 0xc03493dc.  However,
remember that bit 1 of the PC got set.  So that makes the PC value
0xc03493de.

And that value is the value we find in the oops dump for PC.  What is the
instruction here when interpreted in ARM mode?

       0:       f71e150c                ; <UNDEFINED> instruction: 0xf71e150c

and there we have our undefined instruction (remember that the 'never'
condition code, 0xf, has been deprecated and is now always executed as it
is now being used for additional instructions.)

This path also nicely explains the state of the stack we see in the oops
dump too.

The above is a consistent and sane story for how we got to the oops dump,
which all stems from the instruction at 0xc000d18a being wrong.

Reported-by: Daniel Mack <zonque@gmail.com>
Tested-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/entry-common.S |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 417bac1..3471175 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -88,9 +88,9 @@ ENTRY(ret_from_fork)
 	bl	schedule_tail
 	cmp	r5, #0
 	movne	r0, r4
-	movne	lr, pc
+	adrne	lr, BSYM(1f)
 	movne	pc, r5
-	get_thread_info tsk
+1:	get_thread_info tsk
 	b	ret_slow_syscall
 ENDPROC(ret_from_fork)
 

^ permalink raw reply related

* [git pull] signals pile 3
From: Daniel Mack @ 2012-10-14 22:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121014222449.GN21164@n2100.arm.linux.org.uk>

On 15.10.2012 00:24, Russell King - ARM Linux wrote:
> Okay, here's the post-mortem diagnosis.
> 
> What's happening is as follows (I'm very certain of this.)
> 
> We come through the usual init, and issue (see init/main.c):
> 
> 	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
> 
> This creates a new thread, which falls through to the ret_from_fork
> assembly, with r4 set NULL and r5 set to kernel_init.  You can see
> this in your oops dump register set - r5 is 0xc0344555, which is the
> address of kernel_init plus 1 which marks the function as Thumb code.
> 
> Now, let's look at this code a little closer - this is what the
> disassembly looks like:
> 
> c000d180 <ret_from_fork>:
> c000d180:       f03a fe08       bl      c0047d94 <schedule_tail>
> c000d184:       2d00            cmp     r5, #0
> c000d186:       bf1e            ittt    ne
> c000d188:       4620            movne   r0, r4
> c000d18a:       46fe            movne   lr, pc <-- XXXXXXX
> c000d18c:       46af            movne   pc, r5
> c000d18e:       46e9            mov     r9, sp
> c000d190:       ea4f 3959       mov.w   r9, r9, lsr #13
> c000d194:       ea4f 3949       mov.w   r9, r9, lsl #13
> c000d198:       e7c8            b.n     c000d12c <ret_to_user>
> c000d19a:       bf00            nop
> c000d19c:       f3af 8000       nop.w
> 
> I have marked one instruction, and it's the significant one.
> 
> Eventually, having had a successful call to kernel_execve(), kernel_init()
> returns zero.
> 
> In returning, it uses the value in 'lr' which was set by the instruction
> I marked above.  Unfortunately, this causes lr to contain 0xc000d18e -
> an even address.  This switches the ISA to ARM on return but with a non
> word aligned PC value.
> 
> So, what do we end up executing?  Well, not the instructions above - yes
> the opcodes, but they don't mean the same thing in ARM mode.  In ARM mode,
> it looks like this instead:
> 
> c000d18c:       46e946af        strbtmi r4, [r9], pc, lsr #13
> c000d190:       3959ea4f        ldmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
> c000d194:       3949ea4f        stmdbcc r9, {r0, r1, r2, r3, r6, r9, fp, sp, lr, pc}^
> c000d198:       bf00e7c8        svclt   0x0000e7c8
> c000d19c:       8000f3af        andhi   pc, r0, pc, lsr #7
> c000d1a0:       e88db092        stm     sp, {r1, r4, r7, ip, sp, pc}
> c000d1a4:       46e81fff                        ; <UNDEFINED> instruction: 0x46e81fff
> c000d1a8:       8a00f3ef        bhi     0xc004a16c
> c000d1ac:       0a0cf08a        beq     0xc03493dc
> 
> I have included more above, because it's relevant.  The PSR flags which we
> can see in the oops dump are nZCv, so Z and C are set.
> 
> All the above ARM instructions are not executed, except for two.  c000d1a0,
> which has no writeback, and writes below the current stack pointer (and
> that data is lost when we take the next exception.)  The other instruction
> which is executed is c000d1ac, which takes us to... 0xc03493dc.  However,
> remember that bit 1 of the PC got set.  So that makes it 0xc03493de.
> 
> And that value is the value we find in the oops dump for PC.  What is the
> instruction here when interpreted in ARM mode?
> 
>        0:       f71e150c                ; <UNDEFINED> instruction: 0xf71e150c
> 
> and there we have our undefined instruction (remember that the 'never'
> condition code, 0xf, has been deprecated and is now always executed.)
> 
> So, what we have above is a consistent and sane story for how we ended up
> at such a strange place in the kernel with such an odd register dump - with
> no unanswered questions about what happened to get us there.
> 
> In light of this, I'm 100% certain that the patch below will fix the issue
> you're seeing - please test this and get back to me ASAP, thanks.

Quite impressive analysis :) And it seems you really spotted the reason
here, as your patch fixes the problem.

>  arch/arm/kernel/entry-common.S |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
> index 417bac1..3471175 100644
> --- a/arch/arm/kernel/entry-common.S
> +++ b/arch/arm/kernel/entry-common.S
> @@ -88,9 +88,9 @@ ENTRY(ret_from_fork)
>  	bl	schedule_tail
>  	cmp	r5, #0
>  	movne	r0, r4
> -	movne	lr, pc
> +	adrne	lr, BSYM(1f)
>  	movne	pc, r5
> -	get_thread_info tsk
> +1:	get_thread_info tsk
>  	b	ret_slow_syscall
>  ENDPROC(ret_from_fork)

Tested-by: Daniel Mack <zonque@gmail.com>

Many thanks for the very prompt response!


Daniel

^ 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