3 #include <asm/arch/adc_drvapi.h>
4 #include <asm/arch/adi_hal_internal.h>
5 #include <asm/arch/sprd_reg.h>
11 #define debug(format, arg...) printf("\t" format, ## arg)
12 #define debug2(format, arg...) printf("\t\t" format, ## arg)
15 #define debug(format, arg...)
16 #define debug2(format, arg...)
18 #define debug0(format, arg...)
20 /* abs() handles unsigned and signed longs, ints, shorts and chars. For all input types abs()
21 * returns a signed long.
22 * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64() for those.*/
25 if (sizeof(x) == sizeof(long)) { \
27 ret = (__x < 0) ? -__x : __x; \
30 ret = (__x < 0) ? -__x : __x; \
39 /* On ARMv5 and above those functions can be implemented around the clz instruction for
40 * much better code efficiency. */
42 static inline int fls(int x)
46 asm("clz\t%0, %1": "=r"(ret):"r"(x));
51 #define __fls(x) (fls(x) - 1)
52 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
53 #define __ffs(x) (ffs(x) - 1)
54 #define ffz(x) __ffs( ~(x) )
56 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
58 #define MEASURE_TIMES (15)
60 #define ADC_DROP_CNT ( DIV_ROUND(MEASURE_TIMES, 5) )
61 static int __average(int a[], int N)
64 for (i = 0; i < N; i++)
66 return DIV_ROUND(sum, N);
69 static void bubble_sort(int a[], int N)
72 for (i = 0; i < N - 1; i++) {
73 for (j = i + 1; j < N; j++) {
83 static int sci_adc_request(int channel)
86 int results[MEASURE_TIMES];
88 if (-1 == ADC_GetValues(channel, ADC_SCALE_3V, MEASURE_TIMES, results)) {
92 bubble_sort(results, MEASURE_TIMES);
95 for (i = 0; i < MEASURE_TIMES; i++) {
96 printf("%d ", results[i]);
100 return results[MEASURE_TIMES / 2];
103 #define RATIO(_n_, _d_) (_n_ << 16 | _d_)
105 static int sci_adc_ratio(int channel, int mux)
122 if ((mux & 0xFFFF) == BIT(5))
134 static u32 bat_numerators, bat_denominators = 0;
135 extern uint16_t sprdbat_auxadc2vbatvol (uint16_t adcvalue);
137 static int sci_adc_vol_request(int channel, int mux)
140 adc_res = sci_adc_request(channel);
142 u32 res, chan_numerators, chan_denominators;
143 res = (u32) sci_adc_ratio(channel, mux);
144 chan_numerators = res >> 16;
145 chan_denominators = res & 0xffff;
146 return sprdbat_auxadc2vbatvol(adc_res)
147 * (bat_numerators * chan_denominators)
148 / (bat_denominators * chan_numerators);
153 /* Simple shorthand for a section definition */
155 # define __section(S) __attribute__ ((__section__(#S)))
158 #define __init0 __section(.rodata.regu.init0)
159 #define __init1 __section(.rodata.regu.init1)
160 #define __init2 __section(.rodata.regu.init2)
162 static const u32 __init0 __init_begin = 0xeeeebbbb;
163 static const u32 __init2 __init_end = 0xddddeeee;
165 struct regulator_regs {
167 u32 pd_set, pd_set_bit;
168 /* at new feature, some LDOs had only set, no rst bits.
169 * and DCDCs voltage and trimming controller is the same register */
170 u32 pd_rst, pd_rst_bit;
171 u32 slp_ctl, slp_ctl_bit;
172 u32 vol_trm, vol_trm_bits;
173 u32 cal_ctl, cal_ctl_bits;
175 u32 vol_ctl, vol_ctl_bits;
176 u32 vol_sel_cnt, vol_sel[];
179 struct regulator_desc {
182 const struct regulator_regs *regs;
185 #define REGU_VERIFY_DLY (1000) /*ms */
186 #define SCI_REGU_REG(VDD, TYP, PD_SET, SET_BIT, PD_RST, RST_BIT, SLP_CTL, SLP_CTL_BIT, \
187 VOL_TRM, VOL_TRM_BITS, CAL_CTL, CAL_CTL_BITS, VOL_DEF, \
188 VOL_CTL, VOL_CTL_BITS, VOL_SEL_CNT, ...) \
189 static const struct regulator_regs REGS_##VDD = { \
192 .pd_set_bit = SET_BIT, \
194 .pd_rst_bit = RST_BIT, \
195 .slp_ctl = SLP_CTL, \
196 .slp_ctl_bit = SLP_CTL_BIT, \
197 .vol_trm = VOL_TRM, \
198 .vol_trm_bits = VOL_TRM_BITS, \
199 .cal_ctl = CAL_CTL, \
200 .cal_ctl_bits = CAL_CTL_BITS, \
201 .vol_def = VOL_DEF, \
202 .vol_ctl = VOL_CTL, \
203 .vol_ctl_bits = VOL_CTL_BITS, \
204 .vol_sel_cnt = VOL_SEL_CNT, \
205 .vol_sel = {__VA_ARGS__}, \
207 struct regulator_desc __init1 DESC_##VDD = { \
210 .regs = ®S_##VDD, \
214 #include <asm/arch/chip_x35/sprd_reg_regulator_map.h>
217 typedef struct dcdc_cali_tag
220 int cali_vol; /* ctl_vol - to_vol */
223 #define CALI_VOL_ADDR 0x1F00
224 #define CALI_VOL_ADDR_NUM 8
226 static dcdc_cali_t* get_cali_addr()
228 dcdc_cali_t *p = (dcdc_cali_t *)CALI_VOL_ADDR;
231 while ((*(u32 *)p != 0) && (i < 4))
238 return (dcdc_cali_t*)0;
243 /* standard dcdc ops*/
244 static int __dcdc_is_orig(struct regulator_desc *desc)
246 if (0 == strcmp(desc->name, "vddmem") || 0 == strcmp(desc->name, "vddwrf"))
247 if (ANA_REG_GET(ANA_REG_GLB_CHIP_ID_LOW) & 0xff) /* BA CHIP */
252 static int dcdc_get_trimming_step(struct regulator_desc *desc, int to_vol)
254 /* FIXME: vddmem step 200/32mV */
255 if (0 == strcmp(desc->name, "vddmem") || 0 == strcmp(desc->name, "vddwrf"))
257 return 1000 * 200 / 32; /*uV */
259 return 1000 * 100 / 32; /*uV */
262 static int __match_dcdc_vol(struct regulator_desc *desc, u32 vol)
265 int ds, min_ds = 100; /* mV, the max range of small voltage */
266 const struct regulator_regs *regs = desc->regs;
268 for (i = 0; i < regs->vol_sel_cnt; i++) {
269 ds = vol - regs->vol_sel[i];
270 if (ds >= 0 && ds < min_ds) {
276 if (j < 0 && !__dcdc_is_orig(desc)) {
277 for (i = 0; i < regs->vol_sel_cnt; i++) {
278 ds = abs(vol - regs->vol_sel[i]);
289 static int dcdc_get_voltage(struct regulator_desc *desc)
291 const struct regulator_regs *regs = desc->regs;
293 int cal = 0; /* uV */
294 int i, shft = __ffs(regs->vol_ctl_bits);
296 i = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> shft;
297 mv = regs->vol_sel[i];
299 cal = (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> __ffs(regs->vol_trm_bits);
300 if (!__dcdc_is_orig(desc)) {
303 cal *= dcdc_get_trimming_step(desc, 0); /*uV */
305 debug0("%s %d +%dmv\n", desc->name, mv, cal / 1000);
306 return mv + cal / 1000;
309 static int dcdc_set_voltage(struct regulator_desc *desc, int min_mV, int max_mV)
311 const struct regulator_regs *regs = desc->regs;
314 /* found the closely vol ctrl bits */
315 i = __match_dcdc_vol(desc, mv);
317 debug2("%s: %s failed to match voltage: %d\n",__func__,desc->name,mv);
321 /* dcdc calibration control bits (default 0) small adjust voltage: 100/32mv ~= 3.125mv */
323 int shft = __ffs(regs->vol_ctl_bits);
324 int j = (mv - (int)regs->vol_sel[i]) * 1000 / dcdc_get_trimming_step(desc, mv);
326 if (!__dcdc_is_orig(desc))
329 debug2("regu_dcdc %p (%s) %d = %d %+dmv (trim=%d);\n", regs, desc->name,
330 mv, regs->vol_sel[i], mv - regs->vol_sel[i], j);
332 if (j >= 0 && j < 32)
333 ANA_REG_MSK_OR(regs->vol_ctl, j | (i << shft),
334 regs->vol_trm_bits | regs->vol_ctl_bits);
339 static int dcdc_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
341 dcdc_cali_t *p = NULL;
342 int acc_vol = dcdc_get_trimming_step(desc, to_vol) / 1000;
344 /*FIXME: no need division?
345 int ctl_vol = DIV_ROUND_UP(def_vol * to_vol * 1000, adc_vol) + acc_vol; */
346 int ctl_vol = (def_vol - (adc_vol - to_vol)) + acc_vol;
350 strcpy(p->name, desc->name);
351 p->cali_vol = ctl_vol - to_vol;
354 return dcdc_set_voltage(desc, ctl_vol, ctl_vol);
357 static int ldo_get_voltage(struct regulator_desc *desc)
359 const struct regulator_regs *regs = desc->regs;
362 if (regs->vol_trm && regs->vol_sel_cnt == 2) {
363 int shft = __ffs(regs->vol_trm_bits);
365 (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft;
366 vol = regs->vol_sel[0] * 1000 + trim * regs->vol_sel[1];
368 debug0("%s voltage %dmv\n", desc->name, vol);
375 /* ldo trimming step about 0.625%, range 90% ~ 109.375%. that all maps as follow.
377 0x1F : +9.375 : 109.375
378 0x1E : +8.750 : 108.750
379 0x1D : +8.125 : 108.125
380 0x1C : +7.500 : 107.500
381 0x1B : +6.875 : 106.875
382 0x1A : +6.250 : 106.250
383 0x19 : +5.625 : 105.625
384 0x18 : +5.000 : 105.000
385 0x17 : +4.375 : 104.375
386 0x16 : +3.750 : 103.750
387 0x15 : +3.125 : 103.125
388 0x14 : +2.500 : 102.500
389 0x13 : +1.875 : 101.875
390 0x12 : +1.250 : 101.250
391 0x11 : +0.625 : 100.625
392 0x10 : +0.000 : 100.000
393 0x0F : -0.625 : 99.375
394 0x0E : -1.250 : 98.750
395 0x0D : -1.875 : 98.125
396 0x0C : -2.500 : 97.500
397 0x0B : -3.125 : 96.875
398 0x0A : -3.750 : 96.250
399 0x09 : -4.375 : 95.625
400 0x08 : -5.000 : 95.000
401 0x07 : -5.625 : 94.375
402 0x06 : -6.250 : 93.750
403 0x05 : -6.875 : 93.125
404 0x04 : -7.500 : 92.500
405 0x03 : -8.125 : 91.875
406 0x02 : -8.750 : 91.250
407 0x01 : -9.375 : 90.625
408 0x00 : -10.000 : 90.000
410 static int ldo_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
412 const struct regulator_regs *regs = desc->regs;
416 /* assert 5 valid trim bits, R = V_IDEAL / V_ADCIN - 1 */
417 u32 trim = DIV_ROUND_UP((to_vol * 100 - adc_vol * 90) * 32, (adc_vol * 20));
418 if (trim > BIT(5) - 1)
420 debug2("regu %p (%s) trimming %d = %d %+d%%, got [%02X]\n",
421 regs, desc->name, to_vol, adc_vol, (trim * 20 / 32 - 10), trim);
423 ANA_REG_MSK_OR(regs->vol_trm,
424 trim << __ffs(regs->vol_trm_bits),
433 static int dcdc_get_trimming_vol(struct regulator_desc *desc)
435 int shft, trm_vol = 0;
438 shft = __ffs(desc->regs->vol_trm_bits);
439 tmpVal = (ANA_REG_GET(desc->regs->vol_trm) & desc->regs->vol_trm_bits) >> shft;
441 if (!__dcdc_is_orig(desc))
444 trm_vol = tmpVal * (dcdc_get_trimming_step(desc, trm_vol))/1000;
449 static int DCDC_Cal_One(struct regulator_desc *desc, int is_cal)
451 const struct regulator_regs *regs = desc->regs;
452 int def_vol = 0, to_vol = 0;
453 int adc_vol = 0, cal_vol = 0;
454 int ret = -1, adc_chan = regs->cal_ctl_bits >> 16;
455 u16 ldo_cal_sel = regs->cal_ctl_bits & 0xFFFF;
457 if (!adc_chan || !regs->vol_def)
461 ANA_REG_OR(regs->cal_ctl, ldo_cal_sel);
465 tmpVal = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> __ffs(regs->vol_ctl_bits);
467 def_vol = to_vol = (int)regs->vol_sel[tmpVal] + dcdc_get_trimming_vol(desc);
468 else if (regs->typ == 0)
469 def_vol = to_vol = regs->vol_sel[tmpVal];
472 adc_vol = sci_adc_vol_request(adc_chan, ldo_cal_sel);
474 debug("%s default %dmv, maybe not enable\n", desc->name, def_vol);
478 cal_vol = abs(adc_vol - to_vol);
479 debug("%s default %dmv, from %dmv to %dmv, bias %c%d.%03d%%\n",
480 desc->name, def_vol, adc_vol, to_vol,
481 (adc_vol > to_vol) ? '+' : '-',
482 cal_vol * 100 / to_vol, cal_vol * 100 * 1000 / to_vol % 1000);
484 if (!def_vol || !to_vol || adc_vol <= 0)
487 if (abs(adc_vol - def_vol) >= def_vol / 10) /* adjust limit 10% */
489 else if (cal_vol < to_vol / 100) { /* bias 1% */
493 if (regs->typ == 2/*VDD_TYP_DCDC*/)
494 ret = dcdc_set_trimming(desc, def_vol, to_vol, adc_vol);
495 else if (regs->typ == 0/*VDD_TYP_LDO*/)
496 ret = ldo_set_trimming(desc, def_vol, to_vol, adc_vol);
501 ANA_REG_BIC(regs->cal_ctl, ldo_cal_sel);
506 int SC2713S_DCDC_Cal_ArmCore(void);
507 int DCDC_Cal_ArmCore(void)
511 struct regulator_desc *desc = NULL;
512 struct regulator_desc *desc_end = NULL;
514 printf("%s\n", __FUNCTION__);
516 #ifdef CONFIG_ADIE_SC2713S
517 if((sci_get_adie_chip_id() & ~0xFFF)== 0x2713C000)
518 return SC2713S_DCDC_Cal_ArmCore();
521 /* mem arm core bits are [11:9]*/
522 regVal = ANA_REG_GET(ANA_REG_GLB_LDO_DCDC_PD_RTCCLR);
523 regVal |= BIT(11) | BIT(10) | BIT(9);
524 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD_RTCCLR, regVal);
526 /* enable sim0, sim2. */
527 regVal = ANA_REG_GET(ANA_REG_GLB_LDO_PD_CTRL);
528 regVal &= ~(BIT(2) | BIT(4));
529 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regVal);
531 /* FIXME: Update CHGMNG_AdcvalueToVoltage table before setup vbat ratio. */
532 /*ADC_CHANNEL_VBAT is 5*/
533 res = (u32) sci_adc_ratio(5, 0);
534 bat_numerators = res >> 16;
535 bat_denominators = res & 0xffff;
537 /* initialize 4 struct free */
538 memset((u8 *)CALI_VOL_ADDR , 0x00, (sizeof(dcdc_cali_t) * (CALI_VOL_ADDR_NUM)));
540 /* TODO: calibrate all DCDCs */
541 desc = (struct regulator_desc *)(&__init_begin + 1);
543 printf("%p (%x) -- %p -- %p (%x)\n", &__init_begin, __init_begin,
544 desc, &__init_end, __init_end);
546 while (desc < (struct regulator_desc *)&__init_end) {
547 if ((0 == strcmp("vddmem", desc->name))
548 || (0 == strcmp("vddarm", desc->name))
549 || (0 == strcmp("vddcore", desc->name))
550 || (0 == strcmp("vddsim0", desc->name))
551 || (0 == strcmp("vddsim2", desc->name))) {
553 printf("\nCalibrate %s ...\n", desc->name);
554 DCDC_Cal_One(desc, 1);
560 /* wait a moment for LDOs ready */
563 /* TODO: verify all DCDCs */
564 desc = (struct regulator_desc *)(&__init_begin + 1);
566 while (desc < (struct regulator_desc *)&__init_end) {
567 if ((0 == strcmp("vddmem", desc->name))
568 || (0 == strcmp("vddarm", desc->name))
569 || (0 == strcmp("vddcore", desc->name))
570 || (0 == strcmp("vddsim0", desc->name))
571 || (0 == strcmp("vddsim2", desc->name))) {
573 printf("\nVerify %s ...\n", desc->name);
574 DCDC_Cal_One(desc, 0);
580 /* disable sim0, sim2. */
581 regVal |= (BIT(2) | BIT(4));
582 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regVal);