aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/gpio.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 13:50:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 13:50:00 -0400
commita6f039869ff87e0a8d621e31d14bbb120c1dfa93 (patch)
treec8975a8d02893633d03efe5435aa8b0635298a93 /arch/arm/plat-omap/gpio.c
parente0bc5d4a54938eedcde14005210e6c08aa9727e4 (diff)
parentf6304f5804f228b6c2fea9e3dfac25c5b2db9b38 (diff)
Merge branch 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6
* 'omap-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6: (113 commits) omap4: Add support for i2c init omap: Fix i2c platform init code for omap4 OMAP2 clock: fix recursive spinlock attempt when CONFIG_CPU_FREQ=y OMAP powerdomain, hwmod, omap_device: add some credits OMAP4 powerdomain: Support LOWPOWERSTATECHANGE for powerdomains OMAP3 clock: add support for setting the divider for sys_clkout2 using clk_set_rate OMAP4 powerdomain: Fix pwrsts flags for ALWAYS ON domains OMAP: timers: Fix clock source names for OMAP4 OMAP4 clock: Support clk_set_parent OMAP4: PRCM: Add offset defines for all CM registers OMAP4: PRCM: Add offset defines for all PRM registers OMAP4: PRCM: Remove duplicate definition of base addresses OMAP4: PRM: Remove MPU internal code name and apply PRCM naming convention OMAP4: CM: Remove non-functional registers in ES1.0 OMAP: hwmod: Replace WARN by pr_warning for clockdomain check OMAP: hwmod: Rename hwmod name for the MPU OMAP: hwmod: Do not exit the iteration if one clock init failed OMAP: hwmod: Replace WARN by pr_warning if clock lookup failed OMAP: hwmod: Remove IS_ERR check with omap_clk_get_by_name return value OMAP: hwmod: Fix wrong pointer iteration in oh->slaves ...
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r--arch/arm/plat-omap/gpio.c236
1 files changed, 94 insertions, 142 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 45a225d09125..dc2ac42d6319 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
@@ -137,7 +138,11 @@
137#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040 138#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040
138#define OMAP4_GPIO_IRQWAKEN0 0x0044 139#define OMAP4_GPIO_IRQWAKEN0 0x0044
139#define OMAP4_GPIO_IRQWAKEN1 0x0048 140#define OMAP4_GPIO_IRQWAKEN1 0x0048
140#define OMAP4_GPIO_SYSSTATUS 0x0104 141#define OMAP4_GPIO_SYSSTATUS 0x0114
142#define OMAP4_GPIO_IRQENABLE1 0x011c
143#define OMAP4_GPIO_WAKE_EN 0x0120
144#define OMAP4_GPIO_IRQSTATUS2 0x0128
145#define OMAP4_GPIO_IRQENABLE2 0x012c
141#define OMAP4_GPIO_CTRL 0x0130 146#define OMAP4_GPIO_CTRL 0x0130
142#define OMAP4_GPIO_OE 0x0134 147#define OMAP4_GPIO_OE 0x0134
143#define OMAP4_GPIO_DATAIN 0x0138 148#define OMAP4_GPIO_DATAIN 0x0138
@@ -148,6 +153,10 @@
148#define OMAP4_GPIO_FALLINGDETECT 0x014c 153#define OMAP4_GPIO_FALLINGDETECT 0x014c
149#define OMAP4_GPIO_DEBOUNCENABLE 0x0150 154#define OMAP4_GPIO_DEBOUNCENABLE 0x0150
150#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154 155#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154
156#define OMAP4_GPIO_CLEARIRQENABLE1 0x0160
157#define OMAP4_GPIO_SETIRQENABLE1 0x0164
158#define OMAP4_GPIO_CLEARWKUENA 0x0180
159#define OMAP4_GPIO_SETWKUENA 0x0184
151#define OMAP4_GPIO_CLEARDATAOUT 0x0190 160#define OMAP4_GPIO_CLEARDATAOUT 0x0190
152#define OMAP4_GPIO_SETDATAOUT 0x0194 161#define OMAP4_GPIO_SETDATAOUT 0x0194
153/* 162/*
@@ -195,6 +204,7 @@ struct gpio_bank {
195 struct gpio_chip chip; 204 struct gpio_chip chip;
196 struct clk *dbck; 205 struct clk *dbck;
197 u32 mod_usage; 206 u32 mod_usage;
207 u32 dbck_enable_mask;
198}; 208};
199 209
200#define METHOD_MPUIO 0 210#define METHOD_MPUIO 0
@@ -303,8 +313,6 @@ struct omap3_gpio_regs {
303 u32 risingdetect; 313 u32 risingdetect;
304 u32 fallingdetect; 314 u32 fallingdetect;
305 u32 dataout; 315 u32 dataout;
306 u32 setwkuena;
307 u32 setdataout;
308}; 316};
309 317
310static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; 318static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
@@ -591,12 +599,16 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
591 reg += OMAP7XX_GPIO_DATA_OUTPUT; 599 reg += OMAP7XX_GPIO_DATA_OUTPUT;
592 break; 600 break;
593#endif 601#endif
594#ifdef CONFIG_ARCH_OMAP2PLUS 602#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
595 case METHOD_GPIO_24XX: 603 case METHOD_GPIO_24XX:
596 case METHOD_GPIO_44XX:
597 reg += OMAP24XX_GPIO_DATAOUT; 604 reg += OMAP24XX_GPIO_DATAOUT;
598 break; 605 break;
599#endif 606#endif
607#ifdef CONFIG_ARCH_OMAP4
608 case METHOD_GPIO_44XX:
609 reg += OMAP4_GPIO_DATAOUT;
610 break;
611#endif
600 default: 612 default:
601 return -EINVAL; 613 return -EINVAL;
602 } 614 }
@@ -646,6 +658,7 @@ void omap_set_gpio_debounce(int gpio, int enable)
646 goto done; 658 goto done;
647 659
648 if (cpu_is_omap34xx() || cpu_is_omap44xx()) { 660 if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
661 bank->dbck_enable_mask = val;
649 if (enable) 662 if (enable)
650 clk_enable(bank->dbck); 663 clk_enable(bank->dbck);
651 else 664 else
@@ -724,15 +737,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
724 OMAP4_GPIO_IRQWAKEN0); 737 OMAP4_GPIO_IRQWAKEN0);
725 } 738 }
726 } else { 739 } else {
727 if (trigger != 0) 740 /*
741 * GPIO wakeup request can only be generated on edge
742 * transitions
743 */
744 if (trigger & IRQ_TYPE_EDGE_BOTH)
728 __raw_writel(1 << gpio, bank->base 745 __raw_writel(1 << gpio, bank->base
729 + OMAP24XX_GPIO_SETWKUENA); 746 + OMAP24XX_GPIO_SETWKUENA);
730 else 747 else
731 __raw_writel(1 << gpio, bank->base 748 __raw_writel(1 << gpio, bank->base
732 + OMAP24XX_GPIO_CLEARWKUENA); 749 + OMAP24XX_GPIO_CLEARWKUENA);
733 } 750 }
734 } else { 751 }
735 if (trigger != 0) 752 /* This part needs to be executed always for OMAP34xx */
753 if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
754 /*
755 * Log the edge gpio and manually trigger the IRQ
756 * after resume if the input level changes
757 * to avoid irq lost during PER RET/OFF mode
758 * Applies for omap2 non-wakeup gpio and all omap3 gpios
759 */
760 if (trigger & IRQ_TYPE_EDGE_BOTH)
736 bank->enabled_non_wakeup_gpios |= gpio_bit; 761 bank->enabled_non_wakeup_gpios |= gpio_bit;
737 else 762 else
738 bank->enabled_non_wakeup_gpios &= ~gpio_bit; 763 bank->enabled_non_wakeup_gpios &= ~gpio_bit;
@@ -1200,11 +1225,17 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
1200#endif 1225#endif
1201 if (!cpu_class_is_omap1()) { 1226 if (!cpu_class_is_omap1()) {
1202 if (!bank->mod_usage) { 1227 if (!bank->mod_usage) {
1228 void __iomem *reg = bank->base;
1203 u32 ctrl; 1229 u32 ctrl;
1204 ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); 1230
1205 ctrl &= 0xFFFFFFFE; 1231 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1232 reg += OMAP24XX_GPIO_CTRL;
1233 else if (cpu_is_omap44xx())
1234 reg += OMAP4_GPIO_CTRL;
1235 ctrl = __raw_readl(reg);
1206 /* Module is enabled, clocks are not gated */ 1236 /* Module is enabled, clocks are not gated */
1207 __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL); 1237 ctrl &= 0xFFFFFFFE;
1238 __raw_writel(ctrl, reg);
1208 } 1239 }
1209 bank->mod_usage |= 1 << offset; 1240 bank->mod_usage |= 1 << offset;
1210 } 1241 }
@@ -1226,22 +1257,34 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
1226 __raw_writel(1 << offset, reg); 1257 __raw_writel(1 << offset, reg);
1227 } 1258 }
1228#endif 1259#endif
1229#ifdef CONFIG_ARCH_OMAP2PLUS 1260#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
1230 if ((bank->method == METHOD_GPIO_24XX) || 1261 if (bank->method == METHOD_GPIO_24XX) {
1231 (bank->method == METHOD_GPIO_44XX)) {
1232 /* Disable wake-up during idle for dynamic tick */ 1262 /* Disable wake-up during idle for dynamic tick */
1233 void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; 1263 void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
1234 __raw_writel(1 << offset, reg); 1264 __raw_writel(1 << offset, reg);
1235 } 1265 }
1236#endif 1266#endif
1267#ifdef CONFIG_ARCH_OMAP4
1268 if (bank->method == METHOD_GPIO_44XX) {
1269 /* Disable wake-up during idle for dynamic tick */
1270 void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
1271 __raw_writel(1 << offset, reg);
1272 }
1273#endif
1237 if (!cpu_class_is_omap1()) { 1274 if (!cpu_class_is_omap1()) {
1238 bank->mod_usage &= ~(1 << offset); 1275 bank->mod_usage &= ~(1 << offset);
1239 if (!bank->mod_usage) { 1276 if (!bank->mod_usage) {
1277 void __iomem *reg = bank->base;
1240 u32 ctrl; 1278 u32 ctrl;
1241 ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); 1279
1280 if (cpu_is_omap24xx() || cpu_is_omap34xx())
1281 reg += OMAP24XX_GPIO_CTRL;
1282 else if (cpu_is_omap44xx())
1283 reg += OMAP4_GPIO_CTRL;
1284 ctrl = __raw_readl(reg);
1242 /* Module is disabled, clocks are gated */ 1285 /* Module is disabled, clocks are gated */
1243 ctrl |= 1; 1286 ctrl |= 1;
1244 __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL); 1287 __raw_writel(ctrl, reg);
1245 } 1288 }
1246 } 1289 }
1247 _reset_gpio(bank, bank->chip.base + offset); 1290 _reset_gpio(bank, bank->chip.base + offset);
@@ -1570,9 +1613,14 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
1570 reg += OMAP7XX_GPIO_DIR_CONTROL; 1613 reg += OMAP7XX_GPIO_DIR_CONTROL;
1571 break; 1614 break;
1572 case METHOD_GPIO_24XX: 1615 case METHOD_GPIO_24XX:
1573 case METHOD_GPIO_44XX:
1574 reg += OMAP24XX_GPIO_OE; 1616 reg += OMAP24XX_GPIO_OE;
1575 break; 1617 break;
1618 case METHOD_GPIO_44XX:
1619 reg += OMAP4_GPIO_OE;
1620 break;
1621 default:
1622 WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
1623 return -EINVAL;
1576 } 1624 }
1577 return __raw_readl(reg) & mask; 1625 return __raw_readl(reg) & mask;
1578} 1626}
@@ -1845,7 +1893,8 @@ static int __init _omap_gpio_init(void)
1845 __raw_writel(0, bank->base + 1893 __raw_writel(0, bank->base +
1846 OMAP24XX_GPIO_CTRL); 1894 OMAP24XX_GPIO_CTRL);
1847 } 1895 }
1848 if (i < ARRAY_SIZE(non_wakeup_gpios)) 1896 if (cpu_is_omap24xx() &&
1897 i < ARRAY_SIZE(non_wakeup_gpios))
1849 bank->non_wakeup_gpios = non_wakeup_gpios[i]; 1898 bank->non_wakeup_gpios = non_wakeup_gpios[i];
1850 gpio_count = 32; 1899 gpio_count = 32;
1851 } 1900 }
@@ -2028,16 +2077,27 @@ static struct sys_device omap_gpio_device = {
2028 2077
2029static int workaround_enabled; 2078static int workaround_enabled;
2030 2079
2031void omap2_gpio_prepare_for_retention(void) 2080void omap2_gpio_prepare_for_idle(int power_state)
2032{ 2081{
2033 int i, c = 0; 2082 int i, c = 0;
2083 int min = 0;
2034 2084
2035 /* Remove triggering for all non-wakeup GPIOs. Otherwise spurious 2085 if (cpu_is_omap34xx())
2036 * IRQs will be generated. See OMAP2420 Errata item 1.101. */ 2086 min = 1;
2037 for (i = 0; i < gpio_bank_count; i++) { 2087
2088 for (i = min; i < gpio_bank_count; i++) {
2038 struct gpio_bank *bank = &gpio_bank[i]; 2089 struct gpio_bank *bank = &gpio_bank[i];
2039 u32 l1, l2; 2090 u32 l1, l2;
2040 2091
2092 if (bank->dbck_enable_mask)
2093 clk_disable(bank->dbck);
2094
2095 if (power_state > PWRDM_POWER_OFF)
2096 continue;
2097
2098 /* If going to OFF, remove triggering for all
2099 * non-wakeup GPIOs. Otherwise spurious IRQs will be
2100 * generated. See OMAP2420 Errata item 1.101. */
2041 if (!(bank->enabled_non_wakeup_gpios)) 2101 if (!(bank->enabled_non_wakeup_gpios))
2042 continue; 2102 continue;
2043 2103
@@ -2085,16 +2145,23 @@ void omap2_gpio_prepare_for_retention(void)
2085 workaround_enabled = 1; 2145 workaround_enabled = 1;
2086} 2146}
2087 2147
2088void omap2_gpio_resume_after_retention(void) 2148void omap2_gpio_resume_after_idle(void)
2089{ 2149{
2090 int i; 2150 int i;
2151 int min = 0;
2091 2152
2092 if (!workaround_enabled) 2153 if (cpu_is_omap34xx())
2093 return; 2154 min = 1;
2094 for (i = 0; i < gpio_bank_count; i++) { 2155 for (i = min; i < gpio_bank_count; i++) {
2095 struct gpio_bank *bank = &gpio_bank[i]; 2156 struct gpio_bank *bank = &gpio_bank[i];
2096 u32 l, gen, gen0, gen1; 2157 u32 l, gen, gen0, gen1;
2097 2158
2159 if (bank->dbck_enable_mask)
2160 clk_enable(bank->dbck);
2161
2162 if (!workaround_enabled)
2163 continue;
2164
2098 if (!(bank->enabled_non_wakeup_gpios)) 2165 if (!(bank->enabled_non_wakeup_gpios))
2099 continue; 2166 continue;
2100 2167
@@ -2119,7 +2186,7 @@ void omap2_gpio_resume_after_retention(void)
2119 * horribly racy, but it's the best we can do to work around 2186 * horribly racy, but it's the best we can do to work around
2120 * this silicon bug. */ 2187 * this silicon bug. */
2121 l ^= bank->saved_datain; 2188 l ^= bank->saved_datain;
2122 l &= bank->non_wakeup_gpios; 2189 l &= bank->enabled_non_wakeup_gpios;
2123 2190
2124 /* 2191 /*
2125 * No need to generate IRQs for the rising edge for gpio IRQs 2192 * No need to generate IRQs for the rising edge for gpio IRQs
@@ -2207,10 +2274,6 @@ void omap_gpio_save_context(void)
2207 __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); 2274 __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
2208 gpio_context[i].dataout = 2275 gpio_context[i].dataout =
2209 __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); 2276 __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 } 2277 }
2215} 2278}
2216 2279
@@ -2243,10 +2306,6 @@ void omap_gpio_restore_context(void)
2243 bank->base + OMAP24XX_GPIO_FALLINGDETECT); 2306 bank->base + OMAP24XX_GPIO_FALLINGDETECT);
2244 __raw_writel(gpio_context[i].dataout, 2307 __raw_writel(gpio_context[i].dataout,
2245 bank->base + OMAP24XX_GPIO_DATAOUT); 2308 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 } 2309 }
2251} 2310}
2252#endif 2311#endif
@@ -2286,110 +2345,3 @@ static int __init omap_gpio_sysinit(void)
2286} 2345}
2287 2346
2288arch_initcall(omap_gpio_sysinit); 2347arch_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