1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2023 Rockchip Electronics Co., Ltd.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/init.h>
7*4882a593Smuzhiyun #include <linux/io.h>
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/of_address.h>
11*4882a593Smuzhiyun #include <linux/suspend.h>
12*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <asm/cacheflush.h>
15*4882a593Smuzhiyun #include <asm/fiq_glue.h>
16*4882a593Smuzhiyun #include <asm/tlbflush.h>
17*4882a593Smuzhiyun #include <asm/suspend.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include "rkpm_gicv2.h"
20*4882a593Smuzhiyun #include "rkpm_helpers.h"
21*4882a593Smuzhiyun #include "rkpm_uart.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include "rv1106_pm.h"
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #define RV1106_PM_REG_REGION_MEM_SIZE SZ_4K
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun enum {
28*4882a593Smuzhiyun RV1106_GPIO_PULL_NONE,
29*4882a593Smuzhiyun RV1106_GPIO_PULL_UP,
30*4882a593Smuzhiyun RV1106_GPIO_PULL_DOWN,
31*4882a593Smuzhiyun RV1106_GPIO_PULL_UP_DOWN,
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun struct rockchip_pm_data {
35*4882a593Smuzhiyun const struct platform_suspend_ops *ops;
36*4882a593Smuzhiyun int (*init)(struct device_node *np);
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun struct rv1106_sleep_ddr_data {
40*4882a593Smuzhiyun u32 cru_gate_con[RV1106_CRU_GATE_CON_NUM];
41*4882a593Smuzhiyun u32 pmucru_gate_con[RV1106_PMUCRU_GATE_CON_NUM];
42*4882a593Smuzhiyun u32 pericru_gate_con[RV1106_PERICRU_GATE_CON_NUM];
43*4882a593Smuzhiyun u32 npucru_gate_con[RV1106_NPUCRU_GATE_CON_NUM];
44*4882a593Smuzhiyun u32 venccru_gate_con[RV1106_VENCCRU_GATE_CON_NUM];
45*4882a593Smuzhiyun u32 vicru_gate_con[RV1106_VICRU_GATE_CON_NUM];
46*4882a593Smuzhiyun u32 vocru_gate_con[RV1106_VOCRU_GATE_CON_NUM];
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun u32 ddrgrf_con1, ddrgrf_con2, ddrgrf_con3, ddrc_pwrctrl, ddrc_dfilpcfg0;
49*4882a593Smuzhiyun u32 pmucru_sel_con7;
50*4882a593Smuzhiyun u32 pmugrf_soc_con0, pmugrf_soc_con1, pmugrf_soc_con4, pmugrf_soc_con5;
51*4882a593Smuzhiyun u32 ioc0_1a_iomux_l, ioc1_1a_iomux_l;
52*4882a593Smuzhiyun u32 gpio0a_iomux_l, gpio0a_iomux_h, gpio0a0_pull;
53*4882a593Smuzhiyun u32 gpio0_ddr_l, gpio0_ddr_h;
54*4882a593Smuzhiyun u32 pmu_wkup_int_st, gpio0_int_st;
55*4882a593Smuzhiyun };
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun static struct rv1106_sleep_ddr_data ddr_data;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun static void __iomem *pmucru_base;
60*4882a593Smuzhiyun static void __iomem *cru_base;
61*4882a593Smuzhiyun static void __iomem *pericru_base;
62*4882a593Smuzhiyun static void __iomem *vicru_base;
63*4882a593Smuzhiyun static void __iomem *npucru_base;
64*4882a593Smuzhiyun static void __iomem *corecru_base;
65*4882a593Smuzhiyun static void __iomem *venccru_base;
66*4882a593Smuzhiyun static void __iomem *vocru_base;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun static void __iomem *perigrf_base;
69*4882a593Smuzhiyun static void __iomem *vencgrf_base;
70*4882a593Smuzhiyun static void __iomem *npugrf_base;
71*4882a593Smuzhiyun static void __iomem *pmugrf_base;
72*4882a593Smuzhiyun static void __iomem *ddrgrf_base;
73*4882a593Smuzhiyun static void __iomem *coregrf_base;
74*4882a593Smuzhiyun static void __iomem *vigrf_base;
75*4882a593Smuzhiyun static void __iomem *vogrf_base;
76*4882a593Smuzhiyun static void __iomem *perisgrf_base;
77*4882a593Smuzhiyun static void __iomem *visgrf_base;
78*4882a593Smuzhiyun static void __iomem *npusgrf_base;
79*4882a593Smuzhiyun static void __iomem *coresgrf_base;
80*4882a593Smuzhiyun static void __iomem *vencsgrf_base;
81*4882a593Smuzhiyun static void __iomem *vosgrf_base;
82*4882a593Smuzhiyun static void __iomem *pmusgrf_base;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun static void __iomem *pmupvtm_base;
85*4882a593Smuzhiyun static void __iomem *uartdbg_base;
86*4882a593Smuzhiyun static void __iomem *pmu_base;
87*4882a593Smuzhiyun static void __iomem *gicd_base;
88*4882a593Smuzhiyun static void __iomem *gicc_base;
89*4882a593Smuzhiyun static void __iomem *firewall_ddr_base;
90*4882a593Smuzhiyun static void __iomem *firewall_syssram_base;
91*4882a593Smuzhiyun static void __iomem *pmu_base;
92*4882a593Smuzhiyun static void __iomem *nstimer_base;
93*4882a593Smuzhiyun static void __iomem *stimer_base;
94*4882a593Smuzhiyun static void __iomem *ddrc_base;
95*4882a593Smuzhiyun static void __iomem *ioc_base[5];
96*4882a593Smuzhiyun static void __iomem *gpio_base[5];
97*4882a593Smuzhiyun static void __iomem *rv1106_bootram_base;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun #define WMSK_VAL 0xffff0000
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun static struct reg_region vd_core_reg_rgns[] = {
102*4882a593Smuzhiyun /* core_cru */
103*4882a593Smuzhiyun { REG_REGION(0x300, 0x310, 4, &corecru_base, WMSK_VAL)},
104*4882a593Smuzhiyun { REG_REGION(0x800, 0x804, 4, &corecru_base, WMSK_VAL)},
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* core_sgrf */
107*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &coresgrf_base, 0)},
108*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &coresgrf_base, 0)},
109*4882a593Smuzhiyun { REG_REGION(0x020, 0x030, 4, &coresgrf_base, WMSK_VAL)},
110*4882a593Smuzhiyun { REG_REGION(0x040, 0x040, 4, &coresgrf_base, WMSK_VAL)},
111*4882a593Smuzhiyun { REG_REGION(0x044, 0x044, 4, &coresgrf_base, 0)},
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /* core grf */
114*4882a593Smuzhiyun { REG_REGION(0x004, 0x004, 4, &coregrf_base, WMSK_VAL)},
115*4882a593Smuzhiyun { REG_REGION(0x008, 0x010, 4, &coregrf_base, 0)},
116*4882a593Smuzhiyun { REG_REGION(0x024, 0x028, 4, &coregrf_base, 0)},
117*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &coregrf_base, WMSK_VAL)},
118*4882a593Smuzhiyun { REG_REGION(0x02c, 0x02c, 4, &coregrf_base, WMSK_VAL)},
119*4882a593Smuzhiyun { REG_REGION(0x038, 0x03c, 4, &coregrf_base, WMSK_VAL)},
120*4882a593Smuzhiyun };
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun static struct reg_region vd_log_reg_rgns[] = {
123*4882a593Smuzhiyun /* firewall_ddr */
124*4882a593Smuzhiyun { REG_REGION(0x000, 0x03c, 4, &firewall_ddr_base, 0)},
125*4882a593Smuzhiyun { REG_REGION(0x040, 0x06c, 4, &firewall_ddr_base, 0)},
126*4882a593Smuzhiyun { REG_REGION(0x0f0, 0x0f0, 4, &firewall_ddr_base, 0)},
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* firewall_sram */
129*4882a593Smuzhiyun { REG_REGION(0x000, 0x01c, 4, &firewall_syssram_base, 0)},
130*4882a593Smuzhiyun { REG_REGION(0x040, 0x054, 4, &firewall_syssram_base, 0)},
131*4882a593Smuzhiyun { REG_REGION(0x0f0, 0x0f0, 4, &firewall_syssram_base, 0)},
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* cru */
134*4882a593Smuzhiyun { REG_REGION(0x000, 0x004, 4, &cru_base, WMSK_VAL)},
135*4882a593Smuzhiyun { REG_REGION(0x008, 0x008, 4, &cru_base, 0)},
136*4882a593Smuzhiyun { REG_REGION(0x00c, 0x010, 4, &cru_base, WMSK_VAL)},
137*4882a593Smuzhiyun { REG_REGION(0x020, 0x024, 4, &cru_base, WMSK_VAL)},
138*4882a593Smuzhiyun { REG_REGION(0x028, 0x028, 4, &cru_base, 0)},
139*4882a593Smuzhiyun { REG_REGION(0x02c, 0x030, 4, &cru_base, WMSK_VAL)},
140*4882a593Smuzhiyun { REG_REGION(0x060, 0x064, 4, &cru_base, WMSK_VAL)},
141*4882a593Smuzhiyun { REG_REGION(0x068, 0x068, 4, &cru_base, 0)},
142*4882a593Smuzhiyun { REG_REGION(0x06c, 0x070, 4, &cru_base, WMSK_VAL)},
143*4882a593Smuzhiyun { REG_REGION(0x140, 0x1bc, 4, &cru_base, 0)},
144*4882a593Smuzhiyun /* { REG_REGION(0x280, 0x280, 4, &cru_base, WMSK_VAL)}, */
145*4882a593Smuzhiyun { REG_REGION(0x300, 0x310, 4, &cru_base, WMSK_VAL)},
146*4882a593Smuzhiyun { REG_REGION(0x314, 0x34c, 8, &cru_base, WMSK_VAL)},
147*4882a593Smuzhiyun { REG_REGION(0x318, 0x350, 8, &cru_base, 0)},
148*4882a593Smuzhiyun { REG_REGION(0x354, 0x360, 4, &cru_base, WMSK_VAL)},
149*4882a593Smuzhiyun { REG_REGION(0x364, 0x37c, 8, &cru_base, WMSK_VAL)},
150*4882a593Smuzhiyun { REG_REGION(0x368, 0x380, 8, &cru_base, 0)},
151*4882a593Smuzhiyun { REG_REGION(0x384, 0x384, 4, &cru_base, WMSK_VAL)},
152*4882a593Smuzhiyun { REG_REGION(0x800, 0x80c, 4, &cru_base, WMSK_VAL)},
153*4882a593Smuzhiyun { REG_REGION(0xc00, 0xc00, 4, &cru_base, 0)},
154*4882a593Smuzhiyun { REG_REGION(0xc10, 0xc10, 4, &cru_base, 0)},
155*4882a593Smuzhiyun { REG_REGION(0xc14, 0xc28, 4, &cru_base, WMSK_VAL)},
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* npu_cru */
158*4882a593Smuzhiyun { REG_REGION(0x300, 0x300, 4, &npucru_base, WMSK_VAL)},
159*4882a593Smuzhiyun { REG_REGION(0x800, 0x804, 4, &npucru_base, WMSK_VAL)},
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* npu_sgrf */
162*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &npusgrf_base, 0)},
163*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &npusgrf_base, 0)},
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* peri_cru */
166*4882a593Smuzhiyun { REG_REGION(0x304, 0x32c, 4, &pericru_base, WMSK_VAL)},
167*4882a593Smuzhiyun { REG_REGION(0x800, 0x81c, 4, &pericru_base, WMSK_VAL)},
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* peri_sgrf */
170*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &perisgrf_base, 0)},
171*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &perisgrf_base, 0)},
172*4882a593Smuzhiyun { REG_REGION(0x020, 0x030, 4, &perisgrf_base, WMSK_VAL)},
173*4882a593Smuzhiyun { REG_REGION(0x080, 0x0a4, 4, &perisgrf_base, WMSK_VAL)},
174*4882a593Smuzhiyun { REG_REGION(0x0b8, 0x0bc, 4, &perisgrf_base, WMSK_VAL)},
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* vi_cru */
177*4882a593Smuzhiyun { REG_REGION(0x300, 0x30c, 4, &vicru_base, WMSK_VAL)},
178*4882a593Smuzhiyun { REG_REGION(0x800, 0x808, 4, &vicru_base, WMSK_VAL)},
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /* vi_sgrf */
181*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &visgrf_base, 0)},
182*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &visgrf_base, 0)},
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* vo_cru */
185*4882a593Smuzhiyun { REG_REGION(0x300, 0x30c, 4, &vocru_base, WMSK_VAL)},
186*4882a593Smuzhiyun { REG_REGION(0x800, 0x80c, 4, &vocru_base, WMSK_VAL)},
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* vo_sgrf */
189*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &vosgrf_base, 0)},
190*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &vosgrf_base, 0)},
191*4882a593Smuzhiyun { REG_REGION(0x018, 0x018, 4, &vosgrf_base, WMSK_VAL)},
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* vepu_cru */
194*4882a593Smuzhiyun { REG_REGION(0x300, 0x304, 4, &venccru_base, WMSK_VAL)},
195*4882a593Smuzhiyun { REG_REGION(0x800, 0x808, 4, &venccru_base, WMSK_VAL)},
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* vepu_sgrf */
198*4882a593Smuzhiyun { REG_REGION(0x004, 0x014, 4, &vencsgrf_base, 0)},
199*4882a593Smuzhiyun { REG_REGION(0x000, 0x000, 4, &vencsgrf_base, 0)},
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* gpio1_ioc */
202*4882a593Smuzhiyun { REG_REGION(0x000, 0x018, 4, &ioc_base[1], WMSK_VAL)},
203*4882a593Smuzhiyun { REG_REGION(0x080, 0x0b4, 4, &ioc_base[1], WMSK_VAL)},
204*4882a593Smuzhiyun { REG_REGION(0x180, 0x18c, 4, &ioc_base[1], WMSK_VAL)},
205*4882a593Smuzhiyun { REG_REGION(0x1c0, 0x1cc, 4, &ioc_base[1], WMSK_VAL)},
206*4882a593Smuzhiyun { REG_REGION(0x200, 0x20c, 4, &ioc_base[1], WMSK_VAL)},
207*4882a593Smuzhiyun { REG_REGION(0x240, 0x24c, 4, &ioc_base[1], WMSK_VAL)},
208*4882a593Smuzhiyun { REG_REGION(0x280, 0x28c, 4, &ioc_base[1], WMSK_VAL)},
209*4882a593Smuzhiyun { REG_REGION(0x2c0, 0x2cc, 4, &ioc_base[1], WMSK_VAL)},
210*4882a593Smuzhiyun { REG_REGION(0x2f4, 0x2f4, 4, &ioc_base[1], WMSK_VAL)},
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun /* gpio2_ioc */
213*4882a593Smuzhiyun { REG_REGION(0x020, 0x028, 4, &ioc_base[2], WMSK_VAL)},
214*4882a593Smuzhiyun { REG_REGION(0x0c0, 0x0d0, 4, &ioc_base[2], WMSK_VAL)},
215*4882a593Smuzhiyun { REG_REGION(0x190, 0x194, 4, &ioc_base[2], WMSK_VAL)},
216*4882a593Smuzhiyun { REG_REGION(0x1d0, 0x1d4, 4, &ioc_base[2], WMSK_VAL)},
217*4882a593Smuzhiyun { REG_REGION(0x210, 0x214, 4, &ioc_base[2], WMSK_VAL)},
218*4882a593Smuzhiyun { REG_REGION(0x250, 0x254, 4, &ioc_base[2], WMSK_VAL)},
219*4882a593Smuzhiyun { REG_REGION(0x290, 0x294, 4, &ioc_base[2], WMSK_VAL)},
220*4882a593Smuzhiyun { REG_REGION(0x2d0, 0x2d4, 4, &ioc_base[2], WMSK_VAL)},
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* gpio3_ioc */
223*4882a593Smuzhiyun { REG_REGION(0x040, 0x058, 4, &ioc_base[3], WMSK_VAL)},
224*4882a593Smuzhiyun { REG_REGION(0x100, 0x10c, 4, &ioc_base[3], WMSK_VAL)},
225*4882a593Smuzhiyun { REG_REGION(0x128, 0x134, 4, &ioc_base[3], WMSK_VAL)},
226*4882a593Smuzhiyun { REG_REGION(0x1a0, 0x1ac, 4, &ioc_base[3], WMSK_VAL)},
227*4882a593Smuzhiyun { REG_REGION(0x1e0, 0x1ec, 4, &ioc_base[3], WMSK_VAL)},
228*4882a593Smuzhiyun { REG_REGION(0x220, 0x22c, 4, &ioc_base[3], WMSK_VAL)},
229*4882a593Smuzhiyun { REG_REGION(0x260, 0x26c, 4, &ioc_base[3], WMSK_VAL)},
230*4882a593Smuzhiyun { REG_REGION(0x2a0, 0x2ac, 4, &ioc_base[3], WMSK_VAL)},
231*4882a593Smuzhiyun { REG_REGION(0x2e0, 0x2ec, 4, &ioc_base[3], WMSK_VAL)},
232*4882a593Smuzhiyun { REG_REGION(0x2f4, 0x2f4, 4, &ioc_base[3], WMSK_VAL)},
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* gpio1~3 */
235*4882a593Smuzhiyun { REG_REGION(0x000, 0x00c, 4, &gpio_base[1], WMSK_VAL)},
236*4882a593Smuzhiyun { REG_REGION(0x018, 0x044, 4, &gpio_base[1], WMSK_VAL)},
237*4882a593Smuzhiyun { REG_REGION(0x048, 0x048, 4, &gpio_base[1], 0)},
238*4882a593Smuzhiyun { REG_REGION(0x060, 0x064, 4, &gpio_base[1], WMSK_VAL)},
239*4882a593Smuzhiyun { REG_REGION(0x100, 0x108, 4, &gpio_base[1], WMSK_VAL)},
240*4882a593Smuzhiyun { REG_REGION(0x010, 0x014, 4, &gpio_base[1], WMSK_VAL)},
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun { REG_REGION(0x000, 0x00c, 4, &gpio_base[2], WMSK_VAL)},
243*4882a593Smuzhiyun { REG_REGION(0x018, 0x044, 4, &gpio_base[2], WMSK_VAL)},
244*4882a593Smuzhiyun { REG_REGION(0x048, 0x048, 4, &gpio_base[2], 0)},
245*4882a593Smuzhiyun { REG_REGION(0x060, 0x064, 4, &gpio_base[2], WMSK_VAL)},
246*4882a593Smuzhiyun { REG_REGION(0x100, 0x108, 4, &gpio_base[2], WMSK_VAL)},
247*4882a593Smuzhiyun { REG_REGION(0x010, 0x014, 4, &gpio_base[2], WMSK_VAL)},
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun { REG_REGION(0x000, 0x00c, 4, &gpio_base[3], WMSK_VAL)},
250*4882a593Smuzhiyun { REG_REGION(0x018, 0x044, 4, &gpio_base[3], WMSK_VAL)},
251*4882a593Smuzhiyun { REG_REGION(0x048, 0x048, 4, &gpio_base[3], 0)},
252*4882a593Smuzhiyun { REG_REGION(0x060, 0x064, 4, &gpio_base[3], WMSK_VAL)},
253*4882a593Smuzhiyun { REG_REGION(0x100, 0x108, 4, &gpio_base[3], WMSK_VAL)},
254*4882a593Smuzhiyun { REG_REGION(0x010, 0x014, 4, &gpio_base[3], WMSK_VAL)},
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* NS TIMER 6 channel */
257*4882a593Smuzhiyun { REG_REGION(0x00, 0x04, 4, &nstimer_base, 0)},
258*4882a593Smuzhiyun { REG_REGION(0x10, 0x10, 4, &nstimer_base, 0)},
259*4882a593Smuzhiyun { REG_REGION(0x20, 0x24, 4, &nstimer_base, 0)},
260*4882a593Smuzhiyun { REG_REGION(0x30, 0x30, 4, &nstimer_base, 0)},
261*4882a593Smuzhiyun { REG_REGION(0x40, 0x44, 4, &nstimer_base, 0)},
262*4882a593Smuzhiyun { REG_REGION(0x50, 0x50, 4, &nstimer_base, 0)},
263*4882a593Smuzhiyun { REG_REGION(0x60, 0x64, 4, &nstimer_base, 0)},
264*4882a593Smuzhiyun { REG_REGION(0x70, 0x70, 4, &nstimer_base, 0)},
265*4882a593Smuzhiyun { REG_REGION(0x80, 0x84, 4, &nstimer_base, 0)},
266*4882a593Smuzhiyun { REG_REGION(0x90, 0x90, 4, &nstimer_base, 0)},
267*4882a593Smuzhiyun { REG_REGION(0xa0, 0xa4, 4, &nstimer_base, 0)},
268*4882a593Smuzhiyun { REG_REGION(0xb0, 0xb0, 4, &nstimer_base, 0)},
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* S TIMER0 2 channel */
271*4882a593Smuzhiyun { REG_REGION(0x00, 0x04, 4, &stimer_base, 0)},
272*4882a593Smuzhiyun { REG_REGION(0x10, 0x10, 4, &stimer_base, 0)},
273*4882a593Smuzhiyun { REG_REGION(0x20, 0x24, 4, &stimer_base, 0)},
274*4882a593Smuzhiyun { REG_REGION(0x30, 0x30, 4, &stimer_base, 0)},
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun #define PLL_LOCKED_TIMEOUT 600000U
278*4882a593Smuzhiyun
pm_pll_wait_lock(u32 pll_id)279*4882a593Smuzhiyun static void pm_pll_wait_lock(u32 pll_id)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun int delay = PLL_LOCKED_TIMEOUT;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (readl_relaxed(cru_base + RV1106_CRU_PLL_CON(pll_id, 1)) & CRU_PLLCON1_PWRDOWN)
284*4882a593Smuzhiyun return;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun while (delay-- >= 0) {
287*4882a593Smuzhiyun if (readl_relaxed(cru_base + RV1106_CRU_PLL_CON(pll_id, 1)) &
288*4882a593Smuzhiyun CRU_PLLCON1_LOCK_STATUS)
289*4882a593Smuzhiyun break;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun rkpm_raw_udelay(1);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (delay <= 0) {
295*4882a593Smuzhiyun rkpm_printstr("Can't wait pll lock: ");
296*4882a593Smuzhiyun rkpm_printhex(pll_id);
297*4882a593Smuzhiyun rkpm_printch('\n');
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun struct plat_gicv2_dist_ctx_t gicd_ctx_save;
302*4882a593Smuzhiyun struct plat_gicv2_cpu_ctx_t gicc_ctx_save;
303*4882a593Smuzhiyun
gic400_save(void)304*4882a593Smuzhiyun static void gic400_save(void)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun rkpm_gicv2_cpu_save(gicd_base, gicc_base, &gicc_ctx_save);
307*4882a593Smuzhiyun rkpm_gicv2_dist_save(gicd_base, &gicd_ctx_save);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
gic400_restore(void)310*4882a593Smuzhiyun static void gic400_restore(void)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun rkpm_gicv2_dist_restore(gicd_base, &gicd_ctx_save);
313*4882a593Smuzhiyun rkpm_gicv2_cpu_restore(gicd_base, gicc_base, &gicc_ctx_save);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
uart_wrtie_byte(uint8_t byte)316*4882a593Smuzhiyun static void uart_wrtie_byte(uint8_t byte)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun writel_relaxed(byte, uartdbg_base + 0x0);
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun while (!(readl_relaxed(uartdbg_base + 0x14) & 0x40))
321*4882a593Smuzhiyun ;
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
rkpm_printch(int c)324*4882a593Smuzhiyun void rkpm_printch(int c)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun if (c == '\n')
327*4882a593Smuzhiyun uart_wrtie_byte('\r');
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun uart_wrtie_byte(c);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun #define RV1106_DUMP_GPIO_INTEN(id) \
333*4882a593Smuzhiyun do { \
334*4882a593Smuzhiyun rkpm_printstr("GPIO"); \
335*4882a593Smuzhiyun rkpm_printdec(id); \
336*4882a593Smuzhiyun rkpm_printstr(": "); \
337*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_EN_L)); \
338*4882a593Smuzhiyun rkpm_printch(' '); \
339*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_EN_H)); \
340*4882a593Smuzhiyun rkpm_printch(' '); \
341*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_MASK_L)); \
342*4882a593Smuzhiyun rkpm_printch(' '); \
343*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_MASK_H)); \
344*4882a593Smuzhiyun rkpm_printch(' '); \
345*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_STATUS)); \
346*4882a593Smuzhiyun rkpm_printch(' '); \
347*4882a593Smuzhiyun rkpm_printhex(readl_relaxed(gpio_base[id] + RV1106_GPIO_INT_RAWSTATUS));\
348*4882a593Smuzhiyun rkpm_printch('\n'); \
349*4882a593Smuzhiyun } while (0)
350*4882a593Smuzhiyun
rv1106_dbg_pmu_wkup_src(void)351*4882a593Smuzhiyun static void rv1106_dbg_pmu_wkup_src(void)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun u32 pmu_int_st = ddr_data.pmu_wkup_int_st;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun rkpm_printstr("wake up status:");
356*4882a593Smuzhiyun rkpm_printhex(pmu_int_st);
357*4882a593Smuzhiyun rkpm_printch('\n');
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (pmu_int_st)
360*4882a593Smuzhiyun rkpm_printstr("wake up information:\n");
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN)) {
363*4882a593Smuzhiyun rkpm_printstr("GPIO0 interrupt wakeup:");
364*4882a593Smuzhiyun rkpm_printhex(ddr_data.gpio0_int_st);
365*4882a593Smuzhiyun rkpm_printch('\n');
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_SDMMC_EN))
369*4882a593Smuzhiyun rkpm_printstr("PWM detect wakeup\n");
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_SDIO_EN))
372*4882a593Smuzhiyun rkpm_printstr("GMAC interrupt wakeup\n");
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMER_EN))
375*4882a593Smuzhiyun rkpm_printstr("TIMER interrupt wakeup\n");
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_USBDEV_EN))
378*4882a593Smuzhiyun rkpm_printstr("USBDEV detect wakeup\n");
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (pmu_int_st & BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN))
381*4882a593Smuzhiyun rkpm_printstr("TIMEOUT interrupt wakeup\n");
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun rkpm_printch('\n');
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
rv1106_dbg_irq_prepare(void)386*4882a593Smuzhiyun static void rv1106_dbg_irq_prepare(void)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun RV1106_DUMP_GPIO_INTEN(0);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
rv1106_dbg_irq_finish(void)391*4882a593Smuzhiyun static void rv1106_dbg_irq_finish(void)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun rv1106_dbg_pmu_wkup_src();
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
rv1106_l2_config(void)396*4882a593Smuzhiyun static inline u32 rv1106_l2_config(void)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun u32 l2ctlr;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr));
401*4882a593Smuzhiyun return l2ctlr;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
rv1106_config_bootdata(void)404*4882a593Smuzhiyun static void __init rv1106_config_bootdata(void)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun rkpm_bootdata_cpusp = RV1106_PMUSRAM_BASE + (SZ_8K - 8);
407*4882a593Smuzhiyun rkpm_bootdata_cpu_code = __pa_symbol(cpu_resume);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun rkpm_bootdata_l2ctlr_f = 1;
410*4882a593Smuzhiyun rkpm_bootdata_l2ctlr = rv1106_l2_config();
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
clock_suspend(void)413*4882a593Smuzhiyun static void clock_suspend(void)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun int i;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun for (i = 0; i < RV1106_CRU_GATE_CON_NUM; i++) {
418*4882a593Smuzhiyun ddr_data.cru_gate_con[i] =
419*4882a593Smuzhiyun readl_relaxed(cru_base + RV1106_CRU_GATE_CON(i));
420*4882a593Smuzhiyun writel_relaxed(0xffff0000, cru_base + RV1106_CRU_GATE_CON(i));
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun for (i = 0; i < RV1106_PMUCRU_GATE_CON_NUM; i++) {
424*4882a593Smuzhiyun ddr_data.pmucru_gate_con[i] =
425*4882a593Smuzhiyun readl_relaxed(pmucru_base + RV1106_PMUCRU_GATE_CON(i));
426*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmucru_base + RV1106_PMUCRU_GATE_CON(i));
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun for (i = 0; i < RV1106_PERICRU_GATE_CON_NUM; i++) {
430*4882a593Smuzhiyun ddr_data.pericru_gate_con[i] =
431*4882a593Smuzhiyun readl_relaxed(pericru_base + RV1106_PERICRU_GATE_CON(i));
432*4882a593Smuzhiyun writel_relaxed(0xffff0000, pericru_base + RV1106_PERICRU_GATE_CON(i));
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun for (i = 0; i < RV1106_NPUCRU_GATE_CON_NUM; i++) {
436*4882a593Smuzhiyun ddr_data.npucru_gate_con[i] =
437*4882a593Smuzhiyun readl_relaxed(npucru_base + RV1106_NPUCRU_GATE_CON(i));
438*4882a593Smuzhiyun writel_relaxed(0xffff0000, npucru_base + RV1106_NPUCRU_GATE_CON(i));
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun for (i = 0; i < RV1106_VENCCRU_GATE_CON_NUM; i++) {
442*4882a593Smuzhiyun ddr_data.venccru_gate_con[i] =
443*4882a593Smuzhiyun readl_relaxed(venccru_base + RV1106_VENCCRU_GATE_CON(i));
444*4882a593Smuzhiyun writel_relaxed(0xffff0000, venccru_base + RV1106_VENCCRU_GATE_CON(i));
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun for (i = 0; i < RV1106_VICRU_GATE_CON_NUM; i++) {
448*4882a593Smuzhiyun ddr_data.vicru_gate_con[i] =
449*4882a593Smuzhiyun readl_relaxed(vicru_base + RV1106_VICRU_GATE_CON(i));
450*4882a593Smuzhiyun writel_relaxed(0xffff0000, vicru_base + RV1106_VICRU_GATE_CON(i));
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun for (i = 0; i < RV1106_VOCRU_GATE_CON_NUM; i++) {
454*4882a593Smuzhiyun ddr_data.vocru_gate_con[i] =
455*4882a593Smuzhiyun readl_relaxed(vocru_base + RV1106_VOCRU_GATE_CON(i));
456*4882a593Smuzhiyun writel_relaxed(0xffff0000, vocru_base + RV1106_VOCRU_GATE_CON(i));
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
clock_resume(void)460*4882a593Smuzhiyun static void clock_resume(void)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun int i;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun for (i = 0; i < RV1106_CRU_GATE_CON_NUM; i++)
465*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.cru_gate_con[i]),
466*4882a593Smuzhiyun cru_base + RV1106_CRU_GATE_CON(i));
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun for (i = 0; i < RV1106_PMUCRU_GATE_CON_NUM; i++)
469*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmucru_gate_con[i]),
470*4882a593Smuzhiyun pmucru_base + RV1106_PMUCRU_GATE_CON(i));
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun for (i = 0; i < RV1106_PERICRU_GATE_CON_NUM; i++)
473*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pericru_gate_con[i]),
474*4882a593Smuzhiyun pericru_base + RV1106_PERICRU_GATE_CON(i));
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun for (i = 0; i < RV1106_NPUCRU_GATE_CON_NUM; i++)
477*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.npucru_gate_con[i]),
478*4882a593Smuzhiyun npucru_base + RV1106_NPUCRU_GATE_CON(i));
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun for (i = 0; i < RV1106_VENCCRU_GATE_CON_NUM; i++)
481*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.venccru_gate_con[i]),
482*4882a593Smuzhiyun venccru_base + RV1106_VENCCRU_GATE_CON(i));
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun for (i = 0; i < RV1106_VICRU_GATE_CON_NUM; i++)
485*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.vicru_gate_con[i]),
486*4882a593Smuzhiyun vicru_base + RV1106_VICRU_GATE_CON(i));
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun for (i = 0; i < RV1106_VOCRU_GATE_CON_NUM; i++)
489*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.vocru_gate_con[i]),
490*4882a593Smuzhiyun vocru_base + RV1106_VOCRU_GATE_CON(i));
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
pvtm_32k_config(int flag)493*4882a593Smuzhiyun static void pvtm_32k_config(int flag)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun int value;
496*4882a593Smuzhiyun int pvtm_freq_khz, pvtm_div;
497*4882a593Smuzhiyun int sleep_clk_freq_khz;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun ddr_data.pmucru_sel_con7 =
500*4882a593Smuzhiyun readl_relaxed(pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun if (flag) {
503*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0x1, 6), vigrf_base + 0x0);
504*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x4, 0xf, 0), ioc_base[0] + 0);
505*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0x1, 15),
506*4882a593Smuzhiyun pmugrf_base + RV1106_PMUGRF_SOC_CON(1));
507*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0x3, 0),
508*4882a593Smuzhiyun pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
509*4882a593Smuzhiyun } else {
510*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0, 0x3, 0),
511*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(2));
512*4882a593Smuzhiyun writel_relaxed(RV1106_PVTM_CALC_CNT,
513*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(1));
514*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0, 0x3, PVTM_START),
515*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(0));
516*4882a593Smuzhiyun dsb();
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0, 0x7, PVTM_OSC_SEL),
519*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(0));
520*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(1, 0x1, PVTM_OSC_EN),
521*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(0));
522*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(1, 0x1, PVTM_RND_SEED_EN),
523*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(0));
524*4882a593Smuzhiyun dsb();
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(1, 0x1, PVTM_START),
527*4882a593Smuzhiyun pmupvtm_base + RV1106_PVTM_CON(0));
528*4882a593Smuzhiyun dsb();
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun while (readl_relaxed(pmupvtm_base + RV1106_PVTM_STATUS(1)) < 30)
531*4882a593Smuzhiyun ;
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun dsb();
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun while (!readl_relaxed(pmupvtm_base + RV1106_PVTM_STATUS(0)) & 0x1)
536*4882a593Smuzhiyun ;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun value = (readl_relaxed(pmupvtm_base + RV1106_PVTM_STATUS(1)));
539*4882a593Smuzhiyun pvtm_freq_khz = (value * 24000 + RV1106_PVTM_CALC_CNT / 2) / RV1106_PVTM_CALC_CNT;
540*4882a593Smuzhiyun pvtm_div = (pvtm_freq_khz + 16) / 32 - 1;
541*4882a593Smuzhiyun if (pvtm_div > 0xfff)
542*4882a593Smuzhiyun pvtm_div = 0xfff;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pvtm_div),
545*4882a593Smuzhiyun pmugrf_base + RV1106_PMUGRF_SOC_CON(3));
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /* select 32k source */
548*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x2, 0x3, 0),
549*4882a593Smuzhiyun pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun sleep_clk_freq_khz = pvtm_freq_khz / (pvtm_div + 1);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun rkpm_printstr("pvtm real_freq (khz):");
554*4882a593Smuzhiyun rkpm_printhex(sleep_clk_freq_khz);
555*4882a593Smuzhiyun rkpm_printch('\n');
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
pvtm_32k_config_restore(void)559*4882a593Smuzhiyun static void pvtm_32k_config_restore(void)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmucru_sel_con7),
562*4882a593Smuzhiyun pmucru_base + RV1106_PMUCRU_CLKSEL_CON(7));
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
ddr_sleep_config(void)565*4882a593Smuzhiyun static void ddr_sleep_config(void)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun u32 val;
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun ddr_data.ddrc_pwrctrl = readl_relaxed(ddrc_base + 0x30);
570*4882a593Smuzhiyun ddr_data.ddrgrf_con1 = readl_relaxed(ddrgrf_base + RV1106_DDRGRF_CON(1));
571*4882a593Smuzhiyun ddr_data.ddrgrf_con2 = readl_relaxed(ddrgrf_base + RV1106_DDRGRF_CON(2));
572*4882a593Smuzhiyun ddr_data.ddrgrf_con3 = readl_relaxed(ddrgrf_base + RV1106_DDRGRF_CON(3));
573*4882a593Smuzhiyun ddr_data.ddrc_dfilpcfg0 = readl_relaxed(ddrc_base + 0x198);
574*4882a593Smuzhiyun ddr_data.pmugrf_soc_con0 = readl_relaxed(pmugrf_base + RV1106_PMUGRF_SOC_CON(0));
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun val = readl_relaxed(ddrc_base + 0x30);
577*4882a593Smuzhiyun writel_relaxed(val & ~(BIT(0) | BIT(1)), ddrc_base + 0x30);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* disable ddr auto gt */
580*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x12, 0x1f, 0), ddrgrf_base + RV1106_DDRGRF_CON(1));
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x3ff, 0x3ff, 0), ddrgrf_base + RV1106_DDRGRF_CON(2));
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /* ddr low power request by pmu */
585*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x3, 0x3, 8), ddrgrf_base + RV1106_DDRGRF_CON(3));
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun while ((readl_relaxed(ddrc_base + 0x4) & 0x7) != 0x1)
588*4882a593Smuzhiyun continue;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun val = readl_relaxed(ddrc_base + 0x198) & ~(0xf << 12 | 0xf << 4);
591*4882a593Smuzhiyun val |= (0xa << 12 | 0xa << 4);
592*4882a593Smuzhiyun writel_relaxed(val, ddrc_base + 0x198);
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun val = readl_relaxed(ddrc_base + 0x198) | BIT(8) | BIT(0);
595*4882a593Smuzhiyun writel_relaxed(val, ddrc_base + 0x198);
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun /* ddr io ret by pmu */
598*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x0, 0x7, 9), pmugrf_base + RV1106_PMUGRF_SOC_CON(0));
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
ddr_sleep_config_restore(void)601*4882a593Smuzhiyun static void ddr_sleep_config_restore(void)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.ddrgrf_con3),
604*4882a593Smuzhiyun ddrgrf_base + RV1106_DDRGRF_CON(3));
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
pmu_sleep_config(void)607*4882a593Smuzhiyun static void pmu_sleep_config(void)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun u32 clk_freq_khz = 32;
610*4882a593Smuzhiyun u32 pmu_wkup_con, pmu_pwr_con, pmu_scu_con, pmu_ddr_con;
611*4882a593Smuzhiyun u32 pmu_bus_idle_con, pmu_cru_con[2], pmu_pll_con;
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun ddr_data.pmugrf_soc_con1 = readl_relaxed(pmugrf_base + RV1106_PMUGRF_SOC_CON(1));
614*4882a593Smuzhiyun ddr_data.pmugrf_soc_con4 = readl_relaxed(pmugrf_base + RV1106_PMUGRF_SOC_CON(4));
615*4882a593Smuzhiyun ddr_data.pmugrf_soc_con5 = readl_relaxed(pmugrf_base + RV1106_PMUGRF_SOC_CON(5));
616*4882a593Smuzhiyun ddr_data.ioc1_1a_iomux_l = readl_relaxed(ioc_base[1] + 0);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun pmu_wkup_con =
619*4882a593Smuzhiyun /* BIT(RV1106_PMU_WAKEUP_TIMEROUT_EN) | */
620*4882a593Smuzhiyun /* BIT(RV1106_PMU_WAKEUP_CPU_INT_EN) | */
621*4882a593Smuzhiyun BIT(RV1106_PMU_WAKEUP_GPIO_INT_EN) |
622*4882a593Smuzhiyun 0;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun pmu_pwr_con =
625*4882a593Smuzhiyun BIT(RV1106_PMU_PWRMODE_EN) |
626*4882a593Smuzhiyun /* BIT(RV1106_PMU_BUS_BYPASS) | */
627*4882a593Smuzhiyun /* BIT(RV1106_PMU_DDR_BYPASS) | */
628*4882a593Smuzhiyun /* BIT(RV1106_PMU_CRU_BYPASS) | */
629*4882a593Smuzhiyun 0;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun pmu_scu_con =
632*4882a593Smuzhiyun BIT(RV1106_PMU_SCU_INT_MASK_ENA) |
633*4882a593Smuzhiyun BIT(RV1106_PMU_CPU_INT_MASK_ENA) |
634*4882a593Smuzhiyun 0;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun pmu_bus_idle_con =
637*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_MSCH) |
638*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_DDR) |
639*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_NPU) |
640*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_NPU_ACLK) |
641*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_VI) |
642*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_VO) |
643*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_PERI) |
644*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_CRU) |
645*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_CPU) |
646*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_VENC_COM) |
647*4882a593Smuzhiyun BIT(RV1106_PMU_IDLE_REQ_VEPU) |
648*4882a593Smuzhiyun 0;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun pmu_cru_con[0] =
651*4882a593Smuzhiyun BIT(RV1106_PMU_ALIVE_32K_ENA) |
652*4882a593Smuzhiyun BIT(RV1106_PMU_OSC_DIS_ENA) |
653*4882a593Smuzhiyun BIT(RV1106_PMU_WAKEUP_RST_ENA) |
654*4882a593Smuzhiyun BIT(RV1106_PMU_INPUT_CLAMP_ENA) |
655*4882a593Smuzhiyun /* BIT(RV1106_PMU_ALIVE_OSC_ENA) | */
656*4882a593Smuzhiyun BIT(RV1106_PMU_POWER_OFF_ENA) |
657*4882a593Smuzhiyun 0;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun pmu_cru_con[1] =
660*4882a593Smuzhiyun /* BIT(RV1106_PMU_VI_CLK_SRC_GATE_ENA) | */
661*4882a593Smuzhiyun /* BIT(RV1106_PMU_VO_CLK_SRC_GATE_ENA) | */
662*4882a593Smuzhiyun /* BIT(RV1106_PMU_VENC_CLK_SRC_GATE_ENA) | */
663*4882a593Smuzhiyun /* BIT(RV1106_PMU_NPU_CLK_SRC_GATE_ENA) | */
664*4882a593Smuzhiyun /* BIT(RV1106_PMU_DDR_CLK_SRC_CATE_ENA) | */
665*4882a593Smuzhiyun /* BIT(RV1106_PMU_PERI_CLK_SRC_GATE_ENA) | */
666*4882a593Smuzhiyun /* BIT(RV1106_PMU_CORE_CLK_SRC_GATE_ENA) | */
667*4882a593Smuzhiyun /* BIT(RV1106_PMU_CRU_CLK_SRC_GATE_ENA) | */
668*4882a593Smuzhiyun 0;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun pmu_ddr_con =
671*4882a593Smuzhiyun BIT(RV1106_PMU_DDR_SREF_C_ENA) |
672*4882a593Smuzhiyun #if !RV1106_WAKEUP_TO_SYSTEM_RESET
673*4882a593Smuzhiyun BIT(RV1106_PMU_DDRIO_RET_ENA) |
674*4882a593Smuzhiyun #endif
675*4882a593Smuzhiyun BIT(RV1106_PMU_DDRCTL_C_AUTO_GATING_ENA) |
676*4882a593Smuzhiyun BIT(RV1106_PMU_MSCH_AUTO_GATING_ENA) |
677*4882a593Smuzhiyun BIT(RV1106_PMU_DDR_SREF_A_ENA) |
678*4882a593Smuzhiyun BIT(RV1106_PMU_DDRCTL_A_AUTO_GATING_ENA) |
679*4882a593Smuzhiyun 0;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun pmu_pll_con =
682*4882a593Smuzhiyun BIT(RV1106_PMU_APLL_PD_ENA) |
683*4882a593Smuzhiyun BIT(RV1106_PMU_DPLL_PD_ENA) |
684*4882a593Smuzhiyun BIT(RV1106_PMU_CPLL_PD_ENA) |
685*4882a593Smuzhiyun BIT(RV1106_PMU_GPLL_PD_ENA) |
686*4882a593Smuzhiyun 0;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /* pmic_sleep */
689*4882a593Smuzhiyun /* gpio0_a3 activelow, gpio0_a4 active high */
690*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x4, 0x7, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1));
691*4882a593Smuzhiyun /* select sleep func */
692*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0x1, 0), pmugrf_base + RV1106_PMUGRF_SOC_CON(1));
693*4882a593Smuzhiyun /* gpio0_a3 iomux */
694*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 12), ioc_base[0] + 0);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun /* pmu_debug */
697*4882a593Smuzhiyun writel_relaxed(0xffffff01, pmu_base + RV1106_PMU_INFO_TX_CON);
698*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0x1, 0xf, 4), ioc_base[1] + 0);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun /* pmu count */
701*4882a593Smuzhiyun writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_OSC_STABLE_CNT);
702*4882a593Smuzhiyun writel_relaxed(clk_freq_khz * 32, pmu_base + RV1106_PMU_PMIC_STABLE_CNT);
703*4882a593Smuzhiyun writel_relaxed(clk_freq_khz * 3000, pmu_base + RV1106_PMU_WAKEUP_TIMEOUT_CNT);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* Pmu's clk has switched to 24M back When pmu FSM counts
706*4882a593Smuzhiyun * the follow counters, so we should use 24M to calculate
707*4882a593Smuzhiyun * these counters.
708*4882a593Smuzhiyun */
709*4882a593Smuzhiyun writel_relaxed(24000 * 2, pmu_base + RV1106_PMU_WAKEUP_RSTCLR_CNT);
710*4882a593Smuzhiyun writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PLL_LOCK_CNT);
711*4882a593Smuzhiyun writel_relaxed(24000 * 5, pmu_base + RV1106_PMU_PWM_SWITCH_CNT);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun /* pmu reset hold */
714*4882a593Smuzhiyun writel_relaxed(0xffffffff, pmugrf_base + RV1106_PMUGRF_SOC_CON(4));
715*4882a593Smuzhiyun writel_relaxed(0xffffff47, pmugrf_base + RV1106_PMUGRF_SOC_CON(5));
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun writel_relaxed(0x00010001, pmu_base + RV1106_PMU_INT_MASK_CON);
718*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_scu_con), pmu_base + RV1106_PMU_SCU_PWR_CON);
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_cru_con[0]), pmu_base + RV1106_PMU_CRU_PWR_CON0);
721*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_cru_con[1]), pmu_base + RV1106_PMU_CRU_PWR_CON1);
722*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_bus_idle_con), pmu_base + RV1106_PMU_BIU_IDLE_CON);
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_ddr_con), pmu_base + RV1106_PMU_DDR_PWR_CON);
725*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_pll_con), pmu_base + RV1106_PMU_PLLPD_CON);
726*4882a593Smuzhiyun writel_relaxed(pmu_wkup_con, pmu_base + RV1106_PMU_WAKEUP_INT_CON);
727*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(pmu_pwr_con), pmu_base + RV1106_PMU_PWR_CON);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun #if RV1106_WAKEUP_TO_SYSTEM_RESET
730*4882a593Smuzhiyun writel_relaxed(0, pmugrf_base + RV1106_PMUGRF_OS_REG(9));
731*4882a593Smuzhiyun /* Use PMUGRF_OS_REG10 to save wakeup source */
732*4882a593Smuzhiyun writel_relaxed(0, pmugrf_base + RV1106_PMUGRF_OS_REG(10));
733*4882a593Smuzhiyun #else
734*4882a593Smuzhiyun writel_relaxed(PMU_SUSPEND_MAGIC, pmugrf_base + RV1106_PMUGRF_OS_REG(9));
735*4882a593Smuzhiyun #endif
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun
pmu_sleep_restore(void)738*4882a593Smuzhiyun static void pmu_sleep_restore(void)
739*4882a593Smuzhiyun {
740*4882a593Smuzhiyun ddr_data.pmu_wkup_int_st = readl_relaxed(pmu_base + RV1106_PMU_WAKEUP_INT_ST);
741*4882a593Smuzhiyun ddr_data.gpio0_int_st = readl_relaxed(gpio_base[0] + RV1106_GPIO_INT_STATUS);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_INFO_TX_CON);
744*4882a593Smuzhiyun writel_relaxed(0x00010000, pmu_base + RV1106_PMU_INT_MASK_CON);
745*4882a593Smuzhiyun writel_relaxed(0x00000000, pmu_base + RV1106_PMU_WAKEUP_INT_CON);
746*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_PWR_CON);
747*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_BIU_IDLE_CON);
748*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_DDR_PWR_CON);
749*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_SCU_PWR_CON);
750*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_PLLPD_CON);
751*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_CRU_PWR_CON0);
752*4882a593Smuzhiyun writel_relaxed(0xffff0000, pmu_base + RV1106_PMU_CRU_PWR_CON1);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.ioc1_1a_iomux_l),
755*4882a593Smuzhiyun ioc_base[1] + 0);
756*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmugrf_soc_con1),
757*4882a593Smuzhiyun pmugrf_base + RV1106_PMUGRF_SOC_CON(1));
758*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmugrf_soc_con4),
759*4882a593Smuzhiyun pmugrf_base + RV1106_PMUGRF_SOC_CON(4));
760*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.pmugrf_soc_con5),
761*4882a593Smuzhiyun pmugrf_base + RV1106_PMUGRF_SOC_CON(5));
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
soc_sleep_config(void)764*4882a593Smuzhiyun static void soc_sleep_config(void)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun ddr_data.ioc0_1a_iomux_l = readl_relaxed(ioc_base[0] + 0);
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun rkpm_printch('a');
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun pvtm_32k_config(0);
771*4882a593Smuzhiyun rkpm_printch('b');
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun ddr_sleep_config();
774*4882a593Smuzhiyun rkpm_printch('c');
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun pmu_sleep_config();
777*4882a593Smuzhiyun rkpm_printch('d');
778*4882a593Smuzhiyun }
779*4882a593Smuzhiyun
soc_sleep_restore(void)780*4882a593Smuzhiyun static void soc_sleep_restore(void)
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun rkpm_printch('d');
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun pmu_sleep_restore();
785*4882a593Smuzhiyun rkpm_printch('c');
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun ddr_sleep_config_restore();
788*4882a593Smuzhiyun rkpm_printch('b');
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun pvtm_32k_config_restore();
791*4882a593Smuzhiyun rkpm_printch('a');
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.ioc0_1a_iomux_l),
794*4882a593Smuzhiyun ioc_base[0] + 0);
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
plls_suspend(void)797*4882a593Smuzhiyun static void plls_suspend(void)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun
plls_resume(void)801*4882a593Smuzhiyun static void plls_resume(void)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun
gpio0_set_iomux(u32 pin_id,u32 func)805*4882a593Smuzhiyun static void gpio0_set_iomux(u32 pin_id, u32 func)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun u32 sft = (pin_id % 4) << 2;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun if (pin_id < 4)
810*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(func, 0xf, sft), ioc_base[0] + 0);
811*4882a593Smuzhiyun else
812*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(func, 0xf, sft), ioc_base[0] + 4);
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun
gpio0_set_pull(u32 pin_id,int pull)815*4882a593Smuzhiyun static void gpio0_set_pull(u32 pin_id, int pull)
816*4882a593Smuzhiyun {
817*4882a593Smuzhiyun u32 sft = (pin_id % 8) << 1;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(pull, 0x3, sft), ioc_base[0] + 0x38);
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
gpio0_set_direct(u32 pin_id,int out)822*4882a593Smuzhiyun static void gpio0_set_direct(u32 pin_id, int out)
823*4882a593Smuzhiyun {
824*4882a593Smuzhiyun u32 sft = (pin_id % 16);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun if (pin_id < 16)
827*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(out, 0x1, sft),
828*4882a593Smuzhiyun gpio_base[0] + RV1106_GPIO_SWPORT_DDR_L);
829*4882a593Smuzhiyun else
830*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(out, 0x1, sft),
831*4882a593Smuzhiyun gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H);
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
gpio_config(void)834*4882a593Smuzhiyun static void gpio_config(void)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun ddr_data.gpio0a_iomux_l = readl_relaxed(ioc_base[0] + 0);
837*4882a593Smuzhiyun ddr_data.gpio0a_iomux_h = readl_relaxed(ioc_base[0] + 0x4);
838*4882a593Smuzhiyun ddr_data.gpio0a0_pull = readl_relaxed(ioc_base[0] + 0x38);
839*4882a593Smuzhiyun ddr_data.gpio0_ddr_l = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_L);
840*4882a593Smuzhiyun ddr_data.gpio0_ddr_h = readl_relaxed(gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H);
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun /* gpio0_a0, input, pulldown */
843*4882a593Smuzhiyun gpio0_set_iomux(0, 0);
844*4882a593Smuzhiyun gpio0_set_pull(0, RV1106_GPIO_PULL_DOWN);
845*4882a593Smuzhiyun gpio0_set_direct(0, 0);
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun #ifdef RV1106_GPIO0_A1_LOWPOWER
848*4882a593Smuzhiyun /* gpio0_a1, input, pulldown */
849*4882a593Smuzhiyun gpio0_set_iomux(1, 0);
850*4882a593Smuzhiyun gpio0_set_pull(1, RV1106_GPIO_PULL_DOWN);
851*4882a593Smuzhiyun gpio0_set_direct(1, 0);
852*4882a593Smuzhiyun #endif
853*4882a593Smuzhiyun /* gpio0_a2, input, pulldown */
854*4882a593Smuzhiyun gpio0_set_iomux(2, 0);
855*4882a593Smuzhiyun gpio0_set_pull(2, RV1106_GPIO_PULL_DOWN);
856*4882a593Smuzhiyun gpio0_set_direct(2, 0);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun /* gpio0_a3, pullnone */
859*4882a593Smuzhiyun gpio0_set_pull(3, RV1106_GPIO_PULL_NONE);
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun /* gpio0_a4, input, pulldown */
862*4882a593Smuzhiyun gpio0_set_iomux(4, 0);
863*4882a593Smuzhiyun gpio0_set_pull(4, RV1106_GPIO_PULL_DOWN);
864*4882a593Smuzhiyun gpio0_set_direct(4, 0);
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun /* gpio0_a5, input, pullnone */
867*4882a593Smuzhiyun gpio0_set_iomux(5, 0);
868*4882a593Smuzhiyun gpio0_set_pull(5, RV1106_GPIO_PULL_NONE);
869*4882a593Smuzhiyun gpio0_set_direct(5, 0);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun /* gpio0_a6, input, pullnone */
872*4882a593Smuzhiyun gpio0_set_iomux(6, 0);
873*4882a593Smuzhiyun gpio0_set_pull(6, RV1106_GPIO_PULL_NONE);
874*4882a593Smuzhiyun gpio0_set_direct(6, 0);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
gpio_restore(void)877*4882a593Smuzhiyun static void gpio_restore(void)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l), ioc_base[0] + 0);
880*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h), ioc_base[0] + 0x4);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0a0_pull), ioc_base[0] + 0x38);
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0_ddr_l),
885*4882a593Smuzhiyun gpio_base[0] + RV1106_GPIO_SWPORT_DDR_L);
886*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(ddr_data.gpio0_ddr_h),
887*4882a593Smuzhiyun gpio_base[0] + RV1106_GPIO_SWPORT_DDR_H);
888*4882a593Smuzhiyun }
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun static struct uart_debug_ctx debug_port_save;
891*4882a593Smuzhiyun static u32 cru_mode;
892*4882a593Smuzhiyun
vd_log_regs_save(void)893*4882a593Smuzhiyun static void vd_log_regs_save(void)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun cru_mode = readl_relaxed(cru_base + 0x280);
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun rkpm_printch('a');
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun gic400_save();
900*4882a593Smuzhiyun rkpm_printch('b');
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun rkpm_reg_rgn_save(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns));
903*4882a593Smuzhiyun rkpm_printch('c');
904*4882a593Smuzhiyun rkpm_reg_rgn_save(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns));
905*4882a593Smuzhiyun rkpm_printch('d');
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun rkpm_uart_debug_save(uartdbg_base, &debug_port_save);
908*4882a593Smuzhiyun rkpm_printch('e');
909*4882a593Smuzhiyun }
910*4882a593Smuzhiyun
vd_log_regs_restore(void)911*4882a593Smuzhiyun static void vd_log_regs_restore(void)
912*4882a593Smuzhiyun {
913*4882a593Smuzhiyun rkpm_uart_debug_restore(uartdbg_base, &debug_port_save);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun /* slow mode */
916*4882a593Smuzhiyun writel_relaxed(0x003f0000, cru_base + 0x280);
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun rkpm_reg_rgn_restore(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns));
919*4882a593Smuzhiyun rkpm_reg_rgn_restore(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns));
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* wait lock */
922*4882a593Smuzhiyun pm_pll_wait_lock(RV1106_APLL_ID);
923*4882a593Smuzhiyun pm_pll_wait_lock(RV1106_CPLL_ID);
924*4882a593Smuzhiyun pm_pll_wait_lock(RV1106_GPLL_ID);
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun /* restore mode */
927*4882a593Smuzhiyun writel_relaxed(WITH_16BITS_WMSK(cru_mode), cru_base + 0x280);
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun gic400_restore();
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun
rkpm_reg_rgns_init(void)932*4882a593Smuzhiyun static void rkpm_reg_rgns_init(void)
933*4882a593Smuzhiyun {
934*4882a593Smuzhiyun rkpm_alloc_region_mem(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns));
935*4882a593Smuzhiyun rkpm_alloc_region_mem(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns));
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
rkpm_regs_rgn_dump(void)938*4882a593Smuzhiyun static void rkpm_regs_rgn_dump(void)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun return;
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun rkpm_dump_reg_rgns(vd_core_reg_rgns, ARRAY_SIZE(vd_core_reg_rgns));
943*4882a593Smuzhiyun rkpm_dump_reg_rgns(vd_log_reg_rgns, ARRAY_SIZE(vd_log_reg_rgns));
944*4882a593Smuzhiyun }
945*4882a593Smuzhiyun
rockchip_lpmode_enter(unsigned long arg)946*4882a593Smuzhiyun static int rockchip_lpmode_enter(unsigned long arg)
947*4882a593Smuzhiyun {
948*4882a593Smuzhiyun flush_cache_all();
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun cpu_do_idle();
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun pr_err("%s: Failed to suspend\n", __func__);
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun return 1;
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun
rv1106_suspend_enter(suspend_state_t state)957*4882a593Smuzhiyun static int rv1106_suspend_enter(suspend_state_t state)
958*4882a593Smuzhiyun {
959*4882a593Smuzhiyun rkpm_printstr("rv1106 enter sleep\n");
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun local_fiq_disable();
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun rv1106_dbg_irq_prepare();
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun rkpm_printch('-');
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun clock_suspend();
968*4882a593Smuzhiyun rkpm_printch('0');
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun soc_sleep_config();
971*4882a593Smuzhiyun rkpm_printch('1');
972*4882a593Smuzhiyun
973*4882a593Smuzhiyun plls_suspend();
974*4882a593Smuzhiyun rkpm_printch('2');
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun gpio_config();
977*4882a593Smuzhiyun rkpm_printch('3');
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun vd_log_regs_save();
980*4882a593Smuzhiyun rkpm_regs_rgn_dump();
981*4882a593Smuzhiyun rkpm_printch('4');
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun rkpm_printstr("-WFI-");
984*4882a593Smuzhiyun cpu_suspend(0, rockchip_lpmode_enter);
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun rkpm_printch('4');
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun vd_log_regs_restore();
989*4882a593Smuzhiyun rkpm_printch('3');
990*4882a593Smuzhiyun rkpm_regs_rgn_dump();
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun gpio_restore();
993*4882a593Smuzhiyun rkpm_printch('2');
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun plls_resume();
996*4882a593Smuzhiyun rkpm_printch('1');
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun soc_sleep_restore();
999*4882a593Smuzhiyun rkpm_printch('0');
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun clock_resume();
1002*4882a593Smuzhiyun rkpm_printch('-');
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun fiq_glue_resume();
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun rv1106_dbg_irq_finish();
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun local_fiq_enable();
1009*4882a593Smuzhiyun rkpm_printstr("rv1106 exit sleep\n");
1010*4882a593Smuzhiyun
1011*4882a593Smuzhiyun return 0;
1012*4882a593Smuzhiyun }
1013*4882a593Smuzhiyun
rv1106_suspend_init(struct device_node * np)1014*4882a593Smuzhiyun static int __init rv1106_suspend_init(struct device_node *np)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun void __iomem *dev_reg_base;
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun dev_reg_base = ioremap(RV1106_DEV_REG_BASE, RV1106_DEV_REG_SIZE);
1019*4882a593Smuzhiyun if (dev_reg_base)
1020*4882a593Smuzhiyun pr_info("%s map dev_reg 0x%x -> 0x%x\n",
1021*4882a593Smuzhiyun __func__, RV1106_DEV_REG_BASE, (u32)dev_reg_base);
1022*4882a593Smuzhiyun else
1023*4882a593Smuzhiyun pr_err("%s: can't map dev_reg(0x%x)\n", __func__, RV1106_DEV_REG_BASE);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun gicd_base = dev_reg_base + RV1106_GIC_OFFSET + 0x1000;
1026*4882a593Smuzhiyun gicc_base = dev_reg_base + RV1106_GIC_OFFSET + 0x2000;
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun firewall_ddr_base = dev_reg_base + RV1106_FW_DDR_OFFSET;
1029*4882a593Smuzhiyun firewall_syssram_base = dev_reg_base + RV1106_FW_SRAM_OFFSET;
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun nstimer_base = dev_reg_base + RV1106_NSTIMER_OFFSET;
1032*4882a593Smuzhiyun stimer_base = dev_reg_base + RV1106_STIMER_OFFSET;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun pmu_base = dev_reg_base + RV1106_PMU_OFFSET;
1035*4882a593Smuzhiyun uartdbg_base = dev_reg_base + RV1106_UART2_OFFSET;
1036*4882a593Smuzhiyun pmupvtm_base = dev_reg_base + RV1106_PMUPVTM_OFFSET;
1037*4882a593Smuzhiyun pmusgrf_base = dev_reg_base + RV1106_PMUSGRF_OFFSET;
1038*4882a593Smuzhiyun ddrc_base = dev_reg_base + RV1106_DDRC_OFFSET;
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun perigrf_base = dev_reg_base + RV1106_PERIGRF_OFFSET;
1041*4882a593Smuzhiyun vencgrf_base = dev_reg_base + RV1106_VENCGRF_OFFSET;
1042*4882a593Smuzhiyun npugrf_base = dev_reg_base + RV1106_NPUGRF_OFFSET;
1043*4882a593Smuzhiyun pmugrf_base = dev_reg_base + RV1106_PMUGRF_OFFSET;
1044*4882a593Smuzhiyun ddrgrf_base = dev_reg_base + RV1106_DDRGRF_OFFSET;
1045*4882a593Smuzhiyun coregrf_base = dev_reg_base + RV1106_COREGRF_OFFSET;
1046*4882a593Smuzhiyun vigrf_base = dev_reg_base + RV1106_VIGRF_OFFSET;
1047*4882a593Smuzhiyun vogrf_base = dev_reg_base + RV1106_VOGRF_OFFSET;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun perisgrf_base = dev_reg_base + RV1106_PERISGRF_OFFSET;
1050*4882a593Smuzhiyun visgrf_base = dev_reg_base + RV1106_VIGRF_OFFSET;
1051*4882a593Smuzhiyun npusgrf_base = dev_reg_base + RV1106_NPUSGRF_OFFSET;
1052*4882a593Smuzhiyun coresgrf_base = dev_reg_base + RV1106_CORESGRF_OFFSET;
1053*4882a593Smuzhiyun vencsgrf_base = dev_reg_base + RV1106_VENCSGRF_OFFSET;
1054*4882a593Smuzhiyun vosgrf_base = dev_reg_base + RV1106_VOSGRF_OFFSET;
1055*4882a593Smuzhiyun pmusgrf_base = dev_reg_base + RV1106_PMUSGRF_OFFSET;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun pmucru_base = dev_reg_base + RV1106_PMUCRU_OFFSET;
1058*4882a593Smuzhiyun cru_base = dev_reg_base + RV1106_CRU_OFFSET;
1059*4882a593Smuzhiyun pericru_base = dev_reg_base + RV1106_PERICRU_OFFSET;
1060*4882a593Smuzhiyun vicru_base = dev_reg_base + RV1106_VICRU_OFFSET;
1061*4882a593Smuzhiyun npucru_base = dev_reg_base + RV1106_NPUCRU_OFFSET;
1062*4882a593Smuzhiyun corecru_base = dev_reg_base + RV1106_CORECRU_OFFSET;
1063*4882a593Smuzhiyun venccru_base = dev_reg_base + RV1106_VENCCRU_OFFSET;
1064*4882a593Smuzhiyun vocru_base = dev_reg_base + RV1106_VOCRU_OFFSET;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun ioc_base[0] = dev_reg_base + RV1106_GPIO0IOC_OFFSET;
1067*4882a593Smuzhiyun ioc_base[1] = dev_reg_base + RV1106_GPIO1IOC_OFFSET;
1068*4882a593Smuzhiyun ioc_base[2] = dev_reg_base + RV1106_GPIO2IOC_OFFSET;
1069*4882a593Smuzhiyun ioc_base[3] = dev_reg_base + RV1106_GPIO3IOC_OFFSET;
1070*4882a593Smuzhiyun ioc_base[4] = dev_reg_base + RV1106_GPIO4IOC_OFFSET;
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun gpio_base[0] = dev_reg_base + RV1106_GPIO0_OFFSET;
1073*4882a593Smuzhiyun gpio_base[1] = dev_reg_base + RV1106_GPIO1_OFFSET;
1074*4882a593Smuzhiyun gpio_base[2] = dev_reg_base + RV1106_GPIO2_OFFSET;
1075*4882a593Smuzhiyun gpio_base[3] = dev_reg_base + RV1106_GPIO3_OFFSET;
1076*4882a593Smuzhiyun gpio_base[4] = dev_reg_base + RV1106_GPIO4_OFFSET;
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun rv1106_bootram_base = dev_reg_base + RV1106_PMUSRAM_OFFSET;
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun rv1106_config_bootdata();
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun /* copy resume code and data to bootsram */
1083*4882a593Smuzhiyun memcpy(rv1106_bootram_base, rockchip_slp_cpu_resume,
1084*4882a593Smuzhiyun rv1106_bootram_sz + 0x50);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun /* remap */
1087*4882a593Smuzhiyun #if RV1106_WAKEUP_TO_SYSTEM_RESET
1088*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(1, 0x1, 10), pmusgrf_base + RV1106_PMUSGRF_SOC_CON(1));
1089*4882a593Smuzhiyun #else
1090*4882a593Smuzhiyun writel_relaxed(BITS_WITH_WMASK(0, 0x1, 10), pmusgrf_base + RV1106_PMUSGRF_SOC_CON(1));
1091*4882a593Smuzhiyun #endif
1092*4882a593Smuzhiyun /* biu auto con */
1093*4882a593Smuzhiyun writel_relaxed(0x07ff07ff, pmu_base + RV1106_PMU_BIU_AUTO_CON);
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun rkpm_region_mem_init(RV1106_PM_REG_REGION_MEM_SIZE);
1096*4882a593Smuzhiyun rkpm_reg_rgns_init();
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun return 0;
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun static const struct platform_suspend_ops rv1106_suspend_ops = {
1102*4882a593Smuzhiyun .enter = rv1106_suspend_enter,
1103*4882a593Smuzhiyun .valid = suspend_valid_only_mem,
1104*4882a593Smuzhiyun };
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun static const struct rockchip_pm_data rv1106_pm_data __initconst = {
1107*4882a593Smuzhiyun .ops = &rv1106_suspend_ops,
1108*4882a593Smuzhiyun .init = rv1106_suspend_init,
1109*4882a593Smuzhiyun };
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun /****************************************************************************/
1112*4882a593Smuzhiyun static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = {
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun .compatible = "rockchip,rv1106-pmu",
1115*4882a593Smuzhiyun .data = &rv1106_pm_data,
1116*4882a593Smuzhiyun },
1117*4882a593Smuzhiyun { /* sentinel */ },
1118*4882a593Smuzhiyun };
1119*4882a593Smuzhiyun
rockchip_suspend_init(void)1120*4882a593Smuzhiyun void __init rockchip_suspend_init(void)
1121*4882a593Smuzhiyun {
1122*4882a593Smuzhiyun const struct rockchip_pm_data *pm_data;
1123*4882a593Smuzhiyun const struct of_device_id *match;
1124*4882a593Smuzhiyun struct device_node *np;
1125*4882a593Smuzhiyun int ret;
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids,
1128*4882a593Smuzhiyun &match);
1129*4882a593Smuzhiyun if (!match) {
1130*4882a593Smuzhiyun pr_err("Failed to find PMU node\n");
1131*4882a593Smuzhiyun return;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun pm_data = (struct rockchip_pm_data *)match->data;
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun if (pm_data->init) {
1136*4882a593Smuzhiyun ret = pm_data->init(np);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun if (ret) {
1139*4882a593Smuzhiyun pr_err("%s: matches init error %d\n", __func__, ret);
1140*4882a593Smuzhiyun return;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun suspend_set_ops(pm_data->ops);
1145*4882a593Smuzhiyun }
1146