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

Commit 2e47b8b3 authored by Colin Cross's avatar Colin Cross
Browse files

[ARM] tegra: gpio: Add suspend and wake support



Includes checkpatch fixes and TEGRA_NR_GPIOS changes from
Mike Rapoport <mike@compulab.co.il>

Signed-off-by: default avatarColin Cross <ccross@android.com>
parent c5f04b8d
Loading
Loading
Loading
Loading
+93 −11
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

#include <linux/io.h>
#include <linux/gpio.h>
@@ -60,6 +61,13 @@ struct tegra_gpio_bank {
	int bank;
	int irq;
	spinlock_t lvl_lock[4];
#ifdef CONFIG_PM
	u32 cnf[4];
	u32 out[4];
	u32 oe[4];
	u32 int_enb[4];
	u32 int_lvl[4];
#endif
};


@@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = {
	.direction_output	= tegra_gpio_direction_output,
	.set			= tegra_gpio_set,
	.base			= 0,
	.ngpio			= ARCH_NR_GPIOS,
	.ngpio			= TEGRA_NR_GPIOS,
};

static void tegra_gpio_irq_ack(unsigned int irq)
@@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)

}

#ifdef CONFIG_PM
void tegra_gpio_resume(void)
{
	unsigned long flags;
	int b, p, i;

	local_irq_save(flags);

	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];

		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
			unsigned int gpio = (b<<5) | (p<<3);
			__raw_writel(bank->cnf[p], GPIO_CNF(gpio));
			__raw_writel(bank->out[p], GPIO_OUT(gpio));
			__raw_writel(bank->oe[p], GPIO_OE(gpio));
			__raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
			__raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
		}
	}

	local_irq_restore(flags);

	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
		struct irq_desc *desc = irq_to_desc(i);
		if (!desc || (desc->status & IRQ_WAKEUP))
			continue;
		enable_irq(i);
	}
}

void tegra_gpio_suspend(void)
{
	unsigned long flags;
	int b, p, i;

	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
		struct irq_desc *desc = irq_to_desc(i);
		if (!desc)
			continue;
		if (desc->status & IRQ_WAKEUP) {
			int gpio = i - INT_GPIO_BASE;
			pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
			continue;
		}
		disable_irq(i);
	}

	local_irq_save(flags);
	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];

		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
			unsigned int gpio = (b<<5) | (p<<3);
			bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
			bank->out[p] = __raw_readl(GPIO_OUT(gpio));
			bank->oe[p] = __raw_readl(GPIO_OE(gpio));
			bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
			bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
		}
	}
	local_irq_restore(flags);
}

static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
{
	struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
	return set_irq_wake(bank->irq, enable);
}
#endif

static struct irq_chip tegra_gpio_irq_chip = {
	.name		= "GPIO",
@@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = {
	.mask		= tegra_gpio_irq_mask,
	.unmask		= tegra_gpio_irq_unmask,
	.set_type	= tegra_gpio_irq_set_type,
#ifdef CONFIG_PM
	.set_wake	= tegra_gpio_wake_enable,
#endif
};


@@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void)

	gpiochip_add(&tegra_gpio_chip);

	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];

		lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
@@ -312,7 +393,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
	for (i = 0; i < 7; i++) {
		for (j = 0; j < 4; j++) {
			int gpio = tegra_gpio_compose(i, j, 0);
			seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
			seq_printf(s,
				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
				i, j,
				__raw_readl(GPIO_CNF(gpio)),
				__raw_readl(GPIO_OE(gpio)),
+2 −2
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@

#include <mach/irqs.h>

#define ARCH_NR_GPIOS		INT_GPIO_NR
#define TEGRA_NR_GPIOS		INT_GPIO_NR

#include <asm-generic/gpio.h>

@@ -35,7 +35,7 @@

static inline int gpio_to_irq(unsigned int gpio)
{
	if (gpio < ARCH_NR_GPIOS)
	if (gpio < TEGRA_NR_GPIOS)
		return INT_GPIO_BASE + gpio;
	return -EINVAL;
}