1 #include <asm/arch/sci_types.h>
2 #include <asm/arch/adi_hal_internal.h>
3 #include <asm/arch/chip_drv_common_io.h>
4 #include <asm/arch/sprd_reg.h>
5 #include <asm/arch/low_power.h>
7 //#define LDO_SLP_DEBUG
9 typedef struct slp_test {
15 void test_store (test_t *buf)
19 buf[i].reg = ANA_REG_GLB_PWR_WR_PROT_VALUE;
20 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_WR_PROT_VALUE);
22 buf[i].reg = ANA_REG_GLB_LDO_DCDC_PD;
23 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_LDO_DCDC_PD);
25 buf[i].reg = ANA_REG_GLB_DCDC_SLP_CTRL0;
26 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_DCDC_SLP_CTRL0);
28 buf[i].reg = ANA_REG_GLB_PWR_SLP_CTRL0;
29 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_SLP_CTRL0);
31 buf[i].reg = ANA_REG_GLB_PWR_SLP_CTRL1;
32 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_SLP_CTRL1);
34 buf[i].reg = ANA_REG_GLB_PWR_SLP_CTRL2;
35 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_SLP_CTRL2);
37 buf[i].reg = ANA_REG_GLB_PWR_SLP_CTRL3;
38 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_SLP_CTRL3);
40 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN0;
41 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_XTL_EN0);
43 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN1;
44 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_XTL_EN1);
46 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN2;
47 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_XTL_EN2);
49 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN3;
50 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_XTL_EN3);
52 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN4;
53 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_PWR_XTL_EN4);
55 buf[i].reg = REG_PMU_APB_XTL0_REL_CFG;
56 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTL0_REL_CFG);
58 buf[i].reg = REG_PMU_APB_XTL1_REL_CFG;
59 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTL1_REL_CFG);
61 buf[i].reg = REG_PMU_APB_XTL2_REL_CFG;
62 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTL2_REL_CFG);
64 buf[i].reg = REG_PMU_APB_XTLBUF0_REL_CFG;
65 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTLBUF0_REL_CFG);
67 buf[i].reg = REG_PMU_APB_XTLBUF1_REL_CFG;
68 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTLBUF1_REL_CFG);
70 buf[i].reg = REG_PMU_APB_MPLL_REL_CFG;
71 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_MPLL_REL_CFG);
73 buf[i].reg = REG_PMU_APB_DPLL_REL_CFG;
74 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_DPLL_REL_CFG);
76 buf[i].reg = REG_PMU_APB_TDPLL_REL_CFG;
77 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_TDPLL_REL_CFG);
79 buf[i].reg = REG_PMU_APB_WPLL_REL_CFG;
80 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_WPLL_REL_CFG);
82 buf[i].reg = ANA_REG_GLB_PWR_XTL_EN3;
83 buf[i++].val = CHIP_REG_GET(ANA_REG_GLB_PWR_XTL_EN3);
85 buf[i].reg = REG_PMU_APB_CPLL_REL_CFG;
86 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_CPLL_REL_CFG);
88 buf[i].reg = REG_PMU_APB_WIFIPLL1_REL_CFG;
89 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_WIFIPLL1_REL_CFG);
91 buf[i].reg = REG_PMU_APB_WIFIPLL2_REL_CFG;
92 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_WIFIPLL2_REL_CFG);
94 buf[i].reg = REG_PMU_APB_CGM_AP_EN;
95 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_CGM_AP_EN);
97 buf[i].reg = REG_PMU_APB_PD_CA7_TOP_CFG;
98 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_CA7_TOP_CFG);
100 buf[i].reg = REG_PMU_APB_PD_CA7_C0_CFG;
101 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_CA7_C0_CFG);
103 buf[i].reg = REG_PMU_APB_PD_CA7_C1_CFG;
104 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_CA7_C1_CFG);
106 buf[i].reg = REG_PMU_APB_PD_CA7_C2_CFG;
107 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_CA7_C2_CFG);
109 buf[i].reg = REG_PMU_APB_PD_CA7_C3_CFG;
110 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_CA7_C3_CFG);
112 buf[i].reg = REG_PMU_APB_PD_AP_SYS_CFG;
113 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_AP_SYS_CFG);
115 buf[i].reg = REG_PMU_APB_PD_MM_TOP_CFG;
116 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_MM_TOP_CFG);
118 buf[i].reg = REG_PMU_APB_PD_GPU_TOP_CFG;
119 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_GPU_TOP_CFG);
121 buf[i].reg = REG_PMU_APB_PD_PUB_SYS_CFG;
122 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PD_PUB_SYS_CFG);
124 buf[i].reg = REG_PMU_APB_XTL_WAIT_CNT;
125 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTL_WAIT_CNT);
127 buf[i].reg = REG_PMU_APB_XTLBUF_WAIT_CNT;
128 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_XTLBUF_WAIT_CNT);
130 buf[i].reg = REG_PMU_APB_PLL_WAIT_CNT1;
131 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PLL_WAIT_CNT1);
133 buf[i].reg = REG_PMU_APB_PLL_WAIT_CNT2;
134 buf[i++].val = CHIP_REG_GET(REG_PMU_APB_PLL_WAIT_CNT2);
136 buf[i].reg = ANA_REG_GLB_SLP_WAIT_DCDCARM;
137 buf[i++].val = ANA_REG_GET(ANA_REG_GLB_SLP_WAIT_DCDCARM);
140 buf[i].val = 0x55AA55AA;
144 static struct ldo_lowpower_cfg *gp_ldo_cfg = NULL;
145 static struct pll_cfg *gp_pll_cfg = NULL;
146 static struct shutdown_cfg *gp_shutdown_cfg = NULL;
148 /*********************************************************************
150 ** This function used to get customize information. if not get, don't running.
155 ** Date Author Operation
156 ** 2014/01/23 ypxie optimization
157 *********************************************************************/
158 void customize_low_power_init_prepare(struct ldo_lowpower_cfg *ldo,
160 struct shutdown_cfg *shutdown)
164 gp_shutdown_cfg = shutdown;
167 static void lowpower_earlyinit(void)
169 unsigned int reg_val;
171 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD,
172 BIT_DCDC_TOP_CLKF_EN|BIT_DCDC_TOP_OSC_EN);
174 ANA_REG_SET(ANA_REG_GLB_PWR_SLP_CTRL0, BIT_SLP_IO_EN);
175 ANA_REG_SET(ANA_REG_GLB_PWR_SLP_CTRL1, BIT_SLP_LDO_PD_EN);
176 ANA_REG_SET(ANA_REG_GLB_PWR_XTL_EN0, BIT_LDO_XTL_EN);
177 CHIP_REG_SET(REG_PMU_APB_CGM_AP_EN,0x1FFF81);
179 reg_val = ANA_REG_GET(ANA_REG_GLB_DCDC_SLP_CTRL0);
180 reg_val &= ~BITS_DCDC_CORE_CTL_DS_SW(7);
181 reg_val |= BITS_DCDC_CORE_CTL_DS_SW(4);
182 ANA_REG_SET(ANA_REG_GLB_DCDC_SLP_CTRL0,reg_val);
184 ANA_REG_SET(ANA_REG_GLB_SLP_WAIT_DCDCARM,0x0908);
185 /*plls wait, xtl0/1 wait, xtlbuf0/1 wait time*/
187 if (ANA_GET_CHIP_ID() != 0x2711a000) {
188 CHIP_REG_SET(REG_AON_CLK_FM_CFG,
189 //BIT_CLK_FM_PAD_SEL |
193 CHIP_REG_SET(REG_AON_APB_GPS_26M_REF_SEL,
194 //BIT_XTLBUF1_GPS_SEL |
195 BIT_XTLBUF0_GPS_SEL |
196 //BIT_GPS_26M_REF_SEL |
201 static void wr_prot_dis(void)
203 unsigned int reg_val = 0;
205 ANA_REG_SET(ANA_REG_GLB_PWR_WR_PROT_VALUE,
206 BITS_PWR_WR_PROT_VALUE(0x6e7f));
209 reg_val = (ANA_REG_GET(ANA_REG_GLB_PWR_WR_PROT_VALUE)
211 }while(reg_val == 0);
214 static void wr_prot_en(void)
216 ANA_REG_SET(ANA_REG_GLB_PWR_WR_PROT_VALUE, BITS_PWR_WR_PROT_VALUE(0));
219 static unsigned long ffs(unsigned int x)
225 while((x & (1<<i)) == 0) {
233 static unsigned long __ffs(unsigned int x)
239 static void pll_xtl_with_sys_config(struct pll_cfg *cfg, struct pll_reg_bit *pll_reg)
241 /*enable all xtl for simply config. xtlbuf0 is for ap, xtlbuf1 is for tdpll, choose!*/
242 unsigned int i = 0, j;
243 unsigned int sel_mode = 0, sel_tmp = 0;
245 if ((!cfg) || (cfg[0].pll_id == RESERVED_NUM) || (pll_reg == NULL)) {
249 /*collecting the current system mode, like TD only ..etc.*/
250 while (cfg[i].pll_id != RESERVED_NUM) {
252 while (pll_reg[j].pll_id != RESERVED_NUM) {
253 if (cfg[i].pll_id == pll_reg[j].pll_id) {
260 if (pll_reg[j].cgm_ap_reg != -1) {
261 if (cfg[i].cgm_ap_en != NO_USED) {
262 if (cfg[i].cgm_ap_en == LP_EN) {
263 CHIP_REG_OR(pll_reg[j].cgm_ap_reg, pll_reg[j].cgm_ap_reg_bitmsk);
265 else if (cfg[i].cgm_ap_en == LP_DIS){
266 CHIP_REG_AND(pll_reg[j].cgm_ap_reg, ~(pll_reg[j].cgm_ap_reg_bitmsk));
272 /* set select by ap,cp0,cp1,cp2 */
273 if (pll_reg[j].pll_sys_reg != -1) {
274 if(cfg[i].sys != NO_USED) {
275 if (cfg[i].sys & AP_SYS) {
278 if (cfg[i].sys & CP0_SYS) {
281 if (cfg[i].sys & CP1_SYS) {
284 if (cfg[i].sys & CP2_SYS) {
288 if (cfg[i].sys & REF_SYS) {
292 sel_tmp = CHIP_REG_GET(pll_reg[j].pll_sys_reg);
293 sel_tmp &= ~pll_reg[j].pll_sys_reg_bitmsk;
294 sel_tmp |= (sel_mode << __ffs(pll_reg[j].pll_sys_reg_bitmsk)
295 & pll_reg[j].pll_sys_reg_bitmsk);
297 CHIP_REG_SET(pll_reg[j].pll_sys_reg, sel_tmp);
301 if (pll_reg[j].pll_wait_reg != -1) {
302 if (cfg[i].wait != NO_USED) {
303 sel_mode = cfg[i].wait << __ffs(pll_reg[j].pll_wait_reg_bitmsk);
304 sel_mode &= pll_reg[j].pll_wait_reg_bitmsk;
306 sel_tmp = CHIP_REG_GET(pll_reg[j].pll_wait_reg);
307 sel_tmp &= ~pll_reg[j].pll_wait_reg_bitmsk;
310 CHIP_REG_SET(pll_reg[j].pll_wait_reg, sel_tmp);
318 static void pd_shutdown_config(struct shutdown_cfg *cfg,
319 struct pd_reg_bit *pd_reg)
321 /*enable all xtl for simply config. xtlbuf0 is for ap, xtlbuf1 is for tdpll, choose!*/
322 unsigned int i = 0, j;
323 unsigned int reg_value = 0;
325 if ((!cfg) || (cfg[0].pd_shutdown_id == RESERVED_NUM) || (pd_reg == NULL)) {
329 /*collecting the current system mode, like TD only ..etc.*/
330 while (cfg[i].pd_shutdown_id != RESERVED_NUM) {
332 while (pd_reg[j].pd_shutdown_id != RESERVED_NUM) {
333 if (cfg[i].pd_shutdown_id == pd_reg[j].pd_shutdown_id) {
339 if (pd_reg[j].pd_shutdown_id == RESERVED_NUM) {
343 if (pd_reg[j].pd_reg != -1) {
344 if(cfg[i].iso_on_delay != NO_USED) {
345 reg_value = cfg[i].iso_on_delay << __ffs(pd_reg[j].iso_on_delay_bitmsk);
346 CHIP_REG_AND(pd_reg[j].pd_reg, ~pd_reg[j].iso_on_delay_bitmsk);
347 CHIP_REG_OR(pd_reg[j].pd_reg, reg_value);
350 if(cfg[i].pwr_on_seq_delay != NO_USED) {//pwr_on_seq_delay
351 reg_value = cfg[i].pwr_on_seq_delay
352 << __ffs(pd_reg[j].pwr_on_seq_delay_bitmsk);
353 CHIP_REG_AND(pd_reg[j].pd_reg, ~pd_reg[j].pwr_on_seq_delay_bitmsk);
354 CHIP_REG_OR(pd_reg[j].pd_reg, reg_value);
357 if(cfg[i].pwr_on_delay != NO_USED) {//pwr_on_delay
358 reg_value = cfg[i].pwr_on_delay << __ffs(pd_reg[j].pwr_on_delay_bitmsk);
359 CHIP_REG_AND(pd_reg[j].pd_reg, ~pd_reg[j].pwr_on_delay_bitmsk);
360 CHIP_REG_OR(pd_reg[j].pd_reg,reg_value);
363 if(cfg[i].auto_shutdown != NO_USED) {
364 if(cfg[i].auto_shutdown == LP_EN) {//auto_shutdown
365 CHIP_REG_OR(pd_reg[j].pd_reg, pd_reg[j].auto_shutdown_bitmsk);
367 else if(cfg[i].auto_shutdown == LP_DIS) {
368 CHIP_REG_AND(pd_reg[j].pd_reg, ~pd_reg[j].auto_shutdown_bitmsk);
372 if(cfg[i].force_shutdown != NO_USED) {
373 if(cfg[i].force_shutdown == LP_EN) {//force_shutdown
374 CHIP_REG_OR(pd_reg[j].pd_reg, pd_reg[j].force_shutdown_bitmsk);
376 else if(cfg[i].force_shutdown == LP_DIS) {
377 CHIP_REG_AND(pd_reg[j].pd_reg, ~pd_reg[j].force_shutdown_bitmsk);
381 if(cfg[i].debug_shutdown != NO_USED) {
382 if(cfg[i].debug_shutdown == LP_EN) {//debug_shutdown
383 CHIP_REG_OR(pd_reg[j].pd_reg, pd_reg[j].debug_shutdown_bitmsk);
385 else if(cfg[i].debug_shutdown == LP_DIS) {
386 CHIP_REG_AND(pd_reg[j].pd_reg, ~(pd_reg[j].debug_shutdown_bitmsk));
394 static void ddie_pll_lowpower_init(void)
396 /*default all:xtl0/1/2 to ap, default all:xtlbuf0/1 to ap +*/
397 pll_xtl_with_sys_config(gp_pll_cfg, pll_reg_tb);
398 pd_shutdown_config(gp_shutdown_cfg, shutdown_tb);
403 static void ldo_set_sts(struct ldo_lowpower_cfg *cfg, struct ldo_reg_bit *reg)
405 if (reg->ldo_pd_reg != -1) {
406 if (cfg->ldo_pd == LP_DIS) {
407 ANA_REG_OR(reg->ldo_pd_reg, reg->ldo_pd_reg_bitmsk);
408 } else if (cfg->ldo_pd == LP_EN) {
409 ANA_REG_BIC(reg->ldo_pd_reg, reg->ldo_pd_reg_bitmsk);
414 static void ldo_set_sts_sleep(struct ldo_lowpower_cfg *cfg, struct ldo_reg_bit *reg)
416 if (cfg->status_in_sleep == SLP_PD_MODE) {
417 if (reg->ldo_pd_reg != -1) {
418 ANA_REG_OR(reg->slp_pd_reg, reg->slp_pd_reg_bitmsk);
420 if (reg->slp_lp_reg != -1) {
421 ANA_REG_BIC(reg->slp_lp_reg, reg->slp_lp_reg_bitmsk);
423 } else if (cfg->status_in_sleep == SLP_LP_MODE) {
424 if (reg->slp_pd_reg != -1) {
425 ANA_REG_BIC(reg->slp_pd_reg, reg->slp_pd_reg_bitmsk);
427 if (reg->slp_lp_reg != -1) {
428 ANA_REG_OR(reg->slp_lp_reg, reg->slp_lp_reg_bitmsk);
430 } else if (cfg->status_in_sleep == SLP_NO_MODE) {
431 if (reg->slp_pd_reg != -1) {
432 ANA_REG_BIC(reg->slp_pd_reg, reg->slp_pd_reg_bitmsk);
434 if (reg->slp_lp_reg != -1) {
435 ANA_REG_BIC(reg->slp_lp_reg, reg->slp_lp_reg_bitmsk);
440 /* ldo_id, cfg_to_xtl, cfg_to_ext_xtl,power_sts_in_sleep; */
441 static void ldo_set_xtl(struct ldo_lowpower_cfg *cfg, struct ldo_reg_bit *reg)
443 unsigned int v = 0, tmp = 0;
444 unsigned int shft = 0;
446 if (reg->xtl_reg != -1) {
447 shft = __ffs(reg->xtl_reg_bitmsk);
449 if (cfg->select_by_xtl & BY_XTL0)
451 /* no xtl1 in 7715 */
452 /*if (cfg->select_by_xtl & BY_XTL1)
454 if (cfg->select_by_xtl & BY_XTL2)
457 v &= reg->xtl_reg_bitmsk;
459 tmp = ANA_REG_GET(reg->xtl_reg);
460 tmp &= ~reg->xtl_reg_bitmsk;
463 ANA_REG_SET(reg->xtl_reg, tmp);
467 static void ldo_set_exxtl(struct ldo_lowpower_cfg *cfg, struct ldo_reg_bit *reg)
469 unsigned int v = 0, tmp = 0;
470 unsigned int shft = 0;
472 if (reg->ext_xtl_reg != -1) {
473 shft = __ffs(reg->ext_xtl_reg_bitmsk);
475 if (cfg->select_by_ext_xtl & BY_EXT_XTL0)
477 if (cfg->select_by_ext_xtl & BY_EXT_XTL1)
479 /* no xtl1 in 7715 */
480 /*if (cfg->select_by_ext_xtl & BY_EXT_XTL2)
484 v &= reg->ext_xtl_reg_bitmsk;
486 tmp = ANA_REG_GET(reg->ext_xtl_reg);
487 tmp &= ~reg->ext_xtl_reg_bitmsk;
490 ANA_REG_SET(reg->ext_xtl_reg, tmp);
494 static void adie_ldo_lowpower_init()
496 struct ldo_lowpower_cfg *ldo_cfg = gp_ldo_cfg;
497 struct ldo_reg_bit *ldo_reg = ldo_reg_tb;
498 unsigned int i = 0, j = 0;
500 if ((!ldo_cfg) || (ldo_reg == NULL))
503 while (ldo_cfg[i].ldo_id != RESERVED_NUM) {
505 while (ldo_reg[j].ldo_id != RESERVED_NUM) {
506 if (ldo_cfg[i].ldo_id == ldo_reg[j].ldo_id) {
512 if (ldo_reg[j].ldo_id == RESERVED_NUM) {
516 if (ldo_cfg[i].ldo_pd != NO_USED) {
517 ldo_set_sts(&ldo_cfg[i], &ldo_reg[j]);
519 if (ldo_cfg[i].status_in_sleep != NO_USED) {
520 ldo_set_sts_sleep(&ldo_cfg[i], &ldo_reg[j]);
522 if (ldo_cfg[i].select_by_xtl!= NO_USED) {
523 ldo_set_xtl(&ldo_cfg[i], &ldo_reg[j]);
525 if (ldo_cfg[i].select_by_ext_xtl != NO_USED) {
526 ldo_set_exxtl(&ldo_cfg[i], &ldo_reg[j]);
532 /*********************************************************************
534 ** This function used to init low power. Before running this function, must be running
535 ** customize_low_power_init_prepare().
540 ** Date Author Operation
541 ** 2014/01/23 ypxie optimization
542 *********************************************************************/
543 void low_power_init(void)
546 Every ldo LP/PD depend on AP, we can make ap select xtl_buf_en0, xtl_buf_en1,
547 xtl_buf_en2 and cp0 select xtl_buf_en0, cp1 select xtl-buf_en1, cp2 select xtl_buf_en2, so
548 ldo_x can flexiblly config to xtl0/cp0, xtl1/cp1, xtl2/cp2. But now, we can make this process
549 to simple. make xtl_buf_en0 == xtl_buf_en1 == xtl_buf_en2
550 if cp(X) is exist, slecet all xtl_Buf_en0/1/2.
553 lowpower_earlyinit();
554 ddie_pll_lowpower_init();
555 adie_ldo_lowpower_init();
558 /* used test register */