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