diff options
| author | Rodrigo Vivi <[email protected]> | 2018-07-23 09:13:12 -0700 | 
|---|---|---|
| committer | Rodrigo Vivi <[email protected]> | 2018-07-23 09:13:12 -0700 | 
| commit | c74a7469f97c0f40b46e82ee979f9fb1bb6e847c (patch) | |
| tree | f2690a1a916b73ef94657fbf0e0141ae57701825 /arch/arm/mach-omap2/prm44xx.c | |
| parent | 6f15a7de86c8cf2dc09fc9e6d07047efa40ef809 (diff) | |
| parent | 500775074f88d9cf5416bed2ca19592812d62c41 (diff) | |
Merge drm/drm-next into drm-intel-next-queued
We need a backmerge to get DP_DPCD_REV_14 before we push other
i915 changes to dinq that could break compilation.
Signed-off-by: Rodrigo Vivi <[email protected]>
Diffstat (limited to 'arch/arm/mach-omap2/prm44xx.c')
| -rw-r--r-- | arch/arm/mach-omap2/prm44xx.c | 104 | 
1 files changed, 104 insertions, 0 deletions
| diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index acb95936dfe7..7b95729e8359 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -12,6 +12,7 @@   * published by the Free Software Foundation.   */ +#include <linux/cpu_pm.h>  #include <linux/kernel.h>  #include <linux/delay.h>  #include <linux/errno.h> @@ -30,6 +31,7 @@  #include "prcm44xx.h"  #include "prminst44xx.h"  #include "powerdomain.h" +#include "pm.h"  /* Static data */ @@ -57,6 +59,13 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {  	.reconfigure_io_chain	= &omap44xx_prm_reconfigure_io_chain,  }; +struct omap_prm_irq_context { +	unsigned long irq_enable; +	unsigned long pm_ctrl; +}; + +static struct omap_prm_irq_context omap_prm_context; +  /*   * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST   *   hardware register (which are specific to OMAP44xx SoCs) to reset @@ -667,6 +676,54 @@ static int omap4_check_vcvp(void)  	return 0;  } +/** + * omap4_pwrdm_save_context - Saves the powerdomain state + * @pwrdm: pointer to individual powerdomain + * + * The function saves the powerdomain state control information. + * This is needed in rtc+ddr modes where we lose powerdomain context. + */ +static void omap4_pwrdm_save_context(struct powerdomain *pwrdm) +{ +	pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, +						     pwrdm->prcm_offs, +						     pwrdm->pwrstctrl_offs); + +	/* +	 * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request, +	 * reading back a 1 indicates a request in progress. +	 */ +	pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK; +} + +/** + * omap4_pwrdm_restore_context - Restores the powerdomain state + * @pwrdm: pointer to individual powerdomain + * + * The function restores the powerdomain state control information. + * This is needed in rtc+ddr modes where we lose powerdomain context. + */ +static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm) +{ +	int st, ctrl; + +	st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, +					 pwrdm->prcm_offs, +					 pwrdm->pwrstctrl_offs); + +	omap4_prminst_write_inst_reg(pwrdm->context, +				     pwrdm->prcm_partition, +				     pwrdm->prcm_offs, +				     pwrdm->pwrstctrl_offs); + +	/* Make sure we only wait for a transition if there is one */ +	st &= OMAP_POWERSTATEST_MASK; +	ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context; + +	if (st != ctrl) +		omap4_pwrdm_wait_transition(pwrdm); +} +  struct pwrdm_ops omap4_pwrdm_operations = {  	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,  	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst, @@ -685,10 +742,50 @@ struct pwrdm_ops omap4_pwrdm_operations = {  	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,  	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,  	.pwrdm_has_voltdm	= omap4_check_vcvp, +	.pwrdm_save_context	= omap4_pwrdm_save_context, +	.pwrdm_restore_context	= omap4_pwrdm_restore_context,  };  static int omap44xx_prm_late_init(void); +void prm_save_context(void) +{ +	omap_prm_context.irq_enable = +			omap4_prm_read_inst_reg(AM43XX_PRM_OCP_SOCKET_INST, +						omap4_prcm_irq_setup.mask); + +	omap_prm_context.pm_ctrl = +			omap4_prm_read_inst_reg(AM43XX_PRM_DEVICE_INST, +						omap4_prcm_irq_setup.pm_ctrl); +} + +void prm_restore_context(void) +{ +	omap4_prm_write_inst_reg(omap_prm_context.irq_enable, +				 OMAP4430_PRM_OCP_SOCKET_INST, +				 omap4_prcm_irq_setup.mask); + +	omap4_prm_write_inst_reg(omap_prm_context.pm_ctrl, +				 AM43XX_PRM_DEVICE_INST, +				 omap4_prcm_irq_setup.pm_ctrl); +} + +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ +	switch (cmd) { +	case CPU_CLUSTER_PM_ENTER: +		if (enable_off_mode) +			prm_save_context(); +		break; +	case CPU_CLUSTER_PM_EXIT: +		if (enable_off_mode) +			prm_restore_context(); +		break; +	} + +	return NOTIFY_OK; +} +  /*   * XXX document   */ @@ -709,6 +806,7 @@ static const struct omap_prcm_init_data *prm_init_data;  int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)  { +	static struct notifier_block nb;  	omap_prm_base_init();  	prm_init_data = data; @@ -730,6 +828,12 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)  		omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET;  	} +	/* Only AM43XX can lose prm context during rtc-ddr suspend */ +	if (soc_is_am43xx()) { +		nb.notifier_call = cpu_notifier; +		cpu_pm_register_notifier(&nb); +	} +  	return prm_register(&omap44xx_prm_ll_data);  } |