diff options
author | Chris Zhong <zyw@rock-chips.com> | 2015-03-21 12:04:51 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2015-04-16 15:17:26 -0400 |
commit | b403125d3bbf8046c1186e1a49cb17bb5551db14 (patch) | |
tree | a71540ca75dd0f65c491333046a67c67f272c29b /arch | |
parent | 0ea001d3b43cc9d387c093ae205c4228cd88a886 (diff) |
ARM: rockchip: fix undefined instruction of reset_ctrl_regs
Sometimes the debug module may not work well after resume, since it has
not been correctly reset when wakeup from suspend. That cause system
crash during reusme, and a 'undefined instruction' is displayed on the
console. Set the GRF_FORCE_JTAG bit of RK3288_GRF_SOC_CON0 can ensure
that debug modul is reset. And we can change the value of
RK3288_GRF_SOC_CON0 back when system resume.
Signed-off-by: Chris Zhong <zyw@rock-chips.com>
Tested-by: Caesar Wang <wxt@rock-chips.com>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
According to discussions, there does not seem a better solution available.
Please also see the potential security implication described in the
comment inline in the code.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-rockchip/pm.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-rockchip/pm.h | 4 |
2 files changed, 30 insertions, 0 deletions
diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c index b0dcbe28f78c..22812fe06460 100644 --- a/arch/arm/mach-rockchip/pm.c +++ b/arch/arm/mach-rockchip/pm.c | |||
@@ -44,9 +44,11 @@ static void __iomem *rk3288_bootram_base; | |||
44 | static phys_addr_t rk3288_bootram_phy; | 44 | static phys_addr_t rk3288_bootram_phy; |
45 | 45 | ||
46 | static struct regmap *pmu_regmap; | 46 | static struct regmap *pmu_regmap; |
47 | static struct regmap *grf_regmap; | ||
47 | static struct regmap *sgrf_regmap; | 48 | static struct regmap *sgrf_regmap; |
48 | 49 | ||
49 | static u32 rk3288_pmu_pwr_mode_con; | 50 | static u32 rk3288_pmu_pwr_mode_con; |
51 | static u32 rk3288_grf_soc_con0; | ||
50 | static u32 rk3288_sgrf_soc_con0; | 52 | static u32 rk3288_sgrf_soc_con0; |
51 | 53 | ||
52 | static inline u32 rk3288_l2_config(void) | 54 | static inline u32 rk3288_l2_config(void) |
@@ -70,12 +72,26 @@ static void rk3288_slp_mode_set(int level) | |||
70 | { | 72 | { |
71 | u32 mode_set, mode_set1; | 73 | u32 mode_set, mode_set1; |
72 | 74 | ||
75 | regmap_read(grf_regmap, RK3288_GRF_SOC_CON0, &rk3288_grf_soc_con0); | ||
76 | |||
73 | regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); | 77 | regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); |
74 | 78 | ||
75 | regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, | 79 | regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, |
76 | &rk3288_pmu_pwr_mode_con); | 80 | &rk3288_pmu_pwr_mode_con); |
77 | 81 | ||
78 | /* | 82 | /* |
83 | * We need set this bit GRF_FORCE_JTAG here, for the debug module, | ||
84 | * otherwise, it may become inaccessible after resume. | ||
85 | * This creates a potential security issue, as the sdmmc pins may | ||
86 | * accept jtag data for a short time during resume if no card is | ||
87 | * inserted. | ||
88 | * But this is of course also true for the regular boot, before we | ||
89 | * turn of the jtag/sdmmc autodetect. | ||
90 | */ | ||
91 | regmap_write(grf_regmap, RK3288_GRF_SOC_CON0, GRF_FORCE_JTAG | | ||
92 | GRF_FORCE_JTAG_WRITE); | ||
93 | |||
94 | /* | ||
79 | * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR | 95 | * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR |
80 | * PCLK_WDT_GATE - disable WDT during suspend. | 96 | * PCLK_WDT_GATE - disable WDT during suspend. |
81 | */ | 97 | */ |
@@ -135,6 +151,9 @@ static void rk3288_slp_mode_set_resume(void) | |||
135 | regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, | 151 | regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, |
136 | rk3288_sgrf_soc_con0 | SGRF_PCLK_WDT_GATE_WRITE | 152 | rk3288_sgrf_soc_con0 | SGRF_PCLK_WDT_GATE_WRITE |
137 | | SGRF_FAST_BOOT_EN_WRITE); | 153 | | SGRF_FAST_BOOT_EN_WRITE); |
154 | |||
155 | regmap_write(grf_regmap, RK3288_GRF_SOC_CON0, rk3288_grf_soc_con0 | | ||
156 | GRF_FORCE_JTAG_WRITE); | ||
138 | } | 157 | } |
139 | 158 | ||
140 | static int rockchip_lpmode_enter(unsigned long arg) | 159 | static int rockchip_lpmode_enter(unsigned long arg) |
@@ -193,6 +212,13 @@ static int rk3288_suspend_init(struct device_node *np) | |||
193 | return PTR_ERR(pmu_regmap); | 212 | return PTR_ERR(pmu_regmap); |
194 | } | 213 | } |
195 | 214 | ||
215 | grf_regmap = syscon_regmap_lookup_by_compatible( | ||
216 | "rockchip,rk3288-grf"); | ||
217 | if (IS_ERR(grf_regmap)) { | ||
218 | pr_err("%s: could not find grf regmap\n", __func__); | ||
219 | return PTR_ERR(pmu_regmap); | ||
220 | } | ||
221 | |||
196 | sram_np = of_find_compatible_node(NULL, NULL, | 222 | sram_np = of_find_compatible_node(NULL, NULL, |
197 | "rockchip,rk3288-pmu-sram"); | 223 | "rockchip,rk3288-pmu-sram"); |
198 | if (!sram_np) { | 224 | if (!sram_np) { |
diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h index 3e8d39c0c3d5..f8a747bc1437 100644 --- a/arch/arm/mach-rockchip/pm.h +++ b/arch/arm/mach-rockchip/pm.h | |||
@@ -48,6 +48,10 @@ static inline void rockchip_suspend_init(void) | |||
48 | #define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44 | 48 | #define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44 |
49 | #define RK3288_PMU_PWRMODE_CON1 0x90 | 49 | #define RK3288_PMU_PWRMODE_CON1 0x90 |
50 | 50 | ||
51 | #define RK3288_GRF_SOC_CON0 0x244 | ||
52 | #define GRF_FORCE_JTAG BIT(12) | ||
53 | #define GRF_FORCE_JTAG_WRITE BIT(28) | ||
54 | |||
51 | #define RK3288_SGRF_SOC_CON0 (0x0000) | 55 | #define RK3288_SGRF_SOC_CON0 (0x0000) |
52 | #define RK3288_SGRF_FAST_BOOT_ADDR (0x0120) | 56 | #define RK3288_SGRF_FAST_BOOT_ADDR (0x0120) |
53 | #define SGRF_PCLK_WDT_GATE BIT(6) | 57 | #define SGRF_PCLK_WDT_GATE BIT(6) |