diff options
-rw-r--r-- | arch/arm/mach-omap2/gpio.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 14 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/gpio.h | 5 | ||||
-rw-r--r-- | drivers/gpio/gpio-omap.c | 131 |
4 files changed, 63 insertions, 90 deletions
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 @@ | |||
23 | 23 | ||
24 | #include <plat/omap_hwmod.h> | 24 | #include <plat/omap_hwmod.h> |
25 | #include <plat/omap_device.h> | 25 | #include <plat/omap_device.h> |
26 | #include <plat/omap-pm.h> | ||
26 | 27 | ||
27 | #include "powerdomain.h" | 28 | #include "powerdomain.h" |
28 | 29 | ||
@@ -55,7 +56,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) | |||
55 | pdata->bank_width = dev_attr->bank_width; | 56 | pdata->bank_width = dev_attr->bank_width; |
56 | pdata->dbck_flag = dev_attr->dbck_flag; | 57 | pdata->dbck_flag = dev_attr->dbck_flag; |
57 | pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1); | 58 | pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1); |
58 | 59 | pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; | |
59 | pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL); | 60 | pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL); |
60 | if (!pdata) { | 61 | if (!pdata) { |
61 | pr_err("gpio%d: Memory allocation failed\n", id); | 62 | 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; | |||
75 | static struct powerdomain *core_pwrdm, *per_pwrdm; | 75 | static struct powerdomain *core_pwrdm, *per_pwrdm; |
76 | static struct powerdomain *cam_pwrdm; | 76 | static struct powerdomain *cam_pwrdm; |
77 | 77 | ||
78 | static inline void omap3_per_save_context(void) | ||
79 | { | ||
80 | omap_gpio_save_context(); | ||
81 | } | ||
82 | |||
83 | static inline void omap3_per_restore_context(void) | ||
84 | { | ||
85 | omap_gpio_restore_context(); | ||
86 | } | ||
87 | |||
88 | static void omap3_enable_io_chain(void) | 78 | static void omap3_enable_io_chain(void) |
89 | { | 79 | { |
90 | int timeout = 0; | 80 | int timeout = 0; |
@@ -332,8 +322,6 @@ void omap_sram_idle(void) | |||
332 | if (per_next_state < PWRDM_POWER_ON) { | 322 | if (per_next_state < PWRDM_POWER_ON) { |
333 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; | 323 | per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0; |
334 | omap2_gpio_prepare_for_idle(per_going_off); | 324 | omap2_gpio_prepare_for_idle(per_going_off); |
335 | if (per_next_state == PWRDM_POWER_OFF) | ||
336 | omap3_per_save_context(); | ||
337 | } | 325 | } |
338 | 326 | ||
339 | /* CORE */ | 327 | /* CORE */ |
@@ -399,8 +387,6 @@ void omap_sram_idle(void) | |||
399 | if (per_next_state < PWRDM_POWER_ON) { | 387 | if (per_next_state < PWRDM_POWER_ON) { |
400 | per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); | 388 | per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); |
401 | omap2_gpio_resume_after_idle(); | 389 | omap2_gpio_resume_after_idle(); |
402 | if (per_prev_state == PWRDM_POWER_OFF) | ||
403 | omap3_per_restore_context(); | ||
404 | } | 390 | } |
405 | 391 | ||
406 | /* Disable IO-PAD and IO-CHAIN wakeup */ | 392 | /* 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 { | |||
201 | bool loses_context; /* whether the bank would ever lose context */ | 201 | bool loses_context; /* whether the bank would ever lose context */ |
202 | 202 | ||
203 | struct omap_gpio_reg_offs *regs; | 203 | struct omap_gpio_reg_offs *regs; |
204 | |||
205 | /* Return context loss count due to PM states changing */ | ||
206 | int (*get_context_loss_count)(struct device *dev); | ||
204 | }; | 207 | }; |
205 | 208 | ||
206 | extern void omap2_gpio_prepare_for_idle(int off_mode); | 209 | extern void omap2_gpio_prepare_for_idle(int off_mode); |
207 | extern void omap2_gpio_resume_after_idle(void); | 210 | extern void omap2_gpio_resume_after_idle(void); |
208 | extern void omap_set_gpio_debounce(int gpio, int enable); | 211 | extern void omap_set_gpio_debounce(int gpio, int enable); |
209 | extern void omap_set_gpio_debounce_time(int gpio, int enable); | 212 | extern void omap_set_gpio_debounce_time(int gpio, int enable); |
210 | extern void omap_gpio_save_context(void); | ||
211 | extern void omap_gpio_restore_context(void); | ||
212 | /*-------------------------------------------------------------------------*/ | 213 | /*-------------------------------------------------------------------------*/ |
213 | 214 | ||
214 | /* Wrappers for "new style" GPIO calls, using the new infrastructure | 215 | /* 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 { | |||
72 | bool loses_context; | 72 | bool loses_context; |
73 | int stride; | 73 | int stride; |
74 | u32 width; | 74 | u32 width; |
75 | int context_loss_count; | ||
75 | u16 id; | 76 | u16 id; |
76 | 77 | ||
77 | void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); | 78 | void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable); |
79 | int (*get_context_loss_count)(struct device *dev); | ||
78 | 80 | ||
79 | struct omap_gpio_reg_offs *regs; | 81 | struct omap_gpio_reg_offs *regs; |
80 | }; | 82 | }; |
@@ -1179,6 +1181,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1179 | bank->stride = pdata->bank_stride; | 1181 | bank->stride = pdata->bank_stride; |
1180 | bank->width = pdata->bank_width; | 1182 | bank->width = pdata->bank_width; |
1181 | bank->loses_context = pdata->loses_context; | 1183 | bank->loses_context = pdata->loses_context; |
1184 | bank->get_context_loss_count = pdata->get_context_loss_count; | ||
1182 | bank->regs = pdata->regs; | 1185 | bank->regs = pdata->regs; |
1183 | 1186 | ||
1184 | if (bank->regs->set_dataout && bank->regs->clr_dataout) | 1187 | if (bank->regs->set_dataout && bank->regs->clr_dataout) |
@@ -1323,11 +1326,11 @@ static struct syscore_ops omap_gpio_syscore_ops = { | |||
1323 | 1326 | ||
1324 | #ifdef CONFIG_ARCH_OMAP2PLUS | 1327 | #ifdef CONFIG_ARCH_OMAP2PLUS |
1325 | 1328 | ||
1326 | static int workaround_enabled; | 1329 | static void omap_gpio_save_context(struct gpio_bank *bank); |
1330 | static void omap_gpio_restore_context(struct gpio_bank *bank); | ||
1327 | 1331 | ||
1328 | void omap2_gpio_prepare_for_idle(int off_mode) | 1332 | void omap2_gpio_prepare_for_idle(int off_mode) |
1329 | { | 1333 | { |
1330 | int c = 0; | ||
1331 | struct gpio_bank *bank; | 1334 | struct gpio_bank *bank; |
1332 | 1335 | ||
1333 | list_for_each_entry(bank, &omap_gpio_list, node) { | 1336 | list_for_each_entry(bank, &omap_gpio_list, node) { |
@@ -1347,7 +1350,7 @@ void omap2_gpio_prepare_for_idle(int off_mode) | |||
1347 | * non-wakeup GPIOs. Otherwise spurious IRQs will be | 1350 | * non-wakeup GPIOs. Otherwise spurious IRQs will be |
1348 | * generated. See OMAP2420 Errata item 1.101. */ | 1351 | * generated. See OMAP2420 Errata item 1.101. */ |
1349 | if (!(bank->enabled_non_wakeup_gpios)) | 1352 | if (!(bank->enabled_non_wakeup_gpios)) |
1350 | continue; | 1353 | goto save_gpio_context; |
1351 | 1354 | ||
1352 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 1355 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
1353 | bank->saved_datain = __raw_readl(bank->base + | 1356 | bank->saved_datain = __raw_readl(bank->base + |
@@ -1384,13 +1387,13 @@ void omap2_gpio_prepare_for_idle(int off_mode) | |||
1384 | __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); | 1387 | __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); |
1385 | } | 1388 | } |
1386 | 1389 | ||
1387 | c++; | 1390 | save_gpio_context: |
1388 | } | 1391 | if (bank->get_context_loss_count) |
1389 | if (!c) { | 1392 | bank->context_loss_count = |
1390 | workaround_enabled = 0; | 1393 | bank->get_context_loss_count(bank->dev); |
1391 | return; | 1394 | |
1395 | omap_gpio_save_context(bank); | ||
1392 | } | 1396 | } |
1393 | workaround_enabled = 1; | ||
1394 | } | 1397 | } |
1395 | 1398 | ||
1396 | void omap2_gpio_resume_after_idle(void) | 1399 | void omap2_gpio_resume_after_idle(void) |
@@ -1398,6 +1401,7 @@ void omap2_gpio_resume_after_idle(void) | |||
1398 | struct gpio_bank *bank; | 1401 | struct gpio_bank *bank; |
1399 | 1402 | ||
1400 | list_for_each_entry(bank, &omap_gpio_list, node) { | 1403 | list_for_each_entry(bank, &omap_gpio_list, node) { |
1404 | int context_lost_cnt_after; | ||
1401 | u32 l = 0, gen, gen0, gen1; | 1405 | u32 l = 0, gen, gen0, gen1; |
1402 | int j; | 1406 | int j; |
1403 | 1407 | ||
@@ -1407,8 +1411,13 @@ void omap2_gpio_resume_after_idle(void) | |||
1407 | for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) | 1411 | for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) |
1408 | clk_enable(bank->dbck); | 1412 | clk_enable(bank->dbck); |
1409 | 1413 | ||
1410 | if (!workaround_enabled) | 1414 | if (bank->get_context_loss_count) { |
1411 | continue; | 1415 | context_lost_cnt_after = |
1416 | bank->get_context_loss_count(bank->dev); | ||
1417 | if (context_lost_cnt_after != bank->context_loss_count | ||
1418 | || !context_lost_cnt_after) | ||
1419 | omap_gpio_restore_context(bank); | ||
1420 | } | ||
1412 | 1421 | ||
1413 | if (!(bank->enabled_non_wakeup_gpios)) | 1422 | if (!(bank->enabled_non_wakeup_gpios)) |
1414 | continue; | 1423 | continue; |
@@ -1486,74 +1495,50 @@ void omap2_gpio_resume_after_idle(void) | |||
1486 | } | 1495 | } |
1487 | } | 1496 | } |
1488 | } | 1497 | } |
1489 | |||
1490 | } | 1498 | } |
1491 | 1499 | ||
1492 | #endif | 1500 | static void omap_gpio_save_context(struct gpio_bank *bank) |
1493 | |||
1494 | #ifdef CONFIG_ARCH_OMAP3 | ||
1495 | void omap_gpio_save_context(void) | ||
1496 | { | 1501 | { |
1497 | struct gpio_bank *bank; | 1502 | bank->context.irqenable1 = |
1498 | 1503 | __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); | |
1499 | list_for_each_entry(bank, &omap_gpio_list, node) { | 1504 | bank->context.irqenable2 = |
1500 | 1505 | __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); | |
1501 | if (!bank->loses_context) | 1506 | bank->context.wake_en = |
1502 | continue; | 1507 | __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); |
1503 | 1508 | bank->context.ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); | |
1504 | bank->context.irqenable1 = | 1509 | bank->context.oe = __raw_readl(bank->base + OMAP24XX_GPIO_OE); |
1505 | __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); | 1510 | bank->context.leveldetect0 = |
1506 | bank->context.irqenable2 = | 1511 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); |
1507 | __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2); | 1512 | bank->context.leveldetect1 = |
1508 | bank->context.wake_en = | 1513 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); |
1509 | __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN); | 1514 | bank->context.risingdetect = |
1510 | bank->context.ctrl = | 1515 | __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); |
1511 | __raw_readl(bank->base + OMAP24XX_GPIO_CTRL); | 1516 | bank->context.fallingdetect = |
1512 | bank->context.oe = | 1517 | __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); |
1513 | __raw_readl(bank->base + OMAP24XX_GPIO_OE); | 1518 | bank->context.dataout = |
1514 | bank->context.leveldetect0 = | 1519 | __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); |
1515 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); | ||
1516 | bank->context.leveldetect1 = | ||
1517 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); | ||
1518 | bank->context.risingdetect = | ||
1519 | __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); | ||
1520 | bank->context.fallingdetect = | ||
1521 | __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); | ||
1522 | bank->context.dataout = | ||
1523 | __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT); | ||
1524 | } | ||
1525 | } | 1520 | } |
1526 | 1521 | ||
1527 | void omap_gpio_restore_context(void) | 1522 | static void omap_gpio_restore_context(struct gpio_bank *bank) |
1528 | { | 1523 | { |
1529 | struct gpio_bank *bank; | 1524 | __raw_writel(bank->context.irqenable1, |
1530 | 1525 | bank->base + OMAP24XX_GPIO_IRQENABLE1); | |
1531 | list_for_each_entry(bank, &omap_gpio_list, node) { | 1526 | __raw_writel(bank->context.irqenable2, |
1532 | 1527 | bank->base + OMAP24XX_GPIO_IRQENABLE2); | |
1533 | if (!bank->loses_context) | 1528 | __raw_writel(bank->context.wake_en, |
1534 | continue; | 1529 | bank->base + OMAP24XX_GPIO_WAKE_EN); |
1535 | 1530 | __raw_writel(bank->context.ctrl, bank->base + OMAP24XX_GPIO_CTRL); | |
1536 | __raw_writel(bank->context.irqenable1, | 1531 | __raw_writel(bank->context.oe, bank->base + OMAP24XX_GPIO_OE); |
1537 | bank->base + OMAP24XX_GPIO_IRQENABLE1); | 1532 | __raw_writel(bank->context.leveldetect0, |
1538 | __raw_writel(bank->context.irqenable2, | 1533 | bank->base + OMAP24XX_GPIO_LEVELDETECT0); |
1539 | bank->base + OMAP24XX_GPIO_IRQENABLE2); | 1534 | __raw_writel(bank->context.leveldetect1, |
1540 | __raw_writel(bank->context.wake_en, | 1535 | bank->base + OMAP24XX_GPIO_LEVELDETECT1); |
1541 | bank->base + OMAP24XX_GPIO_WAKE_EN); | 1536 | __raw_writel(bank->context.risingdetect, |
1542 | __raw_writel(bank->context.ctrl, | 1537 | bank->base + OMAP24XX_GPIO_RISINGDETECT); |
1543 | bank->base + OMAP24XX_GPIO_CTRL); | 1538 | __raw_writel(bank->context.fallingdetect, |
1544 | __raw_writel(bank->context.oe, | 1539 | bank->base + OMAP24XX_GPIO_FALLINGDETECT); |
1545 | bank->base + OMAP24XX_GPIO_OE); | 1540 | __raw_writel(bank->context.dataout, |
1546 | __raw_writel(bank->context.leveldetect0, | 1541 | bank->base + OMAP24XX_GPIO_DATAOUT); |
1547 | bank->base + OMAP24XX_GPIO_LEVELDETECT0); | ||
1548 | __raw_writel(bank->context.leveldetect1, | ||
1549 | bank->base + OMAP24XX_GPIO_LEVELDETECT1); | ||
1550 | __raw_writel(bank->context.risingdetect, | ||
1551 | bank->base + OMAP24XX_GPIO_RISINGDETECT); | ||
1552 | __raw_writel(bank->context.fallingdetect, | ||
1553 | bank->base + OMAP24XX_GPIO_FALLINGDETECT); | ||
1554 | __raw_writel(bank->context.dataout, | ||
1555 | bank->base + OMAP24XX_GPIO_DATAOUT); | ||
1556 | } | ||
1557 | } | 1542 | } |
1558 | #endif | 1543 | #endif |
1559 | 1544 | ||