884d527c446adeceaf92750928256b0496fa70fe
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / power / sprd_battery.c
1 #include <common.h>
2 #include <asm/io.h>
3
4 #include <asm/arch/regs_adi.h>
5 #include <asm/arch/adi_hal_internal.h>
6 #include <asm/arch/sprd_reg.h>
7 #include <asm/arch/sprd_eic.h>
8 #include <sprd_battery.h>
9
10 #ifdef DEBUG
11 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
12 #else
13 #define debugf(fmt, args...)
14 #endif
15 #define ADC_CAL_TYPE_NO                 0
16 #define ADC_CAL_TYPE_NV                 1
17 #define ADC_CAL_TYPE_EFUSE              2
18
19 extern int charger_connected(void);
20 extern int read_adc_calibration_data(char *buffer, int size);
21 extern int sci_efuse_calibration_get(unsigned int *p_cal_data);
22 extern int sprd_eic_request(unsigned offset);
23 extern int sprd_eic_get(unsigned offset);
24 extern void power_down_devices(unsigned pd_cmd);
25
26
27 uint16_t adc_voltage_table[2][2] = {
28         {3310, 4200},
29         {2832, 3600},
30 };
31
32 uint32_t adc_cal_flag = 0;
33
34 uint16_t sprdbat_auxadc2vbatvol(uint16_t adcvalue)
35 {
36         int32_t temp;
37         temp = adc_voltage_table[0][1] - adc_voltage_table[1][1];
38         temp = temp * (adcvalue - adc_voltage_table[0][0]);
39         temp = temp / (adc_voltage_table[0][0] - adc_voltage_table[1][0]);
40
41         debugf("uboot battery voltage:%d,adc4200:%d,adc3600:%d\n",
42                temp + adc_voltage_table[0][1], adc_voltage_table[0][0],
43                adc_voltage_table[1][0]);
44
45         return temp + adc_voltage_table[0][1];
46 }
47
48 void sprdchg_stop_charge(void)
49 {
50         ANA_REG_MSK_OR(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_PD, BIT_CHGR_PD);
51 }
52
53 static void sprdchg_set_recharge(void)
54 {
55         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL2, BIT_RECHG);
56 }
57
58 void sprdchg_set_chg_cur(uint32_t chg_current)
59 {
60         uint32_t temp;
61
62         if (chg_current < 1400) {
63                 temp = ((chg_current - 300) / 50);
64         } else {
65                 temp = ((chg_current - 1400) / 100);
66                 temp += 0x16;
67         }
68
69         sci_adi_clr(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
70
71         sci_adi_write(ANA_REG_GLB_CHGR_CTRL1,
72                       BITS_CHGR_CC_I(temp), BITS_CHGR_CC_I(~0));
73
74         sci_adi_set(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
75 }
76
77 void sprdchg_start_charge() {
78         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL2, BIT_RECHG);
79         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL1, BIT_12|BIT_10);
80 }
81
82 uint32_t sprdbat_get_vbatauxadc_caltype(void)
83 {
84         return adc_cal_flag;
85 }
86
87 #ifndef CONFIG_FDL2_BUILD
88 extern void sprd_ext_charger_init(void);
89 extern void sprd_ext_charger_uninit(void);
90 void sprdchg_lowbat_charge(void)
91 {
92 #ifdef CONFIG_SPRD_EXT_IC_POWER
93         sprd_ext_charger_init();
94 #else
95         return;
96 #endif
97 }
98
99 void sprdbat_lateinit(void)
100 {
101 #ifdef CONFIG_SPRD_EXT_IC_POWER
102         sprd_ext_charger_uninit();
103 #else
104         return;
105 #endif
106 }
107
108 #endif
109
110 #ifndef CONFIG_FDL1
111 /* used to get adc calibration data from nv or efuse */
112 void sprdbat_get_vbatauxadc_caldata(void)
113 {
114         unsigned int adc_data[64];
115         int ret = 0;
116
117         adc_cal_flag = ADC_CAL_TYPE_NO;
118
119 #ifndef FDL_CHG_SP8830
120         /* get voltage values from nv */
121         ret = read_adc_calibration_data((char *)adc_data, 48);
122         if ((ret > 0) &&
123             ((adc_data[2] & 0xFFFF) < 4500) && ((adc_data[2] & 0xFFFF) > 3000)
124             && ((adc_data[3] & 0xFFFF) < 4500)
125             && ((adc_data[3] & 0xFFFF) > 3000)) {
126                 debugf("adc_para from nv is 0x%x 0x%x \n", adc_data[2],
127                        adc_data[3]);
128                 adc_voltage_table[0][1] = adc_data[2] & 0xFFFF;
129                 adc_voltage_table[0][0] = (adc_data[2] >> 16) & 0xFFFF;
130                 adc_voltage_table[1][1] = adc_data[3] & 0xFFFF;
131                 adc_voltage_table[1][0] = (adc_data[3] >> 16) & 0xFFFF;
132                 adc_cal_flag = ADC_CAL_TYPE_NV;
133         }
134 #endif
135         /* get voltage values from efuse */
136         if (adc_cal_flag == ADC_CAL_TYPE_NO) {
137                 ret = sci_efuse_calibration_get(adc_data);
138                 if (ret > 0) {
139                         debugf("adc_para from efuse is 0x%x 0x%x \n",
140                                adc_data[0], adc_data[1]);
141                         adc_voltage_table[0][1] = adc_data[0] & 0xFFFF;
142                         adc_voltage_table[0][0] = (adc_data[0] >> 16) & 0xFFFF;
143                         adc_voltage_table[1][1] = adc_data[1] & 0xFFFF;
144                         adc_voltage_table[1][0] = (adc_data[1] >> 16) & 0xFFFF;
145                         adc_cal_flag = ADC_CAL_TYPE_EFUSE;
146                 }
147         }
148 }
149 #endif
150
151 #ifndef FDL_CHG_SP8830
152 int sprdchg_charger_is_adapter(void)
153 {
154         int ret = ADP_TYPE_UNKNOW;
155         int charger_status;
156         charger_status = sci_adi_read(ANA_REG_GLB_CHGR_STATUS)
157             & (BIT_CDP_INT | BIT_DCP_INT | BIT_SDP_INT);
158
159         switch (charger_status) {
160         case BIT_CDP_INT:
161                 ret = ADP_TYPE_CDP;
162                 break;
163         case BIT_DCP_INT:
164                 ret = ADP_TYPE_DCP;
165                 break;
166         case BIT_SDP_INT:
167                 ret = ADP_TYPE_SDP;
168                 break;
169         default:
170                 break;
171         }
172         return ret;
173 }
174
175 #define REGS_FGU_BASE SPRD_ANA_FPU_PHYS
176 #define REG_FGU_START                   SCI_ADDR(REGS_FGU_BASE, 0x0000)
177 #define REG_FGU_CONFIG                  SCI_ADDR(REGS_FGU_BASE, 0x0004)
178 #define REG_FGU_INT_EN                  SCI_ADDR(REGS_FGU_BASE, 0x0010)
179 #define REG_FGU_INT_CLR                 SCI_ADDR(REGS_FGU_BASE, 0x0014)
180 #define REG_FGU_VOLT_VAL                SCI_ADDR(REGS_FGU_BASE, 0x0020)
181 #define REG_FGU_OCV_VAL                 SCI_ADDR(REGS_FGU_BASE, 0x0024)
182 #define REG_FGU_POCV_VAL                SCI_ADDR(REGS_FGU_BASE, 0x0028)
183 #define REG_FGU_CURT_VAL                SCI_ADDR(REGS_FGU_BASE, 0x002c)
184 #define REG_FGU_CURT_OFFSET             SCI_ADDR(REGS_FGU_BASE, 0x0090)
185 #define BIT_VOLT_H_VALID                ( BIT(12) )
186 #define BITS_VOLT_DUTY(_x_)             ( (_x_) << 5 & (BIT(5)|BIT(6)) )
187
188 #define REG_FGU_USER_AREA_SET             SCI_ADDR(REGS_FGU_BASE, 0x00A0)
189 #define REG_FGU_USER_AREA_CLEAR             SCI_ADDR(REGS_FGU_BASE, 0x00A4)
190 #define REG_FGU_USER_AREA_STATUS             SCI_ADDR(REGS_FGU_BASE, 0x00A8)
191
192 #define BITS_POWERON_TYPE_SHIFT   12
193 #define BITS_POWERON_TYPE(_x_)           ( (_x_) << 12 & (0xF000))
194 #define BITS_RTC_AREA_SHIFT     0
195 #define BITS_RTC_AREA(_x_)           ( (_x_) << 0 & (0xFFF) )
196
197 #define FIRST_POWERTON  0xF
198 #define NORMAIL_POWERTON  0x5
199 #define WDG_POWERTON  0xA
200
201 static void sprdfgu_rtc_reg_write(uint32_t val)
202 {
203         sci_adi_write(REG_FGU_USER_AREA_CLEAR, BITS_RTC_AREA(~val),
204                       BITS_RTC_AREA(~0));
205         sci_adi_write(REG_FGU_USER_AREA_SET, BITS_RTC_AREA(val),
206                       BITS_RTC_AREA(~0));
207 }
208
209 static uint32_t sprdfgu_rtc_reg_read(void)
210 {
211         return (sci_adi_read(REG_FGU_USER_AREA_STATUS) & BITS_RTC_AREA(~0)) >>
212             BITS_RTC_AREA_SHIFT;
213 }
214
215 static void sprdfgu_poweron_type_write(uint32_t val)
216 {
217         sci_adi_write(REG_FGU_USER_AREA_CLEAR, BITS_POWERON_TYPE(~val),
218                       BITS_POWERON_TYPE(~0));
219         sci_adi_write(REG_FGU_USER_AREA_SET, BITS_POWERON_TYPE(val),
220                       BITS_POWERON_TYPE(~0));
221 }
222
223 static uint32_t sprdfgu_poweron_type_read(void)
224 {
225         return (sci_adi_read(REG_FGU_USER_AREA_STATUS) & BITS_POWERON_TYPE(~0))
226             >> BITS_POWERON_TYPE_SHIFT;
227 }
228
229 #define mdelay(_ms) udelay(_ms*1000)
230 unsigned int fgu_vol, fgu_cur;
231
232 unsigned int get_fgu_vol() {
233         return fgu_vol;
234 }
235
236 unsigned int get_fgu_cur() {
237         return fgu_cur;
238 }
239
240 void sprdfgu_init(void)
241 {
242
243         sci_adi_set(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_FGU_EN);
244         sci_adi_set(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_FGU_EN | BIT_RTC_FGUA_EN);
245
246         sci_adi_clr(REG_FGU_INT_EN, 0xFFFF);    //disable int after watchdog reset
247         sci_adi_set(REG_FGU_INT_CLR, 0xFFFF);
248         sci_adi_write(REG_FGU_CURT_OFFSET, 0, ~0);      //init offset after watchdog reset
249
250         //mdelay(1000);
251
252         fgu_vol = sci_adi_read(REG_FGU_VOLT_VAL);
253         fgu_cur = sci_adi_read(REG_FGU_CURT_VAL);
254
255         debugf("fgu_init fgu_vol 0x%x fgu_cur 0x%x \n", fgu_vol, fgu_cur);
256 }
257
258 int sprdbat_is_battery_connected(void)
259 {
260         printf("eica status bat%x\n", sprd_eic_get(EIC_BATDET));
261
262         return ! !sprd_eic_get(EIC_BATDET);
263 }
264
265 void sprdbat_init(void)
266 {
267 #ifdef  CONFIG_SHARK_PAD_HW_V102
268         sprd_gpio_request(NULL, USB_CHG_EN);
269         sprd_gpio_direction_output(NULL, USB_CHG_EN, 1);
270         sprd_gpio_set(NULL, USB_CHG_EN, 1);
271         mdelay(20);
272         sprd_gpio_set(NULL, USB_CHG_EN, 0);
273 #endif
274
275         sprd_eic_request(EIC_BATDET);   //enable battery detect eic
276
277         //set charge current 500mA(USB) or 600mA(AC)
278         if (charger_connected()) {
279                 enum sprd_adapter_type adp_type = sprdchg_charger_is_adapter();
280                 if (adp_type == ADP_TYPE_CDP || adp_type == ADP_TYPE_DCP) {
281                         debugf("uboot adp AC\n");
282 //                      sprdchg_set_chg_cur(700);
283                 } else {
284                         debugf("uboot adp USB\n");
285 //                      sprdchg_set_chg_cur(450);
286                 }
287         }
288 #if defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
289         sci_adi_write(ANA_REG_GLB_CHGR_CTRL2,
290                 BITS_CHGR_DPM(3), BITS_CHGR_DPM(~0));   //fixed bug367845, only for 2723
291         mdelay(10);
292 #endif
293         sprdchg_set_recharge();
294         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
295         sprdchg_start_charge();
296
297         sprdbat_get_vbatauxadc_caldata();
298         sprdfgu_init();
299         //if battery do NOT connect, shutdown charge,maybe system poweroff
300         if (!sprdbat_is_battery_connected()) {
301                 printf("battery unconnected shutdown charge!!!!!\n");
302                 sprdchg_stop_charge();
303         } else {
304                 if (charger_connected()) {
305                         if ((FIRST_POWERTON == sprdfgu_poweron_type_read())
306                             || (sprdfgu_rtc_reg_read() == 0xFFF)) {
307                                 sprdfgu_rtc_reg_write(0xFF);
308                                 mdelay(1);
309                                 sprdfgu_poweron_type_write(NORMAIL_POWERTON);
310                                 printf("charge first poweron reset!!!!!\n");
311                                 mdelay(3);
312                                 sprdchg_stop_charge();
313                                 power_down_devices(0);
314                         }
315                 }
316         }
317         if (sprdfgu_rtc_reg_read() == 0xFF) {
318                 printf("secend poweron !!!!!\n");
319                 sprdfgu_poweron_type_write(FIRST_POWERTON);
320                 mdelay(1);
321                 sprdfgu_rtc_reg_write(0xFFF);
322         }
323 }
324 #endif