summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/prm2xxx.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-10-21 09:01:13 +0200
committerPaul Walmsley <paul@pwsan.com>2012-10-21 09:01:13 +0200
commit2bb2a5d30abb0dc99d074877bfad2056142c730b (patch)
tree6da1f32009cec6777baa0a474f7c2579cc57a6bc /arch/arm/mach-omap2/prm2xxx.c
parentARM: OMAP1: create read_reset_sources() function (for initial use by watchdog) (diff)
downloadlinux-2bb2a5d30abb0dc99d074877bfad2056142c730b.tar.xz
linux-2bb2a5d30abb0dc99d074877bfad2056142c730b.zip
ARM: OMAP2+: PRM: create PRM reset source API for the watchdog timer driver
The OMAP watchdog timer driver needs to determine what caused the SoC to reset for its GETBOOTSTATUS ioctl. So, define a set of standard reset sources across OMAP SoCs. For OMAP2xxx, 3xxx, and 4xxx SoCs, define mappings from the SoC-specific reset source register bits to the standardized reset source IDs. Create SoC-specific PRM functions that read the appropriate per-SoC register and use the mapping to return the standardized reset bits. Register the SoC-specific PRM functions with the common PRM code via prm_register(). Create a function in the common PRM code, prm_read_reset_sources(), that calls the SoC-specific function, registered during boot. This patch does not yet handle some SoCs, such as AM33xx. Those SoCs were not handled by the code this will replace. Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm/mach-omap2/prm2xxx.c')
-rw-r--r--arch/arm/mach-omap2/prm2xxx.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/prm2xxx.c b/arch/arm/mach-omap2/prm2xxx.c
index 9cdb4e5e3d80..e2860f9c111d 100644
--- a/arch/arm/mach-omap2/prm2xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx.c
@@ -29,6 +29,46 @@
#include "cm2xxx_3xxx.h"
#include "prm-regbits-24xx.h"
+/*
+ * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
+ * hardware register (which are specific to the OMAP2xxx SoCs) to
+ * reset source ID bit shifts (which is an OMAP SoC-independent
+ * enumeration)
+ */
+static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
+ { OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
+ { OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
+ { OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
+ { OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
+ { OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
+ { OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
+ { -1, -1 },
+};
+
+/**
+ * omap2xxx_prm_read_reset_sources - return the last SoC reset source
+ *
+ * Return a u32 representing the last reset sources of the SoC. The
+ * returned reset source bits are standardized across OMAP SoCs.
+ */
+static u32 omap2xxx_prm_read_reset_sources(void)
+{
+ struct prm_reset_src_map *p;
+ u32 r = 0;
+ u32 v;
+
+ v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
+
+ p = omap2xxx_prm_reset_src_map;
+ while (p->reg_shift >= 0 && p->std_shift >= 0) {
+ if (v & (1 << p->reg_shift))
+ r |= 1 << p->std_shift;
+ p++;
+ }
+
+ return r;
+}
+
int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
{
omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
@@ -56,3 +96,31 @@ struct pwrdm_ops omap2_pwrdm_operations = {
.pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
.pwrdm_wait_transition = omap2_pwrdm_wait_transition,
};
+
+/*
+ *
+ */
+
+static struct prm_ll_data omap2xxx_prm_ll_data = {
+ .read_reset_sources = &omap2xxx_prm_read_reset_sources,
+};
+
+static int __init omap2xxx_prm_init(void)
+{
+ if (!cpu_is_omap24xx())
+ return 0;
+
+ return prm_register(&omap2xxx_prm_ll_data);
+}
+subsys_initcall(omap2xxx_prm_init);
+
+static void __exit omap2xxx_prm_exit(void)
+{
+ if (!cpu_is_omap24xx())
+ return;
+
+ /* Should never happen */
+ WARN(prm_unregister(&omap2xxx_prm_ll_data),
+ "%s: prm_ll_data function pointer mismatch\n", __func__);
+}
+__exitcall(omap2xxx_prm_exit);