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

Commit 60a3437d authored by Tarun Kanti DebBarma's avatar Tarun Kanti DebBarma
Browse files

gpio/omap: handle save/restore context in GPIO driver



Modify omap_gpio_prepare_for_idle() & omap_gpio_resume_after_idle() functions
to handle save context & restore context respectively in the OMAP GPIO driver
itself instead of calling these functions from pm specific files.
For this, in gpio_prepare_for_idle(), call *_get_context_loss_count() and in
gpio_resume_after_idle() call it again. If the count is different, do restore
context.

Signed-off-by: default avatarCharulatha V <charu@ti.com>
Signed-off-by: default avatarTarun Kanti DebBarma <tarun.kanti@ti.com>
Reviewed-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
Reviewed-by: default avatarKevin Hilman <khilman@ti.com>
Signed-off-by: default avatarKevin Hilman <khilman@ti.com>
parent 6d62e216
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@


#include <plat/omap_hwmod.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
#include <plat/omap_device.h>
#include <plat/omap-pm.h>


#include "powerdomain.h"
#include "powerdomain.h"


@@ -55,7 +56,7 @@ static int omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
	pdata->bank_width = dev_attr->bank_width;
	pdata->bank_width = dev_attr->bank_width;
	pdata->dbck_flag = dev_attr->dbck_flag;
	pdata->dbck_flag = dev_attr->dbck_flag;
	pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);
	pdata->virtual_irq_start = IH_GPIO_BASE + 32 * (id - 1);

	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
	pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
	pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
	if (!pdata) {
	if (!pdata) {
		pr_err("gpio%d: Memory allocation failed\n", id);
		pr_err("gpio%d: Memory allocation failed\n", id);
+0 −14
Original line number Original line Diff line number Diff line
@@ -75,16 +75,6 @@ static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *core_pwrdm, *per_pwrdm;
static struct powerdomain *cam_pwrdm;
static struct powerdomain *cam_pwrdm;


static inline void omap3_per_save_context(void)
{
	omap_gpio_save_context();
}

static inline void omap3_per_restore_context(void)
{
	omap_gpio_restore_context();
}

static void omap3_enable_io_chain(void)
static void omap3_enable_io_chain(void)
{
{
	int timeout = 0;
	int timeout = 0;
@@ -332,8 +322,6 @@ void omap_sram_idle(void)
	if (per_next_state < PWRDM_POWER_ON) {
	if (per_next_state < PWRDM_POWER_ON) {
		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
		per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
		omap2_gpio_prepare_for_idle(per_going_off);
		omap2_gpio_prepare_for_idle(per_going_off);
		if (per_next_state == PWRDM_POWER_OFF)
				omap3_per_save_context();
	}
	}


	/* CORE */
	/* CORE */
@@ -399,8 +387,6 @@ void omap_sram_idle(void)
	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();
		omap2_gpio_resume_after_idle();
		if (per_prev_state == PWRDM_POWER_OFF)
			omap3_per_restore_context();
	}
	}


	/* Disable IO-PAD and IO-CHAIN wakeup */
	/* Disable IO-PAD and IO-CHAIN wakeup */
+3 −2
Original line number Original line Diff line number Diff line
@@ -201,14 +201,15 @@ struct omap_gpio_platform_data {
	bool loses_context;	/* whether the bank would ever lose context */
	bool loses_context;	/* whether the bank would ever lose context */


	struct omap_gpio_reg_offs *regs;
	struct omap_gpio_reg_offs *regs;

	/* Return context loss count due to PM states changing */
	int (*get_context_loss_count)(struct device *dev);
};
};


extern void omap2_gpio_prepare_for_idle(int off_mode);
extern void omap2_gpio_prepare_for_idle(int off_mode);
extern void omap2_gpio_resume_after_idle(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_restore_context(void);
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/


/* Wrappers for "new style" GPIO calls, using the new infrastructure
/* Wrappers for "new style" GPIO calls, using the new infrastructure
+58 −73
Original line number Original line Diff line number Diff line
@@ -72,9 +72,11 @@ struct gpio_bank {
	bool loses_context;
	bool loses_context;
	int stride;
	int stride;
	u32 width;
	u32 width;
	int context_loss_count;
	u16 id;
	u16 id;


	void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable);
	void (*set_dataout)(struct gpio_bank *bank, int gpio, int enable);
	int (*get_context_loss_count)(struct device *dev);


	struct omap_gpio_reg_offs *regs;
	struct omap_gpio_reg_offs *regs;
};
};
@@ -1179,6 +1181,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
	bank->stride = pdata->bank_stride;
	bank->stride = pdata->bank_stride;
	bank->width = pdata->bank_width;
	bank->width = pdata->bank_width;
	bank->loses_context = pdata->loses_context;
	bank->loses_context = pdata->loses_context;
	bank->get_context_loss_count = pdata->get_context_loss_count;
	bank->regs = pdata->regs;
	bank->regs = pdata->regs;


	if (bank->regs->set_dataout && bank->regs->clr_dataout)
	if (bank->regs->set_dataout && bank->regs->clr_dataout)
@@ -1323,11 +1326,11 @@ static struct syscore_ops omap_gpio_syscore_ops = {


#ifdef CONFIG_ARCH_OMAP2PLUS
#ifdef CONFIG_ARCH_OMAP2PLUS


static int workaround_enabled;
static void omap_gpio_save_context(struct gpio_bank *bank);
static void omap_gpio_restore_context(struct gpio_bank *bank);


void omap2_gpio_prepare_for_idle(int off_mode)
void omap2_gpio_prepare_for_idle(int off_mode)
{
{
	int c = 0;
	struct gpio_bank *bank;
	struct gpio_bank *bank;


	list_for_each_entry(bank, &omap_gpio_list, node) {
	list_for_each_entry(bank, &omap_gpio_list, node) {
@@ -1347,7 +1350,7 @@ void omap2_gpio_prepare_for_idle(int off_mode)
		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
		 * non-wakeup GPIOs.  Otherwise spurious IRQs will be
		 * generated.  See OMAP2420 Errata item 1.101. */
		 * generated.  See OMAP2420 Errata item 1.101. */
		if (!(bank->enabled_non_wakeup_gpios))
		if (!(bank->enabled_non_wakeup_gpios))
			continue;
			goto save_gpio_context;


		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
		if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
			bank->saved_datain = __raw_readl(bank->base +
			bank->saved_datain = __raw_readl(bank->base +
@@ -1384,13 +1387,13 @@ void omap2_gpio_prepare_for_idle(int off_mode)
			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
			__raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
		}
		}


		c++;
save_gpio_context:
	}
		if (bank->get_context_loss_count)
	if (!c) {
			bank->context_loss_count =
		workaround_enabled = 0;
				bank->get_context_loss_count(bank->dev);
		return;

		omap_gpio_save_context(bank);
	}
	}
	workaround_enabled = 1;
}
}


void omap2_gpio_resume_after_idle(void)
void omap2_gpio_resume_after_idle(void)
@@ -1398,6 +1401,7 @@ void omap2_gpio_resume_after_idle(void)
	struct gpio_bank *bank;
	struct gpio_bank *bank;


	list_for_each_entry(bank, &omap_gpio_list, node) {
	list_for_each_entry(bank, &omap_gpio_list, node) {
		int context_lost_cnt_after;
		u32 l = 0, gen, gen0, gen1;
		u32 l = 0, gen, gen0, gen1;
		int j;
		int j;


@@ -1407,8 +1411,13 @@ void omap2_gpio_resume_after_idle(void)
		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
		for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
			clk_enable(bank->dbck);
			clk_enable(bank->dbck);


		if (!workaround_enabled)
		if (bank->get_context_loss_count) {
			continue;
			context_lost_cnt_after =
				bank->get_context_loss_count(bank->dev);
			if (context_lost_cnt_after != bank->context_loss_count
				|| !context_lost_cnt_after)
				omap_gpio_restore_context(bank);
		}


		if (!(bank->enabled_non_wakeup_gpios))
		if (!(bank->enabled_non_wakeup_gpios))
			continue;
			continue;
@@ -1486,31 +1495,18 @@ void omap2_gpio_resume_after_idle(void)
			}
			}
		}
		}
	}
	}

}
}


#endif
static void omap_gpio_save_context(struct gpio_bank *bank)

#ifdef CONFIG_ARCH_OMAP3
void omap_gpio_save_context(void)
{
{
	struct gpio_bank *bank;

	list_for_each_entry(bank, &omap_gpio_list, node) {

		if (!bank->loses_context)
			continue;

	bank->context.irqenable1 =
	bank->context.irqenable1 =
		__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
		__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
	bank->context.irqenable2 =
	bank->context.irqenable2 =
		__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
		__raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
	bank->context.wake_en =
	bank->context.wake_en =
		__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
		__raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
		bank->context.ctrl =
	bank->context.ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
			__raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
	bank->context.oe = __raw_readl(bank->base + OMAP24XX_GPIO_OE);
		bank->context.oe =
			__raw_readl(bank->base + OMAP24XX_GPIO_OE);
	bank->context.leveldetect0 =
	bank->context.leveldetect0 =
		__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
		__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
	bank->context.leveldetect1 =
	bank->context.leveldetect1 =
@@ -1522,27 +1518,17 @@ void omap_gpio_save_context(void)
	bank->context.dataout =
	bank->context.dataout =
		__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
		__raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
}
}
}


void omap_gpio_restore_context(void)
static void omap_gpio_restore_context(struct gpio_bank *bank)
{
{
	struct gpio_bank *bank;

	list_for_each_entry(bank, &omap_gpio_list, node) {

		if (!bank->loses_context)
			continue;

	__raw_writel(bank->context.irqenable1,
	__raw_writel(bank->context.irqenable1,
			bank->base + OMAP24XX_GPIO_IRQENABLE1);
			bank->base + OMAP24XX_GPIO_IRQENABLE1);
	__raw_writel(bank->context.irqenable2,
	__raw_writel(bank->context.irqenable2,
			bank->base + OMAP24XX_GPIO_IRQENABLE2);
			bank->base + OMAP24XX_GPIO_IRQENABLE2);
	__raw_writel(bank->context.wake_en,
	__raw_writel(bank->context.wake_en,
			bank->base + OMAP24XX_GPIO_WAKE_EN);
			bank->base + OMAP24XX_GPIO_WAKE_EN);
		__raw_writel(bank->context.ctrl,
	__raw_writel(bank->context.ctrl, bank->base + OMAP24XX_GPIO_CTRL);
				bank->base + OMAP24XX_GPIO_CTRL);
	__raw_writel(bank->context.oe, bank->base + OMAP24XX_GPIO_OE);
		__raw_writel(bank->context.oe,
				bank->base + OMAP24XX_GPIO_OE);
	__raw_writel(bank->context.leveldetect0,
	__raw_writel(bank->context.leveldetect0,
			bank->base + OMAP24XX_GPIO_LEVELDETECT0);
			bank->base + OMAP24XX_GPIO_LEVELDETECT0);
	__raw_writel(bank->context.leveldetect1,
	__raw_writel(bank->context.leveldetect1,
@@ -1554,7 +1540,6 @@ void omap_gpio_restore_context(void)
	__raw_writel(bank->context.dataout,
	__raw_writel(bank->context.dataout,
			bank->base + OMAP24XX_GPIO_DATAOUT);
			bank->base + OMAP24XX_GPIO_DATAOUT);
}
}
}
#endif
#endif


static struct platform_driver omap_gpio_driver = {
static struct platform_driver omap_gpio_driver = {