Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 935d9180 authored by Tony Lindgren's avatar Tony Lindgren
Browse files

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
parents df760137 d009559a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ static void omap2_enter_full_retention(void)
	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);

	omap2_gpio_prepare_for_retention();
	omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);

	if (omap2_pm_debug) {
		omap2_pm_dump(0, 0, 0);
@@ -141,7 +141,7 @@ static void omap2_enter_full_retention(void)
		tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
		omap2_pm_dump(0, 1, tmp);
	}
	omap2_gpio_resume_after_retention();
	omap2_gpio_resume_after_idle();

	clk_enable(osc_ck);

+2 −2
Original line number Diff line number Diff line
@@ -376,7 +376,7 @@ void omap_sram_idle(void)
	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
	if (per_next_state < PWRDM_POWER_ON) {
		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 (core_next_state == PWRDM_POWER_ON) {
				per_next_state = PWRDM_POWER_RET;
@@ -454,9 +454,9 @@ void omap_sram_idle(void)
	/* PER */
	if (per_next_state < PWRDM_POWER_ON) {
		per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
		omap2_gpio_resume_after_idle();
		if (per_prev_state == PWRDM_POWER_OFF)
			omap3_per_restore_context();
		omap2_gpio_resume_after_retention();
		omap_uart_resume_idle(2);
		if (per_state_modified)
			pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
+47 −130
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -72,8 +72,8 @@
				 IH_GPIO_BASE + (nr))

extern int omap_gpio_init(void);	/* Call from board init only */
extern void omap2_gpio_prepare_for_retention(void);
extern void omap2_gpio_resume_after_retention(void);
extern void omap2_gpio_prepare_for_idle(int power_state);
extern void omap2_gpio_resume_after_idle(void);
extern void omap_set_gpio_debounce(int gpio, int enable);
extern void omap_set_gpio_debounce_time(int gpio, int enable);
extern void omap_gpio_save_context(void);