arm: sc8830: remove build warnings
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8830 / dcdc_cal_sc2723.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 typedef void (*pfun)(int);
13 static pfun calibrate_post = NULL;
14
15 static u16 ana_mixed_ctl;
16
17 #define REGU_CALI_DEBUG
18
19 #ifdef REGU_CALI_DEBUG
20 #define regu_debug(fmt, arg...)         printf(fmt, ## arg)
21 #else
22 #define regu_debug(fmt, arg...)
23 #endif
24
25 #undef debug
26 #define debug0(format, arg...)
27 #define debug(format, arg...)           regu_debug(format, ## arg)
28 #define debug1(format, arg...)          regu_debug("\t" format, ## arg)
29 #define debug2(format, arg...)          regu_debug("\t\t" format, ## arg)
30
31 /* abs() handles unsigned and signed longs, ints, shorts and chars.  For all input types abs()
32  * returns a signed long.
33  * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64() for those.*/
34 #define abs(x) ({                                                                       \
35                                 long ret;                                                       \
36                                 if (sizeof(x) == sizeof(long)) {                \
37                                         long __x = (x);                         \
38                                         ret = (__x < 0) ? -__x : __x;           \
39                                 } else {                                                        \
40                                         int __x = (x);                                  \
41                                         ret = (__x < 0) ? -__x : __x;           \
42                                 }                                                               \
43                                 ret;                                                            \
44                         })
45
46
47 #undef ffs
48 #undef fls
49
50 /* On ARMv5 and above those functions can be implemented around the clz instruction for
51  * much better code efficiency.         */
52
53 static inline int fls(int x)
54 {
55         int ret;
56
57         asm("clz\t%0, %1": "=r"(ret):"r"(x));
58         ret = 32 - ret;
59         return ret;
60 }
61
62 #define __fls(x) (fls(x) - 1)
63 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
64 #define __ffs(x) (ffs(x) - 1)
65 #define ffz(x) __ffs( ~(x) )
66
67 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
68
69 #define MEASURE_TIMES                           (15)
70
71 #define ADC_DROP_CNT    ( DIV_ROUND(MEASURE_TIMES, 5) )
72 static int __average(int a[], int N)
73 {
74         int i, sum = 0;
75         for (i = 0; i < N; i++)
76                 sum += a[i];
77         return DIV_ROUND(sum, N);
78 }
79
80 static void bubble_sort(int a[], int N)
81 {
82         int i, j, t;
83         for (i = 0; i < N - 1; i++) {
84                 for (j = i + 1; j < N; j++) {
85                         if (a[i] > a[j]) {
86                                 t = a[i];
87                                 a[i] = a[j];
88                                 a[j] = t;
89                         }
90                 }
91         }
92 }
93
94 //#define ADC_CALI_DEBUG
95
96 #ifdef ADC_CALI_DEBUG
97 static short adc_data[4][2] = {
98         /* same as nv adc_t */
99         {4200, 3360}, /* 4.2@VBAT Reserved IdealA Value */
100         {3600, 2877}, /* 3.6@VBAT Reserved IdealB Value */
101         {900, 0}, /* 0.9@VBAT, Reserved IdealC Value */
102         {300, 0}, /* 0.3@VBAT, Reserved IdealD Value */
103 };
104
105 static int adc2vbat(int adc_res, int scale)
106 {
107         int t = 0;
108
109         if (scale) {
110                 t = adc_data[0][0] - adc_data[1][0];
111                 t *= (adc_res - adc_data[0][1]);
112                 t /= (adc_data[0][1] - adc_data[1][1]);
113                 t += adc_data[0][0];
114         } else {
115                 t = adc_data[2][0] - adc_data[3][0];
116                 t *= (adc_res - adc_data[2][1]);
117                 t /= (adc_data[2][1] - adc_data[3][1]);
118                 t += adc_data[2][0];
119         }
120
121         return t;
122 }
123 #endif
124
125 static int sci_adc_request(int channel, int scale)
126 {
127         int results[MEASURE_TIMES];
128
129         if (-1 == ADC_GetValues(channel, scale, MEASURE_TIMES, results)) {
130                 return 0;
131         }
132
133         bubble_sort(results, MEASURE_TIMES);
134
135 #if defined(ADC_CALI_DEBUG)
136 {
137         int i = 0;
138         /* dump results */
139         for (i = 0; i < MEASURE_TIMES; i++) {
140                 debug("%d ", results[i]);
141         }
142         debug("\n");
143 }
144 #endif
145
146         return __average(&results[ADC_DROP_CNT], MEASURE_TIMES - ADC_DROP_CNT * 2);
147 }
148
149 #define RATIO(_n_, _d_) (_n_ << 16 | _d_)
150
151 static int sci_adc_ratio(int channel, int scale, int mux)
152 {
153         switch (channel) {
154         case 0x00:
155                 return RATIO(1, 1);
156         case 0x01:
157         case 0x02:
158         case 0x03:
159                 return ((ADC_SCALE_3V == scale) ? RATIO(400, 1025) : RATIO(1, 1));
160         case 0x05:              //Vbat
161         case 0x08:
162                 return RATIO(7, 29);
163         case 0x06:
164                 return RATIO(77, 1024);
165         case 0x0D:  //dcdc core/arm/mem/gen/rf/con/wpa
166                 mux = mux >> 13;
167                 switch (mux) {
168                 case 1: //dcdcarm
169                 case 2: //dcdccore
170                         return ((ADC_SCALE_3V == scale) ? RATIO(36, 55) : RATIO(9, 11));
171                 case 3: //dcdcmem
172                 case 5: //dcdcrf
173                         return ((ADC_SCALE_3V == scale) ? RATIO(12, 25) : RATIO(3, 5));
174                 case 4: //dcdcgen
175                         return ((ADC_SCALE_3V == scale) ? RATIO(3, 10) : RATIO(3, 8));
176                 case 6: //dcdccon
177                         return ((ADC_SCALE_3V == scale) ? RATIO(9, 20) : RATIO(9, 16));
178                 case 7: //dcdwpa
179                         return ((ADC_SCALE_3V == scale) ? RATIO(12, 55) : RATIO(3, 11));
180                 default:
181                         return RATIO(1, 1);
182                 }
183         case 0xE:       //LP dcxo
184                 return ((ADC_SCALE_3V == scale) ? RATIO(4, 5) : RATIO(1, 1));
185         case 0x14:      //headmic
186                 return RATIO(1, 3);
187
188         case 0x15:      //dcdc supply LDO, vdd18/vddcamd/vddcamio/vddrf0/vddgen1/vddgen0
189                 return RATIO(1, 2);
190         case 0x13:      //VbatBK
191         case 0x16:      //VbatD Domain LDO, vdd25/vddcama/vddsim2/vddsim1/vddsim0
192         case 0x17:      //VbatA Domain LDO,  vddwifipa/vddcammot/vddemmccore/vdddcxo/vddsdcore/vdd28
193         case 0x18:      //kpled/vibr
194         case 0x1D://vddsdio/vddusb/vddfgu
195         case 0x1E:              //DP from terminal
196         case 0x1F:              //DM from terminal
197                 return RATIO(1, 3);
198
199         default:
200                 return RATIO(1, 1);
201         }
202         return RATIO(1, 1);
203 }
204
205
206 static u32 bat_numerators, bat_denominators = 0;
207 extern uint16_t sprdbat_auxadc2vbatvol (uint16_t adcvalue);
208 extern u32 __adie_efuse_read(int blk_index);
209
210 static int sci_adc_vol_request(int channel, int scale, int mux, int* adc)
211 {
212         int chan_adc, chan_vol;
213
214         if(0 == bat_denominators) {
215                 u32 res;
216                 /* FIXME: Update CHGMNG_AdcvalueToVoltage table before setup vbat ratio. */
217                 /*ADC_CHANNEL_VBAT is 5*/
218                 res = (u32) sci_adc_ratio(5, ADC_SCALE_3V, 0);
219                 bat_numerators = res >> 16;
220                 bat_denominators = res & 0xffff;
221         }
222
223         chan_adc = sci_adc_request(channel, scale);
224         if (chan_adc) {
225                 u32 res, chan_numerators, chan_denominators;
226                 res = (u32) sci_adc_ratio(channel, scale, mux);
227                 chan_numerators = res >> 16;
228                 chan_denominators = res & 0xffff;
229
230                 if(adc)
231                         *adc = chan_adc;
232
233         #ifdef ADC_CALI_DEBUG
234                 chan_vol = adc2vbat(chan_adc, 1);
235         #else
236                 chan_vol = sprdbat_auxadc2vbatvol(chan_adc);
237         #endif
238
239                 chan_vol *= (bat_numerators * chan_denominators);
240                 chan_vol /= (bat_denominators * chan_numerators);
241
242                 return chan_vol;
243         }
244
245         return 0;
246 }
247
248 /* Simple shorthand for a section definition */
249 #ifndef __section
250 # define __section(S) __attribute__ ((__section__(#S)))
251 #endif
252
253 #define __init0 __section(.rodata.regu.init0)
254 #define __init1 __section(.rodata.regu.init1)
255 #define __init2 __section(.rodata.regu.init2)
256
257 static const u32 __init0 __init_begin = 0xeeeebbbb;
258 static const u32 __init2 __init_end = 0xddddeeee;
259
260 struct regulator_regs {
261         int typ; /* BIT4: default on/off(0: off, 1: on); BIT0~BIT3: dcdc/ldo type(0: ldo; 2: dcdc) */
262         unsigned long pd_set;
263         u32 pd_set_bit;
264         unsigned long vol_trm;
265         u32 vol_trm_bits;
266         unsigned long cal_ctl;
267         u32 cal_ctl_bits;
268         //u32 min_mV, step_uV;
269         u32 vol_def;
270         unsigned long vol_ctl;
271         u32 vol_ctl_bits;
272         u32 vol_sel_cnt, vol_sel[];
273 };
274
275
276 struct regulator_desc {
277         int id;
278         const char *name;
279         struct regulator_regs *regs;
280 };
281
282 #define REGU_VERIFY_DLY (1000)  /*ms */
283 #define SCI_REGU_REG(VDD, TYP, PD_SET, SET_BIT, \
284                      VOL_TRM, VOL_TRM_BITS, CAL_CTL, CAL_CTL_BITS, VOL_DEF,     \
285                      VOL_CTL, VOL_CTL_BITS, VOL_SEL_CNT, ...)           \
286         static struct regulator_regs REGS_##VDD = {                                             \
287                 .typ = TYP,                                                     \
288                 .pd_set = PD_SET,                                       \
289                 .pd_set_bit = SET_BIT,                          \
290                 .vol_trm = VOL_TRM,                                     \
291                 .vol_trm_bits = VOL_TRM_BITS,           \
292                 .cal_ctl = CAL_CTL,                                     \
293                 .cal_ctl_bits = CAL_CTL_BITS,           \
294                 .vol_def = VOL_DEF,                                     \
295                 .vol_ctl = VOL_CTL,                                     \
296                 .vol_ctl_bits = VOL_CTL_BITS,           \
297                 .vol_sel_cnt = VOL_SEL_CNT,                     \
298                 .vol_sel = {__VA_ARGS__},                       \
299         };                                                                              \
300         struct regulator_desc __init1 DESC_##VDD = {    \
301                 .id = -1,                                                               \
302                 .name = #VDD,                                           \
303                 .regs = &REGS_##VDD,                                    \
304         };                                                                              \
305
306 #include <asm/arch/__sc2723_regulator_map.h>
307
308
309 /* standard dcdc ops*/
310
311 static int dcdc_get_trimming_step(struct regulator_desc *desc, int to_vol)
312 {
313 #if 0
314         if (0 == strcmp(desc->name, "vddmem")) {
315                 /* FIXME: vddmem step 200/32mV */
316                 return 1000 * 200 / 32; /*uV */
317         }
318 #endif
319         return 1000 * 100 / 32; /*uV */
320 }
321
322 static int __match_vol(struct regulator_desc *desc, u32 vol)
323 {
324         int i, j = -1;
325         int ds, min_ds = 100;   /* mV, the max range of small voltage */
326         struct regulator_regs *regs = desc->regs;
327
328         for (i = 0; i < regs->vol_sel_cnt; i++) {
329                 ds = (int)(vol - regs->vol_sel[i]);
330                 if (ds >= 0 && ds < min_ds) {
331                         min_ds = ds;
332                         j = i;
333                 }
334         }
335
336         if ((2 == (regs->typ & (BIT(4) - 1))) && (j < 0)) {
337                 for (i = 0; i < regs->vol_sel_cnt; i++) {
338                         ds = abs(vol - regs->vol_sel[i]);
339                         if (ds < min_ds) {
340                                 min_ds = ds;
341                                 j = i;
342                         }
343                 }
344         }
345
346         return j;
347 }
348
349 static int dcdc_get_voltage(struct regulator_desc *desc)
350 {
351         struct regulator_regs *regs = desc->regs;
352         u32 mv = 0;
353         int cal = 0; /* uV */
354         int i = 0;
355
356         BUG_ON(regs->vol_sel_cnt > 8);
357
358         if (regs->vol_ctl) {
359                 int shft_ctl = __ffs(regs->vol_ctl_bits);
360                 int shft_trm = __ffs(regs->vol_trm_bits);
361
362                 i = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> shft_ctl;
363                 mv = regs->vol_sel[i];
364
365                 if (regs->vol_trm) {
366                         cal = (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft_trm;
367                         cal *= dcdc_get_trimming_step(desc, 0); /*uV */
368                 }
369
370                 debug0("%s %d +%dmv(trim %#x)\n", desc->name, mv, cal / 1000, cal / dcdc_get_trimming_step(desc, 0));
371
372         } else if (regs->vol_trm && regs->vol_sel_cnt == 2) {
373                 int shft_trm = __ffs(regs->vol_trm_bits);
374                 u32 trim =
375                     (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft_trm;
376                 mv = regs->vol_sel[0] + trim * regs->vol_sel[1] / 1000;
377
378                 debug0("%s %d +%dmv(trim %#x)\n", desc->name, regs->vol_sel[0], (mv - regs->vol_sel[0]), trim);
379         }
380
381         return (mv + cal / 1000);
382 }
383
384 static int dcdc_set_voltage(struct regulator_desc *desc, int min_mV, int max_mV)
385 {
386         struct regulator_regs *regs = desc->regs;
387         int i = 0, mv = min_mV;
388
389         if (regs->vol_ctl) {
390                 /* found the closely vol ctrl bits */
391                 i = __match_vol(desc, mv);
392                 if (i < 0) {
393                         debug2("%s: %s failed to match voltage: %d\n", __func__, desc->name, mv);
394                         return -1;
395                 }
396         }
397
398         /* dcdc calibration control bits (default 0) small adjust voltage: 100/32mv ~= 3.125mv */
399         {
400                 int shft_trm = __ffs(regs->vol_trm_bits);
401                 int shft_ctl = 0;
402                 int step = 0;
403                 int j = 0;
404
405                 if (regs->vol_ctl) {
406                         shft_ctl = __ffs(regs->vol_ctl_bits);
407                         step = dcdc_get_trimming_step(desc, mv);
408
409                         j = (int)(mv - (int)regs->vol_sel[i]) * 1000 / step;
410                 } else {
411                         if(regs->vol_sel_cnt == 2) {
412                                 step = regs->vol_sel[1];
413                                 j = DIV_ROUND_UP((mv - regs->vol_sel[0]) * 1000, step);
414                         }
415                 }
416
417                 debug2("regu_dcdc %p (%s) %d = %d %+dmv (trim=%d step=%duv);\n", regs, desc->name,
418                            mv, regs->vol_sel[i], mv - regs->vol_sel[i], j, step);
419
420                 if ((regs->vol_trm == regs->vol_ctl) && regs->vol_ctl) {
421                         if (j >= 0 && j <= (regs->vol_trm_bits >> shft_trm)) {
422                                 ANA_REG_MSK_OR(regs->vol_ctl, (j << shft_trm) | (i << shft_ctl),
423                                         regs->vol_trm_bits | regs->vol_ctl_bits);
424                         }
425                 } else {
426                         if (regs->vol_trm) { /* small adjust first */
427                                 if (j >= 0 && j <= (regs->vol_trm_bits >> shft_trm)) {
428                                         ANA_REG_MSK_OR(regs->vol_trm, j << shft_trm, regs->vol_trm_bits);
429                                 }
430                         }
431
432                         if (regs->vol_ctl) {
433                                 ANA_REG_MSK_OR(regs->vol_ctl, i << shft_ctl, regs->vol_ctl_bits);
434                         }
435                 }
436         }
437         return 0;
438 }
439
440 static int dcdc_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
441 {
442         //int acc_vol = dcdc_get_trimming_step(desc, to_vol) / 1000;
443         int ctl_vol = (to_vol - (adc_vol - def_vol));
444
445         return dcdc_set_voltage(desc, ctl_vol, ctl_vol);
446 }
447
448 static int ldo_get_voltage(struct regulator_desc *desc)
449 {
450         struct regulator_regs *regs = desc->regs;
451         u32 vol;
452
453         if (regs->vol_trm && regs->vol_sel_cnt == 2) {
454                 int shft = __ffs(regs->vol_trm_bits);
455                 u32 trim =
456                     (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft;
457                 vol = regs->vol_sel[0] * 1000 + trim * regs->vol_sel[1];
458                 vol /= 1000;
459
460                 debug0("%s get voltage %dmv(trim %#x)\n", desc->name, vol, trim);
461
462                 return vol;
463         }
464
465         return -1;
466 }
467
468 static int ldo_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
469 {
470         struct regulator_regs *regs = desc->regs;
471         int ret = -1;
472
473         if (!regs->vol_ctl && regs->vol_sel_cnt == 2) {
474                 /* ctl_vol = vol_base + reg[vol_trm] * vol_step  */
475                 int shft = __ffs(regs->vol_trm_bits);
476                 int ctl_vol = (to_vol - (adc_vol - def_vol));
477                 u32 trim = 0;
478
479                 if(adc_vol > def_vol)
480                         trim = DIV_ROUND_UP((ctl_vol - regs->vol_sel[0]) * 1000, regs->vol_sel[1]);
481                 else
482                         trim = ((ctl_vol - regs->vol_sel[0]) * 1000 / regs->vol_sel[1]);
483
484                 debug2("regu_ldo %p (%s) %d = %d %+dmv (trim=%d step=%duv)\n", regs, desc->name,
485                         ctl_vol, regs->vol_sel[0], ctl_vol - regs->vol_sel[0], trim, regs->vol_sel[1]);
486
487                 if ((trim >= 0) && (trim <= (regs->vol_trm_bits >> shft))) {
488                         ANA_REG_MSK_OR(regs->vol_trm,
489                                         trim << shft,
490                                         regs->vol_trm_bits);
491                         ret = 0;
492                 }
493         }
494
495         return ret;
496 }
497
498 static int reconfig_regulator(struct regulator_desc *desc)
499 {
500         struct regulator_regs *regs = desc->regs;
501
502         /* Fixme: Config DCDC  linear/no linear control
503          *   accoring to BIT14 of Reg(0x40038800 + 0x0118)
504          */
505         if (ana_mixed_ctl & BIT_DCDC_V_CTRL_MODE) {
506                 /* dcdc linear control */
507                 if ((0 == strcmp(desc->name, "vddcore"))
508                          || (0 == strcmp(desc->name, "vddarm"))) {
509                         regs->vol_trm_bits = (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4) \
510                                                                                 |BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9));
511                         regs->vol_ctl = 0;
512                         regs->vol_ctl_bits = 0;
513
514                         regs->vol_sel_cnt = 2;
515                         regs->vol_sel[0] = 600;
516                         regs->vol_sel[1] = 3125;
517                 }
518         } else {
519                 /* dcdc Non-linear control */
520                 if ((0 == strcmp(desc->name, "vddcore"))
521                          || (0 == strcmp(desc->name, "vddarm"))) {
522                         regs->vol_ctl = regs->vol_trm;
523                         regs->vol_trm_bits = (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4));
524                         regs->vol_ctl_bits = (BIT(5)|BIT(6)|BIT(7));
525
526                         regs->vol_sel_cnt = 8;
527                         regs->vol_sel[0] = 1100;
528                         regs->vol_sel[1] = 700;
529                         regs->vol_sel[2] = 800;
530                         regs->vol_sel[3] = 900;
531                         regs->vol_sel[4] = 1000;
532                         regs->vol_sel[5] = 650;
533                         regs->vol_sel[6] = 1200;
534                         regs->vol_sel[7] = 1300;
535                 }
536         }
537         return 0;
538 }
539
540 static int DCDC_Cal_One(struct regulator_desc *desc, int is_cal)
541 {
542         struct regulator_regs *regs = desc->regs;
543         int def_vol = 0, to_vol = 0, ref_vol = 0;
544         int adc = 0, adc_vol = 0, cal_vol = 0;
545         int ret = -1, adc_chan = 0;
546         u16 ldo_cal_sel = 0, adc_scale = 0;
547         int vdd_type = desc->regs->typ & (BIT(4) - 1);
548
549         reconfig_regulator(desc);
550
551         if (!regs->cal_ctl_bits)
552                 return -1;
553
554         adc_chan = regs->cal_ctl_bits >> 16;
555         ldo_cal_sel = regs->cal_ctl_bits & 0xFFFF;
556
557         if (!adc_chan || !regs->vol_def)
558                 return -2;
559
560         /* only verify dcdc/ldo default on calibration */
561         if (!is_cal && !(regs->typ & BIT(4)))
562                 return -3;
563
564         if (is_cal)
565                 debug("\nCalibrate %s ...\n", desc->name);
566         else
567                 debug("\nVerify %s ...\n", desc->name);
568
569         adc_scale = (((adc_chan != 13) && (adc_chan != 14)) ? ADC_SCALE_3V : ADC_SCALE_1V2);
570
571         if (ldo_cal_sel)
572                 ANA_REG_OR(regs->cal_ctl, ldo_cal_sel);
573
574         /*
575          * FIXME: force get dcdc&ldo voltage from ana global regs
576          * and get ideal voltage from vol para.
577          */
578         if (vdd_type == 2 /*DCDC*/) {
579                 def_vol = dcdc_get_voltage(desc);
580         }
581         else if (vdd_type == 0 /*LDO*/) {
582                 def_vol = ldo_get_voltage(desc);
583         }
584
585         to_vol = regulator_default_get(desc->name);
586         if (!to_vol)
587                 to_vol = regs->vol_def;
588
589         adc_vol = sci_adc_vol_request(adc_chan, adc_scale, ldo_cal_sel, &adc);
590         if (adc_vol <= 0) {
591                 debug1("%s default %dmv, adc channel %d, maybe not enable\n", desc->name, def_vol, adc_chan);
592                 goto exit;
593         }
594
595         ref_vol = (is_cal ? def_vol : to_vol);
596         cal_vol = abs(adc_vol - ref_vol);
597
598         debug1("%s chan[%d] adc %d, default %dmv, from %dmv to %dmv, bias %c%01d.%03d%%\n",
599               desc->name, adc_chan, adc, def_vol, adc_vol, to_vol,
600               (adc_vol > to_vol) ? '+' : '-',
601               cal_vol * 100 / ref_vol, cal_vol * 100 * 1000 / ref_vol % 1000);
602
603         if (!def_vol || !to_vol || adc_vol <= 0)
604                 goto exit;
605         if (cal_vol >= ref_vol / 9)     /* adjust limit 9% */
606                 goto exit;
607         else if (cal_vol < ref_vol / 100) {     /* bias 1% */
608                 goto exit;
609         }
610
611         if (is_cal) {
612                 if (vdd_type == 2 /*VDD_TYP_DCDC*/)
613                         ret = dcdc_set_trimming(desc, def_vol, to_vol, adc_vol);
614                 else if (vdd_type == 0 /*VDD_TYP_LDO*/)
615                         ret = ldo_set_trimming(desc, def_vol, to_vol, adc_vol);
616
617                 if(ret < 0)
618                         regulator_default_set(desc->name, 0);
619         }
620
621 exit:
622         if (ldo_cal_sel)
623                 ANA_REG_BIC(regs->cal_ctl, ldo_cal_sel);
624
625         return ret;
626 }
627
628 int DCDC_Cal_ArmCore(void)
629 {
630         u16 regval_dcdc_store, regval_ldo_store, otp_pwr_sel;
631         struct regulator_desc *desc = NULL;
632         struct regulator_desc *desc_end = NULL;
633         u32 cali_mask = regulator_get_calibration_mask();
634         u32 chip_id = ANA_GET_CHIP_ID();
635         int vbat_adc = 0;
636         int vbat_vol = sci_adc_vol_request(5, ADC_SCALE_3V, 0, &vbat_adc);
637         u16 otp_ana_flag = (u8)__adie_efuse_read(0) & BIT(7);
638
639         ana_mixed_ctl = ANA_REG_GET(ANA_REG_GLB_MIXED_CTRL0);
640         otp_pwr_sel = ANA_REG_GET(ANA_REG_GLB_PWR_SEL);
641
642         printf("%s; adie chipid:(0x%08x), mixed_ctl:(0x%08x), otp_sel:(0x%08x), cali_mask:(0x%08x), VBAT(vol %d, adc %d)\n",
643                 __func__, chip_id, ana_mixed_ctl, otp_pwr_sel, cali_mask, vbat_vol, vbat_adc);
644
645         if(!otp_ana_flag) {
646                 /* TODO: verify all DCDCs */
647                 desc = (struct regulator_desc *)(&__init_begin + 1);
648                 desc_end = (struct regulator_desc *)(&__init_end) - 1;
649                 while (desc_end >= desc) { /* reverse order */
650                         DCDC_Cal_One(desc_end, 0);
651                         desc_end--;
652                 }
653
654                 goto exit;
655         }
656
657         cali_mask &= 0x3FFFFFF1;
658
659         regval_dcdc_store = ANA_REG_GET(ANA_REG_GLB_LDO_DCDC_PD) & 0xFFFF;
660         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, BITS_PWR_WR_PROT_VALUE(0x6e7f), 0x7FFF);
661         ANA_REG_BIC(ANA_REG_GLB_LDO_DCDC_PD, (cali_mask >> 16));
662         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, 0, 0x7FFF);
663
664         regval_ldo_store = ANA_REG_GET(ANA_REG_GLB_LDO_PD_CTRL) & 0xFFFF;
665         ANA_REG_BIC(ANA_REG_GLB_LDO_PD_CTRL, cali_mask & 0xFFFF);
666
667         printf("REG_DCDC_PD(0x%08x): (0x%08x), REG_LDO_PD(0x%08x): (0x%08x), \n",
668                 ANA_REG_GLB_LDO_DCDC_PD, regval_dcdc_store, ANA_REG_GLB_LDO_PD_CTRL, regval_ldo_store);
669
670         /* TODO: calibrate all DCDCs */
671         desc = (struct regulator_desc *)(&__init_begin + 1);
672         desc_end = (struct regulator_desc *)(&__init_end) - 1;
673
674         printf("%p (%x) -- %p -- %p (%x)\n", &__init_begin, __init_begin,
675                 desc, &__init_end, __init_end);
676
677         while (desc_end >= desc) { /* reverse order */
678                 DCDC_Cal_One(desc_end, 1);
679                 desc_end--;
680         }
681
682 #if defined(REGU_CALI_DEBUG)
683         /* wait a moment for LDOs ready */
684         udelay(10 * 1000); //wait 10ms
685
686         /* TODO: verify all DCDCs */
687         desc = (struct regulator_desc *)(&__init_begin + 1);
688         desc_end = (struct regulator_desc *)(&__init_end) - 1;
689         while (desc_end >= desc) { /* reverse order */
690                 DCDC_Cal_One(desc_end, 0);
691                 desc_end--;
692         }
693 #endif
694
695         /* restore adie dcdc/ldo PD bits */
696         ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regval_ldo_store);
697         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, BITS_PWR_WR_PROT_VALUE(0x6e7f), 0x7FFF);
698         ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD, regval_dcdc_store);
699         ANA_REG_MSK_OR(ANA_REG_GLB_PWR_WR_PROT_VALUE, 0, 0x7FFF);
700
701 exit:
702         if(calibrate_post)
703                 calibrate_post(1);
704
705         return 0;
706 }
707
708
709 int regulator_init(void)
710 {
711         /*
712          * FIXME: turn on all DCDC/LDOs if need
713          */
714         return 0;
715 }
716
717 struct regulator_desc *regulator_get(void/*struct device*/ *dev, const char *id)
718 {
719         struct regulator_desc *desc =
720                 (struct regulator_desc *)(&__init_begin + 1);
721         while (desc < (struct regulator_desc *)&__init_end) {
722                 if (0 == strcmp(desc->name, id))
723                         return desc;
724                 desc++;
725         }
726         return 0;
727 }
728
729 int regulator_disable_all(void)
730 {
731         ANA_REG_OR(ANA_REG_GLB_LDO_PD_CTRL, 0x7fff);
732         ANA_REG_OR(ANA_REG_GLB_LDO_DCDC_PD, 0xbfff);
733         return 0;
734 }
735
736 int regulator_enable_all(void)
737 {
738         ANA_REG_BIC(ANA_REG_GLB_LDO_DCDC_PD, 0xbfff);
739         ANA_REG_BIC(ANA_REG_GLB_LDO_PD_CTRL, 0x7fff);
740         return 0;
741 }
742
743 int regulator_disable(const char con_id[])
744 {
745         struct regulator_desc *desc = regulator_get(0, con_id);
746         if (desc) {
747                 struct regulator_regs *regs = desc->regs;
748                 ANA_REG_OR(regs->pd_set, regs->pd_set_bit);
749         }
750         return 0;
751 }
752
753 int regulator_enable(const char con_id[])
754 {
755         struct regulator_desc *desc = regulator_get(0, con_id);
756         if (desc) {
757                 struct regulator_regs *regs = desc->regs;
758                 ANA_REG_BIC(regs->pd_set, regs->pd_set_bit);
759         }
760         return 0;
761 }
762
763 int regulator_set_voltage(const char con_id[], int to_vol)
764 {
765         int ret = 0;
766         struct regulator_desc *desc = regulator_get(0, con_id);
767         if (desc) {
768                 struct regulator_regs *regs = desc->regs;
769                 int vdd_type = regs->typ & (BIT(4) - 1);
770
771                 if (vdd_type == 2 /*VDD_TYP_DCDC*/)
772                         ret = dcdc_set_voltage(desc, to_vol, 0);
773                 else if (vdd_type == 0 /*VDD_TYP_LDO*/)
774                         ret = ldo_set_trimming(desc, 0, to_vol, 0);
775         }
776         return ret;
777 }
778
779 typedef struct {
780         uint16 ideal_vol;
781         const char name[14];
782 }vol_para_t;
783
784 #if defined(CONFIG_FDL2_BUILD)
785 vol_para_t **ppvol_para = (vol_para_t **)0x50000020;
786 #elif defined(CONFIG_SPL_32K)
787 vol_para_t **ppvol_para = (vol_para_t **)0x50003C20;
788 #else
789 vol_para_t **ppvol_para = (vol_para_t **)0x50003C20;
790 #endif
791
792 static int get_vol_para_num(void)
793 {
794         int i = 0;
795
796         if (!(ppvol_para && *ppvol_para))
797                 return 0;
798
799         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
800                 return 0;
801
802         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end"))
803                 ;
804
805         return (i+1);
806 }
807
808 static vol_para_t * match_vol_para(const char* vol_name)
809 {
810         int i = 0;
811
812         BUG_ON(NULL == vol_name);
813
814         if (!(ppvol_para && *ppvol_para))
815                 return NULL;
816
817         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
818                 return NULL;
819
820         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end")) {
821                 if (0 == strcmp((*ppvol_para)[i].name, vol_name)) {
822                         debug0("%s name %s, ideal_vol %d\n", __func__, (*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
823                         return (vol_para_t*)(&(*ppvol_para)[i]);
824                 }
825         }
826
827         return NULL;
828 }
829
830 int regulator_default_get(const char con_id[])
831 {
832         vol_para_t * pvol_para = match_vol_para(con_id);
833
834         return (int)(pvol_para ? pvol_para->ideal_vol : 0);
835 }
836
837 void regulator_default_set(const char con_id[], int vol)
838 {
839         vol_para_t * pvol_para = match_vol_para(con_id);
840
841         if(pvol_para) {
842                 pvol_para->ideal_vol = vol;
843         }
844 }
845
846 int regulator_default_set_all(void)
847 {
848         int i = 0, ret = 0;
849
850         //dump & check all vol para
851         if (!(ppvol_para && *ppvol_para))
852                 return -1;
853
854         if(strcmp((*ppvol_para)[0].name, "volpara_begin") || (0xfaed != (*ppvol_para)[0].ideal_vol))
855                 return 0;
856
857         while(0 != strcmp((*ppvol_para)[i++].name, "volpara_end")) {
858                 debug("regu: [%d] %s : %d\n", i, (*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
859
860                 ret |= regulator_set_voltage((*ppvol_para)[i].name, (*ppvol_para)[i].ideal_vol);
861         }
862
863         return ret;
864 }
865
866 /********************************************************************
867 *
868 * regulator_get_calibration_mask - get dcdc/ldo calibration flag
869 *
870 //
871 //High 16bit: dcdc ctrl calibration flag
872 //
873 * bit[15] : ldoemm
874 * bit[14] : dcdctopclk6M
875 * bit[13] : dcdcrf
876 * bit[12] : dcdcgen
877 * bit[11] : dcdcmem
878 * bit[10] : dcdcarm
879 * bit[9]   : dcdccore
880 * bit[8]   : vddrf0
881 * bit[7]   : vddemmccore
882 * bit[6]   : vddgen1
883 * bit[5]   : vdddcxo
884 * bit[4]   : vddgen0
885 * bit[3]   : vdd25
886 * bit[2]   : vdd28
887 * bit[1]   : vdd18
888 * bit[0]   : vddbg
889
890 //
891 //Low 16bit: ldo ctrl calibration flag
892 //
893 * bit[15] : ldolpref
894 * bit[14] : dcdcwpa
895 * bit[13] : dcdccon
896 * bit[12] : reserved
897 * bit[11] : vddwifipa
898 * bit[10] : vddsdcore
899 * bit[9]   : reserved
900 * bit[8]   : vddusb
901 * bit[7]   : vddcammot
902 * bit[6]   : vddcamio
903 * bit[5]   : vddcamd
904 * bit[4]   : vddcama
905 * bit[3]   : vddsim2
906 * bit[2]   : vddsim1
907 * bit[1]   : vddsim0
908 * bit[0]   : vddsdio
909 ********************************************************************/
910 u32 regulator_get_calibration_mask(void)
911 {
912         int len = get_vol_para_num();
913         volatile vol_para_t *pvol_para = (volatile vol_para_t *)(*ppvol_para);
914         volatile u32* pdebug_flag = (u32*)(&pvol_para[len-1]);
915
916         if(len > 2) {
917                 printf("%s, vol_para_tbl_len %d, ldo_pd_mask 0x%08x; \n", __func__, len, *pdebug_flag);
918                 return (*pdebug_flag);
919         }
920
921         return 0;
922 }
923
924 /* register callback function after dcdc/ldo calibration  */
925 int calibrate_register_callback(void* callback_fun)
926 {
927         if(callback_fun) {
928                 calibrate_post = (pfun)callback_fun;
929                 return 0;
930         } else
931                 return -1;
932 }
933