diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2012-05-11 20:51:19 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2012-05-11 20:51:19 -0400 |
commit | 453007cf472a2b4c1034e850c3004ee9027005f6 (patch) | |
tree | 93d68be64b6cd2def634853836218ffb6681d8c4 /drivers/gpio | |
parent | 7563bbf89d065a2c3f05059ecbcc805645edcc62 (diff) | |
parent | 1b1287032df3a69d3ef9a486b444f4ffcca50d01 (diff) |
Merge branch 'for_3.5/gpio/cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into gpio/next
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-omap.c | 112 |
1 files changed, 26 insertions, 86 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 1adc2ec1e383..9b71f04538aa 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -57,14 +57,10 @@ struct gpio_bank { | |||
57 | u16 irq; | 57 | u16 irq; |
58 | int irq_base; | 58 | int irq_base; |
59 | struct irq_domain *domain; | 59 | struct irq_domain *domain; |
60 | u32 suspend_wakeup; | ||
61 | u32 saved_wakeup; | ||
62 | u32 non_wakeup_gpios; | 60 | u32 non_wakeup_gpios; |
63 | u32 enabled_non_wakeup_gpios; | 61 | u32 enabled_non_wakeup_gpios; |
64 | struct gpio_regs context; | 62 | struct gpio_regs context; |
65 | u32 saved_datain; | 63 | u32 saved_datain; |
66 | u32 saved_fallingdetect; | ||
67 | u32 saved_risingdetect; | ||
68 | u32 level_mask; | 64 | u32 level_mask; |
69 | u32 toggle_mask; | 65 | u32 toggle_mask; |
70 | spinlock_t lock; | 66 | spinlock_t lock; |
@@ -516,11 +512,11 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) | |||
516 | 512 | ||
517 | spin_lock_irqsave(&bank->lock, flags); | 513 | spin_lock_irqsave(&bank->lock, flags); |
518 | if (enable) | 514 | if (enable) |
519 | bank->suspend_wakeup |= gpio_bit; | 515 | bank->context.wake_en |= gpio_bit; |
520 | else | 516 | else |
521 | bank->suspend_wakeup &= ~gpio_bit; | 517 | bank->context.wake_en &= ~gpio_bit; |
522 | 518 | ||
523 | __raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en); | 519 | __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); |
524 | spin_unlock_irqrestore(&bank->lock, flags); | 520 | spin_unlock_irqrestore(&bank->lock, flags); |
525 | 521 | ||
526 | return 0; | 522 | return 0; |
@@ -640,7 +636,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
640 | u32 isr; | 636 | u32 isr; |
641 | unsigned int gpio_irq, gpio_index; | 637 | unsigned int gpio_irq, gpio_index; |
642 | struct gpio_bank *bank; | 638 | struct gpio_bank *bank; |
643 | u32 retrigger = 0; | ||
644 | int unmasked = 0; | 639 | int unmasked = 0; |
645 | struct irq_chip *chip = irq_desc_get_chip(desc); | 640 | struct irq_chip *chip = irq_desc_get_chip(desc); |
646 | 641 | ||
@@ -677,8 +672,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
677 | chained_irq_exit(chip, desc); | 672 | chained_irq_exit(chip, desc); |
678 | } | 673 | } |
679 | 674 | ||
680 | isr |= retrigger; | ||
681 | retrigger = 0; | ||
682 | if (!isr) | 675 | if (!isr) |
683 | break; | 676 | break; |
684 | 677 | ||
@@ -789,8 +782,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev) | |||
789 | unsigned long flags; | 782 | unsigned long flags; |
790 | 783 | ||
791 | spin_lock_irqsave(&bank->lock, flags); | 784 | spin_lock_irqsave(&bank->lock, flags); |
792 | bank->saved_wakeup = __raw_readl(mask_reg); | 785 | __raw_writel(0xffff & ~bank->context.wake_en, mask_reg); |
793 | __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg); | ||
794 | spin_unlock_irqrestore(&bank->lock, flags); | 786 | spin_unlock_irqrestore(&bank->lock, flags); |
795 | 787 | ||
796 | return 0; | 788 | return 0; |
@@ -805,7 +797,7 @@ static int omap_mpuio_resume_noirq(struct device *dev) | |||
805 | unsigned long flags; | 797 | unsigned long flags; |
806 | 798 | ||
807 | spin_lock_irqsave(&bank->lock, flags); | 799 | spin_lock_irqsave(&bank->lock, flags); |
808 | __raw_writel(bank->saved_wakeup, mask_reg); | 800 | __raw_writel(bank->context.wake_en, mask_reg); |
809 | spin_unlock_irqrestore(&bank->lock, flags); | 801 | spin_unlock_irqrestore(&bank->lock, flags); |
810 | 802 | ||
811 | return 0; | 803 | return 0; |
@@ -965,18 +957,15 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) | |||
965 | } | 957 | } |
966 | 958 | ||
967 | _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); | 959 | _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->irqenable_inv); |
968 | _gpio_rmw(base, bank->regs->irqstatus, l, | 960 | _gpio_rmw(base, bank->regs->irqstatus, l, !bank->regs->irqenable_inv); |
969 | bank->regs->irqenable_inv == false); | ||
970 | _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->debounce_en != 0); | ||
971 | _gpio_rmw(base, bank->regs->irqenable, l, bank->regs->ctrl != 0); | ||
972 | if (bank->regs->debounce_en) | 961 | if (bank->regs->debounce_en) |
973 | _gpio_rmw(base, bank->regs->debounce_en, 0, 1); | 962 | __raw_writel(0, base + bank->regs->debounce_en); |
974 | 963 | ||
975 | /* Save OE default value (0xffffffff) in the context */ | 964 | /* Save OE default value (0xffffffff) in the context */ |
976 | bank->context.oe = __raw_readl(bank->base + bank->regs->direction); | 965 | bank->context.oe = __raw_readl(bank->base + bank->regs->direction); |
977 | /* Initialize interface clk ungated, module enabled */ | 966 | /* Initialize interface clk ungated, module enabled */ |
978 | if (bank->regs->ctrl) | 967 | if (bank->regs->ctrl) |
979 | _gpio_rmw(base, bank->regs->ctrl, 0, 1); | 968 | __raw_writel(0, base + bank->regs->ctrl); |
980 | } | 969 | } |
981 | 970 | ||
982 | static __devinit void | 971 | static __devinit void |
@@ -1155,54 +1144,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) | |||
1155 | 1144 | ||
1156 | #ifdef CONFIG_ARCH_OMAP2PLUS | 1145 | #ifdef CONFIG_ARCH_OMAP2PLUS |
1157 | 1146 | ||
1158 | #if defined(CONFIG_PM_SLEEP) | ||
1159 | static int omap_gpio_suspend(struct device *dev) | ||
1160 | { | ||
1161 | struct platform_device *pdev = to_platform_device(dev); | ||
1162 | struct gpio_bank *bank = platform_get_drvdata(pdev); | ||
1163 | void __iomem *base = bank->base; | ||
1164 | void __iomem *wakeup_enable; | ||
1165 | unsigned long flags; | ||
1166 | |||
1167 | if (!bank->mod_usage || !bank->loses_context) | ||
1168 | return 0; | ||
1169 | |||
1170 | if (!bank->regs->wkup_en || !bank->suspend_wakeup) | ||
1171 | return 0; | ||
1172 | |||
1173 | wakeup_enable = bank->base + bank->regs->wkup_en; | ||
1174 | |||
1175 | spin_lock_irqsave(&bank->lock, flags); | ||
1176 | bank->saved_wakeup = __raw_readl(wakeup_enable); | ||
1177 | _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); | ||
1178 | _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); | ||
1179 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | static int omap_gpio_resume(struct device *dev) | ||
1185 | { | ||
1186 | struct platform_device *pdev = to_platform_device(dev); | ||
1187 | struct gpio_bank *bank = platform_get_drvdata(pdev); | ||
1188 | void __iomem *base = bank->base; | ||
1189 | unsigned long flags; | ||
1190 | |||
1191 | if (!bank->mod_usage || !bank->loses_context) | ||
1192 | return 0; | ||
1193 | |||
1194 | if (!bank->regs->wkup_en || !bank->saved_wakeup) | ||
1195 | return 0; | ||
1196 | |||
1197 | spin_lock_irqsave(&bank->lock, flags); | ||
1198 | _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); | ||
1199 | _gpio_rmw(base, bank->regs->wkup_en, bank->saved_wakeup, 1); | ||
1200 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1201 | |||
1202 | return 0; | ||
1203 | } | ||
1204 | #endif /* CONFIG_PM_SLEEP */ | ||
1205 | |||
1206 | #if defined(CONFIG_PM_RUNTIME) | 1147 | #if defined(CONFIG_PM_RUNTIME) |
1207 | static void omap_gpio_restore_context(struct gpio_bank *bank); | 1148 | static void omap_gpio_restore_context(struct gpio_bank *bank); |
1208 | 1149 | ||
@@ -1216,6 +1157,9 @@ static int omap_gpio_runtime_suspend(struct device *dev) | |||
1216 | 1157 | ||
1217 | spin_lock_irqsave(&bank->lock, flags); | 1158 | spin_lock_irqsave(&bank->lock, flags); |
1218 | 1159 | ||
1160 | if (!bank->enabled_non_wakeup_gpios) | ||
1161 | goto update_gpio_context_count; | ||
1162 | |||
1219 | /* | 1163 | /* |
1220 | * Only edges can generate a wakeup event to the PRCM. | 1164 | * Only edges can generate a wakeup event to the PRCM. |
1221 | * | 1165 | * |
@@ -1247,11 +1191,9 @@ static int omap_gpio_runtime_suspend(struct device *dev) | |||
1247 | */ | 1191 | */ |
1248 | bank->saved_datain = __raw_readl(bank->base + | 1192 | bank->saved_datain = __raw_readl(bank->base + |
1249 | bank->regs->datain); | 1193 | bank->regs->datain); |
1250 | l1 = __raw_readl(bank->base + bank->regs->fallingdetect); | 1194 | l1 = bank->context.fallingdetect; |
1251 | l2 = __raw_readl(bank->base + bank->regs->risingdetect); | 1195 | l2 = bank->context.risingdetect; |
1252 | 1196 | ||
1253 | bank->saved_fallingdetect = l1; | ||
1254 | bank->saved_risingdetect = l2; | ||
1255 | l1 &= ~bank->enabled_non_wakeup_gpios; | 1197 | l1 &= ~bank->enabled_non_wakeup_gpios; |
1256 | l2 &= ~bank->enabled_non_wakeup_gpios; | 1198 | l2 &= ~bank->enabled_non_wakeup_gpios; |
1257 | 1199 | ||
@@ -1293,11 +1235,6 @@ static int omap_gpio_runtime_resume(struct device *dev) | |||
1293 | __raw_writel(bank->context.risingdetect, | 1235 | __raw_writel(bank->context.risingdetect, |
1294 | bank->base + bank->regs->risingdetect); | 1236 | bank->base + bank->regs->risingdetect); |
1295 | 1237 | ||
1296 | if (!bank->workaround_enabled) { | ||
1297 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | if (bank->get_context_loss_count) { | 1238 | if (bank->get_context_loss_count) { |
1302 | context_lost_cnt_after = | 1239 | context_lost_cnt_after = |
1303 | bank->get_context_loss_count(bank->dev); | 1240 | bank->get_context_loss_count(bank->dev); |
@@ -1310,9 +1247,14 @@ static int omap_gpio_runtime_resume(struct device *dev) | |||
1310 | } | 1247 | } |
1311 | } | 1248 | } |
1312 | 1249 | ||
1313 | __raw_writel(bank->saved_fallingdetect, | 1250 | if (!bank->workaround_enabled) { |
1251 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | __raw_writel(bank->context.fallingdetect, | ||
1314 | bank->base + bank->regs->fallingdetect); | 1256 | bank->base + bank->regs->fallingdetect); |
1315 | __raw_writel(bank->saved_risingdetect, | 1257 | __raw_writel(bank->context.risingdetect, |
1316 | bank->base + bank->regs->risingdetect); | 1258 | bank->base + bank->regs->risingdetect); |
1317 | l = __raw_readl(bank->base + bank->regs->datain); | 1259 | l = __raw_readl(bank->base + bank->regs->datain); |
1318 | 1260 | ||
@@ -1329,14 +1271,15 @@ static int omap_gpio_runtime_resume(struct device *dev) | |||
1329 | * No need to generate IRQs for the rising edge for gpio IRQs | 1271 | * No need to generate IRQs for the rising edge for gpio IRQs |
1330 | * configured with falling edge only; and vice versa. | 1272 | * configured with falling edge only; and vice versa. |
1331 | */ | 1273 | */ |
1332 | gen0 = l & bank->saved_fallingdetect; | 1274 | gen0 = l & bank->context.fallingdetect; |
1333 | gen0 &= bank->saved_datain; | 1275 | gen0 &= bank->saved_datain; |
1334 | 1276 | ||
1335 | gen1 = l & bank->saved_risingdetect; | 1277 | gen1 = l & bank->context.risingdetect; |
1336 | gen1 &= ~(bank->saved_datain); | 1278 | gen1 &= ~(bank->saved_datain); |
1337 | 1279 | ||
1338 | /* FIXME: Consider GPIO IRQs with level detections properly! */ | 1280 | /* FIXME: Consider GPIO IRQs with level detections properly! */ |
1339 | gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect)); | 1281 | gen = l & (~(bank->context.fallingdetect) & |
1282 | ~(bank->context.risingdetect)); | ||
1340 | /* Consider all GPIO IRQs needed to be updated */ | 1283 | /* Consider all GPIO IRQs needed to be updated */ |
1341 | gen |= gen0 | gen1; | 1284 | gen |= gen0 | gen1; |
1342 | 1285 | ||
@@ -1346,14 +1289,14 @@ static int omap_gpio_runtime_resume(struct device *dev) | |||
1346 | old0 = __raw_readl(bank->base + bank->regs->leveldetect0); | 1289 | old0 = __raw_readl(bank->base + bank->regs->leveldetect0); |
1347 | old1 = __raw_readl(bank->base + bank->regs->leveldetect1); | 1290 | old1 = __raw_readl(bank->base + bank->regs->leveldetect1); |
1348 | 1291 | ||
1349 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { | 1292 | if (!bank->regs->irqstatus_raw0) { |
1350 | __raw_writel(old0 | gen, bank->base + | 1293 | __raw_writel(old0 | gen, bank->base + |
1351 | bank->regs->leveldetect0); | 1294 | bank->regs->leveldetect0); |
1352 | __raw_writel(old1 | gen, bank->base + | 1295 | __raw_writel(old1 | gen, bank->base + |
1353 | bank->regs->leveldetect1); | 1296 | bank->regs->leveldetect1); |
1354 | } | 1297 | } |
1355 | 1298 | ||
1356 | if (cpu_is_omap44xx()) { | 1299 | if (bank->regs->irqstatus_raw0) { |
1357 | __raw_writel(old0 | l, bank->base + | 1300 | __raw_writel(old0 | l, bank->base + |
1358 | bank->regs->leveldetect0); | 1301 | bank->regs->leveldetect0); |
1359 | __raw_writel(old1 | l, bank->base + | 1302 | __raw_writel(old1 | l, bank->base + |
@@ -1432,14 +1375,11 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) | |||
1432 | } | 1375 | } |
1433 | #endif /* CONFIG_PM_RUNTIME */ | 1376 | #endif /* CONFIG_PM_RUNTIME */ |
1434 | #else | 1377 | #else |
1435 | #define omap_gpio_suspend NULL | ||
1436 | #define omap_gpio_resume NULL | ||
1437 | #define omap_gpio_runtime_suspend NULL | 1378 | #define omap_gpio_runtime_suspend NULL |
1438 | #define omap_gpio_runtime_resume NULL | 1379 | #define omap_gpio_runtime_resume NULL |
1439 | #endif | 1380 | #endif |
1440 | 1381 | ||
1441 | static const struct dev_pm_ops gpio_pm_ops = { | 1382 | static const struct dev_pm_ops gpio_pm_ops = { |
1442 | SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) | ||
1443 | SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, | 1383 | SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, |
1444 | NULL) | 1384 | NULL) |
1445 | }; | 1385 | }; |