|
@@ -27,6 +27,7 @@
|
|
|
#include <mach/irqs.h>
|
|
|
#include <mach/gpio.h>
|
|
|
#include <asm/mach/irq.h>
|
|
|
+#include <plat/powerdomain.h>
|
|
|
|
|
|
/*
|
|
|
* OMAP1510 GPIO registers
|
|
@@ -195,6 +196,7 @@ struct gpio_bank {
|
|
|
struct gpio_chip chip;
|
|
|
struct clk *dbck;
|
|
|
u32 mod_usage;
|
|
|
+ u32 dbck_enable_mask;
|
|
|
};
|
|
|
|
|
|
#define METHOD_MPUIO 0
|
|
@@ -303,8 +305,6 @@ struct omap3_gpio_regs {
|
|
|
u32 risingdetect;
|
|
|
u32 fallingdetect;
|
|
|
u32 dataout;
|
|
|
- u32 setwkuena;
|
|
|
- u32 setdataout;
|
|
|
};
|
|
|
|
|
|
static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
|
|
@@ -646,6 +646,7 @@ void omap_set_gpio_debounce(int gpio, int enable)
|
|
|
goto done;
|
|
|
|
|
|
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
|
|
|
+ bank->dbck_enable_mask = val;
|
|
|
if (enable)
|
|
|
clk_enable(bank->dbck);
|
|
|
else
|
|
@@ -724,15 +725,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
|
|
|
OMAP4_GPIO_IRQWAKEN0);
|
|
|
}
|
|
|
} else {
|
|
|
- if (trigger != 0)
|
|
|
+ /*
|
|
|
+ * GPIO wakeup request can only be generated on edge
|
|
|
+ * transitions
|
|
|
+ */
|
|
|
+ if (trigger & IRQ_TYPE_EDGE_BOTH)
|
|
|
__raw_writel(1 << gpio, bank->base
|
|
|
+ OMAP24XX_GPIO_SETWKUENA);
|
|
|
else
|
|
|
__raw_writel(1 << gpio, bank->base
|
|
|
+ OMAP24XX_GPIO_CLEARWKUENA);
|
|
|
}
|
|
|
- } else {
|
|
|
- if (trigger != 0)
|
|
|
+ }
|
|
|
+ /* This part needs to be executed always for OMAP34xx */
|
|
|
+ if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
|
|
|
+ /*
|
|
|
+ * Log the edge gpio and manually trigger the IRQ
|
|
|
+ * after resume if the input level changes
|
|
|
+ * to avoid irq lost during PER RET/OFF mode
|
|
|
+ * Applies for omap2 non-wakeup gpio and all omap3 gpios
|
|
|
+ */
|
|
|
+ if (trigger & IRQ_TYPE_EDGE_BOTH)
|
|
|
bank->enabled_non_wakeup_gpios |= gpio_bit;
|
|
|
else
|
|
|
bank->enabled_non_wakeup_gpios &= ~gpio_bit;
|
|
@@ -1845,7 +1858,8 @@ static int __init _omap_gpio_init(void)
|
|
|
__raw_writel(0, bank->base +
|
|
|
OMAP24XX_GPIO_CTRL);
|
|
|
}
|
|
|
- if (i < ARRAY_SIZE(non_wakeup_gpios))
|
|
|
+ if (cpu_is_omap24xx() &&
|
|
|
+ i < ARRAY_SIZE(non_wakeup_gpios))
|
|
|
bank->non_wakeup_gpios = non_wakeup_gpios[i];
|
|
|
gpio_count = 32;
|
|
|
}
|
|
@@ -2028,16 +2042,27 @@ static struct sys_device omap_gpio_device = {
|
|
|
|
|
|
static int workaround_enabled;
|
|
|
|
|
|
-void omap2_gpio_prepare_for_retention(void)
|
|
|
+void omap2_gpio_prepare_for_idle(int power_state)
|
|
|
{
|
|
|
int i, c = 0;
|
|
|
+ int min = 0;
|
|
|
|
|
|
- /* Remove triggering for all non-wakeup GPIOs. Otherwise spurious
|
|
|
- * IRQs will be generated. See OMAP2420 Errata item 1.101. */
|
|
|
- for (i = 0; i < gpio_bank_count; i++) {
|
|
|
+ if (cpu_is_omap34xx())
|
|
|
+ min = 1;
|
|
|
+
|
|
|
+ for (i = min; i < gpio_bank_count; i++) {
|
|
|
struct gpio_bank *bank = &gpio_bank[i];
|
|
|
u32 l1, l2;
|
|
|
|
|
|
+ if (bank->dbck_enable_mask)
|
|
|
+ clk_disable(bank->dbck);
|
|
|
+
|
|
|
+ if (power_state > PWRDM_POWER_OFF)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* If going to OFF, remove triggering for all
|
|
|
+ * non-wakeup GPIOs. Otherwise spurious IRQs will be
|
|
|
+ * generated. See OMAP2420 Errata item 1.101. */
|
|
|
if (!(bank->enabled_non_wakeup_gpios))
|
|
|
continue;
|
|
|
|
|
@@ -2085,16 +2110,23 @@ void omap2_gpio_prepare_for_retention(void)
|
|
|
workaround_enabled = 1;
|
|
|
}
|
|
|
|
|
|
-void omap2_gpio_resume_after_retention(void)
|
|
|
+void omap2_gpio_resume_after_idle(void)
|
|
|
{
|
|
|
int i;
|
|
|
+ int min = 0;
|
|
|
|
|
|
- if (!workaround_enabled)
|
|
|
- return;
|
|
|
- for (i = 0; i < gpio_bank_count; i++) {
|
|
|
+ if (cpu_is_omap34xx())
|
|
|
+ min = 1;
|
|
|
+ for (i = min; i < gpio_bank_count; i++) {
|
|
|
struct gpio_bank *bank = &gpio_bank[i];
|
|
|
u32 l, gen, gen0, gen1;
|
|
|
|
|
|
+ if (bank->dbck_enable_mask)
|
|
|
+ clk_enable(bank->dbck);
|
|
|
+
|
|
|
+ if (!workaround_enabled)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (!(bank->enabled_non_wakeup_gpios))
|
|
|
continue;
|
|
|
|
|
@@ -2119,7 +2151,7 @@ void omap2_gpio_resume_after_retention(void)
|
|
|
* horribly racy, but it's the best we can do to work around
|
|
|
* this silicon bug. */
|
|
|
l ^= bank->saved_datain;
|
|
|
- l &= bank->non_wakeup_gpios;
|
|
|
+ l &= bank->enabled_non_wakeup_gpios;
|
|
|
|
|
|
/*
|
|
|
* No need to generate IRQs for the rising edge for gpio IRQs
|
|
@@ -2207,10 +2239,6 @@ void omap_gpio_save_context(void)
|
|
|
__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
|
|
|
gpio_context[i].dataout =
|
|
|
__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
|
|
|
- gpio_context[i].setwkuena =
|
|
|
- __raw_readl(bank->base + OMAP24XX_GPIO_SETWKUENA);
|
|
|
- gpio_context[i].setdataout =
|
|
|
- __raw_readl(bank->base + OMAP24XX_GPIO_SETDATAOUT);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2243,10 +2271,6 @@ void omap_gpio_restore_context(void)
|
|
|
bank->base + OMAP24XX_GPIO_FALLINGDETECT);
|
|
|
__raw_writel(gpio_context[i].dataout,
|
|
|
bank->base + OMAP24XX_GPIO_DATAOUT);
|
|
|
- __raw_writel(gpio_context[i].setwkuena,
|
|
|
- bank->base + OMAP24XX_GPIO_SETWKUENA);
|
|
|
- __raw_writel(gpio_context[i].setdataout,
|
|
|
- bank->base + OMAP24XX_GPIO_SETDATAOUT);
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
@@ -2286,110 +2310,3 @@ static int __init omap_gpio_sysinit(void)
|
|
|
}
|
|
|
|
|
|
arch_initcall(omap_gpio_sysinit);
|
|
|
-
|
|
|
-
|
|
|
-#ifdef CONFIG_DEBUG_FS
|
|
|
-
|
|
|
-#include <linux/debugfs.h>
|
|
|
-#include <linux/seq_file.h>
|
|
|
-
|
|
|
-static int dbg_gpio_show(struct seq_file *s, void *unused)
|
|
|
-{
|
|
|
- unsigned i, j, gpio;
|
|
|
-
|
|
|
- for (i = 0, gpio = 0; i < gpio_bank_count; i++) {
|
|
|
- struct gpio_bank *bank = gpio_bank + i;
|
|
|
- unsigned bankwidth = 16;
|
|
|
- u32 mask = 1;
|
|
|
-
|
|
|
- if (bank_is_mpuio(bank))
|
|
|
- gpio = OMAP_MPUIO(0);
|
|
|
- else if (cpu_class_is_omap2() || cpu_is_omap7xx())
|
|
|
- bankwidth = 32;
|
|
|
-
|
|
|
- for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
|
|
|
- unsigned irq, value, is_in, irqstat;
|
|
|
- const char *label;
|
|
|
-
|
|
|
- label = gpiochip_is_requested(&bank->chip, j);
|
|
|
- if (!label)
|
|
|
- continue;
|
|
|
-
|
|
|
- irq = bank->virtual_irq_start + j;
|
|
|
- value = gpio_get_value(gpio);
|
|
|
- is_in = gpio_is_input(bank, mask);
|
|
|
-
|
|
|
- if (bank_is_mpuio(bank))
|
|
|
- seq_printf(s, "MPUIO %2d ", j);
|
|
|
- else
|
|
|
- seq_printf(s, "GPIO %3d ", gpio);
|
|
|
- seq_printf(s, "(%-20.20s): %s %s",
|
|
|
- label,
|
|
|
- is_in ? "in " : "out",
|
|
|
- value ? "hi" : "lo");
|
|
|
-
|
|
|
-/* FIXME for at least omap2, show pullup/pulldown state */
|
|
|
-
|
|
|
- irqstat = irq_desc[irq].status;
|
|
|
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
|
|
|
- if (is_in && ((bank->suspend_wakeup & mask)
|
|
|
- || irqstat & IRQ_TYPE_SENSE_MASK)) {
|
|
|
- char *trigger = NULL;
|
|
|
-
|
|
|
- switch (irqstat & IRQ_TYPE_SENSE_MASK) {
|
|
|
- case IRQ_TYPE_EDGE_FALLING:
|
|
|
- trigger = "falling";
|
|
|
- break;
|
|
|
- case IRQ_TYPE_EDGE_RISING:
|
|
|
- trigger = "rising";
|
|
|
- break;
|
|
|
- case IRQ_TYPE_EDGE_BOTH:
|
|
|
- trigger = "bothedge";
|
|
|
- break;
|
|
|
- case IRQ_TYPE_LEVEL_LOW:
|
|
|
- trigger = "low";
|
|
|
- break;
|
|
|
- case IRQ_TYPE_LEVEL_HIGH:
|
|
|
- trigger = "high";
|
|
|
- break;
|
|
|
- case IRQ_TYPE_NONE:
|
|
|
- trigger = "(?)";
|
|
|
- break;
|
|
|
- }
|
|
|
- seq_printf(s, ", irq-%d %-8s%s",
|
|
|
- irq, trigger,
|
|
|
- (bank->suspend_wakeup & mask)
|
|
|
- ? " wakeup" : "");
|
|
|
- }
|
|
|
-#endif
|
|
|
- seq_printf(s, "\n");
|
|
|
- }
|
|
|
-
|
|
|
- if (bank_is_mpuio(bank)) {
|
|
|
- seq_printf(s, "\n");
|
|
|
- gpio = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static int dbg_gpio_open(struct inode *inode, struct file *file)
|
|
|
-{
|
|
|
- return single_open(file, dbg_gpio_show, &inode->i_private);
|
|
|
-}
|
|
|
-
|
|
|
-static const struct file_operations debug_fops = {
|
|
|
- .open = dbg_gpio_open,
|
|
|
- .read = seq_read,
|
|
|
- .llseek = seq_lseek,
|
|
|
- .release = single_release,
|
|
|
-};
|
|
|
-
|
|
|
-static int __init omap_gpio_debuginit(void)
|
|
|
-{
|
|
|
- (void) debugfs_create_file("omap_gpio", S_IRUGO,
|
|
|
- NULL, NULL, &debug_fops);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-late_initcall(omap_gpio_debuginit);
|
|
|
-#endif
|