tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / power / sprd_battery_2713.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 <sprd_battery.h>
8
9 #ifdef DEBUG
10 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
11 #else
12 #define debugf(fmt, args...)
13 #endif
14 #define ADC_CAL_TYPE_NO                 0
15 #define ADC_CAL_TYPE_NV                 1
16 #define ADC_CAL_TYPE_EFUSE              2
17
18 extern int charger_connected(void);
19 extern int read_adc_calibration_data(char *buffer,int size);
20 extern int sci_efuse_calibration_get(unsigned int * p_cal_data);
21 uint16_t adc_voltage_table[2][2] = {
22         {3310, 4200},
23         {2832, 3600},
24 };
25
26 uint32_t adc_cal_flag = 0;
27
28 uint16_t sprdbat_auxadc2vbatvol(uint16_t adcvalue)
29 {
30         int32_t temp;
31         temp = adc_voltage_table[0][1] - adc_voltage_table[1][1];
32         temp = temp * (adcvalue - adc_voltage_table[0][0]);
33         temp = temp / (adc_voltage_table[0][0] - adc_voltage_table[1][0]);
34
35         debugf("uboot battery voltage:%d,adc4200:%d,adc3600:%d\n",
36                temp + adc_voltage_table[0][1], adc_voltage_table[0][0],
37                adc_voltage_table[1][0]);
38
39         return temp + adc_voltage_table[0][1];
40 }
41
42 void sprdchg_start_charge(void)
43 {
44 #if defined(CONFIG_SPX15) || defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
45         ANA_REG_MSK_OR(ANA_REG_GLB_CHGR_CTRL0, 0, BIT_CHGR_PD);
46 #else
47         ANA_REG_MSK_OR(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_PD_RTCCLR, (BIT_CHGR_PD_RTCCLR | BIT_CHGR_PD_RTCSET));
48 #endif
49 }
50
51 void sprdchg_stop_charge(void)
52 {
53 #if defined(CONFIG_SPX15) || defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
54         ANA_REG_MSK_OR(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_PD, BIT_CHGR_PD);
55 #else
56         ANA_REG_MSK_OR(ANA_REG_GLB_CHGR_CTRL0, BIT_CHGR_PD_RTCSET, (BIT_CHGR_PD_RTCCLR | BIT_CHGR_PD_RTCSET));
57 #endif
58 }
59
60 static void sprdchg_set_recharge(void)
61 {
62         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL2, BIT_RECHG);
63 }
64 void sprdchg_set_chg_cur(uint32_t chg_current)
65 {
66         uint32_t temp;
67
68         if (chg_current < 1400) {
69                 temp = ((chg_current - 300) / 50);
70         } else {
71                 temp = ((chg_current - 1400) / 100);
72                 temp += 0x16;
73         }
74
75         sci_adi_clr(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
76
77         sci_adi_write(ANA_REG_GLB_CHGR_CTRL1,
78                       BITS_CHGR_CC_I(temp), BITS_CHGR_CC_I(~0));
79
80         sci_adi_set(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
81 }
82
83 uint32_t sprdbat_get_vbatauxadc_caltype(void)
84 {
85         return adc_cal_flag;
86 }
87
88 #ifndef CONFIG_FDL2_BUILD
89 extern void sprd_ext_charger_init(void);
90 extern void sprd_ext_charger_uninit(void);
91 void sprdchg_lowbat_charge(void)
92 {
93 #ifdef CONFIG_SPRD_EXT_IC_POWER
94         sprd_ext_charger_init();
95 #else
96         return;
97 #endif
98 }
99
100 void sprdbat_lateinit(void)
101 {
102 #ifdef CONFIG_SPRD_EXT_IC_POWER
103         sprd_ext_charger_uninit();
104 #else
105         return;
106 #endif
107 }
108
109 #endif
110
111
112 #ifndef CONFIG_FDL1
113 /* used to get adc calibration data from nv or efuse */
114 void sprdbat_get_vbatauxadc_caldata(void)
115 {
116         unsigned int adc_data[64];
117         int ret=0;
118
119         adc_cal_flag = ADC_CAL_TYPE_NO;
120
121 #ifndef FDL_CHG_SP8830
122         /* get voltage values from nv */
123         ret = read_adc_calibration_data((char *)adc_data,48);
124         if((ret > 0) &&
125                         ((adc_data[2] & 0xFFFF) < 4500 ) && ((adc_data[2] & 0xFFFF) > 3000) &&
126                         ((adc_data[3] & 0xFFFF) < 4500 ) && ((adc_data[3] & 0xFFFF) > 3000)){
127                 debugf("adc_para from nv is 0x%x 0x%x \n",adc_data[2],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",adc_data[0],adc_data[1]);
140                         adc_voltage_table[0][1]=adc_data[0] & 0xFFFF;
141                         adc_voltage_table[0][0]=(adc_data[0]>>16) & 0xFFFF;
142                         adc_voltage_table[1][1]=adc_data[1] & 0xFFFF;
143                         adc_voltage_table[1][0]=(adc_data[1] >> 16) & 0xFFFF;
144                         adc_cal_flag = ADC_CAL_TYPE_EFUSE;
145                 }
146         }
147 }
148 #endif
149
150 #ifndef FDL_CHG_SP8830
151 int sprdchg_charger_is_adapter(void)
152 {
153         int ret = ADP_TYPE_UNKNOW;
154         int charger_status;
155         charger_status = sci_adi_read(ANA_REG_GLB_CHGR_STATUS)
156             & (BIT_CDP_INT | BIT_DCP_INT | BIT_SDP_INT);
157
158         switch (charger_status) {
159         case BIT_CDP_INT:
160                 ret = ADP_TYPE_CDP;
161                 break;
162         case BIT_DCP_INT:
163                 ret = ADP_TYPE_DCP;
164                 break;
165         case BIT_SDP_INT:
166                 ret = ADP_TYPE_SDP;
167                 break;
168         default:
169                 break;
170         }
171         return ret;
172 }
173
174 #define REGS_FGU_BASE SPRD_ANA_FPU_PHYS
175 #define REG_FGU_START                   SCI_ADDR(REGS_FGU_BASE, 0x0000)
176 #define REG_FGU_CONFIG                  SCI_ADDR(REGS_FGU_BASE, 0x0004)
177 #define REG_FGU_INT_EN                  SCI_ADDR(REGS_FGU_BASE, 0x0010)
178 #define REG_FGU_INT_CLR                 SCI_ADDR(REGS_FGU_BASE, 0x0014)
179 #define REG_FGU_VOLT_VAL                SCI_ADDR(REGS_FGU_BASE, 0x0020)
180 #define REG_FGU_OCV_VAL                 SCI_ADDR(REGS_FGU_BASE, 0x0024)
181 #define REG_FGU_POCV_VAL                SCI_ADDR(REGS_FGU_BASE, 0x0028)
182 #define REG_FGU_CURT_VAL                SCI_ADDR(REGS_FGU_BASE, 0x002c)
183 #define REG_FGU_CURT_OFFSET             SCI_ADDR(REGS_FGU_BASE, 0x0090)
184
185 #define BIT_VOLT_H_VALID                ( BIT(12) )
186 #define BITS_VOLT_DUTY(_x_)             ( (_x_) << 5 & (BIT(5)|BIT(6)) )
187
188 #define mdelay(_ms) udelay(_ms*1000)
189 unsigned int fgu_vol, fgu_cur;
190 void sprdfgu_init(void)
191 {
192 #if defined(CONFIG_SPX15) ||defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
193         //sci_adi_clr(ANA_REG_GLB_CHGR_DET_FGU_CTRL, (BIT_SD_CHOP_CAP_EN|BIT_CHOP_EN));
194 #else
195         //sci_adi_set(ANA_REG_GLB_MP_MISC_CTRL, (BIT(1)));
196         sci_adi_write(ANA_REG_GLB_MP_MISC_CTRL, BIT(1), (BIT(1) | BIT(2)));
197         sci_adi_write(ANA_REG_GLB_DCDC_CTRL2, (4 << 8), (7 << 8));
198 #endif
199         sci_adi_set(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_FGU_EN);
200         sci_adi_set(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_FGU_EN | BIT_RTC_FGUA_EN);
201
202 #if 1
203         {
204                 int i = 0;
205                 sci_adi_set(ANA_REG_GLB_ARM_RST, BIT_ANA_FGU_SOFT_RST);
206                 for (i = 0; i < 1000; i++) {;}
207                 sci_adi_clr(ANA_REG_GLB_ARM_RST, BIT_ANA_FGU_SOFT_RST);
208         }
209 #endif
210         //sci_adi_clr(REG_FGU_INT_EN, 0xFFFF);    //disable int after watchdog reset
211         //sci_adi_set(REG_FGU_INT_CLR, 0xFFFF);
212         //sci_adi_write(REG_FGU_CURT_OFFSET, 0, ~0);  //init offset after watchdog reset
213
214         //sci_adi_clr(REG_FGU_CONFIG, BIT_VOLT_H_VALID);
215         //sci_adi_clr(REG_FGU_CONFIG, BIT_AD1_ENABLE);
216 #if defined(CONFIG_SPX15) ||defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
217         if(sci_get_adie_chip_id() < 0x2711A100) {
218                 sci_adi_write(REG_FGU_CONFIG, BITS_VOLT_DUTY(3), BITS_VOLT_DUTY(3)|BIT_VOLT_H_VALID);
219         }
220 #else
221         sci_adi_write(REG_FGU_CONFIG, BITS_VOLT_DUTY(3), BITS_VOLT_DUTY(3)|BIT_VOLT_H_VALID);
222 #endif
223         //mdelay(1000);
224
225         fgu_vol = 0; //sci_adi_read(REG_FGU_VOLT_VAL);
226
227         fgu_cur = 0; //sci_adi_read(REG_FGU_CURT_VAL);
228         debugf("fgu_init fgu_vol 0x%x fgu_cur 0x%x \n", fgu_vol, fgu_cur);
229 }
230
231 void sprdbat_init(void)
232 {
233 #ifdef  CONFIG_SHARK_PAD_HW_V102
234         sprd_gpio_request(NULL,USB_CHG_EN);
235         sprd_gpio_direction_output(NULL, USB_CHG_EN, 1);
236         sprd_gpio_set(NULL, USB_CHG_EN, 1);
237         mdelay(20);
238         sprd_gpio_set(NULL, USB_CHG_EN, 0);
239 #endif
240         //set charge current 500mA(USB) or 600mA(AC)
241         if (charger_connected()) {
242                 enum sprd_adapter_type adp_type = sprdchg_charger_is_adapter();
243                 if (adp_type == ADP_TYPE_CDP || adp_type == ADP_TYPE_DCP) {
244                         debugf("uboot adp AC\n");
245                         sprdchg_set_chg_cur(700);
246                 } else {
247                         debugf("uboot adp USB\n");
248                         sprdchg_set_chg_cur(500);
249                 }
250         }
251
252         sprdchg_set_recharge();
253         ANA_REG_OR(ANA_REG_GLB_CHGR_CTRL2, BIT_CHGR_CC_EN);
254         sprdchg_start_charge();
255
256         sprdbat_get_vbatauxadc_caldata();
257         sprdfgu_init();
258 }
259 #endif