1 /******************************************************************************
2 ** File Name: ldo_drv.c *
5 ** Copyright: 2007 Spreatrum, Incoporated. All Rights Reserved. *
6 ** Description: This file defines the basic function for ldo management. *
7 ******************************************************************************/
9 /******************************************************************************
11 ** ------------------------------------------------------------------------- *
12 ** DATE NAME DESCRIPTION *
13 ** 01/09/2009 Yi.Qiu Create. *
14 ******************************************************************************/
16 /**---------------------------------------------------------------------------*
18 **---------------------------------------------------------------------------*/
22 #include <asm/arch/regs_global.h>
23 #include <asm/arch/bits.h>
24 #include <asm/arch/ldo.h>
25 #include <asm/arch/regs_ana.h>
27 #define LDO_INVALID_REG 0xFFFFFFFF
28 #define LDO_INVALID_BIT 0xFFFFFFFF
31 #define CURRENT_STATUS_INIT 0x00000001
32 #define CURRENT_STATUS_ON 0x00000002
33 #define CURRENT_STATUS_OFF 0x00000004
35 #define LDO_INVALID_REG_ADDR (0x1)
37 #define CHIP_REG_OR(reg_addr, value) (*(volatile unsigned int *)(reg_addr) |= (unsigned int)(value))
38 #define CHIP_REG_AND(reg_addr, value) (*(volatile unsigned int *)(reg_addr) &= (unsigned int)(value))
39 #define CHIP_REG_GET(reg_addr) (*(volatile unsigned int *)(reg_addr))
40 #define CHIP_REG_SET(reg_addr, value) (*(volatile unsigned int *)(reg_addr) = (unsigned int)(value))
42 #define SCI_PASSERT(condition, format...) \
45 printf("function :%s\r\n", __FUNCTION__);\
57 unsigned int bp_rst_reg;
58 unsigned int bp_rst;//bits
60 unsigned int level_reg_b0;
64 unsigned int level_reg_b1;
68 unsigned int init_level;
74 int current_volt_level;
77 struct ldo_sleep_ctl_info {
79 unsigned int ldo_sleep_reg;
85 static struct ldo_ctl_info ldo_ctl_data[] =
89 .bp_reg = ANA_LDO_PD_SET,
91 .bp_rst_reg = ANA_LDO_PD_RST,
93 .level_reg_b0 = LDO_INVALID_REG_ADDR,
96 .level_reg_b1 = LDO_INVALID_REG_ADDR,
99 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
103 .bp_reg = ANA_LDO_PD_SET,
105 .bp_rst_reg = ANA_LDO_PD_RST,
107 .level_reg_b0 = ANA_LDO_VCTL3,
110 .level_reg_b1 = ANA_LDO_VCTL3,
113 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
117 .bp_reg = ANA_LDO_PD_SET,
119 .bp_rst_reg = ANA_LDO_PD_RST,
121 .level_reg_b0 = ANA_LDO_VCTL3,
124 .level_reg_b1 = ANA_LDO_VCTL3,
127 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
131 .bp_reg = ANA_LDO_PD_SET,
133 .bp_rst_reg = ANA_LDO_PD_RST,
135 .level_reg_b0 = ANA_LDO_VCTL3,
138 .level_reg_b1 = ANA_LDO_VCTL3,
141 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
145 .bp_reg = ANA_LDO_PD_SET,
147 .bp_rst_reg = ANA_LDO_PD_RST,
149 .level_reg_b0 = ANA_LDO_VCTL0,
152 .level_reg_b1 = ANA_LDO_VCTL0,
155 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
159 .bp_reg = ANA_LDO_PD_SET,
161 .bp_rst_reg = ANA_LDO_PD_RST,
163 .level_reg_b0 = ANA_LDO_VCTL0,
166 .level_reg_b1 = ANA_LDO_VCTL0,
169 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
173 .bp_reg = ANA_LDO_PD_SET,
175 .bp_rst_reg = ANA_LDO_PD_RST,
177 .level_reg_b0 = ANA_LDO_VCTL0,
180 .level_reg_b1 = ANA_LDO_VCTL0,
183 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
187 .bp_reg = ANA_LDO_PD_SET,
189 .bp_rst_reg = ANA_LDO_PD_RST,
191 .level_reg_b0 = LDO_INVALID_REG_ADDR,
194 .level_reg_b1 = LDO_INVALID_REG_ADDR,
197 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
201 .bp_reg = ANA_LDO_PD_SET,
203 .bp_rst_reg = ANA_LDO_PD_RST,
205 .level_reg_b0 = LDO_INVALID_REG_ADDR,
208 .level_reg_b1 = LDO_INVALID_REG_ADDR,
211 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
215 .bp_reg = ANA_LDO_PD_SET,
217 .bp_rst_reg = ANA_LDO_PD_RST,
219 .level_reg_b0 = LDO_INVALID_REG_ADDR,
222 .level_reg_b1 = LDO_INVALID_REG_ADDR,
225 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
229 .bp_reg = ANA_LDO_PD_CTL0,
231 .bp_rst_reg = ANA_LDO_PD_CTL0,
233 .level_reg_b0 = ANA_LDO_VCTL1,
236 .level_reg_b1 = ANA_LDO_VCTL1,
239 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
243 .bp_reg = ANA_LDO_PD_CTL0,
245 .bp_rst_reg = ANA_LDO_PD_CTL0,
247 .level_reg_b0 = ANA_LDO_VCTL2,
250 .level_reg_b1 = ANA_LDO_VCTL2,
253 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
257 .bp_reg = ANA_LDO_PD_CTL0,
259 .bp_rst_reg = ANA_LDO_PD_CTL0,
261 .level_reg_b0 = ANA_LDO_VCTL2,
264 .level_reg_b1 = ANA_LDO_VCTL2,
267 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
271 .bp_reg = ANA_LDO_PD_CTL0,
273 .bp_rst_reg = ANA_LDO_PD_CTL0,
275 .level_reg_b0 = ANA_LDO_VCTL2,
278 .level_reg_b1 = ANA_LDO_VCTL2,
281 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
285 .bp_reg = ANA_LDO_PD_CTL0,
287 .bp_rst_reg = ANA_LDO_PD_CTL0,
289 .level_reg_b0 = ANA_LDO_VCTL1,
292 .level_reg_b1 = ANA_LDO_VCTL1,
295 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
299 .bp_reg = ANA_LDO_PD_CTL0,
301 .bp_rst_reg = ANA_LDO_PD_CTL0,
303 .level_reg_b0 = ANA_LDO_VCTL1,
306 .level_reg_b1 = ANA_LDO_VCTL1,
309 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
313 .bp_reg = ANA_LDO_PD_CTL0,
315 .bp_rst_reg = ANA_LDO_PD_CTL0,
317 .level_reg_b0 = ANA_LDO_VCTL1,
320 .level_reg_b1 = ANA_LDO_VCTL1,
323 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
327 .bp_reg = ANA_LDO_PD_CTL0,
329 .bp_rst_reg = ANA_LDO_PD_CTL0,
331 .level_reg_b0 = ANA_LDO_VCTL2,
334 .level_reg_b1 = ANA_LDO_VCTL2,
337 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
341 .bp_reg = ANA_LDO_PD_CTL1,
343 .bp_rst_reg = ANA_LDO_PD_CTL1,
345 .level_reg_b0 = ANA_LDO_VCTL4,
348 .level_reg_b1 = ANA_LDO_VCTL4,
351 .init_level = LDO_VOLT_LEVEL3, //CMMB 1.2V
355 .bp_reg = ANA_LDO_PD_CTL1,
357 .bp_rst_reg = ANA_LDO_PD_CTL1,
359 .level_reg_b0 = ANA_LDO_VCTL4,
362 .level_reg_b1 = ANA_LDO_VCTL4,
365 .init_level = LDO_VOLT_LEVEL1, //E-NAND 3.0V
369 .bp_reg = ANA_LDO_PD_CTL1,
371 .bp_rst_reg = ANA_LDO_PD_CTL1,
373 .level_reg_b0 = ANA_LDO_VCTL4,
376 .level_reg_b1 = ANA_LDO_VCTL4,
379 .init_level = LDO_VOLT_LEVEL2, //WIFI 1.8V
383 .bp_reg = ANA_LDO_PD_CTL1,
385 .bp_rst_reg = ANA_LDO_PD_CTL1,
387 .level_reg_b0 = ANA_LDO_VCTL4,
390 .level_reg_b1 = ANA_LDO_VCTL4,
393 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
397 .bp_reg = ANA_LDO_PD_CTL1,
399 .bp_rst_reg = ANA_LDO_PD_CTL1,
401 .level_reg_b0 = ANA_LDO_VCTL3,
404 .level_reg_b1 = ANA_LDO_VCTL3,
407 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
411 .bp_reg = LDO_INVALID_REG_ADDR,
413 .bp_rst_reg = LDO_INVALID_REG_ADDR,
415 .level_reg_b0 = ANA_LDO_VCTL0,
418 .level_reg_b1 = ANA_LDO_VCTL0,
421 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
425 .bp_reg = LDO_INVALID_REG_ADDR,
427 .bp_rst_reg = LDO_INVALID_REG_ADDR,
429 .level_reg_b0 = LDO_INVALID_REG_ADDR,
432 .level_reg_b1 = LDO_INVALID_REG_ADDR,
435 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
439 .bp_reg = ANA_LDO_PD_CTL1,
441 .bp_rst_reg = ANA_LDO_PD_CTL1,
443 .level_reg_b0 = ANA_LDO_VCTL4,
446 .level_reg_b1 = ANA_LDO_VCTL4,
449 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
453 .bp_reg = ANA_LDO_PD_CTL1,
455 .bp_rst_reg = ANA_LDO_PD_CTL1,
457 .level_reg_b0 = ANA_LDO_VCTL1,
460 .level_reg_b1 = ANA_LDO_VCTL1,
463 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
467 static struct ldo_sleep_ctl_info slp_ldo_ctl_data[] = {
468 {SLP_LDO_SDIO1, ANA_LDO_SLP_CTL0, BIT_14, 0},
469 {SLP_LDO_VDD25, ANA_LDO_SLP_CTL0, BIT_13, 1},
470 {SLP_LDO_VDD18, ANA_LDO_SLP_CTL0, BIT_12, 0},
471 {SLP_LDO_VDD28, ANA_LDO_SLP_CTL0, BIT_11, 0},
472 {SLP_LDO_AVDDBB, ANA_LDO_SLP_CTL0, BIT_10, 1},
473 {SLP_LDO_SDIO0, ANA_LDO_SLP_CTL0, BIT_9, 1},
474 {SLP_LDO_VB, ANA_LDO_SLP_CTL0, BIT_8, 0},
475 {SLP_LDO_CAMA, ANA_LDO_SLP_CTL0, BIT_7, 1},
476 {SLP_LDO_CAMD1, ANA_LDO_SLP_CTL0, BIT_6, 1},
477 {SLP_LDO_CAMD0, ANA_LDO_SLP_CTL0, BIT_5, 1},
478 {SLP_LDO_USBH, ANA_LDO_SLP_CTL0, BIT_4, 1},
479 {SLP_LDO_SIM1, ANA_LDO_SLP_CTL0, BIT_3, 1},
480 {SLP_LDO_SIM0, ANA_LDO_SLP_CTL0, BIT_2, 0},
481 {SLP_LDO_RF1, ANA_LDO_SLP_CTL0, BIT_1, 1},
482 {SLP_LDO_RF0, ANA_LDO_SLP_CTL0, BIT_0, 1},
485 /**---------------------------------------------------------------------------*
486 ** Function Declaration *
487 **---------------------------------------------------------------------------*/
488 static struct ldo_ctl_info* LDO_GetLdoCtl(LDO_ID_E ldo_id)
491 struct ldo_ctl_info* ctl = NULL;
493 for ( i = 0; i < ARRAY_SIZE(ldo_ctl_data); ++i) {
494 if (ldo_ctl_data[i].id == ldo_id) {
495 ctl = &ldo_ctl_data[i];
500 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
504 LDO_ERR_E LDO_TurnOnLDO(LDO_ID_E ldo_id)
506 struct ldo_ctl_info* ctl = NULL;
508 ctl = LDO_GetLdoCtl(ldo_id);
509 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
511 if ((ctl->ref++) == 0) {
512 if(ctl->bp_reg == LDO_INVALID_REG_ADDR) {
513 if (LDO_LDO_USBD == ldo_id)
514 CHIP_REG_AND((~LDO_USB_PD), GR_CLK_GEN5);
517 if (ctl->bp_reg == ctl->bp_rst_reg) {
518 REG_SETCLRBIT(ctl->bp_rst_reg, ctl->bp_rst, ctl->bp_bits);
521 ANA_REG_BIC(ctl->bp_reg, ctl->bp_bits);
522 ANA_REG_OR(ctl->bp_rst_reg, ctl->bp_rst);//high priority
525 ctl->current_status = CURRENT_STATUS_ON;
532 LDO_ERR_E LDO_TurnOffLDO(LDO_ID_E ldo_id)
534 struct ldo_ctl_info* ctl = NULL;
537 ctl = LDO_GetLdoCtl(ldo_id);
538 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
540 local_irq_save(flags);
542 if ((--ctl->ref) == 0) {
543 if(ctl->bp_reg == LDO_INVALID_REG_ADDR) {
544 if (LDO_LDO_USBD == ldo_id)
545 CHIP_REG_OR((LDO_USB_PD), GR_CLK_GEN5);
547 if (ctl->bp_reg == ctl->bp_rst_reg) {
548 REG_SETCLRBIT(ctl->bp_reg, ctl->bp_bits, ctl->bp_rst);
551 ANA_REG_BIC(ctl->bp_rst_reg, ctl->bp_rst);//high priority
552 ANA_REG_OR(ctl->bp_reg, ctl->bp_bits);
555 ctl->current_status = CURRENT_STATUS_OFF;
558 local_irq_restore(flags);
563 int LDO_IsLDOOn(LDO_ID_E ldo_id)
565 unsigned int masked_val = 0;
566 struct ldo_ctl_info* ctl = NULL;
568 ctl = LDO_GetLdoCtl(ldo_id);
569 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
571 if (ctl->current_status == CURRENT_STATUS_INIT)
572 masked_val = (LDO_REG_GET(ctl->bp_reg) & ctl->bp_bits);
574 return (ctl->current_status == CURRENT_STATUS_OFF ? 0 : 1);
576 return (masked_val ? 0 : 1);
579 LDO_ERR_E LDO_SetVoltLevel(LDO_ID_E ldo_id, LDO_VOLT_LEVEL_E volt_level)
581 unsigned int b0_mask,b1_mask;
582 struct ldo_ctl_info* ctl = NULL;
585 b0_mask = (volt_level & BIT_0)?~0:0;
586 b1_mask = (volt_level & BIT_1)?~0:0;
588 ctl = LDO_GetLdoCtl(ldo_id);
589 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
591 if(ctl->level_reg_b0 == ctl->level_reg_b1) {
592 if (ctl->level_reg_b0 == LDO_INVALID_REG_ADDR)
595 SET_LEVEL(ctl->level_reg_b0, b0_mask, b1_mask, ctl->b0, ctl->b0_rst, ctl->b1, ctl->b1_rst);
597 if (ctl->level_reg_b0 == LDO_INVALID_REG_ADDR || ctl->level_reg_b1 == LDO_INVALID_REG_ADDR) {
600 SET_LEVELBIT(ctl->level_reg_b0, b0_mask, ctl->b0, ctl->b0_rst);
601 SET_LEVELBIT(ctl->level_reg_b1, b1_mask, ctl->b1, ctl->b1_rst);
605 ctl->current_volt_level = volt_level;
612 LDO_VOLT_LEVEL_E LDO_GetVoltLevel(LDO_ID_E ldo_id)
614 unsigned int level_ret = 0;
615 struct ldo_ctl_info* ctl = NULL;
618 ctl = LDO_GetLdoCtl(ldo_id);
619 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
621 if (ctl->current_volt_level == LDO_VOLT_LEVEL_FAULT_MAX) {
622 if(ctl->level_reg_b0 == ctl->level_reg_b1) {
623 GET_LEVEL(ctl->level_reg_b0, ctl->b0, ctl->b1, level_ret);
625 GET_LEVELBIT(ctl->level_reg_b0, ctl->b0, BIT_0, level_ret);
626 GET_LEVELBIT(ctl->level_reg_b1, ctl->b1, BIT_1, level_ret);
631 level_ret = ctl->current_volt_level;
637 void LDO_DeepSleepInit(void)
642 for ( i = 0; i < ARRAY_SIZE(slp_ldo_ctl_data); ++i) {
643 aux = ANA_REG_GET(slp_ldo_ctl_data[i].ldo_sleep_reg);
644 aux &= ~slp_ldo_ctl_data[i].mask;
645 aux |= slp_ldo_ctl_data[i].value;
646 ANA_REG_SET(slp_ldo_ctl_data[i].ldo_sleep_reg, aux);
654 for ( i = 0; i < ARRAY_SIZE(ldo_ctl_data); ++i) {
655 if( ldo_ctl_data[i].init_level != LDO_VOLT_LEVEL_FAULT_MAX) {
656 LDO_SetVoltLevel(ldo_ctl_data[i].id, ldo_ctl_data[i].init_level);
658 ldo_ctl_data[i].ref = 0;
659 ldo_ctl_data[i].current_status = CURRENT_STATUS_INIT;
660 ldo_ctl_data[i].current_volt_level = ldo_ctl_data[i].init_level;
668 static void LDO_TurnOffCoreLDO(void)
670 ANA_REG_SET (ANA_LDO_PD_RST, 0);
671 ANA_REG_SET (ANA_LDO_PD_SET, ANA_LDO_PD_SET_MSK);/// turn off system core ldo
674 static void LDO_TurnOffAllModuleLDO(void)
676 ANA_REG_OR(ANA_AUDIO_PA_CTL1, PA_LDO_EN_RST);///PA poweroff
677 ANA_REG_SET (ANA_LDO_PD_CTL1, ANA_LDO_PD_CTL_MSK);
678 ANA_REG_SET (ANA_LDO_PD_CTL0, ANA_LDO_PD_CTL_MSK);
681 void LDO_TurnOffAllLDO(void)
683 LDO_TurnOffAllModuleLDO();
684 LDO_TurnOffCoreLDO();