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/ldo.h>
23 #include <asm/arch/chip_drv_common_io.h>
24 #include <asm/arch/sprd_reg.h>
26 #define LDO_INVALID_REG 0xFFFFFFFF
27 #define LDO_INVALID_BIT 0xFFFFFFFF
30 #define CURRENT_STATUS_INIT 0x00000001
31 #define CURRENT_STATUS_ON 0x00000002
32 #define CURRENT_STATUS_OFF 0x00000004
34 #define LDO_INVALID_REG_ADDR 0x1
36 #define SCI_PASSERT(condition, format...) \
39 printf("function :%s\r\n", __FUNCTION__);\
43 #if defined(CONFIG_SPX15) || defined(CONFIG_ADIE_SC2723) || defined(CONFIG_ADIE_SC2723S)
49 .id = LDO_LDO_USB, .name = "vddusb",
52 .id = LDO_LDO_EMMCCORE, .name = "vddemmccore",
54 #if defined(CONFIG_ADIE_SC2723) || defined(CONFIG_ADIE_SC2723S)
56 .id = LDO_LDO_SDIO0, .name = "vddsdcore",
59 .id = LDO_LDO_SDIO1, .name = "vddsdio",
62 .id = LDO_LDO_EMMCIO, .name = "vddgen1",
66 .id = LDO_LDO_EMMCIO, .name = "vddemmcio",
69 .id = LDO_LDO_SDIO0, .name = "vddsd",
73 .id = LDO_LDO_SIM0, .name = "vddsim0",
76 .id = LDO_LDO_SIM1, .name = "vddsim1",
79 .id = LDO_LDO_SIM2, .name = "vddsim2",
83 const char* __LDO_NAME(LDO_ID_E ldo_id)
86 for(i = 0; i < ARRAY_SIZE(__ldo_names); i++) {
87 if (ldo_id == __ldo_names[i].id)
88 return __ldo_names[i].name;
95 return regulator_init();
98 void LDO_TurnOffAllLDO(void)
100 unsigned int reg_val;
102 ANA_REG_SET(ANA_REG_GLB_PWR_WR_PROT_VALUE,BITS_PWR_WR_PROT_VALUE(0x6e7f));
105 reg_val = (ANA_REG_GET(ANA_REG_GLB_PWR_WR_PROT_VALUE) & BIT_PWR_WR_PROT);
106 }while(reg_val == 0);
108 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL,0x0FFF);
109 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD,0x7FFF);
111 ANA_REG_SET(ANA_REG_GLB_PWR_WR_PROT_VALUE,BITS_PWR_WR_PROT_VALUE(0x0000));
112 //never return here and wait power down action
116 LDO_ERR_E LDO_TurnOffLDO(LDO_ID_E ldo_id)
118 return regulator_disable(__LDO_NAME(ldo_id));
121 LDO_ERR_E LDO_TurnOnLDO(LDO_ID_E ldo_id)
123 return regulator_enable(__LDO_NAME(ldo_id));
128 struct ldo_ctl_info {
134 unsigned int bp_bits;
135 unsigned int bp_rst_reg;
136 unsigned int bp_rst;//bits
138 unsigned int level_reg_b0;
142 unsigned int level_reg_b1;
146 unsigned int init_level;
152 int current_volt_level;
155 static struct ldo_ctl_info ldo_ctl_data[] =
158 .id = LDO_LDO_EMMCCORE,
159 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
161 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
163 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
166 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
169 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
172 .id = LDO_LDO_EMMCIO,
173 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
175 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
177 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
180 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
183 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
187 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
189 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
191 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
194 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
197 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
201 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
203 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
205 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
208 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
211 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
215 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
217 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
219 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
222 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
225 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
229 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
231 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
233 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
236 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
239 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
243 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
245 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
247 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
250 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
253 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
257 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
259 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
261 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL0,
264 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL0,
267 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
271 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
273 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
275 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL1,
278 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL1,
281 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
285 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
287 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
289 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL1,
292 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL1,
295 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
299 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
301 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
303 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL1,
306 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL1,
309 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
313 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
315 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
317 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL1,
320 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL1,
323 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
326 .id = LDO_LDO_AVDD18,
327 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
329 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
331 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL1,
334 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL1,
337 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
340 .id = LDO_LDO_VBAT_RES, //new
341 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
343 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
345 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
348 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
351 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
354 .id = LDO_LDO_VBAT_V, //new
355 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
357 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
359 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
362 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
365 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
369 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
371 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
373 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
376 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
379 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
383 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
385 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
387 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
390 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
393 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
396 .id = LDO_LDO_CAMM, //LDO_LDO_CAMMOT
397 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
399 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
401 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
404 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
407 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
410 .id = LDO_LDO_CAMD1, //LDO_LDO_CAMIO
411 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
413 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
415 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
418 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
421 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
424 .id = LDO_LDO_CAMD0, //LDO_LDO_CAMCORE
425 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
427 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
429 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
432 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
435 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
438 .id = LDO_LDO_CAMA, //LDO_LDO_CAMA
439 .bp_reg = ANA_REG_GLB_LDO_PD_CTRL,
441 .bp_rst_reg = ANA_REG_GLB_LDO_PD_CTRL,
443 .level_reg_b0 = ANA_REG_GLB_LDO_V_CTRL2,
446 .level_reg_b1 = ANA_REG_GLB_LDO_V_CTRL2,
449 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
451 /** config it later **/
454 .bp_reg = LDO_INVALID_REG_ADDR,
456 .bp_rst_reg = LDO_INVALID_REG_ADDR,
458 .level_reg_b0 = LDO_INVALID_REG_ADDR,
461 .level_reg_b1 = LDO_INVALID_REG_ADDR,
464 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
468 .bp_reg = LDO_INVALID_REG_ADDR,
470 .bp_rst_reg = LDO_INVALID_REG_ADDR,
472 .level_reg_b0 = LDO_INVALID_REG_ADDR,
475 .level_reg_b1 = LDO_INVALID_REG_ADDR,
478 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
482 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
484 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
486 .level_reg_b0 = ANA_REG_GLB_DCDC_MEM_ADI,
489 .level_reg_b1 = ANA_REG_GLB_DCDC_MEM_ADI,
492 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
496 .bp_reg = LDO_INVALID_REG_ADDR,
498 .bp_rst_reg = LDO_INVALID_REG_ADDR,
500 .level_reg_b0 = LDO_INVALID_REG_ADDR,
503 .level_reg_b1 = LDO_INVALID_REG_ADDR,
506 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
510 .bp_reg = LDO_INVALID_REG_ADDR,
512 .bp_rst_reg = LDO_INVALID_REG_ADDR,
514 .level_reg_b0 = LDO_INVALID_REG_ADDR,
517 .level_reg_b1 = LDO_INVALID_REG_ADDR,
520 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
524 .bp_reg = LDO_INVALID_REG_ADDR,
526 .bp_rst_reg = LDO_INVALID_REG_ADDR,
528 .level_reg_b0 = LDO_INVALID_REG_ADDR,
531 .level_reg_b1 = LDO_INVALID_REG_ADDR,
534 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
538 .bp_reg = LDO_INVALID_REG_ADDR,
540 .bp_rst_reg = LDO_INVALID_REG_ADDR,
542 .level_reg_b0 = LDO_INVALID_REG_ADDR,
545 .level_reg_b1 = LDO_INVALID_REG_ADDR,
548 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
552 .bp_reg = LDO_INVALID_REG_ADDR,
554 .bp_rst_reg = LDO_INVALID_REG_ADDR,
556 .level_reg_b0 = LDO_INVALID_REG_ADDR,
559 .level_reg_b1 = LDO_INVALID_REG_ADDR,
562 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
566 .bp_reg = LDO_INVALID_REG_ADDR,
568 .bp_rst_reg = LDO_INVALID_REG_ADDR,
570 .level_reg_b0 = LDO_INVALID_REG_ADDR,
573 .level_reg_b1 = LDO_INVALID_REG_ADDR,
576 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
580 .bp_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCSET,
582 .bp_rst_reg = ANA_REG_GLB_LDO_DCDC_PD_RTCCLR,
584 .level_reg_b0 = LDO_INVALID_REG_ADDR,
587 .level_reg_b1 = LDO_INVALID_REG_ADDR,
590 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
594 .bp_reg = LDO_INVALID_REG_ADDR,
596 .bp_rst_reg = LDO_INVALID_REG_ADDR,
598 .level_reg_b0 = LDO_INVALID_REG_ADDR,
601 .level_reg_b1 = LDO_INVALID_REG_ADDR,
604 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
608 .bp_reg = LDO_INVALID_REG_ADDR,
610 .bp_rst_reg = LDO_INVALID_REG_ADDR,
612 .level_reg_b0 = LDO_INVALID_REG_ADDR,
615 .level_reg_b1 = LDO_INVALID_REG_ADDR,
618 .init_level = LDO_VOLT_LEVEL_FAULT_MAX,
622 /**---------------------------------------------------------------------------*
623 ** Function Declaration *
624 **---------------------------------------------------------------------------*/
625 static struct ldo_ctl_info* LDO_GetLdoCtl(LDO_ID_E ldo_id)
628 struct ldo_ctl_info* ctl = NULL;
630 for ( i = 0; i < ARRAY_SIZE(ldo_ctl_data); ++i)
632 if (ldo_ctl_data[i].id == ldo_id)
634 ctl = &ldo_ctl_data[i];
639 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
643 LDO_ERR_E LDO_TurnOnLDO(LDO_ID_E ldo_id)
645 struct ldo_ctl_info* ctl = NULL;
647 if (ldo_id == LDO_LDO_SDIO3)
649 if (LDO_TurnOnLDO(LDO_LDO_EMMCCORE) != LDO_ERR_OK)
651 if (LDO_TurnOnLDO(LDO_LDO_EMMCIO) != LDO_ERR_OK)
656 ctl = LDO_GetLdoCtl(ldo_id);
657 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
659 //if ((ctl->ref++) == 0)
661 if(ctl->bp_reg == LDO_INVALID_REG_ADDR)
663 //if (LDO_LDO_USBD == ldo_id)
664 // CHIP_REG_AND((~LDO_USB_PD), GR_CLK_GEN5);
669 ANA_REG_OR (ctl->bp_rst_reg, ctl->bp_rst);
670 ANA_REG_AND(ctl->bp_reg, ~(ctl->bp_bits));
672 ctl->current_status = CURRENT_STATUS_ON;
677 LDO_ERR_E LDO_TurnOffLDO(LDO_ID_E ldo_id)
679 struct ldo_ctl_info* ctl = NULL;
681 if (ldo_id == LDO_LDO_SDIO3)
683 if (LDO_TurnOffLDO(LDO_LDO_EMMCCORE) != LDO_ERR_OK)
685 if (LDO_TurnOffLDO(LDO_LDO_EMMCIO) != LDO_ERR_OK)
690 ctl = LDO_GetLdoCtl(ldo_id);
691 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
693 //local_irq_save(flags);
695 //if ((--ctl->ref) == 0)
697 if(ctl->bp_reg == LDO_INVALID_REG_ADDR)
699 //if (LDO_LDO_USBD == ldo_id)
700 // CHIP_REG_OR((LDO_USB_PD), GR_CLK_GEN5);
704 ANA_REG_AND(ctl->bp_rst_reg, (~(ctl->bp_rst)));
705 ANA_REG_OR (ctl->bp_reg, ctl->bp_bits);
707 ctl->current_status = CURRENT_STATUS_OFF;
710 //local_irq_restore(flags);
715 int LDO_IsLDOOn(LDO_ID_E ldo_id)
717 unsigned int masked_val = 0;
718 struct ldo_ctl_info* ctl = NULL;
720 ctl = LDO_GetLdoCtl(ldo_id);
721 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
723 if (ctl->current_status == CURRENT_STATUS_INIT)
725 masked_val = (LDO_REG_GET(ctl->bp_reg) & ctl->bp_bits);
729 return (ctl->current_status == CURRENT_STATUS_OFF ? 0 : 1);
732 return (masked_val ? 0 : 1);
735 LDO_ERR_E LDO_SetVoltLevel(LDO_ID_E ldo_id, LDO_VOLT_LEVEL_E volt_level)
737 unsigned short reg_data;
738 struct ldo_ctl_info* ctl = NULL;
740 ctl = LDO_GetLdoCtl(ldo_id);
741 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
743 if (ctl->level_reg_b0 == LDO_INVALID_REG_ADDR)
748 if (ctl->level_reg_b0 != ctl->level_reg_b1)
750 printf("ldo_id:%d, level_reg_b0:%08x, level_reg_b1:%08x\r\n", ldo_id, ctl->level_reg_b0, ctl->level_reg_b1);
756 case LDO_VOLT_LEVEL0:
757 ANA_REG_AND(ctl->level_reg_b0, (~(ctl->b0|ctl->b1)));
760 case LDO_VOLT_LEVEL1:
761 reg_data = ANA_REG_GET(ctl->level_reg_b0);
764 ANA_REG_SET(ctl->level_reg_b0, reg_data);
767 case LDO_VOLT_LEVEL2:
768 reg_data = ANA_REG_GET(ctl->level_reg_b0);
771 ANA_REG_SET(ctl->level_reg_b0, reg_data);
774 case LDO_VOLT_LEVEL3:
775 ANA_REG_OR (ctl->level_reg_b0, (ctl->b0|ctl->b1));
782 ctl->current_volt_level = volt_level;
788 LDO_VOLT_LEVEL_E LDO_GetVoltLevel(LDO_ID_E ldo_id)
790 unsigned int level_ret = 0;
791 struct ldo_ctl_info* ctl = NULL;
793 ctl = LDO_GetLdoCtl(ldo_id);
794 SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
796 if (ctl->current_volt_level == LDO_VOLT_LEVEL_FAULT_MAX)
798 if(ctl->level_reg_b0 == ctl->level_reg_b1)
805 SCI_PASSERT(0, ("shakr b0 must equal b1!"));
810 level_ret = ctl->current_volt_level;
819 for ( i = 0; i < ARRAY_SIZE(ldo_ctl_data); ++i)
821 if( ldo_ctl_data[i].init_level != LDO_VOLT_LEVEL_FAULT_MAX)
823 LDO_SetVoltLevel(ldo_ctl_data[i].id, ldo_ctl_data[i].init_level);
825 ldo_ctl_data[i].ref = 0;
826 ldo_ctl_data[i].current_status = CURRENT_STATUS_INIT;
827 ldo_ctl_data[i].current_volt_level = ldo_ctl_data[i].init_level;
832 static void LDO_TurnOffCoreLDO(void)
834 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD_RTCCLR, 0x0);
835 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD_RTCSET, 0x7FFF);
838 static void LDO_TurnOffAllModuleLDO(void)
840 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, 0x1FFF);
843 void LDO_TurnOffAllLDO(void)
845 LDO_TurnOffAllModuleLDO();
846 LDO_TurnOffCoreLDO();