aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-05-20 14:07:34 -0400
committerTony Lindgren <tony@atomide.com>2010-05-20 14:07:34 -0400
commit935d918046d4c29f053d56fff67d6a21495fd780 (patch)
tree5f413376f00e774abbc14a25cfc2047ac37ad846 /arch
parentdf760137ad3cbfa15ceed42478f81bff01b6e799 (diff)
parentd009559a4215c71694b1a29ec0e520453087a9f6 (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.c4
-rw-r--r--arch/arm/mach-omap2/pm34xx.c4
-rw-r--r--arch/arm/plat-omap/gpio.c177
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h4
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
310static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; 310static 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
2029static int workaround_enabled; 2043static int workaround_enabled;
2030 2044
2031void omap2_gpio_prepare_for_retention(void) 2045void 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
2088void omap2_gpio_resume_after_retention(void) 2113void 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
2288arch_initcall(omap_gpio_sysinit); 2312arch_initcall(omap_gpio_sysinit);
2289
2290
2291#ifdef CONFIG_DEBUG_FS
2292
2293#include <linux/debugfs.h>
2294#include <linux/seq_file.h>
2295
2296static 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
2376static int dbg_gpio_open(struct inode *inode, struct file *file)
2377{
2378 return single_open(file, dbg_gpio_show, &inode->i_private);
2379}
2380
2381static 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
2388static 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}
2394late_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
74extern int omap_gpio_init(void); /* Call from board init only */ 74extern int omap_gpio_init(void); /* Call from board init only */
75extern void omap2_gpio_prepare_for_retention(void); 75extern void omap2_gpio_prepare_for_idle(int power_state);
76extern void omap2_gpio_resume_after_retention(void); 76extern void omap2_gpio_resume_after_idle(void);
77extern void omap_set_gpio_debounce(int gpio, int enable); 77extern void omap_set_gpio_debounce(int gpio, int enable);
78extern void omap_set_gpio_debounce_time(int gpio, int enable); 78extern void omap_set_gpio_debounce_time(int gpio, int enable);
79extern void omap_gpio_save_context(void); 79extern void omap_gpio_save_context(void);