From 03e128ca35e5da22e9e65ec8ab158ec0e905fdea Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Thu, 5 May 2011 19:58:01 +0530 Subject: gpio/omap: remove dependency on gpio_bank_count The gpio_bank_count is the count of number of GPIO devices in a SoC. Remove this dependency from the driver by using list. Also remove the dependency on array of pointers to gpio_bank struct of all GPIO devices. Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 163 +++++++++++++++++++++++------------------------ 1 file changed, 80 insertions(+), 83 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0b0562979171..6ea7390e7801 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -28,7 +28,10 @@ #include #include +static LIST_HEAD(omap_gpio_list); + struct gpio_bank { + struct list_head node; unsigned long pbase; void __iomem *base; u16 irq; @@ -55,6 +58,7 @@ struct gpio_bank { bool dbck_flag; int stride; u32 width; + u16 id; void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); @@ -78,15 +82,6 @@ struct omap3_gpio_regs { static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; #endif -/* - * TODO: Cleanup gpio_bank usage as it is having information - * related to all instances of the device - */ -static struct gpio_bank *gpio_bank; - -/* TODO: Analyze removing gpio_bank_count usage from driver code */ -int gpio_bank_count; - #define GPIO_INDEX(bank, gpio) (gpio % bank->width) #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) @@ -869,9 +864,8 @@ static struct platform_device omap_mpuio_device = { /* could list the /proc/iomem resources */ }; -static inline void mpuio_init(void) +static inline void mpuio_init(struct gpio_bank *bank) { - struct gpio_bank *bank = &gpio_bank[0]; platform_set_drvdata(&omap_mpuio_device, bank); if (platform_driver_register(&omap_mpuio_driver) == 0) @@ -879,13 +873,13 @@ static inline void mpuio_init(void) } #else -static inline void mpuio_init(void) {} +static inline void mpuio_init(struct gpio_bank *bank) {} #endif /* 16xx */ #else #define bank_is_mpuio(bank) 0 -static inline void mpuio_init(void) {} +static inline void mpuio_init(struct gpio_bank *bank) {} #endif @@ -1007,20 +1001,8 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank) */ static struct lock_class_key gpio_lock_class; -static inline int init_gpio_info(struct platform_device *pdev) -{ - /* TODO: Analyze removing gpio_bank_count usage from driver code */ - gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank), - GFP_KERNEL); - if (!gpio_bank) { - dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n"); - return -ENOMEM; - } - return 0; -} - /* TODO: Cleanup cpu_is_* checks */ -static void omap_gpio_mod_init(struct gpio_bank *bank, int id) +static void omap_gpio_mod_init(struct gpio_bank *bank) { if (cpu_class_is_omap2()) { if (cpu_is_omap44xx()) { @@ -1044,13 +1026,16 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) static const u32 non_wakeup_gpios[] = { 0xe203ffc0, 0x08700040 }; - if (id < ARRAY_SIZE(non_wakeup_gpios)) - bank->non_wakeup_gpios = non_wakeup_gpios[id]; + if (bank->id < ARRAY_SIZE(non_wakeup_gpios)) + bank->non_wakeup_gpios = + non_wakeup_gpios[bank->id]; } } else if (cpu_class_is_omap1()) { - if (bank_is_mpuio(bank)) + if (bank_is_mpuio(bank)) { __raw_writew(0xffff, bank->base + OMAP_MPUIO_GPIO_MASKIT / bank->stride); + mpuio_init(bank); + } if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); @@ -1161,35 +1146,35 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) static int __devinit omap_gpio_probe(struct platform_device *pdev) { - static int gpio_init_done; struct omap_gpio_platform_data *pdata; struct resource *res; - int id; struct gpio_bank *bank; + int ret = 0; - if (!pdev->dev.platform_data) - return -EINVAL; - - pdata = pdev->dev.platform_data; - - if (!gpio_init_done) { - int ret; - - ret = init_gpio_info(pdev); - if (ret) - return ret; + if (!pdev->dev.platform_data) { + ret = -EINVAL; + goto err_exit; } - id = pdev->id; - bank = &gpio_bank[id]; + bank = kzalloc(sizeof(struct gpio_bank), GFP_KERNEL); + if (!bank) { + dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n"); + ret = -ENOMEM; + goto err_exit; + } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (unlikely(!res)) { - dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id); - return -ENODEV; + dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", + pdev->id); + ret = -ENODEV; + goto err_free; } bank->irq = res->start; + bank->id = pdev->id; + + pdata = pdev->dev.platform_data; bank->virtual_irq_start = pdata->virtual_irq_start; bank->method = pdata->bank_type; bank->dev = &pdev->dev; @@ -1209,39 +1194,46 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) /* Static mapping, never released */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(!res)) { - dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id); - return -ENODEV; + dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", + pdev->id); + ret = -ENODEV; + goto err_free; } bank->base = ioremap(res->start, resource_size(res)); if (!bank->base) { - dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id); - return -ENOMEM; + dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", + pdev->id); + ret = -ENOMEM; + goto err_free; } pm_runtime_enable(bank->dev); pm_runtime_get_sync(bank->dev); - omap_gpio_mod_init(bank, id); + omap_gpio_mod_init(bank); omap_gpio_chip_init(bank); omap_gpio_show_rev(bank); - if (!gpio_init_done) - gpio_init_done = 1; + list_add_tail(&bank->node, &omap_gpio_list); - return 0; + return ret; + +err_free: + kfree(bank); +err_exit: + return ret; } #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) static int omap_gpio_suspend(void) { - int i; + struct gpio_bank *bank; if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) return 0; - for (i = 0; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; + list_for_each_entry(bank, &omap_gpio_list, node) { void __iomem *wake_status; void __iomem *wake_clear; void __iomem *wake_set; @@ -1285,13 +1277,12 @@ static int omap_gpio_suspend(void) static void omap_gpio_resume(void) { - int i; + struct gpio_bank *bank; if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) return; - for (i = 0; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; + list_for_each_entry(bank, &omap_gpio_list, node) { void __iomem *wake_clear; void __iomem *wake_set; unsigned long flags; @@ -1339,17 +1330,17 @@ static int workaround_enabled; void omap2_gpio_prepare_for_idle(int off_mode) { - int i, c = 0; - int min = 0; - - if (cpu_is_omap34xx()) - min = 1; + int c = 0; + struct gpio_bank *bank; - for (i = min; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; + list_for_each_entry(bank, &omap_gpio_list, node) { u32 l1 = 0, l2 = 0; int j; + /* TODO: Do not use cpu_is_omap34xx */ + if ((cpu_is_omap34xx()) && (bank->id == 0)) + continue; + for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) clk_disable(bank->dbck); @@ -1408,16 +1399,16 @@ void omap2_gpio_prepare_for_idle(int off_mode) void omap2_gpio_resume_after_idle(void) { - int i; - int min = 0; + struct gpio_bank *bank; - if (cpu_is_omap34xx()) - min = 1; - for (i = min; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; + list_for_each_entry(bank, &omap_gpio_list, node) { u32 l = 0, gen, gen0, gen1; int j; + /* TODO: Do not use cpu_is_omap34xx */ + if ((cpu_is_omap34xx()) && (bank->id == 0)) + continue; + for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) clk_enable(bank->dbck); @@ -1506,14 +1497,17 @@ void omap2_gpio_resume_after_idle(void) #endif #ifdef CONFIG_ARCH_OMAP3 -/* save the registers of bank 2-6 */ void omap_gpio_save_context(void) { - int i; + struct gpio_bank *bank; + int i = 0; + + list_for_each_entry(bank, &omap_gpio_list, node) { + i++; + + if (bank->id == 0) + continue; - /* saving banks from 2-6 only since GPIO1 is in WKUP */ - for (i = 1; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; gpio_context[i].irqenable1 = __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); gpio_context[i].irqenable2 = @@ -1537,13 +1531,17 @@ void omap_gpio_save_context(void) } } -/* restore the required registers of bank 2-6 */ void omap_gpio_restore_context(void) { - int i; + struct gpio_bank *bank; + int i = 0; + + list_for_each_entry(bank, &omap_gpio_list, node) { + i++; + + if (bank->id == 0) + continue; - for (i = 1; i < gpio_bank_count; i++) { - struct gpio_bank *bank = &gpio_bank[i]; __raw_writel(gpio_context[i].irqenable1, bank->base + OMAP24XX_GPIO_IRQENABLE1); __raw_writel(gpio_context[i].irqenable2, @@ -1588,7 +1586,6 @@ postcore_initcall(omap_gpio_drv_reg); static int __init omap_gpio_sysinit(void) { - mpuio_init(); #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) if (cpu_is_omap16xx() || cpu_class_is_omap2()) -- cgit v1.2.3 From 0cde8d03dd297fa8e7e88cedeb498d0ed5b7776d Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Thu, 5 May 2011 20:15:16 +0530 Subject: gpio/omap: use flag to identify wakeup domain In omap3, save/restore context is implemented for GPIO banks 2-6 as GPIO bank1 is in wakeup domain. Instead of identifying bank's power domain by bank id, use 'loses_context' flag which is filled by pwrdm_can_ever_lose_context() during dev_init. For getting the powerdomain pointer, omap_hwmod_get_pwrdm() is used. omap_device_get_pwrdm() could not be used as the pwrdm information needs to be filled in pdata, whereas omap_device_get_pwrdm() could be used only after omap_device_build() call. Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 6 ++++++ arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 13 ++++++------- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 07ac64850746..076be342ad28 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -24,6 +24,8 @@ #include #include +#include "powerdomain.h" + static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) { struct platform_device *pdev; @@ -31,6 +33,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) struct omap_gpio_dev_attr *dev_attr; char *name = "omap_gpio"; int id; + struct powerdomain *pwrdm; /* * extract the device id from name field available in the @@ -99,6 +102,9 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) return -EINVAL; } + pwrdm = omap_hwmod_get_pwrdm(oh); + pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); + pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata), NULL, 0, false); kfree(pdata); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index acf1c779629e..6eb035c0cc16 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -198,6 +198,7 @@ struct omap_gpio_platform_data { int bank_width; /* GPIO bank width */ int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ + bool loses_context; /* whether the bank would ever lose context */ struct omap_gpio_reg_offs *regs; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 6ea7390e7801..07efa15c3549 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -56,6 +56,7 @@ struct gpio_bank { u32 dbck_enable_mask; struct device *dev; bool dbck_flag; + bool loses_context; int stride; u32 width; u16 id; @@ -1181,7 +1182,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; - + bank->loses_context = pdata->loses_context; bank->regs = pdata->regs; if (bank->regs->set_dataout && bank->regs->clr_dataout) @@ -1337,8 +1338,7 @@ void omap2_gpio_prepare_for_idle(int off_mode) u32 l1 = 0, l2 = 0; int j; - /* TODO: Do not use cpu_is_omap34xx */ - if ((cpu_is_omap34xx()) && (bank->id == 0)) + if (!bank->loses_context) continue; for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) @@ -1405,8 +1405,7 @@ void omap2_gpio_resume_after_idle(void) u32 l = 0, gen, gen0, gen1; int j; - /* TODO: Do not use cpu_is_omap34xx */ - if ((cpu_is_omap34xx()) && (bank->id == 0)) + if (!bank->loses_context) continue; for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) @@ -1505,7 +1504,7 @@ void omap_gpio_save_context(void) list_for_each_entry(bank, &omap_gpio_list, node) { i++; - if (bank->id == 0) + if (!bank->loses_context) continue; gpio_context[i].irqenable1 = @@ -1539,7 +1538,7 @@ void omap_gpio_restore_context(void) list_for_each_entry(bank, &omap_gpio_list, node) { i++; - if (bank->id == 0) + if (!bank->loses_context) continue; __raw_writel(gpio_context[i].irqenable1, -- cgit v1.2.3 From 6d62e216b2ccbb8176dca73b6899b12a417bb22d Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Mon, 18 Apr 2011 15:06:51 +0000 Subject: gpio/omap: make gpio_context part of gpio_bank structure Currently gpio_context array used to save gpio bank's context, is used only for OMAP3 architecture. Move gpio_context as part of gpio_bank structure so that it can be specific to each gpio bank and can be used for any OMAP architecture Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 76 ++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 42 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 07efa15c3549..6788c8a2a770 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -30,6 +30,19 @@ static LIST_HEAD(omap_gpio_list); +struct gpio_regs { + u32 irqenable1; + u32 irqenable2; + u32 wake_en; + u32 ctrl; + u32 oe; + u32 leveldetect0; + u32 leveldetect1; + u32 risingdetect; + u32 fallingdetect; + u32 dataout; +}; + struct gpio_bank { struct list_head node; unsigned long pbase; @@ -43,7 +56,7 @@ struct gpio_bank { #endif u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; - + struct gpio_regs context; u32 saved_datain; u32 saved_fallingdetect; u32 saved_risingdetect; @@ -66,23 +79,6 @@ struct gpio_bank { struct omap_gpio_reg_offs *regs; }; -#ifdef CONFIG_ARCH_OMAP3 -struct omap3_gpio_regs { - u32 irqenable1; - u32 irqenable2; - u32 wake_en; - u32 ctrl; - u32 oe; - u32 leveldetect0; - u32 leveldetect1; - u32 risingdetect; - u32 fallingdetect; - u32 dataout; -}; - -static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; -#endif - #define GPIO_INDEX(bank, gpio) (gpio % bank->width) #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) @@ -1499,33 +1495,31 @@ void omap2_gpio_resume_after_idle(void) void omap_gpio_save_context(void) { struct gpio_bank *bank; - int i = 0; list_for_each_entry(bank, &omap_gpio_list, node) { - i++; if (!bank->loses_context) continue; - gpio_context[i].irqenable1 = + bank->context.irqenable1 = __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); - gpio_context[i].irqenable2 = + bank->context.irqenable2 = __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); - gpio_context[i].wake_en = + bank->context.wake_en = __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); - gpio_context[i].ctrl = + bank->context.ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); - gpio_context[i].oe = + bank->context.oe = __raw_readl(bank->base + OMAP24XX_GPIO_OE); - gpio_context[i].leveldetect0 = + bank->context.leveldetect0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); - gpio_context[i].leveldetect1 = + bank->context.leveldetect1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); - gpio_context[i].risingdetect = + bank->context.risingdetect = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); - gpio_context[i].fallingdetect = + bank->context.fallingdetect = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); - gpio_context[i].dataout = + bank->context.dataout = __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); } } @@ -1533,33 +1527,31 @@ void omap_gpio_save_context(void) void omap_gpio_restore_context(void) { struct gpio_bank *bank; - int i = 0; list_for_each_entry(bank, &omap_gpio_list, node) { - i++; if (!bank->loses_context) continue; - __raw_writel(gpio_context[i].irqenable1, + __raw_writel(bank->context.irqenable1, bank->base + OMAP24XX_GPIO_IRQENABLE1); - __raw_writel(gpio_context[i].irqenable2, + __raw_writel(bank->context.irqenable2, bank->base + OMAP24XX_GPIO_IRQENABLE2); - __raw_writel(gpio_context[i].wake_en, + __raw_writel(bank->context.wake_en, bank->base + OMAP24XX_GPIO_WAKE_EN); - __raw_writel(gpio_context[i].ctrl, + __raw_writel(bank->context.ctrl, bank->base + OMAP24XX_GPIO_CTRL); - __raw_writel(gpio_context[i].oe, + __raw_writel(bank->context.oe, bank->base + OMAP24XX_GPIO_OE); - __raw_writel(gpio_context[i].leveldetect0, + __raw_writel(bank->context.leveldetect0, bank->base + OMAP24XX_GPIO_LEVELDETECT0); - __raw_writel(gpio_context[i].leveldetect1, + __raw_writel(bank->context.leveldetect1, bank->base + OMAP24XX_GPIO_LEVELDETECT1); - __raw_writel(gpio_context[i].risingdetect, + __raw_writel(bank->context.risingdetect, bank->base + OMAP24XX_GPIO_RISINGDETECT); - __raw_writel(gpio_context[i].fallingdetect, + __raw_writel(bank->context.fallingdetect, bank->base + OMAP24XX_GPIO_FALLINGDETECT); - __raw_writel(gpio_context[i].dataout, + __raw_writel(bank->context.dataout, bank->base + OMAP24XX_GPIO_DATAOUT); } } -- cgit v1.2.3 From 60a3437dc9a61c7f4b199c2bac3dcc7b611b1178 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 29 Sep 2011 04:47:25 +0530 Subject: gpio/omap: handle save/restore context in GPIO driver Modify omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle() functions to handle save context & restore context respectively in the OMAP GPIO driver itself instead of calling these functions from pm specific files. For this, in gpio_prepare_for_idle(), call *_get_context_loss_count() and in gpio_resume_after_idle() call it again. If the count is different, do restore context. Signed-off-by: Charulatha V Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 3 +- arch/arm/mach-omap2/pm34xx.c | 14 ---- arch/arm/plat-omap/include/plat/gpio.h | 5 +- drivers/gpio/gpio-omap.c | 131 +++++++++++++++------------------ 4 files changed, 63 insertions(+), 90 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 076be342ad28..f84db8ff207f 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -23,6 +23,7 @@ #include #include +#include #include "powerdomain.h" @@ -55,7 +56,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->bank_width = dev_attr->bank_width; pdata->dbck_flag = dev_attr->dbck_flag; pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1); - + pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL); if (!pdata) { pr_err("gpio%d: Memory allocation failed\n", id); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index fc6987578920..59c6dc16dd1d 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -75,16 +75,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm; static struct powerdomain *core_pwrdm, *per_pwrdm; static struct powerdomain *cam_pwrdm; -static inline void omap3_per_save_context(void) -{ - omap_gpio_save_context(); -} - -static inline void omap3_per_restore_context(void) -{ - omap_gpio_restore_context(); -} - static void omap3_enable_io_chain(void) { int timeout = 0; @@ -332,8 +322,6 @@ void omap_sram_idle(void) if (per_next_state < PWRDM_POWER_ON) { per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; omap2_gpio_prepare_for_idle(per_going_off); - if (per_next_state == PWRDM_POWER_OFF) - omap3_per_save_context(); } /* CORE */ @@ -399,8 +387,6 @@ void omap_sram_idle(void) if (per_next_state < PWRDM_POWER_ON) { per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); omap2_gpio_resume_after_idle(); - if (per_prev_state == PWRDM_POWER_OFF) - omap3_per_restore_context(); } /* Disable IO-PAD and IO-CHAIN wakeup */ diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 6eb035c0cc16..c1ddc5a3de2a 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -201,14 +201,15 @@ struct omap_gpio_platform_data { bool loses_context; /* whether the bank would ever lose context */ struct omap_gpio_reg_offs *regs; + + /* Return context loss count due to PM states changing */ + int (*get_context_loss_count)(struct device *dev); }; extern void omap2_gpio_prepare_for_idle(int off_mode); extern void omap2_gpio_resume_after_idle(void); extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable); -extern void omap_gpio_save_context(void); -extern void omap_gpio_restore_context(void); /*-------------------------------------------------------------------------*/ /* Wrappers for "new style" GPIO calls, using the new infrastructure diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 6788c8a2a770..a1a3b9dca178 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -72,9 +72,11 @@ struct gpio_bank { bool loses_context; int stride; u32 width; + int context_loss_count; u16 id; void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); + int (*get_context_loss_count)(struct device *dev); struct omap_gpio_reg_offs *regs; }; @@ -1179,6 +1181,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; bank->loses_context = pdata->loses_context; + bank->get_context_loss_count = pdata->get_context_loss_count; bank->regs = pdata->regs; if (bank->regs->set_dataout && bank->regs->clr_dataout) @@ -1323,11 +1326,11 @@ static struct syscore_ops omap_gpio_syscore_ops = { #ifdef CONFIG_ARCH_OMAP2PLUS -static int workaround_enabled; +static void omap_gpio_save_context(struct gpio_bank *bank); +static void omap_gpio_restore_context(struct gpio_bank *bank); void omap2_gpio_prepare_for_idle(int off_mode) { - int c = 0; struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { @@ -1347,7 +1350,7 @@ void omap2_gpio_prepare_for_idle(int off_mode) * non-wakeup GPIOs. Otherwise spurious IRQs will be * generated. See OMAP2420 Errata item 1.101. */ if (!(bank->enabled_non_wakeup_gpios)) - continue; + goto save_gpio_context; if (cpu_is_omap24xx() || cpu_is_omap34xx()) { bank->saved_datain = __raw_readl(bank->base + @@ -1384,13 +1387,13 @@ void omap2_gpio_prepare_for_idle(int off_mode) __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); } - c++; - } - if (!c) { - workaround_enabled = 0; - return; +save_gpio_context: + if (bank->get_context_loss_count) + bank->context_loss_count = + bank->get_context_loss_count(bank->dev); + + omap_gpio_save_context(bank); } - workaround_enabled = 1; } void omap2_gpio_resume_after_idle(void) @@ -1398,6 +1401,7 @@ void omap2_gpio_resume_after_idle(void) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { + int context_lost_cnt_after; u32 l = 0, gen, gen0, gen1; int j; @@ -1407,8 +1411,13 @@ void omap2_gpio_resume_after_idle(void) for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) clk_enable(bank->dbck); - if (!workaround_enabled) - continue; + if (bank->get_context_loss_count) { + context_lost_cnt_after = + bank->get_context_loss_count(bank->dev); + if (context_lost_cnt_after != bank->context_loss_count + || !context_lost_cnt_after) + omap_gpio_restore_context(bank); + } if (!(bank->enabled_non_wakeup_gpios)) continue; @@ -1486,74 +1495,50 @@ void omap2_gpio_resume_after_idle(void) } } } - } -#endif - -#ifdef CONFIG_ARCH_OMAP3 -void omap_gpio_save_context(void) +static void omap_gpio_save_context(struct gpio_bank *bank) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - - if (!bank->loses_context) - continue; - - bank->context.irqenable1 = - __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); - bank->context.irqenable2 = - __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); - bank->context.wake_en = - __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); - bank->context.ctrl = - __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); - bank->context.oe = - __raw_readl(bank->base + OMAP24XX_GPIO_OE); - bank->context.leveldetect0 = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); - bank->context.leveldetect1 = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); - bank->context.risingdetect = - __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); - bank->context.fallingdetect = - __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); - bank->context.dataout = - __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); - } + bank->context.irqenable1 = + __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); + bank->context.irqenable2 = + __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); + bank->context.wake_en = + __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); + bank->context.ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); + bank->context.oe = __raw_readl(bank->base + OMAP24XX_GPIO_OE); + bank->context.leveldetect0 = + __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); + bank->context.leveldetect1 = + __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); + bank->context.risingdetect = + __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); + bank->context.fallingdetect = + __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); + bank->context.dataout = + __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); } -void omap_gpio_restore_context(void) +static void omap_gpio_restore_context(struct gpio_bank *bank) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - - if (!bank->loses_context) - continue; - - __raw_writel(bank->context.irqenable1, - bank->base + OMAP24XX_GPIO_IRQENABLE1); - __raw_writel(bank->context.irqenable2, - bank->base + OMAP24XX_GPIO_IRQENABLE2); - __raw_writel(bank->context.wake_en, - bank->base + OMAP24XX_GPIO_WAKE_EN); - __raw_writel(bank->context.ctrl, - bank->base + OMAP24XX_GPIO_CTRL); - __raw_writel(bank->context.oe, - bank->base + OMAP24XX_GPIO_OE); - __raw_writel(bank->context.leveldetect0, - bank->base + OMAP24XX_GPIO_LEVELDETECT0); - __raw_writel(bank->context.leveldetect1, - bank->base + OMAP24XX_GPIO_LEVELDETECT1); - __raw_writel(bank->context.risingdetect, - bank->base + OMAP24XX_GPIO_RISINGDETECT); - __raw_writel(bank->context.fallingdetect, - bank->base + OMAP24XX_GPIO_FALLINGDETECT); - __raw_writel(bank->context.dataout, - bank->base + OMAP24XX_GPIO_DATAOUT); - } + __raw_writel(bank->context.irqenable1, + bank->base + OMAP24XX_GPIO_IRQENABLE1); + __raw_writel(bank->context.irqenable2, + bank->base + OMAP24XX_GPIO_IRQENABLE2); + __raw_writel(bank->context.wake_en, + bank->base + OMAP24XX_GPIO_WAKE_EN); + __raw_writel(bank->context.ctrl, bank->base + OMAP24XX_GPIO_CTRL); + __raw_writel(bank->context.oe, bank->base + OMAP24XX_GPIO_OE); + __raw_writel(bank->context.leveldetect0, + bank->base + OMAP24XX_GPIO_LEVELDETECT0); + __raw_writel(bank->context.leveldetect1, + bank->base + OMAP24XX_GPIO_LEVELDETECT1); + __raw_writel(bank->context.risingdetect, + bank->base + OMAP24XX_GPIO_RISINGDETECT); + __raw_writel(bank->context.fallingdetect, + bank->base + OMAP24XX_GPIO_FALLINGDETECT); + __raw_writel(bank->context.dataout, + bank->base + OMAP24XX_GPIO_DATAOUT); } #endif -- cgit v1.2.3 From 803a24343f94c3eaeed35e69efa12a576258ca70 Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Thu, 5 May 2011 17:04:12 +0530 Subject: gpio/omap: make non-wakeup GPIO part of pdata Non-wakeup GPIOs are available only in OMAP2. Avoid cpu_is checks by making non_wakeup_gpios as part of pdata. Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 8 ++++++++ arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 8 +------- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index f84db8ff207f..1d60fffccb32 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -65,6 +65,14 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) switch (oh->class->rev) { case 0: + if (id == 1) + /* non-wakeup GPIO pins for OMAP2 Bank1 */ + pdata->non_wakeup_gpios = 0xe203ffc0; + else if (id == 2) + /* non-wakeup GPIO pins for OMAP2 Bank2 */ + pdata->non_wakeup_gpios = 0x08700040; + /* fall through */ + case 1: pdata->bank_type = METHOD_GPIO_24XX; pdata->regs->revision = OMAP24XX_GPIO_REVISION; diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index c1ddc5a3de2a..49ec751f630e 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -199,6 +199,7 @@ struct omap_gpio_platform_data { int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ bool loses_context; /* whether the bank would ever lose context */ + u32 non_wakeup_gpios; struct omap_gpio_reg_offs *regs; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a1a3b9dca178..2eed159d964e 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1021,13 +1021,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) /* Initialize interface clk ungated, module enabled */ __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); - } else if (cpu_is_omap24xx()) { - static const u32 non_wakeup_gpios[] = { - 0xe203ffc0, 0x08700040 - }; - if (bank->id < ARRAY_SIZE(non_wakeup_gpios)) - bank->non_wakeup_gpios = - non_wakeup_gpios[bank->id]; } } else if (cpu_class_is_omap1()) { if (bank_is_mpuio(bank)) { @@ -1180,6 +1173,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; + bank->non_wakeup_gpios = pdata->non_wakeup_gpios; bank->loses_context = pdata->loses_context; bank->get_context_loss_count = pdata->get_context_loss_count; bank->regs = pdata->regs; -- cgit v1.2.3 From c8eef65a2fc311f8edca47f2e4ac2cccb70eb192 Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Mon, 2 May 2011 15:21:42 +0530 Subject: gpio/omap: avoid cpu checks during module ena/disable Remove cpu-is checks while enabling/disabling OMAP GPIO module during a gpio request/free. Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 2 ++ arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 53 +++++++++++++++------------------- 3 files changed, 26 insertions(+), 30 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 1d60fffccb32..bc9271a970a5 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -88,6 +88,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1; pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL; pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN; + pdata->regs->ctrl = OMAP24XX_GPIO_CTRL; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -104,6 +105,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0; pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME; pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE; + pdata->regs->ctrl = OMAP4_GPIO_CTRL; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 49ec751f630e..db94bd145bc2 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -188,6 +188,7 @@ struct omap_gpio_reg_offs { u16 clr_irqenable; u16 debounce; u16 debounce_en; + u16 ctrl; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 2eed159d964e..5cc2c04cd0a6 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -83,6 +83,7 @@ struct gpio_bank { #define GPIO_INDEX(bank, gpio) (gpio % bank->width) #define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio)) +#define GPIO_MOD_CTRL_BIT BIT(0) static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) { @@ -577,22 +578,18 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) __raw_writel(__raw_readl(reg) | (1 << offset), reg); } #endif - if (!cpu_class_is_omap1()) { - if (!bank->mod_usage) { - void __iomem *reg = bank->base; - u32 ctrl; - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - reg += OMAP24XX_GPIO_CTRL; - else if (cpu_is_omap44xx()) - reg += OMAP4_GPIO_CTRL; - ctrl = __raw_readl(reg); - /* Module is enabled, clocks are not gated */ - ctrl &= 0xFFFFFFFE; - __raw_writel(ctrl, reg); - } - bank->mod_usage |= 1 << offset; + if (bank->regs->ctrl && !bank->mod_usage) { + void __iomem *reg = bank->base + bank->regs->ctrl; + u32 ctrl; + + ctrl = __raw_readl(reg); + /* Module is enabled, clocks are not gated */ + ctrl &= ~GPIO_MOD_CTRL_BIT; + __raw_writel(ctrl, reg); } + + bank->mod_usage |= 1 << offset; + spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -625,22 +622,18 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) __raw_writel(1 << offset, reg); } #endif - if (!cpu_class_is_omap1()) { - bank->mod_usage &= ~(1 << offset); - if (!bank->mod_usage) { - void __iomem *reg = bank->base; - u32 ctrl; - - if (cpu_is_omap24xx() || cpu_is_omap34xx()) - reg += OMAP24XX_GPIO_CTRL; - else if (cpu_is_omap44xx()) - reg += OMAP4_GPIO_CTRL; - ctrl = __raw_readl(reg); - /* Module is disabled, clocks are gated */ - ctrl |= 1; - __raw_writel(ctrl, reg); - } + bank->mod_usage &= ~(1 << offset); + + if (bank->regs->ctrl && !bank->mod_usage) { + void __iomem *reg = bank->base + bank->regs->ctrl; + u32 ctrl; + + ctrl = __raw_readl(reg); + /* Module is disabled, clocks are gated */ + ctrl |= GPIO_MOD_CTRL_BIT; + __raw_writel(ctrl, reg); } + _reset_gpio(bank, bank->chip.base + offset); spin_unlock_irqrestore(&bank->lock, flags); } -- cgit v1.2.3 From 6ed87c5b66ca81996fae2dae6d1e702d66b9832b Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 13 Sep 2011 14:41:44 +0530 Subject: gpio/omap: further cleanup using wkup_en register Wakeup enable register offset initialized according to OMAP versions during device registration. Use this to avoid version checks. Starting with OMAP4, legacy registers should not be used in combination with the updated regsiters. Use wkup_en register consistently for all SoCs wherever applicable. Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio16xx.c | 1 + arch/arm/mach-omap2/gpio.c | 2 + arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 110 +++++++-------------------------- 4 files changed, 25 insertions(+), 89 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index df4bb445d829..1eb47e2760d8 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -89,6 +89,7 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = { .irqenable = OMAP1610_GPIO_IRQENABLE1, .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1, .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1, + .wkup_en = OMAP1610_GPIO_WAKEUPENABLE, }; static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index bc9271a970a5..4877b525def3 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -89,6 +89,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL; pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN; pdata->regs->ctrl = OMAP24XX_GPIO_CTRL; + pdata->regs->wkup_en = OMAP24XX_GPIO_WAKE_EN; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -106,6 +107,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME; pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE; pdata->regs->ctrl = OMAP4_GPIO_CTRL; + pdata->regs->wkup_en = OMAP4_GPIO_IRQWAKEN0; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index db94bd145bc2..2b54bca511d7 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -189,6 +189,7 @@ struct omap_gpio_reg_offs { u16 debounce; u16 debounce_en; u16 ctrl; + u16 wkup_en; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 5cc2c04cd0a6..3daedffbd707 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -51,9 +51,7 @@ struct gpio_bank { u16 virtual_irq_start; int method; u32 suspend_wakeup; -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) u32 saved_wakeup; -#endif u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; @@ -598,30 +596,15 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) { struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); + void __iomem *base = bank->base; unsigned long flags; spin_lock_irqsave(&bank->lock, flags); -#ifdef CONFIG_ARCH_OMAP16XX - if (bank->method == METHOD_GPIO_1610) { - /* Disable wake-up during idle for dynamic tick */ - void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - __raw_writel(1 << offset, reg); - } -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - if (bank->method == METHOD_GPIO_24XX) { - /* Disable wake-up during idle for dynamic tick */ - void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; - __raw_writel(1 << offset, reg); - } -#endif -#ifdef CONFIG_ARCH_OMAP4 - if (bank->method == METHOD_GPIO_44XX) { + + if (bank->regs->wkup_en) /* Disable wake-up during idle for dynamic tick */ - void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0; - __raw_writel(1 << offset, reg); - } -#endif + _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); + bank->mod_usage &= ~(1 << offset); if (bank->regs->ctrl && !bank->mod_usage) { @@ -1071,8 +1054,8 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start, ct->chip.irq_mask = irq_gc_mask_set_bit; ct->chip.irq_unmask = irq_gc_mask_clr_bit; ct->chip.irq_set_type = gpio_irq_type; - /* REVISIT: assuming only 16xx supports MPUIO wake events */ - if (cpu_is_omap16xx()) + + if (bank->regs->wkup_en) ct->chip.irq_set_wake = gpio_wake_enable, ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride; @@ -1101,7 +1084,8 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) if (bank_is_mpuio(bank)) { bank->chip.label = "mpuio"; #ifdef CONFIG_ARCH_OMAP16XX - bank->chip.dev = &omap_mpuio_device.dev; + if (bank->regs->wkup_en) + bank->chip.dev = &omap_mpuio_device.dev; #endif bank->chip.base = OMAP_MPUIO(0); } else { @@ -1212,50 +1196,24 @@ err_exit: return ret; } -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) static int omap_gpio_suspend(void) { struct gpio_bank *bank; - if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) - return 0; - list_for_each_entry(bank, &omap_gpio_list, node) { + void __iomem *base = bank->base; void __iomem *wake_status; - void __iomem *wake_clear; - void __iomem *wake_set; unsigned long flags; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE; - wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN; - wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; - wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0; - wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; - wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; - break; -#endif - default: - continue; - } + if (!bank->regs->wkup_en) + return 0; + + wake_status = bank->base + bank->regs->wkup_en; spin_lock_irqsave(&bank->lock, flags); bank->saved_wakeup = __raw_readl(wake_status); - __raw_writel(0xffffffff, wake_clear); - __raw_writel(bank->suspend_wakeup, wake_set); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); spin_unlock_irqrestore(&bank->lock, flags); } @@ -1266,40 +1224,16 @@ static void omap_gpio_resume(void) { struct gpio_bank *bank; - if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) - return; - list_for_each_entry(bank, &omap_gpio_list, node) { - void __iomem *wake_clear; - void __iomem *wake_set; + void __iomem *base = bank->base; unsigned long flags; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: - wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; - break; -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - case METHOD_GPIO_24XX: - wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; - wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; - break; -#endif -#ifdef CONFIG_ARCH_OMAP4 - case METHOD_GPIO_44XX: - wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; - wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; - break; -#endif - default: - continue; - } + if (!bank->regs->wkup_en) + return; spin_lock_irqsave(&bank->lock, flags); - __raw_writel(0xffffffff, wake_clear); - __raw_writel(bank->saved_wakeup, wake_set); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); spin_unlock_irqrestore(&bank->lock, flags); } } @@ -1309,8 +1243,6 @@ static struct syscore_ops omap_gpio_syscore_ops = { .resume = omap_gpio_resume, }; -#endif - #ifdef CONFIG_ARCH_OMAP2PLUS static void omap_gpio_save_context(struct gpio_bank *bank); -- cgit v1.2.3 From 9ea14d8cbbf1c8fc941e8e8a12aa0a3edc5c336e Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 30 Aug 2011 15:05:44 +0530 Subject: gpio/omap: use level/edge detect reg offsets By adding level and edge detection register offsets and then initializing them correctly according to OMAP versions during device registrations we can now remove lot of revision checks in these functions. Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 8 +++ arch/arm/plat-omap/include/plat/gpio.h | 4 ++ drivers/gpio/gpio-omap.c | 114 +++++++++------------------------ 3 files changed, 44 insertions(+), 82 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 4877b525def3..ae5043eaba82 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -90,6 +90,10 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN; pdata->regs->ctrl = OMAP24XX_GPIO_CTRL; pdata->regs->wkup_en = OMAP24XX_GPIO_WAKE_EN; + pdata->regs->leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0; + pdata->regs->leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1; + pdata->regs->risingdetect = OMAP24XX_GPIO_RISINGDETECT; + pdata->regs->fallingdetect = OMAP24XX_GPIO_FALLINGDETECT; break; case 2: pdata->bank_type = METHOD_GPIO_44XX; @@ -108,6 +112,10 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE; pdata->regs->ctrl = OMAP4_GPIO_CTRL; pdata->regs->wkup_en = OMAP4_GPIO_IRQWAKEN0; + pdata->regs->leveldetect0 = OMAP4_GPIO_LEVELDETECT0; + pdata->regs->leveldetect1 = OMAP4_GPIO_LEVELDETECT1; + pdata->regs->risingdetect = OMAP4_GPIO_RISINGDETECT; + pdata->regs->fallingdetect = OMAP4_GPIO_FALLINGDETECT; break; default: WARN(1, "Invalid gpio bank_type\n"); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 2b54bca511d7..395b3c1e8ba4 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -190,6 +190,10 @@ struct omap_gpio_reg_offs { u16 debounce_en; u16 ctrl; u16 wkup_en; + u16 leveldetect0; + u16 leveldetect1; + u16 risingdetect; + u16 fallingdetect; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 3daedffbd707..991dd39f6eda 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -257,15 +257,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, bank->enabled_non_wakeup_gpios &= ~gpio_bit; } - if (cpu_is_omap44xx()) { - bank->level_mask = - __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) | - __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1); - } else { - bank->level_mask = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); - } + bank->level_mask = + __raw_readl(bank->base + bank->regs->leveldetect0) | + __raw_readl(bank->base + bank->regs->leveldetect1); } #endif @@ -405,12 +399,12 @@ static int gpio_irq_type(struct irq_data *d, unsigned type) if (type & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; - /* OMAP1 allows only only edge triggering */ - if (!cpu_class_is_omap2() - && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) + bank = irq_data_get_irq_chip_data(d); + + if (!bank->regs->leveldetect0 && + (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))) return -EINVAL; - bank = irq_data_get_irq_chip_data(d); spin_lock_irqsave(&bank->lock, flags); retval = _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), type); spin_unlock_irqrestore(&bank->lock, flags); @@ -658,9 +652,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) isr &= 0x0000ffff; - if (cpu_class_is_omap2()) { + if (bank->level_mask) level_mask = bank->level_mask & enabled; - } /* clear edge sensitive interrupts before handler(s) are called so that we don't miss any interrupt occurred while @@ -1271,40 +1264,18 @@ void omap2_gpio_prepare_for_idle(int off_mode) if (!(bank->enabled_non_wakeup_gpios)) goto save_gpio_context; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - bank->saved_datain = __raw_readl(bank->base + - OMAP24XX_GPIO_DATAIN); - l1 = __raw_readl(bank->base + - OMAP24XX_GPIO_FALLINGDETECT); - l2 = __raw_readl(bank->base + - OMAP24XX_GPIO_RISINGDETECT); - } - - if (cpu_is_omap44xx()) { - bank->saved_datain = __raw_readl(bank->base + - OMAP4_GPIO_DATAIN); - l1 = __raw_readl(bank->base + - OMAP4_GPIO_FALLINGDETECT); - l2 = __raw_readl(bank->base + - OMAP4_GPIO_RISINGDETECT); - } + bank->saved_datain = __raw_readl(bank->base + + bank->regs->datain); + l1 = __raw_readl(bank->base + bank->regs->fallingdetect); + l2 = __raw_readl(bank->base + bank->regs->risingdetect); bank->saved_fallingdetect = l1; bank->saved_risingdetect = l2; l1 &= ~bank->enabled_non_wakeup_gpios; l2 &= ~bank->enabled_non_wakeup_gpios; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - __raw_writel(l1, bank->base + - OMAP24XX_GPIO_FALLINGDETECT); - __raw_writel(l2, bank->base + - OMAP24XX_GPIO_RISINGDETECT); - } - - if (cpu_is_omap44xx()) { - __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT); - __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); - } + __raw_writel(l1, bank->base + bank->regs->fallingdetect); + __raw_writel(l2, bank->base + bank->regs->risingdetect); save_gpio_context: if (bank->get_context_loss_count) @@ -1341,21 +1312,11 @@ void omap2_gpio_resume_after_idle(void) if (!(bank->enabled_non_wakeup_gpios)) continue; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - __raw_writel(bank->saved_fallingdetect, - bank->base + OMAP24XX_GPIO_FALLINGDETECT); - __raw_writel(bank->saved_risingdetect, - bank->base + OMAP24XX_GPIO_RISINGDETECT); - l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); - } - - if (cpu_is_omap44xx()) { - __raw_writel(bank->saved_fallingdetect, - bank->base + OMAP4_GPIO_FALLINGDETECT); - __raw_writel(bank->saved_risingdetect, - bank->base + OMAP4_GPIO_RISINGDETECT); - l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN); - } + __raw_writel(bank->saved_fallingdetect, + bank->base + bank->regs->fallingdetect); + __raw_writel(bank->saved_risingdetect, + bank->base + bank->regs->risingdetect); + l = __raw_readl(bank->base + bank->regs->datain); /* Check if any of the non-wakeup interrupt GPIOs have changed * state. If so, generate an IRQ by software. This is @@ -1383,35 +1344,24 @@ void omap2_gpio_resume_after_idle(void) if (gen) { u32 old0, old1; + old0 = __raw_readl(bank->base + + bank->regs->leveldetect0); + old1 = __raw_readl(bank->base + + bank->regs->leveldetect1); + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - old0 = __raw_readl(bank->base + - OMAP24XX_GPIO_LEVELDETECT0); - old1 = __raw_readl(bank->base + - OMAP24XX_GPIO_LEVELDETECT1); - __raw_writel(old0 | gen, bank->base + - OMAP24XX_GPIO_LEVELDETECT0); - __raw_writel(old1 | gen, bank->base + - OMAP24XX_GPIO_LEVELDETECT1); - __raw_writel(old0, bank->base + - OMAP24XX_GPIO_LEVELDETECT0); - __raw_writel(old1, bank->base + - OMAP24XX_GPIO_LEVELDETECT1); + old0 |= gen; + old1 |= gen; } if (cpu_is_omap44xx()) { - old0 = __raw_readl(bank->base + - OMAP4_GPIO_LEVELDETECT0); - old1 = __raw_readl(bank->base + - OMAP4_GPIO_LEVELDETECT1); - __raw_writel(old0 | l, bank->base + - OMAP4_GPIO_LEVELDETECT0); - __raw_writel(old1 | l, bank->base + - OMAP4_GPIO_LEVELDETECT1); - __raw_writel(old0, bank->base + - OMAP4_GPIO_LEVELDETECT0); - __raw_writel(old1, bank->base + - OMAP4_GPIO_LEVELDETECT1); + old0 |= l; + old1 |= l; } + __raw_writel(old0, bank->base + + bank->regs->leveldetect0); + __raw_writel(old1, bank->base + + bank->regs->leveldetect1); } } } -- cgit v1.2.3 From ae10f2336b9c0c8da73da2878eba684ab876eb8f Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 30 Aug 2011 15:24:27 +0530 Subject: gpio/omap: remove hardcoded offsets in context save/restore It is not required to use hard-coded offsets any more in context save and restore functions and instead use the generic offsets which have been correctly initialized during device registration. Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 2 ++ arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 42 ++++++++++++++++------------------ 3 files changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index ae5043eaba82..f4c45ca2cc59 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -84,6 +84,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1; pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2; pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1; + pdata->regs->irqenable2 = OMAP24XX_GPIO_IRQENABLE2; pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1; pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1; pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL; @@ -106,6 +107,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0; pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1; pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0; + pdata->regs->irqenable2 = OMAP4_GPIO_IRQSTATUSSET1; pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0; pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0; pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME; diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 395b3c1e8ba4..914c976b1de0 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -184,6 +184,7 @@ struct omap_gpio_reg_offs { u16 irqstatus; u16 irqstatus2; u16 irqenable; + u16 irqenable2; u16 set_irqenable; u16 clr_irqenable; u16 debounce; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 991dd39f6eda..ceb9edf16dab 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1369,45 +1369,43 @@ void omap2_gpio_resume_after_idle(void) static void omap_gpio_save_context(struct gpio_bank *bank) { bank->context.irqenable1 = - __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); + __raw_readl(bank->base + bank->regs->irqenable); bank->context.irqenable2 = - __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); + __raw_readl(bank->base + bank->regs->irqenable2); bank->context.wake_en = - __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); - bank->context.ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); - bank->context.oe = __raw_readl(bank->base + OMAP24XX_GPIO_OE); + __raw_readl(bank->base + bank->regs->wkup_en); + bank->context.ctrl = __raw_readl(bank->base + bank->regs->ctrl); + bank->context.oe = __raw_readl(bank->base + bank->regs->direction); bank->context.leveldetect0 = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); + __raw_readl(bank->base + bank->regs->leveldetect0); bank->context.leveldetect1 = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); + __raw_readl(bank->base + bank->regs->leveldetect1); bank->context.risingdetect = - __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); + __raw_readl(bank->base + bank->regs->risingdetect); bank->context.fallingdetect = - __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); - bank->context.dataout = - __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); + __raw_readl(bank->base + bank->regs->fallingdetect); + bank->context.dataout = __raw_readl(bank->base + bank->regs->dataout); } static void omap_gpio_restore_context(struct gpio_bank *bank) { __raw_writel(bank->context.irqenable1, - bank->base + OMAP24XX_GPIO_IRQENABLE1); + bank->base + bank->regs->irqenable); __raw_writel(bank->context.irqenable2, - bank->base + OMAP24XX_GPIO_IRQENABLE2); + bank->base + bank->regs->irqenable2); __raw_writel(bank->context.wake_en, - bank->base + OMAP24XX_GPIO_WAKE_EN); - __raw_writel(bank->context.ctrl, bank->base + OMAP24XX_GPIO_CTRL); - __raw_writel(bank->context.oe, bank->base + OMAP24XX_GPIO_OE); + bank->base + bank->regs->wkup_en); + __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); + __raw_writel(bank->context.oe, bank->base + bank->regs->direction); __raw_writel(bank->context.leveldetect0, - bank->base + OMAP24XX_GPIO_LEVELDETECT0); + bank->base + bank->regs->leveldetect0); __raw_writel(bank->context.leveldetect1, - bank->base + OMAP24XX_GPIO_LEVELDETECT1); + bank->base + bank->regs->leveldetect1); __raw_writel(bank->context.risingdetect, - bank->base + OMAP24XX_GPIO_RISINGDETECT); + bank->base + bank->regs->risingdetect); __raw_writel(bank->context.fallingdetect, - bank->base + OMAP24XX_GPIO_FALLINGDETECT); - __raw_writel(bank->context.dataout, - bank->base + OMAP24XX_GPIO_DATAOUT); + bank->base + bank->regs->fallingdetect); + __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); } #endif -- cgit v1.2.3 From 5e571f38f6a44ef541fac0821631509d787ef0cd Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 13 Sep 2011 15:02:14 +0530 Subject: gpio/omap: cleanup set_gpio_triggering function Getting rid of ifdefs within the function by adding register offset intctrl and associating OMAPXXXX_GPIO_INT_CONTROL in respective SoC specific files. Also, use wkup_status register consistently instead of referring to wakeup clear and wakeup set register offsets. Get rid of cpu_is_xxxx checks in set_gpio_trigger() using irqctrl. Signed-off-by: Charulatha V Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 2 + arch/arm/mach-omap1/gpio16xx.c | 3 + arch/arm/mach-omap1/gpio7xx.c | 2 + arch/arm/plat-omap/include/plat/gpio.h | 3 + drivers/gpio/gpio-omap.c | 157 +++++++++------------------------ 5 files changed, 53 insertions(+), 114 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index f8c15eabf06e..2adfece30ce6 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -42,6 +42,7 @@ static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { .irqstatus = OMAP_MPUIO_GPIO_INT, .irqenable = OMAP_MPUIO_GPIO_MASKIT, .irqenable_inv = true, + .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE, }; static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { @@ -83,6 +84,7 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = { .irqstatus = OMAP1510_GPIO_INT_STATUS, .irqenable = OMAP1510_GPIO_INT_MASK, .irqenable_inv = true, + .irqctrl = OMAP1510_GPIO_INT_CONTROL, }; static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 1eb47e2760d8..46bb57a8cb7d 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -45,6 +45,7 @@ static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { .irqstatus = OMAP_MPUIO_GPIO_INT, .irqenable = OMAP_MPUIO_GPIO_MASKIT, .irqenable_inv = true, + .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE, }; static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { @@ -90,6 +91,8 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = { .set_irqenable = OMAP1610_GPIO_SET_IRQENABLE1, .clr_irqenable = OMAP1610_GPIO_CLEAR_IRQENABLE1, .wkup_en = OMAP1610_GPIO_WAKEUPENABLE, + .edgectrl1 = OMAP1610_GPIO_EDGE_CTRL1, + .edgectrl2 = OMAP1610_GPIO_EDGE_CTRL2, }; static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 923eaa1df955..207a23cfa1a0 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -47,6 +47,7 @@ static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { .irqstatus = OMAP_MPUIO_GPIO_INT / 2, .irqenable = OMAP_MPUIO_GPIO_MASKIT / 2, .irqenable_inv = true, + .irqctrl = OMAP_MPUIO_GPIO_INT_EDGE >> 1, }; static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { @@ -88,6 +89,7 @@ static struct omap_gpio_reg_offs omap7xx_gpio_regs = { .irqstatus = OMAP7XX_GPIO_INT_STATUS, .irqenable = OMAP7XX_GPIO_INT_MASK, .irqenable_inv = true, + .irqctrl = OMAP7XX_GPIO_INT_CONTROL, }; static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 914c976b1de0..9e403e54f6f9 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -195,6 +195,9 @@ struct omap_gpio_reg_offs { u16 leveldetect1; u16 risingdetect; u16 fallingdetect; + u16 irqctrl; + u16 edgectrl1; + u16 edgectrl2; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index ceb9edf16dab..f39d9e4967b2 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -199,52 +199,32 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, __raw_writel(val, reg); } -#ifdef CONFIG_ARCH_OMAP2PLUS -static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, +static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, int trigger) { void __iomem *base = bank->base; u32 gpio_bit = 1 << gpio; - if (cpu_is_omap44xx()) { - _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - _gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - _gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); - } else { - _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - _gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - _gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); - } - if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { - if (cpu_is_omap44xx()) { - _gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit, - trigger != 0); - } else { - /* - * GPIO wakeup request can only be generated on edge - * transitions - */ - if (trigger & IRQ_TYPE_EDGE_BOTH) - __raw_writel(1 << gpio, bank->base - + OMAP24XX_GPIO_SETWKUENA); - else - __raw_writel(1 << gpio, bank->base - + OMAP24XX_GPIO_CLEARWKUENA); - } - } + _gpio_rmw(base, bank->regs->leveldetect0, gpio_bit, + trigger & IRQ_TYPE_LEVEL_LOW); + _gpio_rmw(base, bank->regs->leveldetect1, gpio_bit, + trigger & IRQ_TYPE_LEVEL_HIGH); + _gpio_rmw(base, bank->regs->risingdetect, gpio_bit, + trigger & IRQ_TYPE_EDGE_RISING); + _gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, + trigger & IRQ_TYPE_EDGE_FALLING); + + if (likely(!(bank->non_wakeup_gpios & gpio_bit))) + _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); + /* This part needs to be executed always for OMAP{34xx, 44xx} */ - if (cpu_is_omap34xx() || cpu_is_omap44xx() || - (bank->non_wakeup_gpios & gpio_bit)) { + if (!bank->regs->irqctrl) { + /* On omap24xx proceed only when valid GPIO bit is set */ + if (bank->non_wakeup_gpios) { + if (!(bank->non_wakeup_gpios & gpio_bit)) + goto exit; + } + /* * Log the edge gpio and manually trigger the IRQ * after resume if the input level changes @@ -257,11 +237,11 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, bank->enabled_non_wakeup_gpios &= ~gpio_bit; } +exit: bank->level_mask = __raw_readl(bank->base + bank->regs->leveldetect0) | __raw_readl(bank->base + bank->regs->leveldetect1); } -#endif #ifdef CONFIG_ARCH_OMAP1 /* @@ -273,23 +253,10 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) void __iomem *reg = bank->base; u32 l = 0; - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; - break; -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_CONTROL; - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_INT_CONTROL; - break; -#endif - default: + if (!bank->regs->irqctrl) return; - } + + reg += bank->regs->irqctrl; l = __raw_readl(reg); if ((l >> gpio) & 1) @@ -299,31 +266,21 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) __raw_writel(l, reg); } +#else +static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) {} #endif static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) { void __iomem *reg = bank->base; + void __iomem *base = bank->base; u32 l = 0; - switch (bank->method) { -#ifdef CONFIG_ARCH_OMAP1 - case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; - l = __raw_readl(reg); - if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) - bank->toggle_mask |= 1 << gpio; - if (trigger & IRQ_TYPE_EDGE_RISING) - l |= 1 << gpio; - else if (trigger & IRQ_TYPE_EDGE_FALLING) - l &= ~(1 << gpio); - else - goto bad; - break; -#endif -#ifdef CONFIG_ARCH_OMAP15XX - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_INT_CONTROL; + if (bank->regs->leveldetect0 && bank->regs->wkup_en) { + set_gpio_trigger(bank, gpio, trigger); + } else if (bank->regs->irqctrl) { + reg += bank->regs->irqctrl; + l = __raw_readl(reg); if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) bank->toggle_mask |= 1 << gpio; @@ -332,15 +289,15 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) else if (trigger & IRQ_TYPE_EDGE_FALLING) l &= ~(1 << gpio); else - goto bad; - break; -#endif -#ifdef CONFIG_ARCH_OMAP16XX - case METHOD_GPIO_1610: + return -EINVAL; + + __raw_writel(l, reg); + } else if (bank->regs->edgectrl1) { if (gpio & 0x08) - reg += OMAP1610_GPIO_EDGE_CTRL2; + reg += bank->regs->edgectrl2; else - reg += OMAP1610_GPIO_EDGE_CTRL1; + reg += bank->regs->edgectrl1; + gpio &= 0x07; l = __raw_readl(reg); l &= ~(3 << (gpio << 1)); @@ -348,40 +305,12 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) l |= 2 << (gpio << 1); if (trigger & IRQ_TYPE_EDGE_FALLING) l |= 1 << (gpio << 1); - if (trigger) - /* Enable wake-up during idle for dynamic tick */ - __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA); - else - __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA); - break; -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - case METHOD_GPIO_7XX: - reg += OMAP7XX_GPIO_INT_CONTROL; - l = __raw_readl(reg); - if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) - bank->toggle_mask |= 1 << gpio; - if (trigger & IRQ_TYPE_EDGE_RISING) - l |= 1 << gpio; - else if (trigger & IRQ_TYPE_EDGE_FALLING) - l &= ~(1 << gpio); - else - goto bad; - break; -#endif -#ifdef CONFIG_ARCH_OMAP2PLUS - case METHOD_GPIO_24XX: - case METHOD_GPIO_44XX: - set_24xx_gpio_triggering(bank, gpio, trigger); - return 0; -#endif - default: - goto bad; + + /* Enable wake-up during idle for dynamic tick */ + _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); + __raw_writel(l, reg); } - __raw_writel(l, reg); return 0; -bad: - return -EINVAL; } static int gpio_irq_type(struct irq_data *d, unsigned type) -- cgit v1.2.3 From ab985f0f7c2c0ef90b7c832f0c04f470dda0593d Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 13 Sep 2011 15:12:05 +0530 Subject: gpio/omap: cleanup omap_gpio_mod_init function With register offsets now defined for respective OMAP versions we can get rid of cpu_class_* checks. This function now has common initialization code for all OMAP versions. Initialization specific to OMAP16xx has been moved within omap16xx_gpio_init(). Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio16xx.c | 35 ++++++++++++++++++- drivers/gpio/gpio-omap.c | 77 +++++++++++++----------------------------- 2 files changed, 57 insertions(+), 55 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 46bb57a8cb7d..86ac41544a21 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -24,6 +24,9 @@ #define OMAP1610_GPIO4_BASE 0xfffbbc00 #define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE +/* smart idle, enable wakeup */ +#define SYSCONFIG_WORD 0x14 + /* mpu gpio */ static struct __initdata resource omap16xx_mpu_gpio_resources[] = { { @@ -218,12 +221,42 @@ static struct __initdata platform_device * omap16xx_gpio_dev[] = { static int __init omap16xx_gpio_init(void) { int i; + void __iomem *base; + struct resource *res; + struct platform_device *pdev; + struct omap_gpio_platform_data *pdata; if (!cpu_is_omap16xx()) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++) + for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++) { + pdev = omap16xx_gpio_dev[i]; + pdata = pdev->dev.platform_data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "Invalid mem resource.\n"); + return -ENODEV; + } + + base = ioremap(res->start, resource_size(res)); + if (unlikely(!base)) { + dev_err(&pdev->dev, "ioremap failed.\n"); + return -ENOMEM; + } + + __raw_writel(SYSCONFIG_WORD, base + OMAP1610_GPIO_SYSCONFIG); + iounmap(base); + + /* + * Enable system clock for GPIO module. + * The CAM_CLK_CTRL *is* really the right place. + */ + omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, + ULPD_CAM_CLK_CTRL); + platform_device_register(omap16xx_gpio_dev[i]); + } return 0; } diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f39d9e4967b2..a948351ad6c4 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -610,7 +610,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (!(isr & 1)) continue; -#ifdef CONFIG_ARCH_OMAP1 /* * Some chips can't respond to both rising and falling * at the same time. If this irq was requested with @@ -620,7 +619,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) */ if (bank->toggle_mask & (1 << gpio_index)) _toggle_gpio_edge_triggering(bank, gpio_index); -#endif generic_handle_irq(gpio_irq); } @@ -898,62 +896,30 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank) */ static struct lock_class_key gpio_lock_class; -/* TODO: Cleanup cpu_is_* checks */ static void omap_gpio_mod_init(struct gpio_bank *bank) { - if (cpu_class_is_omap2()) { - if (cpu_is_omap44xx()) { - __raw_writel(0xffffffff, bank->base + - OMAP4_GPIO_IRQSTATUSCLR0); - __raw_writel(0x00000000, bank->base + - OMAP4_GPIO_DEBOUNCENABLE); - /* Initialize interface clk ungated, module enabled */ - __raw_writel(0, bank->base + OMAP4_GPIO_CTRL); - } else if (cpu_is_omap34xx()) { - __raw_writel(0x00000000, bank->base + - OMAP24XX_GPIO_IRQENABLE1); - __raw_writel(0xffffffff, bank->base + - OMAP24XX_GPIO_IRQSTATUS1); - __raw_writel(0x00000000, bank->base + - OMAP24XX_GPIO_DEBOUNCE_EN); - - /* Initialize interface clk ungated, module enabled */ - __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); - } - } else if (cpu_class_is_omap1()) { - if (bank_is_mpuio(bank)) { - __raw_writew(0xffff, bank->base + - OMAP_MPUIO_GPIO_MASKIT / bank->stride); - mpuio_init(bank); - } - if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { - __raw_writew(0xffff, bank->base - + OMAP1510_GPIO_INT_MASK); - __raw_writew(0x0000, bank->base - + OMAP1510_GPIO_INT_STATUS); - } - if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) { - __raw_writew(0x0000, bank->base - + OMAP1610_GPIO_IRQENABLE1); - __raw_writew(0xffff, bank->base - + OMAP1610_GPIO_IRQSTATUS1); - __raw_writew(0x0014, bank->base - + OMAP1610_GPIO_SYSCONFIG); + void __iomem *base = bank->base; + u32 l = 0xffffffff; - /* - * Enable system clock for GPIO module. - * The CAM_CLK_CTRL *is* really the right place. - */ - omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, - ULPD_CAM_CLK_CTRL); - } - if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { - __raw_writel(0xffffffff, bank->base - + OMAP7XX_GPIO_INT_MASK); - __raw_writel(0x00000000, bank->base - + OMAP7XX_GPIO_INT_STATUS); - } + if (bank->width == 16) + l = 0xffff; + + if (bank_is_mpuio(bank)) { + __raw_writel(l, bank->base + bank->regs->irqenable); + return; } + + _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); + _gpio_rmw(base, bank->regs->irqstatus, l, + bank->regs->irqenable_inv == false); + _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->debounce_en != 0); + _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->ctrl != 0); + if (bank->regs->debounce_en) + _gpio_rmw(base, bank->regs->debounce_en, 0, 1); + + /* Initialize interface clk ungated, module enabled */ + if (bank->regs->ctrl) + _gpio_rmw(base, bank->regs->ctrl, 0, 1); } static __init void @@ -1104,6 +1070,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) pm_runtime_enable(bank->dev); pm_runtime_get_sync(bank->dev); + if (bank_is_mpuio(bank)) + mpuio_init(bank); + omap_gpio_mod_init(bank); omap_gpio_chip_init(bank); omap_gpio_show_rev(bank); -- cgit v1.2.3 From fad96ea825e7a8ee0c5b77292b470e4978157ee7 Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Wed, 25 May 2011 11:23:50 +0530 Subject: gpio/omap: use pinctrl offset instead of macro Use regs->pinctrl field instead of using the macro OMAP1510_GPIO_PIN_CONTROL Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 1 + arch/arm/plat-omap/include/plat/gpio.h | 1 + drivers/gpio/gpio-omap.c | 8 +++----- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 2adfece30ce6..950e467361d0 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -85,6 +85,7 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = { .irqenable = OMAP1510_GPIO_INT_MASK, .irqenable_inv = true, .irqctrl = OMAP1510_GPIO_INT_CONTROL, + .pinctrl = OMAP1510_GPIO_PIN_CONTROL, }; static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 9e403e54f6f9..8be165108aad 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -198,6 +198,7 @@ struct omap_gpio_reg_offs { u16 irqctrl; u16 edgectrl1; u16 edgectrl2; + u16 pinctrl; bool irqenable_inv; }; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a948351ad6c4..485b6b207ef9 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -490,15 +490,13 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) */ _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); -#ifdef CONFIG_ARCH_OMAP15XX - if (bank->method == METHOD_GPIO_1510) { - void __iomem *reg; + if (bank->regs->pinctrl) { + void __iomem *reg = bank->base + bank->regs->pinctrl; /* Claim the pin for MPU */ - reg = bank->base + OMAP1510_GPIO_PIN_CONTROL; __raw_writel(__raw_readl(reg) | (1 << offset), reg); } -#endif + if (bank->regs->ctrl && !bank->mod_usage) { void __iomem *reg = bank->base + bank->regs->ctrl; u32 ctrl; -- cgit v1.2.3 From d3901eaf1fc289e8175faa8c7c460d542b6eb7dd Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 27 Sep 2011 05:38:09 +0530 Subject: gpio/omap: remove unnecessary bit-masking for read access Remove un-necessary bit masking. Since the register are 4 byte aligned and readl would work as is. The 'enabled' mask is already taking care to mask for bank width. Signed-off-by: Charulatha V Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 485b6b207ef9..38beccc9e655 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -576,9 +576,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) enabled = _get_gpio_irqbank_mask(bank); isr_saved = isr = __raw_readl(isr_reg) & enabled; - if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) - isr &= 0x0000ffff; - if (bank->level_mask) level_mask = bank->level_mask & enabled; -- cgit v1.2.3 From d0d665a896c5b9a0aa60e8bac15c270cb59aa9e7 Mon Sep 17 00:00:00 2001 From: Charulatha V Date: Wed, 31 Aug 2011 00:02:21 +0530 Subject: gpio/omap: remove bank->method & METHOD_* macros The only bank->type (method) used in the OMAP GPIO driver is MPUIO type as they need to be handled separately. Identify the same using a flag and remove all METHOD_* macros. mpuio_init() function is defined under #ifdefs. It is required only in case of MPUIO bank type and only when PM operations are supported by it. This is applicable only in case of OMAP16xx SoC's MPUIO GPIO bank type. For all the other cases it is a dummy function. Hence clean up the same and remove all the OMAP SoC specific #ifdefs. Signed-off-by: Charulatha V Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Acked-by: Tony Lindgren Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/gpio15xx.c | 3 +-- arch/arm/mach-omap1/gpio16xx.c | 6 +----- arch/arm/mach-omap1/gpio7xx.c | 8 +------ arch/arm/mach-omap2/gpio.c | 2 -- arch/arm/plat-omap/include/plat/gpio.h | 8 +------ drivers/gpio/gpio-omap.c | 38 ++++++---------------------------- 6 files changed, 10 insertions(+), 55 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c index 950e467361d0..634903ef8292 100644 --- a/arch/arm/mach-omap1/gpio15xx.c +++ b/arch/arm/mach-omap1/gpio15xx.c @@ -47,7 +47,7 @@ static struct omap_gpio_reg_offs omap15xx_mpuio_regs = { static struct __initdata omap_gpio_platform_data omap15xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, - .bank_type = METHOD_MPUIO, + .is_mpuio = true, .bank_width = 16, .bank_stride = 1, .regs = &omap15xx_mpuio_regs, @@ -90,7 +90,6 @@ static struct omap_gpio_reg_offs omap15xx_gpio_regs = { static struct __initdata omap_gpio_platform_data omap15xx_gpio_config = { .virtual_irq_start = IH_GPIO_BASE, - .bank_type = METHOD_GPIO_1510, .bank_width = 16, .regs = &omap15xx_gpio_regs, }; diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 86ac41544a21..1c5f90e17427 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -53,7 +53,7 @@ static struct omap_gpio_reg_offs omap16xx_mpuio_regs = { static struct __initdata omap_gpio_platform_data omap16xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, - .bank_type = METHOD_MPUIO, + .is_mpuio = true, .bank_width = 16, .bank_stride = 1, .regs = &omap16xx_mpuio_regs, @@ -100,7 +100,6 @@ static struct omap_gpio_reg_offs omap16xx_gpio_regs = { static struct __initdata omap_gpio_platform_data omap16xx_gpio1_config = { .virtual_irq_start = IH_GPIO_BASE, - .bank_type = METHOD_GPIO_1610, .bank_width = 16, .regs = &omap16xx_gpio_regs, }; @@ -130,7 +129,6 @@ static struct __initdata resource omap16xx_gpio2_resources[] = { static struct __initdata omap_gpio_platform_data omap16xx_gpio2_config = { .virtual_irq_start = IH_GPIO_BASE + 16, - .bank_type = METHOD_GPIO_1610, .bank_width = 16, .regs = &omap16xx_gpio_regs, }; @@ -160,7 +158,6 @@ static struct __initdata resource omap16xx_gpio3_resources[] = { static struct __initdata omap_gpio_platform_data omap16xx_gpio3_config = { .virtual_irq_start = IH_GPIO_BASE + 32, - .bank_type = METHOD_GPIO_1610, .bank_width = 16, .regs = &omap16xx_gpio_regs, }; @@ -190,7 +187,6 @@ static struct __initdata resource omap16xx_gpio4_resources[] = { static struct __initdata omap_gpio_platform_data omap16xx_gpio4_config = { .virtual_irq_start = IH_GPIO_BASE + 48, - .bank_type = METHOD_GPIO_1610, .bank_width = 16, .regs = &omap16xx_gpio_regs, }; diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c index 207a23cfa1a0..433491cb73fa 100644 --- a/arch/arm/mach-omap1/gpio7xx.c +++ b/arch/arm/mach-omap1/gpio7xx.c @@ -52,8 +52,8 @@ static struct omap_gpio_reg_offs omap7xx_mpuio_regs = { static struct __initdata omap_gpio_platform_data omap7xx_mpu_gpio_config = { .virtual_irq_start = IH_MPUIO_BASE, - .bank_type = METHOD_MPUIO, .bank_width = 32, + .is_mpuio = true, .bank_stride = 2, .regs = &omap7xx_mpuio_regs, }; @@ -94,7 +94,6 @@ static struct omap_gpio_reg_offs omap7xx_gpio_regs = { static struct __initdata omap_gpio_platform_data omap7xx_gpio1_config = { .virtual_irq_start = IH_GPIO_BASE, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; @@ -124,7 +123,6 @@ static struct __initdata resource omap7xx_gpio2_resources[] = { static struct __initdata omap_gpio_platform_data omap7xx_gpio2_config = { .virtual_irq_start = IH_GPIO_BASE + 32, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; @@ -154,7 +152,6 @@ static struct __initdata resource omap7xx_gpio3_resources[] = { static struct __initdata omap_gpio_platform_data omap7xx_gpio3_config = { .virtual_irq_start = IH_GPIO_BASE + 64, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; @@ -184,7 +181,6 @@ static struct __initdata resource omap7xx_gpio4_resources[] = { static struct __initdata omap_gpio_platform_data omap7xx_gpio4_config = { .virtual_irq_start = IH_GPIO_BASE + 96, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; @@ -214,7 +210,6 @@ static struct __initdata resource omap7xx_gpio5_resources[] = { static struct __initdata omap_gpio_platform_data omap7xx_gpio5_config = { .virtual_irq_start = IH_GPIO_BASE + 128, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; @@ -244,7 +239,6 @@ static struct __initdata resource omap7xx_gpio6_resources[] = { static struct __initdata omap_gpio_platform_data omap7xx_gpio6_config = { .virtual_irq_start = IH_GPIO_BASE + 160, - .bank_type = METHOD_GPIO_7XX, .bank_width = 32, .regs = &omap7xx_gpio_regs, }; diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index f4c45ca2cc59..dfda6b3478b2 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -74,7 +74,6 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) /* fall through */ case 1: - pdata->bank_type = METHOD_GPIO_24XX; pdata->regs->revision = OMAP24XX_GPIO_REVISION; pdata->regs->direction = OMAP24XX_GPIO_OE; pdata->regs->datain = OMAP24XX_GPIO_DATAIN; @@ -97,7 +96,6 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) pdata->regs->fallingdetect = OMAP24XX_GPIO_FALLINGDETECT; break; case 2: - pdata->bank_type = METHOD_GPIO_44XX; pdata->regs->revision = OMAP4_GPIO_REVISION; pdata->regs->direction = OMAP4_GPIO_OE; pdata->regs->datain = OMAP4_GPIO_DATAIN; diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 8be165108aad..cb75b657b04b 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -162,13 +162,6 @@ IH_MPUIO_BASE + ((nr) & 0x0f) : \ IH_GPIO_BASE + (nr)) -#define METHOD_MPUIO 0 -#define METHOD_GPIO_1510 1 -#define METHOD_GPIO_1610 2 -#define METHOD_GPIO_7XX 3 -#define METHOD_GPIO_24XX 5 -#define METHOD_GPIO_44XX 6 - struct omap_gpio_dev_attr { int bank_width; /* GPIO bank width */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ @@ -210,6 +203,7 @@ struct omap_gpio_platform_data { int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ bool loses_context; /* whether the bank would ever lose context */ + bool is_mpuio; /* whether the bank is of type MPUIO */ u32 non_wakeup_gpios; struct omap_gpio_reg_offs *regs; diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 38beccc9e655..951d78435812 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -49,7 +49,6 @@ struct gpio_bank { void __iomem *base; u16 irq; u16 virtual_irq_start; - int method; u32 suspend_wakeup; u32 saved_wakeup; u32 non_wakeup_gpios; @@ -66,6 +65,7 @@ struct gpio_bank { u32 mod_usage; u32 dbck_enable_mask; struct device *dev; + bool is_mpuio; bool dbck_flag; bool loses_context; int stride; @@ -693,14 +693,6 @@ static struct irq_chip gpio_irq_chip = { /*---------------------------------------------------------------------*/ -#ifdef CONFIG_ARCH_OMAP1 - -#define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO) - -#ifdef CONFIG_ARCH_OMAP16XX - -#include - static int omap_mpuio_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -762,23 +754,8 @@ static inline void mpuio_init(struct gpio_bank *bank) (void) platform_device_register(&omap_mpuio_device); } -#else -static inline void mpuio_init(struct gpio_bank *bank) {} -#endif /* 16xx */ - -#else - -#define bank_is_mpuio(bank) 0 -static inline void mpuio_init(struct gpio_bank *bank) {} - -#endif - /*---------------------------------------------------------------------*/ -/* REVISIT these are stupid implementations! replace by ones that - * don't switch on METHOD_* and which mostly avoid spinlocks - */ - static int gpio_input(struct gpio_chip *chip, unsigned offset) { struct gpio_bank *bank; @@ -899,7 +876,7 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) if (bank->width == 16) l = 0xffff; - if (bank_is_mpuio(bank)) { + if (bank->is_mpuio) { __raw_writel(l, bank->base + bank->regs->irqenable); return; } @@ -951,7 +928,6 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) int j; static int gpio; - bank->mod_usage = 0; /* * REVISIT eventually switch from OMAP-specific gpio structs * over to the generic ones @@ -964,12 +940,10 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) bank->chip.set_debounce = gpio_debounce; bank->chip.set = gpio_set; bank->chip.to_irq = gpio_2irq; - if (bank_is_mpuio(bank)) { + if (bank->is_mpuio) { bank->chip.label = "mpuio"; -#ifdef CONFIG_ARCH_OMAP16XX if (bank->regs->wkup_en) bank->chip.dev = &omap_mpuio_device.dev; -#endif bank->chip.base = OMAP_MPUIO(0); } else { bank->chip.label = "gpio"; @@ -984,7 +958,7 @@ static void __devinit omap_gpio_chip_init(struct gpio_bank *bank) j < bank->virtual_irq_start + bank->width; j++) { irq_set_lockdep_class(j, &gpio_lock_class); irq_set_chip_data(j, bank); - if (bank_is_mpuio(bank)) { + if (bank->is_mpuio) { omap_mpuio_alloc_gc(bank, j, bank->width); } else { irq_set_chip(j, &gpio_irq_chip); @@ -1028,11 +1002,11 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) pdata = pdev->dev.platform_data; bank->virtual_irq_start = pdata->virtual_irq_start; - bank->method = pdata->bank_type; bank->dev = &pdev->dev; bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; + bank->is_mpuio = pdata->is_mpuio; bank->non_wakeup_gpios = pdata->non_wakeup_gpios; bank->loses_context = pdata->loses_context; bank->get_context_loss_count = pdata->get_context_loss_count; @@ -1065,7 +1039,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) pm_runtime_enable(bank->dev); pm_runtime_get_sync(bank->dev); - if (bank_is_mpuio(bank)) + if (bank->is_mpuio) mpuio_init(bank); omap_gpio_mod_init(bank); -- cgit v1.2.3 From 55b93c32520dc7ff0097db81db9b1e6b735951a9 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 29 Sep 2011 07:23:22 +0530 Subject: gpio/omap: use pm-runtime framework Call runtime pm APIs pm_runtime_get_sync() and pm_runtime_put() for enabling/disabling clocks appropriately. Remove syscore_ops and instead use SET_RUNTIME_PM_OPS macro. There is no more need to call omap_device_disable_idle_on_suspend since driver is PM runtime adapted now. Signed-off-by: Charulatha V Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/gpio.c | 2 -- drivers/gpio/gpio-omap.c | 68 ++++++++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 26 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index dfda6b3478b2..1e0b750afcaa 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -136,8 +136,6 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) return PTR_ERR(pdev); } - omap_device_disable_idle_on_suspend(pdev); - return 0; } diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 951d78435812..7e1e50c23f93 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -483,8 +484,14 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - spin_lock_irqsave(&bank->lock, flags); + /* + * If this is the first gpio_request for the bank, + * enable the bank module. + */ + if (!bank->mod_usage) + pm_runtime_get_sync(bank->dev); + spin_lock_irqsave(&bank->lock, flags); /* Set trigger to none. You need to enable the desired trigger with * request_irq() or set_irq_type(). */ @@ -540,6 +547,13 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) _reset_gpio(bank, bank->chip.base + offset); spin_unlock_irqrestore(&bank->lock, flags); + + /* + * If this is the last gpio to be freed in the bank, + * disable the bank module. + */ + if (!bank->mod_usage) + pm_runtime_put(bank->dev); } /* @@ -565,6 +579,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) bank = irq_get_handler_data(irq); isr_reg = bank->base + bank->regs->irqstatus; + pm_runtime_get_sync(bank->dev); if (WARN_ON(!isr_reg)) goto exit; @@ -625,6 +640,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) exit: if (!unmasked) chained_irq_exit(chip, desc); + pm_runtime_put(bank->dev); } static void gpio_irq_shutdown(struct irq_data *d) @@ -1037,6 +1053,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) } pm_runtime_enable(bank->dev); + pm_runtime_irq_safe(bank->dev); pm_runtime_get_sync(bank->dev); if (bank->is_mpuio) @@ -1046,6 +1063,8 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) omap_gpio_chip_init(bank); omap_gpio_show_rev(bank); + pm_runtime_put(bank->dev); + list_add_tail(&bank->node, &omap_gpio_list); return ret; @@ -1056,7 +1075,10 @@ err_exit: return ret; } -static int omap_gpio_suspend(void) +#ifdef CONFIG_ARCH_OMAP2PLUS + +#if defined(CONFIG_PM_SLEEP) +static int omap_gpio_suspend(struct device *dev) { struct gpio_bank *bank; @@ -1080,7 +1102,7 @@ static int omap_gpio_suspend(void) return 0; } -static void omap_gpio_resume(void) +static int omap_gpio_resume(struct device *dev) { struct gpio_bank *bank; @@ -1089,21 +1111,17 @@ static void omap_gpio_resume(void) unsigned long flags; if (!bank->regs->wkup_en) - return; + return 0; spin_lock_irqsave(&bank->lock, flags); _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); spin_unlock_irqrestore(&bank->lock, flags); } -} - -static struct syscore_ops omap_gpio_syscore_ops = { - .suspend = omap_gpio_suspend, - .resume = omap_gpio_resume, -}; -#ifdef CONFIG_ARCH_OMAP2PLUS + return 0; +} +#endif /* CONFIG_PM_SLEEP */ static void omap_gpio_save_context(struct gpio_bank *bank); static void omap_gpio_restore_context(struct gpio_bank *bank); @@ -1145,11 +1163,15 @@ void omap2_gpio_prepare_for_idle(int off_mode) __raw_writel(l2, bank->base + bank->regs->risingdetect); save_gpio_context: + if (bank->get_context_loss_count) bank->context_loss_count = bank->get_context_loss_count(bank->dev); omap_gpio_save_context(bank); + + if (!pm_runtime_suspended(bank->dev)) + pm_runtime_put(bank->dev); } } @@ -1168,6 +1190,9 @@ void omap2_gpio_resume_after_idle(void) for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) clk_enable(bank->dbck); + if (pm_runtime_suspended(bank->dev)) + pm_runtime_get_sync(bank->dev); + if (bank->get_context_loss_count) { context_lost_cnt_after = bank->get_context_loss_count(bank->dev); @@ -1274,12 +1299,20 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) bank->base + bank->regs->fallingdetect); __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); } +#else +#define omap_gpio_suspend NULL +#define omap_gpio_resume NULL #endif +static const struct dev_pm_ops gpio_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) +}; + static struct platform_driver omap_gpio_driver = { .probe = omap_gpio_probe, .driver = { .name = "omap_gpio", + .pm = &gpio_pm_ops, }, }; @@ -1293,16 +1326,3 @@ static int __init omap_gpio_drv_reg(void) return platform_driver_register(&omap_gpio_driver); } postcore_initcall(omap_gpio_drv_reg); - -static int __init omap_gpio_sysinit(void) -{ - -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) - if (cpu_is_omap16xx() || cpu_class_is_omap2()) - register_syscore_ops(&omap_gpio_syscore_ops); -#endif - - return 0; -} - -arch_initcall(omap_gpio_sysinit); -- cgit v1.2.3 From 065cd795d2721f8d2d1f2967ee6ed0aec07a4202 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 24 Nov 2011 01:48:52 +0530 Subject: gpio/omap: optimize suspend and resume functions There is no need to operate on all the banks every time the function is called. Just operate on the current bank passed by the framework. Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 54 ++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 7e1e50c23f93..e9a30fa8715b 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1052,6 +1052,8 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) goto err_free; } + platform_set_drvdata(pdev, bank); + pm_runtime_enable(bank->dev); pm_runtime_irq_safe(bank->dev); pm_runtime_get_sync(bank->dev); @@ -1080,44 +1082,46 @@ err_exit: #if defined(CONFIG_PM_SLEEP) static int omap_gpio_suspend(struct device *dev) { - struct gpio_bank *bank; + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + void __iomem *base = bank->base; + void __iomem *wakeup_enable; + unsigned long flags; - list_for_each_entry(bank, &omap_gpio_list, node) { - void __iomem *base = bank->base; - void __iomem *wake_status; - unsigned long flags; + if (!bank->mod_usage || !bank->loses_context) + return 0; - if (!bank->regs->wkup_en) - return 0; + if (!bank->regs->wkup_en || !bank->suspend_wakeup) + return 0; - wake_status = bank->base + bank->regs->wkup_en; + wakeup_enable = bank->base + bank->regs->wkup_en; - spin_lock_irqsave(&bank->lock, flags); - bank->saved_wakeup = __raw_readl(wake_status); - _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); - _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); - spin_unlock_irqrestore(&bank->lock, flags); - } + spin_lock_irqsave(&bank->lock, flags); + bank->saved_wakeup = __raw_readl(wakeup_enable); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); + spin_unlock_irqrestore(&bank->lock, flags); return 0; } static int omap_gpio_resume(struct device *dev) { - struct gpio_bank *bank; + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + void __iomem *base = bank->base; + unsigned long flags; - list_for_each_entry(bank, &omap_gpio_list, node) { - void __iomem *base = bank->base; - unsigned long flags; + if (!bank->mod_usage || !bank->loses_context) + return 0; - if (!bank->regs->wkup_en) - return 0; + if (!bank->regs->wkup_en || !bank->saved_wakeup) + return 0; - spin_lock_irqsave(&bank->lock, flags); - _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); - _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); - spin_unlock_irqrestore(&bank->lock, flags); - } + spin_lock_irqsave(&bank->lock, flags); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); + spin_unlock_irqrestore(&bank->lock, flags); return 0; } -- cgit v1.2.3 From 2dc983c565e03f6f6f96c5fe7449b65d86af4dee Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 24 Nov 2011 02:44:29 +0530 Subject: gpio/omap: cleanup prepare_for_idle and resume_after_idle Since *_prepare_for_idle() and *_resume_after_idle() are called with interrupts disabled they should be kept as simple as possible. So, moving most of the stuff to *_runtime_suspend/resume() callbacks. To avoid invalid context restore happening in *_runtime_resume() callback as a result of *_get_sync() call in *_gpio_probe(), update bank->context_loss_count. This would make context restore condition check false in the callback and skip restore until further initialization take place. The workaround_enabled static variable is now a member of struct gpio_bank. Unlike most GPIO registers the OE has 0xffffffff as the default value. To make sure invalid context is not restored, updating the OE context with default value. Signed-off-by: Tarun Kanti DebBarma Signed-off-by: Charulatha V Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 245 ++++++++++++++++++++++++++++------------------- 1 file changed, 147 insertions(+), 98 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e9a30fa8715b..d483cc9f0c63 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -29,6 +29,8 @@ #include #include +#define OFF_MODE 1 + static LIST_HEAD(omap_gpio_list); struct gpio_regs { @@ -73,6 +75,8 @@ struct gpio_bank { u32 width; int context_loss_count; u16 id; + int power_mode; + bool workaround_enabled; void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); int (*get_context_loss_count)(struct device *dev); @@ -905,6 +909,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) if (bank->regs->debounce_en) _gpio_rmw(base, bank->regs->debounce_en, 0, 1); + /* Save OE default value (0xffffffff) in the context */ + bank->context.oe = __raw_readl(bank->base + bank->regs->direction); /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) _gpio_rmw(base, bank->regs->ctrl, 0, 1); @@ -1127,141 +1133,179 @@ static int omap_gpio_resume(struct device *dev) } #endif /* CONFIG_PM_SLEEP */ +#if defined(CONFIG_PM_RUNTIME) static void omap_gpio_save_context(struct gpio_bank *bank); static void omap_gpio_restore_context(struct gpio_bank *bank); -void omap2_gpio_prepare_for_idle(int off_mode) +static int omap_gpio_runtime_suspend(struct device *dev) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - u32 l1 = 0, l2 = 0; - int j; - - if (!bank->loses_context) - continue; - - for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) - clk_disable(bank->dbck); + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + u32 l1 = 0, l2 = 0; + unsigned long flags; - if (!off_mode) - continue; + spin_lock_irqsave(&bank->lock, flags); + if (bank->power_mode != OFF_MODE) { + bank->power_mode = 0; + goto save_gpio_context; + } + /* + * If going to OFF, remove triggering for all + * non-wakeup GPIOs. Otherwise spurious IRQs will be + * generated. See OMAP2420 Errata item 1.101. + */ + if (!(bank->enabled_non_wakeup_gpios)) + goto save_gpio_context; - /* If going to OFF, remove triggering for all - * non-wakeup GPIOs. Otherwise spurious IRQs will be - * generated. See OMAP2420 Errata item 1.101. */ - if (!(bank->enabled_non_wakeup_gpios)) - goto save_gpio_context; + bank->saved_datain = __raw_readl(bank->base + + bank->regs->datain); + l1 = __raw_readl(bank->base + bank->regs->fallingdetect); + l2 = __raw_readl(bank->base + bank->regs->risingdetect); - bank->saved_datain = __raw_readl(bank->base + - bank->regs->datain); - l1 = __raw_readl(bank->base + bank->regs->fallingdetect); - l2 = __raw_readl(bank->base + bank->regs->risingdetect); + bank->saved_fallingdetect = l1; + bank->saved_risingdetect = l2; + l1 &= ~bank->enabled_non_wakeup_gpios; + l2 &= ~bank->enabled_non_wakeup_gpios; - bank->saved_fallingdetect = l1; - bank->saved_risingdetect = l2; - l1 &= ~bank->enabled_non_wakeup_gpios; - l2 &= ~bank->enabled_non_wakeup_gpios; + __raw_writel(l1, bank->base + bank->regs->fallingdetect); + __raw_writel(l2, bank->base + bank->regs->risingdetect); - __raw_writel(l1, bank->base + bank->regs->fallingdetect); - __raw_writel(l2, bank->base + bank->regs->risingdetect); + bank->workaround_enabled = true; save_gpio_context: - - if (bank->get_context_loss_count) - bank->context_loss_count = + if (bank->get_context_loss_count) + bank->context_loss_count = bank->get_context_loss_count(bank->dev); - omap_gpio_save_context(bank); + omap_gpio_save_context(bank); + spin_unlock_irqrestore(&bank->lock, flags); - if (!pm_runtime_suspended(bank->dev)) - pm_runtime_put(bank->dev); - } + return 0; } -void omap2_gpio_resume_after_idle(void) +static int omap_gpio_runtime_resume(struct device *dev) { - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - int context_lost_cnt_after; - u32 l = 0, gen, gen0, gen1; - int j; - - if (!bank->loses_context) - continue; - - for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) - clk_enable(bank->dbck); + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + int context_lost_cnt_after; + u32 l = 0, gen, gen0, gen1; + unsigned long flags; - if (pm_runtime_suspended(bank->dev)) - pm_runtime_get_sync(bank->dev); + spin_lock_irqsave(&bank->lock, flags); + if (!bank->enabled_non_wakeup_gpios || !bank->workaround_enabled) { + spin_unlock_irqrestore(&bank->lock, flags); + return 0; + } - if (bank->get_context_loss_count) { - context_lost_cnt_after = - bank->get_context_loss_count(bank->dev); - if (context_lost_cnt_after != bank->context_loss_count - || !context_lost_cnt_after) - omap_gpio_restore_context(bank); + if (bank->get_context_loss_count) { + context_lost_cnt_after = + bank->get_context_loss_count(bank->dev); + if (context_lost_cnt_after != bank->context_loss_count || + !context_lost_cnt_after) { + omap_gpio_restore_context(bank); + } else { + spin_unlock_irqrestore(&bank->lock, flags); + return 0; } + } - if (!(bank->enabled_non_wakeup_gpios)) - continue; + __raw_writel(bank->saved_fallingdetect, + bank->base + bank->regs->fallingdetect); + __raw_writel(bank->saved_risingdetect, + bank->base + bank->regs->risingdetect); + l = __raw_readl(bank->base + bank->regs->datain); - __raw_writel(bank->saved_fallingdetect, - bank->base + bank->regs->fallingdetect); - __raw_writel(bank->saved_risingdetect, - bank->base + bank->regs->risingdetect); - l = __raw_readl(bank->base + bank->regs->datain); + /* + * Check if any of the non-wakeup interrupt GPIOs have changed + * state. If so, generate an IRQ by software. This is + * horribly racy, but it's the best we can do to work around + * this silicon bug. + */ + l ^= bank->saved_datain; + l &= bank->enabled_non_wakeup_gpios; - /* Check if any of the non-wakeup interrupt GPIOs have changed - * state. If so, generate an IRQ by software. This is - * horribly racy, but it's the best we can do to work around - * this silicon bug. */ - l ^= bank->saved_datain; - l &= bank->enabled_non_wakeup_gpios; + /* + * No need to generate IRQs for the rising edge for gpio IRQs + * configured with falling edge only; and vice versa. + */ + gen0 = l & bank->saved_fallingdetect; + gen0 &= bank->saved_datain; - /* - * No need to generate IRQs for the rising edge for gpio IRQs - * configured with falling edge only; and vice versa. - */ - gen0 = l & bank->saved_fallingdetect; - gen0 &= bank->saved_datain; + gen1 = l & bank->saved_risingdetect; + gen1 &= ~(bank->saved_datain); - gen1 = l & bank->saved_risingdetect; - gen1 &= ~(bank->saved_datain); + /* FIXME: Consider GPIO IRQs with level detections properly! */ + gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect)); + /* Consider all GPIO IRQs needed to be updated */ + gen |= gen0 | gen1; - /* FIXME: Consider GPIO IRQs with level detections properly! */ - gen = l & (~(bank->saved_fallingdetect) & - ~(bank->saved_risingdetect)); - /* Consider all GPIO IRQs needed to be updated */ - gen |= gen0 | gen1; + if (gen) { + u32 old0, old1; - if (gen) { - u32 old0, old1; + old0 = __raw_readl(bank->base + bank->regs->leveldetect0); + old1 = __raw_readl(bank->base + bank->regs->leveldetect1); - old0 = __raw_readl(bank->base + + if (cpu_is_omap24xx() || cpu_is_omap34xx()) { + __raw_writel(old0 | gen, bank->base + bank->regs->leveldetect0); - old1 = __raw_readl(bank->base + + __raw_writel(old1 | gen, bank->base + bank->regs->leveldetect1); + } - if (cpu_is_omap24xx() || cpu_is_omap34xx()) { - old0 |= gen; - old1 |= gen; - } - - if (cpu_is_omap44xx()) { - old0 |= l; - old1 |= l; - } - __raw_writel(old0, bank->base + + if (cpu_is_omap44xx()) { + __raw_writel(old0 | l, bank->base + bank->regs->leveldetect0); - __raw_writel(old1, bank->base + + __raw_writel(old1 | l, bank->base + bank->regs->leveldetect1); } + __raw_writel(old0, bank->base + bank->regs->leveldetect0); + __raw_writel(old1, bank->base + bank->regs->leveldetect1); + } + + bank->workaround_enabled = false; + spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} +#endif /* CONFIG_PM_RUNTIME */ + +void omap2_gpio_prepare_for_idle(int pwr_mode) +{ + struct gpio_bank *bank; + + list_for_each_entry(bank, &omap_gpio_list, node) { + int j; + + if (!bank->mod_usage || !bank->loses_context) + continue; + + bank->power_mode = pwr_mode; + + for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) + clk_disable(bank->dbck); + + pm_runtime_put_sync_suspend(bank->dev); + } +} + +void omap2_gpio_resume_after_idle(void) +{ + struct gpio_bank *bank; + + list_for_each_entry(bank, &omap_gpio_list, node) { + int j; + + if (!bank->mod_usage || !bank->loses_context) + continue; + + for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) + clk_enable(bank->dbck); + + pm_runtime_get_sync(bank->dev); } } +#if defined(CONFIG_PM_RUNTIME) static void omap_gpio_save_context(struct gpio_bank *bank) { bank->context.irqenable1 = @@ -1303,13 +1347,18 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) bank->base + bank->regs->fallingdetect); __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); } +#endif /* CONFIG_PM_RUNTIME */ #else #define omap_gpio_suspend NULL #define omap_gpio_resume NULL +#define omap_gpio_runtime_suspend NULL +#define omap_gpio_runtime_resume NULL #endif static const struct dev_pm_ops gpio_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) + SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, + NULL) }; static struct platform_driver omap_gpio_driver = { -- cgit v1.2.3 From 72f83af99838bb663f85b65386db5b875748f379 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 24 Nov 2011 03:03:28 +0530 Subject: gpio/omap: fix debounce clock handling The dbck_enable_mask indicates which all GPIOs within a bank have debounce enabled and dbck is enabled/disabled based upon this. But there is no mechanism to track the dbck state. In order to manage the dbck state we need additional flag and logic so that turning off/on dbck is synchronized with pm_runtime_put/get_sync calls. Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d483cc9f0c63..69e61aecab71 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -67,6 +67,7 @@ struct gpio_bank { struct clk *dbck; u32 mod_usage; u32 dbck_enable_mask; + bool dbck_enabled; struct device *dev; bool is_mpuio; bool dbck_flag; @@ -158,6 +159,22 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set) __raw_writel(l, base + reg); } +static inline void _gpio_dbck_enable(struct gpio_bank *bank) +{ + if (bank->dbck_enable_mask && !bank->dbck_enabled) { + clk_enable(bank->dbck); + bank->dbck_enabled = true; + } +} + +static inline void _gpio_dbck_disable(struct gpio_bank *bank) +{ + if (bank->dbck_enable_mask && bank->dbck_enabled) { + clk_disable(bank->dbck); + bank->dbck_enabled = false; + } +} + /** * _set_gpio_debounce - low level gpio debounce time * @bank: the gpio bank we're acting upon @@ -1178,6 +1195,7 @@ save_gpio_context: bank->get_context_loss_count(bank->dev); omap_gpio_save_context(bank); + _gpio_dbck_disable(bank); spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1192,6 +1210,7 @@ static int omap_gpio_runtime_resume(struct device *dev) unsigned long flags; spin_lock_irqsave(&bank->lock, flags); + _gpio_dbck_enable(bank); if (!bank->enabled_non_wakeup_gpios || !bank->workaround_enabled) { spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1274,16 +1293,11 @@ void omap2_gpio_prepare_for_idle(int pwr_mode) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - int j; - if (!bank->mod_usage || !bank->loses_context) continue; bank->power_mode = pwr_mode; - for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) - clk_disable(bank->dbck); - pm_runtime_put_sync_suspend(bank->dev); } } @@ -1293,14 +1307,9 @@ void omap2_gpio_resume_after_idle(void) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - int j; - if (!bank->mod_usage || !bank->loses_context) continue; - for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) - clk_enable(bank->dbck); - pm_runtime_get_sync(bank->dev); } } -- cgit v1.2.3 From 6fd9c421649961a9d6d30b149e0128dde1b806b4 Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Thu, 24 Nov 2011 03:58:54 +0530 Subject: gpio/omap: fix incorrect access of debounce module Enable debounce clock before writing/reading debounce registers. Disable the clock at the end so that it is synchronized with the pm_runtime_get/put_sync calls. Enable debounce clock per module. This call is mandatory because in omap_gpio_request() when *_runtime_get_sync() is called, _gpio_dbck_enable() within runtime callbck fails to turn on dbck because dbck_enable_mask used within _gpio_dbck_enable() is still not initialized at that point. Therefore we have to enable dbck here. Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 69e61aecab71..8aeb8dd4342b 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -203,22 +203,30 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, l = GPIO_BIT(bank, gpio); + clk_enable(bank->dbck); reg = bank->base + bank->regs->debounce; __raw_writel(debounce, reg); reg = bank->base + bank->regs->debounce_en; val = __raw_readl(reg); - if (debounce) { + if (debounce) val |= l; - clk_enable(bank->dbck); - } else { + else val &= ~l; - clk_disable(bank->dbck); - } bank->dbck_enable_mask = val; __raw_writel(val, reg); + clk_disable(bank->dbck); + /* + * Enable debounce clock per module. + * This call is mandatory because in omap_gpio_request() when + * *_runtime_get_sync() is called, _gpio_dbck_enable() within + * runtime callbck fails to turn on dbck because dbck_enable_mask + * used within _gpio_dbck_enable() is still not initialized at + * that point. Therefore we have to enable dbck here. + */ + _gpio_dbck_enable(bank); } static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, -- cgit v1.2.3 From 41d87cbd660fd5793a6c70f9c93d9dcc8964179d Mon Sep 17 00:00:00 2001 From: Tarun Kanti DebBarma Date: Tue, 15 Nov 2011 12:52:38 +0530 Subject: gpio/omap: remove omap_gpio_save_context overhead Context is now saved dynamically in respective functions whenever and whichever registers are modified. This avoid overhead of saving all registers context in the runtime suspend callback. Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 8aeb8dd4342b..62c49e0f7f29 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -101,6 +101,7 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) else l &= ~(1 << gpio); __raw_writel(l, reg); + bank->context.oe = l; } @@ -131,6 +132,7 @@ static void _set_gpio_dataout_mask(struct gpio_bank *bank, int gpio, int enable) else l &= ~gpio_bit; __raw_writel(l, reg); + bank->context.dataout = l; } static int _get_gpio_datain(struct gpio_bank *bank, int gpio) @@ -244,8 +246,20 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, _gpio_rmw(base, bank->regs->fallingdetect, gpio_bit, trigger & IRQ_TYPE_EDGE_FALLING); - if (likely(!(bank->non_wakeup_gpios & gpio_bit))) + bank->context.leveldetect0 = + __raw_readl(bank->base + bank->regs->leveldetect0); + bank->context.leveldetect1 = + __raw_readl(bank->base + bank->regs->leveldetect1); + bank->context.risingdetect = + __raw_readl(bank->base + bank->regs->risingdetect); + bank->context.fallingdetect = + __raw_readl(bank->base + bank->regs->fallingdetect); + + if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { _gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); + bank->context.wake_en = + __raw_readl(bank->base + bank->regs->wkup_en); + } /* This part needs to be executed always for OMAP{34xx, 44xx} */ if (!bank->regs->irqctrl) { @@ -338,6 +352,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) /* Enable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger); + bank->context.wake_en = + __raw_readl(bank->base + bank->regs->wkup_en); __raw_writel(l, reg); } return 0; @@ -430,6 +446,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) } __raw_writel(l, reg); + bank->context.irqenable1 = l; } static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) @@ -450,6 +467,7 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) } __raw_writel(l, reg); + bank->context.irqenable1 = l; } static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) @@ -541,6 +559,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) /* Module is enabled, clocks are not gated */ ctrl &= ~GPIO_MOD_CTRL_BIT; __raw_writel(ctrl, reg); + bank->context.ctrl = ctrl; } bank->mod_usage |= 1 << offset; @@ -558,9 +577,12 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&bank->lock, flags); - if (bank->regs->wkup_en) + if (bank->regs->wkup_en) { /* Disable wake-up during idle for dynamic tick */ _gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0); + bank->context.wake_en = + __raw_readl(bank->base + bank->regs->wkup_en); + } bank->mod_usage &= ~(1 << offset); @@ -572,6 +594,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) /* Module is disabled, clocks are gated */ ctrl |= GPIO_MOD_CTRL_BIT; __raw_writel(ctrl, reg); + bank->context.ctrl = ctrl; } _reset_gpio(bank, bank->chip.base + offset); @@ -1159,7 +1182,6 @@ static int omap_gpio_resume(struct device *dev) #endif /* CONFIG_PM_SLEEP */ #if defined(CONFIG_PM_RUNTIME) -static void omap_gpio_save_context(struct gpio_bank *bank); static void omap_gpio_restore_context(struct gpio_bank *bank); static int omap_gpio_runtime_suspend(struct device *dev) @@ -1172,7 +1194,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) spin_lock_irqsave(&bank->lock, flags); if (bank->power_mode != OFF_MODE) { bank->power_mode = 0; - goto save_gpio_context; + goto update_gpio_context_count; } /* * If going to OFF, remove triggering for all @@ -1180,7 +1202,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) * generated. See OMAP2420 Errata item 1.101. */ if (!(bank->enabled_non_wakeup_gpios)) - goto save_gpio_context; + goto update_gpio_context_count; bank->saved_datain = __raw_readl(bank->base + bank->regs->datain); @@ -1197,12 +1219,11 @@ static int omap_gpio_runtime_suspend(struct device *dev) bank->workaround_enabled = true; -save_gpio_context: +update_gpio_context_count: if (bank->get_context_loss_count) bank->context_loss_count = bank->get_context_loss_count(bank->dev); - omap_gpio_save_context(bank); _gpio_dbck_disable(bank); spin_unlock_irqrestore(&bank->lock, flags); @@ -1323,27 +1344,6 @@ void omap2_gpio_resume_after_idle(void) } #if defined(CONFIG_PM_RUNTIME) -static void omap_gpio_save_context(struct gpio_bank *bank) -{ - bank->context.irqenable1 = - __raw_readl(bank->base + bank->regs->irqenable); - bank->context.irqenable2 = - __raw_readl(bank->base + bank->regs->irqenable2); - bank->context.wake_en = - __raw_readl(bank->base + bank->regs->wkup_en); - bank->context.ctrl = __raw_readl(bank->base + bank->regs->ctrl); - bank->context.oe = __raw_readl(bank->base + bank->regs->direction); - bank->context.leveldetect0 = - __raw_readl(bank->base + bank->regs->leveldetect0); - bank->context.leveldetect1 = - __raw_readl(bank->base + bank->regs->leveldetect1); - bank->context.risingdetect = - __raw_readl(bank->base + bank->regs->risingdetect); - bank->context.fallingdetect = - __raw_readl(bank->base + bank->regs->fallingdetect); - bank->context.dataout = __raw_readl(bank->base + bank->regs->dataout); -} - static void omap_gpio_restore_context(struct gpio_bank *bank) { __raw_writel(bank->context.irqenable1, -- cgit v1.2.3 From ae547354a8ed59f19b57f7e1de9c7816edfc3537 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Fri, 9 Sep 2011 19:08:58 +0530 Subject: gpio/omap: save and restore debounce registers GPIO debounce registers need to be saved and restored for proper functioning of driver. Signed-off-by: Nishanth Menon tarun.kanti@ti.com: Debounce context save is moved to _set_gpio_debounce() as part of dynamic context save to remove overhead. Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 62c49e0f7f29..f6b2c51b2935 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -44,6 +44,8 @@ struct gpio_regs { u32 risingdetect; u32 fallingdetect; u32 dataout; + u32 debounce; + u32 debounce_en; }; struct gpio_bank { @@ -229,6 +231,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, * that point. Therefore we have to enable dbck here. */ _gpio_dbck_enable(bank); + if (bank->dbck_enable_mask) { + bank->context.debounce = debounce; + bank->context.debounce_en = val; + } } static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, @@ -1363,6 +1369,12 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) __raw_writel(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); + if (bank->dbck_enable_mask) { + __raw_writel(bank->context.debounce, bank->base + + bank->regs->debounce); + __raw_writel(bank->context.debounce_en, + bank->base + bank->regs->debounce_en); + } } #endif /* CONFIG_PM_RUNTIME */ #else -- cgit v1.2.3 From ba805be53cb9112917631d368f859af5e20d695f Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 29 Aug 2011 18:41:08 +0530 Subject: gpio/omap: enable irq at the end of all configuration in restore Setup the interrupt enable registers only after we have configured the required edge and required configurations, not before, to prevent spurious events as part of restore routine. Signed-off-by: Nishanth Menon Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index f6b2c51b2935..41265e823b23 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1352,10 +1352,6 @@ void omap2_gpio_resume_after_idle(void) #if defined(CONFIG_PM_RUNTIME) static void omap_gpio_restore_context(struct gpio_bank *bank) { - __raw_writel(bank->context.irqenable1, - bank->base + bank->regs->irqenable); - __raw_writel(bank->context.irqenable2, - bank->base + bank->regs->irqenable2); __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); @@ -1375,6 +1371,11 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) __raw_writel(bank->context.debounce_en, bank->base + bank->regs->debounce_en); } + + __raw_writel(bank->context.irqenable1, + bank->base + bank->regs->irqenable); + __raw_writel(bank->context.irqenable2, + bank->base + bank->regs->irqenable2); } #endif /* CONFIG_PM_RUNTIME */ #else -- cgit v1.2.3 From 6d13eaaf33436e20d1a41122f28434bcc37999dc Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 29 Aug 2011 18:54:50 +0530 Subject: gpio/omap: restore OE only after setting the output level Setup the dataout register before restoring OE. This is to make sure that we have valid data in dataout register which would be made available in output pins as soon as OE is enabled. Else, there is risk of unknown data getting out into gpio pins. Signed-off-by: Nishanth Menon Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 41265e823b23..e0fd2e4b2b9c 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1355,7 +1355,6 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); __raw_writel(bank->context.ctrl, bank->base + bank->regs->ctrl); - __raw_writel(bank->context.oe, bank->base + bank->regs->direction); __raw_writel(bank->context.leveldetect0, bank->base + bank->regs->leveldetect0); __raw_writel(bank->context.leveldetect1, @@ -1365,6 +1364,8 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) __raw_writel(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); + __raw_writel(bank->context.oe, bank->base + bank->regs->direction); + if (bank->dbck_enable_mask) { __raw_writel(bank->context.debounce, bank->base + bank->regs->debounce); -- cgit v1.2.3 From f86bcc302a8c570dd0f5a50097a6af96a0e717c2 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Fri, 9 Sep 2011 19:14:08 +0530 Subject: gpio/omap: handle set_dataout reg capable IP on restore GPIO IP revisions such as those used in OMAP4 have a set_dataout while the previous revisions used a single dataout register. Depending on what is available restore the dataout settings to the right register. Signed-off-by: Nishanth Menon Signed-off-by: Tarun Kanti DebBarma Reviewed-by: Santosh Shilimkar Reviewed-by: Kevin Hilman Signed-off-by: Kevin Hilman --- drivers/gpio/gpio-omap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e0fd2e4b2b9c..f49bd6f47a50 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1363,7 +1363,12 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) bank->base + bank->regs->risingdetect); __raw_writel(bank->context.fallingdetect, bank->base + bank->regs->fallingdetect); - __raw_writel(bank->context.dataout, bank->base + bank->regs->dataout); + if (bank->regs->set_dataout && bank->regs->clr_dataout) + __raw_writel(bank->context.dataout, + bank->base + bank->regs->set_dataout); + else + __raw_writel(bank->context.dataout, + bank->base + bank->regs->dataout); __raw_writel(bank->context.oe, bank->base + bank->regs->direction); if (bank->dbck_enable_mask) { -- cgit v1.2.3 From 63325ff235deeed5a5fc25705e292239115c76cd Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 24 Feb 2012 10:34:33 -0800 Subject: ARM: OMAP1: Move 16xx GPIO system clock to platform init code This way we can remove omap_read/write call from the GPIO driver and remove include to linux/io.h. Cc: Grant Likely Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/gpio16xx.c | 7 +++++++ drivers/gpio/gpio-omap.c | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c index 0f399bd0e70e..99cabc498ab5 100644 --- a/arch/arm/mach-omap1/gpio16xx.c +++ b/arch/arm/mach-omap1/gpio16xx.c @@ -218,6 +218,13 @@ static int __init omap16xx_gpio_init(void) if (!cpu_is_omap16xx()) return -EINVAL; + /* + * Enable system clock for GPIO module. + * The CAM_CLK_CTRL *is* really the right place. + */ + omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, + ULPD_CAM_CLK_CTRL); + for (i = 0; i < ARRAY_SIZE(omap16xx_gpio_dev); i++) platform_device_register(omap16xx_gpio_dev[i]); diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0b0562979171..5b7b164e08ad 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1064,13 +1064,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) + OMAP1610_GPIO_IRQSTATUS1); __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG); - - /* - * Enable system clock for GPIO module. - * The CAM_CLK_CTRL *is* really the right place. - */ - omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, - ULPD_CAM_CLK_CTRL); } if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { __raw_writel(0xffffffff, bank->base -- cgit v1.2.3 From 08932d81961b1c57870949d069ce2dad235da443 Mon Sep 17 00:00:00 2001 From: Ryan Mallon Date: Wed, 11 Jan 2012 09:58:30 +1100 Subject: ep93xx: Configure GPIO ports in core code Move the pinmux setting of the EP93xx GPIOs to the core code. This removes the need for the GPIO driver to have access to the system controller registers. Signed-off-by: Ryan Mallon Cc: Grant Likely Reviewed-by: Mika Westerberg Acked-by: Hartley Sweeten --- arch/arm/mach-ep93xx/core.c | 7 +++++++ drivers/gpio/gpio-ep93xx.c | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpio') diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 776b34619901..bab6e470cbd7 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -909,6 +909,13 @@ void __init ep93xx_init_devices(void) /* Disallow access to MaverickCrunch initially */ ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); + /* Default all ports to GPIO */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | + EP93XX_SYSCON_DEVCFG_GONK | + EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); + /* Get the GPIO working early, other devices need it */ platform_device_register(&ep93xx_gpio_device); diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c index 1c0fc3756cb1..4ca5642e9776 100644 --- a/drivers/gpio/gpio-ep93xx.c +++ b/drivers/gpio/gpio-ep93xx.c @@ -378,13 +378,6 @@ static int __devinit ep93xx_gpio_probe(struct platform_device *pdev) } ep93xx_gpio->mmio_base = mmio; - /* Default all ports to GPIO */ - ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | - EP93XX_SYSCON_DEVCFG_GONK | - EP93XX_SYSCON_DEVCFG_EONIDE | - EP93XX_SYSCON_DEVCFG_GONIDE | - EP93XX_SYSCON_DEVCFG_HONIDE); - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) { struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i]; struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; -- cgit v1.2.3