Version:  2.0.40 2.2.26 2.4.37 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1

Linux/drivers/power/bq24190_charger.c

  1 /*
  2  * Driver for the TI bq24190 battery charger.
  3  *
  4  * Author: Mark A. Greer <mgreer@animalcreek.com>
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License version 2 as
  8  * published by the Free Software Foundation.
  9  */
 10 
 11 #include <linux/module.h>
 12 #include <linux/interrupt.h>
 13 #include <linux/delay.h>
 14 #include <linux/of_irq.h>
 15 #include <linux/of_device.h>
 16 #include <linux/pm_runtime.h>
 17 #include <linux/power_supply.h>
 18 #include <linux/gpio.h>
 19 #include <linux/i2c.h>
 20 
 21 #include <linux/power/bq24190_charger.h>
 22 
 23 
 24 #define BQ24190_MANUFACTURER    "Texas Instruments"
 25 
 26 #define BQ24190_REG_ISC         0x00 /* Input Source Control */
 27 #define BQ24190_REG_ISC_EN_HIZ_MASK             BIT(7)
 28 #define BQ24190_REG_ISC_EN_HIZ_SHIFT            7
 29 #define BQ24190_REG_ISC_VINDPM_MASK             (BIT(6) | BIT(5) | BIT(4) | \
 30                                                  BIT(3))
 31 #define BQ24190_REG_ISC_VINDPM_SHIFT            3
 32 #define BQ24190_REG_ISC_IINLIM_MASK             (BIT(2) | BIT(1) | BIT(0))
 33 #define BQ24190_REG_ISC_IINLIM_SHIFT            0
 34 
 35 #define BQ24190_REG_POC         0x01 /* Power-On Configuration */
 36 #define BQ24190_REG_POC_RESET_MASK              BIT(7)
 37 #define BQ24190_REG_POC_RESET_SHIFT             7
 38 #define BQ24190_REG_POC_WDT_RESET_MASK          BIT(6)
 39 #define BQ24190_REG_POC_WDT_RESET_SHIFT         6
 40 #define BQ24190_REG_POC_CHG_CONFIG_MASK         (BIT(5) | BIT(4))
 41 #define BQ24190_REG_POC_CHG_CONFIG_SHIFT        4
 42 #define BQ24190_REG_POC_SYS_MIN_MASK            (BIT(3) | BIT(2) | BIT(1))
 43 #define BQ24190_REG_POC_SYS_MIN_SHIFT           1
 44 #define BQ24190_REG_POC_BOOST_LIM_MASK          BIT(0)
 45 #define BQ24190_REG_POC_BOOST_LIM_SHIFT         0
 46 
 47 #define BQ24190_REG_CCC         0x02 /* Charge Current Control */
 48 #define BQ24190_REG_CCC_ICHG_MASK               (BIT(7) | BIT(6) | BIT(5) | \
 49                                                  BIT(4) | BIT(3) | BIT(2))
 50 #define BQ24190_REG_CCC_ICHG_SHIFT              2
 51 #define BQ24190_REG_CCC_FORCE_20PCT_MASK        BIT(0)
 52 #define BQ24190_REG_CCC_FORCE_20PCT_SHIFT       0
 53 
 54 #define BQ24190_REG_PCTCC       0x03 /* Pre-charge/Termination Current Cntl */
 55 #define BQ24190_REG_PCTCC_IPRECHG_MASK          (BIT(7) | BIT(6) | BIT(5) | \
 56                                                  BIT(4))
 57 #define BQ24190_REG_PCTCC_IPRECHG_SHIFT         4
 58 #define BQ24190_REG_PCTCC_ITERM_MASK            (BIT(3) | BIT(2) | BIT(1) | \
 59                                                  BIT(0))
 60 #define BQ24190_REG_PCTCC_ITERM_SHIFT           0
 61 
 62 #define BQ24190_REG_CVC         0x04 /* Charge Voltage Control */
 63 #define BQ24190_REG_CVC_VREG_MASK               (BIT(7) | BIT(6) | BIT(5) | \
 64                                                  BIT(4) | BIT(3) | BIT(2))
 65 #define BQ24190_REG_CVC_VREG_SHIFT              2
 66 #define BQ24190_REG_CVC_BATLOWV_MASK            BIT(1)
 67 #define BQ24190_REG_CVC_BATLOWV_SHIFT           1
 68 #define BQ24190_REG_CVC_VRECHG_MASK             BIT(0)
 69 #define BQ24190_REG_CVC_VRECHG_SHIFT            0
 70 
 71 #define BQ24190_REG_CTTC        0x05 /* Charge Term/Timer Control */
 72 #define BQ24190_REG_CTTC_EN_TERM_MASK           BIT(7)
 73 #define BQ24190_REG_CTTC_EN_TERM_SHIFT          7
 74 #define BQ24190_REG_CTTC_TERM_STAT_MASK         BIT(6)
 75 #define BQ24190_REG_CTTC_TERM_STAT_SHIFT        6
 76 #define BQ24190_REG_CTTC_WATCHDOG_MASK          (BIT(5) | BIT(4))
 77 #define BQ24190_REG_CTTC_WATCHDOG_SHIFT         4
 78 #define BQ24190_REG_CTTC_EN_TIMER_MASK          BIT(3)
 79 #define BQ24190_REG_CTTC_EN_TIMER_SHIFT         3
 80 #define BQ24190_REG_CTTC_CHG_TIMER_MASK         (BIT(2) | BIT(1))
 81 #define BQ24190_REG_CTTC_CHG_TIMER_SHIFT        1
 82 #define BQ24190_REG_CTTC_JEITA_ISET_MASK        BIT(0)
 83 #define BQ24190_REG_CTTC_JEITA_ISET_SHIFT       0
 84 
 85 #define BQ24190_REG_ICTRC       0x06 /* IR Comp/Thermal Regulation Control */
 86 #define BQ24190_REG_ICTRC_BAT_COMP_MASK         (BIT(7) | BIT(6) | BIT(5))
 87 #define BQ24190_REG_ICTRC_BAT_COMP_SHIFT        5
 88 #define BQ24190_REG_ICTRC_VCLAMP_MASK           (BIT(4) | BIT(3) | BIT(2))
 89 #define BQ24190_REG_ICTRC_VCLAMP_SHIFT          2
 90 #define BQ24190_REG_ICTRC_TREG_MASK             (BIT(1) | BIT(0))
 91 #define BQ24190_REG_ICTRC_TREG_SHIFT            0
 92 
 93 #define BQ24190_REG_MOC         0x07 /* Misc. Operation Control */
 94 #define BQ24190_REG_MOC_DPDM_EN_MASK            BIT(7)
 95 #define BQ24190_REG_MOC_DPDM_EN_SHIFT           7
 96 #define BQ24190_REG_MOC_TMR2X_EN_MASK           BIT(6)
 97 #define BQ24190_REG_MOC_TMR2X_EN_SHIFT          6
 98 #define BQ24190_REG_MOC_BATFET_DISABLE_MASK     BIT(5)
 99 #define BQ24190_REG_MOC_BATFET_DISABLE_SHIFT    5
100 #define BQ24190_REG_MOC_JEITA_VSET_MASK         BIT(4)
101 #define BQ24190_REG_MOC_JEITA_VSET_SHIFT        4
102 #define BQ24190_REG_MOC_INT_MASK_MASK           (BIT(1) | BIT(0))
103 #define BQ24190_REG_MOC_INT_MASK_SHIFT          0
104 
105 #define BQ24190_REG_SS          0x08 /* System Status */
106 #define BQ24190_REG_SS_VBUS_STAT_MASK           (BIT(7) | BIT(6))
107 #define BQ24190_REG_SS_VBUS_STAT_SHIFT          6
108 #define BQ24190_REG_SS_CHRG_STAT_MASK           (BIT(5) | BIT(4))
109 #define BQ24190_REG_SS_CHRG_STAT_SHIFT          4
110 #define BQ24190_REG_SS_DPM_STAT_MASK            BIT(3)
111 #define BQ24190_REG_SS_DPM_STAT_SHIFT           3
112 #define BQ24190_REG_SS_PG_STAT_MASK             BIT(2)
113 #define BQ24190_REG_SS_PG_STAT_SHIFT            2
114 #define BQ24190_REG_SS_THERM_STAT_MASK          BIT(1)
115 #define BQ24190_REG_SS_THERM_STAT_SHIFT         1
116 #define BQ24190_REG_SS_VSYS_STAT_MASK           BIT(0)
117 #define BQ24190_REG_SS_VSYS_STAT_SHIFT          0
118 
119 #define BQ24190_REG_F           0x09 /* Fault */
120 #define BQ24190_REG_F_WATCHDOG_FAULT_MASK       BIT(7)
121 #define BQ24190_REG_F_WATCHDOG_FAULT_SHIFT      7
122 #define BQ24190_REG_F_BOOST_FAULT_MASK          BIT(6)
123 #define BQ24190_REG_F_BOOST_FAULT_SHIFT         6
124 #define BQ24190_REG_F_CHRG_FAULT_MASK           (BIT(5) | BIT(4))
125 #define BQ24190_REG_F_CHRG_FAULT_SHIFT          4
126 #define BQ24190_REG_F_BAT_FAULT_MASK            BIT(3)
127 #define BQ24190_REG_F_BAT_FAULT_SHIFT           3
128 #define BQ24190_REG_F_NTC_FAULT_MASK            (BIT(2) | BIT(1) | BIT(0))
129 #define BQ24190_REG_F_NTC_FAULT_SHIFT           0
130 
131 #define BQ24190_REG_VPRS        0x0A /* Vendor/Part/Revision Status */
132 #define BQ24190_REG_VPRS_PN_MASK                (BIT(5) | BIT(4) | BIT(3))
133 #define BQ24190_REG_VPRS_PN_SHIFT               3
134 #define BQ24190_REG_VPRS_PN_24190                       0x4
135 #define BQ24190_REG_VPRS_PN_24192                       0x5 /* Also 24193 */
136 #define BQ24190_REG_VPRS_PN_24192I                      0x3
137 #define BQ24190_REG_VPRS_TS_PROFILE_MASK        BIT(2)
138 #define BQ24190_REG_VPRS_TS_PROFILE_SHIFT       2
139 #define BQ24190_REG_VPRS_DEV_REG_MASK           (BIT(1) | BIT(0))
140 #define BQ24190_REG_VPRS_DEV_REG_SHIFT          0
141 
142 /*
143  * The FAULT register is latched by the bq24190 (except for NTC_FAULT)
144  * so the first read after a fault returns the latched value and subsequent
145  * reads return the current value.  In order to return the fault status
146  * to the user, have the interrupt handler save the reg's value and retrieve
147  * it in the appropriate health/status routine.  Each routine has its own
148  * flag indicating whether it should use the value stored by the last run
149  * of the interrupt handler or do an actual reg read.  That way each routine
150  * can report back whatever fault may have occured.
151  */
152 struct bq24190_dev_info {
153         struct i2c_client               *client;
154         struct device                   *dev;
155         struct power_supply             *charger;
156         struct power_supply             *battery;
157         char                            model_name[I2C_NAME_SIZE];
158         kernel_ulong_t                  model;
159         unsigned int                    gpio_int;
160         unsigned int                    irq;
161         struct mutex                    f_reg_lock;
162         bool                            first_time;
163         bool                            charger_health_valid;
164         bool                            battery_health_valid;
165         bool                            battery_status_valid;
166         u8                              f_reg;
167         u8                              ss_reg;
168         u8                              watchdog;
169 };
170 
171 /*
172  * The tables below provide a 2-way mapping for the value that goes in
173  * the register field and the real-world value that it represents.
174  * The index of the array is the value that goes in the register; the
175  * number at that index in the array is the real-world value that it
176  * represents.
177  */
178 /* REG02[7:2] (ICHG) in uAh */
179 static const int bq24190_ccc_ichg_values[] = {
180          512000,  576000,  640000,  704000,  768000,  832000,  896000,  960000,
181         1024000, 1088000, 1152000, 1216000, 1280000, 1344000, 1408000, 1472000,
182         1536000, 1600000, 1664000, 1728000, 1792000, 1856000, 1920000, 1984000,
183         2048000, 2112000, 2176000, 2240000, 2304000, 2368000, 2432000, 2496000,
184         2560000, 2624000, 2688000, 2752000, 2816000, 2880000, 2944000, 3008000,
185         3072000, 3136000, 3200000, 3264000, 3328000, 3392000, 3456000, 3520000,
186         3584000, 3648000, 3712000, 3776000, 3840000, 3904000, 3968000, 4032000,
187         4096000, 4160000, 4224000, 4288000, 4352000, 4416000, 4480000, 4544000
188 };
189 
190 /* REG04[7:2] (VREG) in uV */
191 static const int bq24190_cvc_vreg_values[] = {
192         3504000, 3520000, 3536000, 3552000, 3568000, 3584000, 3600000, 3616000,
193         3632000, 3648000, 3664000, 3680000, 3696000, 3712000, 3728000, 3744000,
194         3760000, 3776000, 3792000, 3808000, 3824000, 3840000, 3856000, 3872000,
195         3888000, 3904000, 3920000, 3936000, 3952000, 3968000, 3984000, 4000000,
196         4016000, 4032000, 4048000, 4064000, 4080000, 4096000, 4112000, 4128000,
197         4144000, 4160000, 4176000, 4192000, 4208000, 4224000, 4240000, 4256000,
198         4272000, 4288000, 4304000, 4320000, 4336000, 4352000, 4368000, 4384000,
199         4400000
200 };
201 
202 /* REG06[1:0] (TREG) in tenths of degrees Celcius */
203 static const int bq24190_ictrc_treg_values[] = {
204         600, 800, 1000, 1200
205 };
206 
207 /*
208  * Return the index in 'tbl' of greatest value that is less than or equal to
209  * 'val'.  The index range returned is 0 to 'tbl_size' - 1.  Assumes that
210  * the values in 'tbl' are sorted from smallest to largest and 'tbl_size'
211  * is less than 2^8.
212  */
213 static u8 bq24190_find_idx(const int tbl[], int tbl_size, int v)
214 {
215         int i;
216 
217         for (i = 1; i < tbl_size; i++)
218                 if (v < tbl[i])
219                         break;
220 
221         return i - 1;
222 }
223 
224 /* Basic driver I/O routines */
225 
226 static int bq24190_read(struct bq24190_dev_info *bdi, u8 reg, u8 *data)
227 {
228         int ret;
229 
230         ret = i2c_smbus_read_byte_data(bdi->client, reg);
231         if (ret < 0)
232                 return ret;
233 
234         *data = ret;
235         return 0;
236 }
237 
238 static int bq24190_write(struct bq24190_dev_info *bdi, u8 reg, u8 data)
239 {
240         return i2c_smbus_write_byte_data(bdi->client, reg, data);
241 }
242 
243 static int bq24190_read_mask(struct bq24190_dev_info *bdi, u8 reg,
244                 u8 mask, u8 shift, u8 *data)
245 {
246         u8 v;
247         int ret;
248 
249         ret = bq24190_read(bdi, reg, &v);
250         if (ret < 0)
251                 return ret;
252 
253         v &= mask;
254         v >>= shift;
255         *data = v;
256 
257         return 0;
258 }
259 
260 static int bq24190_write_mask(struct bq24190_dev_info *bdi, u8 reg,
261                 u8 mask, u8 shift, u8 data)
262 {
263         u8 v;
264         int ret;
265 
266         ret = bq24190_read(bdi, reg, &v);
267         if (ret < 0)
268                 return ret;
269 
270         v &= ~mask;
271         v |= ((data << shift) & mask);
272 
273         return bq24190_write(bdi, reg, v);
274 }
275 
276 static int bq24190_get_field_val(struct bq24190_dev_info *bdi,
277                 u8 reg, u8 mask, u8 shift,
278                 const int tbl[], int tbl_size,
279                 int *val)
280 {
281         u8 v;
282         int ret;
283 
284         ret = bq24190_read_mask(bdi, reg, mask, shift, &v);
285         if (ret < 0)
286                 return ret;
287 
288         v = (v >= tbl_size) ? (tbl_size - 1) : v;
289         *val = tbl[v];
290 
291         return 0;
292 }
293 
294 static int bq24190_set_field_val(struct bq24190_dev_info *bdi,
295                 u8 reg, u8 mask, u8 shift,
296                 const int tbl[], int tbl_size,
297                 int val)
298 {
299         u8 idx;
300 
301         idx = bq24190_find_idx(tbl, tbl_size, val);
302 
303         return bq24190_write_mask(bdi, reg, mask, shift, idx);
304 }
305 
306 #ifdef CONFIG_SYSFS
307 /*
308  * There are a numerous options that are configurable on the bq24190
309  * that go well beyond what the power_supply properties provide access to.
310  * Provide sysfs access to them so they can be examined and possibly modified
311  * on the fly.  They will be provided for the charger power_supply object only
312  * and will be prefixed by 'f_' to make them easier to recognize.
313  */
314 
315 #define BQ24190_SYSFS_FIELD(_name, r, f, m, store)                      \
316 {                                                                       \
317         .attr   = __ATTR(f_##_name, m, bq24190_sysfs_show, store),      \
318         .reg    = BQ24190_REG_##r,                                      \
319         .mask   = BQ24190_REG_##r##_##f##_MASK,                         \
320         .shift  = BQ24190_REG_##r##_##f##_SHIFT,                        \
321 }
322 
323 #define BQ24190_SYSFS_FIELD_RW(_name, r, f)                             \
324                 BQ24190_SYSFS_FIELD(_name, r, f, S_IWUSR | S_IRUGO,     \
325                                 bq24190_sysfs_store)
326 
327 #define BQ24190_SYSFS_FIELD_RO(_name, r, f)                             \
328                 BQ24190_SYSFS_FIELD(_name, r, f, S_IRUGO, NULL)
329 
330 static ssize_t bq24190_sysfs_show(struct device *dev,
331                 struct device_attribute *attr, char *buf);
332 static ssize_t bq24190_sysfs_store(struct device *dev,
333                 struct device_attribute *attr, const char *buf, size_t count);
334 
335 struct bq24190_sysfs_field_info {
336         struct device_attribute attr;
337         u8      reg;
338         u8      mask;
339         u8      shift;
340 };
341 
342 /* On i386 ptrace-abi.h defines SS that breaks the macro calls below. */
343 #undef SS
344 
345 static struct bq24190_sysfs_field_info bq24190_sysfs_field_tbl[] = {
346                         /*      sysfs name      reg     field in reg */
347         BQ24190_SYSFS_FIELD_RW(en_hiz,          ISC,    EN_HIZ),
348         BQ24190_SYSFS_FIELD_RW(vindpm,          ISC,    VINDPM),
349         BQ24190_SYSFS_FIELD_RW(iinlim,          ISC,    IINLIM),
350         BQ24190_SYSFS_FIELD_RW(chg_config,      POC,    CHG_CONFIG),
351         BQ24190_SYSFS_FIELD_RW(sys_min,         POC,    SYS_MIN),
352         BQ24190_SYSFS_FIELD_RW(boost_lim,       POC,    BOOST_LIM),
353         BQ24190_SYSFS_FIELD_RW(ichg,            CCC,    ICHG),
354         BQ24190_SYSFS_FIELD_RW(force_20_pct,    CCC,    FORCE_20PCT),
355         BQ24190_SYSFS_FIELD_RW(iprechg,         PCTCC,  IPRECHG),
356         BQ24190_SYSFS_FIELD_RW(iterm,           PCTCC,  ITERM),
357         BQ24190_SYSFS_FIELD_RW(vreg,            CVC,    VREG),
358         BQ24190_SYSFS_FIELD_RW(batlowv,         CVC,    BATLOWV),
359         BQ24190_SYSFS_FIELD_RW(vrechg,          CVC,    VRECHG),
360         BQ24190_SYSFS_FIELD_RW(en_term,         CTTC,   EN_TERM),
361         BQ24190_SYSFS_FIELD_RW(term_stat,       CTTC,   TERM_STAT),
362         BQ24190_SYSFS_FIELD_RO(watchdog,        CTTC,   WATCHDOG),
363         BQ24190_SYSFS_FIELD_RW(en_timer,        CTTC,   EN_TIMER),
364         BQ24190_SYSFS_FIELD_RW(chg_timer,       CTTC,   CHG_TIMER),
365         BQ24190_SYSFS_FIELD_RW(jeta_iset,       CTTC,   JEITA_ISET),
366         BQ24190_SYSFS_FIELD_RW(bat_comp,        ICTRC,  BAT_COMP),
367         BQ24190_SYSFS_FIELD_RW(vclamp,          ICTRC,  VCLAMP),
368         BQ24190_SYSFS_FIELD_RW(treg,            ICTRC,  TREG),
369         BQ24190_SYSFS_FIELD_RW(dpdm_en,         MOC,    DPDM_EN),
370         BQ24190_SYSFS_FIELD_RW(tmr2x_en,        MOC,    TMR2X_EN),
371         BQ24190_SYSFS_FIELD_RW(batfet_disable,  MOC,    BATFET_DISABLE),
372         BQ24190_SYSFS_FIELD_RW(jeita_vset,      MOC,    JEITA_VSET),
373         BQ24190_SYSFS_FIELD_RO(int_mask,        MOC,    INT_MASK),
374         BQ24190_SYSFS_FIELD_RO(vbus_stat,       SS,     VBUS_STAT),
375         BQ24190_SYSFS_FIELD_RO(chrg_stat,       SS,     CHRG_STAT),
376         BQ24190_SYSFS_FIELD_RO(dpm_stat,        SS,     DPM_STAT),
377         BQ24190_SYSFS_FIELD_RO(pg_stat,         SS,     PG_STAT),
378         BQ24190_SYSFS_FIELD_RO(therm_stat,      SS,     THERM_STAT),
379         BQ24190_SYSFS_FIELD_RO(vsys_stat,       SS,     VSYS_STAT),
380         BQ24190_SYSFS_FIELD_RO(watchdog_fault,  F,      WATCHDOG_FAULT),
381         BQ24190_SYSFS_FIELD_RO(boost_fault,     F,      BOOST_FAULT),
382         BQ24190_SYSFS_FIELD_RO(chrg_fault,      F,      CHRG_FAULT),
383         BQ24190_SYSFS_FIELD_RO(bat_fault,       F,      BAT_FAULT),
384         BQ24190_SYSFS_FIELD_RO(ntc_fault,       F,      NTC_FAULT),
385         BQ24190_SYSFS_FIELD_RO(pn,              VPRS,   PN),
386         BQ24190_SYSFS_FIELD_RO(ts_profile,      VPRS,   TS_PROFILE),
387         BQ24190_SYSFS_FIELD_RO(dev_reg,         VPRS,   DEV_REG),
388 };
389 
390 static struct attribute *
391         bq24190_sysfs_attrs[ARRAY_SIZE(bq24190_sysfs_field_tbl) + 1];
392 
393 static const struct attribute_group bq24190_sysfs_attr_group = {
394         .attrs = bq24190_sysfs_attrs,
395 };
396 
397 static void bq24190_sysfs_init_attrs(void)
398 {
399         int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
400 
401         for (i = 0; i < limit; i++)
402                 bq24190_sysfs_attrs[i] = &bq24190_sysfs_field_tbl[i].attr.attr;
403 
404         bq24190_sysfs_attrs[limit] = NULL; /* Has additional entry for this */
405 }
406 
407 static struct bq24190_sysfs_field_info *bq24190_sysfs_field_lookup(
408                 const char *name)
409 {
410         int i, limit = ARRAY_SIZE(bq24190_sysfs_field_tbl);
411 
412         for (i = 0; i < limit; i++)
413                 if (!strcmp(name, bq24190_sysfs_field_tbl[i].attr.attr.name))
414                         break;
415 
416         if (i >= limit)
417                 return NULL;
418 
419         return &bq24190_sysfs_field_tbl[i];
420 }
421 
422 static ssize_t bq24190_sysfs_show(struct device *dev,
423                 struct device_attribute *attr, char *buf)
424 {
425         struct power_supply *psy = dev_get_drvdata(dev);
426         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
427         struct bq24190_sysfs_field_info *info;
428         int ret;
429         u8 v;
430 
431         info = bq24190_sysfs_field_lookup(attr->attr.name);
432         if (!info)
433                 return -EINVAL;
434 
435         ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
436         if (ret)
437                 return ret;
438 
439         return scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
440 }
441 
442 static ssize_t bq24190_sysfs_store(struct device *dev,
443                 struct device_attribute *attr, const char *buf, size_t count)
444 {
445         struct power_supply *psy = dev_get_drvdata(dev);
446         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
447         struct bq24190_sysfs_field_info *info;
448         int ret;
449         u8 v;
450 
451         info = bq24190_sysfs_field_lookup(attr->attr.name);
452         if (!info)
453                 return -EINVAL;
454 
455         ret = kstrtou8(buf, 0, &v);
456         if (ret < 0)
457                 return ret;
458 
459         ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
460         if (ret)
461                 return ret;
462 
463         return count;
464 }
465 
466 static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
467 {
468         bq24190_sysfs_init_attrs();
469 
470         return sysfs_create_group(&bdi->charger->dev.kobj,
471                         &bq24190_sysfs_attr_group);
472 }
473 
474 static void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi)
475 {
476         sysfs_remove_group(&bdi->charger->dev.kobj, &bq24190_sysfs_attr_group);
477 }
478 #else
479 static int bq24190_sysfs_create_group(struct bq24190_dev_info *bdi)
480 {
481         return 0;
482 }
483 
484 static inline void bq24190_sysfs_remove_group(struct bq24190_dev_info *bdi) {}
485 #endif
486 
487 /*
488  * According to the "Host Mode and default Mode" section of the
489  * manual, a write to any register causes the bq24190 to switch
490  * from default mode to host mode.  It will switch back to default
491  * mode after a WDT timeout unless the WDT is turned off as well.
492  * So, by simply turning off the WDT, we accomplish both with the
493  * same write.
494  */
495 static int bq24190_set_mode_host(struct bq24190_dev_info *bdi)
496 {
497         int ret;
498         u8 v;
499 
500         ret = bq24190_read(bdi, BQ24190_REG_CTTC, &v);
501         if (ret < 0)
502                 return ret;
503 
504         bdi->watchdog = ((v & BQ24190_REG_CTTC_WATCHDOG_MASK) >>
505                                         BQ24190_REG_CTTC_WATCHDOG_SHIFT);
506         v &= ~BQ24190_REG_CTTC_WATCHDOG_MASK;
507 
508         return bq24190_write(bdi, BQ24190_REG_CTTC, v);
509 }
510 
511 static int bq24190_register_reset(struct bq24190_dev_info *bdi)
512 {
513         int ret, limit = 100;
514         u8 v;
515 
516         /* Reset the registers */
517         ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
518                         BQ24190_REG_POC_RESET_MASK,
519                         BQ24190_REG_POC_RESET_SHIFT,
520                         0x1);
521         if (ret < 0)
522                 return ret;
523 
524         /* Reset bit will be cleared by hardware so poll until it is */
525         do {
526                 ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
527                                 BQ24190_REG_POC_RESET_MASK,
528                                 BQ24190_REG_POC_RESET_SHIFT,
529                                 &v);
530                 if (ret < 0)
531                         return ret;
532 
533                 if (!v)
534                         break;
535 
536                 udelay(10);
537         } while (--limit);
538 
539         if (!limit)
540                 return -EIO;
541 
542         return 0;
543 }
544 
545 /* Charger power supply property routines */
546 
547 static int bq24190_charger_get_charge_type(struct bq24190_dev_info *bdi,
548                 union power_supply_propval *val)
549 {
550         u8 v;
551         int type, ret;
552 
553         ret = bq24190_read_mask(bdi, BQ24190_REG_POC,
554                         BQ24190_REG_POC_CHG_CONFIG_MASK,
555                         BQ24190_REG_POC_CHG_CONFIG_SHIFT,
556                         &v);
557         if (ret < 0)
558                 return ret;
559 
560         /* If POC[CHG_CONFIG] (REG01[5:4]) == 0, charge is disabled */
561         if (!v) {
562                 type = POWER_SUPPLY_CHARGE_TYPE_NONE;
563         } else {
564                 ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
565                                 BQ24190_REG_CCC_FORCE_20PCT_MASK,
566                                 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
567                                 &v);
568                 if (ret < 0)
569                         return ret;
570 
571                 type = (v) ? POWER_SUPPLY_CHARGE_TYPE_TRICKLE :
572                              POWER_SUPPLY_CHARGE_TYPE_FAST;
573         }
574 
575         val->intval = type;
576 
577         return 0;
578 }
579 
580 static int bq24190_charger_set_charge_type(struct bq24190_dev_info *bdi,
581                 const union power_supply_propval *val)
582 {
583         u8 chg_config, force_20pct, en_term;
584         int ret;
585 
586         /*
587          * According to the "Termination when REG02[0] = 1" section of
588          * the bq24190 manual, the trickle charge could be less than the
589          * termination current so it recommends turning off the termination
590          * function.
591          *
592          * Note: AFAICT from the datasheet, the user will have to manually
593          * turn off the charging when in 20% mode.  If its not turned off,
594          * there could be battery damage.  So, use this mode at your own risk.
595          */
596         switch (val->intval) {
597         case POWER_SUPPLY_CHARGE_TYPE_NONE:
598                 chg_config = 0x0;
599                 break;
600         case POWER_SUPPLY_CHARGE_TYPE_TRICKLE:
601                 chg_config = 0x1;
602                 force_20pct = 0x1;
603                 en_term = 0x0;
604                 break;
605         case POWER_SUPPLY_CHARGE_TYPE_FAST:
606                 chg_config = 0x1;
607                 force_20pct = 0x0;
608                 en_term = 0x1;
609                 break;
610         default:
611                 return -EINVAL;
612         }
613 
614         if (chg_config) { /* Enabling the charger */
615                 ret = bq24190_write_mask(bdi, BQ24190_REG_CCC,
616                                 BQ24190_REG_CCC_FORCE_20PCT_MASK,
617                                 BQ24190_REG_CCC_FORCE_20PCT_SHIFT,
618                                 force_20pct);
619                 if (ret < 0)
620                         return ret;
621 
622                 ret = bq24190_write_mask(bdi, BQ24190_REG_CTTC,
623                                 BQ24190_REG_CTTC_EN_TERM_MASK,
624                                 BQ24190_REG_CTTC_EN_TERM_SHIFT,
625                                 en_term);
626                 if (ret < 0)
627                         return ret;
628         }
629 
630         return bq24190_write_mask(bdi, BQ24190_REG_POC,
631                         BQ24190_REG_POC_CHG_CONFIG_MASK,
632                         BQ24190_REG_POC_CHG_CONFIG_SHIFT, chg_config);
633 }
634 
635 static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
636                 union power_supply_propval *val)
637 {
638         u8 v;
639         int health, ret;
640 
641         mutex_lock(&bdi->f_reg_lock);
642 
643         if (bdi->charger_health_valid) {
644                 v = bdi->f_reg;
645                 bdi->charger_health_valid = false;
646                 mutex_unlock(&bdi->f_reg_lock);
647         } else {
648                 mutex_unlock(&bdi->f_reg_lock);
649 
650                 ret = bq24190_read(bdi, BQ24190_REG_F, &v);
651                 if (ret < 0)
652                         return ret;
653         }
654 
655         if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
656                 /*
657                  * This could be over-current or over-voltage but there's
658                  * no way to tell which.  Return 'OVERVOLTAGE' since there
659                  * isn't an 'OVERCURRENT' value defined that we can return
660                  * even if it was over-current.
661                  */
662                 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
663         } else {
664                 v &= BQ24190_REG_F_CHRG_FAULT_MASK;
665                 v >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
666 
667                 switch (v) {
668                 case 0x0: /* Normal */
669                         health = POWER_SUPPLY_HEALTH_GOOD;
670                         break;
671                 case 0x1: /* Input Fault (VBUS OVP or VBAT<VBUS<3.8V) */
672                         /*
673                          * This could be over-voltage or under-voltage
674                          * and there's no way to tell which.  Instead
675                          * of looking foolish and returning 'OVERVOLTAGE'
676                          * when its really under-voltage, just return
677                          * 'UNSPEC_FAILURE'.
678                          */
679                         health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
680                         break;
681                 case 0x2: /* Thermal Shutdown */
682                         health = POWER_SUPPLY_HEALTH_OVERHEAT;
683                         break;
684                 case 0x3: /* Charge Safety Timer Expiration */
685                         health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
686                         break;
687                 default:
688                         health = POWER_SUPPLY_HEALTH_UNKNOWN;
689                 }
690         }
691 
692         val->intval = health;
693 
694         return 0;
695 }
696 
697 static int bq24190_charger_get_online(struct bq24190_dev_info *bdi,
698                 union power_supply_propval *val)
699 {
700         u8 v;
701         int ret;
702 
703         ret = bq24190_read_mask(bdi, BQ24190_REG_SS,
704                         BQ24190_REG_SS_PG_STAT_MASK,
705                         BQ24190_REG_SS_PG_STAT_SHIFT, &v);
706         if (ret < 0)
707                 return ret;
708 
709         val->intval = v;
710         return 0;
711 }
712 
713 static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,
714                 union power_supply_propval *val)
715 {
716         u8 v;
717         int curr, ret;
718 
719         ret = bq24190_get_field_val(bdi, BQ24190_REG_CCC,
720                         BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
721                         bq24190_ccc_ichg_values,
722                         ARRAY_SIZE(bq24190_ccc_ichg_values), &curr);
723         if (ret < 0)
724                 return ret;
725 
726         ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
727                         BQ24190_REG_CCC_FORCE_20PCT_MASK,
728                         BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
729         if (ret < 0)
730                 return ret;
731 
732         /* If FORCE_20PCT is enabled, then current is 20% of ICHG value */
733         if (v)
734                 curr /= 5;
735 
736         val->intval = curr;
737         return 0;
738 }
739 
740 static int bq24190_charger_get_current_max(struct bq24190_dev_info *bdi,
741                 union power_supply_propval *val)
742 {
743         int idx = ARRAY_SIZE(bq24190_ccc_ichg_values) - 1;
744 
745         val->intval = bq24190_ccc_ichg_values[idx];
746         return 0;
747 }
748 
749 static int bq24190_charger_set_current(struct bq24190_dev_info *bdi,
750                 const union power_supply_propval *val)
751 {
752         u8 v;
753         int ret, curr = val->intval;
754 
755         ret = bq24190_read_mask(bdi, BQ24190_REG_CCC,
756                         BQ24190_REG_CCC_FORCE_20PCT_MASK,
757                         BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v);
758         if (ret < 0)
759                 return ret;
760 
761         /* If FORCE_20PCT is enabled, have to multiply value passed in by 5 */
762         if (v)
763                 curr *= 5;
764 
765         return bq24190_set_field_val(bdi, BQ24190_REG_CCC,
766                         BQ24190_REG_CCC_ICHG_MASK, BQ24190_REG_CCC_ICHG_SHIFT,
767                         bq24190_ccc_ichg_values,
768                         ARRAY_SIZE(bq24190_ccc_ichg_values), curr);
769 }
770 
771 static int bq24190_charger_get_voltage(struct bq24190_dev_info *bdi,
772                 union power_supply_propval *val)
773 {
774         int voltage, ret;
775 
776         ret = bq24190_get_field_val(bdi, BQ24190_REG_CVC,
777                         BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
778                         bq24190_cvc_vreg_values,
779                         ARRAY_SIZE(bq24190_cvc_vreg_values), &voltage);
780         if (ret < 0)
781                 return ret;
782 
783         val->intval = voltage;
784         return 0;
785 }
786 
787 static int bq24190_charger_get_voltage_max(struct bq24190_dev_info *bdi,
788                 union power_supply_propval *val)
789 {
790         int idx = ARRAY_SIZE(bq24190_cvc_vreg_values) - 1;
791 
792         val->intval = bq24190_cvc_vreg_values[idx];
793         return 0;
794 }
795 
796 static int bq24190_charger_set_voltage(struct bq24190_dev_info *bdi,
797                 const union power_supply_propval *val)
798 {
799         return bq24190_set_field_val(bdi, BQ24190_REG_CVC,
800                         BQ24190_REG_CVC_VREG_MASK, BQ24190_REG_CVC_VREG_SHIFT,
801                         bq24190_cvc_vreg_values,
802                         ARRAY_SIZE(bq24190_cvc_vreg_values), val->intval);
803 }
804 
805 static int bq24190_charger_get_property(struct power_supply *psy,
806                 enum power_supply_property psp, union power_supply_propval *val)
807 {
808         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
809         int ret;
810 
811         dev_dbg(bdi->dev, "prop: %d\n", psp);
812 
813         pm_runtime_get_sync(bdi->dev);
814 
815         switch (psp) {
816         case POWER_SUPPLY_PROP_CHARGE_TYPE:
817                 ret = bq24190_charger_get_charge_type(bdi, val);
818                 break;
819         case POWER_SUPPLY_PROP_HEALTH:
820                 ret = bq24190_charger_get_health(bdi, val);
821                 break;
822         case POWER_SUPPLY_PROP_ONLINE:
823                 ret = bq24190_charger_get_online(bdi, val);
824                 break;
825         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
826                 ret = bq24190_charger_get_current(bdi, val);
827                 break;
828         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
829                 ret = bq24190_charger_get_current_max(bdi, val);
830                 break;
831         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
832                 ret = bq24190_charger_get_voltage(bdi, val);
833                 break;
834         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
835                 ret = bq24190_charger_get_voltage_max(bdi, val);
836                 break;
837         case POWER_SUPPLY_PROP_SCOPE:
838                 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
839                 ret = 0;
840                 break;
841         case POWER_SUPPLY_PROP_MODEL_NAME:
842                 val->strval = bdi->model_name;
843                 ret = 0;
844                 break;
845         case POWER_SUPPLY_PROP_MANUFACTURER:
846                 val->strval = BQ24190_MANUFACTURER;
847                 ret = 0;
848                 break;
849         default:
850                 ret = -ENODATA;
851         }
852 
853         pm_runtime_put_sync(bdi->dev);
854         return ret;
855 }
856 
857 static int bq24190_charger_set_property(struct power_supply *psy,
858                 enum power_supply_property psp,
859                 const union power_supply_propval *val)
860 {
861         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
862         int ret;
863 
864         dev_dbg(bdi->dev, "prop: %d\n", psp);
865 
866         pm_runtime_get_sync(bdi->dev);
867 
868         switch (psp) {
869         case POWER_SUPPLY_PROP_CHARGE_TYPE:
870                 ret = bq24190_charger_set_charge_type(bdi, val);
871                 break;
872         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
873                 ret = bq24190_charger_set_current(bdi, val);
874                 break;
875         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
876                 ret = bq24190_charger_set_voltage(bdi, val);
877                 break;
878         default:
879                 ret = -EINVAL;
880         }
881 
882         pm_runtime_put_sync(bdi->dev);
883         return ret;
884 }
885 
886 static int bq24190_charger_property_is_writeable(struct power_supply *psy,
887                 enum power_supply_property psp)
888 {
889         int ret;
890 
891         switch (psp) {
892         case POWER_SUPPLY_PROP_CHARGE_TYPE:
893         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
894         case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
895                 ret = 1;
896                 break;
897         default:
898                 ret = 0;
899         }
900 
901         return ret;
902 }
903 
904 static enum power_supply_property bq24190_charger_properties[] = {
905         POWER_SUPPLY_PROP_TYPE,
906         POWER_SUPPLY_PROP_HEALTH,
907         POWER_SUPPLY_PROP_ONLINE,
908         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
909         POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
910         POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
911         POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
912         POWER_SUPPLY_PROP_SCOPE,
913         POWER_SUPPLY_PROP_MODEL_NAME,
914         POWER_SUPPLY_PROP_MANUFACTURER,
915 };
916 
917 static char *bq24190_charger_supplied_to[] = {
918         "main-battery",
919 };
920 
921 static const struct power_supply_desc bq24190_charger_desc = {
922         .name                   = "bq24190-charger",
923         .type                   = POWER_SUPPLY_TYPE_USB,
924         .properties             = bq24190_charger_properties,
925         .num_properties         = ARRAY_SIZE(bq24190_charger_properties),
926         .get_property           = bq24190_charger_get_property,
927         .set_property           = bq24190_charger_set_property,
928         .property_is_writeable  = bq24190_charger_property_is_writeable,
929 };
930 
931 /* Battery power supply property routines */
932 
933 static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,
934                 union power_supply_propval *val)
935 {
936         u8 ss_reg, chrg_fault;
937         int status, ret;
938 
939         mutex_lock(&bdi->f_reg_lock);
940 
941         if (bdi->battery_status_valid) {
942                 chrg_fault = bdi->f_reg;
943                 bdi->battery_status_valid = false;
944                 mutex_unlock(&bdi->f_reg_lock);
945         } else {
946                 mutex_unlock(&bdi->f_reg_lock);
947 
948                 ret = bq24190_read(bdi, BQ24190_REG_F, &chrg_fault);
949                 if (ret < 0)
950                         return ret;
951         }
952 
953         chrg_fault &= BQ24190_REG_F_CHRG_FAULT_MASK;
954         chrg_fault >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
955 
956         ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
957         if (ret < 0)
958                 return ret;
959 
960         /*
961          * The battery must be discharging when any of these are true:
962          * - there is no good power source;
963          * - there is a charge fault.
964          * Could also be discharging when in "supplement mode" but
965          * there is no way to tell when its in that mode.
966          */
967         if (!(ss_reg & BQ24190_REG_SS_PG_STAT_MASK) || chrg_fault) {
968                 status = POWER_SUPPLY_STATUS_DISCHARGING;
969         } else {
970                 ss_reg &= BQ24190_REG_SS_CHRG_STAT_MASK;
971                 ss_reg >>= BQ24190_REG_SS_CHRG_STAT_SHIFT;
972 
973                 switch (ss_reg) {
974                 case 0x0: /* Not Charging */
975                         status = POWER_SUPPLY_STATUS_NOT_CHARGING;
976                         break;
977                 case 0x1: /* Pre-charge */
978                 case 0x2: /* Fast Charging */
979                         status = POWER_SUPPLY_STATUS_CHARGING;
980                         break;
981                 case 0x3: /* Charge Termination Done */
982                         status = POWER_SUPPLY_STATUS_FULL;
983                         break;
984                 default:
985                         ret = -EIO;
986                 }
987         }
988 
989         if (!ret)
990                 val->intval = status;
991 
992         return ret;
993 }
994 
995 static int bq24190_battery_get_health(struct bq24190_dev_info *bdi,
996                 union power_supply_propval *val)
997 {
998         u8 v;
999         int health, ret;
1000 
1001         mutex_lock(&bdi->f_reg_lock);
1002 
1003         if (bdi->battery_health_valid) {
1004                 v = bdi->f_reg;
1005                 bdi->battery_health_valid = false;
1006                 mutex_unlock(&bdi->f_reg_lock);
1007         } else {
1008                 mutex_unlock(&bdi->f_reg_lock);
1009 
1010                 ret = bq24190_read(bdi, BQ24190_REG_F, &v);
1011                 if (ret < 0)
1012                         return ret;
1013         }
1014 
1015         if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
1016                 health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
1017         } else {
1018                 v &= BQ24190_REG_F_NTC_FAULT_MASK;
1019                 v >>= BQ24190_REG_F_NTC_FAULT_SHIFT;
1020 
1021                 switch (v) {
1022                 case 0x0: /* Normal */
1023                         health = POWER_SUPPLY_HEALTH_GOOD;
1024                         break;
1025                 case 0x1: /* TS1 Cold */
1026                 case 0x3: /* TS2 Cold */
1027                 case 0x5: /* Both Cold */
1028                         health = POWER_SUPPLY_HEALTH_COLD;
1029                         break;
1030                 case 0x2: /* TS1 Hot */
1031                 case 0x4: /* TS2 Hot */
1032                 case 0x6: /* Both Hot */
1033                         health = POWER_SUPPLY_HEALTH_OVERHEAT;
1034                         break;
1035                 default:
1036                         health = POWER_SUPPLY_HEALTH_UNKNOWN;
1037                 }
1038         }
1039 
1040         val->intval = health;
1041         return 0;
1042 }
1043 
1044 static int bq24190_battery_get_online(struct bq24190_dev_info *bdi,
1045                 union power_supply_propval *val)
1046 {
1047         u8 batfet_disable;
1048         int ret;
1049 
1050         ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,
1051                         BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1052                         BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);
1053         if (ret < 0)
1054                 return ret;
1055 
1056         val->intval = !batfet_disable;
1057         return 0;
1058 }
1059 
1060 static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,
1061                 const union power_supply_propval *val)
1062 {
1063         return bq24190_write_mask(bdi, BQ24190_REG_MOC,
1064                         BQ24190_REG_MOC_BATFET_DISABLE_MASK,
1065                         BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, !val->intval);
1066 }
1067 
1068 static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,
1069                 union power_supply_propval *val)
1070 {
1071         int temp, ret;
1072 
1073         ret = bq24190_get_field_val(bdi, BQ24190_REG_ICTRC,
1074                         BQ24190_REG_ICTRC_TREG_MASK,
1075                         BQ24190_REG_ICTRC_TREG_SHIFT,
1076                         bq24190_ictrc_treg_values,
1077                         ARRAY_SIZE(bq24190_ictrc_treg_values), &temp);
1078         if (ret < 0)
1079                 return ret;
1080 
1081         val->intval = temp;
1082         return 0;
1083 }
1084 
1085 static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
1086                 const union power_supply_propval *val)
1087 {
1088         return bq24190_set_field_val(bdi, BQ24190_REG_ICTRC,
1089                         BQ24190_REG_ICTRC_TREG_MASK,
1090                         BQ24190_REG_ICTRC_TREG_SHIFT,
1091                         bq24190_ictrc_treg_values,
1092                         ARRAY_SIZE(bq24190_ictrc_treg_values), val->intval);
1093 }
1094 
1095 static int bq24190_battery_get_property(struct power_supply *psy,
1096                 enum power_supply_property psp, union power_supply_propval *val)
1097 {
1098         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
1099         int ret;
1100 
1101         dev_dbg(bdi->dev, "prop: %d\n", psp);
1102 
1103         pm_runtime_get_sync(bdi->dev);
1104 
1105         switch (psp) {
1106         case POWER_SUPPLY_PROP_STATUS:
1107                 ret = bq24190_battery_get_status(bdi, val);
1108                 break;
1109         case POWER_SUPPLY_PROP_HEALTH:
1110                 ret = bq24190_battery_get_health(bdi, val);
1111                 break;
1112         case POWER_SUPPLY_PROP_ONLINE:
1113                 ret = bq24190_battery_get_online(bdi, val);
1114                 break;
1115         case POWER_SUPPLY_PROP_TECHNOLOGY:
1116                 /* Could be Li-on or Li-polymer but no way to tell which */
1117                 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
1118                 ret = 0;
1119                 break;
1120         case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1121                 ret = bq24190_battery_get_temp_alert_max(bdi, val);
1122                 break;
1123         case POWER_SUPPLY_PROP_SCOPE:
1124                 val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
1125                 ret = 0;
1126                 break;
1127         default:
1128                 ret = -ENODATA;
1129         }
1130 
1131         pm_runtime_put_sync(bdi->dev);
1132         return ret;
1133 }
1134 
1135 static int bq24190_battery_set_property(struct power_supply *psy,
1136                 enum power_supply_property psp,
1137                 const union power_supply_propval *val)
1138 {
1139         struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
1140         int ret;
1141 
1142         dev_dbg(bdi->dev, "prop: %d\n", psp);
1143 
1144         pm_runtime_put_sync(bdi->dev);
1145 
1146         switch (psp) {
1147         case POWER_SUPPLY_PROP_ONLINE:
1148                 ret = bq24190_battery_set_online(bdi, val);
1149                 break;
1150         case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1151                 ret = bq24190_battery_set_temp_alert_max(bdi, val);
1152                 break;
1153         default:
1154                 ret = -EINVAL;
1155         }
1156 
1157         pm_runtime_put_sync(bdi->dev);
1158         return ret;
1159 }
1160 
1161 static int bq24190_battery_property_is_writeable(struct power_supply *psy,
1162                 enum power_supply_property psp)
1163 {
1164         int ret;
1165 
1166         switch (psp) {
1167         case POWER_SUPPLY_PROP_ONLINE:
1168         case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
1169                 ret = 1;
1170                 break;
1171         default:
1172                 ret = 0;
1173         }
1174 
1175         return ret;
1176 }
1177 
1178 static enum power_supply_property bq24190_battery_properties[] = {
1179         POWER_SUPPLY_PROP_STATUS,
1180         POWER_SUPPLY_PROP_HEALTH,
1181         POWER_SUPPLY_PROP_ONLINE,
1182         POWER_SUPPLY_PROP_TECHNOLOGY,
1183         POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
1184         POWER_SUPPLY_PROP_SCOPE,
1185 };
1186 
1187 static const struct power_supply_desc bq24190_battery_desc = {
1188         .name                   = "bq24190-battery",
1189         .type                   = POWER_SUPPLY_TYPE_BATTERY,
1190         .properties             = bq24190_battery_properties,
1191         .num_properties         = ARRAY_SIZE(bq24190_battery_properties),
1192         .get_property           = bq24190_battery_get_property,
1193         .set_property           = bq24190_battery_set_property,
1194         .property_is_writeable  = bq24190_battery_property_is_writeable,
1195 };
1196 
1197 static irqreturn_t bq24190_irq_handler_thread(int irq, void *data)
1198 {
1199         struct bq24190_dev_info *bdi = data;
1200         bool alert_userspace = false;
1201         u8 ss_reg = 0, f_reg = 0;
1202         int ret;
1203 
1204         pm_runtime_get_sync(bdi->dev);
1205 
1206         ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg);
1207         if (ret < 0) {
1208                 dev_err(bdi->dev, "Can't read SS reg: %d\n", ret);
1209                 goto out;
1210         }
1211 
1212         if (ss_reg != bdi->ss_reg) {
1213                 /*
1214                  * The device is in host mode so when PG_STAT goes from 1->0
1215                  * (i.e., power removed) HIZ needs to be disabled.
1216                  */
1217                 if ((bdi->ss_reg & BQ24190_REG_SS_PG_STAT_MASK) &&
1218                                 !(ss_reg & BQ24190_REG_SS_PG_STAT_MASK)) {
1219                         ret = bq24190_write_mask(bdi, BQ24190_REG_ISC,
1220                                         BQ24190_REG_ISC_EN_HIZ_MASK,
1221                                         BQ24190_REG_ISC_EN_HIZ_SHIFT,
1222                                         0);
1223                         if (ret < 0)
1224                                 dev_err(bdi->dev, "Can't access ISC reg: %d\n",
1225                                         ret);
1226                 }
1227 
1228                 bdi->ss_reg = ss_reg;
1229                 alert_userspace = true;
1230         }
1231 
1232         mutex_lock(&bdi->f_reg_lock);
1233 
1234         ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg);
1235         if (ret < 0) {
1236                 mutex_unlock(&bdi->f_reg_lock);
1237                 dev_err(bdi->dev, "Can't read F reg: %d\n", ret);
1238                 goto out;
1239         }
1240 
1241         if (f_reg != bdi->f_reg) {
1242                 bdi->f_reg = f_reg;
1243                 bdi->charger_health_valid = true;
1244                 bdi->battery_health_valid = true;
1245                 bdi->battery_status_valid = true;
1246 
1247                 alert_userspace = true;
1248         }
1249 
1250         mutex_unlock(&bdi->f_reg_lock);
1251 
1252         /*
1253          * Sometimes bq24190 gives a steady trickle of interrupts even
1254          * though the watchdog timer is turned off and neither the STATUS
1255          * nor FAULT registers have changed.  Weed out these sprurious
1256          * interrupts so userspace isn't alerted for no reason.
1257          * In addition, the chip always generates an interrupt after
1258          * register reset so we should ignore that one (the very first
1259          * interrupt received).
1260          */
1261         if (alert_userspace && !bdi->first_time) {
1262                 power_supply_changed(bdi->charger);
1263                 power_supply_changed(bdi->battery);
1264                 bdi->first_time = false;
1265         }
1266 
1267 out:
1268         pm_runtime_put_sync(bdi->dev);
1269 
1270         dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg);
1271 
1272         return IRQ_HANDLED;
1273 }
1274 
1275 static int bq24190_hw_init(struct bq24190_dev_info *bdi)
1276 {
1277         u8 v;
1278         int ret;
1279 
1280         pm_runtime_get_sync(bdi->dev);
1281 
1282         /* First check that the device really is what its supposed to be */
1283         ret = bq24190_read_mask(bdi, BQ24190_REG_VPRS,
1284                         BQ24190_REG_VPRS_PN_MASK,
1285                         BQ24190_REG_VPRS_PN_SHIFT,
1286                         &v);
1287         if (ret < 0)
1288                 goto out;
1289 
1290         if (v != bdi->model) {
1291                 ret = -ENODEV;
1292                 goto out;
1293         }
1294 
1295         ret = bq24190_register_reset(bdi);
1296         if (ret < 0)
1297                 goto out;
1298 
1299         ret = bq24190_set_mode_host(bdi);
1300 out:
1301         pm_runtime_put_sync(bdi->dev);
1302         return ret;
1303 }
1304 
1305 #ifdef CONFIG_OF
1306 static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
1307 {
1308         bdi->irq = irq_of_parse_and_map(bdi->dev->of_node, 0);
1309         if (bdi->irq <= 0)
1310                 return -1;
1311 
1312         return 0;
1313 }
1314 #else
1315 static int bq24190_setup_dt(struct bq24190_dev_info *bdi)
1316 {
1317         return -1;
1318 }
1319 #endif
1320 
1321 static int bq24190_setup_pdata(struct bq24190_dev_info *bdi,
1322                 struct bq24190_platform_data *pdata)
1323 {
1324         int ret;
1325 
1326         if (!gpio_is_valid(pdata->gpio_int))
1327                 return -1;
1328 
1329         ret = gpio_request(pdata->gpio_int, dev_name(bdi->dev));
1330         if (ret < 0)
1331                 return -1;
1332 
1333         ret = gpio_direction_input(pdata->gpio_int);
1334         if (ret < 0)
1335                 goto out;
1336 
1337         bdi->irq = gpio_to_irq(pdata->gpio_int);
1338         if (!bdi->irq)
1339                 goto out;
1340 
1341         bdi->gpio_int = pdata->gpio_int;
1342         return 0;
1343 
1344 out:
1345         gpio_free(pdata->gpio_int);
1346         return -1;
1347 }
1348 
1349 static int bq24190_probe(struct i2c_client *client,
1350                 const struct i2c_device_id *id)
1351 {
1352         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1353         struct device *dev = &client->dev;
1354         struct bq24190_platform_data *pdata = client->dev.platform_data;
1355         struct power_supply_config charger_cfg = {}, battery_cfg = {};
1356         struct bq24190_dev_info *bdi;
1357         int ret;
1358 
1359         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1360                 dev_err(dev, "No support for SMBUS_BYTE_DATA\n");
1361                 return -ENODEV;
1362         }
1363 
1364         bdi = devm_kzalloc(dev, sizeof(*bdi), GFP_KERNEL);
1365         if (!bdi) {
1366                 dev_err(dev, "Can't alloc bdi struct\n");
1367                 return -ENOMEM;
1368         }
1369 
1370         bdi->client = client;
1371         bdi->dev = dev;
1372         bdi->model = id->driver_data;
1373         strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
1374         mutex_init(&bdi->f_reg_lock);
1375         bdi->first_time = true;
1376         bdi->charger_health_valid = false;
1377         bdi->battery_health_valid = false;
1378         bdi->battery_status_valid = false;
1379 
1380         i2c_set_clientdata(client, bdi);
1381 
1382         if (dev->of_node)
1383                 ret = bq24190_setup_dt(bdi);
1384         else
1385                 ret = bq24190_setup_pdata(bdi, pdata);
1386 
1387         if (ret) {
1388                 dev_err(dev, "Can't get irq info\n");
1389                 return -EINVAL;
1390         }
1391 
1392         ret = devm_request_threaded_irq(dev, bdi->irq, NULL,
1393                         bq24190_irq_handler_thread,
1394                         IRQF_TRIGGER_RISING | IRQF_ONESHOT,
1395                         "bq24190-charger", bdi);
1396         if (ret < 0) {
1397                 dev_err(dev, "Can't set up irq handler\n");
1398                 goto out1;
1399         }
1400 
1401         pm_runtime_enable(dev);
1402         pm_runtime_resume(dev);
1403 
1404         ret = bq24190_hw_init(bdi);
1405         if (ret < 0) {
1406                 dev_err(dev, "Hardware init failed\n");
1407                 goto out2;
1408         }
1409 
1410         charger_cfg.drv_data = bdi;
1411         charger_cfg.supplied_to = bq24190_charger_supplied_to;
1412         charger_cfg.num_supplicants = ARRAY_SIZE(bq24190_charger_supplied_to),
1413         bdi->charger = power_supply_register(dev, &bq24190_charger_desc,
1414                                                 &charger_cfg);
1415         if (IS_ERR(bdi->charger)) {
1416                 dev_err(dev, "Can't register charger\n");
1417                 ret = PTR_ERR(bdi->charger);
1418                 goto out2;
1419         }
1420 
1421         battery_cfg.drv_data = bdi;
1422         bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
1423                                                 &battery_cfg);
1424         if (IS_ERR(bdi->battery)) {
1425                 dev_err(dev, "Can't register battery\n");
1426                 ret = PTR_ERR(bdi->battery);
1427                 goto out3;
1428         }
1429 
1430         ret = bq24190_sysfs_create_group(bdi);
1431         if (ret) {
1432                 dev_err(dev, "Can't create sysfs entries\n");
1433                 goto out4;
1434         }
1435 
1436         return 0;
1437 
1438 out4:
1439         power_supply_unregister(bdi->battery);
1440 out3:
1441         power_supply_unregister(bdi->charger);
1442 out2:
1443         pm_runtime_disable(dev);
1444 out1:
1445         if (bdi->gpio_int)
1446                 gpio_free(bdi->gpio_int);
1447 
1448         return ret;
1449 }
1450 
1451 static int bq24190_remove(struct i2c_client *client)
1452 {
1453         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1454 
1455         pm_runtime_get_sync(bdi->dev);
1456         bq24190_register_reset(bdi);
1457         pm_runtime_put_sync(bdi->dev);
1458 
1459         bq24190_sysfs_remove_group(bdi);
1460         power_supply_unregister(bdi->battery);
1461         power_supply_unregister(bdi->charger);
1462         pm_runtime_disable(bdi->dev);
1463 
1464         if (bdi->gpio_int)
1465                 gpio_free(bdi->gpio_int);
1466 
1467         return 0;
1468 }
1469 
1470 #ifdef CONFIG_PM_SLEEP
1471 static int bq24190_pm_suspend(struct device *dev)
1472 {
1473         struct i2c_client *client = to_i2c_client(dev);
1474         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1475 
1476         pm_runtime_get_sync(bdi->dev);
1477         bq24190_register_reset(bdi);
1478         pm_runtime_put_sync(bdi->dev);
1479 
1480         return 0;
1481 }
1482 
1483 static int bq24190_pm_resume(struct device *dev)
1484 {
1485         struct i2c_client *client = to_i2c_client(dev);
1486         struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
1487 
1488         bdi->charger_health_valid = false;
1489         bdi->battery_health_valid = false;
1490         bdi->battery_status_valid = false;
1491 
1492         pm_runtime_get_sync(bdi->dev);
1493         bq24190_register_reset(bdi);
1494         pm_runtime_put_sync(bdi->dev);
1495 
1496         /* Things may have changed while suspended so alert upper layer */
1497         power_supply_changed(bdi->charger);
1498         power_supply_changed(bdi->battery);
1499 
1500         return 0;
1501 }
1502 #endif
1503 
1504 static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume);
1505 
1506 /*
1507  * Only support the bq24190 right now.  The bq24192, bq24192i, and bq24193
1508  * are similar but not identical so the driver needs to be extended to
1509  * support them.
1510  */
1511 static const struct i2c_device_id bq24190_i2c_ids[] = {
1512         { "bq24190", BQ24190_REG_VPRS_PN_24190 },
1513         { },
1514 };
1515 
1516 #ifdef CONFIG_OF
1517 static const struct of_device_id bq24190_of_match[] = {
1518         { .compatible = "ti,bq24190", },
1519         { },
1520 };
1521 MODULE_DEVICE_TABLE(of, bq24190_of_match);
1522 #else
1523 static const struct of_device_id bq24190_of_match[] = {
1524         { },
1525 };
1526 #endif
1527 
1528 static struct i2c_driver bq24190_driver = {
1529         .probe          = bq24190_probe,
1530         .remove         = bq24190_remove,
1531         .id_table       = bq24190_i2c_ids,
1532         .driver = {
1533                 .name           = "bq24190-charger",
1534                 .owner          = THIS_MODULE,
1535                 .pm             = &bq24190_pm_ops,
1536                 .of_match_table = of_match_ptr(bq24190_of_match),
1537         },
1538 };
1539 module_i2c_driver(bq24190_driver);
1540 
1541 MODULE_LICENSE("GPL");
1542 MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
1543 MODULE_ALIAS("i2c:bq24190-charger");
1544 MODULE_DESCRIPTION("TI BQ24190 Charger Driver");
1545 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us