tizen 2.4 release
[kernel/u-boot-tm1.git] / arch / arm / cpu / arm926ejs / sc8800g / ldo.c
1 /******************************************************************************
2  ** File Name:      ldo_drv.c                                             *
3  ** Author:         Yi.Qiu                                                 *
4  ** DATE:           01/09/2009                                                *
5  ** Copyright:      2007 Spreatrum, Incoporated. All Rights Reserved.         *
6  ** Description:    This file defines the basic function for ldo management.  *
7  ******************************************************************************/
8
9 /******************************************************************************
10  **                        Edit History                                       *
11  ** ------------------------------------------------------------------------- *
12  ** DATE           NAME             DESCRIPTION                               *
13  ** 01/09/2009     Yi.Qiu        Create.                                   *
14  ******************************************************************************/
15
16 /**---------------------------------------------------------------------------*
17  **                         Dependencies                                      *
18  **---------------------------------------------------------------------------*/
19 #include <common.h>
20 #include <asm/io.h>
21
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>
26
27 #define LDO_INVALID_REG 0xFFFFFFFF
28 #define LDO_INVALID_BIT         0xFFFFFFFF
29
30 #define TRUE                    1
31 #define FALSE           0
32
33 #define CHIP_REG_OR(reg_addr, value)    (*(volatile unsigned int *)(reg_addr) |= (unsigned int)(value))
34 #define CHIP_REG_AND(reg_addr, value)   (*(volatile unsigned int *)(reg_addr) &= (unsigned int)(value))
35 #define CHIP_REG_GET(reg_addr)          (*(volatile unsigned int *)(reg_addr))
36 #define CHIP_REG_SET(reg_addr, value)   (*(volatile unsigned int *)(reg_addr)  = (unsigned int)(value))
37
38 #undef NULL
39 #ifndef NULL
40 #define NULL 0x0
41 #endif
42
43 #define SCI_ASSERT(condition) BUG_ON(!(condition))  
44 #define SCI_PASSERT(condition, format...)  \
45         do {            \
46                 if(!(condition)) { \
47                         printf("function :%s\r\n", __FUNCTION__);\
48                         BUG();  \
49                 } \
50         }while(0)
51         
52 typedef enum 
53 {
54         SLP_BIT_CLR = 0,
55         SLP_BIT_SET
56 }SLP_BIT_DEF_E;
57
58 typedef struct  
59 {
60         LDO_ID_E id;
61         unsigned int bp_reg;
62         unsigned int bp;
63         unsigned int bp_rst;
64         unsigned int level_reg_b0;
65         unsigned int b0;
66         unsigned int b0_rst;
67         unsigned int level_reg_b1;
68         unsigned int b1;
69         unsigned int b1_rst;
70         unsigned int valid_time;
71         unsigned int init_level;
72         int ref;
73 }LDO_CTL_T, * LDO_CTL_PTR;
74
75 typedef struct  
76 {
77         SLP_LDO_E id;
78         unsigned int ldo_reg;
79         unsigned int mask;
80         SLP_BIT_DEF_E value;
81         int valid;
82         unsigned int reserved;
83 }SLP_LDO_CTL_T, * SLP_LDO_CTL_PTR;
84
85
86 LDO_CTL_T ldo_ctl_data[] =
87 {
88     {
89         LDO_LDO_ABB,   NULL,           NULL,   NULL,   ANA_LDO_VCTL0,  BIT_12, BIT_13,
90         ANA_LDO_VCTL0,  BIT_14, BIT_15, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
91     },
92     {
93         LDO_LDO_RF1,   NULL,           NULL,   NULL,   ANA_LDO_VCTL0,  BIT_8,  BIT_9,
94         ANA_LDO_VCTL0,  BIT_10, BIT_11, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
95     },
96     {
97         LDO_LDO_RF0,   NULL,           NULL,   NULL,   ANA_LDO_VCTL0,  BIT_4,  BIT_5,
98         ANA_LDO_VCTL0,  BIT_6,  BIT_7,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
99     },
100     {
101         LDO_LDO_RTC,   NULL,           NULL,   NULL,   ANA_LDO_VCTL0,  BIT_0,  BIT_1,
102         ANA_LDO_VCTL0,  BIT_2,  BIT_3,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
103     },
104     {
105         LDO_LDO_SDIO,  ANA_LDO_PD_CTL, BIT_2,  BIT_3,  ANA_LDO_VCTL1,  BIT_12,BIT_13,
106         ANA_LDO_VCTL1,  BIT_14, BIT_15, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
107     },
108     {
109         LDO_LDO_AVBO,  ANA_LDO_PD_CTL, BIT_14, BIT_15, ANA_LDO_VCTL1,  BIT_8,  BIT_9,
110         ANA_LDO_VCTL1,  BIT_10, BIT_11, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
111     },
112     {
113         LDO_LDO_SIM1,  ANA_LDO_PD_CTL, BIT_6,  BIT_7,  ANA_LDO_VCTL1,  BIT_4,  BIT_5,
114         ANA_LDO_VCTL1,  BIT_6,  BIT_7,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
115     },
116     {
117         LDO_LDO_SIM0,  ANA_LDO_PD_CTL, BIT_4,  BIT_5,  ANA_LDO_VCTL1,  BIT_0,  BIT_1,
118         ANA_LDO_VCTL1,  BIT_2,  BIT_3,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
119     },
120     {
121         LDO_LDO_USB,   ANA_LDO_PD_CTL, BIT_0,  BIT_1,  ANA_LDO_VCTL2,  BIT_12, BIT_13,
122         ANA_LDO_VCTL2,  BIT_14, BIT_15, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
123     },
124     {
125         LDO_LDO_USBD,  NULL,           NULL,   NULL,   NULL,           NULL,   NULL,
126         NULL,           NULL,   NULL,   NULL,   LDO_VOLT_LEVEL_MAX,     NULL
127     },
128     {
129         LDO_LDO_CAMA,  ANA_LDO_PD_CTL, BIT_12, BIT_13, ANA_LDO_VCTL2,  BIT_8,  BIT_9,
130         ANA_LDO_VCTL2,  BIT_10, BIT_11, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
131     },
132     {
133         LDO_LDO_CAMD1, ANA_LDO_PD_CTL, BIT_10, BIT_11, ANA_LDO_VCTL2,  BIT_4,  BIT_5,
134         ANA_LDO_VCTL2,  BIT_6,  BIT_7,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
135     },
136     {
137         LDO_LDO_CAMD0, ANA_LDO_PD_CTL, BIT_8,  BIT_9,  ANA_LDO_VCTL2,  BIT_0,  BIT_1,
138         ANA_LDO_VCTL2,  BIT_2,  BIT_3,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
139     },
140     {
141         LDO_LDO_VDD25, NULL,           NULL,   NULL,   ANA_LDO_VCTL3,  BIT_8,  BIT_9,
142         ANA_LDO_VCTL3,  BIT_10, BIT_11, NULL,   LDO_VOLT_LEVEL_MAX,     NULL
143     },
144     {
145         LDO_LDO_VDD18, NULL,           NULL,   NULL,   ANA_LDO_VCTL3,  BIT_4,  BIT_5,
146         ANA_LDO_VCTL3,  BIT_6,  BIT_7,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
147     },
148     {
149         LDO_LDO_VDD28, NULL,           NULL,   NULL,   ANA_LDO_VCTL3,  BIT_0,  BIT_1,
150         ANA_LDO_VCTL3,  BIT_2,  BIT_3,  NULL,   LDO_VOLT_LEVEL_MAX,     NULL
151     },
152     {
153         LDO_LDO_MAX,   NULL,           NULL,   NULL,   NULL,           NULL,   NULL,
154         NULL,           NULL,   NULL,   NULL,   LDO_VOLT_LEVEL_MAX,     NULL
155     }
156 };
157
158 SLP_LDO_CTL_T slp_ldo_ctl_data[] =
159 {
160     {SLP_LDO_PA,        ANA_LDO_SLP,    BIT_15, SLP_BIT_SET,    TRUE,   NULL},
161     {SLP_LDO_DVDD18,    ANA_LDO_SLP,    BIT_14, SLP_BIT_CLR,    TRUE,   NULL},
162     {SLP_LDO_VDD25,     ANA_LDO_SLP,    BIT_13, SLP_BIT_SET,    TRUE,   NULL},
163     {SLP_LDO_VDD18,     ANA_LDO_SLP,    BIT_12, SLP_BIT_CLR,    TRUE,   NULL},
164     {SLP_LDO_VDD28,     ANA_LDO_SLP,    BIT_11, SLP_BIT_CLR,    TRUE,   NULL},
165     {SLP_LDO_ABB,       ANA_LDO_SLP,    BIT_10, SLP_BIT_SET,    TRUE,   NULL},
166     {SLP_LDO_SDIO,      ANA_LDO_SLP,    BIT_9,  SLP_BIT_SET,    TRUE,   NULL},
167     {SLP_LDO_VBO,       ANA_LDO_SLP,    BIT_8,  SLP_BIT_CLR,    TRUE,   NULL},
168     {SLP_LDO_CAMA,      ANA_LDO_SLP,    BIT_7,  SLP_BIT_SET,    TRUE,   NULL},
169     {SLP_LDO_CAMD1,     ANA_LDO_SLP,    BIT_6,  SLP_BIT_SET,    TRUE,   NULL},
170     {SLP_LDO_CAMD0,     ANA_LDO_SLP,    BIT_5,  SLP_BIT_SET,    TRUE,   NULL},
171     {SLP_LDO_USB,       ANA_LDO_SLP,    BIT_4,  SLP_BIT_SET,    TRUE,   NULL},
172     {SLP_LDO_SIM1,      ANA_LDO_SLP,    BIT_3,  SLP_BIT_SET,    TRUE,   NULL},
173     {SLP_LDO_SIM0,      ANA_LDO_SLP,    BIT_2,  SLP_BIT_CLR,    TRUE,   NULL},
174     {SLP_LDO_RF1,       ANA_LDO_SLP,    BIT_1,  SLP_BIT_SET,    TRUE,   NULL},
175     {SLP_LDO_RF0,       ANA_LDO_SLP,    BIT_0,  SLP_BIT_SET,    TRUE,   NULL},
176     {SLP_LDO_MAX,       NULL,           NULL,   SLP_BIT_SET,    TRUE,   NULL}
177 };
178
179 static  LDO_CTL_PTR Ldo_Get_Cfg(void)
180 {
181         return ldo_ctl_data;
182 }
183
184 /**---------------------------------------------------------------------------*
185  **                         Global variables                                  *
186  **---------------------------------------------------------------------------*/
187
188 LDO_CTL_PTR g_ldo_ctl_tab = NULL;
189
190
191 /*****************************************************************************/
192 //  Description:  Slp_Ldo_Get_Cfg
193 //      Global resource dependence: NONE
194 //  Author: 
195 //      Note:    Slp_Ldo_Get_Cfg
196 /*****************************************************************************/
197 static SLP_LDO_CTL_PTR Slp_Ldo_Get_Cfg(void)
198 {       
199         return  slp_ldo_ctl_data;
200 }
201
202 /**---------------------------------------------------------------------------*
203  **                         Function Declaration                              *
204  **---------------------------------------------------------------------------*/
205
206 /*****************************************************************************/
207 //  Description:  Turn on the LDO specified by input parameter ldo_id  
208 //      Global resource dependence: NONE
209 //  Author:  Tao.Feng && Yi.Qiu
210 //      Note:    return value = LDO_ERR_OK if operation is executed successfully           
211 /*****************************************************************************/
212 static  LDO_CTL_PTR LDO_GetLdoCtl(LDO_ID_E ldo_id)
213 {
214         int i = 0;
215         LDO_CTL_PTR ctl = NULL;
216         
217         SCI_ASSERT(NULL != g_ldo_ctl_tab);
218         
219         for(i=0; g_ldo_ctl_tab[i].id != LDO_LDO_MAX; i++)
220         {
221                 if( g_ldo_ctl_tab[i].id == ldo_id)
222                 {
223                         ctl = &g_ldo_ctl_tab[i];
224                         break;
225                 }
226         }
227                 
228         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
229
230         return ctl;
231 }
232
233 /*****************************************************************************/
234 //  Description:  Turn on the LDO specified by input parameter ldo_id  
235 //      Global resource dependence: NONE
236 //  Author:  Tao.Feng && Yi.Qiu
237 //      Note:    return value = LDO_ERR_OK if operation is executed successfully           
238 /*****************************************************************************/
239  LDO_ERR_E LDO_TurnOnLDO(LDO_ID_E ldo_id)
240 {
241         unsigned int reg_val;   
242         LDO_CTL_PTR ctl = NULL;
243         unsigned long flags;
244         
245         ctl = LDO_GetLdoCtl(ldo_id);
246         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
247
248         if(ctl->bp_reg == NULL){
249                 if (LDO_LDO_USBD == ldo_id){
250                         local_irq_save(flags);
251                         CHIP_REG_AND(GR_CLK_GEN5, (~LDO_USB_PD));
252                         //__raw_bits_and((~LDO_USB_PD), GR_CLK_GEN5);
253                         local_irq_restore(flags);
254                 }
255                 return LDO_ERR_OK;
256         }
257         //SCI_DisableIRQ();
258         local_irq_save(flags);
259         
260         SCI_PASSERT(ctl->ref >= 0, ("ctl->ref = %d", ctl->ref));
261         if(ctl->ref == 0) 
262                 REG_SETCLRBIT(ctl->bp_reg, ctl->bp_rst, ctl->bp);
263
264         ctl->ref++;
265         
266         //SCI_RestoreIRQ();
267         local_irq_restore(flags);
268
269         return LDO_ERR_OK;
270
271
272 /*****************************************************************************/
273 //  Description:  Turo off the LDO specified by parameter ldo_id
274 //      Global resource dependence: NONE
275 //  Author: Tao.Feng && Yi.Qiu
276 //      Note:           
277 /*****************************************************************************/
278  LDO_ERR_E LDO_TurnOffLDO(LDO_ID_E ldo_id)
279 {
280         unsigned int reg_val;
281         LDO_CTL_PTR ctl = NULL;
282         unsigned long flags;
283         
284         ctl = LDO_GetLdoCtl(ldo_id);
285         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
286
287         if(ctl->bp_reg == NULL){
288                 if (LDO_LDO_USBD == ldo_id){
289                         local_irq_save(flags);
290                         CHIP_REG_OR(GR_CLK_GEN5, (~LDO_USB_PD));
291                         //__raw_bits_or((~LDO_USB_PD), GR_CLK_GEN5);
292                         local_irq_restore(flags);
293                 }
294                 return LDO_ERR_OK;
295         }
296         //SCI_DisableIRQ();
297         local_irq_save(flags);
298         
299         if(ctl->ref > 0)
300             ctl->ref--;
301         
302         if(ctl->ref == 0)
303                 REG_SETCLRBIT(ctl->bp_reg, ctl->bp, ctl->bp_rst);
304         
305         //SCI_RestoreIRQ();
306         local_irq_restore(flags);
307         
308         return LDO_ERR_OK;
309 }
310
311 /*****************************************************************************/
312 //  Description: Find the LDO status -- ON or OFF
313 //      Global resource dependence: 
314 //  Author: Tao.Feng && Yi.Qiu
315 //      Note: return SCI_TRUE means LDO is ON, SCI_FALSE is OFF        
316 /*****************************************************************************/
317  int LDO_IsLDOOn(LDO_ID_E ldo_id)
318 {
319         unsigned int  masked_val = 0;
320         LDO_CTL_PTR ctl = NULL;
321
322         ctl = LDO_GetLdoCtl(ldo_id);
323         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
324
325         masked_val = (LDO_REG_GET(ctl->bp_reg) & ctl->bp);
326
327         return (masked_val ? 0 : 1);
328 }
329
330 /*****************************************************************************/
331 //  Description:  change the LDO voltage level specified by parameter ldo_id
332 //      Global resource dependence: 
333 //  Author: Tao.Feng && Yi.Qiu   
334 //      Note:           
335 /*****************************************************************************/
336  LDO_ERR_E LDO_SetVoltLevel(LDO_ID_E ldo_id, LDO_VOLT_LEVEL_E volt_level)
337
338 {
339         unsigned int b0_mask,b1_mask;
340         LDO_CTL_PTR  ctl = NULL;
341
342         b0_mask = (volt_level & BIT_0)?~0:0;
343         b1_mask = (volt_level & BIT_1)?~0:0;
344
345         ctl = LDO_GetLdoCtl(ldo_id);
346         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
347
348         if(ctl->level_reg_b0 == NULL)
349         {
350                 return LDO_ERR_ERR;
351         }
352
353         if(ctl->level_reg_b0 == ctl->level_reg_b1)
354         {
355                 SET_LEVEL(ctl->level_reg_b0, b0_mask, b1_mask, ctl->b0, ctl->b0_rst, ctl->b1, ctl->b1_rst);
356         }
357         else
358         {
359                 SET_LEVELBIT(ctl->level_reg_b0, b0_mask, ctl->b0, ctl->b0_rst);
360                 SET_LEVELBIT(ctl->level_reg_b1, b1_mask, ctl->b1, ctl->b1_rst);
361         }
362         
363         return LDO_ERR_OK;
364 }
365
366 /*****************************************************************************/
367 //  Description: Get LDO voltage level
368 //      Global resource dependence: 
369 //  Author: Tao.Feng && Yi.Qiu   
370 //      Note:           
371 /*****************************************************************************/
372  LDO_VOLT_LEVEL_E LDO_GetVoltLevel(LDO_ID_E ldo_id)
373 {
374         unsigned int level_ret = 0;
375         LDO_CTL_PTR ctl = NULL;
376
377         ctl = LDO_GetLdoCtl(ldo_id);
378         SCI_PASSERT(ctl != NULL, ("ldo_id = %d", ldo_id));
379
380         if(ctl->level_reg_b0 == ctl->level_reg_b1)
381         {
382                 GET_LEVEL(ctl->level_reg_b0, ctl->b0, ctl->b1, level_ret);
383         }
384         else
385         {
386                 GET_LEVELBIT(ctl->level_reg_b0, ctl->b0, BIT_0, level_ret);
387                 GET_LEVELBIT(ctl->level_reg_b1, ctl->b1, BIT_1, level_ret);
388         }
389
390         return level_ret;
391 }
392
393
394 /*****************************************************************************/
395 //  Description:  Shut down any LDO that do not used when system enters deepsleep
396 //      Global resource dependence: s_ldo_reopen[]
397 //  Author: Tao.Feng && Yi.Qiu   
398 //      Note:           
399 /*****************************************************************************/
400 void LDO_DeepSleepInit(void)
401 {
402         int i;
403         SLP_LDO_CTL_PTR  slp_ldo_ctl_tab;
404         
405         slp_ldo_ctl_tab = Slp_Ldo_Get_Cfg();
406
407         SCI_ASSERT(NULL != slp_ldo_ctl_tab);
408
409         for(i=0; slp_ldo_ctl_tab[i].id != SLP_LDO_MAX; i++)
410         {
411                 if(slp_ldo_ctl_tab[i].value == SLP_BIT_SET)
412                         ANA_REG_OR(slp_ldo_ctl_tab[i].ldo_reg, slp_ldo_ctl_tab[i].mask);
413                         //__raw_bits_or(slp_ldo_ctl_tab[i].mask, slp_ldo_ctl_tab[i].ldo_reg);
414                 else
415                         ANA_REG_AND(slp_ldo_ctl_tab[i].ldo_reg, ~slp_ldo_ctl_tab[i].mask);
416                         //__raw_bits_and(~slp_ldo_ctl_tab[i].mask, slp_ldo_ctl_tab[i].ldo_reg);
417         }
418
419 }
420
421 /*****************************************************************************/
422 //  Description:    this function is used to initialize LDO voltage level.
423 //      Global resource dependence: 
424 //  Author: Tao.Feng && Yi.Qiu
425 //      Note:           
426 /*****************************************************************************/
427 int LDO_Init(void)
428 {
429         int i;
430         
431         g_ldo_ctl_tab = Ldo_Get_Cfg();
432
433         SCI_ASSERT(NULL != g_ldo_ctl_tab);
434
435         for(i=0; g_ldo_ctl_tab[i].id != LDO_LDO_MAX; i++)
436         {
437                 if( g_ldo_ctl_tab[i].init_level != LDO_VOLT_LEVEL_MAX)
438                         LDO_SetVoltLevel(g_ldo_ctl_tab[i].id, g_ldo_ctl_tab[i].init_level);
439
440                 g_ldo_ctl_tab[i].ref = 0;
441         }
442
443         //deepsleep init set for ldo
444         LDO_DeepSleepInit();
445         
446         return LDO_ERR_OK;
447 }
448
449 /*****************************************************************************/
450 //  Description: turn off system core ldo
451 //  Global resource dependence:
452 //  Author: Mingwei.Zhang
453 //  Note:
454 /*****************************************************************************/
455 static void LDO_TurnOffCoreLDO (void)
456 {
457     ANA_REG_SET (ANA_LDO_PD_SET, ANA_LDO_PD_SET_MSK);   /// turn off system core ldo
458 }
459
460 /*****************************************************************************/
461 //  Description: turn off all module ldo befor system core ldo
462 //  Global resource dependence:
463 //  Author: Mingwei.Zhang
464 //  Note:
465 /*****************************************************************************/
466
467 static void LDO_TurnOffAllModuleLDO (void)
468 {
469     ANA_REG_SET (ANA_LDO_PD_CTL, ANA_LDO_PD_CTL_MSK);               ///turn off all module ldo
470     ANA_REG_MSK_OR (ANA_PA_CTL, LDO_PA_SET, (LDO_PA_SET|LDO_PA_RST)); ///PA poweroff
471 }
472 /*****************************************************************************/
473 //  Description:  Shut down all LDO when system poweroff
474 //  Global resource dependence:
475 //  Author: Mingwei.Zhang
476 //  Note:
477 /*****************************************************************************/
478 void LDO_TurnOffAllLDO (void)
479 {
480     LDO_TurnOffAllModuleLDO();
481     LDO_TurnOffCoreLDO();
482 }