[PATCH v8 10/11] OMAP: GPIO: Implement GPIO as a platform device

Cory Maccarrone darkstar6262 at gmail.com
Tue Dec 7 00:19:26 EST 2010


On Thu, Nov 25, 2010 at 4:48 AM, Varadarajan, Charulatha <charu at ti.com> wrote:
> Implement GPIO as a platform device.
>
> GPIO APIs are used in machine_init functions. Hence it is
> required to complete GPIO probe before board_init. Therefore
> GPIO device register and driver register are implemented as
> postcore_initcalls.
>
> omap_gpio_init() does nothing now and this function would be
> removed in the next patch as it's usage is spread across most
> of the board files.
>
> Inorder to convert GPIO as platform device, modifications are
> required in clockxxxx_data.c file for OMAP1 so that device names
> can be used to obtain clock instead of getting clocks by
> name/NULL ptr.
>
> Use runtime pm APIs (pm_runtime_put*/pm_runtime_get*) for enabling
> or disabling the clocks, modify sysconfig settings and remove usage
> of clock FW APIs.
> Note 1: Converting GPIO driver to use runtime PM APIs is not done as a
> separate patch because GPIO clock names are different for various OMAPs
> and are different for some of the banks in the same CPU. This would need
> usage of cpu_is checks and bank id checks while using clock FW APIs in
> the gpio driver. Hence while making GPIO a platform driver framework,
> PM runtime APIs are used directly.
>
> Note 2: While implementing GPIO as a platform device, pm runtime APIs
> are used as mentioned above and modification is not done in gpio's
> prepare for idle/ resume after idle functions. This would be done
> in the next patch series and GPIO driver would be made to use dev_pm_ops
> instead of sysdev_class in that series only.
>
> Due to the above, the GPIO driver implicitly relies on
> CM_AUTOIDLE = 1 on its iclk for power management to work, since the
> driver never disables its iclk.
> This would be taken care in the next patch series (see Note 3 below).
>
> Refer to
> http://www.mail-archive.com/linux-omap@vger.kernel.org/msg39112.html
> for more details.
>
> Note 3: only pm_runtime_get_sync is called in gpio's probe() and
> pm_runtime_put* is never called. This is to make the implementation
> similar to the existing GPIO code. Another patch series would be sent
> to correct this.
>
> In OMAP3 and OMAP4 gpio's debounce clocks are optional clocks. They
> are enabled/ disabled whenever required using clock framework APIs
>
> TODO:
> 1. Cleanup the GPIO driver. Use function pointers and register
> offest pointers instead of using hardcoded values
> 2. Remove all cpu_is_ checks and OMAP specific macros
> 3. Remove usage of gpio_bank array so that only
>   instance specific information is used in driver code
> 4. Rename 'method'/ avoid it's usage
> 5. Fix the non-wakeup gpios handling for OMAP2430, OMAP3 & OMAP4
> 6. Modify gpio's prepare for idle/ resume after idle functions
>   to use runtime pm implentation.
>
> Signed-off-by: Charulatha V <charu at ti.com>
> Signed-off-by: Rajendra Nayak <rnayak at ti.com>
> Reviewed-by: Basak, Partha <p-basak2 at ti.com>
> ---
>  arch/arm/mach-omap1/Makefile     |    6 +
>  arch/arm/mach-omap1/clock_data.c |    4 +-
>  arch/arm/mach-omap2/Makefile     |    2 +-
>  arch/arm/plat-omap/gpio.c        |  420 ++++++++++----------------------------
>  4 files changed, 114 insertions(+), 318 deletions(-)
>
> diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
> index de3cc13..0b1c07f 100644
> --- a/arch/arm/mach-omap1/Makefile
> +++ b/arch/arm/mach-omap1/Makefile
> @@ -49,6 +49,12 @@ ifeq ($(CONFIG_ARCH_OMAP15XX),y)
>  obj-$(CONFIG_MACH_OMAP_INNOVATOR)      += fpga.o
>  endif
>
> +# GPIO
> +obj-$(CONFIG_ARCH_OMAP730)             += gpio7xx.o
> +obj-$(CONFIG_ARCH_OMAP850)             += gpio7xx.o
> +obj-$(CONFIG_ARCH_OMAP15XX)            += gpio15xx.o
> +obj-$(CONFIG_ARCH_OMAP16XX)            += gpio16xx.o
> +
>  # LEDs support
>  led-$(CONFIG_MACH_OMAP_H2)             += leds-h2p2-debug.o
>  led-$(CONFIG_MACH_OMAP_H3)             += leds-h2p2-debug.o
> diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
> index af54114..423d21d 100644
> --- a/arch/arm/mach-omap1/clock_data.c
> +++ b/arch/arm/mach-omap1/clock_data.c
> @@ -143,7 +143,7 @@ static struct arm_idlect1_clk armper_ck = {
>  * activation.  [ GPIO code for 1510 ]
>  */
>  static struct clk arm_gpio_ck = {
> -       .name           = "arm_gpio_ck",
> +       .name           = "ick",
>        .ops            = &clkops_generic,
>        .parent         = &ck_dpll1,
>        .flags          = ENABLE_ON_INIT,
> @@ -684,7 +684,7 @@ static struct omap_clk omap_clks[] = {
>        CLK(NULL,       "ck_sossi",     &sossi_ck,      CK_16XX),
>        CLK(NULL,       "arm_ck",       &arm_ck,        CK_16XX | CK_1510 | CK_310),
>        CLK(NULL,       "armper_ck",    &armper_ck.clk, CK_16XX | CK_1510 | CK_310),
> -       CLK(NULL,       "arm_gpio_ck",  &arm_gpio_ck,   CK_1510 | CK_310),
> +       CLK("omap_gpio.0", "ick",       &arm_gpio_ck,   CK_1510 | CK_310),
>        CLK(NULL,       "armxor_ck",    &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX),
>        CLK(NULL,       "armtim_ck",    &armtim_ck.clk, CK_16XX | CK_1510 | CK_310),
>        CLK("omap_wdt", "fck",          &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310),
> diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
> index eb31c9c..31864e1 100644
> --- a/arch/arm/mach-omap2/Makefile
> +++ b/arch/arm/mach-omap2/Makefile
> @@ -4,7 +4,7 @@
>
>  # Common support
>  obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
> -        common.o
> +        common.o gpio.o
>
>  omap-2-3-common                                = irq.o sdrc.o prm2xxx_3xxx.o
>  hwmod-common                           = omap_hwmod.o \
> diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
> index 610787c..d04ded2 100644
> --- a/arch/arm/plat-omap/gpio.c
> +++ b/arch/arm/plat-omap/gpio.c
> @@ -21,6 +21,8 @@
>  #include <linux/err.h>
>  #include <linux/clk.h>
>  #include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/pm_runtime.h>
>
>  #include <mach/hardware.h>
>  #include <asm/irq.h>
> @@ -32,7 +34,6 @@
>  /*
>  * OMAP1510 GPIO registers
>  */
> -#define OMAP1510_GPIO_BASE             0xfffce000
>  #define OMAP1510_GPIO_DATA_INPUT       0x00
>  #define OMAP1510_GPIO_DATA_OUTPUT      0x04
>  #define OMAP1510_GPIO_DIR_CONTROL      0x08
> @@ -46,10 +47,6 @@
>  /*
>  * OMAP1610 specific GPIO registers
>  */
> -#define OMAP1610_GPIO1_BASE            0xfffbe400
> -#define OMAP1610_GPIO2_BASE            0xfffbec00
> -#define OMAP1610_GPIO3_BASE            0xfffbb400
> -#define OMAP1610_GPIO4_BASE            0xfffbbc00
>  #define OMAP1610_GPIO_REVISION         0x0000
>  #define OMAP1610_GPIO_SYSCONFIG                0x0010
>  #define OMAP1610_GPIO_SYSSTATUS                0x0014
> @@ -71,12 +68,6 @@
>  /*
>  * OMAP7XX specific GPIO registers
>  */
> -#define OMAP7XX_GPIO1_BASE             0xfffbc000
> -#define OMAP7XX_GPIO2_BASE             0xfffbc800
> -#define OMAP7XX_GPIO3_BASE             0xfffbd000
> -#define OMAP7XX_GPIO4_BASE             0xfffbd800
> -#define OMAP7XX_GPIO5_BASE             0xfffbe000
> -#define OMAP7XX_GPIO6_BASE             0xfffbe800
>  #define OMAP7XX_GPIO_DATA_INPUT                0x00
>  #define OMAP7XX_GPIO_DATA_OUTPUT       0x04
>  #define OMAP7XX_GPIO_DIR_CONTROL       0x08
> @@ -84,25 +75,10 @@
>  #define OMAP7XX_GPIO_INT_MASK          0x10
>  #define OMAP7XX_GPIO_INT_STATUS                0x14
>
> -#define OMAP1_MPUIO_VBASE              OMAP1_MPUIO_BASE
> -
>  /*
> - * omap24xx specific GPIO registers
> + * omap2+ specific GPIO registers
>  */
> -#define OMAP242X_GPIO1_BASE            0x48018000
> -#define OMAP242X_GPIO2_BASE            0x4801a000
> -#define OMAP242X_GPIO3_BASE            0x4801c000
> -#define OMAP242X_GPIO4_BASE            0x4801e000
> -
> -#define OMAP243X_GPIO1_BASE            0x4900C000
> -#define OMAP243X_GPIO2_BASE            0x4900E000
> -#define OMAP243X_GPIO3_BASE            0x49010000
> -#define OMAP243X_GPIO4_BASE            0x49012000
> -#define OMAP243X_GPIO5_BASE            0x480B6000
> -
>  #define OMAP24XX_GPIO_REVISION         0x0000
> -#define OMAP24XX_GPIO_SYSCONFIG                0x0010
> -#define OMAP24XX_GPIO_SYSSTATUS                0x0014
>  #define OMAP24XX_GPIO_IRQSTATUS1       0x0018
>  #define OMAP24XX_GPIO_IRQSTATUS2       0x0028
>  #define OMAP24XX_GPIO_IRQENABLE2       0x002c
> @@ -126,7 +102,6 @@
>  #define OMAP24XX_GPIO_SETDATAOUT       0x0094
>
>  #define OMAP4_GPIO_REVISION            0x0000
> -#define OMAP4_GPIO_SYSCONFIG           0x0010
>  #define OMAP4_GPIO_EOI                 0x0020
>  #define OMAP4_GPIO_IRQSTATUSRAW0       0x0024
>  #define OMAP4_GPIO_IRQSTATUSRAW1       0x0028
> @@ -138,7 +113,6 @@
>  #define OMAP4_GPIO_IRQSTATUSCLR1       0x0040
>  #define OMAP4_GPIO_IRQWAKEN0           0x0044
>  #define OMAP4_GPIO_IRQWAKEN1           0x0048
> -#define OMAP4_GPIO_SYSSTATUS           0x0114
>  #define OMAP4_GPIO_IRQENABLE1          0x011c
>  #define OMAP4_GPIO_WAKE_EN             0x0120
>  #define OMAP4_GPIO_IRQSTATUS2          0x0128
> @@ -159,26 +133,6 @@
>  #define OMAP4_GPIO_SETWKUENA           0x0184
>  #define OMAP4_GPIO_CLEARDATAOUT                0x0190
>  #define OMAP4_GPIO_SETDATAOUT          0x0194
> -/*
> - * omap34xx specific GPIO registers
> - */
> -
> -#define OMAP34XX_GPIO1_BASE            0x48310000
> -#define OMAP34XX_GPIO2_BASE            0x49050000
> -#define OMAP34XX_GPIO3_BASE            0x49052000
> -#define OMAP34XX_GPIO4_BASE            0x49054000
> -#define OMAP34XX_GPIO5_BASE            0x49056000
> -#define OMAP34XX_GPIO6_BASE            0x49058000
> -
> -/*
> - * OMAP44XX  specific GPIO registers
> - */
> -#define OMAP44XX_GPIO1_BASE             0x4a310000
> -#define OMAP44XX_GPIO2_BASE             0x48055000
> -#define OMAP44XX_GPIO3_BASE             0x48057000
> -#define OMAP44XX_GPIO4_BASE             0x48059000
> -#define OMAP44XX_GPIO5_BASE             0x4805B000
> -#define OMAP44XX_GPIO6_BASE             0x4805D000
>
>  struct gpio_bank {
>        unsigned long pbase;
> @@ -203,97 +157,12 @@ struct gpio_bank {
>        struct clk *dbck;
>        u32 mod_usage;
>        u32 dbck_enable_mask;
> +       struct device *dev;
> +       bool dbck_flag;
>  };
>
> -#ifdef CONFIG_ARCH_OMAP16XX
> -static struct gpio_bank gpio_bank_1610[5] = {
> -       { OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE,
> -               METHOD_MPUIO },
> -       { OMAP1610_GPIO1_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_1610 },
> -       { OMAP1610_GPIO2_BASE, NULL, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16,
> -               METHOD_GPIO_1610 },
> -       { OMAP1610_GPIO3_BASE, NULL, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_1610 },
> -       { OMAP1610_GPIO4_BASE, NULL, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48,
> -               METHOD_GPIO_1610 },
> -};
> -#endif
> -
> -#ifdef CONFIG_ARCH_OMAP15XX
> -static struct gpio_bank gpio_bank_1510[2] = {
> -       { OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE,
> -               METHOD_MPUIO },
> -       { OMAP1510_GPIO_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_1510 }
> -};
> -#endif
> -
> -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
> -static struct gpio_bank gpio_bank_7xx[7] = {
> -       { OMAP1_MPUIO_VBASE, NULL, INT_7XX_MPUIO, IH_MPUIO_BASE,
> -               METHOD_MPUIO },
> -       { OMAP7XX_GPIO1_BASE, NULL, INT_7XX_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_7XX },
> -       { OMAP7XX_GPIO2_BASE, NULL, INT_7XX_GPIO_BANK2, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_7XX },
> -       { OMAP7XX_GPIO3_BASE, NULL, INT_7XX_GPIO_BANK3, IH_GPIO_BASE + 64,
> -               METHOD_GPIO_7XX },
> -       { OMAP7XX_GPIO4_BASE, NULL, INT_7XX_GPIO_BANK4,  IH_GPIO_BASE + 96,
> -               METHOD_GPIO_7XX },
> -       { OMAP7XX_GPIO5_BASE, NULL, INT_7XX_GPIO_BANK5,  IH_GPIO_BASE + 128,
> -               METHOD_GPIO_7XX },
> -       { OMAP7XX_GPIO6_BASE, NULL, INT_7XX_GPIO_BANK6,  IH_GPIO_BASE + 160,
> -               METHOD_GPIO_7XX },
> -};
> -#endif
> -
> -#ifdef CONFIG_ARCH_OMAP2
> -
> -static struct gpio_bank gpio_bank_242x[4] = {
> -       { OMAP242X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_24XX },
> -       { OMAP242X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_24XX },
> -       { OMAP242X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,
> -               METHOD_GPIO_24XX },
> -       { OMAP242X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,
> -               METHOD_GPIO_24XX },
> -};
> -
> -static struct gpio_bank gpio_bank_243x[5] = {
> -       { OMAP243X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_24XX },
> -       { OMAP243X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_24XX },
> -       { OMAP243X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64,
> -               METHOD_GPIO_24XX },
> -       { OMAP243X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96,
> -               METHOD_GPIO_24XX },
> -       { OMAP243X_GPIO5_BASE, NULL, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128,
> -               METHOD_GPIO_24XX },
> -};
> -
> -#endif
> -
>  #ifdef CONFIG_ARCH_OMAP3
> -static struct gpio_bank gpio_bank_34xx[6] = {
> -       { OMAP34XX_GPIO1_BASE, NULL, INT_34XX_GPIO_BANK1, IH_GPIO_BASE,
> -               METHOD_GPIO_24XX },
> -       { OMAP34XX_GPIO2_BASE, NULL, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_24XX },
> -       { OMAP34XX_GPIO3_BASE, NULL, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64,
> -               METHOD_GPIO_24XX },
> -       { OMAP34XX_GPIO4_BASE, NULL, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96,
> -               METHOD_GPIO_24XX },
> -       { OMAP34XX_GPIO5_BASE, NULL, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128,
> -               METHOD_GPIO_24XX },
> -       { OMAP34XX_GPIO6_BASE, NULL, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160,
> -               METHOD_GPIO_24XX },
> -};
> -
>  struct omap3_gpio_regs {
> -       u32 sysconfig;
>        u32 irqenable1;
>        u32 irqenable2;
>        u32 wake_en;
> @@ -309,25 +178,14 @@ struct omap3_gpio_regs {
>  static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
>  #endif
>
> -#ifdef CONFIG_ARCH_OMAP4
> -static struct gpio_bank gpio_bank_44xx[6] = {
> -       { OMAP44XX_GPIO1_BASE, NULL, OMAP44XX_IRQ_GPIO1, IH_GPIO_BASE,
> -               METHOD_GPIO_44XX },
> -       { OMAP44XX_GPIO2_BASE, NULL, OMAP44XX_IRQ_GPIO2, IH_GPIO_BASE + 32,
> -               METHOD_GPIO_44XX },
> -       { OMAP44XX_GPIO3_BASE, NULL, OMAP44XX_IRQ_GPIO3, IH_GPIO_BASE + 64,
> -               METHOD_GPIO_44XX },
> -       { OMAP44XX_GPIO4_BASE, NULL, OMAP44XX_IRQ_GPIO4, IH_GPIO_BASE + 96,
> -               METHOD_GPIO_44XX },
> -       { OMAP44XX_GPIO5_BASE, NULL, OMAP44XX_IRQ_GPIO5, IH_GPIO_BASE + 128,
> -               METHOD_GPIO_44XX },
> -       { OMAP44XX_GPIO6_BASE, NULL, OMAP44XX_IRQ_GPIO6, IH_GPIO_BASE + 160,
> -               METHOD_GPIO_44XX },
> -};
> +/*
> + * TODO: Cleanup gpio_bank usage as it is having information
> + * related to all instances of the device
> + */
> +static struct gpio_bank *gpio_bank;
>
> -#endif
> +static int bank_width;
>
> -static struct gpio_bank *gpio_bank;
>  /* TODO: Analyze removing gpio_bank_count usage from driver code */
>  int gpio_bank_count;
>
> @@ -634,6 +492,9 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
>        u32                     val;
>        u32                     l;
>
> +       if (!bank->dbck_flag)
> +               return;
> +
>        if (debounce < 32)
>                debounce = 0x01;
>        else if (debounce > 7936)
> @@ -643,7 +504,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
>
>        l = 1 << get_gpio_index(gpio);
>
> -       if (cpu_is_omap44xx())
> +       if (bank->method == METHOD_GPIO_44XX)
>                reg += OMAP4_GPIO_DEBOUNCINGTIME;
>        else
>                reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
> @@ -651,7 +512,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
>        __raw_writel(debounce, reg);
>
>        reg = bank->base;
> -       if (cpu_is_omap44xx())
> +       if (bank->method == METHOD_GPIO_44XX)
>                reg += OMAP4_GPIO_DEBOUNCENABLE;
>        else
>                reg += OMAP24XX_GPIO_DEBOUNCE_EN;
> @@ -660,12 +521,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
>
>        if (debounce) {
>                val |= l;
> -               if (cpu_is_omap34xx() || cpu_is_omap44xx())
> -                       clk_enable(bank->dbck);
> +               clk_enable(bank->dbck);
>        } else {
>                val &= ~l;
> -               if (cpu_is_omap34xx() || cpu_is_omap44xx())
> -                       clk_disable(bank->dbck);
> +               clk_disable(bank->dbck);
>        }
>        bank->dbck_enable_mask = val;
>
> @@ -1537,7 +1396,8 @@ static struct platform_device omap_mpuio_device = {
>
>  static inline void mpuio_init(void)
>  {
> -       platform_set_drvdata(&omap_mpuio_device, &gpio_bank_1610[0]);
> +       struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
> +       platform_set_drvdata(&omap_mpuio_device, bank);
>
>        if (platform_driver_register(&omap_mpuio_driver) == 0)
>                (void) platform_device_register(&omap_mpuio_device);
> @@ -1642,6 +1502,13 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
>        unsigned long flags;
>
>        bank = container_of(chip, struct gpio_bank, chip);
> +
> +       if (!bank->dbck) {
> +               bank->dbck = clk_get(bank->dev, "dbclk");
> +               if (IS_ERR(bank->dbck))
> +                       dev_err(bank->dev, "Could not get gpio dbck\n");
> +       }
> +

I'm testing this on omap7xx, which doesn't have a dbclk.  Even with
dbck_flag set to false, this code still runs, causing these messages
to show up:

    omap_gpio omap_gpio.5: Could not get gpio dbck
    omap_gpio omap_gpio.6: Could not get gpio dbck

I think that 'if' should be:

    if (bank->dbck_flag && !bank->dbck) {

Also, see my comments in patch 4 - OMAP7xx: GPIO: Introduce support
for GPIO init, as there's dbck_flag entries there that are needed for
omap7xx.  Otherwise, seems to work well.

- Cory



More information about the linux-arm-kernel mailing list