summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 03:49:09 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-12 03:49:09 +0300
commit7c00e8ae041b349992047769af741b67379ce19a (patch)
treee3d504b9523eb6b4109a1873ed804ed03762b26d /arch/arm/mach-omap2
parenta2b7ab45b8905b9c1813b0212e82a39d5c081c8a (diff)
parent958da6e3ff446fe558bdf0fd06fb2713539ebeef (diff)
downloadlinux-7c00e8ae041b349992047769af741b67379ce19a.tar.xz
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Olof Johansson: "Here are the main updates for SoC support (besides DT additions) for ARM 32- and 64-bit platforms. The branch also contains defconfig updates to turn on drivers and options as needed on the various platforms. The largest parts of the delta are from cleanups moving platform data and board file setup of TI platforms to ti-sysc bus drivers. There are also some sweeping changes of eeprom and nand setup on Davinci, i.MX and other platforms. Samsung is removing support for Exynos5440, which was an oddball SoC that hasn't been seen much use in designs. Renesas is adding support for new SoCs (R-Car E3, RZ/G1C and RZ/N1D). Linus Walleij is also removing support for ux500 (Sony Ericsson) U8540/9540 SoCs that never made it to significant mass production and products" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (133 commits) MAINTAINERS: add NXP linux team maillist as i.MX reviewer ARM: stm32: Don't select DMA unconditionally on STM32MP157C arm64: defconfig: Enable PCIe on msm8996 and db820c ARM: pxa3xx: enable external wakeup pins ARM: pxa: stargate2: use device properties for at24 eeprom arm64: defconfig: Enable HISILICON_LPC arm64: defconfig: enable drivers for Poplar support arm64: defconfig: Enable UFS on msm8996 ARM: berlin: switch to SPDX license identifier arm: berlin: remove non-necessary flush_cache_all() ARM: berlin: extend BG2CD Kconfig entry OMAP: CLK: CLKSRC: Add suspend resume hooks ARM: AM43XX: Add functions to save/restore am43xx control registers ASoC: ams_delta: use GPIO lookup table ARM: OMAP1: ams-delta: add GPIO lookup tables bus: ti-sysc: Fix optional clocks array access ARM: OMAP2+: Make sure LOGICRETSTATE bits are not cleared ARM: OMAP2+: prm44xx: Inroduce cpu_pm notifiers for context save/restore ARM: OMAP2+: prm44xx: Introduce context save/restore for am43 PRCM IO ARM: OMAP2+: powerdomain: Introduce cpu_pm notifiers for context save/restore ...
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Makefile1
-rw-r--r--arch/arm/mach-omap2/board-generic.c2
-rw-r--r--arch/arm/mach-omap2/clockdomain.c73
-rw-r--r--arch/arm/mach-omap2/clockdomain.h8
-rw-r--r--arch/arm/mach-omap2/cm33xx.c53
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c43
-rw-r--r--arch/arm/mach-omap2/common.h18
-rw-r--r--arch/arm/mach-omap2/control.c112
-rw-r--r--arch/arm/mach-omap2/control.h61
-rw-r--r--arch/arm/mach-omap2/display.c10
-rw-r--r--arch/arm/mach-omap2/hsmmc.c1
-rw-r--r--arch/arm/mach-omap2/i2c.c1
-rw-r--r--arch/arm/mach-omap2/io.c70
-rw-r--r--arch/arm/mach-omap2/omap-pm-noop.c176
-rw-r--r--arch/arm/mach-omap2/omap-pm.h161
-rw-r--r--arch/arm/mach-omap2/omap_device.c22
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c21
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.h6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_43xx_data.c1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c4
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_54xx_data.c3
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_7xx_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_81xx_data.c1
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c15
-rw-r--r--arch/arm/mach-omap2/pm-debug.c5
-rw-r--r--arch/arm/mach-omap2/pm.c21
-rw-r--r--arch/arm/mach-omap2/pm33xx-core.c4
-rw-r--r--arch/arm/mach-omap2/pm44xx.c13
-rw-r--r--arch/arm/mach-omap2/powerdomain.c87
-rw-r--r--arch/arm/mach-omap2/powerdomain.h7
-rw-r--r--arch/arm/mach-omap2/prm33xx.c31
-rw-r--r--arch/arm/mach-omap2/prm44xx.c104
-rw-r--r--arch/arm/mach-omap2/timer.c100
35 files changed, 764 insertions, 482 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 0d9ce58bc464..01377c292db4 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -78,7 +78,6 @@ endif
omap-4-5-pm-common = omap-mpuss-lowpower.o
obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-pm-common)
obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-pm-common)
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6c61ecc62905..6b4f4975cf7a 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -31,8 +31,6 @@ static const struct of_device_id omap_dt_match_table[] __initconst = {
static void __init __maybe_unused omap_generic_init(void)
{
pdata_quirks_init(omap_dt_match_table);
-
- omapdss_init_of();
omap_soc_device_init();
}
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index b79b1ca9aee9..6d44fe05a3fe 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -23,6 +23,7 @@
#include <linux/limits.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
+#include <linux/cpu_pm.h>
#include <linux/io.h>
@@ -31,6 +32,7 @@
#include "soc.h"
#include "clock.h"
#include "clockdomain.h"
+#include "pm.h"
/* clkdm_list contains all registered struct clockdomains */
static LIST_HEAD(clkdm_list);
@@ -39,6 +41,8 @@ static LIST_HEAD(clkdm_list);
static struct clkdm_autodep *autodeps;
static struct clkdm_ops *arch_clkdm;
+void clkdm_save_context(void);
+void clkdm_restore_context(void);
/* Private functions */
@@ -449,6 +453,22 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia)
return 0;
}
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ clkdm_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ clkdm_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
/**
* clkdm_complete_init - set up the clockdomain layer
*
@@ -460,6 +480,7 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia)
int clkdm_complete_init(void)
{
struct clockdomain *clkdm;
+ static struct notifier_block nb;
if (list_empty(&clkdm_list))
return -EACCES;
@@ -474,6 +495,12 @@ int clkdm_complete_init(void)
clkdm_clear_all_sleepdeps(clkdm);
}
+ /* Only AM43XX can lose clkdm context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
@@ -1307,3 +1334,49 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
return 0;
}
+/**
+ * _clkdm_save_context - save the context for the control of this clkdm
+ *
+ * Due to a suspend or hibernation operation, the state of the registers
+ * controlling this clkdm will be lost, save their context.
+ */
+static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed)
+{
+ if (!arch_clkdm || !arch_clkdm->clkdm_save_context)
+ return -EINVAL;
+
+ return arch_clkdm->clkdm_save_context(clkdm);
+}
+
+/**
+ * _clkdm_restore_context - restore context for control of this clkdm
+ *
+ * Restore the register values for this clockdomain.
+ */
+static int _clkdm_restore_context(struct clockdomain *clkdm, void *ununsed)
+{
+ if (!arch_clkdm || !arch_clkdm->clkdm_restore_context)
+ return -EINVAL;
+
+ return arch_clkdm->clkdm_restore_context(clkdm);
+}
+
+/**
+ * clkdm_save_context - Saves the context for each registered clkdm
+ *
+ * Save the context for each registered clockdomain.
+ */
+void clkdm_save_context(void)
+{
+ clkdm_for_each(_clkdm_save_context, NULL);
+}
+
+/**
+ * clkdm_restore_context - Restores the context for each registered clkdm
+ *
+ * Restore the context for each registered clockdomain.
+ */
+void clkdm_restore_context(void)
+{
+ clkdm_for_each(_clkdm_restore_context, NULL);
+}
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 24667a5a9dc0..c7d0953e4aa2 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -141,6 +141,7 @@ struct clockdomain {
int usecount;
int forcewake_count;
struct list_head node;
+ u32 context;
};
/**
@@ -159,6 +160,8 @@ struct clockdomain {
* @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
* @clkdm_clk_enable: Put the clkdm in right state for a clock enable
* @clkdm_clk_disable: Put the clkdm in right state for a clock disable
+ * @clkdm_save_context: Save the current clkdm context
+ * @clkdm_restore_context: Restore the clkdm context
*/
struct clkdm_ops {
int (*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
@@ -175,6 +178,8 @@ struct clkdm_ops {
void (*clkdm_deny_idle)(struct clockdomain *clkdm);
int (*clkdm_clk_enable)(struct clockdomain *clkdm);
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
+ int (*clkdm_save_context)(struct clockdomain *clkdm);
+ int (*clkdm_restore_context)(struct clockdomain *clkdm);
};
int clkdm_register_platform_funcs(struct clkdm_ops *co);
@@ -214,6 +219,9 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
+void clkdm_save_context(void);
+void clkdm_restore_context(void);
+
extern void __init omap242x_clockdomains_init(void);
extern void __init omap243x_clockdomains_init(void);
extern void __init omap3xxx_clockdomains_init(void);
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 1cc0247a2cb5..084d454f6074 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -72,6 +72,17 @@ static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
return v;
}
+static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask)
+{
+ u32 v;
+
+ v = am33xx_cm_read_reg(inst, idx);
+ v &= mask;
+ v >>= __ffs(mask);
+
+ return v;
+}
+
/**
* _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
* @inst: CM instance register offset (*_INST macro)
@@ -338,6 +349,46 @@ static u32 am33xx_cm_xlate_clkctrl(u8 part, u16 inst, u16 offset)
return cm_base.pa + inst + offset;
}
+/**
+ * am33xx_clkdm_save_context - Save the clockdomain transition context
+ * @clkdm: The clockdomain pointer whose context needs to be saved
+ *
+ * Save the clockdomain transition context.
+ */
+static int am33xx_clkdm_save_context(struct clockdomain *clkdm)
+{
+ clkdm->context = am33xx_cm_read_reg_bits(clkdm->cm_inst,
+ clkdm->clkdm_offs,
+ AM33XX_CLKTRCTRL_MASK);
+
+ return 0;
+}
+
+/**
+ * am33xx_restore_save_context - Restore the clockdomain transition context
+ * @clkdm: The clockdomain pointer whose context needs to be restored
+ *
+ * Restore the clockdomain transition context.
+ */
+static int am33xx_clkdm_restore_context(struct clockdomain *clkdm)
+{
+ switch (clkdm->context) {
+ case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
+ am33xx_clkdm_deny_idle(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
+ am33xx_clkdm_sleep(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
+ am33xx_clkdm_wakeup(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
+ am33xx_clkdm_allow_idle(clkdm);
+ break;
+ }
+ return 0;
+}
+
struct clkdm_ops am33xx_clkdm_operations = {
.clkdm_sleep = am33xx_clkdm_sleep,
.clkdm_wakeup = am33xx_clkdm_wakeup,
@@ -345,6 +396,8 @@ struct clkdm_ops am33xx_clkdm_operations = {
.clkdm_deny_idle = am33xx_clkdm_deny_idle,
.clkdm_clk_enable = am33xx_clkdm_clk_enable,
.clkdm_clk_disable = am33xx_clkdm_clk_disable,
+ .clkdm_save_context = am33xx_clkdm_save_context,
+ .clkdm_restore_context = am33xx_clkdm_restore_context,
};
static const struct cm_ll_data am33xx_cm_ll_data = {
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index 7deefee49fc3..c11ac492b626 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -481,6 +481,47 @@ static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset)
return _cm_bases[part].pa + inst + offset;
}
+/**
+ * omap4_clkdm_save_context - Save the clockdomain modulemode context
+ * @clkdm: The clockdomain pointer whose context needs to be saved
+ *
+ * Save the clockdomain modulemode context.
+ */
+static int omap4_clkdm_save_context(struct clockdomain *clkdm)
+{
+ clkdm->context = omap4_cminst_read_inst_reg(clkdm->prcm_partition,
+ clkdm->cm_inst,
+ clkdm->clkdm_offs +
+ OMAP4_CM_CLKSTCTRL);
+ clkdm->context &= OMAP4430_MODULEMODE_MASK;
+ return 0;
+}
+
+/**
+ * omap4_clkdm_restore_context - Restore the clockdomain modulemode context
+ * @clkdm: The clockdomain pointer whose context needs to be restored
+ *
+ * Restore the clockdomain modulemode context.
+ */
+static int omap4_clkdm_restore_context(struct clockdomain *clkdm)
+{
+ switch (clkdm->context) {
+ case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
+ omap4_clkdm_deny_idle(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
+ omap4_clkdm_sleep(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
+ omap4_clkdm_wakeup(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
+ omap4_clkdm_allow_idle(clkdm);
+ break;
+ }
+ return 0;
+}
+
struct clkdm_ops omap4_clkdm_operations = {
.clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
.clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
@@ -496,6 +537,8 @@ struct clkdm_ops omap4_clkdm_operations = {
.clkdm_deny_idle = omap4_clkdm_deny_idle,
.clkdm_clk_enable = omap4_clkdm_clk_enable,
.clkdm_clk_disable = omap4_clkdm_clk_disable,
+ .clkdm_save_context = omap4_clkdm_save_context,
+ .clkdm_restore_context = omap4_clkdm_restore_context,
};
struct clkdm_ops am43xx_clkdm_operations = {
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index fbe0b78bf489..dff3750e432f 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -44,6 +44,9 @@
#define OMAP_INTC_START NR_IRQS
+extern int (*omap_pm_soc_init)(void);
+int omap_pm_nop_init(void);
+
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP2)
int omap2_pm_init(void);
#else
@@ -79,9 +82,12 @@ static inline int omap4_pm_init_early(void)
#if defined(CONFIG_PM) && (defined(CONFIG_SOC_AM33XX) || \
defined(CONFIG_SOC_AM43XX))
-void amx3_common_pm_init(void);
+int amx3_common_pm_init(void);
#else
-static inline void amx3_common_pm_init(void) { }
+static inline int amx3_common_pm_init(void)
+{
+ return 0;
+}
#endif
extern void omap2_init_common_infrastructure(void);
@@ -122,14 +128,10 @@ void am43xx_init_early(void);
void am43xx_init_late(void);
void omap4430_init_early(void);
void omap5_init_early(void);
-void omap3_init_late(void); /* Do not use this one */
+void omap3_init_late(void);
void omap4430_init_late(void);
void omap2420_init_late(void);
void omap2430_init_late(void);
-void omap3430_init_late(void);
-void omap35xx_init_late(void);
-void omap3630_init_late(void);
-void am35xx_init_late(void);
void ti81xx_init_late(void);
void am33xx_init_late(void);
void omap5_init_late(void);
@@ -350,7 +352,5 @@ extern int omap_dss_reset(struct omap_hwmod *);
/* SoC specific clock initializer */
int omap_clk_init(void);
-int __init omapdss_init_of(void);
-
#endif /* __ASSEMBLER__ */
#endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 180da403639e..0bbfb20e193f 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <linux/cpu_pm.h>
#include "soc.h"
#include "iomap.h"
@@ -621,6 +622,110 @@ void __init omap3_ctrl_init(void)
}
#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+static unsigned long am43xx_control_reg_offsets[] = {
+ AM33XX_CONTROL_SYSCONFIG_OFFSET,
+ AM33XX_CONTROL_STATUS_OFFSET,
+ AM43XX_CONTROL_MPU_L2_CTRL_OFFSET,
+ AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET,
+ AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET,
+ AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET,
+ AM33XX_CONTROL_BANDGAP_CTRL_OFFSET,
+ AM33XX_CONTROL_BANDGAP_TRIM_OFFSET,
+ AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET,
+ AM33XX_CONTROL_MOSC_CTRL_OFFSET,
+ AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET,
+ AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET,
+ AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET,
+ AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET,
+ AM33XX_CONTROL_TPTC_CFG_OFFSET,
+ AM33XX_CONTROL_USB_CTRL0_OFFSET,
+ AM33XX_CONTROL_USB_CTRL1_OFFSET,
+ AM43XX_CONTROL_USB_CTRL2_OFFSET,
+ AM43XX_CONTROL_GMII_SEL_OFFSET,
+ AM43XX_CONTROL_MPUSS_CTRL_OFFSET,
+ AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET,
+ AM43XX_CONTROL_PWMSS_CTRL_OFFSET,
+ AM33XX_CONTROL_MREQPRIO_0_OFFSET,
+ AM33XX_CONTROL_MREQPRIO_1_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET,
+ AM33XX_CONTROL_SMRT_CTRL_OFFSET,
+ AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET,
+ AM43XX_CONTROL_CQDETECT_STS_OFFSET,
+ AM43XX_CONTROL_CQDETECT_STS2_OFFSET,
+ AM43XX_CONTROL_VTP_CTRL_OFFSET,
+ AM33XX_CONTROL_VREF_CTRL_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET,
+ AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET,
+ AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_RESET_ISO_OFFSET,
+};
+
+static u32 am33xx_control_vals[ARRAY_SIZE(am43xx_control_reg_offsets)];
+
+/**
+ * am43xx_control_save_context - Save the wakeup domain registers
+ *
+ * Save the wkup domain registers
+ */
+void am43xx_control_save_context(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
+ am33xx_control_vals[i] =
+ omap_ctrl_readl(am43xx_control_reg_offsets[i]);
+}
+
+/**
+ * am43xx_control_restore_context - Restore the wakeup domain registers
+ *
+ * Restore the wkup domain registers
+ */
+void am43xx_control_restore_context(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
+ omap_ctrl_writel(am33xx_control_vals[i],
+ am43xx_control_reg_offsets[i]);
+}
+
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ am43xx_control_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ am43xx_control_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
struct control_init_data {
int index;
void __iomem *mem;
@@ -699,6 +804,7 @@ int __init omap_control_init(void)
const struct omap_prcm_init_data *data;
int ret;
struct regmap *syscon;
+ static struct notifier_block nb;
for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
data = match->data;
@@ -731,6 +837,12 @@ int __init omap_control_init(void)
}
}
+ /* Only AM43XX can lose ctrl registers context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index ec406bc2c6d4..393b42110511 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -409,6 +409,67 @@
#define AM33XX_DEV_FEATURE 0x604
#define AM33XX_SGX_MASK BIT(29)
+/* Additional AM33XX/AM43XX CONTROL registers */
+#define AM33XX_CONTROL_SYSCONFIG_OFFSET 0x0010
+#define AM33XX_CONTROL_STATUS_OFFSET 0x0040
+#define AM43XX_CONTROL_MPU_L2_CTRL_OFFSET 0x01e0
+#define AM33XX_CONTROL_CORTEX_VBBLDO_CTRL_OFFSET 0x041c
+#define AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET 0x0428
+#define AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET 0x042c
+#define AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET 0x0444
+#define AM33XX_CONTROL_BANDGAP_CTRL_OFFSET 0x0448
+#define AM33XX_CONTROL_BANDGAP_TRIM_OFFSET 0x044c
+#define AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET 0x0458
+#define AM33XX_CONTROL_MOSC_CTRL_OFFSET 0x0468
+#define AM33XX_CONTROL_RCOSC_CTRL_OFFSET 0x046c
+#define AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET 0x0470
+#define AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET 0x0534
+#define AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET 0x0608
+#define AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET 0x060c
+#define AM33XX_CONTROL_MMU_CFG_OFFSET 0x0610
+#define AM33XX_CONTROL_TPTC_CFG_OFFSET 0x0614
+#define AM33XX_CONTROL_USB_CTRL0_OFFSET 0x0620
+#define AM33XX_CONTROL_USB_CTRL1_OFFSET 0x0628
+#define AM33XX_CONTROL_USB_WKUP_CTRL_OFFSET 0x0648
+#define AM43XX_CONTROL_USB_CTRL2_OFFSET 0x064c
+#define AM43XX_CONTROL_GMII_SEL_OFFSET 0x0650
+#define AM43XX_CONTROL_MPUSS_CTRL_OFFSET 0x0654
+#define AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET 0x0658
+#define AM43XX_CONTROL_PWMSS_CTRL_OFFSET 0x0664
+#define AM33XX_CONTROL_MREQPRIO_0_OFFSET 0x0670
+#define AM33XX_CONTROL_MREQPRIO_1_OFFSET 0x0674
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET 0x0690
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET 0x0694
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET 0x0698
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET 0x069c
+#define AM33XX_CONTROL_SMRT_CTRL_OFFSET 0x06a0
+#define AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET 0x06a4
+#define AM43XX_CONTROL_CQDETECT_STS_OFFSET 0x0e00
+#define AM43XX_CONTROL_CQDETECT_STS2_OFFSET 0x0e08
+#define AM43XX_CONTROL_VTP_CTRL_OFFSET 0x0e0c
+#define AM33XX_CONTROL_VREF_CTRL_OFFSET 0x0e14
+#define AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET 0x0f90
+#define AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET 0x0f94
+#define AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET 0x0f98
+#define AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET 0x0f9c
+#define AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET 0x0fa0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET 0x0fa4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET 0x0fa8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET 0x0fac
+#define AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET 0x0fb0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET 0x0fb4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET 0x0fb8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET 0x0fbc
+#define AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET 0x0fc0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET 0x0fc4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET 0x0fc8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET 0x0fcc
+#define AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET 0x0fd0
+#define AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET 0x0fd4
+#define AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET 0x0fd8
+#define AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET 0x0fdc
+#define AM33XX_CONTROL_RESET_ISO_OFFSET 0x1000
+
/* CONTROL OMAP STATUS register to identify OMAP3 features */
#define OMAP3_CONTROL_OMAP_STATUS 0x044c
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index b3f6eb5d04a2..9500b6e27380 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -32,7 +32,6 @@
#include <linux/platform_data/omapdss.h>
#include "omap_hwmod.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "common.h"
#include "soc.h"
@@ -126,11 +125,6 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
omap4_dsi_mux_pads(dsi_id, 0);
}
-static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
-{
- return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput);
-}
-
static enum omapdss_version __init omap_display_get_version(void)
{
if (cpu_is_omap24xx())
@@ -169,7 +163,6 @@ static int __init omapdss_init_fbdev(void)
static struct omap_dss_board_info board_data = {
.dsi_enable_pads = omap_dsi_enable_pads,
.dsi_disable_pads = omap_dsi_disable_pads,
- .set_min_bus_tput = omap_dss_set_min_bus_tput,
};
struct device_node *node;
int r;
@@ -392,7 +385,7 @@ static struct device_node * __init omapdss_find_dss_of_node(void)
return NULL;
}
-int __init omapdss_init_of(void)
+static int __init omapdss_init_of(void)
{
int r;
struct device_node *node;
@@ -422,3 +415,4 @@ int __init omapdss_init_of(void)
return omapdss_init_fbdev();
}
+omap_device_initcall(omapdss_init_of);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b064066d431c..0103548b0b15 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -18,7 +18,6 @@
#include "soc.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "hsmmc.h"
#include "control.h"
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index 91a21c3923b2..37ff25ee3d89 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -22,7 +22,6 @@
#include "soc.h"
#include "omap_hwmod.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "prm.h"
#include "common.h"
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index cf546dfe3b32..bb8e0bb7ef5d 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -37,7 +37,6 @@
#include "clock.h"
#include "clock2xxx.h"
#include "clock3xxx.h"
-#include "omap-pm.h"
#include "sdrc.h"
#include "control.h"
#include "serial.h"
@@ -421,13 +420,6 @@ static void __init __maybe_unused omap_hwmod_init_postsetup(void)
postsetup_state = _HWMOD_STATE_ENABLED;
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
-
- omap_pm_if_early_init();
-}
-
-static void __init __maybe_unused omap_common_late_init(void)
-{
- omap2_common_pm_late_init();
}
#ifdef CONFIG_SOC_OMAP2420
@@ -450,9 +442,7 @@ void __init omap2420_init_early(void)
void __init omap2420_init_late(void)
{
- omap_common_late_init();
- omap2_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap2_pm_init;
}
#endif
@@ -476,9 +466,7 @@ void __init omap2430_init_early(void)
void __init omap2430_init_late(void)
{
- omap_common_late_init();
- omap2_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap2_pm_init;
}
#endif
@@ -529,43 +517,12 @@ void __init am35xx_init_early(void)
void __init omap3_init_late(void)
{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap3430_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap35xx_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap3630_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init am35xx_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap3_pm_init;
}
void __init ti81xx_init_late(void)
{
- omap_common_late_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap_pm_nop_init;
}
#endif
@@ -621,8 +578,7 @@ void __init am33xx_init_early(void)
void __init am33xx_init_late(void)
{
- omap_common_late_init();
- amx3_common_pm_init();
+ omap_pm_soc_init = amx3_common_pm_init;
}
#endif
@@ -645,9 +601,7 @@ void __init am43xx_init_early(void)
void __init am43xx_init_late(void)
{
- omap_common_late_init();
- omap2_clk_enable_autoidle_all();
- amx3_common_pm_init();
+ omap_pm_soc_init = amx3_common_pm_init;
}
#endif
@@ -675,9 +629,7 @@ void __init omap4430_init_early(void)
void __init omap4430_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
@@ -703,9 +655,7 @@ void __init omap5_init_early(void)
void __init omap5_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
@@ -728,9 +678,7 @@ void __init dra7xx_init_early(void)
void __init dra7xx_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
diff --git a/arch/arm/mach-omap2/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c
deleted file mode 100644
index 4ead077ea4e7..000000000000
--- a/arch/arm/mach-omap2/omap-pm-noop.c
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * omap-pm-noop.c - OMAP power management interface - dummy version
- *
- * This code implements the OMAP power management interface to
- * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
- * debug/demonstration use, as it does nothing but printk() whenever a
- * function is called (when DEBUG is defined, below)
- *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order):
- * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan
- * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff
- */
-
-#undef DEBUG
-
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-
-#include "omap_device.h"
-#include "omap-pm.h"
-
-static bool off_mode_enabled;
-static int dummy_context_loss_counter;
-
-/*
- * Device-driver-originated constraints (via board-*.c files)
- */
-
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
-{
- if (!dev || t < -1) {
- WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
- return -EINVAL;
- }
-
- if (t == -1)
- pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
- dev_name(dev));
- else
- pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n",
- dev_name(dev), t);
-
- /*
- * For current Linux, this needs to map the MPU to a
- * powerdomain, then go through the list of current max lat
- * constraints on the MPU and find the smallest. If
- * the latency constraint has changed, the code should
- * recompute the state to enter for the next powerdomain
- * state.
- *
- * TI CDP code can call constraint_set here.
- */
-
- return 0;
-}
-
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
-{
- if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
- agent_id != OCP_TARGET_AGENT)) {
- WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
- return -EINVAL;
- }
-
- if (r == 0)
- pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
- dev_name(dev), agent_id);
- else
- pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n",
- dev_name(dev), agent_id, r);
-
- /*
- * This code should model the interconnect and compute the
- * required clock frequency, convert that to a VDD2 OPP ID, then
- * set the VDD2 OPP appropriately.
- *
- * TI CDP code can call constraint_set here on the VDD2 OPP.
- */
-
- return 0;
-}
-
-/*
- * DSP Bridge-specific constraints
- */
-
-
-/**
- * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been enabled.
- */
-void omap_pm_enable_off_mode(void)
-{
- off_mode_enabled = true;
-}
-
-/**
- * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been disabled.
- */
-void omap_pm_disable_off_mode(void)
-{
- off_mode_enabled = false;
-}
-
-/*
- * Device context loss tracking
- */
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- int count;
-
- if (WARN_ON(!dev))
- return -ENODEV;
-
- if (dev->pm_domain == &omap_device_pm_domain) {
- count = omap_device_get_context_loss_count(pdev);
- } else {
- WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
- dev_name(dev));
-
- count = dummy_context_loss_counter;
-
- if (off_mode_enabled) {
- count++;
- /*
- * Context loss count has to be a non-negative value.
- * Clear the sign bit to get a value range from 0 to
- * INT_MAX.
- */
- count &= INT_MAX;
- dummy_context_loss_counter = count;
- }
- }
-
- pr_debug("OMAP PM: context loss count for dev %s = %d\n",
- dev_name(dev), count);
-
- return count;
-}
-
-#else
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
- return dummy_context_loss_counter;
-}
-
-#endif
-
-/* Should be called before clk framework init */
-int __init omap_pm_if_early_init(void)
-{
- return 0;
-}
-
-/* Must be called after clock framework is initialized */
-int __init omap_pm_if_init(void)
-{
- return 0;
-}
diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h
deleted file mode 100644
index 5ba5df47f91b..000000000000
--- a/arch/arm/mach-omap2/omap-pm.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * omap-pm.h - OMAP power management interface
- *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
- * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
- * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
- * Richard Woodruff
- */
-
-#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
-#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
-
-#include <linux/device.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/pm_opp.h>
-
-/*
- * agent_id values for use with omap_pm_set_min_bus_tput():
- *
- * OCP_INITIATOR_AGENT is only valid for devices that can act as
- * initiators -- it represents the device's L3 interconnect
- * connection. OCP_TARGET_AGENT represents the device's L4
- * interconnect connection.
- */
-#define OCP_TARGET_AGENT 1
-#define OCP_INITIATOR_AGENT 2
-
-/**
- * omap_pm_if_early_init - OMAP PM init code called before clock fw init
- * @mpu_opp_table: array ptr to struct omap_opp for MPU
- * @dsp_opp_table: array ptr to struct omap_opp for DSP
- * @l3_opp_table : array ptr to struct omap_opp for CORE
- *
- * Initialize anything that must be configured before the clock
- * framework starts. The "_if_" is to avoid name collisions with the
- * PM idle-loop code.
- */
-int __init omap_pm_if_early_init(void);
-
-/**
- * omap_pm_if_init - OMAP PM init code called after clock fw init
- *
- * The main initialization code. OPP tables are passed in here. The
- * "_if_" is to avoid name collisions with the PM idle-loop code.
- */
-int __init omap_pm_if_init(void);
-
-/*
- * Device-driver-originated constraints (via board-*.c files, platform_data)
- */
-
-
-/**
- * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
- * @dev: struct device * requesting the constraint
- * @t: maximum MPU wakeup latency in microseconds
- *
- * Request that the maximum interrupt latency for the MPU to be no
- * greater than @t microseconds. "Interrupt latency" in this case is
- * defined as the elapsed time from the occurrence of a hardware or
- * timer interrupt to the time when the device driver's interrupt
- * service routine has been entered by the MPU.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the MPU powerdomain into, and
- * possibly the CORE powerdomain as well, since interrupt handling
- * code currently runs from SDRAM. Advanced PM or board*.c code may
- * also configure interrupt controller priorities, OCP bus priorities,
- * CPU speed(s), etc.
- *
- * This function will not affect device wakeup latency, e.g., time
- * elapsed from when a device driver enables a hardware device with
- * clk_enable(), to when the device is ready for register access or
- * other use. To control this device wakeup latency, use
- * omap_pm_set_max_dev_wakeup_lat()
- *
- * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
- * previous t value. To remove the latency target for the MPU, call
- * with t = -1.
- *
- * XXX This constraint will be deprecated soon in favor of the more
- * general omap_pm_set_max_dev_wakeup_lat()
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
-
-
-/**
- * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
- * @dev: struct device * requesting the constraint
- * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
- * @r: minimum throughput (in KiB/s)
- *
- * Request that the minimum data throughput on the OCP interconnect
- * attached to device @dev interconnect agent @tbus_id be no less
- * than @r KiB/s.
- *
- * It is expected that the OMAP PM or bus code will use this
- * information to set the interconnect clock to run at the lowest
- * possible speed that satisfies all current system users. The PM or
- * bus code will adjust the estimate based on its model of the bus, so
- * device driver authors should attempt to specify an accurate
- * quantity for their device use case, and let the PM or bus code
- * overestimate the numbers as necessary to handle request/response
- * latency, other competing users on the system, etc. On OMAP2/3, if
- * a driver requests a minimum L4 interconnect speed constraint, the
- * code will also need to add an minimum L3 interconnect speed
- * constraint,
- *
- * Multiple calls to omap_pm_set_min_bus_tput() will replace the
- * previous rate value for this device. To remove the interconnect
- * throughput restriction for this device, call with r = 0.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
-
-
-/*
- * CPUFreq-originated constraint
- *
- * In the future, this should be handled by custom OPP clocktype
- * functions.
- */
-
-
-/*
- * Device context loss tracking
- */
-
-/**
- * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx
- * @dev: struct device *
- *
- * This function returns the number of times that the device @dev has
- * lost its internal context. This generally occurs on a powerdomain
- * transition to OFF. Drivers use this as an optimization to avoid restoring
- * context if the device hasn't lost it. To use, drivers should initially
- * call this in their context save functions and store the result. Early in
- * the driver's context restore function, the driver should call this function
- * again, and compare the result to the stored counter. If they differ, the
- * driver must restore device context. If the number of context losses
- * exceeds the maximum positive integer, the function will wrap to 0 and
- * continue counting. Returns the number of context losses for this device,
- * or negative value upon error.
- */
-int omap_pm_get_dev_context_loss_count(struct device *dev);
-
-void omap_pm_enable_off_mode(void);
-void omap_pm_disable_off_mode(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 3b829a50d1db..ac219b9e6a4c 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -143,7 +143,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
struct resource res;
const char *oh_name;
int oh_cnt, i, ret = 0;
- bool device_active = false;
+ bool device_active = false, skip_pm_domain = false;
oh_cnt = of_property_count_strings(node, "ti,hwmods");
if (oh_cnt <= 0) {
@@ -151,8 +151,15 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
return -ENODEV;
}
+ /* SDMA still needs special handling for omap_device_build() */
+ ret = of_property_read_string_index(node, "ti,hwmods", 0, &oh_name);
+ if (!ret && (!strncmp("dma_system", oh_name, 10) ||
+ !strncmp("dma", oh_name, 3)))
+ skip_pm_domain = true;
+
/* Use ti-sysc driver instead of omap_device? */
- if (!omap_hwmod_parse_module_range(NULL, node, &res))
+ if (!skip_pm_domain &&
+ !omap_hwmod_parse_module_range(NULL, node, &res))
return -ENODEV;
hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
@@ -191,11 +198,12 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
r->name = dev_name(&pdev->dev);
}
- dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
-
- if (device_active) {
- omap_device_enable(pdev);
- pm_runtime_set_active(&pdev->dev);
+ if (!skip_pm_domain) {
+ dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
+ if (device_active) {
+ omap_device_enable(pdev);
+ pm_runtime_set_active(&pdev->dev);
+ }
}
odbfd_exit1:
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e7d23e200ecc..2ceffd85dd3d 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -481,7 +481,7 @@ static int _wait_softreset_complete(struct omap_hwmod *oh)
sysc = oh->class->sysc;
- if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+ if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS && sysc->syss_offs > 0)
omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
& SYSS_RESETDONE_MASK),
MAX_MODULE_SOFTRESET_WAIT, c);
@@ -3171,19 +3171,19 @@ static int omap_hwmod_init_regbits(struct device *dev,
*/
int omap_hwmod_init_reg_offs(struct device *dev,
const struct ti_sysc_module_data *data,
- u32 *rev_offs, u32 *sysc_offs, u32 *syss_offs)
+ s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs)
{
- *rev_offs = 0;
+ *rev_offs = -ENODEV;
*sysc_offs = 0;
*syss_offs = 0;
- if (data->offsets[SYSC_REVISION] > 0)
+ if (data->offsets[SYSC_REVISION] >= 0)
*rev_offs = data->offsets[SYSC_REVISION];
- if (data->offsets[SYSC_SYSCONFIG] > 0)
+ if (data->offsets[SYSC_SYSCONFIG] >= 0)
*sysc_offs = data->offsets[SYSC_SYSCONFIG];
- if (data->offsets[SYSC_SYSSTATUS] > 0)
+ if (data->offsets[SYSC_SYSSTATUS] >= 0)
*syss_offs = data->offsets[SYSC_SYSSTATUS];
return 0;
@@ -3312,8 +3312,8 @@ static int omap_hwmod_check_module(struct device *dev,
struct omap_hwmod *oh,
const struct ti_sysc_module_data *data,
struct sysc_regbits *sysc_fields,
- u32 rev_offs, u32 sysc_offs,
- u32 syss_offs, u32 sysc_flags,
+ s32 rev_offs, s32 sysc_offs,
+ s32 syss_offs, u32 sysc_flags,
u32 idlemodes)
{
if (!oh->class->sysc)
@@ -3365,7 +3365,7 @@ static int omap_hwmod_check_module(struct device *dev,
int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
const struct ti_sysc_module_data *data,
struct sysc_regbits *sysc_fields,
- u32 rev_offs, u32 sysc_offs, u32 syss_offs,
+ s32 rev_offs, s32 sysc_offs, s32 syss_offs,
u32 sysc_flags, u32 idlemodes)
{
struct omap_hwmod_class_sysconfig *sysc;
@@ -3425,7 +3425,8 @@ int omap_hwmod_init_module(struct device *dev,
{
struct omap_hwmod *oh;
struct sysc_regbits *sysc_fields;
- u32 rev_offs, sysc_offs, syss_offs, sysc_flags, idlemodes;
+ s32 rev_offs, sysc_offs, syss_offs;
+ u32 sysc_flags, idlemodes;
int error;
if (!dev || !data)
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index c7122abbf977..b70cdc21f8a2 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -317,9 +317,9 @@ struct omap_hwmod_ocp_if {
* then this field has to be populated with the correct offset structure.
*/
struct omap_hwmod_class_sysconfig {
- u32 rev_offs;
- u32 sysc_offs;
- u32 syss_offs;
+ s32 rev_offs;
+ s32 sysc_offs;
+ s32 syss_offs;
u16 sysc_flags;
struct sysc_regbits *sysc_fields;
u8 srst_udelay;
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
index 5efe91c6e95b..9ded7bf972e7 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
@@ -629,6 +629,7 @@ struct omap_hwmod am33xx_gpmc_hwmod = {
/* 'i2c' class */
static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 23336b6c7125..d93f9ea4119e 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -885,6 +885,7 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -990,6 +991,7 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
/* 'mcbsp sidetone' class */
static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_AUTOIDLE,
.sysc_fields = &omap_hwmod_sysc_type1,
@@ -1018,6 +1020,7 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
/* SR common */
static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x24,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
.sysc_fields = &omap34xx_sr_sysc_fields,
@@ -1030,6 +1033,7 @@ static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
};
static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x38,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
index 5f73b730d4fc..aa271ac5ebac 100644
--- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
@@ -378,6 +378,7 @@ static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = {
};
static struct omap_hwmod_class_sysconfig am43xx_qspi_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e4f8ae9cd637..234ee0eec815 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1360,6 +1360,7 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -1634,6 +1635,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0004,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1667,6 +1669,7 @@ static struct omap_hwmod omap44xx_mcasp_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap44xx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -2353,6 +2356,7 @@ static struct omap_hwmod omap44xx_slimbus2_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0038,
.sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index c72cd84b07ec..887a30fa775b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -804,6 +804,7 @@ static struct omap_hwmod omap54xx_gpio8_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -974,6 +975,7 @@ static struct omap_hwmod omap54xx_mailbox_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -1997,6 +1999,7 @@ static struct omap_hwmod omap54xx_ocp2scp3_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x0000,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 62352d1e6361..a27c2fed298c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -1070,6 +1070,7 @@ static struct omap_hwmod dra7xx_hdq1w_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -1440,6 +1441,7 @@ static struct omap_hwmod dra7xx_mcspi4_hwmod = {
*
*/
static struct omap_hwmod_class_sysconfig dra7xx_mcasp_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0004,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
@@ -1898,6 +1900,7 @@ static struct omap_hwmod dra7xx_pciess2_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_qspi_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1930,6 +1933,7 @@ static struct omap_hwmod dra7xx_qspi_hwmod = {
*
*/
static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = {
+ .rev_offs = 0x0074,
.sysc_offs = 0x0078,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1965,6 +1969,7 @@ static struct omap_hwmod dra7xx_rtcss_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x0000,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -2003,6 +2008,7 @@ static struct omap_hwmod dra7xx_sata_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig dra7xx_smartreflex_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0038,
.sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
index 686655f884c1..8e44e2728620 100644
--- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
@@ -954,6 +954,7 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = {
};
static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x1100,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = SIDLE_FORCE,
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 6459816c2879..7f02743edbe4 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -26,14 +26,12 @@
#include <linux/platform_data/iommu-omap.h>
#include <linux/platform_data/ti-sysc.h>
#include <linux/platform_data/wkup_m3.h>
-#include <linux/platform_data/media/ir-rx51.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "common.h"
#include "common-board-devices.h"
#include "control.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "omap-secure.h"
#include "soc.h"
#include "hsmmc.h"
@@ -514,18 +512,6 @@ void omap_auxdata_legacy_init(struct device *dev)
dev->platform_data = &twl_gpio_auxdata;
}
-static struct ir_rx51_platform_data __maybe_unused rx51_ir_data = {
- .set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-};
-
-static struct platform_device __maybe_unused rx51_ir_device = {
- .name = "ir_rx51",
- .id = -1,
- .dev = {
- .platform_data = &rx51_ir_data,
- },
-};
-
#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
static struct omap_mcbsp_platform_data mcbsp_pdata;
static void __init omap3_mcbsp_init(void)
@@ -569,7 +555,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
"480c9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
- OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_ir_data),
/* Only on am3517 */
OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 5c46ea6756d7..acb698d5780f 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -31,7 +31,6 @@
#include "clock.h"
#include "powerdomain.h"
#include "clockdomain.h"
-#include "omap-pm.h"
#include "soc.h"
#include "cm2xxx_3xxx.h"
@@ -240,10 +239,6 @@ static int option_set(void *data, u64 val)
*option = val;
if (option == &enable_off_mode) {
- if (val)
- omap_pm_enable_off_mode();
- else
- omap_pm_disable_off_mode();
if (cpu_is_omap34xx())
omap3_pm_off_mode_enable(val);
}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 6f68576e5695..ca03af8fe43f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -16,11 +16,11 @@
#include <linux/pm_opp.h>
#include <linux/export.h>
#include <linux/suspend.h>
+#include <linux/clk.h>
#include <linux/cpu.h>
#include <asm/system_misc.h>
-#include "omap-pm.h"
#include "omap_device.h"
#include "common.h"
@@ -230,16 +230,20 @@ static void __init omap4_init_voltages(void)
omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
}
-static int __init omap2_common_pm_init(void)
+int __maybe_unused omap_pm_nop_init(void)
{
- omap_pm_if_init();
-
return 0;
}
-omap_postcore_initcall(omap2_common_pm_init);
+
+int (*omap_pm_soc_init)(void);
int __init omap2_common_pm_late_init(void)
{
+ int error;
+
+ if (!omap_pm_soc_init)
+ return 0;
+
/* Init the voltage layer */
omap3_twl_init();
omap4_twl_init();
@@ -252,5 +256,12 @@ int __init omap2_common_pm_late_init(void)
/* Smartreflex device init */
omap_devinit_smartreflex();
+ error = omap_pm_soc_init();
+ if (error)
+ pr_warn("%s: pm soc init failed: %i\n", __func__, error);
+
+ omap2_clk_enable_autoidle_all();
+
return 0;
}
+omap_late_initcall(omap2_common_pm_late_init);
diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c
index 93c0b5ba9f09..9b3755a2e2ec 100644
--- a/arch/arm/mach-omap2/pm33xx-core.c
+++ b/arch/arm/mach-omap2/pm33xx-core.c
@@ -173,7 +173,7 @@ static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
return NULL;
}
-void __init amx3_common_pm_init(void)
+int __init amx3_common_pm_init(void)
{
struct am33xx_pm_platform_data *pdata;
struct platform_device_info devinfo;
@@ -186,4 +186,6 @@ void __init amx3_common_pm_init(void)
devinfo.size_data = sizeof(*pdata);
devinfo.id = -1;
platform_device_register_full(&devinfo);
+
+ return 0;
}
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index b3870220612e..78e1ace7d17d 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -131,6 +131,19 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
return 0;
}
+ /*
+ * Bootloader or kexec boot may have LOGICRETSTATE cleared
+ * for some domains. This is the case when kexec booting from
+ * Android kernels that support off mode for example.
+ * Make sure it's set at least for core and per, otherwise
+ * we currently will see lost GPIO interrupts for wlcore and
+ * smsc911x at least if per hits retention during idle.
+ */
+ if (!strncmp(pwrdm->name, "core", 4) ||
+ !strncmp(pwrdm->name, "l4per", 5) ||
+ !strncmp(pwrdm->name, "wkup", 4))
+ pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_RET);
+
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1e6a967cd2d5..1a0f69c0a376 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -14,6 +14,7 @@
*/
#undef DEBUG
+#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/list.h>
@@ -39,6 +40,9 @@
#define PWRDM_TRACE_STATES_FLAG (1<<31)
+void pwrdms_save_context(void);
+void pwrdms_restore_context(void);
+
enum {
PWRDM_STATE_NOW = 0,
PWRDM_STATE_PREV,
@@ -333,6 +337,22 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
return 0;
}
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ pwrdms_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ pwrdms_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
/**
* pwrdm_complete_init - set up the powerdomain layer
*
@@ -347,6 +367,7 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
int pwrdm_complete_init(void)
{
struct powerdomain *temp_p;
+ static struct notifier_block nb;
if (list_empty(&pwrdm_list))
return -EACCES;
@@ -354,6 +375,12 @@ int pwrdm_complete_init(void)
list_for_each_entry(temp_p, &pwrdm_list, node)
pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+ /* Only AM43XX can lose pwrdm context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
@@ -1199,3 +1226,63 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
return 0;
}
+
+/**
+ * pwrdm_save_context - save powerdomain registers
+ *
+ * Register state is going to be lost due to a suspend or hibernate
+ * event. Save the powerdomain registers.
+ */
+static int pwrdm_save_context(struct powerdomain *pwrdm, void *unused)
+{
+ if (arch_pwrdm && arch_pwrdm->pwrdm_save_context)
+ arch_pwrdm->pwrdm_save_context(pwrdm);
+ return 0;
+}
+
+/**
+ * pwrdm_save_context - restore powerdomain registers
+ *
+ * Restore powerdomain control registers after a suspend or resume
+ * event.
+ */
+static int pwrdm_restore_context(struct powerdomain *pwrdm, void *unused)
+{
+ if (arch_pwrdm && arch_pwrdm->pwrdm_restore_context)
+ arch_pwrdm->pwrdm_restore_context(pwrdm);
+ return 0;
+}
+
+static int pwrdm_lost_power(struct powerdomain *pwrdm, void *unused)
+{
+ int state;
+
+ /*
+ * Power has been lost across all powerdomains, increment the
+ * counter.
+ */
+
+ state = pwrdm_read_pwrst(pwrdm);
+ if (state != PWRDM_POWER_OFF) {
+ pwrdm->state_counter[state]++;
+ pwrdm->state_counter[PWRDM_POWER_OFF]++;
+ }
+ pwrdm->state = state;
+
+ return 0;
+}
+
+void pwrdms_save_context(void)
+{
+ pwrdm_for_each(pwrdm_save_context, NULL);
+}
+
+void pwrdms_restore_context(void)
+{
+ pwrdm_for_each(pwrdm_restore_context, NULL);
+}
+
+void pwrdms_lost_power(void)
+{
+ pwrdm_for_each(pwrdm_lost_power, NULL);
+}
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 28a796ce07d7..9a907fb14044 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -144,6 +144,7 @@ struct powerdomain {
s64 timer;
s64 state_timer[PWRDM_MAX_PWRSTS];
#endif
+ u32 context;
};
/**
@@ -198,6 +199,8 @@ struct pwrdm_ops {
int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
int (*pwrdm_wait_transition)(struct powerdomain *pwrdm);
int (*pwrdm_has_voltdm)(void);
+ void (*pwrdm_save_context)(struct powerdomain *pwrdm);
+ void (*pwrdm_restore_context)(struct powerdomain *pwrdm);
};
int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
@@ -273,4 +276,8 @@ extern struct powerdomain gfx_omap2_pwrdm;
extern void pwrdm_lock(struct powerdomain *pwrdm);
extern void pwrdm_unlock(struct powerdomain *pwrdm);
+extern void pwrdms_save_context(void);
+extern void pwrdms_restore_context(void);
+
+extern void pwrdms_lost_power(void);
#endif
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index ebaf80d72a10..d5141669c28d 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -342,6 +342,35 @@ static void am33xx_prm_global_warm_sw_reset(void)
AM33XX_PRM_RSTCTRL_OFFSET);
}
+static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
+{
+ pwrdm->context = am33xx_prm_read_reg(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 &= ~AM33XX_LOWPOWERSTATECHANGE_MASK;
+}
+
+static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
+{
+ int st, ctrl;
+
+ st = am33xx_prm_read_reg(pwrdm->prcm_offs,
+ pwrdm->pwrstst_offs);
+
+ am33xx_prm_write_reg(pwrdm->context, 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)
+ am33xx_pwrdm_wait_transition(pwrdm);
+}
+
struct pwrdm_ops am33xx_pwrdm_operations = {
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
@@ -357,6 +386,8 @@ struct pwrdm_ops am33xx_pwrdm_operations = {
.pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
.pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
.pwrdm_has_voltdm = am33xx_check_vcvp,
+ .pwrdm_save_context = am33xx_pwrdm_save_context,
+ .pwrdm_restore_context = am33xx_pwrdm_restore_context,
};
static struct prm_ll_data am33xx_prm_ll_data = {
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);
}
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 4fb4dc24e5e9..98ed5ac073bc 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -50,7 +50,6 @@
#include "omap_device.h"
#include <plat/counter-32k.h>
#include <clocksource/timer-ti-dm.h>
-#include "omap-pm.h"
#include "soc.h"
#include "common.h"
@@ -71,6 +70,9 @@ static struct clock_event_device clockevent_gpt;
/* Clockevent hwmod for am335x and am437x suspend */
static struct omap_hwmod *clockevent_gpt_hwmod;
+/* Clockesource hwmod for am437x suspend */
+static struct omap_hwmod *clocksource_gpt_hwmod;
+
#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
static unsigned long arch_timer_freq;
@@ -168,6 +170,43 @@ static const struct of_device_id omap_timer_match[] __initconst = {
{ }
};
+static int omap_timer_add_disabled_property(struct device_node *np)
+{
+ struct property *prop;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+
+ prop->name = "status";
+ prop->value = "disabled";
+ prop->length = strlen(prop->value);
+
+ return of_add_property(np, prop);
+}
+
+static int omap_timer_update_dt(struct device_node *np)
+{
+ int error = 0;
+
+ if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
+ error = omap_timer_add_disabled_property(np);
+ if (error)
+ return error;
+ }
+
+ /* No parent interconnect target module configured? */
+ if (of_get_property(np, "ti,hwmods", NULL))
+ return error;
+
+ /* Tag parent interconnect target module disabled */
+ error = omap_timer_add_disabled_property(np->parent);
+ if (error)
+ return error;
+
+ return 0;
+}
+
/**
* omap_get_timer_dt - get a timer using device-tree
* @match - device-tree match structure for matching a device type
@@ -183,6 +222,7 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *
const char *property)
{
struct device_node *np;
+ int error;
for_each_matching_node(np, match) {
if (!of_device_is_available(np))
@@ -197,17 +237,9 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *
of_get_property(np, "ti,timer-secure", NULL)))
continue;
- if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
- struct property *prop;
+ error = omap_timer_update_dt(np);
+ WARN(error, "%s: Could not update dt: %i\n", __func__, error);
- prop = kzalloc(sizeof(*prop), GFP_KERNEL);
- if (!prop)
- return NULL;
- prop->name = "status";
- prop->value = "disabled";
- prop->length = strlen(prop->value);
- of_add_property(np, prop);
- }
return np;
}
@@ -266,8 +298,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
return -ENODEV;
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
- if (!oh_name)
- return -ENODEV;
+ if (!oh_name) {
+ of_property_read_string_index(np->parent, "ti,hwmods", 0,
+ &oh_name);
+ if (!oh_name)
+ return -ENODEV;
+ }
timer->irq = irq_of_parse_and_map(np, 0);
if (!timer->irq)
@@ -419,9 +455,12 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
if (!np)
return -ENODEV;
- of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
- if (!oh_name)
- return -ENODEV;
+ of_property_read_string_index(np->parent, "ti,hwmods", 0, &oh_name);
+ if (!oh_name) {
+ of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
+ if (!oh_name)
+ return -ENODEV;
+ }
/*
* First check hwmod data is available for sync32k counter
@@ -442,6 +481,26 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
return ret;
}
+static unsigned int omap2_gptimer_clksrc_load;
+
+static void omap2_gptimer_clksrc_suspend(struct clocksource *unused)
+{
+ omap2_gptimer_clksrc_load =
+ __omap_dm_timer_read_counter(&clksrc, OMAP_TIMER_NONPOSTED);
+
+ omap_hwmod_idle(clocksource_gpt_hwmod);
+}
+
+static void omap2_gptimer_clksrc_resume(struct clocksource *unused)
+{
+ omap_hwmod_enable(clocksource_gpt_hwmod);
+
+ __omap_dm_timer_load_start(&clksrc,
+ OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
+ omap2_gptimer_clksrc_load,
+ OMAP_TIMER_NONPOSTED);
+}
+
static void __init omap2_gptimer_clocksource_init(int gptimer_id,
const char *fck_source,
const char *property)
@@ -454,6 +513,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
res = omap_dm_timer_init_one(&clksrc, fck_source, property,
&clocksource_gpt.name,
OMAP_TIMER_NONPOSTED);
+
+ if (soc_is_am43xx()) {
+ clocksource_gpt.suspend = omap2_gptimer_clksrc_suspend;
+ clocksource_gpt.resume = omap2_gptimer_clksrc_resume;
+
+ clocksource_gpt_hwmod =
+ omap_hwmod_lookup(clocksource_gpt.name);
+ }
+
BUG_ON(res);
__omap_dm_timer_load_start(&clksrc,