aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2012-10-21 03:01:13 -0400
committerPaul Walmsley <paul@pwsan.com>2012-10-21 03:01:13 -0400
commit2bb2a5d30abb0dc99d074877bfad2056142c730b (patch)
tree6da1f32009cec6777baa0a474f7c2579cc57a6bc /arch
parentb5c5353d417580f7a6ac21a0954f1c500a5cc4f5 (diff)
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')
-rw-r--r--arch/arm/mach-omap2/prm-regbits-24xx.h4
-rw-r--r--arch/arm/mach-omap2/prm-regbits-34xx.h10
-rw-r--r--arch/arm/mach-omap2/prm.h44
-rw-r--r--arch/arm/mach-omap2/prm2xxx.c68
-rw-r--r--arch/arm/mach-omap2/prm2xxx.h4
-rw-r--r--arch/arm/mach-omap2/prm2xxx_3xxx.h2
-rw-r--r--arch/arm/mach-omap2/prm3xxx.c65
-rw-r--r--arch/arm/mach-omap2/prm3xxx.h2
-rw-r--r--arch/arm/mach-omap2/prm44xx.c83
-rw-r--r--arch/arm/mach-omap2/prm44xx.h2
-rw-r--r--arch/arm/mach-omap2/prm_common.c26
11 files changed, 306 insertions, 4 deletions
diff --git a/arch/arm/mach-omap2/prm-regbits-24xx.h b/arch/arm/mach-omap2/prm-regbits-24xx.h
index bd70a5a04291..638da6dd41c3 100644
--- a/arch/arm/mach-omap2/prm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-24xx.h
@@ -209,9 +209,13 @@
209 209
210/* RM_RSTST_WKUP specific bits */ 210/* RM_RSTST_WKUP specific bits */
211/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */ 211/* 2430 calls EXTWMPU_RST "EXTWARM_RST" and GLOBALWMPU_RST "GLOBALWARM_RST" */
212#define OMAP24XX_EXTWMPU_RST_SHIFT 6
212#define OMAP24XX_EXTWMPU_RST_MASK (1 << 6) 213#define OMAP24XX_EXTWMPU_RST_MASK (1 << 6)
214#define OMAP24XX_SECU_WD_RST_SHIFT 5
213#define OMAP24XX_SECU_WD_RST_MASK (1 << 5) 215#define OMAP24XX_SECU_WD_RST_MASK (1 << 5)
216#define OMAP24XX_MPU_WD_RST_SHIFT 4
214#define OMAP24XX_MPU_WD_RST_MASK (1 << 4) 217#define OMAP24XX_MPU_WD_RST_MASK (1 << 4)
218#define OMAP24XX_SECU_VIOL_RST_SHIFT 3
215#define OMAP24XX_SECU_VIOL_RST_MASK (1 << 3) 219#define OMAP24XX_SECU_VIOL_RST_MASK (1 << 3)
216 220
217/* PM_WKEN_WKUP specific bits */ 221/* PM_WKEN_WKUP specific bits */
diff --git a/arch/arm/mach-omap2/prm-regbits-34xx.h b/arch/arm/mach-omap2/prm-regbits-34xx.h
index 073d4db8aa5c..838b594d4e13 100644
--- a/arch/arm/mach-omap2/prm-regbits-34xx.h
+++ b/arch/arm/mach-omap2/prm-regbits-34xx.h
@@ -509,15 +509,25 @@
509#define OMAP3430_RSTTIME1_MASK (0xff << 0) 509#define OMAP3430_RSTTIME1_MASK (0xff << 0)
510 510
511/* PRM_RSTST */ 511/* PRM_RSTST */
512#define OMAP3430_ICECRUSHER_RST_SHIFT 10
512#define OMAP3430_ICECRUSHER_RST_MASK (1 << 10) 513#define OMAP3430_ICECRUSHER_RST_MASK (1 << 10)
514#define OMAP3430_ICEPICK_RST_SHIFT 9
513#define OMAP3430_ICEPICK_RST_MASK (1 << 9) 515#define OMAP3430_ICEPICK_RST_MASK (1 << 9)
516#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT 8
514#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK (1 << 8) 517#define OMAP3430_VDD2_VOLTAGE_MANAGER_RST_MASK (1 << 8)
518#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT 7
515#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK (1 << 7) 519#define OMAP3430_VDD1_VOLTAGE_MANAGER_RST_MASK (1 << 7)
520#define OMAP3430_EXTERNAL_WARM_RST_SHIFT 6
516#define OMAP3430_EXTERNAL_WARM_RST_MASK (1 << 6) 521#define OMAP3430_EXTERNAL_WARM_RST_MASK (1 << 6)
522#define OMAP3430_SECURE_WD_RST_SHIFT 5
517#define OMAP3430_SECURE_WD_RST_MASK (1 << 5) 523#define OMAP3430_SECURE_WD_RST_MASK (1 << 5)
524#define OMAP3430_MPU_WD_RST_SHIFT 4
518#define OMAP3430_MPU_WD_RST_MASK (1 << 4) 525#define OMAP3430_MPU_WD_RST_MASK (1 << 4)
526#define OMAP3430_SECURITY_VIOL_RST_SHIFT 3
519#define OMAP3430_SECURITY_VIOL_RST_MASK (1 << 3) 527#define OMAP3430_SECURITY_VIOL_RST_MASK (1 << 3)
528#define OMAP3430_GLOBAL_SW_RST_SHIFT 1
520#define OMAP3430_GLOBAL_SW_RST_MASK (1 << 1) 529#define OMAP3430_GLOBAL_SW_RST_MASK (1 << 1)
530#define OMAP3430_GLOBAL_COLD_RST_SHIFT 0
521#define OMAP3430_GLOBAL_COLD_RST_MASK (1 << 0) 531#define OMAP3430_GLOBAL_COLD_RST_MASK (1 << 0)
522 532
523/* PRM_VOLTCTRL */ 533/* PRM_VOLTCTRL */
diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h
index 3e51c1d15757..c30ab5de8d1d 100644
--- a/arch/arm/mach-omap2/prm.h
+++ b/arch/arm/mach-omap2/prm.h
@@ -52,16 +52,58 @@
52#define OMAP_POWERSTATE_SHIFT 0 52#define OMAP_POWERSTATE_SHIFT 0
53#define OMAP_POWERSTATE_MASK (0x3 << 0) 53#define OMAP_POWERSTATE_MASK (0x3 << 0)
54 54
55/*
56 * Standardized OMAP reset source bits
57 *
58 * To the extent these happen to match the hardware register bit
59 * shifts, it's purely coincidental. Used by omap-wdt.c.
60 * OMAP_UNKNOWN_RST_SRC_ID_SHIFT is a special value, used whenever
61 * there are any bits remaining in the global PRM_RSTST register that
62 * haven't been identified, or when the PRM code for the current SoC
63 * doesn't know how to interpret the register.
64 */
65#define OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT 0
66#define OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT 1
67#define OMAP_SECU_VIOL_RST_SRC_ID_SHIFT 2
68#define OMAP_MPU_WD_RST_SRC_ID_SHIFT 3
69#define OMAP_SECU_WD_RST_SRC_ID_SHIFT 4
70#define OMAP_EXTWARM_RST_SRC_ID_SHIFT 5
71#define OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT 6
72#define OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT 7
73#define OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT 8
74#define OMAP_ICEPICK_RST_SRC_ID_SHIFT 9
75#define OMAP_ICECRUSHER_RST_SRC_ID_SHIFT 10
76#define OMAP_C2C_RST_SRC_ID_SHIFT 11
77#define OMAP_UNKNOWN_RST_SRC_ID_SHIFT 12
78
55#ifndef __ASSEMBLER__ 79#ifndef __ASSEMBLER__
56 80
57/** 81/**
82 * struct prm_reset_src_map - map register bitshifts to standard bitshifts
83 * @reg_shift: bitshift in the PRM reset source register
84 * @std_shift: bitshift equivalent in the standard reset source list
85 *
86 * The fields are signed because -1 is used as a terminator.
87 */
88struct prm_reset_src_map {
89 s8 reg_shift;
90 s8 std_shift;
91};
92
93/**
58 * struct prm_ll_data - fn ptrs to per-SoC PRM function implementations 94 * struct prm_ll_data - fn ptrs to per-SoC PRM function implementations
95 * @read_reset_sources: ptr to the Soc PRM-specific get_reset_source impl
59 */ 96 */
60struct prm_ll_data {}; 97struct prm_ll_data {
98 u32 (*read_reset_sources)(void);
99};
61 100
62extern int prm_register(struct prm_ll_data *pld); 101extern int prm_register(struct prm_ll_data *pld);
63extern int prm_unregister(struct prm_ll_data *pld); 102extern int prm_unregister(struct prm_ll_data *pld);
64 103
104extern u32 prm_read_reset_sources(void);
105
65#endif 106#endif
66 107
108
67#endif 109#endif
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 @@
29#include "cm2xxx_3xxx.h" 29#include "cm2xxx_3xxx.h"
30#include "prm-regbits-24xx.h" 30#include "prm-regbits-24xx.h"
31 31
32/*
33 * omap2xxx_prm_reset_src_map - map from bits in the PRM_RSTST_WKUP
34 * hardware register (which are specific to the OMAP2xxx SoCs) to
35 * reset source ID bit shifts (which is an OMAP SoC-independent
36 * enumeration)
37 */
38static struct prm_reset_src_map omap2xxx_prm_reset_src_map[] = {
39 { OMAP_GLOBALCOLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
40 { OMAP_GLOBALWARM_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
41 { OMAP24XX_SECU_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
42 { OMAP24XX_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
43 { OMAP24XX_SECU_WD_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
44 { OMAP24XX_EXTWMPU_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
45 { -1, -1 },
46};
47
48/**
49 * omap2xxx_prm_read_reset_sources - return the last SoC reset source
50 *
51 * Return a u32 representing the last reset sources of the SoC. The
52 * returned reset source bits are standardized across OMAP SoCs.
53 */
54static u32 omap2xxx_prm_read_reset_sources(void)
55{
56 struct prm_reset_src_map *p;
57 u32 r = 0;
58 u32 v;
59
60 v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
61
62 p = omap2xxx_prm_reset_src_map;
63 while (p->reg_shift >= 0 && p->std_shift >= 0) {
64 if (v & (1 << p->reg_shift))
65 r |= 1 << p->std_shift;
66 p++;
67 }
68
69 return r;
70}
71
32int omap2xxx_clkdm_sleep(struct clockdomain *clkdm) 72int omap2xxx_clkdm_sleep(struct clockdomain *clkdm)
33{ 73{
34 omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK, 74 omap2_prm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
@@ -56,3 +96,31 @@ struct pwrdm_ops omap2_pwrdm_operations = {
56 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst, 96 .pwrdm_read_mem_retst = omap2_pwrdm_read_mem_retst,
57 .pwrdm_wait_transition = omap2_pwrdm_wait_transition, 97 .pwrdm_wait_transition = omap2_pwrdm_wait_transition,
58}; 98};
99
100/*
101 *
102 */
103
104static struct prm_ll_data omap2xxx_prm_ll_data = {
105 .read_reset_sources = &omap2xxx_prm_read_reset_sources,
106};
107
108static int __init omap2xxx_prm_init(void)
109{
110 if (!cpu_is_omap24xx())
111 return 0;
112
113 return prm_register(&omap2xxx_prm_ll_data);
114}
115subsys_initcall(omap2xxx_prm_init);
116
117static void __exit omap2xxx_prm_exit(void)
118{
119 if (!cpu_is_omap24xx())
120 return;
121
122 /* Should never happen */
123 WARN(prm_unregister(&omap2xxx_prm_ll_data),
124 "%s: prm_ll_data function pointer mismatch\n", __func__);
125}
126__exitcall(omap2xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm2xxx.h b/arch/arm/mach-omap2/prm2xxx.h
index 6d76716a1ea5..1d97112524f1 100644
--- a/arch/arm/mach-omap2/prm2xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx.h
@@ -123,6 +123,10 @@
123/* Function prototypes */ 123/* Function prototypes */
124extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm); 124extern int omap2xxx_clkdm_sleep(struct clockdomain *clkdm);
125extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm); 125extern int omap2xxx_clkdm_wakeup(struct clockdomain *clkdm);
126
127extern int __init prm2xxx_init(void);
128extern int __exit prm2xxx_exit(void);
129
126#endif 130#endif
127 131
128#endif 132#endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index 22a405a1543b..3330b1bf789d 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -211,7 +211,9 @@ extern int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
211 * 211 *
212 * 3430: RM_RSTST_CORE, RM_RSTST_EMU 212 * 3430: RM_RSTST_CORE, RM_RSTST_EMU
213 */ 213 */
214#define OMAP_GLOBALWARM_RST_SHIFT 1
214#define OMAP_GLOBALWARM_RST_MASK (1 << 1) 215#define OMAP_GLOBALWARM_RST_MASK (1 << 1)
216#define OMAP_GLOBALCOLD_RST_SHIFT 0
215#define OMAP_GLOBALCOLD_RST_MASK (1 << 0) 217#define OMAP_GLOBALCOLD_RST_MASK (1 << 0)
216 218
217/* 219/*
diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c
index e276ff270ac5..1fea656b2ca8 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -47,6 +47,27 @@ static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
47 .restore_irqen = &omap3xxx_prm_restore_irqen, 47 .restore_irqen = &omap3xxx_prm_restore_irqen,
48}; 48};
49 49
50/*
51 * omap3_prm_reset_src_map - map from bits in the PRM_RSTST hardware
52 * register (which are specific to OMAP3xxx SoCs) to reset source ID
53 * bit shifts (which is an OMAP SoC-independent enumeration)
54 */
55static struct prm_reset_src_map omap3xxx_prm_reset_src_map[] = {
56 { OMAP3430_GLOBAL_COLD_RST_SHIFT, OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
57 { OMAP3430_GLOBAL_SW_RST_SHIFT, OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
58 { OMAP3430_SECURITY_VIOL_RST_SHIFT, OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
59 { OMAP3430_MPU_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
60 { OMAP3430_SECURE_WD_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
61 { OMAP3430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
62 { OMAP3430_VDD1_VOLTAGE_MANAGER_RST_SHIFT,
63 OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
64 { OMAP3430_VDD2_VOLTAGE_MANAGER_RST_SHIFT,
65 OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
66 { OMAP3430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
67 { OMAP3430_ICECRUSHER_RST_SHIFT, OMAP_ICECRUSHER_RST_SRC_ID_SHIFT },
68 { -1, -1 },
69};
70
50/* PRM VP */ 71/* PRM VP */
51 72
52/* 73/*
@@ -217,6 +238,30 @@ static void __init omap3xxx_prm_enable_io_wakeup(void)
217 PM_WKEN); 238 PM_WKEN);
218} 239}
219 240
241/**
242 * omap3xxx_prm_read_reset_sources - return the last SoC reset source
243 *
244 * Return a u32 representing the last reset sources of the SoC. The
245 * returned reset source bits are standardized across OMAP SoCs.
246 */
247static u32 omap3xxx_prm_read_reset_sources(void)
248{
249 struct prm_reset_src_map *p;
250 u32 r = 0;
251 u32 v;
252
253 v = omap2_prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST);
254
255 p = omap3xxx_prm_reset_src_map;
256 while (p->reg_shift >= 0 && p->std_shift >= 0) {
257 if (v & (1 << p->reg_shift))
258 r |= 1 << p->std_shift;
259 p++;
260 }
261
262 return r;
263}
264
220/* Powerdomain low-level functions */ 265/* Powerdomain low-level functions */
221 266
222/* Applicable only for OMAP3. Not supported on OMAP2 */ 267/* Applicable only for OMAP3. Not supported on OMAP2 */
@@ -320,6 +365,10 @@ struct pwrdm_ops omap3_pwrdm_operations = {
320 * 365 *
321 */ 366 */
322 367
368static struct prm_ll_data omap3xxx_prm_ll_data = {
369 .read_reset_sources = &omap3xxx_prm_read_reset_sources,
370};
371
323static int __init omap3xxx_prm_init(void) 372static int __init omap3xxx_prm_init(void)
324{ 373{
325 int ret; 374 int ret;
@@ -327,12 +376,28 @@ static int __init omap3xxx_prm_init(void)
327 if (!cpu_is_omap34xx()) 376 if (!cpu_is_omap34xx())
328 return 0; 377 return 0;
329 378
379 ret = prm_register(&omap3xxx_prm_ll_data);
380 if (ret)
381 return ret;
382
330 omap3xxx_prm_enable_io_wakeup(); 383 omap3xxx_prm_enable_io_wakeup();
331 ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); 384 ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
332 if (!ret) 385 if (!ret)
333 irq_set_status_flags(omap_prcm_event_to_irq("io"), 386 irq_set_status_flags(omap_prcm_event_to_irq("io"),
334 IRQ_NOAUTOEN); 387 IRQ_NOAUTOEN);
335 388
389
336 return ret; 390 return ret;
337} 391}
338subsys_initcall(omap3xxx_prm_init); 392subsys_initcall(omap3xxx_prm_init);
393
394static void __exit omap3xxx_prm_exit(void)
395{
396 if (!cpu_is_omap34xx())
397 return;
398
399 /* Should never happen */
400 WARN(prm_unregister(&omap3xxx_prm_ll_data),
401 "%s: prm_ll_data function pointer mismatch\n", __func__);
402}
403__exitcall(omap3xxx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h
index 6821e8321610..a3c28a875410 100644
--- a/arch/arm/mach-omap2/prm3xxx.h
+++ b/arch/arm/mach-omap2/prm3xxx.h
@@ -152,6 +152,8 @@ extern void omap3xxx_prm_ocp_barrier(void);
152extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask); 152extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
153extern void omap3xxx_prm_restore_irqen(u32 *saved_mask); 153extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
154 154
155extern u32 omap3xxx_prm_get_reset_sources(void);
156
155#endif /* __ASSEMBLER */ 157#endif /* __ASSEMBLER */
156 158
157 159
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index 48d91930796d..a799e9552fbf 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * OMAP4 PRM module functions 2 * OMAP4 PRM module functions
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments, Inc. 4 * Copyright (C) 2011-2012 Texas Instruments, Inc.
5 * Copyright (C) 2010 Nokia Corporation 5 * Copyright (C) 2010 Nokia Corporation
6 * Benoît Cousson 6 * Benoît Cousson
7 * Paul Walmsley 7 * Paul Walmsley
@@ -30,6 +30,8 @@
30#include "prminst44xx.h" 30#include "prminst44xx.h"
31#include "powerdomain.h" 31#include "powerdomain.h"
32 32
33/* Static data */
34
33static const struct omap_prcm_irq omap4_prcm_irqs[] = { 35static const struct omap_prcm_irq omap4_prcm_irqs[] = {
34 OMAP_PRCM_IRQ("wkup", 0, 0), 36 OMAP_PRCM_IRQ("wkup", 0, 0),
35 OMAP_PRCM_IRQ("io", 9, 1), 37 OMAP_PRCM_IRQ("io", 9, 1),
@@ -48,6 +50,33 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
48 .restore_irqen = &omap44xx_prm_restore_irqen, 50 .restore_irqen = &omap44xx_prm_restore_irqen,
49}; 51};
50 52
53/*
54 * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
55 * hardware register (which are specific to OMAP44xx SoCs) to reset
56 * source ID bit shifts (which is an OMAP SoC-independent
57 * enumeration)
58 */
59static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
60 { OMAP4430_RST_GLOBAL_WARM_SW_SHIFT,
61 OMAP_GLOBAL_WARM_RST_SRC_ID_SHIFT },
62 { OMAP4430_RST_GLOBAL_COLD_SW_SHIFT,
63 OMAP_GLOBAL_COLD_RST_SRC_ID_SHIFT },
64 { OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT,
65 OMAP_SECU_VIOL_RST_SRC_ID_SHIFT },
66 { OMAP4430_MPU_WDT_RST_SHIFT, OMAP_MPU_WD_RST_SRC_ID_SHIFT },
67 { OMAP4430_SECURE_WDT_RST_SHIFT, OMAP_SECU_WD_RST_SRC_ID_SHIFT },
68 { OMAP4430_EXTERNAL_WARM_RST_SHIFT, OMAP_EXTWARM_RST_SRC_ID_SHIFT },
69 { OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT,
70 OMAP_VDD_MPU_VM_RST_SRC_ID_SHIFT },
71 { OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT,
72 OMAP_VDD_IVA_VM_RST_SRC_ID_SHIFT },
73 { OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT,
74 OMAP_VDD_CORE_VM_RST_SRC_ID_SHIFT },
75 { OMAP4430_ICEPICK_RST_SHIFT, OMAP_ICEPICK_RST_SRC_ID_SHIFT },
76 { OMAP4430_C2C_RST_SHIFT, OMAP_C2C_RST_SRC_ID_SHIFT },
77 { -1, -1 },
78};
79
51/* PRM low-level functions */ 80/* PRM low-level functions */
52 81
53/* Read a register in a CM/PRM instance in the PRM module */ 82/* Read a register in a CM/PRM instance in the PRM module */
@@ -293,6 +322,31 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
293 OMAP4_PRM_IO_PMCTRL_OFFSET); 322 OMAP4_PRM_IO_PMCTRL_OFFSET);
294} 323}
295 324
325/**
326 * omap44xx_prm_read_reset_sources - return the last SoC reset source
327 *
328 * Return a u32 representing the last reset sources of the SoC. The
329 * returned reset source bits are standardized across OMAP SoCs.
330 */
331static u32 omap44xx_prm_read_reset_sources(void)
332{
333 struct prm_reset_src_map *p;
334 u32 r = 0;
335 u32 v;
336
337 v = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
338 OMAP4_RM_RSTST);
339
340 p = omap44xx_prm_reset_src_map;
341 while (p->reg_shift >= 0 && p->std_shift >= 0) {
342 if (v & (1 << p->reg_shift))
343 r |= 1 << p->std_shift;
344 p++;
345 }
346
347 return r;
348}
349
296/* Powerdomain low-level functions */ 350/* Powerdomain low-level functions */
297 351
298static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst) 352static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
@@ -555,14 +609,37 @@ struct pwrdm_ops omap4_pwrdm_operations = {
555 .pwrdm_wait_transition = omap4_pwrdm_wait_transition, 609 .pwrdm_wait_transition = omap4_pwrdm_wait_transition,
556}; 610};
557 611
612/*
613 * XXX document
614 */
615static struct prm_ll_data omap44xx_prm_ll_data = {
616 .read_reset_sources = &omap44xx_prm_read_reset_sources,
617};
558 618
559static int __init omap4xxx_prm_init(void) 619static int __init omap44xx_prm_init(void)
560{ 620{
621 int ret;
622
561 if (!cpu_is_omap44xx()) 623 if (!cpu_is_omap44xx())
562 return 0; 624 return 0;
563 625
626 ret = prm_register(&omap44xx_prm_ll_data);
627 if (ret)
628 return ret;
629
564 omap44xx_prm_enable_io_wakeup(); 630 omap44xx_prm_enable_io_wakeup();
565 631
566 return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); 632 return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
567} 633}
568subsys_initcall(omap4xxx_prm_init); 634subsys_initcall(omap44xx_prm_init);
635
636static void __exit omap44xx_prm_exit(void)
637{
638 if (!cpu_is_omap44xx())
639 return;
640
641 /* Should never happen */
642 WARN(prm_unregister(&omap44xx_prm_ll_data),
643 "%s: prm_ll_data function pointer mismatch\n", __func__);
644}
645__exitcall(omap44xx_prm_exit);
diff --git a/arch/arm/mach-omap2/prm44xx.h b/arch/arm/mach-omap2/prm44xx.h
index ee72ae6bd8c9..c8e1accdc90e 100644
--- a/arch/arm/mach-omap2/prm44xx.h
+++ b/arch/arm/mach-omap2/prm44xx.h
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
771extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask); 771extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
772extern void omap44xx_prm_restore_irqen(u32 *saved_mask); 772extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
773 773
774extern u32 omap44xx_prm_get_reset_sources(void);
775
774# endif 776# endif
775 777
776#endif 778#endif
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 8670a3c4bc5e..e200e4fb47dc 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -28,6 +28,8 @@
28#include <plat/prcm.h> 28#include <plat/prcm.h>
29 29
30#include "prm2xxx_3xxx.h" 30#include "prm2xxx_3xxx.h"
31#include "prm2xxx.h"
32#include "prm3xxx.h"
31#include "prm44xx.h" 33#include "prm44xx.h"
32 34
33/* 35/*
@@ -327,6 +329,30 @@ err:
327} 329}
328 330
329/** 331/**
332 * prm_read_reset_sources - return the sources of the SoC's last reset
333 *
334 * Return a u32 bitmask representing the reset sources that caused the
335 * SoC to reset. The low-level per-SoC functions called by this
336 * function remap the SoC-specific reset source bits into an
337 * OMAP-common set of reset source bits, defined in
338 * arch/arm/mach-omap2/prm.h. Returns the standardized reset source
339 * u32 bitmask from the hardware upon success, or returns (1 <<
340 * OMAP_UNKNOWN_RST_SRC_ID_SHIFT) if no low-level read_reset_sources()
341 * function was registered.
342 */
343u32 prm_read_reset_sources(void)
344{
345 u32 ret = 1 << OMAP_UNKNOWN_RST_SRC_ID_SHIFT;
346
347 if (prm_ll_data->read_reset_sources)
348 ret = prm_ll_data->read_reset_sources();
349 else
350 WARN_ONCE(1, "prm: %s: no mapping function defined for reset sources\n", __func__);
351
352 return ret;
353}
354
355/**
330 * prm_register - register per-SoC low-level data with the PRM 356 * prm_register - register per-SoC low-level data with the PRM
331 * @pld: low-level per-SoC OMAP PRM data & function pointers to register 357 * @pld: low-level per-SoC OMAP PRM data & function pointers to register
332 * 358 *