tizen 2.4 release
[kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc9630 / dcdc_cal_x15.c
1 #include <common.h>
2 #include <asm/io.h>
3 #include <asm/arch/adc_drvapi.h>
4 #include <asm/arch/adi_hal_internal.h>
5 #include <asm/arch/sprd_reg.h>
6
7 int regulator_default_get(const char con_id[]);
8 void regulator_default_set(const char con_id[], int vol);
9 int regulator_default_set_all(void);
10 u32 regulator_get_calibration_mask(void);
11
12
13 #undef debug
14 #define debug0(format, arg...)
15 #define debug(format, arg...) printf("\t" format, ## arg)
16 #define debug2(format, arg...) printf("\t\t" format, ## arg)
17
18 /* abs() handles unsigned and signed longs, ints, shorts and chars.  For all input types abs()
19  * returns a signed long.
20  * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64() for those.*/
21 #define abs(x) ({                                                                       \
22                                 long ret;                                                       \
23                                 if (sizeof(x) == sizeof(long)) {                \
24                                         long __x = (x);                         \
25                                         ret = (__x < 0) ? -__x : __x;           \
26                                 } else {                                                        \
27                                         int __x = (x);                                  \
28                                         ret = (__x < 0) ? -__x : __x;           \
29                                 }                                                               \
30                                 ret;                                                            \
31                         })
32
33
34 #undef ffs
35 #undef fls
36
37 /* On ARMv5 and above those functions can be implemented around the clz instruction for
38  * much better code efficiency.         */
39
40 static inline int fls(int x)
41 {
42         int ret;
43
44         asm("clz\t%0, %1": "=r"(ret):"r"(x));
45         ret = 32 - ret;
46         return ret;
47 }
48
49 #define __fls(x) (fls(x) - 1)
50 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
51 #define __ffs(x) (ffs(x) - 1)
52 #define ffz(x) __ffs( ~(x) )
53
54 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
55
56 #define MEASURE_TIMES                           (15)
57
58 #define ADC_DROP_CNT    ( DIV_ROUND(MEASURE_TIMES, 5) )
59 static int __average(int a[], int N)
60 {
61         int i, sum = 0;
62         for (i = 0; i < N; i++)
63                 sum += a[i];
64         return DIV_ROUND(sum, N);
65 }
66
67 static void bubble_sort(int a[], int N)
68 {
69         int i, j, t;
70         for (i = 0; i < N - 1; i++) {
71                 for (j = i + 1; j < N; j++) {
72                         if (a[i] > a[j]) {
73                                 t = a[i];
74                                 a[i] = a[j];
75                                 a[j] = t;
76                         }
77                 }
78         }
79 }
80
81 int sci_adc_request(int channel)
82 {
83         int i;
84         int results[MEASURE_TIMES];
85
86         if (-1 == ADC_GetValues(channel, ADC_SCALE_3V, MEASURE_TIMES, results)) {
87                 return 0;
88         }
89
90         bubble_sort(results, MEASURE_TIMES);
91
92         /* dump results */
93         for (i = 0; i < MEASURE_TIMES; i++) {
94                 printf("%d ", results[i]);
95         }
96         printf("\n");
97
98         return __average(&results[ADC_DROP_CNT], MEASURE_TIMES - ADC_DROP_CNT * 2);
99 }
100
101 #define RATIO(_n_, _d_) (_n_ << 16 | _d_)
102
103 static int sci_adc_ratio(int channel, int mux)
104 {
105         switch (channel) {
106         case 0x05:              //vbat
107                 return RATIO(7, 29);
108         case 0x0D:              //dcdccore
109         case 0x0E:              //dcdcarm
110                 return RATIO(4, 5);
111         case 0x0F:              //dcdcmem
112                 return RATIO(3, 5);
113         case 0x10:              //dcdcgen
114                 return RATIO(4, 9);
115         case 0x15:              //DCDC Supply LDO
116                 return RATIO(1, 2);
117         case 0x13:              //DCDCVBATBK
118         case 0x14:              //DCDCHEADMIC
119         case 0x16:              //VBATD Domain LDO
120         case 0x17:              //VBATA Domain LDO
121         case 0x1E:              //DP from terminal
122         case 0x1F:              //DM from terminal
123                 return RATIO(1, 3);
124
125         default:
126                 return RATIO(1, 1);
127         }
128         return RATIO(1, 1);
129 }
130
131 static u32 bat_numerators, bat_denominators = 0;
132 extern uint16_t sprdbat_auxadc2vbatvol (uint16_t adcvalue);
133
134 int sci_adc_vol_request(int channel, int mux)
135 {
136         int adc_res;
137         adc_res = sci_adc_request(channel);
138         if (adc_res) {
139                 u32 res, chan_numerators, chan_denominators;
140                 res = (u32) sci_adc_ratio(channel, mux);
141                 chan_numerators = res >> 16;
142                 chan_denominators = res & 0xffff;
143                 return sprdbat_auxadc2vbatvol(adc_res)
144                     * (bat_numerators * chan_denominators)
145                     / (bat_denominators * chan_numerators);
146         }
147         return 0;
148 }
149
150 /* Simple shorthand for a section definition */
151 #ifndef __section
152 # define __section(S) __attribute__ ((__section__(#S)))
153 #endif
154
155 #define __init0 __section(.rodata.regu.init0)
156 #define __init1 __section(.rodata.regu.init1)
157 #define __init2 __section(.rodata.regu.init2)
158
159 const u32 __init0 __init_begin = 0xeeeebbbb;
160 const u32 __init2 __init_end = 0xddddeeee;
161
162 struct regulator_regs {
163         int typ;
164         u32 pd_set, pd_set_bit;
165         /* at new feature, some LDOs had only set, no rst bits.
166          * and DCDCs voltage and trimming controller is the same register */
167         u32 pd_rst, pd_rst_bit;
168         u32 slp_ctl, slp_ctl_bit;
169         u32 vol_trm, vol_trm_bits;
170         u32 cal_ctl, cal_ctl_bits;
171         u32 vol_def;
172         u32 vol_ctl, vol_ctl_bits;
173         u32 vol_sel_cnt, vol_sel[];
174 };
175
176 struct regulator_desc {
177         int id;
178         const char *name;
179         struct regulator_regs *regs;
180 };
181
182 #define REGU_VERIFY_DLY (1000)  /*ms */
183 #define SCI_REGU_REG(VDD, TYP, PD_SET, SET_BIT, PD_RST, RST_BIT, SLP_CTL, SLP_CTL_BIT, \
184                      VOL_TRM, VOL_TRM_BITS, CAL_CTL, CAL_CTL_BITS, VOL_DEF,     \
185                      VOL_CTL, VOL_CTL_BITS, VOL_SEL_CNT, ...)                                   \
186         static struct regulator_regs REGS_##VDD = {                                             \
187                 .typ = TYP,                                                     \
188                 .pd_set = PD_SET,                                       \
189                 .pd_set_bit = SET_BIT,                                  \
190                 .pd_rst = PD_RST,                                               \
191                 .pd_rst_bit = RST_BIT,                                  \
192                 .slp_ctl = SLP_CTL,                                             \
193                 .slp_ctl_bit = SLP_CTL_BIT,                             \
194                 .vol_trm = VOL_TRM,                                     \
195                 .vol_trm_bits = VOL_TRM_BITS,                   \
196                 .cal_ctl = CAL_CTL,                                     \
197                 .cal_ctl_bits = CAL_CTL_BITS,                   \
198                 .vol_def = VOL_DEF,                                     \
199                 .vol_ctl = VOL_CTL,                                     \
200                 .vol_ctl_bits = VOL_CTL_BITS,                   \
201                 .vol_sel_cnt = VOL_SEL_CNT,                     \
202                 .vol_sel = {__VA_ARGS__},                               \
203         };                                                                              \
204         struct regulator_desc __init1 DESC_##VDD = {    \
205                 .id = -1,                                                               \
206                 .name = #VDD,                                           \
207                 .regs = &REGS_##VDD,                                    \
208         };                                                                              \
209
210 #include <asm/arch/chip_x15/__regs_regulator_map.h>
211
212
213 /* standard dcdc ops*/
214 static int adjust_ldo_vol_base(struct regulator_desc *desc)
215 {
216         struct regulator_regs *regs = desc->regs;
217
218         if (regs->vol_sel_cnt == 2) {
219                 if ((0 == strcmp(desc->name, "vdd18"))
220                         || (0 == strcmp(desc->name, "vddemmcio"))
221                         || (0 == strcmp(desc->name, "vddcamd"))
222                         || (0 == strcmp(desc->name, "vddcamio"))) {
223
224                         regs->vol_sel[0] = 1400;
225                 }
226         }
227         debug0("%s vol base %dmv\n", desc->name, regs->vol_sel[0]);
228         return regs->vol_sel[0];
229 }
230
231 static int __dcdc_is_up_down_adjust(struct regulator_desc *desc)
232 {
233         return ((0 == strcmp(desc->name, "dcdcmem")) ? 1 : 0);
234 }
235
236 static int dcdc_get_trimming_step(struct regulator_desc *desc, int to_vol)
237 {
238         /* FIXME: vddmem step 200/32mV */
239         return (!strcmp(desc->name, "dcdcmem") ) ? (1000 * 200 / 32) : (1000 * 100 / 32) /*uV */;
240 }
241
242 static int __match_dcdc_vol(struct regulator_desc *desc, u32 vol)
243 {
244         int i, j = -1;
245         int ds, min_ds = 100;   /* mV, the max range of small voltage */
246         const struct regulator_regs *regs = desc->regs;
247
248         for (i = 0; i < regs->vol_sel_cnt; i++) {
249                 ds = vol - regs->vol_sel[i];
250                 if (ds >= 0 && ds < min_ds) {
251                         min_ds = ds;
252                         j = i;
253                 }
254         }
255
256         if (j < 0) {
257                 for (i = 0; i < regs->vol_sel_cnt; i++) {
258                         ds = abs(vol - regs->vol_sel[i]);
259                         if (ds < min_ds) {
260                                 min_ds = ds;
261                                 j = i;
262                         }
263                 }
264         }
265
266         return j;
267 }
268
269 static int dcdc_get_voltage(struct regulator_desc *desc)
270 {
271         const struct regulator_regs *regs = desc->regs;
272         u32 mv;
273         int cal = 0;            /* uV */
274         int i, shft = __ffs(regs->vol_ctl_bits);
275
276         i = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> shft;
277         mv = regs->vol_sel[i];
278
279         cal = (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> __ffs(regs->vol_trm_bits);
280         if (__dcdc_is_up_down_adjust(desc)) {
281                 cal -= 0x10;
282         }
283         cal *= dcdc_get_trimming_step(desc, 0); /*uV */
284
285         debug0("%s %d +%dmv\n", desc->name, mv, cal / 1000);
286         return mv + cal / 1000;
287 }
288
289 static int dcdc_set_voltage(struct regulator_desc *desc, int min_mV, int max_mV)
290 {
291         const struct regulator_regs *regs = desc->regs;
292         int i, mv = min_mV;
293
294         /* found the closely vol ctrl bits */
295         i = __match_dcdc_vol(desc, mv);
296         if (i < 0) {
297                 debug2("%s: %s failed to match voltage: %d\n",__func__,desc->name,mv);
298                 return -1;
299         }
300
301         /* dcdc calibration control bits (default 0) small adjust voltage: 100/32mv ~= 3.125mv */
302         {
303                 int shft_ctl = __ffs(regs->vol_ctl_bits);
304                 int shft_trm = __ffs(regs->vol_trm_bits);
305                 int step = dcdc_get_trimming_step(desc, mv);
306                 int j = (int)(mv - (int)regs->vol_sel[i]) * 1000 / step;
307
308                 if (__dcdc_is_up_down_adjust(desc))
309                         j += 0x10;
310
311                 debug2("regu_dcdc %p (%s) %d = %d %+dmv (trim=%d step=%duv);\n", regs, desc->name,
312                            mv, regs->vol_sel[i], mv - regs->vol_sel[i], j, step);
313
314                 if (j >= 0 && j <= (regs->vol_trm_bits >> shft_trm))
315                         ANA_REG_MSK_OR(regs->vol_ctl, (j << shft_trm) | (i << shft_ctl),
316                                 regs->vol_trm_bits | regs->vol_ctl_bits);
317         }
318         return 0;
319 }
320
321 static int dcdc_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
322 {
323         //int acc_vol = dcdc_get_trimming_step(desc, to_vol) / 1000;
324         int ctl_vol = (def_vol - (adc_vol - to_vol));
325
326         return dcdc_set_voltage(desc, ctl_vol, ctl_vol);
327 }
328
329 static int ldo_get_voltage(struct regulator_desc *desc)
330 {
331         const struct regulator_regs *regs = desc->regs;
332         u32 vol;
333
334         if (regs->vol_trm && regs->vol_sel_cnt == 2) {
335                 int shft = __ffs(regs->vol_trm_bits);
336                 u32 trim =
337                     (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft;
338                 vol = regs->vol_sel[0] * 1000 + trim * regs->vol_sel[1];
339                 vol /= 1000;
340                 debug0("%s voltage %dmv\n", desc->name, vol);
341                 return vol;
342         }
343
344         return -1;
345 }
346
347 static int ldo_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
348 {
349         const struct regulator_regs *regs = desc->regs;
350         int ret = -1;
351
352         if (!regs->vol_ctl && regs->vol_sel_cnt == 2) {
353                 /* ctl_vol = vol_base + reg[vol_trm] * vol_step  */
354                 int shft = __ffs(regs->vol_trm_bits);
355                 int ctl_vol = (def_vol - (adc_vol - to_vol));   //same as dcdc?
356                 u32 trim = 0;
357                 if(adc_vol > to_vol)
358                         trim = DIV_ROUND_UP((ctl_vol - regs->vol_sel[0]) * 1000, regs->vol_sel[1]);
359                 else
360                         trim = ((ctl_vol - regs->vol_sel[0]) * 1000 / regs->vol_sel[1]);
361
362                 debug2("regu_ldo %p (%s) %d = %d %+dmv (trim=%d step=%duv vol_base=%dmv)\n", regs, desc->name,
363                         ctl_vol, regs->vol_sel[0], ctl_vol - regs->vol_sel[0], trim, regs->vol_sel[1], regs->vol_sel[0]);
364
365                 if ((trim >= 0) && (trim <= (regs->vol_trm_bits >> shft))) {
366                         ANA_REG_MSK_OR(regs->vol_trm,
367                                         trim << shft,
368                                         regs->vol_trm_bits);
369                         ret = 0;
370                 }
371         }
372
373         return ret;
374 }
375
376 static int DCDC_Cal_One(struct regulator_desc *desc, int is_cal)
377 {
378         struct regulator_regs *regs = desc->regs;
379         int def_vol = 0, to_vol = 0;
380         int adc_vol = 0, cal_vol = 0;
381         int ret = -1, adc_chan = regs->cal_ctl_bits >> 16;
382         u16 ldo_cal_sel = regs->cal_ctl_bits & 0xFFFF;
383
384         if (!adc_chan || !regs->vol_def)
385                 return -1;
386
387         if(0x2711A000 == ANA_GET_CHIP_ID()) {
388                 if (desc->regs->typ == 0) {
389                         adjust_ldo_vol_base(desc);
390                 }
391         }
392
393         if (ldo_cal_sel)
394                 ANA_REG_OR(regs->cal_ctl, ldo_cal_sel);
395
396         /*
397          * FIXME: force get dcdc&ldo voltage from ana global regs
398          * and get ideal voltage from vol para.
399          */
400         if (desc->regs->typ == 2 /*DCDC*/) {
401                 def_vol = dcdc_get_voltage(desc);
402         }
403         else if (desc->regs->typ == 0 /*LDO*/) {
404                 def_vol = ldo_get_voltage(desc);
405         }
406
407         to_vol = regulator_default_get(desc->name);
408         if (!to_vol)
409                 to_vol = regs->vol_def;
410
411         adc_vol = sci_adc_vol_request(adc_chan, ldo_cal_sel);
412         if (adc_vol <= 0) {
413                 debug("%s default %dmv, adc channel %d, maybe not enable\n", desc->name, def_vol, adc_chan);
414                 goto exit;
415         }
416
417         cal_vol = abs(adc_vol - to_vol);
418         debug("%s default %dmv, from %dmv to %dmv, bias %c%d.%03d%%\n",
419               desc->name, def_vol, adc_vol, to_vol,
420               (adc_vol > to_vol) ? '+' : '-',
421               cal_vol * 100 / to_vol, cal_vol * 100 * 1000 / to_vol % 1000);
422
423         if (!def_vol || !to_vol || adc_vol <= 0)
424                 goto exit;
425         if (abs(adc_vol - def_vol) >= def_vol / 9)      /* adjust limit 9% */
426                 goto exit;
427         else if (cal_vol < to_vol / 100) {      /* bias 1% */
428                 goto exit;
429         }
430
431         if (is_cal) {
432                 if (regs->typ == 2/*VDD_TYP_DCDC*/)
433                         ret = dcdc_set_trimming(desc, def_vol, to_vol, adc_vol);
434                 else if (regs->typ == 0/*VDD_TYP_LDO*/)
435                         ret = ldo_set_trimming(desc, def_vol, to_vol, adc_vol);
436
437                 if(ret < 0)
438                         regulator_default_set(desc->name, 0);
439         }
440
441 exit:
442         if (ldo_cal_sel)
443                 ANA_REG_BIC(regs->cal_ctl, ldo_cal_sel);
444
445         return ret;
446 }
447
448 int DCDC_Cal_ArmCore(void)
449 {
450         u16 regval_dcdc_store, regval_ldo_store;
451         u32 res;
452         struct regulator_desc *desc = NULL;
453         struct regulator_desc *desc_end = NULL;
454         u32 cali_mask = regulator_get_calibration_mask();
455         u32 chip_id = ANA_GET_CHIP_ID();
456
457         printf("%s; adie chip id 0x%08x\n", __FUNCTION__, chip_id);
458
459         regval_dcdc_store = ANA_REG_GET(ANA_REG_GLB_LDO_DCDC_PD) & 0xFFFF;
460         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, BITS_PWR_WR_PROT_VALUE(0x6e7f), 0x7FFF);
461         ANA_REG_BIC(ANA_REG_GLB_LDO_DCDC_PD, (cali_mask >> 16));
462         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, 0, 0x7FFF);
463
464         regval_ldo_store = ANA_REG_GET(ANA_REG_GLB_LDO_PD_CTRL) & 0xFFFF;
465         ANA_REG_BIC(ANA_REG_GLB_LDO_PD_CTRL, cali_mask & 0xFFFF);
466
467         if(0x2711A000 == chip_id) {
468                 //FIXME: vddcamio/vddcamd/vddemmcio/vdd18 real voltage value is greater than design value
469                 ANA_REG_MSK_OR(ANA_REG_GLB_LDO_V_CTRL9, BITS_LDO_VDD18_V(0x40),
470                                 BITS_LDO_VDD18_V(-1)); //0x68D2 -->0x40D2
471                 ANA_REG_MSK_OR(ANA_REG_GLB_LDO_V_CTRL2, BITS_LDO_EMMCIO_V(0x40),
472                                 BITS_LDO_EMMCIO_V(-1));  //0x3C68 -->0x3C40
473                 ANA_REG_MSK_OR(ANA_REG_GLB_LDO_V_CTRL1, BITS_LDO_CAMIO_V(0x40) | BITS_LDO_CAMD_V(0x10),
474                                 BITS_LDO_CAMIO_V(-1) | BITS_LDO_CAMD_V(-1)); //0x6838 -->0x4010
475                 udelay(200 * 1000); //wait 200ms
476         }
477
478         /* FIXME: Update CHGMNG_AdcvalueToVoltage table before setup vbat ratio. */
479         /*ADC_CHANNEL_VBAT is 5*/
480         res = (u32) sci_adc_ratio(5, 0);
481         bat_numerators = res >> 16;
482         bat_denominators = res & 0xffff;
483
484
485         /* TODO: calibrate all DCDCs */
486         desc = (struct regulator_desc *)(&__init_begin + 1);
487
488         printf("%p (%x) -- %p -- %p (%x)\n", &__init_begin, __init_begin,
489                 desc, &__init_end, __init_end);
490
491         desc_end = (struct regulator_desc *)&__init_end;
492         while (--desc_end >= desc) { /* reverse order */
493                 printf("\nCalibrate %s ...\n", desc_end->name);
494                 DCDC_Cal_One(desc_end, 1);
495         }
496
497         /* wait a moment for LDOs ready */
498         udelay(200 * 1000);
499
500         /* TODO: verify all DCDCs */
501         desc = (struct regulator_desc *)(&__init_begin + 1);
502         desc_end = (struct regulator_desc *)&__init_end;
503         while (--desc_end >= desc) { /* reverse order */
504                 printf("\nVerify %s ...\n", desc_end->name);
505                 DCDC_Cal_One(desc_end, 0);
506         }
507
508         /* restore adie dcdc/ldo PD bits */
509         ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regval_ldo_store);
510         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, BITS_PWR_WR_PROT_VALUE(0x6e7f), 0x7FFF);
511         ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD, regval_dcdc_store);
512         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, 0, 0x7FFF);
513
514         return 0;
515 }
516
517
518 int regulator_init(void)
519 {
520         /*
521          * FIXME: turn on all DCDC/LDOs if need
522          */
523         return 0;
524 }
525
526 struct regulator_desc *regulator_get(void/*struct device*/ *dev, const char *id)
527 {
528         struct regulator_desc *desc =
529                 (struct regulator_desc *)(&__init_begin + 1);
530         while (desc < (struct regulator_desc *)&__init_end) {
531                 if (0 == strcmp(desc->name, id))
532                         return desc;
533                 desc++;
534         }
535         return 0;
536 }
537
538 int regulator_disable_all(void)
539 {
540         ANA_REG_OR(ANA_REG_GLB_LDO_PD_CTRL, 0x7ff);
541         ANA_REG_OR(ANA_REG_GLB_LDO_DCDC_PD, 0x1fff);
542 }
543
544 int regulator_enable_all(void)
545 {
546         ANA_REG_BIC(ANA_REG_GLB_LDO_DCDC_PD, 0x1fff);
547         ANA_REG_BIC(ANA_REG_GLB_LDO_PD_CTRL, 0x7ff);
548 }
549
550 int regulator_disable(const char con_id[])
551 {
552         struct regulator_desc *desc = regulator_get(0, con_id);
553         if (desc) {
554                 struct regulator_regs *regs = desc->regs;
555                 ANA_REG_OR(regs->pd_set, regs->pd_set_bit);
556         }
557         return 0;
558 }
559
560 int regulator_enable(const char con_id[])
561 {
562         struct regulator_desc *desc = regulator_get(0, con_id);
563         if (desc) {
564                 struct regulator_regs *regs = desc->regs;
565                 ANA_REG_BIC(regs->pd_set, regs->pd_set_bit);
566         }
567         return 0;
568 }
569
570 int regulator_set_voltage(const char con_id[], int to_vol)
571 {
572         int ret = 0;
573         struct regulator_desc *desc = regulator_get(0, con_id);
574         if (desc) {
575                 struct regulator_regs *regs = desc->regs;
576                 if (regs->typ == 2/*VDD_TYP_DCDC*/)
577                         ret = dcdc_set_voltage(desc, to_vol, 0);
578                 else if (regs->typ == 0/*VDD_TYP_LDO*/)
579                         ret = ldo_set_trimming(desc, 0, to_vol, 0);
580         }
581         return ret;
582 }
583
584 typedef struct {
585         uint16 ideal_vol;
586         const char name[14];
587 }vol_para_t;
588
589 vol_para_t **ppvol_para = 0x50005c20;
590
591 static int get_vol_para_num(void)
592 {
593         int i = 0;
594
595         if (!(ppvol_para && *ppvol_para))
596                 return 0;
597
598         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
599                 return 0;
600
601         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end"))
602                 ;
603
604         return (i+1);
605 }
606
607 static vol_para_t * match_vol_para(const char* vol_name)
608 {
609         int i = 0;
610
611         BUG_ON(NULL == vol_name);
612
613         if (!(ppvol_para && *ppvol_para))
614                 return NULL;
615
616         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
617                 return NULL;
618
619         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end")) {
620                 if (0 == strcmp((*ppvol_para)[i].name, vol_name)) {
621                         debug("%s name %s, ideal_vol %d\n", __func__, (*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
622                         return (vol_para_t*)(&(*ppvol_para)[i]);
623                 }
624         }
625
626         return NULL;
627 }
628
629 int regulator_default_get(const char con_id[])
630 {
631         vol_para_t * pvol_para = match_vol_para(con_id);
632
633         return (int)(pvol_para ? pvol_para->ideal_vol : 0);
634 }
635
636 void regulator_default_set(const char con_id[], int vol)
637 {
638         vol_para_t * pvol_para = match_vol_para(con_id);
639
640         if(pvol_para) {
641                 pvol_para->ideal_vol = vol;
642         }
643 }
644
645 int regulator_default_set_all(void)
646 {
647         int i = 0, ret = 0;
648
649         //dump & check all vol para
650         if (!(ppvol_para && *ppvol_para))
651                 return -1;
652
653         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
654                 return 0;
655
656         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end")) {
657                 debug("regu: [%d] %s : %d\n", i, (*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
658
659                 ret |= regulator_set_voltage((*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
660         }
661
662         return ret;
663 }
664
665 /********************************************************************
666 *
667 * regulator_get_calibration_mask - get dcdc/ldo calibration flag
668 *
669 //
670 //High 16bit: dcdc ctrl calibration flag
671 //
672 * bit[13] ~ bit[15] : reserved
673 * bit[12] : dcdcgen
674 * bit[11] : dcdcmem
675 * bit[10] : dcdcarm
676 * bit[9]   : dcdccore
677 * bit[8]   : vddrf0
678 * bit[7]   : vddemmccore
679 * bit[6]   : vddemmcio
680 * bit[5]   : vdddcxo
681 * bit[4]   : vddcon
682 * bit[3]   : vdd25
683 * bit[2]   : vdd28
684 * bit[1]   : vdd18
685 * bit[0]   : vddbg
686
687 //
688 //Low 16bit: ldo ctrl calibration flag
689 //
690 * bit[12] ~ bit[15] : reserved
691 * bit[11] : vddlpref
692 * bit[10] : dcdcwpa
693 * bit[9]   : vddclsg
694 * bit[8]   : vddusb
695 * bit[7]   : vddcammot
696 * bit[6]   : vddcamio
697 * bit[5]   : vddcamd
698 * bit[4]   : vddcama
699 * bit[3]   : vddsim2
700 * bit[2]   : vddsim1
701 * bit[1]   : vddsim0
702 * bit[0]   : vddsd
703 ********************************************************************/
704 u32 regulator_get_calibration_mask(void)
705 {
706         int len = get_vol_para_num();
707         volatile vol_para_t *pvol_para = (volatile vol_para_t *)(*ppvol_para);
708         volatile u32* pdebug_flag = (u32*)(&pvol_para[len-1]);
709
710         if(len > 2) {
711                 printf("%s, vol_para_tbl_len %d, ldo_pd_mask 0x%08x; \n", __func__, len, *pdebug_flag);
712                 return (*pdebug_flag);
713         }
714 }
715