2 * Copyright (C) 2013 Spreadtrum Communications Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/interrupt.h>
16 #include <linux/err.h>
18 #include <linux/wakelock.h>
19 #include <linux/hrtimer.h>
20 #include <linux/delay.h>
21 #include <linux/device.h>
22 #include <linux/gpio.h>
23 #include <linux/platform_device.h>
24 #include <linux/power_supply.h>
26 #include <soc/sprd/sci.h>
27 #include <soc/sprd/sci_glb_regs.h>
28 #include <soc/sprd/adi.h>
29 #include <soc/sprd/adc.h>
31 #include "sprd_2713_fgu.h"
32 #include "sprd_battery.h"
33 #include <linux/battery/fuelgauge/sprd27x3_fuelgauge4samsung.h>
34 #include <linux/battery/sec_charging_common.h>
36 #define REGS_FGU_BASE ANA_FPU_INT_BASE
40 /* registers definitions for controller REGS_FGU */
41 #define REG_FGU_START SCI_ADDR(REGS_FGU_BASE, 0x0000)
42 #define REG_FGU_CONFIG SCI_ADDR(REGS_FGU_BASE, 0x0004)
43 #define REG_FGU_ADC_CONFIG SCI_ADDR(REGS_FGU_BASE, 0x0008)
44 #define REG_FGU_STATUS SCI_ADDR(REGS_FGU_BASE, 0x000c)
45 #define REG_FGU_INT_EN SCI_ADDR(REGS_FGU_BASE, 0x0010)
46 #define REG_FGU_INT_CLR SCI_ADDR(REGS_FGU_BASE, 0x0014)
47 #define REG_FGU_INT_RAW SCI_ADDR(REGS_FGU_BASE, 0x0018)
48 #define REG_FGU_INT_STS SCI_ADDR(REGS_FGU_BASE, 0x001c)
49 #define REG_FGU_VOLT_VAL SCI_ADDR(REGS_FGU_BASE, 0x0020)
50 #define REG_FGU_OCV_VAL SCI_ADDR(REGS_FGU_BASE, 0x0024)
51 #define REG_FGU_POCV_VAL SCI_ADDR(REGS_FGU_BASE, 0x0028)
52 #define REG_FGU_CURT_VAL SCI_ADDR(REGS_FGU_BASE, 0x002c)
53 #define REG_FGU_HIGH_OVER SCI_ADDR(REGS_FGU_BASE, 0x0030)
54 #define REG_FGU_LOW_OVER SCI_ADDR(REGS_FGU_BASE, 0x0034)
55 #define REG_FGU_VTHRE_HH SCI_ADDR(REGS_FGU_BASE, 0x0038)
56 #define REG_FGU_VTHRE_HL SCI_ADDR(REGS_FGU_BASE, 0x003c)
57 #define REG_FGU_VTHRE_LH SCI_ADDR(REGS_FGU_BASE, 0x0040)
58 #define REG_FGU_VTHRE_LL SCI_ADDR(REGS_FGU_BASE, 0x0044)
59 #define REG_FGU_OCV_LOCKLO SCI_ADDR(REGS_FGU_BASE, 0x0048)
60 #define REG_FGU_OCV_LOCKHI SCI_ADDR(REGS_FGU_BASE, 0x004c)
61 #define REG_FGU_CLBCNT_SETH SCI_ADDR(REGS_FGU_BASE, 0x0050)
62 #define REG_FGU_CLBCNT_SETL SCI_ADDR(REGS_FGU_BASE, 0x0054)
63 #define REG_FGU_CLBCNT_DELTH SCI_ADDR(REGS_FGU_BASE, 0x0058)
64 #define REG_FGU_CLBCNT_DELTL SCI_ADDR(REGS_FGU_BASE, 0x005c)
65 #define REG_FGU_CLBCNT_LASTOCVH SCI_ADDR(REGS_FGU_BASE, 0x0060)
66 #define REG_FGU_CLBCNT_LASTOCVL SCI_ADDR(REGS_FGU_BASE, 0x0064)
67 #define REG_FGU_CLBCNT_VALH SCI_ADDR(REGS_FGU_BASE, 0x0068)
68 #define REG_FGU_CLBCNT_VALL SCI_ADDR(REGS_FGU_BASE, 0x006c)
69 #define REG_FGU_CLBCNT_QMAXH SCI_ADDR(REGS_FGU_BASE, 0x0070)
70 #define REG_FGU_CLBCNT_QMAXL SCI_ADDR(REGS_FGU_BASE, 0x0074)
71 #define REG_FGU_QMAX_TOSET SCI_ADDR(REGS_FGU_BASE, 0x0078)
72 #define REG_FGU_QMAX_TIMER SCI_ADDR(REGS_FGU_BASE, 0x007c)
73 #define REG_FGU_RELAX_CURT_THRE SCI_ADDR(REGS_FGU_BASE, 0x0080)
74 #define REG_FGU_RELAX_CNT_THRE SCI_ADDR(REGS_FGU_BASE, 0x0084)
75 #define REG_FGU_RELAX_CNT SCI_ADDR(REGS_FGU_BASE, 0x0088)
76 #define REG_FGU_OCV_LAST_CNT SCI_ADDR(REGS_FGU_BASE, 0x008c)
77 #define REG_FGU_CURT_OFFSET SCI_ADDR(REGS_FGU_BASE, 0x0090)
79 #define REG_FGU_USER_AREA_SET SCI_ADDR(REGS_FGU_BASE, 0x00A0)
80 #define REG_FGU_USER_AREA_CLEAR SCI_ADDR(REGS_FGU_BASE, 0x00A4)
81 #define REG_FGU_USER_AREA_STATUS SCI_ADDR(REGS_FGU_BASE, 0x00A8)
83 #define BITS_POWERON_TYPE(_x_) ( (_x_) << 12 & (0xF000))
84 #define BITS_RTC_AREA(_x_) ( (_x_) << 0 & (0xFFF) )
86 /* bits definitions for register REG_FGU_START */
87 #define BIT_QMAX_UPDATE_EN ( BIT(2) )
88 #define BIT_FGU_RESET ( BIT(1) )
89 #define BIT_WRITE_SELCLB_EN ( BIT(0) )
91 /* bits definitions for register REG_FGU_CONFIG */
92 #define BIT_VOLT_H_VALID ( BIT(12) )
93 #define BIT_FGU_DISABLE_EN ( BIT(11) )
94 #define BIT_CLBCNT_DELTA_MODE ( BIT(10) )
95 #define BITS_ONEADC_DUTY(_x_) ( (_x_) << 8 & (BIT(8)|BIT(9)) )
96 #define BIT_CURT_DUTY ( BIT(7) )
97 #define BITS_VOLT_DUTY(_x_) ( (_x_) << 5 & (BIT(5)|BIT(6)) )
98 #define BIT_AD1_ENABLE ( BIT(4) )
99 #define BIT_SW_DIS_CURT ( BIT(3) )
100 #define BIT_FORCE_LOCK_EN ( BIT(2) )
101 #define BIT_LOW_POWER_MODE ( BIT(1) )
102 #define BIT_AUTO_LOW_POWER ( BIT(0) )
104 /* bits definitions for register REG_FGU_ADC_CONFIG */
105 #define BIT_FORCE_AD1_VIN_EN ( BIT(7) )
106 #define BIT_FORCE_AD0_VIN_EN ( BIT(6) )
107 #define BIT_FORCE_AD0_IIN_EN ( BIT(5) )
108 #define BIT_FORCE_AD_EN ( BIT(4) )
109 #define BIT_AD1_VOLT_REF ( BIT(3) )
110 #define BIT_AD0_VOLT_REF ( BIT(2) )
111 #define BIT_AD01_RESET ( BIT(1) )
112 #define BIT_AD01_PD ( BIT(0) )
114 /* bits definitions for register REG_FGU_STATUS */
115 #define BIT_POWER_LOW ( BIT(5) )
116 #define BIT_CURT_LOW ( BIT(4) )
117 #define BITS_OCV_LOCK_STS(_x_) ( (_x_) << 2 & (BIT(2)|BIT(3)) )
118 #define BIT_QMAX_UPDATE_STS ( BIT(1) )
119 #define BIT_WRITE_ACTIVE_STS ( BIT(0) )
121 /* bits definitions for register REG_FGU_INT_EN */
122 #define BIT_CURT_RDEN_INT ( BIT(7) )
123 #define BIT_VOLT_RDEN_INT ( BIT(6) )
124 #define BIT_QMAX_UPD_TOUT ( BIT(5) )
125 #define BIT_QMAX_UPD_DONE ( BIT(4) )
126 #define BIT_RELX_CNT_INT ( BIT(3) )
127 #define BIT_CLBCNT_DELTA_INT ( BIT(2) )
128 #define BIT_VOLT_HIGH_INT ( BIT(1) )
129 #define BIT_VOLT_LOW_INT ( BIT(0) )
131 #define BITS_VOLT_VALUE(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) )
133 /* bits definitions for register REG_FGU_CURT_VAL */
134 #define BITS_CURT_VALUE(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)) )
136 /* bits definitions for register REG_FGU_CLBCNT_SETH */
137 #define BITS_CLBCNT_SETH(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)) )
139 /* bits definitions for register REG_FGU_CLBCNT_SETL */
140 #define BITS_CLBCNT_SETL(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)|BIT(14)|BIT(15)) )
142 /* bits definitions for register REG_FGU_CLBCNT_DELTHAH */
143 #define BITS_CLBCNT_DELTHH(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)) )
145 /* bits definitions for register REG_FGU_CLBCNT_DELTAL */
146 #define BITS_CLBCNT_DELTHL(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)|BIT(14)|BIT(15)) )
148 /* bits definitions for register REG_FGU_RELAX_CURT_THRE */
149 #define BITS_RELAX_CUR_THRE(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)) )
151 /* bits definitions for register REG_FGU_RELAX_CNT_THRE */
152 #define BITS_RELAX_CNT_THRE(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) )
154 /* bits definitions for register REG_FGU_RELAX_CNT */
155 #define BITS_RELAX_CNT_VAL(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) )
157 /* bits definitions for register REG_FGU_OCV_LAST_CNT */
158 #define BITS_OCV_LAST_CNT(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)) )
160 /* bits definitions for register REG_FGU_CURT_OFFSET */
161 #define BITS_CURT_OFFSET_VAL(_x_) ( (_x_) << 0 & (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)|BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13)) )
163 #define SPRDFGU__DEBUG
164 #ifdef SPRDFGU__DEBUG
165 #define FGU_DEBUG(format, arg...) do{\
166 pr_info("sprdfgu: " format, ## arg);\
169 #define FGU_DEBUG(format, arg...)
172 #define SPRDFGU_TEMP_COMP_SOC
174 #define SPRDFGU_OCV_VALID_TIME 20
176 #define CUR_0ma_IDEA_ADC 8192
178 #define FGU_CUR_SAMPLE_HZ 2
180 #define FIRST_POWERTON 0xF
181 #define NORMAIL_POWERTON 0x5
182 #define WDG_POWERTON 0xA
183 struct sprdfgu_drivier_data {
184 struct sprd_battery_platform_data *pdata;
193 unsigned int int_status;
194 struct delayed_work fgu_irq_work;
195 struct power_supply sprdfgu;
197 struct wake_lock low_power_lock;
200 struct sprdfgu_drivier_data sprdfgu_data;
208 static struct sprdfgu_cal fgu_cal = { 2872, 678, 0, 0, SPRDBAT_FGUADC_CAL_NO };
211 struct delayed_work sprdfgu_debug_work;
212 uint32_t sprdfgu_debug_log_time = 120;
213 static int poweron_clbcnt;
214 static u32 start_time;
217 static int fgu_nv_4200mv = 2752;
218 static int fgu_nv_3600mv = 2374;
219 static int fgu_0_cur_adc = 8338;
221 static int cmd_vol_raw, cmd_cur_raw;
223 static BLOCKING_NOTIFIER_HEAD(fgu_chain_head);
224 extern int in_calibration(void);
226 #define REG_SYST_VALUE ((void __iomem *)(SPRD_SYSCNT_BASE + 0x0004))
227 static u32 sci_syst_read(void)
229 #if !(defined(CONFIG_ARCH_SCX35L64)||defined(CONFIG_ARCH_SCX35LT8)) //mingwei TODO
230 u32 t = __raw_readl(REG_SYST_VALUE);
231 while (t != __raw_readl(REG_SYST_VALUE))
232 t = __raw_readl(REG_SYST_VALUE);
239 static int sprdfgu_vol2capacity(uint32_t voltage)
242 sprdbat_interpolate(voltage, sprdfgu_data.pdata->ocv_tab_size,
243 sprdfgu_data.pdata->ocv_tab);
248 static int __init fgu_cal_start(char *str)
250 unsigned int fgu_data[3] = { 0 };
251 char *cali_data = &str[1];
253 printk("sprdfgu fgu_cal%s!\n", str);
254 sscanf(cali_data, "%d,%d,%d", &fgu_data[0], &fgu_data[1],
256 printk("sprdfgu fgu_data: 0x%x 0x%x,0x%x!\n", fgu_data[0],
257 fgu_data[1], fgu_data[2]);
258 fgu_nv_4200mv = (fgu_data[0] >> 16) & 0xffff;
259 fgu_nv_3600mv = (fgu_data[1] >> 16) & 0xffff;
260 fgu_0_cur_adc = fgu_data[2];
261 fgu_cal.cal_type = SPRDBAT_FGUADC_CAL_NV;
266 __setup("fgu_cal", fgu_cal_start);
267 static int __init fgu_cmd(char *str)
269 int fgu_data[2] = { 0 };
270 char *cali_data = &str[1];
272 pr_info("fgu cmd%s!\n", str);
273 sscanf(cali_data, "%d,%d", &fgu_data[0], &fgu_data[1]);
274 pr_info("fgu_cmd adc_data: 0x%x 0x%x!\n", fgu_data[0],
276 cmd_vol_raw = fgu_data[0];
277 cmd_cur_raw = fgu_data[1];
282 __setup("fgu_init", fgu_cmd);
284 static int sprdfgu_cal_init(void)
286 BUG_ON(fgu_nv_4200mv <= fgu_nv_3600mv);
287 if (0 == fgu_nv_3600mv) {
288 fgu_cal.vol_1000mv_adc =
289 DIV_ROUND_CLOSEST((fgu_nv_4200mv) * 10, 42);
290 fgu_cal.vol_offset = 0;
291 fgu_cal.cur_offset = 0;
292 fgu_cal.cur_1000ma_adc =
293 DIV_ROUND_CLOSEST(fgu_cal.vol_1000mv_adc * 4 *
294 sprdfgu_data.pdata->rsense_real,
295 sprdfgu_data.pdata->rsense_spec);
297 fgu_cal.vol_1000mv_adc =
298 DIV_ROUND_CLOSEST((fgu_nv_4200mv - fgu_nv_3600mv) * 10, 6);
300 0 - (fgu_nv_4200mv * 10 - fgu_cal.vol_1000mv_adc * 42) / 10;
301 fgu_cal.cur_offset = CUR_0ma_IDEA_ADC - fgu_0_cur_adc;
302 fgu_cal.cur_1000ma_adc =
303 DIV_ROUND_CLOSEST(fgu_cal.vol_1000mv_adc * 4 *
304 sprdfgu_data.pdata->rsense_real,
305 sprdfgu_data.pdata->rsense_spec);
307 if (SPRDBAT_FGUADC_CAL_CHIP == fgu_cal.cal_type) {
308 fgu_cal.vol_offset += sprdfgu_data.pdata->fgu_cal_ajust;
309 printk("sprdfgu: sprdfgu_data.pdata->fgu_cal_ajust = %d\n",
310 sprdfgu_data.pdata->fgu_cal_ajust);
314 ("sprdfgu: sprdfgu_cal_init fgu_nv_4200mv = %d,fgu_nv_3600mv = %d,fgu_0_cur_adc = %d\n",
315 fgu_nv_4200mv, fgu_nv_3600mv, fgu_0_cur_adc);
317 ("sprdfgu: sprdfgu_cal_init fgu_cal.cur_1000ma_adc = %d,fgu_cal.vol_1000mv_adc = %d,fgu_cal.vol_offset = %d,fgu_cal.cur_offset = %d\n",
318 fgu_cal.cur_1000ma_adc, fgu_cal.vol_1000mv_adc, fgu_cal.vol_offset,
324 #ifdef CONFIG_OTP_SPRD
325 int sci_efuse_fgu_cal_get(unsigned int *p_cal_data);
327 static int sprdfgu_cal_from_chip(void)
329 unsigned int fgu_data[4] = { 0 };
331 #ifdef CONFIG_OTP_SPRD
332 if (!sci_efuse_fgu_cal_get(fgu_data)) {
333 printk("sprdfgu: sprdfgu_cal_from_chip efuse no cal data\n");
337 printk("sprdfgu fgu_data: 0x%x 0x%x,0x%x,0x%x!\n", fgu_data[0],
338 fgu_data[1], fgu_data[2], fgu_data[3]);
339 printk("sprdfgu: sprdfgu_cal_from_chip\n");
341 fgu_nv_4200mv = fgu_data[0];
342 #if defined(CONFIG_ADIE_SC2723) //2723 use one point to cal fgu adc
346 fgu_nv_3600mv = fgu_data[1];
347 fgu_0_cur_adc = fgu_data[2];
349 fgu_cal.cal_type = SPRDBAT_FGUADC_CAL_CHIP;
354 static u32 sprdfgu_adc2vol_mv(u32 adc)
356 return ((adc + fgu_cal.vol_offset) * 1000) / fgu_cal.vol_1000mv_adc;
359 static u32 sprdfgu_vol2adc_mv(u32 vol)
361 return (vol * fgu_cal.vol_1000mv_adc) / 1000 - fgu_cal.vol_offset;
364 static int sprdfgu_adc2cur_ma(int adc)
366 return (adc * 1000) / fgu_cal.cur_1000ma_adc;
369 static u32 sprdfgu_cur2adc_ma(u32 cur)
371 return (cur * fgu_cal.cur_1000ma_adc) / 1000;
374 #if defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
375 static void sprdfgu_rtc_reg_write(uint32_t val)
377 sci_adi_write(REG_FGU_USER_AREA_CLEAR, BITS_RTC_AREA(~val),
379 sci_adi_write(REG_FGU_USER_AREA_SET, BITS_RTC_AREA(val),
383 static uint32_t sprdfgu_rtc_reg_read(void)
385 int shft = __ffs(BITS_RTC_AREA(~0));
386 return (sci_adi_read(REG_FGU_USER_AREA_STATUS) & BITS_RTC_AREA(~0)) >>
390 static void sprdfgu_poweron_type_write(uint32_t val)
392 sci_adi_write(REG_FGU_USER_AREA_CLEAR, BITS_POWERON_TYPE(~val),
393 BITS_POWERON_TYPE(~0));
394 sci_adi_write(REG_FGU_USER_AREA_SET, BITS_POWERON_TYPE(val),
395 BITS_POWERON_TYPE(~0));
398 static uint32_t sprdfgu_poweron_type_read(void)
400 int shft = __ffs(BITS_POWERON_TYPE(~0));
401 return (sci_adi_read(REG_FGU_USER_AREA_STATUS) & BITS_POWERON_TYPE(~0))
405 static inline int sprdfgu_clbcnt_get(void)
407 volatile int cc1 = 0, cc2 = 1;
410 cc1 = (sci_adi_read(REG_FGU_CLBCNT_VALL)) & 0xFFFF;
411 cc1 |= (((sci_adi_read(REG_FGU_CLBCNT_VALH)) & 0xFFFF) << 16);
413 cc2 = (sci_adi_read(REG_FGU_CLBCNT_VALL)) & 0xFFFF;
414 cc2 |= (((sci_adi_read(REG_FGU_CLBCNT_VALH)) & 0xFFFF) << 16);
415 } while (cc1 != cc2);
417 //FGU_DEBUG("sprdfgu_clbcnt_get cc: %d\n", cc1);
421 static inline int sprdfgu_clbcnt_set(int clbcc)
423 sci_adi_write(REG_FGU_CLBCNT_SETL, clbcc & 0xFFFF, ~0);
424 sci_adi_write(REG_FGU_CLBCNT_SETH, (clbcc >> 16) & 0xFFFF, ~0);
425 sci_adi_set(REG_FGU_START, BIT_WRITE_SELCLB_EN);
430 static inline int sprdfgu_reg_get(unsigned long reg)
435 vaule = sci_adi_read(reg);
436 } while (vaule != sci_adi_read(reg));
441 static inline int sprdfgu_clbcnt_init(u32 capacity)
444 DIV_ROUND_CLOSEST(sprdfgu_data.pdata->cnom * capacity, 100);
446 DIV_ROUND_CLOSEST(init_cap * fgu_cal.cur_1000ma_adc * 36 *
447 FGU_CUR_SAMPLE_HZ, 10);
451 static inline void sprdfgu_soc_adjust(int capacity)
453 sprdfgu_data.init_cap = capacity;
454 sprdfgu_data.init_clbcnt = sprdfgu_clbcnt_get();
455 FGU_DEBUG("sprdfgu_soc_adjust sprdfgu_data.init_cap= %d,%d\n",
456 sprdfgu_data.init_cap, sprdfgu_data.init_clbcnt);
459 uint32_t sprdfgu_read_vbat_vol(void)
463 cur_vol_raw = sprdfgu_reg_get(REG_FGU_VOLT_VAL);
464 //FGU_DEBUG("cur_vol_raw = %d\n", cur_vol_raw);
465 temp = sprdfgu_adc2vol_mv(cur_vol_raw);
466 //FGU_DEBUG("sprdfgu_read_vbat_vol : %d\n", temp);
470 static inline u32 sprdfgu_ocv_vol_get(void)
473 ocv_vol_raw = sprdfgu_reg_get(REG_FGU_OCV_VAL);
474 //FGU_DEBUG("ocv_vol_raw = %x\n", ocv_vol_raw);
475 return sprdfgu_adc2vol_mv(ocv_vol_raw);
478 static inline int sprdfgu_cur_current_get(void)
482 current_raw = sprdfgu_reg_get(REG_FGU_CURT_VAL);
483 //FGU_DEBUG("current_raw: %d\n", current_raw);
485 return sprdfgu_adc2cur_ma(current_raw - CUR_0ma_IDEA_ADC);
488 int sprdfgu_read_batcurrent(void)
490 #ifndef CONFIG_SPRD_NOFGUCURRENT_CHG
491 int temp = sprdfgu_cur_current_get();
492 //FGU_DEBUG("sprdfgu_read_batcurrent : %d\n", temp);
499 static int sprdfgu_read_vbat_ocv_pure(uint32_t * vol)
501 if (sprdfgu_reg_get(REG_FGU_OCV_LAST_CNT) > SPRDFGU_OCV_VALID_TIME
502 || sprdfgu_reg_get(REG_FGU_OCV_VAL) == 0) {
506 *vol = sprdfgu_ocv_vol_get();
510 uint32_t sprdfgu_read_vbat_ocv(void)
512 #ifndef CONFIG_SPRD_NOFGUCURRENT_CHG
514 int rint = sprdfgu_data.cur_rint;
516 #ifdef SPRDFGU_TEMP_COMP_SOC
518 union power_supply_propval value;
519 psy_do_property("battery", get, POWER_SUPPLY_PROP_TEMP, value);
520 rint = sprdbat_interpolate(value.intval/10, sprdfgu_data.pdata->rint_temp_tab_size,
521 sprdfgu_data.pdata->rint_temp_tab);
522 FGU_DEBUG("rint:%d,value.intval:%d\n", rint, value.intval);
526 if (sprdfgu_read_vbat_ocv_pure(&vol)) {
527 FGU_DEBUG("hwocv...\n");
530 return sprdfgu_read_vbat_vol() -
531 (sprdfgu_read_batcurrent() * rint) / 1000;
534 return sprdfgu_read_vbat_vol();
538 static int sprdfgu_temp_comp_soc(int soc, int temp)
541 int comp_soc, delta_soc;
545 cnom_temp = sprdbat_interpolate(temp, sprdfgu_data.pdata->cnom_temp_tab_size,
546 sprdfgu_data.pdata->cnom_temp_tab);
548 (sprdfgu_data.pdata->cnom - cnom_temp) * 100 / sprdfgu_data.pdata->cnom;
550 comp_soc = (long)(soc - delta_soc) * 100 / (100 - delta_soc);
558 FGU_DEBUG("cnom_temp %d, delta_soc %d,comp_soc%d,soc %d,temp %d\n",
559 cnom_temp, delta_soc, comp_soc, soc, temp);
564 int sprdfgu_read_soc(void)
566 int cur_cc, cc_delta, capcity_delta, temp;
569 mutex_lock(&sprdfgu_data.lock);
571 cur_cc = sprdfgu_clbcnt_get();
572 cc_delta = cur_cc - sprdfgu_data.init_clbcnt;
573 temp = DIV_ROUND_CLOSEST(cc_delta, (3600 * FGU_CUR_SAMPLE_HZ));
574 temp = sprdfgu_adc2cur_ma(temp);
575 FGU_DEBUG("sprdfgu_read_soc delta %dmAh,sprdfgu_data.init_clbcnt:%d\n",
576 temp, sprdfgu_data.init_clbcnt);
577 capcity_delta = DIV_ROUND_CLOSEST(temp * 100, sprdfgu_data.pdata->cnom);
578 FGU_DEBUG("sprdfgu_read_soc delta capacity %d,full capacity %d\n",
579 capcity_delta, sprdfgu_data.pdata->cnom);
581 capcity_delta += sprdfgu_data.init_cap;
583 FGU_DEBUG("sprdfgu_read_soc soc %d,sprdfgu_data.init_cap %d\n",
584 capcity_delta, sprdfgu_data.init_cap);
586 cur_ocv = sprdfgu_read_vbat_ocv();
587 if (cur_ocv >= sprdfgu_data.bat_full_vol) {
588 FGU_DEBUG("sprdfgu_read_soc cur_ocv %d\n", cur_ocv);
589 if (capcity_delta < 100 || capcity_delta > 102) {
591 sprdfgu_soc_adjust(100);
595 if (capcity_delta > 100) {
597 sprdfgu_soc_adjust(100);
599 if (capcity_delta <= sprdfgu_data.warning_cap
600 && cur_ocv > sprdfgu_data.pdata->alm_vol) {
601 FGU_DEBUG("sprdfgu_read_soc soc low...\n");
602 capcity_delta = sprdfgu_data.warning_cap + 1;
603 sprdfgu_soc_adjust(capcity_delta);
604 } else if (capcity_delta <= 0 && cur_ocv > sprdfgu_data.shutdown_vol) {
605 FGU_DEBUG("sprdfgu_read_soc soc 0...\n");
607 sprdfgu_soc_adjust(capcity_delta);
608 } else if (cur_ocv < sprdfgu_data.shutdown_vol) {
609 FGU_DEBUG("sprdfgu_read_soc vol 0...\n");
611 sprdfgu_soc_adjust(capcity_delta);
612 } else if (capcity_delta > sprdfgu_data.warning_cap
613 && cur_ocv < sprdfgu_data.pdata->alm_vol) {
614 FGU_DEBUG("sprdfgu_read_soc high...\n");
615 sprdfgu_soc_adjust(sprdfgu_vol2capacity(cur_ocv));
616 capcity_delta = sprdfgu_vol2capacity(cur_ocv);
619 #ifdef SPRDFGU_TEMP_COMP_SOC
621 union power_supply_propval value;
622 psy_do_property("battery", get, POWER_SUPPLY_PROP_TEMP, value);
624 sprdfgu_temp_comp_soc(capcity_delta, value.intval / 10);
628 #ifdef SPRDFGU_TEMP_COMP_SOC
629 if (sprdfgu_read_vbat_vol() < sprdfgu_data.pdata->soft_vbat_uvlo) {
630 FGU_DEBUG("TEMP_COMP_SOC vol 0...\n");
632 sprdfgu_soc_adjust(capcity_delta);
636 mutex_unlock(&sprdfgu_data.lock);
637 return capcity_delta;
641 int sprdfgu_avg_current_query(void)
643 int cur_cc, cc_delta, raw_avg, temp, curr_avg, capcity;
644 u32 cur_time = sci_syst_read();
647 cur_cc = sprdfgu_clbcnt_get();
648 time_delta = cur_time - start_time;
649 cc_delta = cur_cc - poweron_clbcnt;
650 temp = time_delta / 500;
651 raw_avg = cc_delta / temp;
653 //FGU_DEBUG("start_time:%d,cur_time : %d,poweron_clbcnt: 0x%x,cur_cc:0x%x\n",
654 // start_time, cur_time, poweron_clbcnt, cur_cc);
655 FGU_DEBUG("time_delta : %d,cc_delta: %d,raw_avg = %d\n", time_delta,
657 curr_avg = sprdfgu_adc2cur_ma(raw_avg);
659 temp = time_delta / 3600;
660 capcity = temp * curr_avg;
661 FGU_DEBUG("capcity/1000 capcity = : %dmah\n", capcity);
665 static void sprdfgu_debug_works(struct work_struct *work)
667 FGU_DEBUG("dump fgu msg s\n");
668 if (!sprdfgu_data.pdata->fgu_mode) {
669 FGU_DEBUG("avg current = %d\n", sprdfgu_avg_current_query());
671 FGU_DEBUG("vol:%d,softocv:%d,hardocv:%d,current%d,cal_type:%d\n",
672 sprdfgu_read_vbat_vol(), sprdfgu_read_vbat_ocv(),
673 sprdfgu_ocv_vol_get(), sprdfgu_cur_current_get(),
675 //FGU_DEBUG("pocv_raw = 0x%x,pocv_voltage = %d\n",
676 // sci_adi_read(REG_FGU_POCV_VAL),
677 // sprdfgu_adc2vol_mv(sci_adi_read(REG_FGU_POCV_VAL)));
678 //FGU_DEBUG("REG_FGU_CURT_OFFSET--- = %d\n",
679 //sci_adi_read(REG_FGU_CURT_OFFSET));
680 //FGU_DEBUG("REG_FGU_RELAX_CURT_THRE--- = %d\n",
681 // sci_adi_read(REG_FGU_RELAX_CURT_THRE));
682 //FGU_DEBUG("REG_FGU_RELAX_CNT--- = %d\n",
683 // sci_adi_read(REG_FGU_RELAX_CNT));
684 //FGU_DEBUG("REG_FGU_OCV_LAST_CNT--- = %d\n",
685 // sci_adi_read(REG_FGU_OCV_LAST_CNT));
686 //FGU_DEBUG("REG_FGU_LOW_OVER--- = %d\n", sci_adi_read(REG_FGU_LOW_OVER));
687 //FGU_DEBUG("REG_FGU_CONFIG--- = 0x%x\n", sci_adi_read(REG_FGU_CONFIG));
688 //printk("ANA_REG_GLB_MP_MISC_CTRL 0x%x ,0x%x \n", sci_adi_read(ANA_REG_GLB_MP_MISC_CTRL), sci_adi_read(ANA_REG_GLB_DCDC_CTRL2));
689 if (!sprdfgu_data.pdata->fgu_mode) {
690 FGU_DEBUG("soc():%d\n", sprdfgu_read_soc());
692 FGU_DEBUG("dump fgu msg e\n");
693 schedule_delayed_work(&sprdfgu_debug_work, sprdfgu_debug_log_time * HZ);
696 static void sprdfgu_cal_battery_impedance(void)
699 int delta_current_raw;
703 delta_vol_raw = sprdfgu_reg_get(REG_FGU_VOLT_VAL);
704 delta_current_raw = sprdfgu_reg_get(REG_FGU_CURT_VAL);
705 #if 0 //use pocv and poci to caculate impedance
706 cmd_vol_raw = sprdfgu_reg_get(REG_FGU_POCV_VAL);
707 cmd_cur_raw = sprdfgu_reg_get(REG_FGU_CLBCNT_QMAXL) << 1;
709 printk("sprdfgu: fgu delta_vol_raw: 0x%x delta_current_raw 0x%x!\n",
710 delta_vol_raw, delta_current_raw);
711 printk("sprdfgu: fgu cmd_vol_raw: 0x%x cmd_cur_raw 0x%x!\n",
712 cmd_vol_raw, cmd_cur_raw);
713 if (0 == cmd_vol_raw || 0 == cmd_cur_raw) {
715 "sprdfgu: sprdfgu_cal_battery_impedance warning.....!\n");
718 delta_vol_raw -= cmd_vol_raw;
719 delta_current_raw -= cmd_cur_raw;
720 delta_vol_raw = ((delta_vol_raw) * 1000) / fgu_cal.vol_1000mv_adc;
721 delta_current_raw = sprdfgu_adc2cur_ma(delta_current_raw);
722 printk("sprdfgu: delta vol delta_vol_raw: %d delta_current_raw %d!\n",
723 (delta_vol_raw), (delta_current_raw));
724 temp = (delta_vol_raw * 1000) / delta_current_raw;
726 impedance = abs(temp);
727 if (impedance > 100) {
728 sprdfgu_data.poweron_rint = impedance;
730 printk("sprdfgu: impedance warning: %d!\n", impedance);
732 printk("sprdfgu: fgu sprdfgu_data.poweron_rint: %d!\n",
733 sprdfgu_data.poweron_rint);
736 uint32_t sprdfgu_read_capacity(void)
741 if (sprdfgu_data.pdata->fgu_mode) {
742 voltage = sprdfgu_read_vbat_ocv();
743 cap = sprdfgu_vol2capacity(voltage);
745 cap = sprdfgu_read_soc();
754 uint32_t sprdfgu_poweron_capacity(void)
756 return sprdfgu_data.init_cap;
759 void sprdfgu_adp_status_set(int plugin)
761 sprdfgu_data.adp_status = plugin;
764 adc = sprdfgu_vol2adc_mv(sprdfgu_data.pdata->alm_vol);
765 sci_adi_set(REG_FGU_INT_CLR, BIT_VOLT_LOW_INT);
766 sci_adi_write(REG_FGU_LOW_OVER, adc & 0xFFFF, ~0);
767 sci_adi_clr(REG_FGU_INT_EN, BIT_CLBCNT_DELTA_INT);
771 static void sprdfgu_irq_works(struct work_struct *work)
777 wake_lock_timeout(&(sprdfgu_data.low_power_lock), 2 * HZ);
779 printk("sprdfgu: sprdfgu_irq_works......0x%x.cur vol = %d\n",
780 sprdfgu_data.int_status, sprdfgu_read_vbat_vol());
781 if (sprdfgu_data.int_status & BIT_VOLT_HIGH_INT) {
782 blocking_notifier_call_chain(&fgu_chain_head, 1, 0);
785 if (sprdfgu_data.int_status & BIT_VOLT_LOW_INT) {
786 cur_soc = sprdfgu_read_soc(); //it must be at here
787 mutex_lock(&sprdfgu_data.lock);
789 cur_ocv = sprdfgu_read_vbat_ocv();
790 if (cur_ocv <= sprdfgu_data.shutdown_vol) {
792 ("sprdfgu: sprdfgu_irq_works...sprdfgu_data.shutdown_vol .\n");
793 sprdfgu_soc_adjust(0);
794 } else if (cur_ocv <= sprdfgu_data.pdata->alm_vol) {
796 ("sprdfgu: sprdfgu_irq_works...sprdfgu_data.pdata->alm_vol %d.\n",
798 if (cur_soc > sprdfgu_data.warning_cap) {
799 sprdfgu_soc_adjust(sprdfgu_data.warning_cap);
800 } else if (cur_soc <= 0) {
801 sprdfgu_soc_adjust(sprdfgu_vol2capacity
804 if (!sprdfgu_data.adp_status) {
807 (sprdfgu_data.shutdown_vol);
808 sci_adi_write(REG_FGU_LOW_OVER, adc & 0xFFFF,
814 mutex_unlock(&sprdfgu_data.lock);
818 static irqreturn_t _sprdfgu_interrupt(int irq, void *dev_id)
820 sprdfgu_data.int_status = sci_adi_read(REG_FGU_INT_STS);
821 sci_adi_set(REG_FGU_INT_CLR, sprdfgu_data.int_status);
823 ("sprdfgu: _sprdfgu_interrupt.....raw..0x%x,sprdfgu_data.int_status0x%x\n",
824 sci_adi_read(REG_FGU_INT_RAW), sprdfgu_data.int_status);
825 schedule_delayed_work(&sprdfgu_data.fgu_irq_work, 0);
826 udelay(60); //fix int bug
830 static int sprdfgu_int_init(void)
833 int delta_cc = sprdfgu_clbcnt_init(1);
836 INIT_DELAYED_WORK(&sprdfgu_data.fgu_irq_work, sprdfgu_irq_works);
838 sci_adi_set(REG_FGU_INT_CLR, 0xFFFF);
840 adc = sprdfgu_vol2adc_mv(sprdfgu_data.pdata->chg_bat_safety_vol);
841 sci_adi_write(REG_FGU_HIGH_OVER, adc & 0xFFFF, ~0);
842 adc = sprdfgu_vol2adc_mv(sprdfgu_data.pdata->alm_vol);
843 sci_adi_write(REG_FGU_LOW_OVER, adc & 0xFFFF, ~0);
845 sci_adi_write(REG_FGU_CLBCNT_DELTL, delta_cc & 0xFFFF, ~0);
846 sci_adi_write(REG_FGU_CLBCNT_DELTH, (delta_cc >> 16) & 0xFFFF, ~0);
848 ret = request_irq(sprdfgu_data.pdata->irq_fgu, _sprdfgu_interrupt,
849 IRQF_NO_SUSPEND, "sprdfgu", NULL);
852 printk(KERN_ERR "sprdfgu: request sprdfgu irq %d failed\n",
853 sprdfgu_data.pdata->irq_fgu);
856 sci_adi_set(REG_FGU_INT_EN, BIT_VOLT_HIGH_INT);
860 void sprdfgu_pm_op(int is_suspend)
863 if (!sprdfgu_data.adp_status) {
864 sci_adi_set(REG_FGU_INT_EN, BIT_VOLT_LOW_INT);
865 if (sprdfgu_read_vbat_ocv() <
866 sprdfgu_data.pdata->alm_vol) {
867 sci_adi_set(REG_FGU_INT_CLR,
868 BIT_CLBCNT_DELTA_INT);
869 sci_adi_set(REG_FGU_INT_EN,
870 BIT_CLBCNT_DELTA_INT);
874 sci_adi_clr(REG_FGU_INT_EN,
875 BIT_VOLT_LOW_INT | BIT_CLBCNT_DELTA_INT);
878 int __weak in_calibration(void){return 0;}
879 static void sprdfgu_hw_init(void)
881 u32 cur_vol_raw, ocv_raw;
884 FGU_DEBUG("FGU_Init\n");
886 #if !defined(CONFIG_ARCH_SCX15) && !defined(CONFIG_ADIE_SC2723S) && !defined(CONFIG_ADIE_SC2723)
887 //sci_adi_set(ANA_REG_GLB_MP_MISC_CTRL, (BIT(1)));
888 //sci_adi_write(ANA_REG_GLB_DCDC_CTRL2, (4 << 8), (7 << 8));
891 sci_adi_set(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_FGU_EN);
892 sci_adi_set(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_FGU_EN | BIT_RTC_FGUA_EN);
894 #if !defined(CONFIG_ARCH_SCX15) && !defined(CONFIG_ADIE_SC2723S) && !defined(CONFIG_ADIE_SC2723)
895 sci_adi_write(REG_FGU_CONFIG, BITS_VOLT_DUTY(3), BITS_VOLT_DUTY(3) | BIT_VOLT_H_VALID); //mingwei
897 sci_adi_write(REG_FGU_RELAX_CURT_THRE, BITS_RELAX_CUR_THRE(sprdfgu_cur2adc_ma(sprdfgu_data.pdata->relax_current)), BITS_RELAX_CUR_THRE(~0)); //mingwei
899 sprdfgu_cal_battery_impedance();
900 pocv_raw = sci_adi_read(REG_FGU_POCV_VAL);
901 cur_vol_raw = sprdfgu_reg_get(REG_FGU_VOLT_VAL);
902 ocv_raw = sprdfgu_reg_get(REG_FGU_OCV_VAL);
903 current_raw = sprdfgu_reg_get(REG_FGU_CURT_VAL);
904 start_time = sci_syst_read();
906 #if defined(CONFIG_ADIE_SC2723S) ||defined(CONFIG_ADIE_SC2723)
907 FGU_DEBUG("REG_FGU_USER_AREA_STATUS- = 0x%x\n",
908 sci_adi_read(REG_FGU_USER_AREA_STATUS));
909 if ((FIRST_POWERTON == sprdfgu_poweron_type_read())
910 || (sprdfgu_rtc_reg_read() == 0xFFF) || (sprdfgu_rtc_reg_read() == 0)) {
911 FGU_DEBUG("FIRST_POWERTON- = 0x%x\n",
912 sprdfgu_poweron_type_read());
913 /*Remove battery from device when USB cable is connected, insert battery to device, battery voltage
914 is not same as it was before removal of battery.
915 SPRD patch : bug 456607
917 //#ifdef CONFIG_SPRD_EXT_IC_POWER
918 if(gpio_get_value(sprdfgu_data.pdata->gpio_vchg_detect)){
919 uint32_t soft_ocv = sprdfgu_read_vbat_vol() -
921 (current_raw - CUR_0ma_IDEA_ADC +
922 fgu_cal.cur_offset) * sprdfgu_data.poweron_rint) / 1000;
924 sprdfgu_data.init_cap = sprdfgu_vol2capacity(soft_ocv);
926 ("Charger poweron soft_ocv:%d,sprdfgu_data.init_cap:%d\n",
927 soft_ocv, sprdfgu_data.init_cap);
932 sprdfgu_reg_get(REG_FGU_CLBCNT_QMAXL) << 1;
934 sprdfgu_adc2cur_ma(poci_raw - CUR_0ma_IDEA_ADC +
937 sprdfgu_adc2vol_mv(pocv_raw) -
938 (poci_curr * sprdfgu_data.poweron_rint) / 1000;
939 sprdfgu_data.init_cap = sprdfgu_vol2capacity(p_ocv);
941 ("poci_raw:0x%x,poci_current:%d,p_softocv:%d,sprdfgu_data.init_cap:%d\n",
942 poci_raw, poci_curr, p_ocv, sprdfgu_data.init_cap);
944 sprdfgu_rtc_reg_write(sprdfgu_data.init_cap);
946 sprdfgu_data.init_cap = sprdfgu_rtc_reg_read();
947 FGU_DEBUG("NORMAIL_POWERTON-- sprdfgu_data.init_cap= %d\n",
948 sprdfgu_data.init_cap);
950 sprdfgu_poweron_type_write(NORMAIL_POWERTON);
955 while((sprdfgu_read_vbat_vol() < 3000) && --cnt){
956 FGU_DEBUG("voltage not ready = %d\n", sprdfgu_read_vbat_vol());
960 printk(KERN_EMERG "sprdfgu: voltage error!!!!");
965 uint32_t soft_ocv = sprdfgu_read_vbat_vol() -
967 (current_raw - CUR_0ma_IDEA_ADC +
968 fgu_cal.cur_offset) * sprdfgu_data.cur_rint) / 1000;
969 sprdfgu_data.init_cap = sprdfgu_vol2capacity(soft_ocv);
973 sprdfgu_data.init_clbcnt = poweron_clbcnt =
974 sprdfgu_clbcnt_init(sprdfgu_data.init_cap);
975 sprdfgu_clbcnt_set(poweron_clbcnt);
976 #if !defined(CONFIG_ADIE_SC2723S) && !defined(CONFIG_ADIE_SC2723)
977 if (!in_calibration()) {
978 sci_adi_write(REG_FGU_CURT_OFFSET, fgu_cal.cur_offset, ~0);
982 FGU_DEBUG("pocv_raw = 0x%x,pocv_voltage = %d\n", pocv_raw,
983 sprdfgu_adc2vol_mv(pocv_raw));
984 FGU_DEBUG("current voltage raw_data = 0x%x,cur voltage = %d\n",
985 cur_vol_raw, sprdfgu_adc2vol_mv(cur_vol_raw));
986 FGU_DEBUG("ocv_raw: 0x%x,ocv voltage = %d\n", ocv_raw,
987 sprdfgu_adc2vol_mv(ocv_raw));
988 FGU_DEBUG("current_raw: 0x%x,current = %d\n", current_raw,
989 sprdfgu_adc2cur_ma(current_raw - CUR_0ma_IDEA_ADC));
990 FGU_DEBUG("poweron_clbcnt: 0x%x,cur_cc0x%x\n", poweron_clbcnt,
991 sprdfgu_clbcnt_get());
992 FGU_DEBUG("sprdfgu_data.poweron_rint = %d\n", sprdfgu_data.poweron_rint);
996 int sprdfgu_register_notifier(struct notifier_block *nb)
998 return blocking_notifier_chain_register(&fgu_chain_head, nb);
1001 int sprdfgu_unregister_notifier(struct notifier_block *nb)
1003 return blocking_notifier_chain_unregister(&fgu_chain_head, nb);
1006 static ssize_t sprdfgu_store_attribute(struct device *dev,
1007 struct device_attribute *attr,
1008 const char *buf, size_t count);
1009 static ssize_t sprdfgu_show_attribute(struct device *dev,
1010 struct device_attribute *attr, char *buf);
1012 #define SPRDFGU_ATTR(_name) \
1014 .attr = { .name = #_name, .mode = S_IRUGO | S_IWUSR | S_IWGRP, }, \
1015 .show = sprdfgu_show_attribute, \
1016 .store = sprdfgu_store_attribute, \
1018 #define SPRDFGU_ATTR_RO(_name) \
1020 .attr = { .name = #_name, .mode = S_IRUGO, }, \
1021 .show = sprdfgu_show_attribute, \
1023 #define SPRDFGU_ATTR_WO(_name) \
1025 .attr = { .name = #_name, .mode = S_IWUSR | S_IWGRP, }, \
1026 .store = sprdfgu_store_attribute, \
1029 static struct device_attribute sprdfgu_attribute[] = {
1030 SPRDFGU_ATTR_RO(fgu_vol_adc),
1031 SPRDFGU_ATTR_RO(fgu_current_adc),
1032 SPRDFGU_ATTR_RO(fgu_vol),
1033 SPRDFGU_ATTR_RO(fgu_current),
1034 SPRDFGU_ATTR_WO(fgu_log_time),
1035 SPRDFGU_ATTR_RO(fgu_cal_from_type),
1038 enum SPRDFGU_ATTRIBUTE {
1047 static ssize_t sprdfgu_store_attribute(struct device *dev,
1048 struct device_attribute *attr,
1049 const char *buf, size_t count)
1051 unsigned long set_value;
1052 const ptrdiff_t off = attr - sprdfgu_attribute;
1054 set_value = simple_strtoul(buf, NULL, 10);
1055 pr_info("sprdfgu_store_attribute %lu %lu\n", off, set_value);
1059 sprdfgu_debug_log_time = set_value;
1068 static ssize_t sprdfgu_show_attribute(struct device *dev,
1069 struct device_attribute *attr, char *buf)
1072 const ptrdiff_t off = attr - sprdfgu_attribute;
1076 i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
1077 sci_adi_read(REG_FGU_VOLT_VAL));
1079 case FGU_CURRENT_ADC:
1080 i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
1081 sci_adi_read(REG_FGU_CURT_VAL));
1084 i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
1085 sprdfgu_read_vbat_vol());
1088 i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
1089 sprdfgu_read_batcurrent());
1091 case FGU_CAL_FROM_TYPE:
1092 i += scnprintf(buf + i, PAGE_SIZE - i, "%d\n",
1104 static int sprdfgu_creat_attr(struct device *dev)
1108 for (i = 0; i < ARRAY_SIZE(sprdfgu_attribute); i++) {
1109 rc = device_create_file(dev, &sprdfgu_attribute[i]);
1111 goto sprd_attrs_failed;
1113 goto sprd_attrs_succeed;
1117 device_remove_file(dev, &sprdfgu_attribute[i]);
1123 static int sprdfgu_power_get_property(struct power_supply *psy,
1124 enum power_supply_property psp,
1125 union power_supply_propval *val)
1130 int sprdfgu_init(struct sprd_battery_platform_data *pdata)
1134 //struct sprdbat_drivier_data *data = platform_get_drvdata(pdev);
1136 sprdfgu_data.pdata = pdata;
1137 sprdfgu_data.warning_cap =
1138 sprdfgu_vol2capacity(sprdfgu_data.pdata->alm_vol);
1139 temp = sprdfgu_data.pdata->ocv_tab_size;
1140 sprdfgu_data.shutdown_vol = sprdfgu_data.pdata->ocv_tab[temp - 1].x;
1142 sprdfgu_data.bat_full_vol = sprdfgu_data.pdata->ocv_tab[0].x;
1143 sprdfgu_data.cur_rint = sprdfgu_data.pdata->rint;
1144 sprdfgu_data.poweron_rint = sprdfgu_data.pdata->rint;
1146 /*Remove battery from device when USB cable is connected, insert battery to device, battery voltage
1147 is not same as it was before revomal of battery.
1148 SPRD patch : bug 456607
1150 //#ifdef CONFIG_SPRD_EXT_IC_POWER
1151 ret = gpio_request(sprdfgu_data.pdata->gpio_vchg_detect, "chg_vchg_detect");
1153 FGU_DEBUG("Already request vchg gpio:%d\n",sprdfgu_data.pdata->gpio_vchg_detect);
1155 gpio_direction_input(sprdfgu_data.pdata->gpio_vchg_detect);
1158 if (fgu_cal.cal_type == SPRDBAT_FGUADC_CAL_NO) {
1159 sprdfgu_cal_from_chip(); //try to find cal data from efuse
1164 sprdfgu_data.sprdfgu.name = "sprdfgu";
1165 sprdfgu_data.sprdfgu.get_property = sprdfgu_power_get_property;
1166 ret = power_supply_register(NULL, &sprdfgu_data.sprdfgu);
1168 pr_err("register power supply error!\n");
1171 sprdfgu_creat_attr(sprdfgu_data.sprdfgu.dev);
1173 INIT_DELAYED_WORK(&sprdfgu_debug_work, sprdfgu_debug_works);
1174 mutex_init(&sprdfgu_data.lock);
1175 wake_lock_init(&(sprdfgu_data.low_power_lock), WAKE_LOCK_SUSPEND,
1176 "sprdfgu_powerlow_lock");
1178 schedule_delayed_work(&sprdfgu_debug_work, sprdfgu_debug_log_time * HZ);
1179 FGU_DEBUG("sprdfgu_init end\n");
1183 int sprdfgu_reset(void)
1185 start_time = sci_syst_read();
1186 sprdfgu_data.init_cap = sprdfgu_vol2capacity(sprdfgu_read_vbat_ocv());
1187 #if defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
1188 sprdfgu_rtc_reg_write(sprdfgu_data.init_cap);
1190 sprdfgu_data.init_clbcnt = poweron_clbcnt =
1191 sprdfgu_clbcnt_init(sprdfgu_data.init_cap);
1192 sprdfgu_clbcnt_set(poweron_clbcnt);
1197 void sprdfgu_record_cap(u32 cap)
1199 #if defined(CONFIG_ADIE_SC2723S) || defined(CONFIG_ADIE_SC2723)
1200 sprdfgu_rtc_reg_write(cap);