Charulatha V <charu@xxxxxx> writes: > This patch implements GPIO as a early platform device. Also it > implements OMAP2PLUS specific GPIO as HWMOD FW adapted driver. Should include a summary explanation of why you're converting to an early platform device as well. > Inorder to convert GPIO as platform device, modifications are > required in clockxxxx_data.c files so that device names can be > used to obtain clock instead of getting clocks by name/NULL ptr. ok > Currently early platform device register does not do device_pm_init. > Hence pm_runtime functions are not used to enable the GPIO device > since gpio is early platform device. OK for now, since this isn't using runtime PM, but maybe we need a late_initcall() here to do the device_pm_init() + pm_runtime_enable() This change log needs more description of the intended init sequence. Right now it seems that there are multiple init paths. Now that GPIO is an early_platform_device, we should be able to at least make omap_gpio_init() static and remove its usage from all the board files. Also, the driver and device separation and init is totally mixed together and very confusing. The platform_driver is in plat-omap/gpio.c and should be doing the driver init: [early_]platform_driver_register() and _probe(). The platform_device setup is in mach-omapX/gpio*.c and where the device init should be, in this case early_platform_add_devices(). > Signed-off-by: Charulatha V <charu@xxxxxx> > Signed-off-by: Rajendra Nayak <rnayak@xxxxxx> > --- > arch/arm/mach-omap1/Makefile | 6 + > arch/arm/mach-omap1/clock_data.c | 2 +- > arch/arm/mach-omap2/Makefile | 2 +- > arch/arm/mach-omap2/clock2420_data.c | 10 +- > arch/arm/mach-omap2/clock2430_data.c | 14 +- > arch/arm/mach-omap2/clock3xxx_data.c | 24 +- > arch/arm/mach-omap2/clock44xx_data.c | 24 +- > arch/arm/plat-omap/gpio.c | 405 ++++++++++++-------------------- > arch/arm/plat-omap/include/plat/gpio.h | 21 ++ > 9 files changed, 220 insertions(+), 288 deletions(-) [...] > @@ -1621,6 +1501,34 @@ static void __init omap_gpio_show_rev(void) > */ > static struct lock_class_key gpio_lock_class; > > +static int init_gpio_info(void) > +{ > + gpio_bank_bits = 32; > + > + if (cpu_is_omap15xx()) { > + gpio_bank_count = 2; > + gpio_bank_bits = 16; > + } else if (cpu_is_omap16xx()) { > + gpio_bank_count = 5; > + gpio_bank_bits = 16; > + } else if (cpu_is_omap7xx()) > + gpio_bank_count = 7; > + else if (cpu_is_omap242x()) > + gpio_bank_count = 4; > + else if (cpu_is_omap243x()) > + gpio_bank_count = 5; > + else if (cpu_is_omap34xx() || cpu_is_omap44xx()) > + gpio_bank_count = OMAP34XX_NR_GPIOS; Both the bank count and bank bits could be part of platform_data and set in the SoC specific init. This is the GPIO driver part and we're trying to make this as SoC independent as possible. Anytime you need to add a cpu_is* or #ifdef in this code indicates something that should be part of SoC specific init and passed in. > + gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank), > + GFP_KERNEL); > + if (!gpio_bank) { > + pr_err("Memory allocation failed for gpio_bank\n"); > + return -ENOMEM; > + } > + return 0; > +} > + > static void omap_gpio_mod_init(struct gpio_bank *bank, int id) > { > if (cpu_class_is_omap2()) { > @@ -1686,16 +1594,9 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) > > static void __init omap_gpio_chip_init(struct gpio_bank *bank) > { > - int j, gpio_bank_bits = 16; > + int j; > static int gpio; > > - if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) > - gpio_bank_bits = 32; /* 7xx has 32-bit GPIOs */ > - > - if ((bank->method == METHOD_GPIO_24XX) || > - (bank->method == METHOD_GPIO_44XX)) > - gpio_bank_bits = 32; > - > bank->mod_usage = 0; > /* REVISIT eventually switch from OMAP-specific gpio structs > * over to the generic ones > @@ -1737,140 +1638,103 @@ static void __init omap_gpio_chip_init(struct gpio_bank *bank) > set_irq_data(bank->irq, bank); > } > > -static int __init _omap_gpio_init(void) > +static inline void get_gpio_dbck(struct platform_device *pdev, > + struct gpio_bank *bank) > { > - int i; > - int gpio = 0; > + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { > + bank->dbck = clk_get(&pdev->dev, "dbck"); > + if (IS_ERR(bank->dbck)) > + pr_err("GPIO: Could not get dbck\n"); > + } > +} > +static int __devinit omap_gpio_probe(struct platform_device *pdev) > +{ > + static int gpio_init_done; > + struct omap_gpio_platform_data *pdata; > + int id; > struct gpio_bank *bank; > - int bank_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ > - char clk_name[11]; > + struct resource *res; > > - initialized = 1; > + if (!gpio_init_done) > + init_gpio_info(); > > -#if defined(CONFIG_ARCH_OMAP1) > - if (cpu_is_omap15xx()) { > - gpio_ick = clk_get(NULL, "arm_gpio_ck"); > - if (IS_ERR(gpio_ick)) > - printk("Could not get arm_gpio_ck\n"); > - else > - clk_enable(gpio_ick); > + if (!pdev || !pdev->dev.platform_data) { > + pr_err("GPIO device initialize without" > + "platform data\n"); > + return -EINVAL; > } > -#endif > -#if defined(CONFIG_ARCH_OMAP2) > - if (cpu_class_is_omap2()) { > - gpio_ick = clk_get(NULL, "gpios_ick"); > - if (IS_ERR(gpio_ick)) > - printk("Could not get gpios_ick\n"); > - else > - clk_enable(gpio_ick); > - gpio_fck = clk_get(NULL, "gpios_fck"); > - if (IS_ERR(gpio_fck)) > - printk("Could not get gpios_fck\n"); > - else > - clk_enable(gpio_fck); > > - /* > - * On 2430 & 3430 GPIO 5 uses CORE L4 ICLK > - */ > -#if defined(CONFIG_ARCH_OMAP2430) > - if (cpu_is_omap2430()) { > - gpio5_ick = clk_get(NULL, "gpio5_ick"); > - if (IS_ERR(gpio5_ick)) > - printk("Could not get gpio5_ick\n"); > - else > - clk_enable(gpio5_ick); > - gpio5_fck = clk_get(NULL, "gpio5_fck"); > - if (IS_ERR(gpio5_fck)) > - printk("Could not get gpio5_fck\n"); > - else > - clk_enable(gpio5_fck); > - } > -#endif > - } > -#endif > + pdata = pdev->dev.platform_data; > > -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) > - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { > - for (i = 0; i < OMAP34XX_NR_GPIOS; i++) { > - sprintf(clk_name, "gpio%d_ick", i + 1); > - gpio_iclks[i] = clk_get(NULL, clk_name); > - if (IS_ERR(gpio_iclks[i])) > - printk(KERN_ERR "Could not get %s\n", clk_name); > - else > - clk_enable(gpio_iclks[i]); > - } > + id = pdev->id; > + if (id > gpio_bank_count) { > + pr_err("Invalid GPIO device id (%d)\n", id); > + return -EINVAL; > } > -#endif > > + bank = &gpio_bank[id]; > > -#ifdef CONFIG_ARCH_OMAP15XX > - if (cpu_is_omap15xx()) { > - gpio_bank_count = 2; > - gpio_bank = gpio_bank_1510; > - bank_size = SZ_2K; > - } > -#endif > -#if defined(CONFIG_ARCH_OMAP16XX) > - if (cpu_is_omap16xx()) { > - gpio_bank_count = 5; > - gpio_bank = gpio_bank_1610; > - bank_size = SZ_2K; > - } > -#endif > -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) > - if (cpu_is_omap7xx()) { > - gpio_bank_count = 7; > - gpio_bank = gpio_bank_7xx; > - bank_size = SZ_2K; > - } > -#endif > -#ifdef CONFIG_ARCH_OMAP2 > - if (cpu_is_omap242x()) { > - gpio_bank_count = 4; > - gpio_bank = gpio_bank_242x; > - } > - if (cpu_is_omap243x()) { > - gpio_bank_count = 5; > - gpio_bank = gpio_bank_243x; > - } > -#endif > -#ifdef CONFIG_ARCH_OMAP3 > - if (cpu_is_omap34xx()) { > - gpio_bank_count = OMAP34XX_NR_GPIOS; > - gpio_bank = gpio_bank_34xx; > + if (bank->initialized == 1) { is_early_platform_device() can be used to tell if the _probe() is being called as part of early platform driver probe or "regular". > + /* > + * Currently, for early platform_devices, > + * clk_get() using dev ptr does not seem to be working > + * Hence getting dbck during regular device probe > + */ Need a better explanation here. "does not seem to work" is not quite good enough. > + get_gpio_dbck(pdev, bank); In any case, maybe it's better to defer the clk_get() into the debounce setup and only use if needed. > + return 0; > } > -#endif > -#ifdef CONFIG_ARCH_OMAP4 > - if (cpu_is_omap44xx()) { > - gpio_bank_count = OMAP34XX_NR_GPIOS; > - gpio_bank = gpio_bank_44xx; > + > + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); > + if (unlikely(!res)) { > + pr_err("GPIO Bank %i Invalid IRQ resource\n", id); > + return -ENODEV; > } > -#endif > - for (i = 0; i < gpio_bank_count; i++) { > + bank->irq = res->start; > + bank->virtual_irq_start = pdata->virtual_irq_start; > + bank->base = pdata->base; Why are you using pdata->base for OMAP2+ base addresses... > + bank->method = pdata->method; > > - bank = &gpio_bank[i]; > - spin_lock_init(&bank->lock); > + spin_lock_init(&bank->lock); > > + if (cpu_class_is_omap2()) { > + bank->device_enable = pdata->device_enable; > + bank->device_idle = pdata->device_idle; > + bank->device_shutdown = pdata->device_shutdown; > + pdata->device_enable(pdev); > + } else if (cpu_class_is_omap1()) { > /* Static mapping, never released */ > - bank->base = ioremap(bank->pbase, bank_size); > - if (!bank->base) { > - printk(KERN_ERR "Could not ioremap gpio bank%i\n", i); > - continue; > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ... and doing it the right way here for OMAP1? platform_get_resource() should be used for both. > + if (unlikely(!res)) { > + pr_err("GPIO Bank %i Invalid mem resource\n", id); > + return -ENODEV; > } > > - omap_gpio_mod_init(bank, i); > - omap_gpio_chip_init(bank); > + bank->base = ioremap(res->start, resource_size(res)); > + if (!bank->base) { > + pr_err("Could not ioremap gpio bank%i\n", id); > + return -ENOMEM; > + } > > - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { > - sprintf(clk_name, "gpio%d_dbck", i + 1); > - bank->dbck = clk_get(NULL, clk_name); > - if (IS_ERR(bank->dbck)) > - printk(KERN_ERR "Could not get %s\n", clk_name); > + if (cpu_is_omap15xx() && (id == 0)) { > + static struct clk *gpio_clk; > + gpio_clk = clk_get(&pdev->dev, "arm_gpio_ck"); > + if (IS_ERR(gpio_clk)) > + pr_err("Could not get arm_gpio_ck\n"); > + else > + clk_enable(gpio_clk); > } > } > > - omap_gpio_show_rev(); > + omap_gpio_mod_init(bank, id); > + omap_gpio_chip_init(bank); > > + if (!gpio_init_done) { > + omap_gpio_show_rev(); > + gpio_init_done = 1; > + } > + > + bank->initialized = 1; I think you can drop this flag, and use is_early_platform_device() if needed. > return 0; > } > > @@ -2210,16 +2074,42 @@ void omap_gpio_restore_context(void) > } > #endif > > -/* > - * This may get called early from board specific init > - * for boards that have interrupts routed via FPGA. > - */ > +static struct platform_driver omap_gpio_driver = { > + .probe = omap_gpio_probe, > + .driver = { > + .name = "omap-gpio", > + }, > +}; > + > +int __init omap_gpio_drv_reg(void) > +{ > + return platform_driver_register(&omap_gpio_driver); > +} > + > +early_platform_init("earlygpio", &omap_gpio_driver); > + > int __init omap_gpio_init(void) > { > - if (!initialized) > - return _omap_gpio_init(); > - else > + int ret = 0; > + > + if (initialized) > return 0; > + > +#ifdef CONFIG_ARCH_OMAP1 > + if (cpu_is_omap7xx()) > + ret = omap7xx_gpio_init(); > + if (cpu_is_omap15xx()) > + ret = omap15xx_gpio_init(); > + if (cpu_is_omap16xx()) > + ret = omap16xx_gpio_init(); > +#endif > +#ifdef CONFIG_ARCH_OMAP2PLUS > + if (cpu_class_is_omap2()) > + ret = omap2_gpio_init(); > +#endif No thanks. driver init should not be calling device init. The device init should have it's own initcall or be called by other early device init. > + initialized = 1; > + > + return ret; > } > > static int __init omap_gpio_sysinit(void) > @@ -2227,7 +2117,10 @@ static int __init omap_gpio_sysinit(void) > int ret = 0; > > if (!initialized) > - ret = _omap_gpio_init(); > + ret = omap_gpio_init(); > + > + if (!ret) > + ret = omap_gpio_drv_reg(); > > mpuio_init(); Kevin -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html