提交 935d9180 编写于 作者: T Tony Lindgren

Merge branch 'gpio-2.6.35' of...

Merge branch 'gpio-2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into omap-for-linus
...@@ -107,7 +107,7 @@ static void omap2_enter_full_retention(void) ...@@ -107,7 +107,7 @@ static void omap2_enter_full_retention(void)
l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
omap2_gpio_prepare_for_retention(); omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);
if (omap2_pm_debug) { if (omap2_pm_debug) {
omap2_pm_dump(0, 0, 0); omap2_pm_dump(0, 0, 0);
...@@ -141,7 +141,7 @@ static void omap2_enter_full_retention(void) ...@@ -141,7 +141,7 @@ static void omap2_enter_full_retention(void)
tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
omap2_pm_dump(0, 1, tmp); omap2_pm_dump(0, 1, tmp);
} }
omap2_gpio_resume_after_retention(); omap2_gpio_resume_after_idle();
clk_enable(osc_ck); clk_enable(osc_ck);
......
...@@ -376,7 +376,7 @@ void omap_sram_idle(void) ...@@ -376,7 +376,7 @@ void omap_sram_idle(void)
core_next_state = pwrdm_read_next_pwrst(core_pwrdm); core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
if (per_next_state < PWRDM_POWER_ON) { if (per_next_state < PWRDM_POWER_ON) {
omap_uart_prepare_idle(2); omap_uart_prepare_idle(2);
omap2_gpio_prepare_for_retention(); omap2_gpio_prepare_for_idle(per_next_state);
if (per_next_state == PWRDM_POWER_OFF) { if (per_next_state == PWRDM_POWER_OFF) {
if (core_next_state == PWRDM_POWER_ON) { if (core_next_state == PWRDM_POWER_ON) {
per_next_state = PWRDM_POWER_RET; per_next_state = PWRDM_POWER_RET;
...@@ -454,9 +454,9 @@ void omap_sram_idle(void) ...@@ -454,9 +454,9 @@ void omap_sram_idle(void)
/* PER */ /* PER */
if (per_next_state < PWRDM_POWER_ON) { if (per_next_state < PWRDM_POWER_ON) {
per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm); per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
omap2_gpio_resume_after_idle();
if (per_prev_state == PWRDM_POWER_OFF) if (per_prev_state == PWRDM_POWER_OFF)
omap3_per_restore_context(); omap3_per_restore_context();
omap2_gpio_resume_after_retention();
omap_uart_resume_idle(2); omap_uart_resume_idle(2);
if (per_state_modified) if (per_state_modified)
pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF); pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/gpio.h> #include <mach/gpio.h>
#include <asm/mach/irq.h> #include <asm/mach/irq.h>
#include <plat/powerdomain.h>
/* /*
* OMAP1510 GPIO registers * OMAP1510 GPIO registers
...@@ -195,6 +196,7 @@ struct gpio_bank { ...@@ -195,6 +196,7 @@ struct gpio_bank {
struct gpio_chip chip; struct gpio_chip chip;
struct clk *dbck; struct clk *dbck;
u32 mod_usage; u32 mod_usage;
u32 dbck_enable_mask;
}; };
#define METHOD_MPUIO 0 #define METHOD_MPUIO 0
...@@ -303,8 +305,6 @@ struct omap3_gpio_regs { ...@@ -303,8 +305,6 @@ struct omap3_gpio_regs {
u32 risingdetect; u32 risingdetect;
u32 fallingdetect; u32 fallingdetect;
u32 dataout; u32 dataout;
u32 setwkuena;
u32 setdataout;
}; };
static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
...@@ -646,6 +646,7 @@ void omap_set_gpio_debounce(int gpio, int enable) ...@@ -646,6 +646,7 @@ void omap_set_gpio_debounce(int gpio, int enable)
goto done; goto done;
if (cpu_is_omap34xx() || cpu_is_omap44xx()) { if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
bank->dbck_enable_mask = val;
if (enable) if (enable)
clk_enable(bank->dbck); clk_enable(bank->dbck);
else else
...@@ -724,15 +725,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, ...@@ -724,15 +725,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
OMAP4_GPIO_IRQWAKEN0); OMAP4_GPIO_IRQWAKEN0);
} }
} else { } 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 __raw_writel(1 << gpio, bank->base
+ OMAP24XX_GPIO_SETWKUENA); + OMAP24XX_GPIO_SETWKUENA);
else else
__raw_writel(1 << gpio, bank->base __raw_writel(1 << gpio, bank->base
+ OMAP24XX_GPIO_CLEARWKUENA); + 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; bank->enabled_non_wakeup_gpios |= gpio_bit;
else else
bank->enabled_non_wakeup_gpios &= ~gpio_bit; bank->enabled_non_wakeup_gpios &= ~gpio_bit;
...@@ -1845,7 +1858,8 @@ static int __init _omap_gpio_init(void) ...@@ -1845,7 +1858,8 @@ static int __init _omap_gpio_init(void)
__raw_writel(0, bank->base + __raw_writel(0, bank->base +
OMAP24XX_GPIO_CTRL); 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]; bank->non_wakeup_gpios = non_wakeup_gpios[i];
gpio_count = 32; gpio_count = 32;
} }
...@@ -2028,16 +2042,27 @@ static struct sys_device omap_gpio_device = { ...@@ -2028,16 +2042,27 @@ static struct sys_device omap_gpio_device = {
static int workaround_enabled; 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 i, c = 0;
int min = 0;
/* Remove triggering for all non-wakeup GPIOs. Otherwise spurious if (cpu_is_omap34xx())
* IRQs will be generated. See OMAP2420 Errata item 1.101. */ min = 1;
for (i = 0; i < gpio_bank_count; i++) {
for (i = min; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i]; struct gpio_bank *bank = &gpio_bank[i];
u32 l1, l2; 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)) if (!(bank->enabled_non_wakeup_gpios))
continue; continue;
...@@ -2085,16 +2110,23 @@ void omap2_gpio_prepare_for_retention(void) ...@@ -2085,16 +2110,23 @@ void omap2_gpio_prepare_for_retention(void)
workaround_enabled = 1; workaround_enabled = 1;
} }
void omap2_gpio_resume_after_retention(void) void omap2_gpio_resume_after_idle(void)
{ {
int i; int i;
int min = 0;
if (!workaround_enabled) if (cpu_is_omap34xx())
return; min = 1;
for (i = 0; i < gpio_bank_count; i++) { for (i = min; i < gpio_bank_count; i++) {
struct gpio_bank *bank = &gpio_bank[i]; struct gpio_bank *bank = &gpio_bank[i];
u32 l, gen, gen0, gen1; u32 l, gen, gen0, gen1;
if (bank->dbck_enable_mask)
clk_enable(bank->dbck);
if (!workaround_enabled)
continue;
if (!(bank->enabled_non_wakeup_gpios)) if (!(bank->enabled_non_wakeup_gpios))
continue; continue;
...@@ -2119,7 +2151,7 @@ void omap2_gpio_resume_after_retention(void) ...@@ -2119,7 +2151,7 @@ void omap2_gpio_resume_after_retention(void)
* horribly racy, but it's the best we can do to work around * horribly racy, but it's the best we can do to work around
* this silicon bug. */ * this silicon bug. */
l ^= bank->saved_datain; 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 * No need to generate IRQs for the rising edge for gpio IRQs
...@@ -2207,10 +2239,6 @@ void omap_gpio_save_context(void) ...@@ -2207,10 +2239,6 @@ void omap_gpio_save_context(void)
__raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
gpio_context[i].dataout = gpio_context[i].dataout =
__raw_readl(bank->base + OMAP24XX_GPIO_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) ...@@ -2243,10 +2271,6 @@ void omap_gpio_restore_context(void)
bank->base + OMAP24XX_GPIO_FALLINGDETECT); bank->base + OMAP24XX_GPIO_FALLINGDETECT);
__raw_writel(gpio_context[i].dataout, __raw_writel(gpio_context[i].dataout,
bank->base + OMAP24XX_GPIO_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 #endif
...@@ -2286,110 +2310,3 @@ static int __init omap_gpio_sysinit(void) ...@@ -2286,110 +2310,3 @@ static int __init omap_gpio_sysinit(void)
} }
arch_initcall(omap_gpio_sysinit); 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
...@@ -72,8 +72,8 @@ ...@@ -72,8 +72,8 @@
IH_GPIO_BASE + (nr)) IH_GPIO_BASE + (nr))
extern int omap_gpio_init(void); /* Call from board init only */ extern int omap_gpio_init(void); /* Call from board init only */
extern void omap2_gpio_prepare_for_retention(void); extern void omap2_gpio_prepare_for_idle(int power_state);
extern void omap2_gpio_resume_after_retention(void); extern void omap2_gpio_resume_after_idle(void);
extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce(int gpio, int enable);
extern void omap_set_gpio_debounce_time(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable);
extern void omap_gpio_save_context(void); extern void omap_gpio_save_context(void);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册