Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2 v2] plat-pxa: move PXA GPIO driver to GPIO subsystem
From: Linus Walleij @ 2011-09-27 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Linus Walleij <linus.walleij@linaro.org>

As per example from the other ARM boards, push the PXA
GPIO driver down to the GPIO subsystem so it can be consolidated.

Cc: Russell King <linux@arm.linux.org.uk>
Acked-by: Eric Miao <eric.y.miao@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/plat-pxa/Makefile |    1 -
 arch/arm/plat-pxa/gpio.c   |  336 --------------------------------------------
 drivers/gpio/Makefile      |    1 +
 drivers/gpio/gpio-pxa.c    |  336 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 337 insertions(+), 337 deletions(-)
 delete mode 100644 arch/arm/plat-pxa/gpio.c
 create mode 100644 drivers/gpio/gpio-pxa.c

diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile
index 3aca5ba..f302d04 100644
--- a/arch/arm/plat-pxa/Makefile
+++ b/arch/arm/plat-pxa/Makefile
@@ -4,7 +4,6 @@
 
 obj-y	:= dma.o
 
-obj-$(CONFIG_GENERIC_GPIO)	+= gpio.o
 obj-$(CONFIG_PXA3xx)		+= mfp.o
 obj-$(CONFIG_PXA95x)		+= mfp.o
 obj-$(CONFIG_ARCH_MMP)		+= mfp.o
diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c
deleted file mode 100644
index 5d6a86b..0000000
--- a/arch/arm/plat-pxa/gpio.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *  linux/arch/arm/plat-pxa/gpio.c
- *
- *  Generic PXA GPIO handling
- *
- *  Author:	Nicolas Pitre
- *  Created:	Jun 15, 2001
- *  Copyright:	MontaVista Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-#include <linux/slab.h>
-
-int pxa_last_gpio;
-
-struct pxa_gpio_chip {
-	struct gpio_chip chip;
-	void __iomem	*regbase;
-	char label[10];
-
-	unsigned long	irq_mask;
-	unsigned long	irq_edge_rise;
-	unsigned long	irq_edge_fall;
-
-#ifdef CONFIG_PM
-	unsigned long	saved_gplr;
-	unsigned long	saved_gpdr;
-	unsigned long	saved_grer;
-	unsigned long	saved_gfer;
-#endif
-};
-
-static DEFINE_SPINLOCK(gpio_lock);
-static struct pxa_gpio_chip *pxa_gpio_chips;
-
-#define for_each_gpio_chip(i, c)			\
-	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
-
-static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
-{
-	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
-}
-
-static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
-{
-	return &pxa_gpio_chips[gpio_to_bank(gpio)];
-}
-
-static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t value, mask = 1 << offset;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	value = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		value |= mask;
-	else
-		value &= ~mask;
-	__raw_writel(value, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_direction_output(struct gpio_chip *chip,
-				     unsigned offset, int value)
-{
-	void __iomem *base = gpio_chip_base(chip);
-	uint32_t tmp, mask = 1 << offset;
-	unsigned long flags;
-
-	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
-
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	tmp = __raw_readl(base + GPDR_OFFSET);
-	if (__gpio_is_inverted(chip->base + offset))
-		tmp &= ~mask;
-	else
-		tmp |= mask;
-	__raw_writel(tmp, base + GPDR_OFFSET);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return 0;
-}
-
-static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
-}
-
-static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	__raw_writel(1 << offset, gpio_chip_base(chip) +
-				(value ? GPSR_OFFSET : GPCR_OFFSET));
-}
-
-static int __init pxa_init_gpio_chip(int gpio_end)
-{
-	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
-	struct pxa_gpio_chip *chips;
-
-	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
-	if (chips == NULL) {
-		pr_err("%s: failed to allocate GPIO chips\n", __func__);
-		return -ENOMEM;
-	}
-
-	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
-		struct gpio_chip *c = &chips[i].chip;
-
-		sprintf(chips[i].label, "gpio-%d", i);
-		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
-
-		c->base  = gpio;
-		c->label = chips[i].label;
-
-		c->direction_input  = pxa_gpio_direction_input;
-		c->direction_output = pxa_gpio_direction_output;
-		c->get = pxa_gpio_get;
-		c->set = pxa_gpio_set;
-
-		/* number of GPIOs on last bank may be less than 32 */
-		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
-		gpiochip_add(c);
-	}
-	pxa_gpio_chips = chips;
-	return 0;
-}
-
-/* Update only those GRERx and GFERx edge detection register bits if those
- * bits are set in c->irq_mask
- */
-static inline void update_edge_detect(struct pxa_gpio_chip *c)
-{
-	uint32_t grer, gfer;
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
-	grer |= c->irq_edge_rise & c->irq_mask;
-	gfer |= c->irq_edge_fall & c->irq_mask;
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct pxa_gpio_chip *c;
-	int gpio = irq_to_gpio(d->irq);
-	unsigned long gpdr, mask = GPIO_bit(gpio);
-
-	c = gpio_to_pxachip(gpio);
-
-	if (type == IRQ_TYPE_PROBE) {
-		/* Don't mess with enabled GPIOs using preconfigured edges or
-		 * GPIOs set to alternate function or to output during probe
-		 */
-		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
-			return 0;
-
-		if (__gpio_is_occupied(gpio))
-			return 0;
-
-		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
-	}
-
-	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-
-	if (__gpio_is_inverted(gpio))
-		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
-	else
-		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
-
-	if (type & IRQ_TYPE_EDGE_RISING)
-		c->irq_edge_rise |= mask;
-	else
-		c->irq_edge_rise &= ~mask;
-
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		c->irq_edge_fall |= mask;
-	else
-		c->irq_edge_fall &= ~mask;
-
-	update_edge_detect(c);
-
-	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
-		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
-		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
-	return 0;
-}
-
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct pxa_gpio_chip *c;
-	int loop, gpio, gpio_base, n;
-	unsigned long gedr;
-
-	do {
-		loop = 0;
-		for_each_gpio_chip(gpio, c) {
-			gpio_base = c->chip.base;
-
-			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
-			gedr = gedr & c->irq_mask;
-			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
-
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
-				loop = 1;
-
-				generic_handle_irq(gpio_to_irq(gpio_base + n));
-				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
-			}
-		}
-	} while (loop);
-}
-
-static void pxa_ack_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
-}
-
-static void pxa_mask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-	uint32_t grer, gfer;
-
-	c->irq_mask &= ~GPIO_bit(gpio);
-
-	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
-	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
-	__raw_writel(grer, c->regbase + GRER_OFFSET);
-	__raw_writel(gfer, c->regbase + GFER_OFFSET);
-}
-
-static void pxa_unmask_muxed_gpio(struct irq_data *d)
-{
-	int gpio = irq_to_gpio(d->irq);
-	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
-
-	c->irq_mask |= GPIO_bit(gpio);
-	update_edge_detect(c);
-}
-
-static struct irq_chip pxa_muxed_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= pxa_ack_muxed_gpio,
-	.irq_mask	= pxa_mask_muxed_gpio,
-	.irq_unmask	= pxa_unmask_muxed_gpio,
-	.irq_set_type	= pxa_gpio_irq_type,
-};
-
-void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
-{
-	struct pxa_gpio_chip *c;
-	int gpio, irq;
-
-	pxa_last_gpio = end;
-
-	/* Initialize GPIO chips */
-	pxa_init_gpio_chip(end);
-
-	/* clear all GPIO edge detects */
-	for_each_gpio_chip(gpio, c) {
-		__raw_writel(0, c->regbase + GFER_OFFSET);
-		__raw_writel(0, c->regbase + GRER_OFFSET);
-		__raw_writel(~0,c->regbase + GEDR_OFFSET);
-	}
-
-	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
-		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
-					 handle_edge_irq);
-		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-	}
-
-	/* Install handler for GPIO>=2 edge detect interrupts */
-	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
-	pxa_muxed_gpio_chip.irq_set_wake = fn;
-}
-
-#ifdef CONFIG_PM
-static int pxa_gpio_suspend(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
-		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
-		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
-		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
-
-		/* Clear GPIO transition detect bits */
-		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
-	}
-	return 0;
-}
-
-static void pxa_gpio_resume(void)
-{
-	struct pxa_gpio_chip *c;
-	int gpio;
-
-	for_each_gpio_chip(gpio, c) {
-		/* restore level with set/clear */
-		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
-		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
-
-		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
-		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
-		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
-	}
-}
-#else
-#define pxa_gpio_suspend	NULL
-#define pxa_gpio_resume		NULL
-#endif
-
-struct syscore_ops pxa_gpio_syscore_ops = {
-	.suspend	= pxa_gpio_suspend,
-	.resume		= pxa_gpio_resume,
-};
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index a4c8ac9..828e9ab 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X)	+= gpio-pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= gpio-pcf857x.o
 obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o
 obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o
+obj-$(CONFIG_PLAT_PXA)		+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o
 obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_PLAT_SAMSUNG)	+= gpio-samsung.o
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
new file mode 100644
index 0000000..5d6a86b
--- /dev/null
+++ b/drivers/gpio/gpio-pxa.c
@@ -0,0 +1,336 @@
+/*
+ *  linux/arch/arm/plat-pxa/gpio.c
+ *
+ *  Generic PXA GPIO handling
+ *
+ *  Author:	Nicolas Pitre
+ *  Created:	Jun 15, 2001
+ *  Copyright:	MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+#include <linux/slab.h>
+
+int pxa_last_gpio;
+
+struct pxa_gpio_chip {
+	struct gpio_chip chip;
+	void __iomem	*regbase;
+	char label[10];
+
+	unsigned long	irq_mask;
+	unsigned long	irq_edge_rise;
+	unsigned long	irq_edge_fall;
+
+#ifdef CONFIG_PM
+	unsigned long	saved_gplr;
+	unsigned long	saved_gpdr;
+	unsigned long	saved_grer;
+	unsigned long	saved_gfer;
+#endif
+};
+
+static DEFINE_SPINLOCK(gpio_lock);
+static struct pxa_gpio_chip *pxa_gpio_chips;
+
+#define for_each_gpio_chip(i, c)			\
+	for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++)
+
+static inline void __iomem *gpio_chip_base(struct gpio_chip *c)
+{
+	return container_of(c, struct pxa_gpio_chip, chip)->regbase;
+}
+
+static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio)
+{
+	return &pxa_gpio_chips[gpio_to_bank(gpio)];
+}
+
+static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t value, mask = 1 << offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	value = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		value |= mask;
+	else
+		value &= ~mask;
+	__raw_writel(value, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_direction_output(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	void __iomem *base = gpio_chip_base(chip);
+	uint32_t tmp, mask = 1 << offset;
+	unsigned long flags;
+
+	__raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET));
+
+	spin_lock_irqsave(&gpio_lock, flags);
+
+	tmp = __raw_readl(base + GPDR_OFFSET);
+	if (__gpio_is_inverted(chip->base + offset))
+		tmp &= ~mask;
+	else
+		tmp |= mask;
+	__raw_writel(tmp, base + GPDR_OFFSET);
+
+	spin_unlock_irqrestore(&gpio_lock, flags);
+	return 0;
+}
+
+static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset);
+}
+
+static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	__raw_writel(1 << offset, gpio_chip_base(chip) +
+				(value ? GPSR_OFFSET : GPCR_OFFSET));
+}
+
+static int __init pxa_init_gpio_chip(int gpio_end)
+{
+	int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
+	struct pxa_gpio_chip *chips;
+
+	chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
+	if (chips == NULL) {
+		pr_err("%s: failed to allocate GPIO chips\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
+		struct gpio_chip *c = &chips[i].chip;
+
+		sprintf(chips[i].label, "gpio-%d", i);
+		chips[i].regbase = (void __iomem *)GPIO_BANK(i);
+
+		c->base  = gpio;
+		c->label = chips[i].label;
+
+		c->direction_input  = pxa_gpio_direction_input;
+		c->direction_output = pxa_gpio_direction_output;
+		c->get = pxa_gpio_get;
+		c->set = pxa_gpio_set;
+
+		/* number of GPIOs on last bank may be less than 32 */
+		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32;
+		gpiochip_add(c);
+	}
+	pxa_gpio_chips = chips;
+	return 0;
+}
+
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+	uint32_t grer, gfer;
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+	grer |= c->irq_edge_rise & c->irq_mask;
+	gfer |= c->irq_edge_fall & c->irq_mask;
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	struct pxa_gpio_chip *c;
+	int gpio = irq_to_gpio(d->irq);
+	unsigned long gpdr, mask = GPIO_bit(gpio);
+
+	c = gpio_to_pxachip(gpio);
+
+	if (type == IRQ_TYPE_PROBE) {
+		/* Don't mess with enabled GPIOs using preconfigured edges or
+		 * GPIOs set to alternate function or to output during probe
+		 */
+		if ((c->irq_edge_rise | c->irq_edge_fall) & GPIO_bit(gpio))
+			return 0;
+
+		if (__gpio_is_occupied(gpio))
+			return 0;
+
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+
+	if (__gpio_is_inverted(gpio))
+		__raw_writel(gpdr | mask,  c->regbase + GPDR_OFFSET);
+	else
+		__raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET);
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		c->irq_edge_rise |= mask;
+	else
+		c->irq_edge_rise &= ~mask;
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		c->irq_edge_fall |= mask;
+	else
+		c->irq_edge_fall &= ~mask;
+
+	update_edge_detect(c);
+
+	pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, d->irq, gpio,
+		((type & IRQ_TYPE_EDGE_RISING)  ? " rising"  : ""),
+		((type & IRQ_TYPE_EDGE_FALLING) ? " falling" : ""));
+	return 0;
+}
+
+static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pxa_gpio_chip *c;
+	int loop, gpio, gpio_base, n;
+	unsigned long gedr;
+
+	do {
+		loop = 0;
+		for_each_gpio_chip(gpio, c) {
+			gpio_base = c->chip.base;
+
+			gedr = __raw_readl(c->regbase + GEDR_OFFSET);
+			gedr = gedr & c->irq_mask;
+			__raw_writel(gedr, c->regbase + GEDR_OFFSET);
+
+			n = find_first_bit(&gedr, BITS_PER_LONG);
+			while (n < BITS_PER_LONG) {
+				loop = 1;
+
+				generic_handle_irq(gpio_to_irq(gpio_base + n));
+				n = find_next_bit(&gedr, BITS_PER_LONG, n + 1);
+			}
+		}
+	} while (loop);
+}
+
+static void pxa_ack_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	__raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET);
+}
+
+static void pxa_mask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+	uint32_t grer, gfer;
+
+	c->irq_mask &= ~GPIO_bit(gpio);
+
+	grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio);
+	gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio);
+	__raw_writel(grer, c->regbase + GRER_OFFSET);
+	__raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
+static void pxa_unmask_muxed_gpio(struct irq_data *d)
+{
+	int gpio = irq_to_gpio(d->irq);
+	struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+	c->irq_mask |= GPIO_bit(gpio);
+	update_edge_detect(c);
+}
+
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
+	.irq_ack	= pxa_ack_muxed_gpio,
+	.irq_mask	= pxa_mask_muxed_gpio,
+	.irq_unmask	= pxa_unmask_muxed_gpio,
+	.irq_set_type	= pxa_gpio_irq_type,
+};
+
+void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn)
+{
+	struct pxa_gpio_chip *c;
+	int gpio, irq;
+
+	pxa_last_gpio = end;
+
+	/* Initialize GPIO chips */
+	pxa_init_gpio_chip(end);
+
+	/* clear all GPIO edge detects */
+	for_each_gpio_chip(gpio, c) {
+		__raw_writel(0, c->regbase + GFER_OFFSET);
+		__raw_writel(0, c->regbase + GRER_OFFSET);
+		__raw_writel(~0,c->regbase + GEDR_OFFSET);
+	}
+
+	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
+		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+	}
+
+	/* Install handler for GPIO>=2 edge detect interrupts */
+	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
+	pxa_muxed_gpio_chip.irq_set_wake = fn;
+}
+
+#ifdef CONFIG_PM
+static int pxa_gpio_suspend(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET);
+		c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET);
+		c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET);
+		c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET);
+
+		/* Clear GPIO transition detect bits */
+		__raw_writel(0xffffffff, c->regbase + GEDR_OFFSET);
+	}
+	return 0;
+}
+
+static void pxa_gpio_resume(void)
+{
+	struct pxa_gpio_chip *c;
+	int gpio;
+
+	for_each_gpio_chip(gpio, c) {
+		/* restore level with set/clear */
+		__raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET);
+		__raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET);
+
+		__raw_writel(c->saved_grer, c->regbase + GRER_OFFSET);
+		__raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET);
+		__raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET);
+	}
+}
+#else
+#define pxa_gpio_suspend	NULL
+#define pxa_gpio_resume		NULL
+#endif
+
+struct syscore_ops pxa_gpio_syscore_ops = {
+	.suspend	= pxa_gpio_suspend,
+	.resume		= pxa_gpio_resume,
+};
-- 
1.7.3.2

^ permalink raw reply related

* [PATCH 2/2 v2] plat-pxa: break out GPIO driver specifics
From: Linus Walleij @ 2011-09-27 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Linus Walleij <linus.walleij@linaro.org>

The <mach/gpio.h> file is included from upper directories
and deal with generic GPIO and gpiolib stuff. Break out the
platform and driver specific defines and functions into its own
header file.

Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-mmp/aspenite.c               |    1 +
 arch/arm/mach-mmp/brownstone.c             |    1 -
 arch/arm/mach-mmp/gplugd.c                 |    2 +-
 arch/arm/mach-mmp/include/mach/gpio-pxa.h  |   30 ++++++
 arch/arm/mach-mmp/include/mach/gpio.h      |   23 -----
 arch/arm/mach-mmp/jasper.c                 |    1 -
 arch/arm/mach-mmp/mmp2.c                   |    2 +-
 arch/arm/mach-mmp/pxa168.c                 |    2 +-
 arch/arm/mach-mmp/pxa910.c                 |    2 +-
 arch/arm/mach-mmp/tavorevb.c               |    1 +
 arch/arm/mach-pxa/cm-x255.c                |    1 -
 arch/arm/mach-pxa/include/mach/gpio-pxa.h  |  133 ++++++++++++++++++++++++++++
 arch/arm/mach-pxa/include/mach/gpio.h      |  110 +----------------------
 arch/arm/mach-pxa/include/mach/littleton.h |    2 +-
 arch/arm/mach-pxa/irq.c                    |    2 +-
 arch/arm/mach-pxa/mfp-pxa2xx.c             |    1 +
 arch/arm/mach-pxa/pxa25x.c                 |    1 +
 arch/arm/mach-pxa/pxa27x.c                 |    1 +
 arch/arm/mach-pxa/pxa3xx.c                 |    2 +-
 arch/arm/mach-pxa/pxa95x.c                 |    2 +-
 arch/arm/mach-pxa/saarb.c                  |    1 +
 arch/arm/plat-pxa/include/plat/gpio-pxa.h  |   44 +++++++++
 arch/arm/plat-pxa/include/plat/gpio.h      |   40 +--------
 drivers/gpio/gpio-pxa.c                    |    2 +
 24 files changed, 227 insertions(+), 180 deletions(-)
 create mode 100644 arch/arm/mach-mmp/include/mach/gpio-pxa.h
 create mode 100644 arch/arm/mach-pxa/include/mach/gpio-pxa.h
 create mode 100644 arch/arm/plat-pxa/include/plat/gpio-pxa.h

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 2b3b0c6..7a60bbb 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -17,6 +17,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index c79162a..e411252 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/regulator/fixed.h>
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 98e25d9..32776f3 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -9,11 +9,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <mach/gpio.h>
 #include <mach/pxa168.h>
 #include <mach/mfp-pxa168.h>
 
diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
new file mode 100644
index 0000000..c017a98
--- /dev/null
+++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_MACH_GPIO_PXA_H
+#define __ASM_MACH_GPIO_PXA_H
+
+#include <mach/addr-map.h>
+#include <mach/irqs.h>
+
+#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
+
+#define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+/* NOTE: these macros are defined here to make optimization of
+ * gpio_{get,set}_value() to work when 'gpio' is a constant.
+ * Usage of these macros otherwise is no longer recommended,
+ * use generic GPIO API whenever possible.
+ */
+#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
+
+#include <plat/gpio-pxa.h>
+
+#endif /* __ASM_MACH_GPIO_PXA_H */
diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h
index 7bfb827..68126235 100644
--- a/arch/arm/mach-mmp/include/mach/gpio.h
+++ b/arch/arm/mach-mmp/include/mach/gpio.h
@@ -1,36 +1,13 @@
 #ifndef __ASM_MACH_GPIO_H
 #define __ASM_MACH_GPIO_H
 
-#include <mach/addr-map.h>
-#include <mach/irqs.h>
 #include <asm-generic/gpio.h>
 
-#define GPIO_REGS_VIRT	(APB_VIRT_BASE + 0x19000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
-
-#define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	(IRQ_GPIO_START + (gpio))
 #define irq_to_gpio(irq)	((irq) - IRQ_GPIO_START)
 
-
 #define __gpio_is_inverted(gpio)	(0)
 #define __gpio_is_occupied(gpio)	(0)
 
-/* NOTE: these macros are defined here to make optimization of
- * gpio_{get,set}_value() to work when 'gpio' is a constant.
- * Usage of these macros otherwise is no longer recommended,
- * use generic GPIO API whenever possible.
- */
-#define GPIO_bit(gpio)	(1 << ((gpio) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF(gpio_to_bank(x)) + 0x24)
-
 #include <plat/gpio.h>
 #endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index 5d6421d..8bfac66 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/max8649.h>
 #include <linux/mfd/max8925.h>
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 1935834..65d8689e 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -9,7 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -25,6 +24,7 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
+#include <mach/gpio-pxa.h>
 #include <mach/devices.h>
 #include <mach/mmp2.h>
 
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index e6f6789..76ca15c 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,6 +20,7 @@
 #include <mach/regs-apbc.h>
 #include <mach/regs-apmu.h>
 #include <mach/irqs.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/devices.h>
 #include <mach/mfp.h>
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index c70b4dd..4ebbfbb 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -20,6 +19,7 @@
 #include <mach/regs-apmu.h>
 #include <mach/cputype.h>
 #include <mach/irqs.h>
+#include <mach/gpio-pxa.h>
 #include <mach/dma.h>
 #include <mach/mfp.h>
 #include <mach/devices.h>
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index 143e52e..eb5be87 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/smc91x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-pxa/cm-x255.c b/arch/arm/mach-pxa/cm-x255.c
index 93f59f8..be75147 100644
--- a/arch/arm/mach-pxa/cm-x255.c
+++ b/arch/arm/mach-pxa/cm-x255.c
@@ -11,7 +11,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand-gpio.h>
diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
new file mode 100644
index 0000000..41b4c93
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/gpio-pxa.h
@@ -0,0 +1,133 @@
+/*
+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __MACH_PXA_GPIO_PXA_H
+#define __MACH_PXA_GPIO_PXA_H
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+
+#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
+
+#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
+#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
+
+/* GPIO Pin Level Registers */
+#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
+#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
+#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
+#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
+
+/* GPIO Pin Direction Registers */
+#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
+#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
+#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
+#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
+
+/* GPIO Pin Output Set Registers */
+#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
+#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
+#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
+#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
+
+/* GPIO Pin Output Clear Registers */
+#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
+#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
+#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
+#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
+
+/* GPIO Rising Edge Detect Registers */
+#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
+#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
+#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
+#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
+
+/* GPIO Falling Edge Detect Registers */
+#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
+#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
+#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
+#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
+
+/* GPIO Edge Detect Status Registers */
+#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
+#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
+#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
+#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
+
+/* GPIO Alternate Function Select Registers */
+#define GAFR0_L		GPIO_REG(0x0054)
+#define GAFR0_U		GPIO_REG(0x0058)
+#define GAFR1_L		GPIO_REG(0x005C)
+#define GAFR1_U		GPIO_REG(0x0060)
+#define GAFR2_L		GPIO_REG(0x0064)
+#define GAFR2_U		GPIO_REG(0x0068)
+#define GAFR3_L		GPIO_REG(0x006C)
+#define GAFR3_U		GPIO_REG(0x0070)
+
+/* More handy macros.  The argument is a literal GPIO number. */
+
+#define GPIO_bit(x)	(1 << ((x) & 0x1f))
+
+#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
+#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
+#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
+#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
+#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
+#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
+
+
+#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
+
+#define gpio_to_bank(gpio)	((gpio) >> 5)
+
+#ifdef CONFIG_CPU_PXA26x
+/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
+ * as well as their Alternate Function value being '1' for GPIO in GAFRx.
+ */
+static inline int __gpio_is_inverted(unsigned gpio)
+{
+	return cpu_is_pxa25x() && gpio > 85;
+}
+#else
+static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
+#endif
+
+/*
+ * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
+ * function of a GPIO, and GPDRx cannot be altered once configured. It
+ * is attributed as "occupied" here (I know this terminology isn't
+ * accurate, you are welcome to propose a better one :-)
+ */
+static inline int __gpio_is_occupied(unsigned gpio)
+{
+	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
+		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
+		int dir = GPDR(gpio) & GPIO_bit(gpio);
+
+		if (__gpio_is_inverted(gpio))
+			return af != 1 || dir == 0;
+		else
+			return af != 0 || dir != 0;
+	} else
+		return GPDR(gpio) & GPIO_bit(gpio);
+}
+
+#include <plat/gpio-pxa.h>
+#endif /* __MACH_PXA_GPIO_PXA_H */
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index c463950..004cade 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -24,84 +24,10 @@
 #ifndef __ASM_ARCH_PXA_GPIO_H
 #define __ASM_ARCH_PXA_GPIO_H
 
-#include <mach/irqs.h>
-#include <mach/hardware.h>
 #include <asm-generic/gpio.h>
+/* The defines for the driver are needed for the accelerated accessors */
+#include "gpio-pxa.h"
 
-#define GPIO_REGS_VIRT	io_p2v(0x40E00000)
-
-#define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)	(*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
-
-/* GPIO Pin Level Registers */
-#define GPLR0		GPIO_REG(BANK_OFF(0) + 0x00)
-#define GPLR1		GPIO_REG(BANK_OFF(1) + 0x00)
-#define GPLR2		GPIO_REG(BANK_OFF(2) + 0x00)
-#define GPLR3		GPIO_REG(BANK_OFF(3) + 0x00)
-
-/* GPIO Pin Direction Registers */
-#define GPDR0		GPIO_REG(BANK_OFF(0) + 0x0c)
-#define GPDR1		GPIO_REG(BANK_OFF(1) + 0x0c)
-#define GPDR2		GPIO_REG(BANK_OFF(2) + 0x0c)
-#define GPDR3		GPIO_REG(BANK_OFF(3) + 0x0c)
-
-/* GPIO Pin Output Set Registers */
-#define GPSR0		GPIO_REG(BANK_OFF(0) + 0x18)
-#define GPSR1		GPIO_REG(BANK_OFF(1) + 0x18)
-#define GPSR2		GPIO_REG(BANK_OFF(2) + 0x18)
-#define GPSR3		GPIO_REG(BANK_OFF(3) + 0x18)
-
-/* GPIO Pin Output Clear Registers */
-#define GPCR0		GPIO_REG(BANK_OFF(0) + 0x24)
-#define GPCR1		GPIO_REG(BANK_OFF(1) + 0x24)
-#define GPCR2		GPIO_REG(BANK_OFF(2) + 0x24)
-#define GPCR3		GPIO_REG(BANK_OFF(3) + 0x24)
-
-/* GPIO Rising Edge Detect Registers */
-#define GRER0		GPIO_REG(BANK_OFF(0) + 0x30)
-#define GRER1		GPIO_REG(BANK_OFF(1) + 0x30)
-#define GRER2		GPIO_REG(BANK_OFF(2) + 0x30)
-#define GRER3		GPIO_REG(BANK_OFF(3) + 0x30)
-
-/* GPIO Falling Edge Detect Registers */
-#define GFER0		GPIO_REG(BANK_OFF(0) + 0x3c)
-#define GFER1		GPIO_REG(BANK_OFF(1) + 0x3c)
-#define GFER2		GPIO_REG(BANK_OFF(2) + 0x3c)
-#define GFER3		GPIO_REG(BANK_OFF(3) + 0x3c)
-
-/* GPIO Edge Detect Status Registers */
-#define GEDR0		GPIO_REG(BANK_OFF(0) + 0x48)
-#define GEDR1		GPIO_REG(BANK_OFF(1) + 0x48)
-#define GEDR2		GPIO_REG(BANK_OFF(2) + 0x48)
-#define GEDR3		GPIO_REG(BANK_OFF(3) + 0x48)
-
-/* GPIO Alternate Function Select Registers */
-#define GAFR0_L		GPIO_REG(0x0054)
-#define GAFR0_U		GPIO_REG(0x0058)
-#define GAFR1_L		GPIO_REG(0x005C)
-#define GAFR1_U		GPIO_REG(0x0060)
-#define GAFR2_L		GPIO_REG(0x0064)
-#define GAFR2_U		GPIO_REG(0x0068)
-#define GAFR3_L		GPIO_REG(0x006C)
-#define GAFR3_U		GPIO_REG(0x0070)
-
-/* More handy macros.  The argument is a literal GPIO number. */
-
-#define GPIO_bit(x)	(1 << ((x) & 0x1f))
-
-#define GPLR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x00)
-#define GPDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x0c)
-#define GPSR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x18)
-#define GPCR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x24)
-#define GRER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x30)
-#define GFER(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x3c)
-#define GEDR(x)		GPIO_REG(BANK_OFF((x) >> 5) + 0x48)
-#define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
-
-
-#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
-
-#define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
 
 static inline int irq_to_gpio(unsigned int irq)
@@ -118,37 +44,5 @@ static inline int irq_to_gpio(unsigned int irq)
 	return -1;
 }
 
-#ifdef CONFIG_CPU_PXA26x
-/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
- * as well as their Alternate Function value being '1' for GPIO in GAFRx.
- */
-static inline int __gpio_is_inverted(unsigned gpio)
-{
-	return cpu_is_pxa25x() && gpio > 85;
-}
-#else
-static inline int __gpio_is_inverted(unsigned gpio) { return 0; }
-#endif
-
-/*
- * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate
- * function of a GPIO, and GPDRx cannot be altered once configured. It
- * is attributed as "occupied" here (I know this terminology isn't
- * accurate, you are welcome to propose a better one :-)
- */
-static inline int __gpio_is_occupied(unsigned gpio)
-{
-	if (cpu_is_pxa27x() || cpu_is_pxa25x()) {
-		int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3;
-		int dir = GPDR(gpio) & GPIO_bit(gpio);
-
-		if (__gpio_is_inverted(gpio))
-			return af != 1 || dir == 0;
-		else
-			return af != 0 || dir != 0;
-	} else
-		return GPDR(gpio) & GPIO_bit(gpio);
-}
-
 #include <plat/gpio.h>
 #endif
diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h
index 1c585a7..b6238cb 100644
--- a/arch/arm/mach-pxa/include/mach/littleton.h
+++ b/arch/arm/mach-pxa/include/mach/littleton.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_ARCH_LITTLETON_H
 #define __ASM_ARCH_LITTLETON_H
 
-#include <asm/gpio.h>
+#include <mach/gpio-pxa.h>
 
 #define LITTLETON_ETH_PHYS	0x30000000
 
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index dafb4bf..d493a23 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -11,7 +11,6 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -21,6 +20,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index b129527..43a5f68 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -20,6 +20,7 @@
 
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa2xx.h>
+#include <mach/gpio-pxa.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 6bb3fa5..8746e10 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -24,6 +24,7 @@
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index d2cdcd6..2bb5cf8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/i2c/pxa-i2c.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 3ab9e84..f940a13 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -12,7 +12,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -26,6 +25,7 @@
 #include <asm/mach/map.h>
 #include <asm/suspend.h>
 #include <mach/hardware.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
 #include <mach/ohci.h>
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index de25ceb..51371b3 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -9,7 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -21,6 +20,7 @@
 #include <linux/syscore_ops.h>
 
 #include <mach/hardware.h>
+#include <mach/gpio-pxa.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/pxa930.h>
 #include <mach/reset.h>
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index 87070a8..3c988b6f 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -15,6 +15,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
new file mode 100644
index 0000000..b6390be
--- /dev/null
+++ b/arch/arm/plat-pxa/include/plat/gpio-pxa.h
@@ -0,0 +1,44 @@
+#ifndef __PLAT_PXA_GPIO_H
+#define __PLAT_PXA_GPIO_H
+
+struct irq_data;
+
+/*
+ * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
+ * one set of registers. The register offsets are organized below:
+ *
+ *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
+ * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
+ * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
+ * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
+ *
+ * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
+ * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
+ * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
+ *
+ * NOTE:
+ *   BANK 3 is only available on PXA27x and later processors.
+ *   BANK 4 and 5 are only available on PXA935
+ */
+
+#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
+
+#define GPLR_OFFSET	0x00
+#define GPDR_OFFSET	0x0C
+#define GPSR_OFFSET	0x18
+#define GPCR_OFFSET	0x24
+#define GRER_OFFSET	0x30
+#define GFER_OFFSET	0x3C
+#define GEDR_OFFSET	0x48
+
+/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
+ * Those cases currently cause holes in the GPIO number space, the
+ * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
+ */
+extern int pxa_last_gpio;
+
+typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
+
+extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
+
+#endif /* __PLAT_PXA_GPIO_H */
diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h
index 6fc41db..258f772 100644
--- a/arch/arm/plat-pxa/include/plat/gpio.h
+++ b/arch/arm/plat-pxa/include/plat/gpio.h
@@ -3,35 +3,8 @@
 
 #define __ARM_GPIOLIB_COMPLEX
 
-struct irq_data;
-
-/*
- * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
- * one set of registers. The register offsets are organized below:
- *
- *           GPLR    GPDR    GPSR    GPCR    GRER    GFER    GEDR
- * BANK 0 - 0x0000  0x000C  0x0018  0x0024  0x0030  0x003C  0x0048
- * BANK 1 - 0x0004  0x0010  0x001C  0x0028  0x0034  0x0040  0x004C
- * BANK 2 - 0x0008  0x0014  0x0020  0x002C  0x0038  0x0044  0x0050
- *
- * BANK 3 - 0x0100  0x010C  0x0118  0x0124  0x0130  0x013C  0x0148
- * BANK 4 - 0x0104  0x0110  0x011C  0x0128  0x0134  0x0140  0x014C
- * BANK 5 - 0x0108  0x0114  0x0120  0x012C  0x0138  0x0144  0x0150
- *
- * NOTE:
- *   BANK 3 is only available on PXA27x and later processors.
- *   BANK 4 and 5 are only available on PXA935
- */
-
-#define GPIO_BANK(n)	(GPIO_REGS_VIRT + BANK_OFF(n))
-
-#define GPLR_OFFSET	0x00
-#define GPDR_OFFSET	0x0C
-#define GPSR_OFFSET	0x18
-#define GPCR_OFFSET	0x24
-#define GRER_OFFSET	0x30
-#define GFER_OFFSET	0x3C
-#define GEDR_OFFSET	0x48
+/* The individual machine provides register offsets and NR_BUILTIN_GPIO */
+#include <mach/gpio-pxa.h>
 
 static inline int gpio_get_value(unsigned gpio)
 {
@@ -54,13 +27,4 @@ static inline void gpio_set_value(unsigned gpio, int value)
 
 #define gpio_cansleep		__gpio_cansleep
 
-/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
- * Those cases currently cause holes in the GPIO number space, the
- * actual number of the last GPIO is recorded by 'pxa_last_gpio'.
- */
-extern int pxa_last_gpio;
-
-typedef int (*set_wake_t)(struct irq_data *d, unsigned int on);
-
-extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn);
 #endif /* __PLAT_GPIO_H */
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 5d6a86b..9052925 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -18,6 +18,8 @@
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
+#include <mach/gpio-pxa.h>
+
 int pxa_last_gpio;
 
 struct pxa_gpio_chip {
-- 
1.7.3.2

^ permalink raw reply related

* [RFC PATCH 3/3] ARM: mm: add l2x0 suspend/resume support
From: Santosh Shilimkar @ 2011-09-27 10:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927102835.GA18572@e102568-lin.cambridge.arm.com>

On Tuesday 27 September 2011 03:58 PM, Lorenzo Pieralisi wrote:
> Santosh,
> 
> On Tue, Sep 27, 2011 at 06:29:38AM +0100, Santosh Shilimkar wrote:
>> Lorenzo,
>>
>> On Monday 26 September 2011 10:44 PM, Lorenzo Pieralisi wrote:
>>> On Mon, Sep 26, 2011 at 04:06:45PM +0100, Russell King - ARM Linux wrote:
>>>> On Mon, Sep 26, 2011 at 03:32:41PM +0100, Lorenzo Pieralisi wrote:
>>>>> Context is saved once for all at boot time, along with the L2 physical address
>>>>> and cache type.
>>>>
>>>> Why is this assembly code?  As Barry's previous patch shows, it's
>>>> entirely possible to save all the state required at init time from
>>>> the existing C code without needing any additional functions.
>>>>
>>>
>> I too didn't like this approach.
>>
>> The platforms which needs to take care of security needs to take
>> care of the L2 on their own and this code doesn't help them.
>>
>> Other platform which wants to use the L2 code, looks like are
>> fine to use the C-version which saves registers in init and restores
>> it in resume path whenever needed. The patch which was posted
>> on that was good enough. Regarding turning OFF MMU is really
>> not necessary unless and until some hardware's are buggy. In that
>> case, instead of adding that un-necessary code in generic code,
>> it's better to patch only that buggy SOC code.
>>
> 
> I summed up the reasons for this patch to exist in the cover letter 
> and I mentioned that some bits can be merged IF needed:
> 
> http://www.spinics.net/lists/arm-kernel/msg141989.html
> 
I read that.

> Having said that:
> 
> - This patch does not switch the MMU off
I noticed that. That comment was miss-placed.

> - This patch does not cover security, and I mentioned that
I never said it is covering security.
"The platforms which needs to take care of security needs to take
care of the L2 on their own and this code doesn't help them."

> - Russell referred to saving registers not restoring them, for a reason
I raised this point on very first patch for L2. My point here was all
the L2 registers cab be saved in init function and C-file.

> - If the resume hook is written in C you cannot call it when the MMU is
>   off, which we need if L2 is retained. Unless you think OMAP is the
>   only platform supporting L2 RAM retention, but there are people who might
>   disagree.
> 
Again I never said that. I guess MX support it as well. But I don't know
whether they have secure limitations as well. If not then probably
this asm resume function can help.

> And if you think it is not worth merging since most SoCs will run in
> non-secure mode, then that's a very valid point, but it is true for both
> patch series, not just for this one.
> 
I agree. From various discussion so far, apart MX, nobody complained
about C-version of the code. Hence the comment. If there are more
platforms which needs it, then the asm version would be useful and
should be preferred over C-version.

Regards
Santosh

^ permalink raw reply

* [PATCH 0/3] Clearify code paths for how to modify the power register
From: Ulf Hansson @ 2011-09-27 11:32 UTC (permalink / raw)
  To: linux-arm-kernel

In the set_ios function there has been a mess of how the power register
can be modified. One part, especially strange was related to the use of 
the vdd_handler.

Note that this patch serie is formated based upon the previously submitted
patch serie for mmci called "mmc: mmci: Improvements and bugfixes for SDIO".

Sebastian Rasmussen (1):
  mmc: mmci: Put power register deviations in variant data

Ulf Hansson (2):
  mmc: mmci: Provide option to configure bus signal direction
  mmc: mmci: Change vdd_handler to a generic ios_handler

 arch/arm/mach-ux500/board-mop500-sdi.c |   21 +++++--------
 drivers/mmc/host/mmci.c                |   49 ++++++++++++++++++++++++++-----
 drivers/mmc/host/mmci.h                |   10 ------
 include/linux/amba/mmci.h              |   22 ++++++++++++--
 4 files changed, 68 insertions(+), 34 deletions(-)

-- 
1.7.5.4

^ permalink raw reply

* [PATCH 1/9] regulator: twl: Remove hardcoded board constraints from driver
From: Mark Brown @ 2011-09-27 11:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-2-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:44PM +0530, Rajendra Nayak wrote:
> Remove the hardcoded .valid_modes_mask and .valid_ops_mask for
> each regulator from the twl driver and let the boards pass it.
> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>


> -	/* Constrain board-specific capabilities according to what
> -	 * this driver and the chip itself can actually do.
> -	 */
> -	c = &initdata->constraints;
> -	c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
> -	c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
> -				| REGULATOR_CHANGE_MODE
> -				| REGULATOR_CHANGE_STATUS;

This isn't actually hard coding constraints, this is restricting the
constraints passed in further rather than adding new ones.

However should be fine:

Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

^ permalink raw reply

* [PATCH 1/3] mmc: mmci: Put power register deviations in variant data
From: Ulf Hansson @ 2011-09-27 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com>

Use variant data to store hardware controller deviations concerning
power registers to improve readability of the code.

Signed-off-by: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com>
Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Reviewed-by: Linus Walleij <linus.walleij@stericsson.com>
---
 drivers/mmc/host/mmci.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 4da20ec..32de82b 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -53,6 +53,7 @@ static unsigned int fmax = 515633;
  * @st_clkdiv: true if using a ST-specific clock divider algorithm
  * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
  * @non_power_of_2_blksize: true if block sizes can be other than power of two
+ * @pwrreg_powerup: power up value for MMCIPOWER register
  */
 struct variant_data {
 	unsigned int		clkreg;
@@ -64,18 +65,21 @@ struct variant_data {
 	bool			st_clkdiv;
 	bool			blksz_datactrl16;
 	bool			non_power_of_2_blksize;
+	unsigned int		pwrreg_powerup;
 };
 
 static struct variant_data variant_arm = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
 	.datalength_bits	= 16,
+	.pwrreg_powerup		= MCI_PWR_UP,
 };
 
 static struct variant_data variant_arm_extended_fifo = {
 	.fifosize		= 128 * 4,
 	.fifohalfsize		= 64 * 4,
 	.datalength_bits	= 16,
+	.pwrreg_powerup		= MCI_PWR_UP,
 };
 
 static struct variant_data variant_u300 = {
@@ -84,6 +88,7 @@ static struct variant_data variant_u300 = {
 	.clkreg_enable		= MCI_ST_U300_HWFCEN,
 	.datalength_bits	= 16,
 	.sdio			= true,
+	.pwrreg_powerup		= MCI_PWR_ON,
 };
 
 static struct variant_data variant_ux500 = {
@@ -94,6 +99,7 @@ static struct variant_data variant_ux500 = {
 	.datalength_bits	= 24,
 	.sdio			= true,
 	.st_clkdiv		= true,
+	.pwrreg_powerup		= MCI_PWR_ON,
 };
 
 static struct variant_data variant_ux500v2 = {
@@ -106,6 +112,7 @@ static struct variant_data variant_ux500v2 = {
 	.st_clkdiv		= true,
 	.blksz_datactrl16	= true,
 	.non_power_of_2_blksize	= true,
+	.pwrreg_powerup		= MCI_PWR_ON,
 };
 
 /*
@@ -1030,6 +1037,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mmci_host *host = mmc_priv(mmc);
+	struct variant_data *variant = host->variant;
 	u32 pwr = 0;
 	unsigned long flags;
 	int ret;
@@ -1056,11 +1064,15 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		if (host->plat->vdd_handler)
 			pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd,
 						       ios->power_mode);
-		/* The ST version does not have this, fall through to POWER_ON */
-		if (host->hw_designer != AMBA_VENDOR_ST) {
-			pwr |= MCI_PWR_UP;
-			break;
-		}
+
+		/*
+		 * The ST Micro variant doesn't have the PL180s MCI_PWR_UP
+		 * and instead uses MCI_PWR_ON so apply whatever value is
+		 * configured in the variant data.
+		 */
+		pwr |= variant->pwrreg_powerup;
+
+		break;
 	case MMC_POWER_ON:
 		pwr |= MCI_PWR_ON;
 		break;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 2/3] mmc: mmci: Provide option to configure bus signal direction
From: Ulf Hansson @ 2011-09-27 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

The ST Micro variant supports bus signal direction indication. A new
member in the variant struct is added for this.

Moreover the actual signal direction configuration is board specific,
thus the amba mmci platform data is extended with a new member to be
able provide mmci with these specific board configurations.

This patch is based upon a patch from Sebastian Rasmussen.

Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Signed-off-by: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com>
---
 drivers/mmc/host/mmci.c   |   21 +++++++++++++++++++++
 drivers/mmc/host/mmci.h   |   10 ----------
 include/linux/amba/mmci.h |   16 ++++++++++++++++
 3 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 32de82b..82810a6 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -54,6 +54,7 @@ static unsigned int fmax = 515633;
  * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register
  * @non_power_of_2_blksize: true if block sizes can be other than power of two
  * @pwrreg_powerup: power up value for MMCIPOWER register
+ * @signal_direction: input/out direction of bus signals can be indicated
  */
 struct variant_data {
 	unsigned int		clkreg;
@@ -66,6 +67,7 @@ struct variant_data {
 	bool			blksz_datactrl16;
 	bool			non_power_of_2_blksize;
 	unsigned int		pwrreg_powerup;
+	bool			signal_direction;
 };
 
 static struct variant_data variant_arm = {
@@ -89,6 +91,7 @@ static struct variant_data variant_u300 = {
 	.datalength_bits	= 16,
 	.sdio			= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.signal_direction	= true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -100,6 +103,7 @@ static struct variant_data variant_ux500 = {
 	.sdio			= true,
 	.st_clkdiv		= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.signal_direction	= true,
 };
 
 static struct variant_data variant_ux500v2 = {
@@ -113,6 +117,7 @@ static struct variant_data variant_ux500v2 = {
 	.blksz_datactrl16	= true,
 	.non_power_of_2_blksize	= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
+	.signal_direction	= true,
 };
 
 /*
@@ -1078,6 +1083,22 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		break;
 	}
 
+	if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) {
+		/*
+		 * The ST Micro variant has some additional bits
+		 * indicating signal direction for the signals in
+		 * the SD/MMC bus and feedback-clock usage.
+		 */
+		pwr |= host->plat->sigdir;
+
+		if (ios->bus_width == MMC_BUS_WIDTH_4)
+			pwr &= ~MCI_ST_DATA74DIREN;
+		else if (ios->bus_width == MMC_BUS_WIDTH_1)
+			pwr &= (~MCI_ST_DATA74DIREN &
+				~MCI_ST_DATA31DIREN &
+				~MCI_ST_DATA2DIREN);
+	}
+
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
 		if (host->hw_designer != AMBA_VENDOR_ST)
 			pwr |= MCI_ROD;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 79e4143..5600755 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -13,16 +13,6 @@
 #define MCI_PWR_ON		0x03
 #define MCI_OD			(1 << 6)
 #define MCI_ROD			(1 << 7)
-/*
- * The ST Micro version does not have ROD and reuse the voltage registers
- * for direction settings
- */
-#define MCI_ST_DATA2DIREN	(1 << 2)
-#define MCI_ST_CMDDIREN		(1 << 3)
-#define MCI_ST_DATA0DIREN	(1 << 4)
-#define MCI_ST_DATA31DIREN	(1 << 5)
-#define MCI_ST_FBCLKEN		(1 << 7)
-#define MCI_ST_DATA74DIREN	(1 << 8)
 
 #define MMCICLOCK		0x004
 #define MCI_CLK_ENABLE		(1 << 8)
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index 2111481..de8a7a1 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -6,6 +6,19 @@
 
 #include <linux/mmc/host.h>
 
+
+/*
+ * These defines is places here due to access is needed from machine
+ * configuration files. The ST Micro version does not have ROD and
+ * reuse the voltage registers for direction settings.
+ */
+#define MCI_ST_DATA2DIREN	(1 << 2)
+#define MCI_ST_CMDDIREN		(1 << 3)
+#define MCI_ST_DATA0DIREN	(1 << 4)
+#define MCI_ST_DATA31DIREN	(1 << 5)
+#define MCI_ST_FBCLKEN		(1 << 7)
+#define MCI_ST_DATA74DIREN	(1 << 8)
+
 /* Just some dummy forwarding */
 struct dma_chan;
 
@@ -30,6 +43,8 @@ struct dma_chan;
  * @cd_invert: true if the gpio_cd pin value is active low
  * @capabilities: the capabilities of the block as implemented in
  * this platform, signify anything MMC_CAP_* from mmc/host.h
+ * @sigdir: a bit field indicating for what bits in the MMC bus the host
+ * should enable signal direction indication.
  * @dma_filter: function used to select an appropriate RX and TX
  * DMA channel to be used for DMA, if and only if you're deploying the
  * generic DMA engine
@@ -52,6 +67,7 @@ struct mmci_platform_data {
 	int	gpio_cd;
 	bool	cd_invert;
 	unsigned long capabilities;
+	unsigned int sigdir;
 	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
 	void *dma_rx_param;
 	void *dma_tx_param;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 3/3] mmc: mmci: Change vdd_handler to a generic ios_handler
From: Ulf Hansson @ 2011-09-27 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

The purpose of the vdd_handler does not make sense. We remove it
and use a generic approach instead. A new ios_handler is added, the
purpose of which e.g. can be to control GPIO pins to a levelshifter.

Previously the vdd_handler was also used for making additional
changes to the power register bits. This option is superfluous and is
therefore removed.

Adaptaptions from the old vdd_handler to the new ios_handler is done for
mach-ux500 board, which was the only one using the vdd_handler.

This patch is based upon a patch from Sebastian Rasmussen.

Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Signed-off-by: Sebastian Rasmussen <sebastian.rasmussen@stericsson.com>
---
 arch/arm/mach-ux500/board-mop500-sdi.c |   21 ++++++++-------------
 drivers/mmc/host/mmci.c                |    8 ++++----
 include/linux/amba/mmci.h              |    6 +++---
 3 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 6826fae..3578c51 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -25,21 +25,13 @@
  * SDI 0 (MicroSD slot)
  */
 
-/* MMCIPOWER bits */
-#define MCI_DATA2DIREN		(1 << 2)
-#define MCI_CMDDIREN		(1 << 3)
-#define MCI_DATA0DIREN		(1 << 4)
-#define MCI_DATA31DIREN		(1 << 5)
-#define MCI_FBCLKEN		(1 << 7)
-
 /* GPIO pins used by the sdi0 level shifter */
 static int sdi0_en = -1;
 static int sdi0_vsel = -1;
 
-static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
-				   unsigned char power_mode)
+static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios)
 {
-	switch (power_mode) {
+	switch (ios->power_mode) {
 	case MMC_POWER_UP:
 	case MMC_POWER_ON:
 		/*
@@ -59,8 +51,7 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
 		break;
 	}
 
-	return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
-	       MCI_DATA2DIREN | MCI_DATA31DIREN;
+	return 0;
 }
 
 #ifdef CONFIG_STE_DMA40
@@ -84,13 +75,17 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 #endif
 
 static struct mmci_platform_data mop500_sdi0_data = {
-	.vdd_handler	= mop500_sdi0_vdd_handler,
+	.ios_handler	= mop500_sdi0_ios_handler,
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA |
 				MMC_CAP_SD_HIGHSPEED |
 				MMC_CAP_MMC_HIGHSPEED,
 	.gpio_wp	= -1,
+	.sigdir		= MCI_ST_FBCLKEN |
+				MCI_ST_CMDDIREN |
+				MCI_ST_DATA0DIREN |
+				MCI_ST_DATA2DIREN,
 #ifdef CONFIG_STE_DMA40
 	.dma_filter	= stedma40_filter,
 	.dma_rx_param	= &mop500_sdi0_dma_cfg_rx,
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 82810a6..13222bd 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1047,6 +1047,10 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	unsigned long flags;
 	int ret;
 
+	if (host->plat->ios_handler &&
+		host->plat->ios_handler(mmc_dev(mmc), ios))
+			dev_err(mmc_dev(mmc), "platform ios_handler failed\n");
+
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
 		if (host->vcc)
@@ -1066,10 +1070,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 				return;
 			}
 		}
-		if (host->plat->vdd_handler)
-			pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd,
-						       ios->power_mode);
-
 		/*
 		 * The ST Micro variant doesn't have the PL180s MCI_PWR_UP
 		 * and instead uses MCI_PWR_ON so apply whatever value is
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index de8a7a1..188676b 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -31,7 +31,8 @@ struct dma_chan;
  * @ocr_mask: available voltages on the 4 pins from the block, this
  * is ignored if a regulator is used, see the MMC_VDD_* masks in
  * mmc/host.h
- * @vdd_handler: a callback function to translate a MMC_VDD_*
+ * @ios_handler: a callback function to act on specfic ios changes,
+ * used for example to control a levelshifter
  * mask into a value to be binary (or set some other custom bits
  * in MMCIPWR) or:ed and written into the MMCIPWR register of the
  * block.  May also control external power based on the power_mode.
@@ -60,8 +61,7 @@ struct dma_chan;
 struct mmci_platform_data {
 	unsigned int f_max;
 	unsigned int ocr_mask;
-	u32 (*vdd_handler)(struct device *, unsigned int vdd,
-			   unsigned char power_mode);
+	int (*ios_handler)(struct device *, struct mmc_ios *);
 	unsigned int (*status)(struct device *);
 	int	gpio_wp;
 	int	gpio_cd;
-- 
1.7.5.4

^ permalink raw reply related

* [RFC 5/5] iommu/omap: eliminate the public omap_find_iommu_device() method
From: Laurent Pinchart @ 2011-09-27 11:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316948337-7924-6-git-send-email-ohad@wizery.com>

Hi Ohad,

Thanks for the patch.

On Sunday 25 September 2011 12:58:57 Ohad Ben-Cohen wrote:
> Eliminate the public omap_find_iommu_device() method, and don't
> expect clients to provide the omap_iommu handle anymore.
> 
> Instead, OMAP's iommu driver should now utilize dev_archdata's private
> iommu extension to be able to access the required iommu information.
> 
> Update omap3isp appropriately.
> 
> Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
> Cc: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Tony Lindgren <tony@atomide.com>

For the OMAP3 ISP driver,

Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH v2 10/16] ARM: ux500: convert to CONFIG_MULTI_IRQ_HANDLER
From: Linus Walleij @ 2011-09-27 11:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317034955-1029-11-git-send-email-marc.zyngier@arm.com>

On Mon, Sep 26, 2011 at 1:02 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:

> Convert the ux500 platforms to be using the gic_handle_irq
> function as their primary interrupt handler.
>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Seems straight-forward provided the first patch is working
good so:
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thanks,
Linus Walleij

^ permalink raw reply

* [PATCH 2/9] regulator: helper routine to extract regulator_init_data
From: Mark Brown @ 2011-09-27 12:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-3-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:45PM +0530, Rajendra Nayak wrote:

> +	init_data = devm_kzalloc(dev, sizeof(struct regulator_init_data),
> +						 GFP_KERNEL);
> +	if (!init_data)
> +		return NULL; /* Out of memory? */

This means that the init data will be kept around for the entire
lifetime of the device rather than being discarded.

> +	init_data->supply_regulator = (char *)of_get_property(dev->of_node,
> +						"regulator-supplies", NULL);

I'd expect that in the device tree world the supply regulator would
reference the node for that regulator.

>  	/* voltage output range (inclusive) - for voltage control */
> -	int min_uV;
> -	int max_uV;
> +	u32 min_uV;
> +	u32 max_uV;
>  
> -	int uV_offset;
> +	u32 uV_offset;
>  
>  	/* current output range (inclusive) - for current control */
> -	int min_uA;
> -	int max_uA;
> +	u32 min_uA;
> +	u32 max_uA;

Hrm, I think loosing the signs here is bad karma - negative voltages do
exist after all.

^ permalink raw reply

* [PATCH 4/9] regulator: twl: Make twl-regulator driver extract data from DT
From: Mark Brown @ 2011-09-27 12:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-5-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:47PM +0530, Rajendra Nayak wrote:

> +#ifdef CONFIG_OF
> +	char			compatible[128];
> +#endif

Might it not be better to just make this a pointer to const char?

^ permalink raw reply

* [PATCH 5/9] regulator: helper routine to extract fixed_voltage_config
From: Mark Brown @ 2011-09-27 12:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-6-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:48PM +0530, Rajendra Nayak wrote:
> The helper routine of_get_fixed_voltage_config() extracts
> fixed_voltage_config structure contents from device tree.
> 
> Also add documenation for additional bindings for fixed
> regulators that can be passed through dt.

Why not just add device tree support into the driver directly?

> +Optional properties:
> +- regulator-fixed-supply: Name of the regulator supply

This is going to be confusing with respect to the generic regulator
supply property.

> +- regulator-fixed-enable-high: Polarity of enable GPIO, 1 = Active High, 0 = Active low

Word wrap for legibility please.

^ permalink raw reply

* [PATCH 1/2] ARM: vic: device tree binding
From: Jamie Iles @ 2011-09-27 12:16 UTC (permalink / raw)
  To: linux-arm-kernel

This adds a device tree binding for the VIC based on the of_irq_init()
support.

Cc: Rob Herring <robherring2@gmail.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 Documentation/devicetree/bindings/arm/vic.txt |   29 ++++++
 arch/arm/common/vic.c                         |  121 ++++++++++++++++++++-----
 arch/arm/include/asm/hardware/vic.h           |   13 +++-
 3 files changed, 137 insertions(+), 26 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/vic.txt

diff --git a/Documentation/devicetree/bindings/arm/vic.txt b/Documentation/devicetree/bindings/arm/vic.txt
new file mode 100644
index 0000000..266716b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vic.txt
@@ -0,0 +1,29 @@
+* ARM Vectored Interrupt Controller
+
+One or more Vectored Interrupt Controllers (VIC's) can be connected in an ARM
+system for interrupt routing.  For multiple controllers they can either be
+nested or have the outputs wire-OR'd together.
+
+Required properties:
+
+- compatible : should be one of
+	"arm,pl190-vic"
+	"arm,pl192-vic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : The number of cells to define the interrupts.  Must be 1 as
+  the VIC has no configuration options for interrupt sources.  The cell is a u32
+  and defines the interrupt number.
+- reg : The register bank for the VIC.
+
+Optional properties:
+
+- interrupts : Interrupt source for parent controllers if the VIC is nested.
+
+Example:
+
+	vic0: interrupt-controller at 60000 {
+		compatible = "arm,pl192-vic";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0x60000 0x1000>;
+	};
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 7aa4262..3658579 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -22,6 +22,10 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/syscore_ops.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
@@ -29,7 +33,6 @@
 #include <asm/mach/irq.h>
 #include <asm/hardware/vic.h>
 
-#ifdef CONFIG_PM
 /**
  * struct vic_device - VIC PM device
  * @irq: The IRQ number for the base of the VIC.
@@ -50,13 +53,15 @@ struct vic_device {
 	u32		int_enable;
 	u32		soft_int;
 	u32		protect;
+#ifdef CONFIG_IRQ_DOMAIN
+	struct irq_domain domain;
+#endif /* CONFIG_IRQ_DOMAIN */
 };
 
 /* we cannot allocate memory when VICs are initially registered */
 static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
 
 static int vic_id;
-#endif /* CONFIG_PM */
 
 /**
  * vic_init2 - common initialisation code
@@ -156,9 +161,10 @@ static int __init vic_pm_init(void)
 	return 0;
 }
 late_initcall(vic_pm_init);
+#endif /* CONFIG_PM */
 
 /**
- * vic_pm_register - Register a VIC for later power management control
+ * vic_register - Register a VIC.
  * @base: The base address of the VIC.
  * @irq: The base IRQ for the VIC.
  * @resume_sources: bitmask of interrupts allowed for resume sources.
@@ -166,24 +172,28 @@ late_initcall(vic_pm_init);
  * Register the VIC with the system device tree so that it can be notified
  * of suspend and resume requests and ensure that the correct actions are
  * taken to re-instate the settings on resume.
+ *
+ * We return the VIC so that it can be used for IRQ domain operations for
+ * device tree translation.
  */
-static void __init vic_pm_register(void __iomem *base, unsigned int irq, u32 resume_sources)
+static struct vic_device * __init
+vic_register(void __iomem *base, unsigned int irq, u32 resume_sources)
 {
 	struct vic_device *v;
 
-	if (vic_id >= ARRAY_SIZE(vic_devices))
+	if (vic_id >= ARRAY_SIZE(vic_devices)) {
 		printk(KERN_ERR "%s: too few VICs, increase CONFIG_ARM_VIC_NR\n", __func__);
-	else {
-		v = &vic_devices[vic_id];
-		v->base = base;
-		v->resume_sources = resume_sources;
-		v->irq = irq;
-		vic_id++;
+		return NULL;
 	}
+
+	v = &vic_devices[vic_id];
+	v->base = base;
+	v->resume_sources = resume_sources;
+	v->irq = irq;
+	vic_id++;
+
+	return v;
 }
-#else
-static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg1) { }
-#endif /* CONFIG_PM */
 
 static void vic_ack_irq(struct irq_data *d)
 {
@@ -331,15 +341,9 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
 	vic_set_irq_sources(base, irq_start, vic_sources);
 }
 
-/**
- * vic_init - initialise a vectored interrupt controller
- * @base: iomem base address
- * @irq_start: starting interrupt number, must be muliple of 32
- * @vic_sources: bitmask of interrupt sources to allow
- * @resume_sources: bitmask of interrupt sources to allow for resume
- */
-void __init vic_init(void __iomem *base, unsigned int irq_start,
-		     u32 vic_sources, u32 resume_sources)
+static struct vic_device * __init
+__vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources,
+	   u32 resume_sources)
 {
 	unsigned int i;
 	u32 cellid = 0;
@@ -357,7 +361,7 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
 	switch(vendor) {
 	case AMBA_VENDOR_ST:
 		vic_init_st(base, irq_start, vic_sources);
-		return;
+		return NULL;
 	default:
 		printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n");
 		/* fall through */
@@ -375,5 +379,72 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
 
 	vic_set_irq_sources(base, irq_start, vic_sources);
 
-	vic_pm_register(base, irq_start, resume_sources);
+	return vic_register(base, irq_start, resume_sources);
 }
+
+/**
+ * vic_init - initialise a vectored interrupt controller
+ * @base: iomem base address
+ * @irq_start: starting interrupt number, must be muliple of 32
+ * @vic_sources: bitmask of interrupt sources to allow
+ * @resume_sources: bitmask of interrupt sources to allow for resume
+ */
+void __init vic_init(void __iomem *base, unsigned int irq_start,
+		     u32 vic_sources, u32 resume_sources)
+{
+	__vic_init(base, irq_start, vic_sources, resume_sources);
+}
+
+#ifdef CONFIG_OF
+static int
+vic_irq_domain_dt_translate(struct irq_domain *d, struct device_node *np,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != np)
+		return -EINVAL;
+	if (intsize < 1)
+		return -EINVAL;
+
+	*out_hwirq = intspec[0];
+	*out_type = IRQ_TYPE_NONE;
+
+	return 0;
+}
+
+static const struct irq_domain_ops vic_irq_domain_ops = {
+	.dt_translate = vic_irq_domain_dt_translate,
+};
+
+int __init vic_of_init(struct device_node *node, struct device_node *parent)
+{
+	void __iomem *regs = of_iomap(node, 0);
+	struct vic_device *vic;
+	int irq_base;
+
+	if (WARN_ON(!regs))
+		return -EIO;
+
+	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+	if (WARN_ON(irq_base < 0))
+		goto out_unmap;
+
+	vic = __vic_init(regs, irq_base, ~0, ~0);
+	if (WARN_ON(!vic))
+		goto out_unmap;
+
+	vic->domain.irq_base = irq_base;
+	vic->domain.nr_irq = 32;
+	vic->domain.of_node = of_node_get(node);
+	vic->domain.ops = &vic_irq_domain_ops;
+	irq_domain_add(&vic->domain);
+
+	return 0;
+
+out_unmap:
+	iounmap(regs);
+
+	return -EIO;
+}
+
+#endif /* CONFIG OF */
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index 5d72550..df1d895 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -41,7 +41,18 @@
 #define VIC_PL192_VECT_ADDR		0xF00
 
 #ifndef __ASSEMBLY__
+struct device_node;
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
-#endif
+
+#ifdef CONFIG_OF
+int vic_of_init(struct device_node *node, struct device_node *parent);
+#else /* CONFIG_OF */
+static inline int vic_of_init(struct device_node *node,
+			      struct device_node *parent)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_OF */
+#endif /* __ASSEMBLY__ */
 
 #endif
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 2/2] ARM: vic: MULTI_IRQ_HANDLER handler
From: Jamie Iles @ 2011-09-27 12:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317125802-14386-1-git-send-email-jamie@jamieiles.com>

Add a handler for the VIC that is suitable for MULTI_IRQ_HANDLER
platforms.  This only works for platforms with CONFIG_OF=y as we can
determine which controllers are the primary controllers (no parent).

Signed-off-by: Jamie Iles <jamie@jamieiles.com>
---
 arch/arm/common/vic.c               |   48 +++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/hardware/vic.h |    1 +
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 3658579..e9b72d3 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -63,6 +63,22 @@ static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
 
 static int vic_id;
 
+#if defined(CONFIG_OF) && defined(CONFIG_MULTI_IRQ_HANDLER)
+/*
+ * The root VIC's.  We keep track of these so that we can do the IRQ demuxing
+ * as we can have more than one root VIC.
+ */
+static struct vic_device *vic_root_devices[CONFIG_ARM_VIC_NR];
+static int nr_root_vics;
+
+static void vic_register_root_controller(struct vic_device *vic)
+{
+	vic_root_devices[nr_root_vics++] = vic;
+}
+#else /* CONFIG_OF && CONFIG_MULTI_IRQ_HANDLER */
+static inline void vic_register_root_controller(struct vic_device *vic) {}
+#endif /* CONFIG_OF && CONFIG_MULTI_IRQ_HANDLER */
+
 /**
  * vic_init2 - common initialisation code
  * @base: Base of the VIC.
@@ -439,6 +455,9 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
 	vic->domain.ops = &vic_irq_domain_ops;
 	irq_domain_add(&vic->domain);
 
+	if (!parent)
+		vic_register_root_controller(vic);
+
 	return 0;
 
 out_unmap:
@@ -447,4 +466,33 @@ out_unmap:
 	return -EIO;
 }
 
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+static void vic_single_handle_irq(struct vic_device *vic, struct pt_regs *regs)
+{
+	u32 stat, irq;
+	bool handled = false;
+
+	while (!handled) {
+		stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
+		if (!stat)
+			break;
+
+		while (stat) {
+			irq = fls(stat) - 1;
+			handle_IRQ(irq + vic->irq, regs);
+			stat &= ~(1 << irq);
+			handled = true;
+		}
+	}
+}
+
+asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
+{
+	int i;
+
+	for (i = 0; i < nr_root_vics; ++i)
+		vic_single_handle_irq(vic_root_devices[i], regs);
+}
+#endif /* CONFIG_MULTI_IRQ_HANDLER */
+
 #endif /* CONFIG OF */
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index df1d895..451788c 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -53,6 +53,7 @@ static inline int vic_of_init(struct device_node *node,
 	return -ENOSYS;
 }
 #endif /* CONFIG_OF */
+void vic_handle_irq(struct pt_regs *regs);
 #endif /* __ASSEMBLY__ */
 
 #endif
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 8/9] regulator: helper to extract regulator node based on supply name
From: Mark Brown @ 2011-09-27 12:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-9-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:51PM +0530, Rajendra Nayak wrote:

> +	if (!dev)
> +		return NULL;

So how do we handle CPUs?  cpufreq is one of the most active users of
regulators...

> +	snprintf(prop_name, 32, "%s-supply", supply);
> +
> +	prop = of_get_property(dev->of_node, prop_name, &sz);
> +	if (!prop || sz < 4)
> +		return NULL;

sz < 4?  Magic!  :)

> +extern struct device_node *of_get_regulator(struct device *dev,
> +	const char *supply);

This shouldn't be part of the public API, it should be transparently
handled within the core.

^ permalink raw reply

* [PATCH 9/9] regulator: map consumer regulator based on device tree
From: Mark Brown @ 2011-09-27 12:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-10-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:52PM +0530, Rajendra Nayak wrote:
> Look up the regulator for a given consumer from device tree, during
> a regulator_get(). If not found fallback and lookup through
> the regulator_map_list instead.

As with the fixed voltage regulator patch just use the code along with
adding it, no need to split it just makes it harder to review.

> +	if (dev->of_node) {
> +		node = of_get_regulator(dev, id);
> +		if (!node)
> +			goto retry; /* fallback and chk regulator_map_list */
> +		list_for_each_entry(rdev, &regulator_list, list)
> +			if (node == rdev->node)
> +				goto found;
> +	}
> +retry:

retry is a confusing name for the target, we don't ever actually retry
using it.  Given the simplicity of the code I'd be inclined to just
intert the if (!node) check.

^ permalink raw reply

* [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
From: Ohad Ben-Cohen @ 2011-09-27 12:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927100505.GH2138@amd.com>

On Tue, Sep 27, 2011 at 1:05 PM, Roedel, Joerg <Joerg.Roedel@amd.com> wrote:
> On Fri, Sep 16, 2011 at 01:51:41PM -0400, Ohad Ben-Cohen wrote:
>> ?int iommu_map(struct iommu_domain *domain, unsigned long iova,
>> - ? ? ? ? ? ? phys_addr_t paddr, int gfp_order, int prot)
>> + ? ? ? ? ? ? phys_addr_t paddr, size_t size, int prot)
>> ?{
>> - ? ? ? size_t size;
>> + ? ? ? int ret = 0;
>> +
>> + ? ? ? /*
>> + ? ? ? ?* both the virtual address and the physical one, as well as
>> + ? ? ? ?* the size of the mapping, must be aligned (at least) to the
>> + ? ? ? ?* size of the smallest page supported by the hardware
>> + ? ? ? ?*/
>> + ? ? ? if (!IS_ALIGNED(iova | paddr | size, iommu_min_pagesz)) {
>> + ? ? ? ? ? ? ? pr_err("unaligned: iova 0x%lx pa 0x%lx size 0x%lx min_pagesz "
>> + ? ? ? ? ? ? ? ? ? ? ? "0x%x\n", iova, (unsigned long)paddr,
>> + ? ? ? ? ? ? ? ? ? ? ? (unsigned long)size, iommu_min_pagesz);
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? }
>> +
>> + ? ? ? pr_debug("map: iova 0x%lx pa 0x%lx size 0x%lx\n", iova,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long)paddr, (unsigned long)size);
>> +
>> + ? ? ? while (size) {
>> + ? ? ? ? ? ? ? unsigned long pgsize = iommu_min_pagesz;
>> + ? ? ? ? ? ? ? unsigned long idx = iommu_min_page_idx;
>> + ? ? ? ? ? ? ? unsigned long addr_merge = iova | paddr;
>> + ? ? ? ? ? ? ? int order;
>> +
>> + ? ? ? ? ? ? ? /* find the max page size with which iova, paddr are aligned */
>> + ? ? ? ? ? ? ? for (;;) {
>> + ? ? ? ? ? ? ? ? ? ? ? unsigned long try_pgsize;
>> +
>> + ? ? ? ? ? ? ? ? ? ? ? idx = find_next_bit(iommu_pgsize_bitmap,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iommu_nr_page_bits, idx + 1);
>> +
>> + ? ? ? ? ? ? ? ? ? ? ? /* no more pages to check ? */
>> + ? ? ? ? ? ? ? ? ? ? ? if (idx >= iommu_nr_page_bits)
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
>> +
>> + ? ? ? ? ? ? ? ? ? ? ? try_pgsize = 1 << idx;
>>
>> - ? ? ? size ? ? ? ? = 0x1000UL << gfp_order;
>> + ? ? ? ? ? ? ? ? ? ? ? /* page too big ? addresses not aligned ? */
>> + ? ? ? ? ? ? ? ? ? ? ? if (size < try_pgsize ||
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? !IS_ALIGNED(addr_merge, try_pgsize))
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
>>
>> - ? ? ? BUG_ON(!IS_ALIGNED(iova | paddr, size));
>> + ? ? ? ? ? ? ? ? ? ? ? pgsize = try_pgsize;
>> + ? ? ? ? ? ? ? }
>
> With an unsigned long you can use plain and fast bit_ops instead of the
> full bitmap functions.

Not sure I follow; the only bit operation I'm using while mapping is
find_next_bit() (which is a bitops.h method).

What other faster variant are you referring to ?

Thanks,
Ohad.

^ permalink raw reply

* Pull request: removal of most instances of mach/memory.h
From: Nicolas Pitre @ 2011-09-27 12:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927072156.GQ22455@n2100.arm.linux.org.uk>

On Tue, 27 Sep 2011, Russell King - ARM Linux wrote:

> The fact of the matter is that you should have said in the final pull
> request that you'd also sent one of the patches to the patch system
> _whether_ _or_ _not_ it was applied.  Whether it was applied or not
> is completely irrelevant - because either way it requires some action
> (either to remove it from my git tree if applied _OR_ discard it from
> the patch system if not.)
> 
> The fact you didn't mention it in the final pull request at all is the
> problem.

Yes, you'reright.


Nicolas

^ permalink raw reply

* [PATCH v2 10/16] ARM: ux500: convert to CONFIG_MULTI_IRQ_HANDLER
From: Marc Zyngier @ 2011-09-27 12:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdY_24LptsjW5WMd6PCw6GsCYDO4LM1v8LDMRL8b7yj5Dw@mail.gmail.com>

On 27/09/11 12:47, Linus Walleij wrote:
> On Mon, Sep 26, 2011 at 1:02 PM, Marc Zyngier <marc.zyngier@arm.com> wrote:
> 
>> Convert the ux500 platforms to be using the gic_handle_irq
>> function as their primary interrupt handler.
>>
>> Cc: Linus Walleij <linus.walleij@stericsson.com>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> 
> Seems straight-forward provided the first patch is working
> good so:
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thanks Linus!

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* Porting linux to Stellaris Cortex-M3
From: Fernando Endo @ 2011-09-27 12:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAJ0-p7YwKR9B6BfoHcRqrNPVvpd49XrPsDCN7UF=-5jAf8XnQ@mail.gmail.com>

Oh sorry for sendig again, I forgot to include the lists


2011/9/27 Maxin John <arm.maxinbjohn@gmail.com>:
>
> We hit this bug if we are scheduling when we should not be. ie : if we
> call schedule() or sleep() from a driver while in an interrupt handler
> or holding a spin-lock, that will trigger this bug. This is because of
> a bug present in any of the kernel drivers.

Do we call schedule() or sleep() explicitly on a kernel driver, or are
there 'hidden' calls inside some function?
As I had to implement the basic drivers (clock, timer, irq and uart)
so far, I didn't call them explicitly.

>?Please share the detailed logs.

This is the log that I got with printascii bypassing printk:

<5>Linux version 2.6.33-arm1 (fernando at fernando-POS-MIG31AG) (gcc
version 4.5.2 (Sourcery G++ Lite 2011.03-41) ) #127 Tue Sep 27
09:14:21 BRT 2011
CPU: ARMv7-M Processor [412fc230] revision 0 (ARMv?(11)M)
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: Stellaris LM3S9B96
<7>On node 0 totalpages: 2048
<7>free_area_init_node: node 0, pgdat 600de1e0, node_mem_map 600f6000
<7> ?DMA zone: 16 pages used for memmap
<7> ?DMA zone: 0 pages reserved
<7> ?DMA zone: 2032 pages, LIFO batch:0
Built 1 zonelists in Zone order, mobility grouping off. ?Total pages: 2032
<5>Kernel command line: init=/bin/busybox console=ttyS mem=8M
<6>PID hash table entries: 32 (order: -5, 128 bytes)
<6>Dentry cache hash table entries: 1024 (order: 0, 4096 bytes)
<6>Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
<6>Memory: 8MB = 8MB total
<5>Memory: 7168k/7168k available, 1024k reserved, 0K highmem
<5>Virtual kernel memory layout:
? ?vector ?: 0x00000000 - 0x00001000 ? ( ? 4 kB)
? ?fixmap ?: 0xfff00000 - 0xfffe0000 ? ( 896 kB)
? ?vmalloc : 0x00000000 - 0xffffffff ? (4095 MB)
? ?lowmem ?: 0x60000000 - 0x60800000 ? ( ? 8 MB)
? ?modules : 0x60000000 - 0x60800000 ? ( ? 8 MB)
? ? ?.init : 0x60008000 - 0x6002f000 ? ( 156 kB)
? ? ?.text : 0x6002f000 - 0x600cb000 ? ( 624 kB)
? ? ?.data : 0x600d6000 - 0x600deb40 ? ( ?35 kB)
<6>Hierarchical RCU implementation.
<6>NR_IRQS:54
<6>console [ttyS0] enabled
<6>Calibrating delay loop... <c>3.82 BogoMIPS (lpj=19136)
Mount-cache hash table entries: 512
<6>Switching to clocksource timer3
<6>ttyS0 at MMIO 0x4000c000 (irq = 5) is a LM3S9B96 UARTx Port
<6>Freeing init memory: 156K
<3>BUG: scheduling while atomic: init/1/0xffff0003
[<60032b6d>] (unwind_backtrace+0x1/0x88) from [<600a1379>] (dump_stack+0xd/0x10)
[<600a1379>] (dump_stack+0xd/0x10) from [<60034ea5>] (__schedule_bug+0x35/0x40)
[<60034ea5>] (__schedule_bug+0x35/0x40) from [<600a17b1>] (schedule+0x2d1/0x2f4)
[<600a17b1>] (schedule+0x2d1/0x2f4) from [<6002f791>] (ret_slow_syscall+0x1/0xc)
<4>ptrace: can't handle thumb mode
<3>BUG: scheduling while atomic: init/1/0x60408008
[<60032b6d>] (unwind_backtrace+0x1/0x88) from [<600a1379>] (dump_stack+0xd/0x10)
[<600a1379>] (dump_stack+0xd/0x10) from [<60034ea5>] (__schedule_bug+0x35/0x40)
[<60034ea5>] (__schedule_bug+0x35/0x40) from [<600a17b1>] (schedule+0x2d1/0x2f4)
[<600a17b1>] (schedule+0x2d1/0x2f4) from [<6002f791>] (ret_slow_syscall+0x1/0xc)

Unhandled exception: IPSR = 00000003 LR = fffffff1
CPU: 0 ? ?Not tainted ?(2.6.33-arm1 #127)
PC is at account_user_time+0x4/0x60
LR is at account_process_tick+0x4d/0x58
pc : [<60038168>] ? ?lr : [<60038389>] ? ?psr: 01000223
sp : 60418038 ?ip : 000002cc ?fp : 00000000
r10: 01000000 ?r9 : 604d1f36 ?r8 : 00000013
r7 : 6041803c ?r6 : 068e7780 ?r5 : 00000001 ?r4 : ffafdad5
r3 : ffafdad5 ?r2 : 00000001 ?r1 : 00000001 ?r0 : ffafdad5

Att,
Fernando Akira Endo

^ permalink raw reply

* [PATCH v4] of/irq: introduce of_irq_init
From: Rob Herring @ 2011-09-27 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927015305.GD20588@ponder.secretlab.ca>

Grant,

On 09/26/2011 08:53 PM, Grant Likely wrote:
> On Mon, Sep 26, 2011 at 02:24:43PM -0500, Rob Herring wrote:
>> From: Rob Herring <rob.herring@calxeda.com>
>>
>> of_irq_init will scan the devicetree for matching interrupt controller
>> nodes. Then it calls an initialization function for each found controller
>> in the proper order with parent nodes initialized before child nodes.
>>
>> Based on initial pseudo code from Grant Likely.
>>
>> Changes in v4:
>> - Drop unnecessary empty list check
>> - Be more verbose on errors
>> - Simplify "if (!desc) WARN_ON(1)" to "if (WARN_ON(!desc))"
>>
>> Changes in v3:
>> - add missing kfree's found by Jamie
>> - Implement Grant's comments to simplify the init loop
>> - fix function comments
>>
>> Changes in v2:
>> - Complete re-write of list searching code from Grant Likely
>>
>> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
> 
> Looks good to me.  Merged.
> 

I'm dependent on this and things in rmk's tree for initial highbank
support, so should this series go in thru arm-soc tree? Several others
are dependent on this as well.

Rob

> g.
> 
>> ---
>>  drivers/of/irq.c       |  107 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/of_irq.h |    3 +
>>  2 files changed, 110 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
>> index 6a5b5e7..6d3dd39 100644
>> --- a/drivers/of/irq.c
>> +++ b/drivers/of/irq.c
>> @@ -19,10 +19,12 @@
>>   */
>>  
>>  #include <linux/errno.h>
>> +#include <linux/list.h>
>>  #include <linux/module.h>
>>  #include <linux/of.h>
>>  #include <linux/of_irq.h>
>>  #include <linux/string.h>
>> +#include <linux/slab.h>
>>  
>>  /* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
>>  #ifndef NO_IRQ
>> @@ -386,3 +388,108 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
>>  
>>  	return i;
>>  }
>> +
>> +struct intc_desc {
>> +	struct list_head	list;
>> +	struct device_node	*dev;
>> +	struct device_node	*interrupt_parent;
>> +};
>> +
>> +/**
>> + * of_irq_init - Scan and init matching interrupt controllers in DT
>> + * @matches: 0 terminated array of nodes to match and init function to call
>> + *
>> + * This function scans the device tree for matching interrupt controller nodes,
>> + * and calls their initialization functions in order with parents first.
>> + */
>> +void __init of_irq_init(const struct of_device_id *matches)
>> +{
>> +	struct device_node *np, *parent = NULL;
>> +	struct intc_desc *desc, *temp_desc;
>> +	struct list_head intc_desc_list, intc_parent_list;
>> +
>> +	INIT_LIST_HEAD(&intc_desc_list);
>> +	INIT_LIST_HEAD(&intc_parent_list);
>> +
>> +	for_each_matching_node(np, matches) {
>> +		if (!of_find_property(np, "interrupt-controller", NULL))
>> +			continue;
>> +		/*
>> +		 * Here, we allocate and populate an intc_desc with the node
>> +		 * pointer, interrupt-parent device_node etc.
>> +		 */
>> +		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
>> +		if (WARN_ON(!desc))
>> +			goto err;
>> +
>> +		desc->dev = np;
>> +		desc->interrupt_parent = of_irq_find_parent(np);
>> +		list_add_tail(&desc->list, &intc_desc_list);
>> +	}
>> +
>> +	/*
>> +	 * The root irq controller is the one without an interrupt-parent.
>> +	 * That one goes first, followed by the controllers that reference it,
>> +	 * followed by the ones that reference the 2nd level controllers, etc.
>> +	 */
>> +	while (!list_empty(&intc_desc_list)) {
>> +		/*
>> +		 * Process all controllers with the current 'parent'.
>> +		 * First pass will be looking for NULL as the parent.
>> +		 * The assumption is that NULL parent means a root controller.
>> +		 */
>> +		list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
>> +			const struct of_device_id *match;
>> +			int ret;
>> +			of_irq_init_cb_t irq_init_cb;
>> +
>> +			if (desc->interrupt_parent != parent)
>> +				continue;
>> +
>> +			list_del(&desc->list);
>> +			match = of_match_node(matches, desc->dev);
>> +			if (WARN(!match->data,
>> +			    "of_irq_init: no init function for %s\n",
>> +			    match->compatible)) {
>> +				kfree(desc);
>> +				continue;
>> +			}
>> +
>> +			pr_debug("of_irq_init: init %s @ %p, parent %p\n",
>> +				 match->compatible,
>> +				 desc->dev, desc->interrupt_parent);
>> +			irq_init_cb = match->data;
>> +			ret = irq_init_cb(desc->dev, desc->interrupt_parent);
>> +			if (ret) {
>> +				kfree(desc);
>> +				continue;
>> +			}
>> +
>> +			/*
>> +			 * This one is now set up; add it to the parent list so
>> +			 * its children can get processed in a subsequent pass.
>> +			 */
>> +			list_add_tail(&desc->list, &intc_parent_list);
>> +		}
>> +
>> +		/* Get the next pending parent that might have children */
>> +		desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
>> +		if (list_empty(&intc_parent_list) || !desc) {
>> +			pr_err("of_irq_init: children remain, but no parents\n");
>> +			break;
>> +		}
>> +		list_del(&desc->list);
>> +		parent = desc->dev;
>> +		kfree(desc);
>> +	}
>> +
>> +	list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
>> +		list_del(&desc->list);
>> +		kfree(desc);
>> +	}
>> +err:
>> +	list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
>> +		list_del(&desc->list);
>> +		kfree(desc);
>> +	}
>> +}
>> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
>> index cd2e61c..d0307ee 100644
>> --- a/include/linux/of_irq.h
>> +++ b/include/linux/of_irq.h
>> @@ -33,6 +33,8 @@ struct of_irq {
>>  	u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
>>  };
>>  
>> +typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
>> +
>>  /*
>>   * Workarounds only applied to 32bit powermac machines
>>   */
>> @@ -73,6 +75,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
>>  		struct resource *res, int nr_irqs);
>>  extern struct device_node *of_irq_find_parent(struct device_node *child);
>>  
>> +extern void of_irq_init(const struct of_device_id *matches);
>>  
>>  #endif /* CONFIG_OF_IRQ */
>>  #endif /* CONFIG_OF */
>> -- 
>> 1.7.5.4
>>

^ permalink raw reply

* [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
From: Roedel, Joerg @ 2011-09-27 13:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK=WgbahwY+7Ux-RjW2Tw9WBSwZnYuTMZ2NQASWyOXQ3zF6qFg@mail.gmail.com>

On Tue, Sep 27, 2011 at 08:26:29AM -0400, Ohad Ben-Cohen wrote:
> > With an unsigned long you can use plain and fast bit_ops instead of the
> > full bitmap functions.
> 
> Not sure I follow; the only bit operation I'm using while mapping is
> find_next_bit() (which is a bitops.h method).
> 
> What other faster variant are you referring to ?

You pass a pointer to an unsigned long for the page-size bitmap. This
allows to use an array of unsigned long. But a single unsigned long is
sufficient and you can use functions like ffs() and fls() together with
shifting. These functions often translate to a single intruction in the
binary. The find_next_bit function has much more overhead because it
needs to handle the array-of-ulong case.

	Joerg

-- 
AMD Operating System Research Center

Advanced Micro Devices GmbH Einsteinring 24 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Landkr. Muenchen; Registerger. Muenchen, HRB Nr. 43632

^ permalink raw reply

* Porting linux to Stellaris Cortex-M3
From: Fernando Endo @ 2011-09-27 13:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927101523.GF14237@e102109-lin.cambridge.arm.com>

2011/9/27 Catalin Marinas <catalin.marinas@arm.com>:
> On Tue, Sep 27, 2011 at 10:29:06AM +0100, Russell King - ARM Linux wrote:
>> On Mon, Sep 26, 2011 at 05:19:39PM -0300, Fernando Endo wrote:
>> > - BUG: scheduling while atomic: init/1/0xffff000a
>>
>> The last figure is the preempt count. ?This is made up from:
>>
>> ?* - bits 0-7 are the preemption count (max preemption depth: 256)
>> ?* - bits 8-15 are the softirq count (max # of softirqs: 256)
>> ?* - bits 16-25 are the hardirq count (max # of nested hardirqs: 1024)
>> ?* - bit 26 is the NMI_MASK
>> ?* - bit 28 is the PREEMPT_ACTIVE flag
>>
>> That seems to be saying that preemption has been disabled 10 times.
>> The upper 16-bits being all-ones seems to be rather insane - maybe
>> there's an additional __irq_exit() or irq_exit() call somewhere in
>> one of your code paths.
>
> Fernando, do you have CONFIG_PREEMPT enabled in your kernel? That's not
> currently possible with my Cortex-M3 port (see the "Exception handling"
> section in the M3 wiki page for an explanation).

I set CONFIG_PREEMPT_NONE after having this bug, my .config is
attached if you want to have a look
Thank you both for the advices, I'll take a look

Att,
Fernando Akira Endo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: config
Type: application/octet-stream
Size: 4715 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110927/1db6d40f/attachment.obj>

^ permalink raw reply

* Update: ARM Sub-Architecture Maintainers workshop at Kernel Summit 2011
From: Igor Grinberg @ 2011-09-27 13:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACxGe6vMLeHrN7jLB2=JYQON1ykOiWTeGiH8YXkUbguV0D-HEw@mail.gmail.com>

On 08/30/11 09:00, Grant Likely wrote:
> 
> Agenda proposals (Thanks to Nicolas and Olof):
> - DT bindings for GPIO and pin mux
> - the pin mux subsystem from linusw (especially if it is still RFC by
>  then)
> - progress with the single zImage work
> - presentation/status of the DMA and memory management work wrt CMA
>  (some SOC specific hacks should go away once this is available)
> - DT porting progress
> - boot architecture status
> - Report from Arnd on experiences from first arm-soc merge window
>   - what worked well and where's room for improvement?
>   - Any particular SoC workflow that should be tuned to make his life easier?
>   - Where are the gaps where he needs help right now?
>   - How did it work out for the SoC maintainers?
> 
> Still accepting more proposals.  Send me the topics you are burning to discuss.

One of the LPC2011's bottom lines was:
"We need more people involved in ARM maintainership to help
the sub-architecture maintainers do a better job on
review/consolidation/generalization/etc. of the code."

Despite the major goal of the DT to reduce the SoC and
board specific code to absolute minimum, there will still be cases
(e.g. discrete power management circuitry) when there is no
appropriate DT solution available and the board file
is a necessity. Also there are already many boards that will remain
and will not be converted to DT.

Bringing all the above together, I'd like to propose a new "job"
for maintaining board specific code on a cross-platform basis.

Pros:
1) There might (I have not checked this, but I'm sure there is) be
code in the existing board files (that are not likely to go away
at least in a couple of years) that can be consolidated and
may be even in a cross-platform manner.
2) Lower the work load from SoC maintainers (that don't have enough
time to care much about the board specific changes).
3) Some more eyes to review the newly submitted code.

Cons:
1) Resulting overhead for the code to go upstream.
2) Possible addition of merge conflicts.


I'd like to hear, what do you think of the above proposal?

-- 
Regards,
Igor.

^ 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