3 #include <asm/arch/adc_drvapi.h>
4 #include <asm/arch/adi_hal_internal.h>
5 #include <asm/arch/sprd_reg.h>
9 #define debug(format, arg...) printf("\t" format, ## arg)
10 #define debug2(format, arg...) printf("\t\t" format, ## arg)
12 #define debug(format, arg...)
13 #define debug2(format, arg...)
15 #define debug0(format, arg...)
17 /* abs() handles unsigned and signed longs, ints, shorts and chars. For all input types abs()
18 * returns a signed long.
19 * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64() for those.*/
22 if (sizeof(x) == sizeof(long)) { \
24 ret = (__x < 0) ? -__x : __x; \
27 ret = (__x < 0) ? -__x : __x; \
36 /* On ARMv5 and above those functions can be implemented around the clz instruction for
37 * much better code efficiency. */
39 static inline int fls(int x)
43 asm("clz\t%0, %1": "=r"(ret):"r"(x));
48 #define __fls(x) (fls(x) - 1)
49 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
50 #define __ffs(x) (ffs(x) - 1)
51 #define ffz(x) __ffs( ~(x) )
53 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
55 #define MEASURE_TIMES (15)
57 #define ADC_DROP_CNT ( DIV_ROUND(MEASURE_TIMES, 5) )
58 static int __average(int a[], int N)
61 for (i = 0; i < N; i++)
63 return DIV_ROUND(sum, N);
66 static void bubble_sort(int a[], int N)
69 for (i = 0; i < N - 1; i++) {
70 for (j = i + 1; j < N; j++) {
80 int sci_adc_request(int channel)
83 int results[MEASURE_TIMES];
85 if (-1 == ADC_GetValues(channel, ADC_SCALE_3V, MEASURE_TIMES, results)) {
89 bubble_sort(results, MEASURE_TIMES);
92 for (i = 0; i < MEASURE_TIMES; i++) {
93 printf("%d ", results[i]);
97 return results[MEASURE_TIMES / 2];
100 #define RATIO(_n_, _d_) (_n_ << 16 | _d_)
102 static int sci_adc_ratio(int channel, int mux)
119 if ((mux & 0xFFFF) == BIT(5))
131 static u32 bat_numerators, bat_denominators = 0;
132 extern uint16_t sprdbat_auxadc2vbatvol (uint16_t adcvalue);
134 int sci_adc_vol_request(int channel, int mux)
137 adc_res = sci_adc_request(channel);
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);
150 /* Simple shorthand for a section definition */
152 # define __section(S) __attribute__ ((__section__(#S)))
155 #define __init0 __section(.rodata.regu.init0)
156 #define __init1 __section(.rodata.regu.init1)
157 #define __init2 __section(.rodata.regu.init2)
159 const u32 __init0 __init_begin = 0xeeeebbbb;
160 const u32 __init2 __init_end = 0xddddeeee;
162 struct regulator_regs {
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;
172 u32 vol_ctl, vol_ctl_bits;
173 u32 vol_sel_cnt, vol_sel[];
176 struct regulator_desc {
179 const struct regulator_regs *regs;
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 const struct regulator_regs REGS_##VDD = { \
189 .pd_set_bit = SET_BIT, \
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__}, \
204 struct regulator_desc __init1 DESC_##VDD = { \
207 .regs = ®S_##VDD, \
211 #include <asm/arch/chip_x35l/sprd_reg_regulator_map.h>
214 typedef struct dcdc_cali_tag
217 int cali_vol; /* ctl_vol - to_vol */
220 #define CALI_VOL_ADDR 0x1F00
221 #define CALI_VOL_ADDR_NUM 8
223 static dcdc_cali_t* get_cali_addr()
225 dcdc_cali_t *p = (dcdc_cali_t *)CALI_VOL_ADDR;
228 while ((*(u32 *)p != 0) && (i < 4))
235 return (dcdc_cali_t*)0;
240 /* standard dcdc ops*/
241 static int __dcdc_is_orig(struct regulator_desc *desc)
243 if (0 == strcmp(desc->name, "vddmem") || 0 == strcmp(desc->name, "vddwrf"))
244 if (ANA_REG_GET(ANA_REG_GLB_CHIP_ID_LOW) & 0xff) /* BA CHIP */
249 static int dcdc_get_trimming_step(struct regulator_desc *desc, int to_vol)
251 /* FIXME: vddmem step 200/32mV */
252 if (0 == strcmp(desc->name, "vddmem") || 0 == strcmp(desc->name, "vddwrf"))
254 return 1000 * 200 / 32; /*uV */
256 return 1000 * 100 / 32; /*uV */
259 static int __match_dcdc_vol(struct regulator_desc *desc, u32 vol)
262 int ds, min_ds = 100; /* mV, the max range of small voltage */
263 const struct regulator_regs *regs = desc->regs;
265 for (i = 0; i < regs->vol_sel_cnt; i++) {
266 ds = vol - regs->vol_sel[i];
267 if (ds >= 0 && ds < min_ds) {
273 if (j < 0 && !__dcdc_is_orig(desc)) {
274 for (i = 0; i < regs->vol_sel_cnt; i++) {
275 ds = abs(vol - regs->vol_sel[i]);
286 static int dcdc_get_voltage(struct regulator_desc *desc)
288 const struct regulator_regs *regs = desc->regs;
290 int cal = 0; /* uV */
291 int i, shft = __ffs(regs->vol_ctl_bits);
293 i = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> shft;
294 mv = regs->vol_sel[i];
296 cal = (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> __ffs(regs->vol_trm_bits);
297 if (!__dcdc_is_orig(desc)) {
300 cal *= dcdc_get_trimming_step(desc, 0); /*uV */
302 debug0("%s %d +%dmv\n", desc->name, mv, cal / 1000);
303 return mv + cal / 1000;
306 static int dcdc_set_voltage(struct regulator_desc *desc, int min_mV, int max_mV)
308 const struct regulator_regs *regs = desc->regs;
311 /* found the closely vol ctrl bits */
312 i = __match_dcdc_vol(desc, mv);
314 debug2("%s: %s failed to match voltage: %d\n",__func__,desc->name,mv);
318 /* dcdc calibration control bits (default 0) small adjust voltage: 100/32mv ~= 3.125mv */
320 int shft = __ffs(regs->vol_ctl_bits);
321 int j = (mv - (int)regs->vol_sel[i]) * 1000 / dcdc_get_trimming_step(desc, mv);
323 if (!__dcdc_is_orig(desc))
326 debug2("regu_dcdc %p (%s) %d = %d %+dmv (trim=%d);\n", regs, desc->name,
327 mv, regs->vol_sel[i], mv - regs->vol_sel[i], j);
329 if (j >= 0 && j < 32)
330 ANA_REG_MSK_OR(regs->vol_ctl, j | (i << shft),
331 regs->vol_trm_bits | regs->vol_ctl_bits);
336 static int dcdc_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
338 dcdc_cali_t *p = NULL;
339 int acc_vol = dcdc_get_trimming_step(desc, to_vol) / 1000;
341 /*FIXME: no need division?
342 int ctl_vol = DIV_ROUND_UP(def_vol * to_vol * 1000, adc_vol) + acc_vol; */
343 int ctl_vol = (def_vol - (adc_vol - to_vol)) + acc_vol;
347 strcpy(p->name, desc->name);
348 p->cali_vol = ctl_vol - to_vol;
351 return dcdc_set_voltage(desc, ctl_vol, ctl_vol);
354 static int ldo_get_voltage(struct regulator_desc *desc)
356 const struct regulator_regs *regs = desc->regs;
359 if (regs->vol_trm && regs->vol_sel_cnt == 2) {
360 int shft = __ffs(regs->vol_trm_bits);
362 (ANA_REG_GET(regs->vol_trm) & regs->vol_trm_bits) >> shft;
363 vol = regs->vol_sel[0] * 1000 + trim * regs->vol_sel[1];
365 debug0("%s voltage %dmv\n", desc->name, vol);
372 /* ldo trimming step about 0.625%, range 90% ~ 109.375%. that all maps as follow.
374 0x1F : +9.375 : 109.375
375 0x1E : +8.750 : 108.750
376 0x1D : +8.125 : 108.125
377 0x1C : +7.500 : 107.500
378 0x1B : +6.875 : 106.875
379 0x1A : +6.250 : 106.250
380 0x19 : +5.625 : 105.625
381 0x18 : +5.000 : 105.000
382 0x17 : +4.375 : 104.375
383 0x16 : +3.750 : 103.750
384 0x15 : +3.125 : 103.125
385 0x14 : +2.500 : 102.500
386 0x13 : +1.875 : 101.875
387 0x12 : +1.250 : 101.250
388 0x11 : +0.625 : 100.625
389 0x10 : +0.000 : 100.000
390 0x0F : -0.625 : 99.375
391 0x0E : -1.250 : 98.750
392 0x0D : -1.875 : 98.125
393 0x0C : -2.500 : 97.500
394 0x0B : -3.125 : 96.875
395 0x0A : -3.750 : 96.250
396 0x09 : -4.375 : 95.625
397 0x08 : -5.000 : 95.000
398 0x07 : -5.625 : 94.375
399 0x06 : -6.250 : 93.750
400 0x05 : -6.875 : 93.125
401 0x04 : -7.500 : 92.500
402 0x03 : -8.125 : 91.875
403 0x02 : -8.750 : 91.250
404 0x01 : -9.375 : 90.625
405 0x00 : -10.000 : 90.000
407 static int ldo_set_trimming(struct regulator_desc *desc, int def_vol, int to_vol, int adc_vol)
409 const struct regulator_regs *regs = desc->regs;
413 /* assert 5 valid trim bits, R = V_IDEAL / V_ADCIN - 1 */
414 u32 trim = DIV_ROUND_UP((to_vol * 100 - adc_vol * 90) * 32, (adc_vol * 20));
415 if (trim > BIT(5) - 1)
417 debug2("regu %p (%s) trimming %d = %d %+d%%, got [%02X]\n",
418 regs, desc->name, to_vol, adc_vol, (trim * 20 / 32 - 10), trim);
420 ANA_REG_MSK_OR(regs->vol_trm,
421 trim << __ffs(regs->vol_trm_bits),
430 static int dcdc_get_trimming_vol(struct regulator_desc *desc)
432 int shft, trm_vol = 0;
435 shft = __ffs(desc->regs->vol_trm_bits);
436 tmpVal = (ANA_REG_GET(desc->regs->vol_trm) & desc->regs->vol_trm_bits) >> shft;
438 if (!__dcdc_is_orig(desc))
441 trm_vol = tmpVal * (dcdc_get_trimming_step(desc, trm_vol))/1000;
446 static int DCDC_Cal_One(struct regulator_desc *desc, int is_cal)
448 struct regulator_regs *regs = desc->regs;
449 int def_vol = 0, to_vol = 0;
450 int adc_vol = 0, cal_vol = 0;
451 int ret = -1, adc_chan = regs->cal_ctl_bits >> 16;
452 u16 ldo_cal_sel = regs->cal_ctl_bits & 0xFFFF;
454 if (!adc_chan || !regs->vol_def)
458 ANA_REG_OR(regs->cal_ctl, ldo_cal_sel);
462 tmpVal = (ANA_REG_GET(regs->vol_ctl) & regs->vol_ctl_bits) >> __ffs(regs->vol_ctl_bits);
464 def_vol = to_vol = (int)regs->vol_sel[tmpVal] + dcdc_get_trimming_vol(desc);
465 else if (regs->typ == 0)
466 def_vol = to_vol = regs->vol_sel[tmpVal];
469 adc_vol = sci_adc_vol_request(adc_chan, ldo_cal_sel);
471 debug("%s default %dmv, maybe not enable\n", desc->name, def_vol);
475 cal_vol = abs(adc_vol - to_vol);
476 debug("%s default %dmv, from %dmv to %dmv, bias %c%d.%03d%%\n",
477 desc->name, def_vol, adc_vol, to_vol,
478 (adc_vol > to_vol) ? '+' : '-',
479 cal_vol * 100 / to_vol, cal_vol * 100 * 1000 / to_vol % 1000);
481 if (!def_vol || !to_vol || adc_vol <= 0)
484 if (abs(adc_vol - def_vol) >= def_vol / 10) /* adjust limit 10% */
486 else if (cal_vol < to_vol / 100) { /* bias 1% */
490 if (regs->typ == 2/*VDD_TYP_DCDC*/)
491 ret = dcdc_set_trimming(desc, def_vol, to_vol, adc_vol);
492 else if (regs->typ == 0/*VDD_TYP_LDO*/)
493 ret = ldo_set_trimming(desc, def_vol, to_vol, adc_vol);
498 ANA_REG_BIC(regs->cal_ctl, ldo_cal_sel);
503 int DCDC_Cal_ArmCore(void)
507 struct regulator_desc *desc = NULL;
508 struct regulator_desc *desc_end = NULL;
510 printf("%s\n", __FUNCTION__);
512 /* mem arm core bits are [11:9]*/
513 regVal = ANA_REG_GET(ANA_REG_GLB_LDO_DCDC_PD_RTCCLR);
514 regVal |= BIT(11) | BIT(10) | BIT(9);
515 ANA_REG_SET(ANA_REG_GLB_LDO_DCDC_PD_RTCCLR, regVal);
517 /* enable sim0, sim2. */
518 regVal = ANA_REG_GET(ANA_REG_GLB_LDO_PD_CTRL);
519 regVal &= ~(BIT(2) | BIT(4));
520 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regVal);
522 /* FIXME: Update CHGMNG_AdcvalueToVoltage table before setup vbat ratio. */
523 /*ADC_CHANNEL_VBAT is 5*/
524 res = (u32) sci_adc_ratio(5, 0);
525 bat_numerators = res >> 16;
526 bat_denominators = res & 0xffff;
528 /* initialize 4 struct free */
529 memset((u8 *)CALI_VOL_ADDR , 0x00, (sizeof(dcdc_cali_t) * (CALI_VOL_ADDR_NUM)));
531 /* TODO: calibrate all DCDCs */
532 desc = (struct regulator_desc *)(&__init_begin + 1);
534 printf("%p (%x) -- %p -- %p (%x)\n", &__init_begin, __init_begin,
535 desc, &__init_end, __init_end);
537 while (desc < (struct regulator_desc *)&__init_end) {
538 if ((0 == strcmp("vddmem", desc->name))
539 || (0 == strcmp("vddarm", desc->name))
540 || (0 == strcmp("vddcore", desc->name))
541 || (0 == strcmp("vddsim0", desc->name))
542 || (0 == strcmp("vddsim2", desc->name))) {
544 printf("\nCalibrate %s ...\n", desc->name);
545 DCDC_Cal_One(desc, 1);
551 /* wait a moment for LDOs ready */
554 /* TODO: verify all DCDCs */
555 desc = (struct regulator_desc *)(&__init_begin + 1);
557 while (desc < (struct regulator_desc *)&__init_end) {
558 if ((0 == strcmp("vddmem", desc->name))
559 || (0 == strcmp("vddarm", desc->name))
560 || (0 == strcmp("vddcore", desc->name))
561 || (0 == strcmp("vddsim0", desc->name))
562 || (0 == strcmp("vddsim2", desc->name))) {
564 printf("\nVerify %s ...\n", desc->name);
565 DCDC_Cal_One(desc, 0);
571 /* disable sim0, sim2. */
572 regVal |= (BIT(2) | BIT(4));
573 ANA_REG_SET(ANA_REG_GLB_LDO_PD_CTRL, regVal);