diff options
author | Tony Lindgren <tony@atomide.com> | 2010-05-20 14:07:34 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2010-05-20 14:07:34 -0400 |
commit | 935d918046d4c29f053d56fff67d6a21495fd780 (patch) | |
tree | 5f413376f00e774abbc14a25cfc2047ac37ad846 /arch | |
parent | df760137ad3cbfa15ceed42478f81bff01b6e799 (diff) | |
parent | d009559a4215c71694b1a29ec0e520453087a9f6 (diff) |
Merge branch 'gpio-2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/pm24xx.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 177 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/gpio.h | 4 |
4 files changed, 53 insertions, 136 deletions
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 374299ea7ade..7816c4e84a32 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c | |||
@@ -107,7 +107,7 @@ static void omap2_enter_full_retention(void) | |||
107 | l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; | 107 | l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; |
108 | omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); | 108 | omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); |
109 | 109 | ||
110 | omap2_gpio_prepare_for_retention(); | 110 | omap2_gpio_prepare_for_idle(PWRDM_POWER_RET); |
111 | 111 | ||
112 | if (omap2_pm_debug) { | 112 | if (omap2_pm_debug) { |
113 | omap2_pm_dump(0, 0, 0); | 113 | omap2_pm_dump(0, 0, 0); |
@@ -141,7 +141,7 @@ no_sleep: | |||
141 | tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; | 141 | tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; |
142 | omap2_pm_dump(0, 1, tmp); | 142 | omap2_pm_dump(0, 1, tmp); |
143 | } | 143 | } |
144 | omap2_gpio_resume_after_retention(); | 144 | omap2_gpio_resume_after_idle(); |
145 | 145 | ||
146 | clk_enable(osc_ck); | 146 | clk_enable(osc_ck); |
147 | 147 | ||
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index ea0000bc5358..468e1e3321e0 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -376,7 +376,7 @@ void omap_sram_idle(void) | |||
376 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); | 376 | core_next_state = pwrdm_read_next_pwrst(core_pwrdm); |
377 | if (per_next_state < PWRDM_POWER_ON) { | 377 | if (per_next_state < PWRDM_POWER_ON) { |
378 | omap_uart_prepare_idle(2); | 378 | omap_uart_prepare_idle(2); |
379 | omap2_gpio_prepare_for_retention(); | 379 | omap2_gpio_prepare_for_idle(per_next_state); |
380 | if (per_next_state == PWRDM_POWER_OFF) { | 380 | if (per_next_state == PWRDM_POWER_OFF) { |
381 | if (core_next_state == PWRDM_POWER_ON) { | 381 | if (core_next_state == PWRDM_POWER_ON) { |
382 | per_next_state = PWRDM_POWER_RET; | 382 | per_next_state = PWRDM_POWER_RET; |
@@ -454,9 +454,9 @@ void omap_sram_idle(void) | |||
454 | /* PER */ | 454 | /* PER */ |
455 | if (per_next_state < PWRDM_POWER_ON) { | 455 | if (per_next_state < PWRDM_POWER_ON) { |
456 | per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); | 456 | per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); |
457 | omap2_gpio_resume_after_idle(); | ||
457 | if (per_prev_state == PWRDM_POWER_OFF) | 458 | if (per_prev_state == PWRDM_POWER_OFF) |
458 | omap3_per_restore_context(); | 459 | omap3_per_restore_context(); |
459 | omap2_gpio_resume_after_retention(); | ||
460 | omap_uart_resume_idle(2); | 460 | omap_uart_resume_idle(2); |
461 | if (per_state_modified) | 461 | if (per_state_modified) |
462 | pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF); | 462 | pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF); |
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 45a225d09125..955597fd6d35 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <mach/irqs.h> | 27 | #include <mach/irqs.h> |
28 | #include <mach/gpio.h> | 28 | #include <mach/gpio.h> |
29 | #include <asm/mach/irq.h> | 29 | #include <asm/mach/irq.h> |
30 | #include <plat/powerdomain.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * OMAP1510 GPIO registers | 33 | * OMAP1510 GPIO registers |
@@ -195,6 +196,7 @@ struct gpio_bank { | |||
195 | struct gpio_chip chip; | 196 | struct gpio_chip chip; |
196 | struct clk *dbck; | 197 | struct clk *dbck; |
197 | u32 mod_usage; | 198 | u32 mod_usage; |
199 | u32 dbck_enable_mask; | ||
198 | }; | 200 | }; |
199 | 201 | ||
200 | #define METHOD_MPUIO 0 | 202 | #define METHOD_MPUIO 0 |
@@ -303,8 +305,6 @@ struct omap3_gpio_regs { | |||
303 | u32 risingdetect; | 305 | u32 risingdetect; |
304 | u32 fallingdetect; | 306 | u32 fallingdetect; |
305 | u32 dataout; | 307 | u32 dataout; |
306 | u32 setwkuena; | ||
307 | u32 setdataout; | ||
308 | }; | 308 | }; |
309 | 309 | ||
310 | static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; | 310 | static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; |
@@ -646,6 +646,7 @@ void omap_set_gpio_debounce(int gpio, int enable) | |||
646 | goto done; | 646 | goto done; |
647 | 647 | ||
648 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { | 648 | if (cpu_is_omap34xx() || cpu_is_omap44xx()) { |
649 | bank->dbck_enable_mask = val; | ||
649 | if (enable) | 650 | if (enable) |
650 | clk_enable(bank->dbck); | 651 | clk_enable(bank->dbck); |
651 | else | 652 | else |
@@ -724,15 +725,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, | |||
724 | OMAP4_GPIO_IRQWAKEN0); | 725 | OMAP4_GPIO_IRQWAKEN0); |
725 | } | 726 | } |
726 | } else { | 727 | } else { |
727 | if (trigger != 0) | 728 | /* |
729 | * GPIO wakeup request can only be generated on edge | ||
730 | * transitions | ||
731 | */ | ||
732 | if (trigger & IRQ_TYPE_EDGE_BOTH) | ||
728 | __raw_writel(1 << gpio, bank->base | 733 | __raw_writel(1 << gpio, bank->base |
729 | + OMAP24XX_GPIO_SETWKUENA); | 734 | + OMAP24XX_GPIO_SETWKUENA); |
730 | else | 735 | else |
731 | __raw_writel(1 << gpio, bank->base | 736 | __raw_writel(1 << gpio, bank->base |
732 | + OMAP24XX_GPIO_CLEARWKUENA); | 737 | + OMAP24XX_GPIO_CLEARWKUENA); |
733 | } | 738 | } |
734 | } else { | 739 | } |
735 | if (trigger != 0) | 740 | /* This part needs to be executed always for OMAP34xx */ |
741 | if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) { | ||
742 | /* | ||
743 | * Log the edge gpio and manually trigger the IRQ | ||
744 | * after resume if the input level changes | ||
745 | * to avoid irq lost during PER RET/OFF mode | ||
746 | * Applies for omap2 non-wakeup gpio and all omap3 gpios | ||
747 | */ | ||
748 | if (trigger & IRQ_TYPE_EDGE_BOTH) | ||
736 | bank->enabled_non_wakeup_gpios |= gpio_bit; | 749 | bank->enabled_non_wakeup_gpios |= gpio_bit; |
737 | else | 750 | else |
738 | bank->enabled_non_wakeup_gpios &= ~gpio_bit; | 751 | bank->enabled_non_wakeup_gpios &= ~gpio_bit; |
@@ -1845,7 +1858,8 @@ static int __init _omap_gpio_init(void) | |||
1845 | __raw_writel(0, bank->base + | 1858 | __raw_writel(0, bank->base + |
1846 | OMAP24XX_GPIO_CTRL); | 1859 | OMAP24XX_GPIO_CTRL); |
1847 | } | 1860 | } |
1848 | if (i < ARRAY_SIZE(non_wakeup_gpios)) | 1861 | if (cpu_is_omap24xx() && |
1862 | i < ARRAY_SIZE(non_wakeup_gpios)) | ||
1849 | bank->non_wakeup_gpios = non_wakeup_gpios[i]; | 1863 | bank->non_wakeup_gpios = non_wakeup_gpios[i]; |
1850 | gpio_count = 32; | 1864 | gpio_count = 32; |
1851 | } | 1865 | } |
@@ -2028,16 +2042,27 @@ static struct sys_device omap_gpio_device = { | |||
2028 | 2042 | ||
2029 | static int workaround_enabled; | 2043 | static int workaround_enabled; |
2030 | 2044 | ||
2031 | void omap2_gpio_prepare_for_retention(void) | 2045 | void omap2_gpio_prepare_for_idle(int power_state) |
2032 | { | 2046 | { |
2033 | int i, c = 0; | 2047 | int i, c = 0; |
2048 | int min = 0; | ||
2034 | 2049 | ||
2035 | /* Remove triggering for all non-wakeup GPIOs. Otherwise spurious | 2050 | if (cpu_is_omap34xx()) |
2036 | * IRQs will be generated. See OMAP2420 Errata item 1.101. */ | 2051 | min = 1; |
2037 | for (i = 0; i < gpio_bank_count; i++) { | 2052 | |
2053 | for (i = min; i < gpio_bank_count; i++) { | ||
2038 | struct gpio_bank *bank = &gpio_bank[i]; | 2054 | struct gpio_bank *bank = &gpio_bank[i]; |
2039 | u32 l1, l2; | 2055 | u32 l1, l2; |
2040 | 2056 | ||
2057 | if (bank->dbck_enable_mask) | ||
2058 | clk_disable(bank->dbck); | ||
2059 | |||
2060 | if (power_state > PWRDM_POWER_OFF) | ||
2061 | continue; | ||
2062 | |||
2063 | /* If going to OFF, remove triggering for all | ||
2064 | * non-wakeup GPIOs. Otherwise spurious IRQs will be | ||
2065 | * generated. See OMAP2420 Errata item 1.101. */ | ||
2041 | if (!(bank->enabled_non_wakeup_gpios)) | 2066 | if (!(bank->enabled_non_wakeup_gpios)) |
2042 | continue; | 2067 | continue; |
2043 | 2068 | ||
@@ -2085,16 +2110,23 @@ void omap2_gpio_prepare_for_retention(void) | |||
2085 | workaround_enabled = 1; | 2110 | workaround_enabled = 1; |
2086 | } | 2111 | } |
2087 | 2112 | ||
2088 | void omap2_gpio_resume_after_retention(void) | 2113 | void omap2_gpio_resume_after_idle(void) |
2089 | { | 2114 | { |
2090 | int i; | 2115 | int i; |
2116 | int min = 0; | ||
2091 | 2117 | ||
2092 | if (!workaround_enabled) | 2118 | if (cpu_is_omap34xx()) |
2093 | return; | 2119 | min = 1; |
2094 | for (i = 0; i < gpio_bank_count; i++) { | 2120 | for (i = min; i < gpio_bank_count; i++) { |
2095 | struct gpio_bank *bank = &gpio_bank[i]; | 2121 | struct gpio_bank *bank = &gpio_bank[i]; |
2096 | u32 l, gen, gen0, gen1; | 2122 | u32 l, gen, gen0, gen1; |
2097 | 2123 | ||
2124 | if (bank->dbck_enable_mask) | ||
2125 | clk_enable(bank->dbck); | ||
2126 | |||
2127 | if (!workaround_enabled) | ||
2128 | continue; | ||
2129 | |||
2098 | if (!(bank->enabled_non_wakeup_gpios)) | 2130 | if (!(bank->enabled_non_wakeup_gpios)) |
2099 | continue; | 2131 | continue; |
2100 | 2132 | ||
@@ -2119,7 +2151,7 @@ void omap2_gpio_resume_after_retention(void) | |||
2119 | * horribly racy, but it's the best we can do to work around | 2151 | * horribly racy, but it's the best we can do to work around |
2120 | * this silicon bug. */ | 2152 | * this silicon bug. */ |
2121 | l ^= bank->saved_datain; | 2153 | l ^= bank->saved_datain; |
2122 | l &= bank->non_wakeup_gpios; | 2154 | l &= bank->enabled_non_wakeup_gpios; |
2123 | 2155 | ||
2124 | /* | 2156 | /* |
2125 | * No need to generate IRQs for the rising edge for gpio IRQs | 2157 | * No need to generate IRQs for the rising edge for gpio IRQs |
@@ -2207,10 +2239,6 @@ void omap_gpio_save_context(void) | |||
2207 | __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); | 2239 | __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); |
2208 | gpio_context[i].dataout = | 2240 | gpio_context[i].dataout = |
2209 | __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); | 2241 | __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); |
2210 | gpio_context[i].setwkuena = | ||
2211 | __raw_readl(bank->base + OMAP24XX_GPIO_SETWKUENA); | ||
2212 | gpio_context[i].setdataout = | ||
2213 | __raw_readl(bank->base + OMAP24XX_GPIO_SETDATAOUT); | ||
2214 | } | 2242 | } |
2215 | } | 2243 | } |
2216 | 2244 | ||
@@ -2243,10 +2271,6 @@ void omap_gpio_restore_context(void) | |||
2243 | bank->base + OMAP24XX_GPIO_FALLINGDETECT); | 2271 | bank->base + OMAP24XX_GPIO_FALLINGDETECT); |
2244 | __raw_writel(gpio_context[i].dataout, | 2272 | __raw_writel(gpio_context[i].dataout, |
2245 | bank->base + OMAP24XX_GPIO_DATAOUT); | 2273 | bank->base + OMAP24XX_GPIO_DATAOUT); |
2246 | __raw_writel(gpio_context[i].setwkuena, | ||
2247 | bank->base + OMAP24XX_GPIO_SETWKUENA); | ||
2248 | __raw_writel(gpio_context[i].setdataout, | ||
2249 | bank->base + OMAP24XX_GPIO_SETDATAOUT); | ||
2250 | } | 2274 | } |
2251 | } | 2275 | } |
2252 | #endif | 2276 | #endif |
@@ -2286,110 +2310,3 @@ static int __init omap_gpio_sysinit(void) | |||
2286 | } | 2310 | } |
2287 | 2311 | ||
2288 | arch_initcall(omap_gpio_sysinit); | 2312 | arch_initcall(omap_gpio_sysinit); |
2289 | |||
2290 | |||
2291 | #ifdef CONFIG_DEBUG_FS | ||
2292 | |||
2293 | #include <linux/debugfs.h> | ||
2294 | #include <linux/seq_file.h> | ||
2295 | |||
2296 | static int dbg_gpio_show(struct seq_file *s, void *unused) | ||
2297 | { | ||
2298 | unsigned i, j, gpio; | ||
2299 | |||
2300 | for (i = 0, gpio = 0; i < gpio_bank_count; i++) { | ||
2301 | struct gpio_bank *bank = gpio_bank + i; | ||
2302 | unsigned bankwidth = 16; | ||
2303 | u32 mask = 1; | ||
2304 | |||
2305 | if (bank_is_mpuio(bank)) | ||
2306 | gpio = OMAP_MPUIO(0); | ||
2307 | else if (cpu_class_is_omap2() || cpu_is_omap7xx()) | ||
2308 | bankwidth = 32; | ||
2309 | |||
2310 | for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { | ||
2311 | unsigned irq, value, is_in, irqstat; | ||
2312 | const char *label; | ||
2313 | |||
2314 | label = gpiochip_is_requested(&bank->chip, j); | ||
2315 | if (!label) | ||
2316 | continue; | ||
2317 | |||
2318 | irq = bank->virtual_irq_start + j; | ||
2319 | value = gpio_get_value(gpio); | ||
2320 | is_in = gpio_is_input(bank, mask); | ||
2321 | |||
2322 | if (bank_is_mpuio(bank)) | ||
2323 | seq_printf(s, "MPUIO %2d ", j); | ||
2324 | else | ||
2325 | seq_printf(s, "GPIO %3d ", gpio); | ||
2326 | seq_printf(s, "(%-20.20s): %s %s", | ||
2327 | label, | ||
2328 | is_in ? "in " : "out", | ||
2329 | value ? "hi" : "lo"); | ||
2330 | |||
2331 | /* FIXME for at least omap2, show pullup/pulldown state */ | ||
2332 | |||
2333 | irqstat = irq_desc[irq].status; | ||
2334 | #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) | ||
2335 | if (is_in && ((bank->suspend_wakeup & mask) | ||
2336 | || irqstat & IRQ_TYPE_SENSE_MASK)) { | ||
2337 | char *trigger = NULL; | ||
2338 | |||
2339 | switch (irqstat & IRQ_TYPE_SENSE_MASK) { | ||
2340 | case IRQ_TYPE_EDGE_FALLING: | ||
2341 | trigger = "falling"; | ||
2342 | break; | ||
2343 | case IRQ_TYPE_EDGE_RISING: | ||
2344 | trigger = "rising"; | ||
2345 | break; | ||
2346 | case IRQ_TYPE_EDGE_BOTH: | ||
2347 | trigger = "bothedge"; | ||
2348 | break; | ||
2349 | case IRQ_TYPE_LEVEL_LOW: | ||
2350 | trigger = "low"; | ||
2351 | break; | ||
2352 | case IRQ_TYPE_LEVEL_HIGH: | ||
2353 | trigger = "high"; | ||
2354 | break; | ||
2355 | case IRQ_TYPE_NONE: | ||
2356 | trigger = "(?)"; | ||
2357 | break; | ||
2358 | } | ||
2359 | seq_printf(s, ", irq-%d %-8s%s", | ||
2360 | irq, trigger, | ||
2361 | (bank->suspend_wakeup & mask) | ||
2362 | ? " wakeup" : ""); | ||
2363 | } | ||
2364 | #endif | ||
2365 | seq_printf(s, "\n"); | ||
2366 | } | ||
2367 | |||
2368 | if (bank_is_mpuio(bank)) { | ||
2369 | seq_printf(s, "\n"); | ||
2370 | gpio = 0; | ||
2371 | } | ||
2372 | } | ||
2373 | return 0; | ||
2374 | } | ||
2375 | |||
2376 | static int dbg_gpio_open(struct inode *inode, struct file *file) | ||
2377 | { | ||
2378 | return single_open(file, dbg_gpio_show, &inode->i_private); | ||
2379 | } | ||
2380 | |||
2381 | static const struct file_operations debug_fops = { | ||
2382 | .open = dbg_gpio_open, | ||
2383 | .read = seq_read, | ||
2384 | .llseek = seq_lseek, | ||
2385 | .release = single_release, | ||
2386 | }; | ||
2387 | |||
2388 | static int __init omap_gpio_debuginit(void) | ||
2389 | { | ||
2390 | (void) debugfs_create_file("omap_gpio", S_IRUGO, | ||
2391 | NULL, NULL, &debug_fops); | ||
2392 | return 0; | ||
2393 | } | ||
2394 | late_initcall(omap_gpio_debuginit); | ||
2395 | #endif | ||
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index de7c54731cbe..de1c604962eb 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h | |||
@@ -72,8 +72,8 @@ | |||
72 | IH_GPIO_BASE + (nr)) | 72 | IH_GPIO_BASE + (nr)) |
73 | 73 | ||
74 | extern int omap_gpio_init(void); /* Call from board init only */ | 74 | extern int omap_gpio_init(void); /* Call from board init only */ |
75 | extern void omap2_gpio_prepare_for_retention(void); | 75 | extern void omap2_gpio_prepare_for_idle(int power_state); |
76 | extern void omap2_gpio_resume_after_retention(void); | 76 | extern void omap2_gpio_resume_after_idle(void); |
77 | extern void omap_set_gpio_debounce(int gpio, int enable); | 77 | extern void omap_set_gpio_debounce(int gpio, int enable); |
78 | extern void omap_set_gpio_debounce_time(int gpio, int enable); | 78 | extern void omap_set_gpio_debounce_time(int gpio, int enable); |
79 | extern void omap_gpio_save_context(void); | 79 | extern void omap_gpio_save_context(void); |