2011-05-30 14:44:12

by Shawn Guo

[permalink] [raw]
Subject: [PATCH 0/4] Move plat-mxc gpio driver into drivers/gpio

The patch set moves plat-mxc gpio driver into drivers/gpio. It's
based on the following tree, plus Sascha's i.MX consolidation
patches.

git://git.pengutronix.de/git/imx/linux-2.6.git imx-for-3.0

Shawn Guo (4):
gpio: gpio-mxc: add gpio driver for Freescale MXC architecture
ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc
ARM: mxc: migrate mach-imx gpio driver to gpio-mxc
ARM: mxc: remove plat-mxc/gpio driver

arch/arm/mach-imx/mm-imx1.c | 9 -
arch/arm/mach-imx/mm-imx21.c | 11 -
arch/arm/mach-imx/mm-imx25.c | 9 -
arch/arm/mach-imx/mm-imx27.c | 11 -
arch/arm/mach-imx/mm-imx31.c | 8 -
arch/arm/mach-imx/mm-imx35.c | 8 -
arch/arm/mach-mx5/devices.c | 64 ------
arch/arm/mach-mx5/mm-mx50.c | 11 -
arch/arm/mach-mx5/mm.c | 6 -
arch/arm/plat-mxc/Makefile | 2 +-
arch/arm/plat-mxc/devices.c | 11 +
arch/arm/plat-mxc/devices/Makefile | 1 +
arch/arm/plat-mxc/devices/platform-gpio-mxc.c | 113 ++++++++++
arch/arm/plat-mxc/include/mach/devices-common.h | 2 +
arch/arm/plat-mxc/include/mach/gpio.h | 27 ---
drivers/gpio/Makefile | 1 +
.../arm/plat-mxc/gpio.c => drivers/gpio/gpio-mxc.c | 218 +++++++++++++-------
17 files changed, 275 insertions(+), 237 deletions(-)


2011-05-30 14:44:22

by Shawn Guo

[permalink] [raw]
Subject: [PATCH 1/4] gpio: gpio-mxc: add gpio driver for Freescale MXC architecture

Add gpio-mxc driver by copying arch/arm/plat-mxc/gpio.c into
drivers/gpio with the following changes.

* Use readl/writel to replace mach-specific accessors
__raw_readl/__raw_writel

* Migrate to platform driver by adding .probe function

* Add a list to save all mx2 ports references, so that
mx2_gpio_irq_handler can walk through all interrupt status
registers

Signed-off-by: Shawn Guo <[email protected]>
---
arch/arm/plat-mxc/include/mach/gpio.h | 2 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-mxc.c | 423 +++++++++++++++++++++++++++++++++
3 files changed, 426 insertions(+), 0 deletions(-)
create mode 100644 drivers/gpio/gpio-mxc.c

diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index a2747f1..87bd4ef 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -37,7 +37,9 @@
#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)

struct mxc_gpio_port {
+ struct list_head node;
void __iomem *base;
+ int id;
int irq;
int irq_high;
int virtual_irq_start;
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b605f8e..060eb79 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -47,4 +47,5 @@ obj-$(CONFIG_GPIO_SX150X) += sx150x.o
obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o
obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o
obj-$(CONFIG_AB8500_GPIO) += ab8500-gpio.o
+obj-$(CONFIG_ARCH_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_TPS65910) += tps65910-gpio.o
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
new file mode 100644
index 0000000..df3df3f
--- /dev/null
+++ b/drivers/gpio/gpio-mxc.c
@@ -0,0 +1,423 @@
+/*
+ * MXC GPIO support. (c) 2008 Daniel Mack <[email protected]>
+ * Copyright 2008 Juergen Beisert, [email protected]
+ *
+ * Based on code from Freescale,
+ * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/hardware.h>
+#include <asm-generic/bug.h>
+
+/*
+ * MX2 has one interrupt *for all* gpio ports. The list is used
+ * to save the references to all ports, so that mx2_gpio_irq_handler
+ * can walk through all interrupt status registers.
+ */
+static LIST_HEAD(mxc_gpio_ports);
+
+#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2())
+
+#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00)
+#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04)
+#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08)
+#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C)
+#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10)
+#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14)
+#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18)
+
+#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0)
+#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1)
+#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2)
+#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3)
+#define GPIO_INT_NONE 0x4
+
+/* Note: This driver assumes 32 GPIOs are handled in one register */
+
+static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)
+{
+ writel(1 << index, port->base + GPIO_ISR);
+}
+
+static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,
+ int enable)
+{
+ u32 l;
+
+ l = readl(port->base + GPIO_IMR);
+ l = (l & (~(1 << index))) | (!!enable << index);
+ writel(l, port->base + GPIO_IMR);
+}
+
+static void gpio_ack_irq(struct irq_data *d)
+{
+ struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 gpio = irq_to_gpio(d->irq);
+ _clear_gpio_irqstatus(port, gpio & 0x1f);
+}
+
+static void gpio_mask_irq(struct irq_data *d)
+{
+ struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 gpio = irq_to_gpio(d->irq);
+ _set_gpio_irqenable(port, gpio & 0x1f, 0);
+}
+
+static void gpio_unmask_irq(struct irq_data *d)
+{
+ struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 gpio = irq_to_gpio(d->irq);
+ _set_gpio_irqenable(port, gpio & 0x1f, 1);
+}
+
+static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
+
+static int gpio_set_irq_type(struct irq_data *d, u32 type)
+{
+ u32 gpio = irq_to_gpio(d->irq);
+ struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 bit, val;
+ int edge;
+ void __iomem *reg = port->base;
+
+ port->both_edges &= ~(1 << (gpio & 31));
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ edge = GPIO_INT_RISE_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ edge = GPIO_INT_FALL_EDGE;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ val = mxc_gpio_get(&port->chip, gpio & 31);
+ if (val) {
+ edge = GPIO_INT_LOW_LEV;
+ pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
+ } else {
+ edge = GPIO_INT_HIGH_LEV;
+ pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
+ }
+ port->both_edges |= 1 << (gpio & 31);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ edge = GPIO_INT_LOW_LEV;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ edge = GPIO_INT_HIGH_LEV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+ bit = gpio & 0xf;
+ val = readl(reg) & ~(0x3 << (bit << 1));
+ writel(val | (edge << (bit << 1)), reg);
+ _clear_gpio_irqstatus(port, gpio & 0x1f);
+
+ return 0;
+}
+
+static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
+{
+ void __iomem *reg = port->base;
+ u32 bit, val;
+ int edge;
+
+ reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
+ bit = gpio & 0xf;
+ val = readl(reg);
+ edge = (val >> (bit << 1)) & 3;
+ val &= ~(0x3 << (bit << 1));
+ if (edge == GPIO_INT_HIGH_LEV) {
+ edge = GPIO_INT_LOW_LEV;
+ pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
+ } else if (edge == GPIO_INT_LOW_LEV) {
+ edge = GPIO_INT_HIGH_LEV;
+ pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
+ } else {
+ pr_err("mxc: invalid configuration for GPIO %d: %x\n",
+ gpio, edge);
+ return;
+ }
+ writel(val | (edge << (bit << 1)), reg);
+}
+
+/* handle 32 interrupts in one status register */
+static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
+{
+ u32 gpio_irq_no_base = port->virtual_irq_start;
+
+ while (irq_stat != 0) {
+ int irqoffset = fls(irq_stat) - 1;
+
+ if (port->both_edges & (1 << irqoffset))
+ mxc_flip_edge(port, irqoffset);
+
+ generic_handle_irq(gpio_irq_no_base + irqoffset);
+
+ irq_stat &= ~(1 << irqoffset);
+ }
+}
+
+/* MX1 and MX3 has one interrupt *per* gpio port */
+static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ u32 irq_stat;
+ struct mxc_gpio_port *port = irq_get_handler_data(irq);
+
+ irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
+
+ mxc_gpio_irq_handler(port, irq_stat);
+}
+
+/* MX2 has one interrupt *for all* gpio ports */
+static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+{
+ u32 irq_msk, irq_stat;
+ struct mxc_gpio_port *port;
+
+ /* walk through all interrupt status registers */
+ list_for_each_entry(port, &mxc_gpio_ports, node) {
+ irq_msk = readl(port->base + GPIO_IMR);
+ if (!irq_msk)
+ continue;
+
+ irq_stat =readl(port->base + GPIO_ISR) & irq_msk;
+ if (irq_stat)
+ mxc_gpio_irq_handler(port, irq_stat);
+ }
+}
+
+/*
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
+ * While system is running, all registered GPIO interrupts need to have
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
+ * need to have wake-up enabled.
+ * @param irq interrupt source number
+ * @param enable enable as wake-up if equal to non-zero
+ * @return This function returns 0 on success.
+ */
+static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
+{
+ u32 gpio = irq_to_gpio(d->irq);
+ u32 gpio_idx = gpio & 0x1F;
+ struct mxc_gpio_port *port = irq_data_get_irq_chip_data(d);
+
+ if (enable) {
+ if (port->irq_high && (gpio_idx >= 16))
+ enable_irq_wake(port->irq_high);
+ else
+ enable_irq_wake(port->irq);
+ } else {
+ if (port->irq_high && (gpio_idx >= 16))
+ disable_irq_wake(port->irq_high);
+ else
+ disable_irq_wake(port->irq);
+ }
+
+ return 0;
+}
+
+static struct irq_chip gpio_irq_chip = {
+ .name = "GPIO",
+ .irq_ack = gpio_ack_irq,
+ .irq_mask = gpio_mask_irq,
+ .irq_unmask = gpio_unmask_irq,
+ .irq_set_type = gpio_set_irq_type,
+ .irq_set_wake = gpio_set_wake_irq,
+};
+
+static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
+ int dir)
+{
+ struct mxc_gpio_port *port =
+ container_of(chip, struct mxc_gpio_port, chip);
+ u32 l;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ l = readl(port->base + GPIO_GDIR);
+ if (dir)
+ l |= 1 << offset;
+ else
+ l &= ~(1 << offset);
+ writel(l, port->base + GPIO_GDIR);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct mxc_gpio_port *port =
+ container_of(chip, struct mxc_gpio_port, chip);
+ void __iomem *reg = port->base + GPIO_DR;
+ u32 l;
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ l = (readl(reg) & (~(1 << offset))) | (!!value << offset);
+ writel(l, reg);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct mxc_gpio_port *port =
+ container_of(chip, struct mxc_gpio_port, chip);
+
+ return (readl(port->base + GPIO_PSR) >> offset) & 1;
+}
+
+static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ _set_gpio_direction(chip, offset, 0);
+ return 0;
+}
+
+static int mxc_gpio_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ mxc_gpio_set(chip, offset, value);
+ _set_gpio_direction(chip, offset, 1);
+ return 0;
+}
+
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static int __devinit mxc_gpio_probe(struct platform_device *pdev)
+{
+ struct mxc_gpio_port *port;
+ struct resource *iores;
+ int err, i;
+
+ port = kzalloc(sizeof(struct mxc_gpio_port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ port->id = pdev->id;
+ port->virtual_irq_start = MXC_GPIO_IRQ_START + port->id * 32;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores) {
+ err = -ENODEV;
+ goto out_kfree;
+ }
+
+ if (!request_mem_region(iores->start, resource_size(iores),
+ pdev->name)) {
+ err = -EBUSY;
+ goto out_kfree;
+ }
+
+ port->base = ioremap(iores->start, resource_size(iores));
+ if (!port->base) {
+ err = -ENOMEM;
+ goto out_release_mem;
+ }
+
+ port->irq_high = platform_get_irq(pdev, 1);
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0) {
+ err = -EINVAL;
+ goto out_iounmap;
+ }
+
+ /* disable the interrupt and clear the status */
+ writel(0, port->base + GPIO_IMR);
+ writel(~0, port->base + GPIO_ISR);
+
+ for (i = port->virtual_irq_start;
+ i < port->virtual_irq_start + 32; i++) {
+ irq_set_lockdep_class(i, &gpio_lock_class);
+ irq_set_chip_and_handler(i, &gpio_irq_chip, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ irq_set_chip_data(i, port);
+ }
+
+ if (cpu_is_mx2()) {
+ /* setup one handler for all GPIO interrupts */
+ if (port->id == 0)
+ irq_set_chained_handler(port->irq,
+ mx2_gpio_irq_handler);
+ } else {
+ /* setup one handler for each entry */
+ irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
+ irq_set_handler_data(port->irq, port);
+ if (port->irq_high > 0) {
+ /* setup handler for GPIO 16 to 31 */
+ irq_set_chained_handler(port->irq_high,
+ mx3_gpio_irq_handler);
+ irq_set_handler_data(port->irq_high, port);
+ }
+ }
+
+ /* register gpio chip */
+ port->chip.direction_input = mxc_gpio_direction_input;
+ port->chip.direction_output = mxc_gpio_direction_output;
+ port->chip.get = mxc_gpio_get;
+ port->chip.set = mxc_gpio_set;
+ port->chip.base = port->id * 32;
+ port->chip.ngpio = 32;
+
+ spin_lock_init(&port->lock);
+
+ err = gpiochip_add(&port->chip);
+ if (err)
+ goto out_iounmap;
+
+ list_add_tail(&port->node, &mxc_gpio_ports);
+
+ return 0;
+
+out_iounmap:
+ iounmap(port->base);
+out_release_mem:
+ release_mem_region(iores->start, resource_size(iores));
+out_kfree:
+ kfree(port);
+ dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
+ return err;
+}
+
+static struct platform_driver mxc_gpio_driver = {
+ .driver = {
+ .name = "gpio-mxc",
+ },
+ .probe = mxc_gpio_probe,
+};
+
+static int __init gpio_mxc_init(void)
+{
+ return platform_driver_register(&mxc_gpio_driver);
+}
+postcore_initcall(gpio_mxc_init);
+
+MODULE_AUTHOR("Freescale Semiconductor, "
+ "Daniel Mack <danielncaiaq.de>, "
+ "Juergen Beisert <[email protected]>");
+MODULE_DESCRIPTION("Freescale MXC GPIO");
+MODULE_LICENSE("GPL");
--
1.7.4.1

2011-05-30 14:44:32

by Shawn Guo

[permalink] [raw]
Subject: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

It adds platform device for drivers/gpio/gpio-mxc, and migrates
mx50/mx51/mx53 gpio driver to gpio-mxc.

Signed-off-by: Shawn Guo <[email protected]>
---
arch/arm/mach-mx5/devices.c | 64 ---------------------
arch/arm/mach-mx5/mm-mx50.c | 11 ----
arch/arm/mach-mx5/mm.c | 6 --
arch/arm/plat-mxc/devices.c | 11 ++++
arch/arm/plat-mxc/devices/Makefile | 1 +
arch/arm/plat-mxc/devices/platform-gpio-mxc.c | 69 +++++++++++++++++++++++
arch/arm/plat-mxc/include/mach/devices-common.h | 2 +
7 files changed, 83 insertions(+), 81 deletions(-)
create mode 100644 arch/arm/plat-mxc/devices/platform-gpio-mxc.c

diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 153ada5..371ca8c 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -12,7 +12,6 @@

#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/imx-uart.h>
#include <mach/irqs.h>
@@ -119,66 +118,3 @@ struct platform_device mxc_usbh2_device = {
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
-
-static struct mxc_gpio_port mxc_gpio_ports[] = {
- {
- .chip.label = "gpio-0",
- .base = MX51_IO_ADDRESS(MX51_GPIO1_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO1_LOW,
- .irq_high = MX51_MXC_INT_GPIO1_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START
- },
- {
- .chip.label = "gpio-1",
- .base = MX51_IO_ADDRESS(MX51_GPIO2_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO2_LOW,
- .irq_high = MX51_MXC_INT_GPIO2_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 1
- },
- {
- .chip.label = "gpio-2",
- .base = MX51_IO_ADDRESS(MX51_GPIO3_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO3_LOW,
- .irq_high = MX51_MXC_INT_GPIO3_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 2
- },
- {
- .chip.label = "gpio-3",
- .base = MX51_IO_ADDRESS(MX51_GPIO4_BASE_ADDR),
- .irq = MX51_MXC_INT_GPIO4_LOW,
- .irq_high = MX51_MXC_INT_GPIO4_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 3
- },
- {
- .chip.label = "gpio-4",
- .base = MX53_IO_ADDRESS(MX53_GPIO5_BASE_ADDR),
- .irq = MX53_INT_GPIO5_LOW,
- .irq_high = MX53_INT_GPIO5_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 4
- },
- {
- .chip.label = "gpio-5",
- .base = MX53_IO_ADDRESS(MX53_GPIO6_BASE_ADDR),
- .irq = MX53_INT_GPIO6_LOW,
- .irq_high = MX53_INT_GPIO6_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 5
- },
- {
- .chip.label = "gpio-6",
- .base = MX53_IO_ADDRESS(MX53_GPIO7_BASE_ADDR),
- .irq = MX53_INT_GPIO7_LOW,
- .irq_high = MX53_INT_GPIO7_HIGH,
- .virtual_irq_start = MXC_GPIO_IRQ_START + 32 * 6
- },
-};
-
-int __init imx51_register_gpios(void)
-{
- return mxc_gpio_init(mxc_gpio_ports, 4);
-}
-
-int __init imx53_register_gpios(void)
-{
- return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports));
-}
-
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
index b9c363b..e1377ca 100644
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ b/arch/arm/mach-mx5/mm-mx50.c
@@ -26,7 +26,6 @@
#include <mach/hardware.h>
#include <mach/common.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>

/*
@@ -56,17 +55,7 @@ void __init imx50_init_early(void)
mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
}

-static struct mxc_gpio_port imx50_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-};
-
void __init mx50_init_irq(void)
{
tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
- mxc_gpio_init(imx50_gpio_ports, ARRAY_SIZE(imx50_gpio_ports));
}
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index ff55730..ccc6ceb 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -69,8 +69,6 @@ void __init imx53_init_early(void)
mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
}

-int imx51_register_gpios(void);
-
void __init mx51_init_irq(void)
{
unsigned long tzic_addr;
@@ -86,11 +84,8 @@ void __init mx51_init_irq(void)
panic("unable to map TZIC interrupt controller\n");

tzic_init_irq(tzic_virt);
- imx51_register_gpios();
}

-int imx53_register_gpios(void);
-
void __init mx53_init_irq(void)
{
unsigned long tzic_addr;
@@ -103,5 +98,4 @@ void __init mx53_init_irq(void)
panic("unable to map TZIC interrupt controller\n");

tzic_init_irq(tzic_virt);
- imx53_register_gpios();
}
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index eee1b60..fb166b2 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -89,3 +89,14 @@ err:

return pdev;
}
+
+struct device mxc_aips_bus = {
+ .init_name = "mxc_aips",
+ .parent = &platform_bus,
+};
+
+static int __init mxc_device_init(void)
+{
+ return device_register(&mxc_aips_bus);
+}
+core_initcall(mxc_device_init);
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index ad2922a..b41bf97 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FEC) += platform-fec.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
+obj-y += platform-gpio-mxc.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
new file mode 100644
index 0000000..3b10da0
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Limited
+ *
+ * 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/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+static struct platform_device *__init mxc_add_gpio(int id,
+ resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
+{
+ struct resource res[] = {
+ {
+ .start = iobase,
+ .end = iobase + iosize - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = irq_high,
+ .end = irq_high,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+
+ return platform_device_register_resndata(&mxc_aips_bus,
+ "gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0);
+}
+
+static int __init mxc_add_mxc_gpio(void)
+{
+ if (cpu_is_mx50()) {
+ mxc_add_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+ mxc_add_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+ mxc_add_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+ mxc_add_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+ mxc_add_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+ mxc_add_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+ }
+
+ if (cpu_is_mx51()) {
+ mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
+ mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
+ mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
+ mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
+ }
+
+ if (cpu_is_mx53()) {
+ mxc_add_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+ mxc_add_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+ mxc_add_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+ mxc_add_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+ mxc_add_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+ mxc_add_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+ mxc_add_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+ }
+
+ return 0;
+}
+postcore_initcall(mxc_add_mxc_gpio);
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index fa84773..03f6266 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -10,6 +10,8 @@
#include <linux/platform_device.h>
#include <linux/init.h>

+extern struct device mxc_aips_bus;
+
struct platform_device *imx_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,
--
1.7.4.1

2011-05-30 14:44:45

by Shawn Guo

[permalink] [raw]
Subject: [PATCH 3/4] ARM: mxc: migrate mach-imx gpio driver to gpio-mxc

It migrates mx1/mx21/mx25/mx27/mx31/mx35 gpio driver to
drivers/gpio/gpio-mxc.

Signed-off-by: Shawn Guo <[email protected]>
---
arch/arm/mach-imx/mm-imx1.c | 9 -----
arch/arm/mach-imx/mm-imx21.c | 11 ------
arch/arm/mach-imx/mm-imx25.c | 9 -----
arch/arm/mach-imx/mm-imx27.c | 11 ------
arch/arm/mach-imx/mm-imx31.c | 8 ----
arch/arm/mach-imx/mm-imx35.c | 8 ----
arch/arm/plat-mxc/devices/platform-gpio-mxc.c | 44 +++++++++++++++++++++++++
7 files changed, 44 insertions(+), 56 deletions(-)

diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 2e482ba..621ee4c 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -23,7 +23,6 @@

#include <mach/common.h>
#include <mach/hardware.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>

@@ -44,15 +43,7 @@ void __init imx1_init_early(void)
MX1_NUM_GPIO_PORT);
}

-static struct mxc_gpio_port imx1_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
- DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
-};
-
void __init mx1_init_irq(void)
{
mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
- mxc_gpio_init(imx1_gpio_ports, ARRAY_SIZE(imx1_gpio_ports));
}
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index 7a0c500..a00ffe1 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -24,7 +24,6 @@
#include <mach/common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>

@@ -70,17 +69,7 @@ void __init imx21_init_early(void)
MX21_NUM_GPIO_PORT);
}

-static struct mxc_gpio_port imx21_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
- DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
- DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
- DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
- DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
- DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
-};
-
void __init mx21_init_irq(void)
{
mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
- mxc_gpio_init(imx21_gpio_ports, ARRAY_SIZE(imx21_gpio_ports));
}
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 02f7b5c..3866c88 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -27,7 +27,6 @@
#include <mach/hardware.h>
#include <mach/mx25.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>

/*
@@ -57,16 +56,8 @@ void __init imx25_init_early(void)
mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
}

-static struct mxc_gpio_port imx25_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
- DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
-};
-
void __init mx25_init_irq(void)
{
mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
- mxc_gpio_init(imx25_gpio_ports, ARRAY_SIZE(imx25_gpio_ports));
}

diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index a6761a3..b98eb7a 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -24,7 +24,6 @@
#include <mach/common.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>
#include <mach/iomux-v1.h>

@@ -70,17 +69,7 @@ void __init imx27_init_early(void)
MX27_NUM_GPIO_PORT);
}

-static struct mxc_gpio_port imx27_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
- DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
- DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
- DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
- DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
- DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
-};
-
void __init mx27_init_irq(void)
{
mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
- mxc_gpio_init(imx27_gpio_ports, ARRAY_SIZE(imx27_gpio_ports));
}
diff --git a/arch/arm/mach-imx/mm-imx31.c b/arch/arm/mach-imx/mm-imx31.c
index 86b9b45..afcca7b 100644
--- a/arch/arm/mach-imx/mm-imx31.c
+++ b/arch/arm/mach-imx/mm-imx31.c
@@ -26,7 +26,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>

static struct map_desc mx31_io_desc[] __initdata = {
@@ -53,14 +52,7 @@ void __init imx31_init_early(void)
mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
}

-static struct mxc_gpio_port imx31_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
-};
-
void __init mx31_init_irq(void)
{
mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
- mxc_gpio_init(imx31_gpio_ports, ARRAY_SIZE(imx31_gpio_ports));
}
diff --git a/arch/arm/mach-imx/mm-imx35.c b/arch/arm/mach-imx/mm-imx35.c
index c880e6d..ac9d031 100644
--- a/arch/arm/mach-imx/mm-imx35.c
+++ b/arch/arm/mach-imx/mm-imx35.c
@@ -27,7 +27,6 @@
#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/iomux-v3.h>
-#include <mach/gpio.h>
#include <mach/irqs.h>

static struct map_desc mx35_io_desc[] __initdata = {
@@ -50,14 +49,7 @@ void __init imx35_init_early(void)
mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
}

-static struct mxc_gpio_port imx35_gpio_ports[] = {
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
- DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
-};
-
void __init mx35_init_irq(void)
{
mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
- mxc_gpio_init(imx35_gpio_ports, ARRAY_SIZE(imx35_gpio_ports));
}
diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
index 3b10da0..07fee19 100644
--- a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
+++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
@@ -38,6 +38,50 @@ static struct platform_device *__init mxc_add_gpio(int id,

static int __init mxc_add_mxc_gpio(void)
{
+ if (cpu_is_mx1()) {
+ mxc_add_gpio(0, MX1_GPIO1_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTA, 0);
+ mxc_add_gpio(1, MX1_GPIO2_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTB, 0);
+ mxc_add_gpio(2, MX1_GPIO3_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTC, 0);
+ mxc_add_gpio(3, MX1_GPIO4_BASE_ADDR, SZ_4K, MX1_GPIO_INT_PORTD, 0);
+ }
+
+ if (cpu_is_mx21()) {
+ mxc_add_gpio(0, MX21_GPIO1_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ mxc_add_gpio(1, MX21_GPIO2_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ mxc_add_gpio(2, MX21_GPIO3_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ mxc_add_gpio(3, MX21_GPIO4_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ mxc_add_gpio(4, MX21_GPIO5_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ mxc_add_gpio(5, MX21_GPIO6_BASE_ADDR, SZ_4K, MX21_INT_GPIO, 0);
+ }
+
+ if (cpu_is_mx25()) {
+ mxc_add_gpio(0, MX25_GPIO1_BASE_ADDR, SZ_16K, MX25_INT_GPIO1, 0);
+ mxc_add_gpio(1, MX25_GPIO2_BASE_ADDR, SZ_16K, MX25_INT_GPIO2, 0);
+ mxc_add_gpio(2, MX25_GPIO3_BASE_ADDR, SZ_16K, MX25_INT_GPIO3, 0);
+ mxc_add_gpio(3, MX25_GPIO4_BASE_ADDR, SZ_16K, MX25_INT_GPIO4, 0);
+ }
+
+ if (cpu_is_mx27()) {
+ mxc_add_gpio(0, MX27_GPIO1_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ mxc_add_gpio(1, MX27_GPIO2_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ mxc_add_gpio(2, MX27_GPIO3_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ mxc_add_gpio(3, MX27_GPIO4_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ mxc_add_gpio(4, MX27_GPIO5_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ mxc_add_gpio(5, MX27_GPIO6_BASE_ADDR, SZ_4K, MX27_INT_GPIO, 0);
+ }
+
+ if (cpu_is_mx31()) {
+ mxc_add_gpio(0, MX31_GPIO1_BASE_ADDR, SZ_16K, MX31_INT_GPIO1, 0);
+ mxc_add_gpio(1, MX31_GPIO2_BASE_ADDR, SZ_16K, MX31_INT_GPIO2, 0);
+ mxc_add_gpio(2, MX31_GPIO3_BASE_ADDR, SZ_16K, MX31_INT_GPIO3, 0);
+ }
+
+ if (cpu_is_mx35()) {
+ mxc_add_gpio(0, MX35_GPIO1_BASE_ADDR, SZ_16K, MX35_INT_GPIO1, 0);
+ mxc_add_gpio(1, MX35_GPIO2_BASE_ADDR, SZ_16K, MX35_INT_GPIO2, 0);
+ mxc_add_gpio(2, MX35_GPIO3_BASE_ADDR, SZ_16K, MX35_INT_GPIO3, 0);
+ }
+
if (cpu_is_mx50()) {
mxc_add_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
mxc_add_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
--
1.7.4.1

2011-05-30 14:44:58

by Shawn Guo

[permalink] [raw]
Subject: [PATCH 4/4] ARM: mxc: remove plat-mxc/gpio driver

With all users of plat-mxc/gpio migrated to drivers/gpio/gpio-mxc,
plat-mxc/gpio can be removed now. And plat-mxc/include/mach/gpio.h
can also be cleaned up as below.

* Remove the helper macros for gpio ports definition
* Move "struct mxc_gpio_port" into drivers/gpio/gpio-mxc.c, as it's
not needed to be public at all

Signed-off-by: Shawn Guo <[email protected]>
---
arch/arm/plat-mxc/Makefile | 2 +-
arch/arm/plat-mxc/gpio.c | 361 ---------------------------------
arch/arm/plat-mxc/include/mach/gpio.h | 29 ---
drivers/gpio/gpio-mxc.c | 12 +
4 files changed, 13 insertions(+), 391 deletions(-)
delete mode 100644 arch/arm/plat-mxc/gpio.c

diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index a138787..d53c35f 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
#

# Common support
-obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
+obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o

# MX51 uses the TZIC interrupt controller, older platforms use AVIC
obj-$(CONFIG_MXC_TZIC) += tzic.o
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
deleted file mode 100644
index 6cd6d7f..0000000
--- a/arch/arm/plat-mxc/gpio.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * MXC GPIO support. (c) 2008 Daniel Mack <[email protected]>
- * Copyright 2008 Juergen Beisert, [email protected]
- *
- * Based on code from Freescale,
- * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <mach/hardware.h>
-#include <asm-generic/bug.h>
-
-static struct mxc_gpio_port *mxc_gpio_ports;
-static int gpio_table_size;
-
-#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2())
-
-#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00)
-#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04)
-#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08)
-#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C)
-#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10)
-#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14)
-#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18)
-
-#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0)
-#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1)
-#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2)
-#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3)
-#define GPIO_INT_NONE 0x4
-
-/* Note: This driver assumes 32 GPIOs are handled in one register */
-
-static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index)
-{
- __raw_writel(1 << index, port->base + GPIO_ISR);
-}
-
-static void _set_gpio_irqenable(struct mxc_gpio_port *port, u32 index,
- int enable)
-{
- u32 l;
-
- l = __raw_readl(port->base + GPIO_IMR);
- l = (l & (~(1 << index))) | (!!enable << index);
- __raw_writel(l, port->base + GPIO_IMR);
-}
-
-static void gpio_ack_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _clear_gpio_irqstatus(&mxc_gpio_ports[gpio / 32], gpio & 0x1f);
-}
-
-static void gpio_mask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 0);
-}
-
-static void gpio_unmask_irq(struct irq_data *d)
-{
- u32 gpio = irq_to_gpio(d->irq);
- _set_gpio_irqenable(&mxc_gpio_ports[gpio / 32], gpio & 0x1f, 1);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset);
-
-static int gpio_set_irq_type(struct irq_data *d, u32 type)
-{
- u32 gpio = irq_to_gpio(d->irq);
- struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
- u32 bit, val;
- int edge;
- void __iomem *reg = port->base;
-
- port->both_edges &= ~(1 << (gpio & 31));
- switch (type) {
- case IRQ_TYPE_EDGE_RISING:
- edge = GPIO_INT_RISE_EDGE;
- break;
- case IRQ_TYPE_EDGE_FALLING:
- edge = GPIO_INT_FALL_EDGE;
- break;
- case IRQ_TYPE_EDGE_BOTH:
- val = mxc_gpio_get(&port->chip, gpio & 31);
- if (val) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: set GPIO %d to low trigger\n", gpio);
- } else {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
- }
- port->both_edges |= 1 << (gpio & 31);
- break;
- case IRQ_TYPE_LEVEL_LOW:
- edge = GPIO_INT_LOW_LEV;
- break;
- case IRQ_TYPE_LEVEL_HIGH:
- edge = GPIO_INT_HIGH_LEV;
- break;
- default:
- return -EINVAL;
- }
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = __raw_readl(reg) & ~(0x3 << (bit << 1));
- __raw_writel(val | (edge << (bit << 1)), reg);
- _clear_gpio_irqstatus(port, gpio & 0x1f);
-
- return 0;
-}
-
-static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
-{
- void __iomem *reg = port->base;
- u32 bit, val;
- int edge;
-
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = __raw_readl(reg);
- edge = (val >> (bit << 1)) & 3;
- val &= ~(0x3 << (bit << 1));
- if (edge == GPIO_INT_HIGH_LEV) {
- edge = GPIO_INT_LOW_LEV;
- pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
- } else if (edge == GPIO_INT_LOW_LEV) {
- edge = GPIO_INT_HIGH_LEV;
- pr_debug("mxc: switch GPIO %d to high trigger\n", gpio);
- } else {
- pr_err("mxc: invalid configuration for GPIO %d: %x\n",
- gpio, edge);
- return;
- }
- __raw_writel(val | (edge << (bit << 1)), reg);
-}
-
-/* handle 32 interrupts in one status register */
-static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
-{
- u32 gpio_irq_no_base = port->virtual_irq_start;
-
- while (irq_stat != 0) {
- int irqoffset = fls(irq_stat) - 1;
-
- if (port->both_edges & (1 << irqoffset))
- mxc_flip_edge(port, irqoffset);
-
- generic_handle_irq(gpio_irq_no_base + irqoffset);
-
- irq_stat &= ~(1 << irqoffset);
- }
-}
-
-/* MX1 and MX3 has one interrupt *per* gpio port */
-static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- u32 irq_stat;
- struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
- irq_stat = __raw_readl(port->base + GPIO_ISR) &
- __raw_readl(port->base + GPIO_IMR);
-
- mxc_gpio_irq_handler(port, irq_stat);
-}
-
-/* MX2 has one interrupt *for all* gpio ports */
-static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
-{
- int i;
- u32 irq_msk, irq_stat;
- struct mxc_gpio_port *port = irq_get_handler_data(irq);
-
- /* walk through all interrupt status registers */
- for (i = 0; i < gpio_table_size; i++) {
- irq_msk = __raw_readl(port[i].base + GPIO_IMR);
- if (!irq_msk)
- continue;
-
- irq_stat = __raw_readl(port[i].base + GPIO_ISR) & irq_msk;
- if (irq_stat)
- mxc_gpio_irq_handler(&port[i], irq_stat);
- }
-}
-
-/*
- * Set interrupt number "irq" in the GPIO as a wake-up source.
- * While system is running, all registered GPIO interrupts need to have
- * wake-up enabled. When system is suspended, only selected GPIO interrupts
- * need to have wake-up enabled.
- * @param irq interrupt source number
- * @param enable enable as wake-up if equal to non-zero
- * @return This function returns 0 on success.
- */
-static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
-{
- u32 gpio = irq_to_gpio(d->irq);
- u32 gpio_idx = gpio & 0x1F;
- struct mxc_gpio_port *port = &mxc_gpio_ports[gpio / 32];
-
- if (enable) {
- if (port->irq_high && (gpio_idx >= 16))
- enable_irq_wake(port->irq_high);
- else
- enable_irq_wake(port->irq);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- disable_irq_wake(port->irq_high);
- else
- disable_irq_wake(port->irq);
- }
-
- return 0;
-}
-
-static struct irq_chip gpio_irq_chip = {
- .name = "GPIO",
- .irq_ack = gpio_ack_irq,
- .irq_mask = gpio_mask_irq,
- .irq_unmask = gpio_unmask_irq,
- .irq_set_type = gpio_set_irq_type,
- .irq_set_wake = gpio_set_wake_irq,
-};
-
-static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
- int dir)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
- u32 l;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- l = __raw_readl(port->base + GPIO_GDIR);
- if (dir)
- l |= 1 << offset;
- else
- l &= ~(1 << offset);
- __raw_writel(l, port->base + GPIO_GDIR);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void mxc_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
- void __iomem *reg = port->base + GPIO_DR;
- u32 l;
- unsigned long flags;
-
- spin_lock_irqsave(&port->lock, flags);
- l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);
- __raw_writel(l, reg);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int mxc_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct mxc_gpio_port *port =
- container_of(chip, struct mxc_gpio_port, chip);
-
- return (__raw_readl(port->base + GPIO_PSR) >> offset) & 1;
-}
-
-static int mxc_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- _set_gpio_direction(chip, offset, 0);
- return 0;
-}
-
-static int mxc_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
-{
- mxc_gpio_set(chip, offset, value);
- _set_gpio_direction(chip, offset, 1);
- return 0;
-}
-
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
-{
- int i, j;
-
- /* save for local usage */
- mxc_gpio_ports = port;
- gpio_table_size = cnt;
-
- printk(KERN_INFO "MXC GPIO hardware\n");
-
- for (i = 0; i < cnt; i++) {
- /* disable the interrupt and clear the status */
- __raw_writel(0, port[i].base + GPIO_IMR);
- __raw_writel(~0, port[i].base + GPIO_ISR);
- for (j = port[i].virtual_irq_start;
- j < port[i].virtual_irq_start + 32; j++) {
- irq_set_lockdep_class(j, &gpio_lock_class);
- irq_set_chip_and_handler(j, &gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(j, IRQF_VALID);
- }
-
- /* register gpio chip */
- port[i].chip.direction_input = mxc_gpio_direction_input;
- port[i].chip.direction_output = mxc_gpio_direction_output;
- port[i].chip.get = mxc_gpio_get;
- port[i].chip.set = mxc_gpio_set;
- port[i].chip.base = i * 32;
- port[i].chip.ngpio = 32;
-
- spin_lock_init(&port[i].lock);
-
- /* its a serious configuration bug when it fails */
- BUG_ON( gpiochip_add(&port[i].chip) < 0 );
-
- if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
- /* setup one handler for each entry */
- irq_set_chained_handler(port[i].irq,
- mx3_gpio_irq_handler);
- irq_set_handler_data(port[i].irq, &port[i]);
- if (port[i].irq_high) {
- /* setup handler for GPIO 16 to 31 */
- irq_set_chained_handler(port[i].irq_high,
- mx3_gpio_irq_handler);
- irq_set_handler_data(port[i].irq_high,
- &port[i]);
- }
- }
- }
-
- if (cpu_is_mx2()) {
- /* setup one handler for all GPIO interrupts */
- irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
- irq_set_handler_data(port[0].irq, port);
- }
-
- return 0;
-}
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 87bd4ef..31c820c 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -36,33 +36,4 @@
#define gpio_to_irq(gpio) (MXC_GPIO_IRQ_START + (gpio))
#define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)

-struct mxc_gpio_port {
- struct list_head node;
- void __iomem *base;
- int id;
- int irq;
- int irq_high;
- int virtual_irq_start;
- struct gpio_chip chip;
- u32 both_edges;
- spinlock_t lock;
-};
-
-#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high) \
- { \
- .chip.label = "gpio-" #_id, \
- .irq = _irq, \
- .irq_high = _irq_high, \
- .base = soc ## _IO_ADDRESS( \
- soc ## _GPIO ## _hwid ## _BASE_ADDR), \
- .virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32, \
- }
-
-#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq) \
- DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
-#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid) \
- DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
-
-int mxc_gpio_init(struct mxc_gpio_port*, int);
-
#endif
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index df3df3f..065b5c0 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -29,6 +29,18 @@
#include <mach/hardware.h>
#include <asm-generic/bug.h>

+struct mxc_gpio_port {
+ struct list_head node;
+ void __iomem *base;
+ int id;
+ int irq;
+ int irq_high;
+ int virtual_irq_start;
+ struct gpio_chip chip;
+ u32 both_edges;
+ spinlock_t lock;
+};
+
/*
* MX2 has one interrupt *for all* gpio ports. The list is used
* to save the references to all ports, so that mx2_gpio_irq_handler
--
1.7.4.1

2011-05-31 00:16:31

by Olof Johansson

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

Hi,

On Mon, May 30, 2011 at 10:52:17PM +0800, Shawn Guo wrote:
> It adds platform device for drivers/gpio/gpio-mxc, and migrates
> mx50/mx51/mx53 gpio driver to gpio-mxc.
>

[...]

> diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
> new file mode 100644
> index 0000000..3b10da0
> --- /dev/null
> +++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
> @@ -0,0 +1,69 @@
> +/*
> + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright 2011 Linaro Limited
> + *
> + * 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/compiler.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/devices-common.h>
> +
> +static struct platform_device *__init mxc_add_gpio(int id,
> + resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
> +{
> + struct resource res[] = {
> + {
> + .start = iobase,
> + .end = iobase + iosize - 1,
> + .flags = IORESOURCE_MEM,
> + }, {
> + .start = irq,
> + .end = irq,
> + .flags = IORESOURCE_IRQ,
> + }, {
> + .start = irq_high,
> + .end = irq_high,
> + .flags = IORESOURCE_IRQ,
> + },
> + };
> +
> + return platform_device_register_resndata(&mxc_aips_bus,
> + "gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0);

Why bother returning the value, it's never checked below?

> +static int __init mxc_add_mxc_gpio(void)

Minor nits: Redundant mxcs? Also, 'gpios' would be more accurate naming.

> +{
> + if (cpu_is_mx50()) {
> + mxc_add_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
> + mxc_add_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
> + mxc_add_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
> + mxc_add_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
> + mxc_add_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
> + mxc_add_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
> + }
> +
> + if (cpu_is_mx51()) {
> + mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
> + mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
> + mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
> + mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
> + }
> +
> + if (cpu_is_mx53()) {
> + mxc_add_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
> + mxc_add_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
> + mxc_add_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
> + mxc_add_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
> + mxc_add_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
> + mxc_add_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
> + mxc_add_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
> + }

The above tables are pretty crazy, and they only get worse later in the series
when the other SoCs are added. Is it really worth it to have a common initcall
entry for the various SoCs here?

It'd seem cleaner to me to just call the registration function for the
family you're running from in per-family-init code such as where it was
removed above (irq init, which makes some sense since the gpios provide
interrupt sources as well).

It's different on OMAP since there it is data driven with a shared
registration function, but here it's really just a hardcoded table
(as code even, not as data) per SoC.


-Olof

2011-05-31 00:53:13

by Olof Johansson

[permalink] [raw]
Subject: Re: [PATCH 1/4] gpio: gpio-mxc: add gpio driver for Freescale MXC architecture

Hi,

On Mon, May 30, 2011 at 10:52:16PM +0800, Shawn Guo wrote:
> Add gpio-mxc driver by copying arch/arm/plat-mxc/gpio.c into
> drivers/gpio with the following changes.
>
> * Use readl/writel to replace mach-specific accessors
> __raw_readl/__raw_writel
>
> * Migrate to platform driver by adding .probe function
>
> * Add a list to save all mx2 ports references, so that
> mx2_gpio_irq_handler can walk through all interrupt status
> registers
>
> Signed-off-by: Shawn Guo <[email protected]>
> ---
> arch/arm/plat-mxc/include/mach/gpio.h | 2 +
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-mxc.c | 423 +++++++++++++++++++++++++++++++++
> 3 files changed, 426 insertions(+), 0 deletions(-)
> create mode 100644 drivers/gpio/gpio-mxc.c
>
> diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
> index a2747f1..87bd4ef 100644
> --- a/arch/arm/plat-mxc/include/mach/gpio.h
> +++ b/arch/arm/plat-mxc/include/mach/gpio.h
> @@ -37,7 +37,9 @@
> #define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
>
> struct mxc_gpio_port {
> + struct list_head node;
> void __iomem *base;
> + int id;

What's id for? You assign it based on pdev->id in the probe function but
never use it anywhere else.


-Olof

2011-05-31 01:30:37

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 1/4] gpio: gpio-mxc: add gpio driver for Freescale MXC architecture

Hi Olof,

Thanks for the review.

On Mon, May 30, 2011 at 05:53:15PM -0700, Olof Johansson wrote:
> Hi,
>
> On Mon, May 30, 2011 at 10:52:16PM +0800, Shawn Guo wrote:
> > Add gpio-mxc driver by copying arch/arm/plat-mxc/gpio.c into
> > drivers/gpio with the following changes.
> >
> > * Use readl/writel to replace mach-specific accessors
> > __raw_readl/__raw_writel
> >
> > * Migrate to platform driver by adding .probe function
> >
> > * Add a list to save all mx2 ports references, so that
> > mx2_gpio_irq_handler can walk through all interrupt status
> > registers
> >
> > Signed-off-by: Shawn Guo <[email protected]>
> > ---
> > arch/arm/plat-mxc/include/mach/gpio.h | 2 +
> > drivers/gpio/Makefile | 1 +
> > drivers/gpio/gpio-mxc.c | 423 +++++++++++++++++++++++++++++++++
> > 3 files changed, 426 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/gpio/gpio-mxc.c
> >
> > diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
> > index a2747f1..87bd4ef 100644
> > --- a/arch/arm/plat-mxc/include/mach/gpio.h
> > +++ b/arch/arm/plat-mxc/include/mach/gpio.h
> > @@ -37,7 +37,9 @@
> > #define irq_to_gpio(irq) ((irq) - MXC_GPIO_IRQ_START)
> >
> > struct mxc_gpio_port {
> > + struct list_head node;
> > void __iomem *base;
> > + int id;
>
> What's id for? You assign it based on pdev->id in the probe function but
> never use it anywhere else.
>
Yes, it is only used in probe function right now, and can be removed.
I feel it will be needed someday when more cleanup and consolidation
works happen, but we can add it back then. So, yes, I will remove it
for now.

--
Regards,
Shawn

2011-05-31 02:44:28

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Mon, May 30, 2011 at 05:16:34PM -0700, Olof Johansson wrote:
> Hi,
>
> On Mon, May 30, 2011 at 10:52:17PM +0800, Shawn Guo wrote:
> > It adds platform device for drivers/gpio/gpio-mxc, and migrates
> > mx50/mx51/mx53 gpio driver to gpio-mxc.
> >
>
> [...]
>
> > diff --git a/arch/arm/plat-mxc/devices/platform-gpio-mxc.c b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
> > new file mode 100644
> > index 0000000..3b10da0
> > --- /dev/null
> > +++ b/arch/arm/plat-mxc/devices/platform-gpio-mxc.c
> > @@ -0,0 +1,69 @@
> > +/*
> > + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> > + * Copyright 2011 Linaro Limited
> > + *
> > + * 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/compiler.h>
> > +#include <linux/err.h>
> > +#include <linux/init.h>
> > +
> > +#include <mach/hardware.h>
> > +#include <mach/devices-common.h>
> > +
> > +static struct platform_device *__init mxc_add_gpio(int id,
> > + resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
> > +{
> > + struct resource res[] = {
> > + {
> > + .start = iobase,
> > + .end = iobase + iosize - 1,
> > + .flags = IORESOURCE_MEM,
> > + }, {
> > + .start = irq,
> > + .end = irq,
> > + .flags = IORESOURCE_IRQ,
> > + }, {
> > + .start = irq_high,
> > + .end = irq_high,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > + };
> > +
> > + return platform_device_register_resndata(&mxc_aips_bus,
> > + "gpio-mxc", id, res, ARRAY_SIZE(res), NULL, 0);
>
> Why bother returning the value, it's never checked below?
>
Please help me understand. You are saying the return value should be
checked below?

> > +static int __init mxc_add_mxc_gpio(void)
>
> Minor nits: Redundant mxcs? Also, 'gpios' would be more accurate naming.
>
The first one is the namespace of plat-mxc function, and the second
one is to reflect gpio driver name 'mxc gpio'.

> > +{
> > + if (cpu_is_mx50()) {
> > + mxc_add_gpio(0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
> > + mxc_add_gpio(1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
> > + mxc_add_gpio(2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
> > + mxc_add_gpio(3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
> > + mxc_add_gpio(4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
> > + mxc_add_gpio(5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
> > + }
> > +
> > + if (cpu_is_mx51()) {
> > + mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
> > + mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
> > + mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
> > + mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
> > + }
> > +
> > + if (cpu_is_mx53()) {
> > + mxc_add_gpio(0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
> > + mxc_add_gpio(1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
> > + mxc_add_gpio(2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
> > + mxc_add_gpio(3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
> > + mxc_add_gpio(4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
> > + mxc_add_gpio(5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
> > + mxc_add_gpio(6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
> > + }
>
> The above tables are pretty crazy, and they only get worse later in the series
> when the other SoCs are added. Is it really worth it to have a common initcall
> entry for the various SoCs here?
>
This common initcall seems a good place to concentrate the gpio device
registration. It's easy to look at the common/different things among
these SoCs. The only problem you reminded me is the scanning of the
long cpu_is_mx list. It can be optimized a little bit by sorting the
list from the latest (most used) SoC to the oldest (least used) one,
and breaking out the scanning immediately when hitting one.

> It'd seem cleaner to me to just call the registration function for the
> family you're running from in per-family-init code such as where it was
> removed above (irq init, which makes some sense since the gpios provide
> interrupt sources as well).
>
I just gave it a test, and it's not working at all. (too early
to register device in irq init?)

--
Regards,
Shawn

2011-05-31 08:26:17

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tuesday 31 May 2011, Shawn Guo wrote:
> > The above tables are pretty crazy, and they only get worse later in the series
> > when the other SoCs are added. Is it really worth it to have a common initcall
> > entry for the various SoCs here?
> >
> This common initcall seems a good place to concentrate the gpio device
> registration. It's easy to look at the common/different things among
> these SoCs. The only problem you reminded me is the scanning of the
> long cpu_is_mx list. It can be optimized a little bit by sorting the
> list from the latest (most used) SoC to the oldest (least used) one,
> and breaking out the scanning immediately when hitting one.

No, better make them separate functions.

> > It'd seem cleaner to me to just call the registration function for the
> > family you're running from in per-family-init code such as where it was
> > removed above (irq init, which makes some sense since the gpios provide
> > interrupt sources as well).
> >
> I just gave it a test, and it's not working at all. (too early
> to register device in irq init?)

Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
mxc_add_gpio() into the respective callers. Having a global
mxc_add_mxc_gpio() function that does something different for each
caller seems entirely pointless to me.

Best think of it from the point of view how it should look like when
everything is converted to the device tree. In that case, you would
have a function scanning the device tree that calls mxc_add_gpio
for each entry.

Arnd

2011-05-31 08:44:29

by Jamie Iles

[permalink] [raw]
Subject: Re: [PATCH 1/4] gpio: gpio-mxc: add gpio driver for Freescale MXC architecture

Hi Shawn,

On Mon, May 30, 2011 at 10:52:16PM +0800, Shawn Guo wrote:
> Add gpio-mxc driver by copying arch/arm/plat-mxc/gpio.c into
> drivers/gpio with the following changes.
>
> * Use readl/writel to replace mach-specific accessors
> __raw_readl/__raw_writel
>
> * Migrate to platform driver by adding .probe function
>
> * Add a list to save all mx2 ports references, so that
> mx2_gpio_irq_handler can walk through all interrupt status
> registers
>
> Signed-off-by: Shawn Guo <[email protected]>
> ---

Could you use the stuff in drivers/gpio/basic_mmio_gpio.c for
implementing the gpio_chip? I had a go a little while ago [1] but since
then we've made it possible to embed the bgpio_chip in your own
structure which may be cleaner.

Jamie

1. http://permalink.gmane.org/gmane.linux.ports.arm.kernel/113139

2011-05-31 09:11:53

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 1/4] gpio: gpio-mxc: add gpio driver for Freescale MXC architecture

Hi Jamie,

On Tue, May 31, 2011 at 09:44:24AM +0100, Jamie Iles wrote:
> Hi Shawn,
>
> On Mon, May 30, 2011 at 10:52:16PM +0800, Shawn Guo wrote:
> > Add gpio-mxc driver by copying arch/arm/plat-mxc/gpio.c into
> > drivers/gpio with the following changes.
> >
> > * Use readl/writel to replace mach-specific accessors
> > __raw_readl/__raw_writel
> >
> > * Migrate to platform driver by adding .probe function
> >
> > * Add a list to save all mx2 ports references, so that
> > mx2_gpio_irq_handler can walk through all interrupt status
> > registers
> >
> > Signed-off-by: Shawn Guo <[email protected]>
> > ---
>
> Could you use the stuff in drivers/gpio/basic_mmio_gpio.c for
> implementing the gpio_chip? I had a go a little while ago [1] but since
> then we've made it possible to embed the bgpio_chip in your own
> structure which may be cleaner.
>
> Jamie
>
> 1. http://permalink.gmane.org/gmane.linux.ports.arm.kernel/113139
> --

I would like to keep this series as simple as it is, straight moving
plat-mxc/gpio into drivers/gpio, and then start looking at the
possible consolidation, like generic_irq_chip and basic_mmio_gpio you
offered here. Thanks for the patch. I will start with it shortly.

--
Regards,
Shawn

2011-05-31 10:25:23

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tue, May 31, 2011 at 10:26:11AM +0200, Arnd Bergmann wrote:
> On Tuesday 31 May 2011, Shawn Guo wrote:
> > > The above tables are pretty crazy, and they only get worse later in the series
> > > when the other SoCs are added. Is it really worth it to have a common initcall
> > > entry for the various SoCs here?
> > >
> > This common initcall seems a good place to concentrate the gpio device
> > registration. It's easy to look at the common/different things among
> > these SoCs. The only problem you reminded me is the scanning of the
> > long cpu_is_mx list. It can be optimized a little bit by sorting the
> > list from the latest (most used) SoC to the oldest (least used) one,
> > and breaking out the scanning immediately when hitting one.
>
> No, better make them separate functions.
>
> > > It'd seem cleaner to me to just call the registration function for the
> > > family you're running from in per-family-init code such as where it was
> > > removed above (irq init, which makes some sense since the gpios provide
> > > interrupt sources as well).
> > >
> > I just gave it a test, and it's not working at all. (too early
> > to register device in irq init?)
>
> Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
> mxc_add_gpio() into the respective callers. Having a global
> mxc_add_mxc_gpio() function that does something different for each
> caller seems entirely pointless to me.
>
Right now, mxc_add_mxc_gpio() is a postcore_initcall. Moving
individual mxc_add_gpio() call into irq_init function does not work.
And I need to find a proper caller for each SoC to call mxc_add_gpio
to register gpio devices.

--
Regards,
Shawn

2011-05-31 11:28:36

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tuesday 31 May 2011, Shawn Guo wrote:
> > Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
> > mxc_add_gpio() into the respective callers. Having a global
> > mxc_add_mxc_gpio() function that does something different for each
> > caller seems entirely pointless to me.
> >
> Right now, mxc_add_mxc_gpio() is a postcore_initcall. Moving
> individual mxc_add_gpio() call into irq_init function does not work.
> And I need to find a proper caller for each SoC to call mxc_add_gpio
> to register gpio devices.

Why not init_machine? That is an arch_initcall(), so it's probably close
enough.

Arnd

2011-05-31 15:05:32

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tue, May 31, 2011 at 01:28:17PM +0200, Arnd Bergmann wrote:
> On Tuesday 31 May 2011, Shawn Guo wrote:
> > > Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
> > > mxc_add_gpio() into the respective callers. Having a global
> > > mxc_add_mxc_gpio() function that does something different for each
> > > caller seems entirely pointless to me.
> > >
> > Right now, mxc_add_mxc_gpio() is a postcore_initcall. Moving
> > individual mxc_add_gpio() call into irq_init function does not work.
> > And I need to find a proper caller for each SoC to call mxc_add_gpio
> > to register gpio devices.
>
> Why not init_machine? That is an arch_initcall(), so it's probably close
> enough.
>
The init_machine is mostly a board specific function than SoC specific
one. That is to say we will call mxc_add_gpio() in every single board
init function even for the same SoC.

--
Regards,
Shawn

2011-05-31 15:28:15

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tuesday 31 May 2011, Shawn Guo wrote:
>
> On Tue, May 31, 2011 at 01:28:17PM +0200, Arnd Bergmann wrote:
> > On Tuesday 31 May 2011, Shawn Guo wrote:
> > > > Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
> > > > mxc_add_gpio() into the respective callers. Having a global
> > > > mxc_add_mxc_gpio() function that does something different for each
> > > > caller seems entirely pointless to me.
> > > >
> > > Right now, mxc_add_mxc_gpio() is a postcore_initcall. Moving
> > > individual mxc_add_gpio() call into irq_init function does not work.
> > > And I need to find a proper caller for each SoC to call mxc_add_gpio
> > > to register gpio devices.
> >
> > Why not init_machine? That is an arch_initcall(), so it's probably close
> > enough.
> >
> The init_machine is mostly a board specific function than SoC specific
> one. That is to say we will call mxc_add_gpio() in every single board
> init function even for the same SoC.

But the machine is the only place that knows what SOC is being used.
Your patch right now detects it by looking at the CPU type that is
also being set by the board file using the init_early call, which
is a bit silly.

I would leave e.g. the imx51_register_gpios() in place, but only
change the definition and the caller to

void __init imx51_register_gpios(void)
{
mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
}

Then you can call that function from each i.mx51 based board, or
from a new imx51_soc_init() function that groups multiple such
functions.

Arnd

2011-05-31 16:03:34

by Shawn Guo

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

On Tue, May 31, 2011 at 05:27:55PM +0200, Arnd Bergmann wrote:
> On Tuesday 31 May 2011, Shawn Guo wrote:
> >
> > On Tue, May 31, 2011 at 01:28:17PM +0200, Arnd Bergmann wrote:
> > > On Tuesday 31 May 2011, Shawn Guo wrote:
> > > > > Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
> > > > > mxc_add_gpio() into the respective callers. Having a global
> > > > > mxc_add_mxc_gpio() function that does something different for each
> > > > > caller seems entirely pointless to me.
> > > > >
> > > > Right now, mxc_add_mxc_gpio() is a postcore_initcall. Moving
> > > > individual mxc_add_gpio() call into irq_init function does not work.
> > > > And I need to find a proper caller for each SoC to call mxc_add_gpio
> > > > to register gpio devices.
> > >
> > > Why not init_machine? That is an arch_initcall(), so it's probably close
> > > enough.
> > >
> > The init_machine is mostly a board specific function than SoC specific
> > one. That is to say we will call mxc_add_gpio() in every single board
> > init function even for the same SoC.
>
> But the machine is the only place that knows what SOC is being used.
> Your patch right now detects it by looking at the CPU type that is
> also being set by the board file using the init_early call, which
> is a bit silly.
>
I would say that the CPU type is being set by SoC file (e.g.
mach-mx5/mm.c) than board file. All the things in mach-mx5/mm.c are
common to any mx51 based boards.

> I would leave e.g. the imx51_register_gpios() in place, but only
> change the definition and the caller to
>
> void __init imx51_register_gpios(void)
> {
> mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
> mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
> mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
> mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
> }
>
> Then you can call that function from each i.mx51 based board, or
> from a new imx51_soc_init() function that groups multiple such
> functions.
>
It will anyway touch every single board file (a lot) to have this SoC
specific device registration plugged in. If you still think it's
worthy to do so, I can turn around.

--
Regards,
Shawn

2011-05-31 16:52:05

by Olof Johansson

[permalink] [raw]
Subject: Re: [PATCH 2/4] ARM: mxc: migrate mach-mx5 gpio driver to gpio-mxc

[was offline last night, apologies for the latency]

On Tue, May 31, 2011 at 9:08 AM, Shawn Guo <[email protected]> wrote:
> On Tue, May 31, 2011 at 05:27:55PM +0200, Arnd Bergmann wrote:
>> On Tuesday 31 May 2011, Shawn Guo wrote:
>> >
>> > On Tue, May 31, 2011 at 01:28:17PM +0200, Arnd Bergmann wrote:
>> > > On Tuesday 31 May 2011, Shawn Guo wrote:
>> > > > > Just open-code the mxc_add_mxc_gpio() by moving the individual calls to
>> > > > > mxc_add_gpio() into the respective callers. Having a global
>> > > > > mxc_add_mxc_gpio() function that does something different for each
>> > > > > caller seems entirely pointless to me.
>> > > > >
>> > > > Right now, mxc_add_mxc_gpio() is a postcore_initcall. ?Moving
>> > > > individual mxc_add_gpio() call into irq_init function does not work.
>> > > > And I need to find a proper caller for each SoC to call mxc_add_gpio
>> > > > to register gpio devices.
>> > >
>> > > Why not init_machine? That is an arch_initcall(), so it's probably close
>> > > enough.
>> > >
>> > The init_machine is mostly a board specific function than SoC specific
>> > one. ?That is to say we will call mxc_add_gpio() in every single board
>> > init function even for the same SoC.
>>
>> But the machine is the only place that knows what SOC is being used.
>> Your patch right now detects it by looking at the CPU type that is
>> also being set by the board file using the init_early call, which
>> is a bit silly.
>>
> I would say that the CPU type is being set by SoC file (e.g.
> mach-mx5/mm.c) than board file. ?All the things in mach-mx5/mm.c are
> common to any mx51 based boards.

The thing is that all initialization today starts at the board file.
Instead of setting a variable that determines code paths in
asyncronous initcalls later, you might as well call the appropriate
initcall functions from common functions called by board files.

So, you'd just add a call to a common per-soc init in each of the
per-board machine_init functions. Over time it'll be a good place to
add code that would otherwise be duplicated per board of the same soc
family.

>> I would leave e.g. the imx51_register_gpios() in place, but only
>> change the definition and the caller to
>>
>> void __init imx51_register_gpios(void)
>> {
>> ? ? ? ? mxc_add_gpio(0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO1_LOW, MX51_MXC_INT_GPIO1_HIGH);
>> ? ? ? ? mxc_add_gpio(1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO2_LOW, MX51_MXC_INT_GPIO2_HIGH);
>> ? ? ? ? mxc_add_gpio(2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO3_LOW, MX51_MXC_INT_GPIO3_HIGH);
>> ? ? ? ? mxc_add_gpio(3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_MXC_INT_GPIO4_LOW, MX51_MXC_INT_GPIO4_HIGH);
>> }
>>
>> Then you can call that function from each i.mx51 based board, or
>> from a new imx51_soc_init() function that groups multiple such
>> functions.
>>
> It will anyway touch every single board file (a lot) to have this SoC
> specific device registration plugged in. ?If you still think it's
> worthy to do so, I can turn around.

I personally prefer the imx51_soc_init() Arnd proposed above, since
there's a chance you will want to add more things to it over time. It
is worth adding it now, it's just a one-line change per board and it
gives you a good place to hook in other per-family setup that might be
needed later.


-Olof