1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * bq2415x charger driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2011-2013 Pali Rohár <pali@kernel.org>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Datasheets:
8*4882a593Smuzhiyun * https://www.ti.com/product/bq24150
9*4882a593Smuzhiyun * https://www.ti.com/product/bq24150a
10*4882a593Smuzhiyun * https://www.ti.com/product/bq24152
11*4882a593Smuzhiyun * https://www.ti.com/product/bq24153
12*4882a593Smuzhiyun * https://www.ti.com/product/bq24153a
13*4882a593Smuzhiyun * https://www.ti.com/product/bq24155
14*4882a593Smuzhiyun * https://www.ti.com/product/bq24157s
15*4882a593Smuzhiyun * https://www.ti.com/product/bq24158
16*4882a593Smuzhiyun */
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/param.h>
21*4882a593Smuzhiyun #include <linux/err.h>
22*4882a593Smuzhiyun #include <linux/workqueue.h>
23*4882a593Smuzhiyun #include <linux/sysfs.h>
24*4882a593Smuzhiyun #include <linux/platform_device.h>
25*4882a593Smuzhiyun #include <linux/power_supply.h>
26*4882a593Smuzhiyun #include <linux/idr.h>
27*4882a593Smuzhiyun #include <linux/i2c.h>
28*4882a593Smuzhiyun #include <linux/slab.h>
29*4882a593Smuzhiyun #include <linux/acpi.h>
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include <linux/power/bq2415x_charger.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* timeout for resetting chip timer */
34*4882a593Smuzhiyun #define BQ2415X_TIMER_TIMEOUT 10
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define BQ2415X_REG_STATUS 0x00
37*4882a593Smuzhiyun #define BQ2415X_REG_CONTROL 0x01
38*4882a593Smuzhiyun #define BQ2415X_REG_VOLTAGE 0x02
39*4882a593Smuzhiyun #define BQ2415X_REG_VENDER 0x03
40*4882a593Smuzhiyun #define BQ2415X_REG_CURRENT 0x04
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* reset state for all registers */
43*4882a593Smuzhiyun #define BQ2415X_RESET_STATUS BIT(6)
44*4882a593Smuzhiyun #define BQ2415X_RESET_CONTROL (BIT(4)|BIT(5))
45*4882a593Smuzhiyun #define BQ2415X_RESET_VOLTAGE (BIT(1)|BIT(3))
46*4882a593Smuzhiyun #define BQ2415X_RESET_CURRENT (BIT(0)|BIT(3)|BIT(7))
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* status register */
49*4882a593Smuzhiyun #define BQ2415X_BIT_TMR_RST 7
50*4882a593Smuzhiyun #define BQ2415X_BIT_OTG 7
51*4882a593Smuzhiyun #define BQ2415X_BIT_EN_STAT 6
52*4882a593Smuzhiyun #define BQ2415X_MASK_STAT (BIT(4)|BIT(5))
53*4882a593Smuzhiyun #define BQ2415X_SHIFT_STAT 4
54*4882a593Smuzhiyun #define BQ2415X_BIT_BOOST 3
55*4882a593Smuzhiyun #define BQ2415X_MASK_FAULT (BIT(0)|BIT(1)|BIT(2))
56*4882a593Smuzhiyun #define BQ2415X_SHIFT_FAULT 0
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /* control register */
59*4882a593Smuzhiyun #define BQ2415X_MASK_LIMIT (BIT(6)|BIT(7))
60*4882a593Smuzhiyun #define BQ2415X_SHIFT_LIMIT 6
61*4882a593Smuzhiyun #define BQ2415X_MASK_VLOWV (BIT(4)|BIT(5))
62*4882a593Smuzhiyun #define BQ2415X_SHIFT_VLOWV 4
63*4882a593Smuzhiyun #define BQ2415X_BIT_TE 3
64*4882a593Smuzhiyun #define BQ2415X_BIT_CE 2
65*4882a593Smuzhiyun #define BQ2415X_BIT_HZ_MODE 1
66*4882a593Smuzhiyun #define BQ2415X_BIT_OPA_MODE 0
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* voltage register */
69*4882a593Smuzhiyun #define BQ2415X_MASK_VO (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7))
70*4882a593Smuzhiyun #define BQ2415X_SHIFT_VO 2
71*4882a593Smuzhiyun #define BQ2415X_BIT_OTG_PL 1
72*4882a593Smuzhiyun #define BQ2415X_BIT_OTG_EN 0
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* vender register */
75*4882a593Smuzhiyun #define BQ2415X_MASK_VENDER (BIT(5)|BIT(6)|BIT(7))
76*4882a593Smuzhiyun #define BQ2415X_SHIFT_VENDER 5
77*4882a593Smuzhiyun #define BQ2415X_MASK_PN (BIT(3)|BIT(4))
78*4882a593Smuzhiyun #define BQ2415X_SHIFT_PN 3
79*4882a593Smuzhiyun #define BQ2415X_MASK_REVISION (BIT(0)|BIT(1)|BIT(2))
80*4882a593Smuzhiyun #define BQ2415X_SHIFT_REVISION 0
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* current register */
83*4882a593Smuzhiyun #define BQ2415X_MASK_RESET BIT(7)
84*4882a593Smuzhiyun #define BQ2415X_MASK_VI_CHRG (BIT(4)|BIT(5)|BIT(6))
85*4882a593Smuzhiyun #define BQ2415X_SHIFT_VI_CHRG 4
86*4882a593Smuzhiyun /* N/A BIT(3) */
87*4882a593Smuzhiyun #define BQ2415X_MASK_VI_TERM (BIT(0)|BIT(1)|BIT(2))
88*4882a593Smuzhiyun #define BQ2415X_SHIFT_VI_TERM 0
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun enum bq2415x_command {
92*4882a593Smuzhiyun BQ2415X_TIMER_RESET,
93*4882a593Smuzhiyun BQ2415X_OTG_STATUS,
94*4882a593Smuzhiyun BQ2415X_STAT_PIN_STATUS,
95*4882a593Smuzhiyun BQ2415X_STAT_PIN_ENABLE,
96*4882a593Smuzhiyun BQ2415X_STAT_PIN_DISABLE,
97*4882a593Smuzhiyun BQ2415X_CHARGE_STATUS,
98*4882a593Smuzhiyun BQ2415X_BOOST_STATUS,
99*4882a593Smuzhiyun BQ2415X_FAULT_STATUS,
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun BQ2415X_CHARGE_TERMINATION_STATUS,
102*4882a593Smuzhiyun BQ2415X_CHARGE_TERMINATION_ENABLE,
103*4882a593Smuzhiyun BQ2415X_CHARGE_TERMINATION_DISABLE,
104*4882a593Smuzhiyun BQ2415X_CHARGER_STATUS,
105*4882a593Smuzhiyun BQ2415X_CHARGER_ENABLE,
106*4882a593Smuzhiyun BQ2415X_CHARGER_DISABLE,
107*4882a593Smuzhiyun BQ2415X_HIGH_IMPEDANCE_STATUS,
108*4882a593Smuzhiyun BQ2415X_HIGH_IMPEDANCE_ENABLE,
109*4882a593Smuzhiyun BQ2415X_HIGH_IMPEDANCE_DISABLE,
110*4882a593Smuzhiyun BQ2415X_BOOST_MODE_STATUS,
111*4882a593Smuzhiyun BQ2415X_BOOST_MODE_ENABLE,
112*4882a593Smuzhiyun BQ2415X_BOOST_MODE_DISABLE,
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun BQ2415X_OTG_LEVEL,
115*4882a593Smuzhiyun BQ2415X_OTG_ACTIVATE_HIGH,
116*4882a593Smuzhiyun BQ2415X_OTG_ACTIVATE_LOW,
117*4882a593Smuzhiyun BQ2415X_OTG_PIN_STATUS,
118*4882a593Smuzhiyun BQ2415X_OTG_PIN_ENABLE,
119*4882a593Smuzhiyun BQ2415X_OTG_PIN_DISABLE,
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun BQ2415X_VENDER_CODE,
122*4882a593Smuzhiyun BQ2415X_PART_NUMBER,
123*4882a593Smuzhiyun BQ2415X_REVISION,
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun enum bq2415x_chip {
127*4882a593Smuzhiyun BQUNKNOWN,
128*4882a593Smuzhiyun BQ24150,
129*4882a593Smuzhiyun BQ24150A,
130*4882a593Smuzhiyun BQ24151,
131*4882a593Smuzhiyun BQ24151A,
132*4882a593Smuzhiyun BQ24152,
133*4882a593Smuzhiyun BQ24153,
134*4882a593Smuzhiyun BQ24153A,
135*4882a593Smuzhiyun BQ24155,
136*4882a593Smuzhiyun BQ24156,
137*4882a593Smuzhiyun BQ24156A,
138*4882a593Smuzhiyun BQ24157S,
139*4882a593Smuzhiyun BQ24158,
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun static char *bq2415x_chip_name[] = {
143*4882a593Smuzhiyun "unknown",
144*4882a593Smuzhiyun "bq24150",
145*4882a593Smuzhiyun "bq24150a",
146*4882a593Smuzhiyun "bq24151",
147*4882a593Smuzhiyun "bq24151a",
148*4882a593Smuzhiyun "bq24152",
149*4882a593Smuzhiyun "bq24153",
150*4882a593Smuzhiyun "bq24153a",
151*4882a593Smuzhiyun "bq24155",
152*4882a593Smuzhiyun "bq24156",
153*4882a593Smuzhiyun "bq24156a",
154*4882a593Smuzhiyun "bq24157s",
155*4882a593Smuzhiyun "bq24158",
156*4882a593Smuzhiyun };
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun struct bq2415x_device {
159*4882a593Smuzhiyun struct device *dev;
160*4882a593Smuzhiyun struct bq2415x_platform_data init_data;
161*4882a593Smuzhiyun struct power_supply *charger;
162*4882a593Smuzhiyun struct power_supply_desc charger_desc;
163*4882a593Smuzhiyun struct delayed_work work;
164*4882a593Smuzhiyun struct device_node *notify_node;
165*4882a593Smuzhiyun struct notifier_block nb;
166*4882a593Smuzhiyun enum bq2415x_mode reported_mode;/* mode reported by hook function */
167*4882a593Smuzhiyun enum bq2415x_mode mode; /* currently configured mode */
168*4882a593Smuzhiyun enum bq2415x_chip chip;
169*4882a593Smuzhiyun const char *timer_error;
170*4882a593Smuzhiyun char *model;
171*4882a593Smuzhiyun char *name;
172*4882a593Smuzhiyun int autotimer; /* 1 - if driver automatically reset timer, 0 - not */
173*4882a593Smuzhiyun int automode; /* 1 - enabled, 0 - disabled; -1 - not supported */
174*4882a593Smuzhiyun int id;
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* each registered chip must have unique id */
178*4882a593Smuzhiyun static DEFINE_IDR(bq2415x_id);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun static DEFINE_MUTEX(bq2415x_id_mutex);
181*4882a593Smuzhiyun static DEFINE_MUTEX(bq2415x_timer_mutex);
182*4882a593Smuzhiyun static DEFINE_MUTEX(bq2415x_i2c_mutex);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /**** i2c read functions ****/
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun /* read value from register */
bq2415x_i2c_read(struct bq2415x_device * bq,u8 reg)187*4882a593Smuzhiyun static int bq2415x_i2c_read(struct bq2415x_device *bq, u8 reg)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(bq->dev);
190*4882a593Smuzhiyun struct i2c_msg msg[2];
191*4882a593Smuzhiyun u8 val;
192*4882a593Smuzhiyun int ret;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (!client->adapter)
195*4882a593Smuzhiyun return -ENODEV;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun msg[0].addr = client->addr;
198*4882a593Smuzhiyun msg[0].flags = 0;
199*4882a593Smuzhiyun msg[0].buf = ®
200*4882a593Smuzhiyun msg[0].len = sizeof(reg);
201*4882a593Smuzhiyun msg[1].addr = client->addr;
202*4882a593Smuzhiyun msg[1].flags = I2C_M_RD;
203*4882a593Smuzhiyun msg[1].buf = &val;
204*4882a593Smuzhiyun msg[1].len = sizeof(val);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun mutex_lock(&bq2415x_i2c_mutex);
207*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
208*4882a593Smuzhiyun mutex_unlock(&bq2415x_i2c_mutex);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (ret < 0)
211*4882a593Smuzhiyun return ret;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun return val;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* read value from register, apply mask and right shift it */
bq2415x_i2c_read_mask(struct bq2415x_device * bq,u8 reg,u8 mask,u8 shift)217*4882a593Smuzhiyun static int bq2415x_i2c_read_mask(struct bq2415x_device *bq, u8 reg,
218*4882a593Smuzhiyun u8 mask, u8 shift)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun int ret;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (shift > 8)
223*4882a593Smuzhiyun return -EINVAL;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun ret = bq2415x_i2c_read(bq, reg);
226*4882a593Smuzhiyun if (ret < 0)
227*4882a593Smuzhiyun return ret;
228*4882a593Smuzhiyun return (ret & mask) >> shift;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /* read value from register and return one specified bit */
bq2415x_i2c_read_bit(struct bq2415x_device * bq,u8 reg,u8 bit)232*4882a593Smuzhiyun static int bq2415x_i2c_read_bit(struct bq2415x_device *bq, u8 reg, u8 bit)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun if (bit > 8)
235*4882a593Smuzhiyun return -EINVAL;
236*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, reg, BIT(bit), bit);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /**** i2c write functions ****/
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /* write value to register */
bq2415x_i2c_write(struct bq2415x_device * bq,u8 reg,u8 val)242*4882a593Smuzhiyun static int bq2415x_i2c_write(struct bq2415x_device *bq, u8 reg, u8 val)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(bq->dev);
245*4882a593Smuzhiyun struct i2c_msg msg[1];
246*4882a593Smuzhiyun u8 data[2];
247*4882a593Smuzhiyun int ret;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun data[0] = reg;
250*4882a593Smuzhiyun data[1] = val;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun msg[0].addr = client->addr;
253*4882a593Smuzhiyun msg[0].flags = 0;
254*4882a593Smuzhiyun msg[0].buf = data;
255*4882a593Smuzhiyun msg[0].len = ARRAY_SIZE(data);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun mutex_lock(&bq2415x_i2c_mutex);
258*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
259*4882a593Smuzhiyun mutex_unlock(&bq2415x_i2c_mutex);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* i2c_transfer returns number of messages transferred */
262*4882a593Smuzhiyun if (ret < 0)
263*4882a593Smuzhiyun return ret;
264*4882a593Smuzhiyun else if (ret != 1)
265*4882a593Smuzhiyun return -EIO;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun return 0;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* read value from register, change it with mask left shifted and write back */
bq2415x_i2c_write_mask(struct bq2415x_device * bq,u8 reg,u8 val,u8 mask,u8 shift)271*4882a593Smuzhiyun static int bq2415x_i2c_write_mask(struct bq2415x_device *bq, u8 reg, u8 val,
272*4882a593Smuzhiyun u8 mask, u8 shift)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun int ret;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (shift > 8)
277*4882a593Smuzhiyun return -EINVAL;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun ret = bq2415x_i2c_read(bq, reg);
280*4882a593Smuzhiyun if (ret < 0)
281*4882a593Smuzhiyun return ret;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun ret &= ~mask;
284*4882a593Smuzhiyun ret |= val << shift;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun return bq2415x_i2c_write(bq, reg, ret);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun /* change only one bit in register */
bq2415x_i2c_write_bit(struct bq2415x_device * bq,u8 reg,bool val,u8 bit)290*4882a593Smuzhiyun static int bq2415x_i2c_write_bit(struct bq2415x_device *bq, u8 reg,
291*4882a593Smuzhiyun bool val, u8 bit)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun if (bit > 8)
294*4882a593Smuzhiyun return -EINVAL;
295*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, reg, val, BIT(bit), bit);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /**** global functions ****/
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun /* exec command function */
bq2415x_exec_command(struct bq2415x_device * bq,enum bq2415x_command command)301*4882a593Smuzhiyun static int bq2415x_exec_command(struct bq2415x_device *bq,
302*4882a593Smuzhiyun enum bq2415x_command command)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun int ret;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun switch (command) {
307*4882a593Smuzhiyun case BQ2415X_TIMER_RESET:
308*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS,
309*4882a593Smuzhiyun 1, BQ2415X_BIT_TMR_RST);
310*4882a593Smuzhiyun case BQ2415X_OTG_STATUS:
311*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
312*4882a593Smuzhiyun BQ2415X_BIT_OTG);
313*4882a593Smuzhiyun case BQ2415X_STAT_PIN_STATUS:
314*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
315*4882a593Smuzhiyun BQ2415X_BIT_EN_STAT);
316*4882a593Smuzhiyun case BQ2415X_STAT_PIN_ENABLE:
317*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 1,
318*4882a593Smuzhiyun BQ2415X_BIT_EN_STAT);
319*4882a593Smuzhiyun case BQ2415X_STAT_PIN_DISABLE:
320*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 0,
321*4882a593Smuzhiyun BQ2415X_BIT_EN_STAT);
322*4882a593Smuzhiyun case BQ2415X_CHARGE_STATUS:
323*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
324*4882a593Smuzhiyun BQ2415X_MASK_STAT, BQ2415X_SHIFT_STAT);
325*4882a593Smuzhiyun case BQ2415X_BOOST_STATUS:
326*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS,
327*4882a593Smuzhiyun BQ2415X_BIT_BOOST);
328*4882a593Smuzhiyun case BQ2415X_FAULT_STATUS:
329*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS,
330*4882a593Smuzhiyun BQ2415X_MASK_FAULT, BQ2415X_SHIFT_FAULT);
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun case BQ2415X_CHARGE_TERMINATION_STATUS:
333*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
334*4882a593Smuzhiyun BQ2415X_BIT_TE);
335*4882a593Smuzhiyun case BQ2415X_CHARGE_TERMINATION_ENABLE:
336*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
337*4882a593Smuzhiyun 1, BQ2415X_BIT_TE);
338*4882a593Smuzhiyun case BQ2415X_CHARGE_TERMINATION_DISABLE:
339*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
340*4882a593Smuzhiyun 0, BQ2415X_BIT_TE);
341*4882a593Smuzhiyun case BQ2415X_CHARGER_STATUS:
342*4882a593Smuzhiyun ret = bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
343*4882a593Smuzhiyun BQ2415X_BIT_CE);
344*4882a593Smuzhiyun if (ret < 0)
345*4882a593Smuzhiyun return ret;
346*4882a593Smuzhiyun return ret > 0 ? 0 : 1;
347*4882a593Smuzhiyun case BQ2415X_CHARGER_ENABLE:
348*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
349*4882a593Smuzhiyun 0, BQ2415X_BIT_CE);
350*4882a593Smuzhiyun case BQ2415X_CHARGER_DISABLE:
351*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
352*4882a593Smuzhiyun 1, BQ2415X_BIT_CE);
353*4882a593Smuzhiyun case BQ2415X_HIGH_IMPEDANCE_STATUS:
354*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
355*4882a593Smuzhiyun BQ2415X_BIT_HZ_MODE);
356*4882a593Smuzhiyun case BQ2415X_HIGH_IMPEDANCE_ENABLE:
357*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
358*4882a593Smuzhiyun 1, BQ2415X_BIT_HZ_MODE);
359*4882a593Smuzhiyun case BQ2415X_HIGH_IMPEDANCE_DISABLE:
360*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
361*4882a593Smuzhiyun 0, BQ2415X_BIT_HZ_MODE);
362*4882a593Smuzhiyun case BQ2415X_BOOST_MODE_STATUS:
363*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL,
364*4882a593Smuzhiyun BQ2415X_BIT_OPA_MODE);
365*4882a593Smuzhiyun case BQ2415X_BOOST_MODE_ENABLE:
366*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
367*4882a593Smuzhiyun 1, BQ2415X_BIT_OPA_MODE);
368*4882a593Smuzhiyun case BQ2415X_BOOST_MODE_DISABLE:
369*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL,
370*4882a593Smuzhiyun 0, BQ2415X_BIT_OPA_MODE);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun case BQ2415X_OTG_LEVEL:
373*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
374*4882a593Smuzhiyun BQ2415X_BIT_OTG_PL);
375*4882a593Smuzhiyun case BQ2415X_OTG_ACTIVATE_HIGH:
376*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
377*4882a593Smuzhiyun 1, BQ2415X_BIT_OTG_PL);
378*4882a593Smuzhiyun case BQ2415X_OTG_ACTIVATE_LOW:
379*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
380*4882a593Smuzhiyun 0, BQ2415X_BIT_OTG_PL);
381*4882a593Smuzhiyun case BQ2415X_OTG_PIN_STATUS:
382*4882a593Smuzhiyun return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE,
383*4882a593Smuzhiyun BQ2415X_BIT_OTG_EN);
384*4882a593Smuzhiyun case BQ2415X_OTG_PIN_ENABLE:
385*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
386*4882a593Smuzhiyun 1, BQ2415X_BIT_OTG_EN);
387*4882a593Smuzhiyun case BQ2415X_OTG_PIN_DISABLE:
388*4882a593Smuzhiyun return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE,
389*4882a593Smuzhiyun 0, BQ2415X_BIT_OTG_EN);
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun case BQ2415X_VENDER_CODE:
392*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
393*4882a593Smuzhiyun BQ2415X_MASK_VENDER, BQ2415X_SHIFT_VENDER);
394*4882a593Smuzhiyun case BQ2415X_PART_NUMBER:
395*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
396*4882a593Smuzhiyun BQ2415X_MASK_PN, BQ2415X_SHIFT_PN);
397*4882a593Smuzhiyun case BQ2415X_REVISION:
398*4882a593Smuzhiyun return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER,
399*4882a593Smuzhiyun BQ2415X_MASK_REVISION, BQ2415X_SHIFT_REVISION);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun return -EINVAL;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /* detect chip type */
bq2415x_detect_chip(struct bq2415x_device * bq)405*4882a593Smuzhiyun static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(bq->dev);
408*4882a593Smuzhiyun int ret = bq2415x_exec_command(bq, BQ2415X_PART_NUMBER);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun if (ret < 0)
411*4882a593Smuzhiyun return ret;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun switch (client->addr) {
414*4882a593Smuzhiyun case 0x6b:
415*4882a593Smuzhiyun switch (ret) {
416*4882a593Smuzhiyun case 0:
417*4882a593Smuzhiyun if (bq->chip == BQ24151A)
418*4882a593Smuzhiyun return bq->chip;
419*4882a593Smuzhiyun return BQ24151;
420*4882a593Smuzhiyun case 1:
421*4882a593Smuzhiyun if (bq->chip == BQ24150A ||
422*4882a593Smuzhiyun bq->chip == BQ24152 ||
423*4882a593Smuzhiyun bq->chip == BQ24155)
424*4882a593Smuzhiyun return bq->chip;
425*4882a593Smuzhiyun return BQ24150;
426*4882a593Smuzhiyun case 2:
427*4882a593Smuzhiyun if (bq->chip == BQ24153A)
428*4882a593Smuzhiyun return bq->chip;
429*4882a593Smuzhiyun return BQ24153;
430*4882a593Smuzhiyun default:
431*4882a593Smuzhiyun return BQUNKNOWN;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun break;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun case 0x6a:
436*4882a593Smuzhiyun switch (ret) {
437*4882a593Smuzhiyun case 0:
438*4882a593Smuzhiyun if (bq->chip == BQ24156A)
439*4882a593Smuzhiyun return bq->chip;
440*4882a593Smuzhiyun return BQ24156;
441*4882a593Smuzhiyun case 2:
442*4882a593Smuzhiyun if (bq->chip == BQ24157S)
443*4882a593Smuzhiyun return bq->chip;
444*4882a593Smuzhiyun return BQ24158;
445*4882a593Smuzhiyun default:
446*4882a593Smuzhiyun return BQUNKNOWN;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun break;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun return BQUNKNOWN;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /* detect chip revision */
bq2415x_detect_revision(struct bq2415x_device * bq)455*4882a593Smuzhiyun static int bq2415x_detect_revision(struct bq2415x_device *bq)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun int ret = bq2415x_exec_command(bq, BQ2415X_REVISION);
458*4882a593Smuzhiyun int chip = bq2415x_detect_chip(bq);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun if (ret < 0 || chip < 0)
461*4882a593Smuzhiyun return -1;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun switch (chip) {
464*4882a593Smuzhiyun case BQ24150:
465*4882a593Smuzhiyun case BQ24150A:
466*4882a593Smuzhiyun case BQ24151:
467*4882a593Smuzhiyun case BQ24151A:
468*4882a593Smuzhiyun case BQ24152:
469*4882a593Smuzhiyun if (ret >= 0 && ret <= 3)
470*4882a593Smuzhiyun return ret;
471*4882a593Smuzhiyun return -1;
472*4882a593Smuzhiyun case BQ24153:
473*4882a593Smuzhiyun case BQ24153A:
474*4882a593Smuzhiyun case BQ24156:
475*4882a593Smuzhiyun case BQ24156A:
476*4882a593Smuzhiyun case BQ24157S:
477*4882a593Smuzhiyun case BQ24158:
478*4882a593Smuzhiyun if (ret == 3)
479*4882a593Smuzhiyun return 0;
480*4882a593Smuzhiyun else if (ret == 1)
481*4882a593Smuzhiyun return 1;
482*4882a593Smuzhiyun return -1;
483*4882a593Smuzhiyun case BQ24155:
484*4882a593Smuzhiyun if (ret == 3)
485*4882a593Smuzhiyun return 3;
486*4882a593Smuzhiyun return -1;
487*4882a593Smuzhiyun case BQUNKNOWN:
488*4882a593Smuzhiyun return -1;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun return -1;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /* return chip vender code */
bq2415x_get_vender_code(struct bq2415x_device * bq)495*4882a593Smuzhiyun static int bq2415x_get_vender_code(struct bq2415x_device *bq)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun int ret;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_VENDER_CODE);
500*4882a593Smuzhiyun if (ret < 0)
501*4882a593Smuzhiyun return 0;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /* convert to binary */
504*4882a593Smuzhiyun return (ret & 0x1) +
505*4882a593Smuzhiyun ((ret >> 1) & 0x1) * 10 +
506*4882a593Smuzhiyun ((ret >> 2) & 0x1) * 100;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* reset all chip registers to default state */
bq2415x_reset_chip(struct bq2415x_device * bq)510*4882a593Smuzhiyun static void bq2415x_reset_chip(struct bq2415x_device *bq)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun bq2415x_i2c_write(bq, BQ2415X_REG_CURRENT, BQ2415X_RESET_CURRENT);
513*4882a593Smuzhiyun bq2415x_i2c_write(bq, BQ2415X_REG_VOLTAGE, BQ2415X_RESET_VOLTAGE);
514*4882a593Smuzhiyun bq2415x_i2c_write(bq, BQ2415X_REG_CONTROL, BQ2415X_RESET_CONTROL);
515*4882a593Smuzhiyun bq2415x_i2c_write(bq, BQ2415X_REG_STATUS, BQ2415X_RESET_STATUS);
516*4882a593Smuzhiyun bq->timer_error = NULL;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun /**** properties functions ****/
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* set current limit in mA */
bq2415x_set_current_limit(struct bq2415x_device * bq,int mA)522*4882a593Smuzhiyun static int bq2415x_set_current_limit(struct bq2415x_device *bq, int mA)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun int val;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun if (mA <= 100)
527*4882a593Smuzhiyun val = 0;
528*4882a593Smuzhiyun else if (mA <= 500)
529*4882a593Smuzhiyun val = 1;
530*4882a593Smuzhiyun else if (mA <= 800)
531*4882a593Smuzhiyun val = 2;
532*4882a593Smuzhiyun else
533*4882a593Smuzhiyun val = 3;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
536*4882a593Smuzhiyun BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun /* get current limit in mA */
bq2415x_get_current_limit(struct bq2415x_device * bq)540*4882a593Smuzhiyun static int bq2415x_get_current_limit(struct bq2415x_device *bq)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun int ret;
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
545*4882a593Smuzhiyun BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT);
546*4882a593Smuzhiyun if (ret < 0)
547*4882a593Smuzhiyun return ret;
548*4882a593Smuzhiyun else if (ret == 0)
549*4882a593Smuzhiyun return 100;
550*4882a593Smuzhiyun else if (ret == 1)
551*4882a593Smuzhiyun return 500;
552*4882a593Smuzhiyun else if (ret == 2)
553*4882a593Smuzhiyun return 800;
554*4882a593Smuzhiyun else if (ret == 3)
555*4882a593Smuzhiyun return 1800;
556*4882a593Smuzhiyun return -EINVAL;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun /* set weak battery voltage in mV */
bq2415x_set_weak_battery_voltage(struct bq2415x_device * bq,int mV)560*4882a593Smuzhiyun static int bq2415x_set_weak_battery_voltage(struct bq2415x_device *bq, int mV)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun int val;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* round to 100mV */
565*4882a593Smuzhiyun if (mV <= 3400 + 50)
566*4882a593Smuzhiyun val = 0;
567*4882a593Smuzhiyun else if (mV <= 3500 + 50)
568*4882a593Smuzhiyun val = 1;
569*4882a593Smuzhiyun else if (mV <= 3600 + 50)
570*4882a593Smuzhiyun val = 2;
571*4882a593Smuzhiyun else
572*4882a593Smuzhiyun val = 3;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val,
575*4882a593Smuzhiyun BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun /* get weak battery voltage in mV */
bq2415x_get_weak_battery_voltage(struct bq2415x_device * bq)579*4882a593Smuzhiyun static int bq2415x_get_weak_battery_voltage(struct bq2415x_device *bq)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun int ret;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL,
584*4882a593Smuzhiyun BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV);
585*4882a593Smuzhiyun if (ret < 0)
586*4882a593Smuzhiyun return ret;
587*4882a593Smuzhiyun return 100 * (34 + ret);
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /* set battery regulation voltage in mV */
bq2415x_set_battery_regulation_voltage(struct bq2415x_device * bq,int mV)591*4882a593Smuzhiyun static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq,
592*4882a593Smuzhiyun int mV)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun int val = (mV/10 - 350) / 2;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun /*
597*4882a593Smuzhiyun * According to datasheet, maximum battery regulation voltage is
598*4882a593Smuzhiyun * 4440mV which is b101111 = 47.
599*4882a593Smuzhiyun */
600*4882a593Smuzhiyun if (val < 0)
601*4882a593Smuzhiyun val = 0;
602*4882a593Smuzhiyun else if (val > 47)
603*4882a593Smuzhiyun return -EINVAL;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val,
606*4882a593Smuzhiyun BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
607*4882a593Smuzhiyun }
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun /* get battery regulation voltage in mV */
bq2415x_get_battery_regulation_voltage(struct bq2415x_device * bq)610*4882a593Smuzhiyun static int bq2415x_get_battery_regulation_voltage(struct bq2415x_device *bq)
611*4882a593Smuzhiyun {
612*4882a593Smuzhiyun int ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_VOLTAGE,
613*4882a593Smuzhiyun BQ2415X_MASK_VO, BQ2415X_SHIFT_VO);
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (ret < 0)
616*4882a593Smuzhiyun return ret;
617*4882a593Smuzhiyun return 10 * (350 + 2*ret);
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun /* set charge current in mA (platform data must provide resistor sense) */
bq2415x_set_charge_current(struct bq2415x_device * bq,int mA)621*4882a593Smuzhiyun static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun int val;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun if (bq->init_data.resistor_sense <= 0)
626*4882a593Smuzhiyun return -EINVAL;
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun val = (mA * bq->init_data.resistor_sense - 37400) / 6800;
629*4882a593Smuzhiyun if (val < 0)
630*4882a593Smuzhiyun val = 0;
631*4882a593Smuzhiyun else if (val > 7)
632*4882a593Smuzhiyun val = 7;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
635*4882a593Smuzhiyun BQ2415X_MASK_VI_CHRG | BQ2415X_MASK_RESET,
636*4882a593Smuzhiyun BQ2415X_SHIFT_VI_CHRG);
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun /* get charge current in mA (platform data must provide resistor sense) */
bq2415x_get_charge_current(struct bq2415x_device * bq)640*4882a593Smuzhiyun static int bq2415x_get_charge_current(struct bq2415x_device *bq)
641*4882a593Smuzhiyun {
642*4882a593Smuzhiyun int ret;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (bq->init_data.resistor_sense <= 0)
645*4882a593Smuzhiyun return -EINVAL;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
648*4882a593Smuzhiyun BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG);
649*4882a593Smuzhiyun if (ret < 0)
650*4882a593Smuzhiyun return ret;
651*4882a593Smuzhiyun return (37400 + 6800*ret) / bq->init_data.resistor_sense;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* set termination current in mA (platform data must provide resistor sense) */
bq2415x_set_termination_current(struct bq2415x_device * bq,int mA)655*4882a593Smuzhiyun static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA)
656*4882a593Smuzhiyun {
657*4882a593Smuzhiyun int val;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (bq->init_data.resistor_sense <= 0)
660*4882a593Smuzhiyun return -EINVAL;
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun val = (mA * bq->init_data.resistor_sense - 3400) / 3400;
663*4882a593Smuzhiyun if (val < 0)
664*4882a593Smuzhiyun val = 0;
665*4882a593Smuzhiyun else if (val > 7)
666*4882a593Smuzhiyun val = 7;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val,
669*4882a593Smuzhiyun BQ2415X_MASK_VI_TERM | BQ2415X_MASK_RESET,
670*4882a593Smuzhiyun BQ2415X_SHIFT_VI_TERM);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun /* get termination current in mA (platform data must provide resistor sense) */
bq2415x_get_termination_current(struct bq2415x_device * bq)674*4882a593Smuzhiyun static int bq2415x_get_termination_current(struct bq2415x_device *bq)
675*4882a593Smuzhiyun {
676*4882a593Smuzhiyun int ret;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun if (bq->init_data.resistor_sense <= 0)
679*4882a593Smuzhiyun return -EINVAL;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT,
682*4882a593Smuzhiyun BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM);
683*4882a593Smuzhiyun if (ret < 0)
684*4882a593Smuzhiyun return ret;
685*4882a593Smuzhiyun return (3400 + 3400*ret) / bq->init_data.resistor_sense;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun /* set default value of property */
689*4882a593Smuzhiyun #define bq2415x_set_default_value(bq, prop) \
690*4882a593Smuzhiyun do { \
691*4882a593Smuzhiyun int ret = 0; \
692*4882a593Smuzhiyun if (bq->init_data.prop != -1) \
693*4882a593Smuzhiyun ret = bq2415x_set_##prop(bq, bq->init_data.prop); \
694*4882a593Smuzhiyun if (ret < 0) \
695*4882a593Smuzhiyun return ret; \
696*4882a593Smuzhiyun } while (0)
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun /* set default values of all properties */
bq2415x_set_defaults(struct bq2415x_device * bq)699*4882a593Smuzhiyun static int bq2415x_set_defaults(struct bq2415x_device *bq)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
702*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
703*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_DISABLE);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun bq2415x_set_default_value(bq, current_limit);
706*4882a593Smuzhiyun bq2415x_set_default_value(bq, weak_battery_voltage);
707*4882a593Smuzhiyun bq2415x_set_default_value(bq, battery_regulation_voltage);
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun if (bq->init_data.resistor_sense > 0) {
710*4882a593Smuzhiyun bq2415x_set_default_value(bq, charge_current);
711*4882a593Smuzhiyun bq2415x_set_default_value(bq, termination_current);
712*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_ENABLE);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
716*4882a593Smuzhiyun return 0;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun /**** charger mode functions ****/
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* set charger mode */
bq2415x_set_mode(struct bq2415x_device * bq,enum bq2415x_mode mode)722*4882a593Smuzhiyun static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun int ret = 0;
725*4882a593Smuzhiyun int charger = 0;
726*4882a593Smuzhiyun int boost = 0;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun if (mode == BQ2415X_MODE_BOOST)
729*4882a593Smuzhiyun boost = 1;
730*4882a593Smuzhiyun else if (mode != BQ2415X_MODE_OFF)
731*4882a593Smuzhiyun charger = 1;
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun if (!charger)
734*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun if (!boost)
737*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun if (ret < 0)
740*4882a593Smuzhiyun return ret;
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun switch (mode) {
743*4882a593Smuzhiyun case BQ2415X_MODE_OFF:
744*4882a593Smuzhiyun dev_dbg(bq->dev, "changing mode to: Offline\n");
745*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, 100);
746*4882a593Smuzhiyun break;
747*4882a593Smuzhiyun case BQ2415X_MODE_NONE:
748*4882a593Smuzhiyun dev_dbg(bq->dev, "changing mode to: N/A\n");
749*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, 100);
750*4882a593Smuzhiyun break;
751*4882a593Smuzhiyun case BQ2415X_MODE_HOST_CHARGER:
752*4882a593Smuzhiyun dev_dbg(bq->dev, "changing mode to: Host/HUB charger\n");
753*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, 500);
754*4882a593Smuzhiyun break;
755*4882a593Smuzhiyun case BQ2415X_MODE_DEDICATED_CHARGER:
756*4882a593Smuzhiyun dev_dbg(bq->dev, "changing mode to: Dedicated charger\n");
757*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, 1800);
758*4882a593Smuzhiyun break;
759*4882a593Smuzhiyun case BQ2415X_MODE_BOOST: /* Boost mode */
760*4882a593Smuzhiyun dev_dbg(bq->dev, "changing mode to: Boost\n");
761*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, 100);
762*4882a593Smuzhiyun break;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun if (ret < 0)
766*4882a593Smuzhiyun return ret;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun if (charger)
769*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE);
770*4882a593Smuzhiyun else if (boost)
771*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_ENABLE);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (ret < 0)
774*4882a593Smuzhiyun return ret;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun bq2415x_set_default_value(bq, weak_battery_voltage);
777*4882a593Smuzhiyun bq2415x_set_default_value(bq, battery_regulation_voltage);
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun bq->mode = mode;
780*4882a593Smuzhiyun sysfs_notify(&bq->charger->dev.kobj, NULL, "mode");
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun return 0;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
bq2415x_update_reported_mode(struct bq2415x_device * bq,int mA)786*4882a593Smuzhiyun static bool bq2415x_update_reported_mode(struct bq2415x_device *bq, int mA)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun enum bq2415x_mode mode;
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun if (mA == 0)
791*4882a593Smuzhiyun mode = BQ2415X_MODE_OFF;
792*4882a593Smuzhiyun else if (mA < 500)
793*4882a593Smuzhiyun mode = BQ2415X_MODE_NONE;
794*4882a593Smuzhiyun else if (mA < 1800)
795*4882a593Smuzhiyun mode = BQ2415X_MODE_HOST_CHARGER;
796*4882a593Smuzhiyun else
797*4882a593Smuzhiyun mode = BQ2415X_MODE_DEDICATED_CHARGER;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (bq->reported_mode == mode)
800*4882a593Smuzhiyun return false;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun bq->reported_mode = mode;
803*4882a593Smuzhiyun return true;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
bq2415x_notifier_call(struct notifier_block * nb,unsigned long val,void * v)806*4882a593Smuzhiyun static int bq2415x_notifier_call(struct notifier_block *nb,
807*4882a593Smuzhiyun unsigned long val, void *v)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun struct bq2415x_device *bq =
810*4882a593Smuzhiyun container_of(nb, struct bq2415x_device, nb);
811*4882a593Smuzhiyun struct power_supply *psy = v;
812*4882a593Smuzhiyun union power_supply_propval prop;
813*4882a593Smuzhiyun int ret;
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun if (val != PSY_EVENT_PROP_CHANGED)
816*4882a593Smuzhiyun return NOTIFY_OK;
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun /* Ignore event if it was not send by notify_node/notify_device */
819*4882a593Smuzhiyun if (bq->notify_node) {
820*4882a593Smuzhiyun if (!psy->dev.parent ||
821*4882a593Smuzhiyun psy->dev.parent->of_node != bq->notify_node)
822*4882a593Smuzhiyun return NOTIFY_OK;
823*4882a593Smuzhiyun } else if (bq->init_data.notify_device) {
824*4882a593Smuzhiyun if (strcmp(psy->desc->name, bq->init_data.notify_device) != 0)
825*4882a593Smuzhiyun return NOTIFY_OK;
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun dev_dbg(bq->dev, "notifier call was called\n");
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX,
831*4882a593Smuzhiyun &prop);
832*4882a593Smuzhiyun if (ret != 0)
833*4882a593Smuzhiyun return NOTIFY_OK;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun if (!bq2415x_update_reported_mode(bq, prop.intval))
836*4882a593Smuzhiyun return NOTIFY_OK;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun /* if automode is not enabled do not tell about reported_mode */
839*4882a593Smuzhiyun if (bq->automode < 1)
840*4882a593Smuzhiyun return NOTIFY_OK;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun schedule_delayed_work(&bq->work, 0);
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun return NOTIFY_OK;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun /**** timer functions ****/
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /* enable/disable auto resetting chip timer */
bq2415x_set_autotimer(struct bq2415x_device * bq,int state)850*4882a593Smuzhiyun static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state)
851*4882a593Smuzhiyun {
852*4882a593Smuzhiyun mutex_lock(&bq2415x_timer_mutex);
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun if (bq->autotimer == state) {
855*4882a593Smuzhiyun mutex_unlock(&bq2415x_timer_mutex);
856*4882a593Smuzhiyun return;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun bq->autotimer = state;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (state) {
862*4882a593Smuzhiyun schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
863*4882a593Smuzhiyun bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
864*4882a593Smuzhiyun bq->timer_error = NULL;
865*4882a593Smuzhiyun } else {
866*4882a593Smuzhiyun cancel_delayed_work_sync(&bq->work);
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun mutex_unlock(&bq2415x_timer_mutex);
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun /* called by bq2415x_timer_work on timer error */
bq2415x_timer_error(struct bq2415x_device * bq,const char * msg)873*4882a593Smuzhiyun static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun bq->timer_error = msg;
876*4882a593Smuzhiyun sysfs_notify(&bq->charger->dev.kobj, NULL, "timer");
877*4882a593Smuzhiyun dev_err(bq->dev, "%s\n", msg);
878*4882a593Smuzhiyun if (bq->automode > 0)
879*4882a593Smuzhiyun bq->automode = 0;
880*4882a593Smuzhiyun bq2415x_set_mode(bq, BQ2415X_MODE_OFF);
881*4882a593Smuzhiyun bq2415x_set_autotimer(bq, 0);
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun /* delayed work function for auto resetting chip timer */
bq2415x_timer_work(struct work_struct * work)885*4882a593Smuzhiyun static void bq2415x_timer_work(struct work_struct *work)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun struct bq2415x_device *bq = container_of(work, struct bq2415x_device,
888*4882a593Smuzhiyun work.work);
889*4882a593Smuzhiyun int ret;
890*4882a593Smuzhiyun int error;
891*4882a593Smuzhiyun int boost;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun if (bq->automode > 0 && (bq->reported_mode != bq->mode)) {
894*4882a593Smuzhiyun sysfs_notify(&bq->charger->dev.kobj, NULL, "reported_mode");
895*4882a593Smuzhiyun bq2415x_set_mode(bq, bq->reported_mode);
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun if (!bq->autotimer)
899*4882a593Smuzhiyun return;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
902*4882a593Smuzhiyun if (ret < 0) {
903*4882a593Smuzhiyun bq2415x_timer_error(bq, "Resetting timer failed");
904*4882a593Smuzhiyun return;
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun boost = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_STATUS);
908*4882a593Smuzhiyun if (boost < 0) {
909*4882a593Smuzhiyun bq2415x_timer_error(bq, "Unknown error");
910*4882a593Smuzhiyun return;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun error = bq2415x_exec_command(bq, BQ2415X_FAULT_STATUS);
914*4882a593Smuzhiyun if (error < 0) {
915*4882a593Smuzhiyun bq2415x_timer_error(bq, "Unknown error");
916*4882a593Smuzhiyun return;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun if (boost) {
920*4882a593Smuzhiyun switch (error) {
921*4882a593Smuzhiyun /* Non fatal errors, chip is OK */
922*4882a593Smuzhiyun case 0: /* No error */
923*4882a593Smuzhiyun break;
924*4882a593Smuzhiyun case 6: /* Timer expired */
925*4882a593Smuzhiyun dev_err(bq->dev, "Timer expired\n");
926*4882a593Smuzhiyun break;
927*4882a593Smuzhiyun case 3: /* Battery voltage too low */
928*4882a593Smuzhiyun dev_err(bq->dev, "Battery voltage to low\n");
929*4882a593Smuzhiyun break;
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun /* Fatal errors, disable and reset chip */
932*4882a593Smuzhiyun case 1: /* Overvoltage protection (chip fried) */
933*4882a593Smuzhiyun bq2415x_timer_error(bq,
934*4882a593Smuzhiyun "Overvoltage protection (chip fried)");
935*4882a593Smuzhiyun return;
936*4882a593Smuzhiyun case 2: /* Overload */
937*4882a593Smuzhiyun bq2415x_timer_error(bq, "Overload");
938*4882a593Smuzhiyun return;
939*4882a593Smuzhiyun case 4: /* Battery overvoltage protection */
940*4882a593Smuzhiyun bq2415x_timer_error(bq,
941*4882a593Smuzhiyun "Battery overvoltage protection");
942*4882a593Smuzhiyun return;
943*4882a593Smuzhiyun case 5: /* Thermal shutdown (too hot) */
944*4882a593Smuzhiyun bq2415x_timer_error(bq,
945*4882a593Smuzhiyun "Thermal shutdown (too hot)");
946*4882a593Smuzhiyun return;
947*4882a593Smuzhiyun case 7: /* N/A */
948*4882a593Smuzhiyun bq2415x_timer_error(bq, "Unknown error");
949*4882a593Smuzhiyun return;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun } else {
952*4882a593Smuzhiyun switch (error) {
953*4882a593Smuzhiyun /* Non fatal errors, chip is OK */
954*4882a593Smuzhiyun case 0: /* No error */
955*4882a593Smuzhiyun break;
956*4882a593Smuzhiyun case 2: /* Sleep mode */
957*4882a593Smuzhiyun dev_err(bq->dev, "Sleep mode\n");
958*4882a593Smuzhiyun break;
959*4882a593Smuzhiyun case 3: /* Poor input source */
960*4882a593Smuzhiyun dev_err(bq->dev, "Poor input source\n");
961*4882a593Smuzhiyun break;
962*4882a593Smuzhiyun case 6: /* Timer expired */
963*4882a593Smuzhiyun dev_err(bq->dev, "Timer expired\n");
964*4882a593Smuzhiyun break;
965*4882a593Smuzhiyun case 7: /* No battery */
966*4882a593Smuzhiyun dev_err(bq->dev, "No battery\n");
967*4882a593Smuzhiyun break;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun /* Fatal errors, disable and reset chip */
970*4882a593Smuzhiyun case 1: /* Overvoltage protection (chip fried) */
971*4882a593Smuzhiyun bq2415x_timer_error(bq,
972*4882a593Smuzhiyun "Overvoltage protection (chip fried)");
973*4882a593Smuzhiyun return;
974*4882a593Smuzhiyun case 4: /* Battery overvoltage protection */
975*4882a593Smuzhiyun bq2415x_timer_error(bq,
976*4882a593Smuzhiyun "Battery overvoltage protection");
977*4882a593Smuzhiyun return;
978*4882a593Smuzhiyun case 5: /* Thermal shutdown (too hot) */
979*4882a593Smuzhiyun bq2415x_timer_error(bq,
980*4882a593Smuzhiyun "Thermal shutdown (too hot)");
981*4882a593Smuzhiyun return;
982*4882a593Smuzhiyun }
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun /**** power supply interface code ****/
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun static enum power_supply_property bq2415x_power_supply_props[] = {
991*4882a593Smuzhiyun /* TODO: maybe add more power supply properties */
992*4882a593Smuzhiyun POWER_SUPPLY_PROP_STATUS,
993*4882a593Smuzhiyun POWER_SUPPLY_PROP_MODEL_NAME,
994*4882a593Smuzhiyun };
995*4882a593Smuzhiyun
bq2415x_power_supply_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)996*4882a593Smuzhiyun static int bq2415x_power_supply_get_property(struct power_supply *psy,
997*4882a593Smuzhiyun enum power_supply_property psp,
998*4882a593Smuzhiyun union power_supply_propval *val)
999*4882a593Smuzhiyun {
1000*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1001*4882a593Smuzhiyun int ret;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun switch (psp) {
1004*4882a593Smuzhiyun case POWER_SUPPLY_PROP_STATUS:
1005*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS);
1006*4882a593Smuzhiyun if (ret < 0)
1007*4882a593Smuzhiyun return ret;
1008*4882a593Smuzhiyun else if (ret == 0) /* Ready */
1009*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
1010*4882a593Smuzhiyun else if (ret == 1) /* Charge in progress */
1011*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_CHARGING;
1012*4882a593Smuzhiyun else if (ret == 2) /* Charge done */
1013*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_FULL;
1014*4882a593Smuzhiyun else
1015*4882a593Smuzhiyun val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
1016*4882a593Smuzhiyun break;
1017*4882a593Smuzhiyun case POWER_SUPPLY_PROP_MODEL_NAME:
1018*4882a593Smuzhiyun val->strval = bq->model;
1019*4882a593Smuzhiyun break;
1020*4882a593Smuzhiyun default:
1021*4882a593Smuzhiyun return -EINVAL;
1022*4882a593Smuzhiyun }
1023*4882a593Smuzhiyun return 0;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun
bq2415x_power_supply_exit(struct bq2415x_device * bq)1026*4882a593Smuzhiyun static void bq2415x_power_supply_exit(struct bq2415x_device *bq)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun bq->autotimer = 0;
1029*4882a593Smuzhiyun if (bq->automode > 0)
1030*4882a593Smuzhiyun bq->automode = 0;
1031*4882a593Smuzhiyun cancel_delayed_work_sync(&bq->work);
1032*4882a593Smuzhiyun power_supply_unregister(bq->charger);
1033*4882a593Smuzhiyun kfree(bq->model);
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /**** additional sysfs entries for power supply interface ****/
1037*4882a593Smuzhiyun
1038*4882a593Smuzhiyun /* show *_status entries */
bq2415x_sysfs_show_status(struct device * dev,struct device_attribute * attr,char * buf)1039*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_status(struct device *dev,
1040*4882a593Smuzhiyun struct device_attribute *attr,
1041*4882a593Smuzhiyun char *buf)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1044*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1045*4882a593Smuzhiyun enum bq2415x_command command;
1046*4882a593Smuzhiyun int ret;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun if (strcmp(attr->attr.name, "otg_status") == 0)
1049*4882a593Smuzhiyun command = BQ2415X_OTG_STATUS;
1050*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "charge_status") == 0)
1051*4882a593Smuzhiyun command = BQ2415X_CHARGE_STATUS;
1052*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "boost_status") == 0)
1053*4882a593Smuzhiyun command = BQ2415X_BOOST_STATUS;
1054*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "fault_status") == 0)
1055*4882a593Smuzhiyun command = BQ2415X_FAULT_STATUS;
1056*4882a593Smuzhiyun else
1057*4882a593Smuzhiyun return -EINVAL;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, command);
1060*4882a593Smuzhiyun if (ret < 0)
1061*4882a593Smuzhiyun return ret;
1062*4882a593Smuzhiyun return sprintf(buf, "%d\n", ret);
1063*4882a593Smuzhiyun }
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun /*
1066*4882a593Smuzhiyun * set timer entry:
1067*4882a593Smuzhiyun * auto - enable auto mode
1068*4882a593Smuzhiyun * off - disable auto mode
1069*4882a593Smuzhiyun * (other values) - reset chip timer
1070*4882a593Smuzhiyun */
bq2415x_sysfs_set_timer(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1071*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_set_timer(struct device *dev,
1072*4882a593Smuzhiyun struct device_attribute *attr,
1073*4882a593Smuzhiyun const char *buf,
1074*4882a593Smuzhiyun size_t count)
1075*4882a593Smuzhiyun {
1076*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1077*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1078*4882a593Smuzhiyun int ret = 0;
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun if (strncmp(buf, "auto", 4) == 0)
1081*4882a593Smuzhiyun bq2415x_set_autotimer(bq, 1);
1082*4882a593Smuzhiyun else if (strncmp(buf, "off", 3) == 0)
1083*4882a593Smuzhiyun bq2415x_set_autotimer(bq, 0);
1084*4882a593Smuzhiyun else
1085*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET);
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun if (ret < 0)
1088*4882a593Smuzhiyun return ret;
1089*4882a593Smuzhiyun return count;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun /* show timer entry (auto or off) */
bq2415x_sysfs_show_timer(struct device * dev,struct device_attribute * attr,char * buf)1093*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_timer(struct device *dev,
1094*4882a593Smuzhiyun struct device_attribute *attr,
1095*4882a593Smuzhiyun char *buf)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1098*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun if (bq->timer_error)
1101*4882a593Smuzhiyun return sprintf(buf, "%s\n", bq->timer_error);
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun if (bq->autotimer)
1104*4882a593Smuzhiyun return sprintf(buf, "auto\n");
1105*4882a593Smuzhiyun return sprintf(buf, "off\n");
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun /*
1109*4882a593Smuzhiyun * set mode entry:
1110*4882a593Smuzhiyun * auto - if automode is supported, enable it and set mode to reported
1111*4882a593Smuzhiyun * none - disable charger and boost mode
1112*4882a593Smuzhiyun * host - charging mode for host/hub chargers (current limit 500mA)
1113*4882a593Smuzhiyun * dedicated - charging mode for dedicated chargers (unlimited current limit)
1114*4882a593Smuzhiyun * boost - disable charger and enable boost mode
1115*4882a593Smuzhiyun */
bq2415x_sysfs_set_mode(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1116*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_set_mode(struct device *dev,
1117*4882a593Smuzhiyun struct device_attribute *attr,
1118*4882a593Smuzhiyun const char *buf,
1119*4882a593Smuzhiyun size_t count)
1120*4882a593Smuzhiyun {
1121*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1122*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1123*4882a593Smuzhiyun enum bq2415x_mode mode;
1124*4882a593Smuzhiyun int ret = 0;
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun if (strncmp(buf, "auto", 4) == 0) {
1127*4882a593Smuzhiyun if (bq->automode < 0)
1128*4882a593Smuzhiyun return -EINVAL;
1129*4882a593Smuzhiyun bq->automode = 1;
1130*4882a593Smuzhiyun mode = bq->reported_mode;
1131*4882a593Smuzhiyun } else if (strncmp(buf, "off", 3) == 0) {
1132*4882a593Smuzhiyun if (bq->automode > 0)
1133*4882a593Smuzhiyun bq->automode = 0;
1134*4882a593Smuzhiyun mode = BQ2415X_MODE_OFF;
1135*4882a593Smuzhiyun } else if (strncmp(buf, "none", 4) == 0) {
1136*4882a593Smuzhiyun if (bq->automode > 0)
1137*4882a593Smuzhiyun bq->automode = 0;
1138*4882a593Smuzhiyun mode = BQ2415X_MODE_NONE;
1139*4882a593Smuzhiyun } else if (strncmp(buf, "host", 4) == 0) {
1140*4882a593Smuzhiyun if (bq->automode > 0)
1141*4882a593Smuzhiyun bq->automode = 0;
1142*4882a593Smuzhiyun mode = BQ2415X_MODE_HOST_CHARGER;
1143*4882a593Smuzhiyun } else if (strncmp(buf, "dedicated", 9) == 0) {
1144*4882a593Smuzhiyun if (bq->automode > 0)
1145*4882a593Smuzhiyun bq->automode = 0;
1146*4882a593Smuzhiyun mode = BQ2415X_MODE_DEDICATED_CHARGER;
1147*4882a593Smuzhiyun } else if (strncmp(buf, "boost", 5) == 0) {
1148*4882a593Smuzhiyun if (bq->automode > 0)
1149*4882a593Smuzhiyun bq->automode = 0;
1150*4882a593Smuzhiyun mode = BQ2415X_MODE_BOOST;
1151*4882a593Smuzhiyun } else if (strncmp(buf, "reset", 5) == 0) {
1152*4882a593Smuzhiyun bq2415x_reset_chip(bq);
1153*4882a593Smuzhiyun bq2415x_set_defaults(bq);
1154*4882a593Smuzhiyun if (bq->automode <= 0)
1155*4882a593Smuzhiyun return count;
1156*4882a593Smuzhiyun bq->automode = 1;
1157*4882a593Smuzhiyun mode = bq->reported_mode;
1158*4882a593Smuzhiyun } else {
1159*4882a593Smuzhiyun return -EINVAL;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun ret = bq2415x_set_mode(bq, mode);
1163*4882a593Smuzhiyun if (ret < 0)
1164*4882a593Smuzhiyun return ret;
1165*4882a593Smuzhiyun return count;
1166*4882a593Smuzhiyun }
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun /* show mode entry (auto, none, host, dedicated or boost) */
bq2415x_sysfs_show_mode(struct device * dev,struct device_attribute * attr,char * buf)1169*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_mode(struct device *dev,
1170*4882a593Smuzhiyun struct device_attribute *attr,
1171*4882a593Smuzhiyun char *buf)
1172*4882a593Smuzhiyun {
1173*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1174*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1175*4882a593Smuzhiyun ssize_t ret = 0;
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun if (bq->automode > 0)
1178*4882a593Smuzhiyun ret += sprintf(buf+ret, "auto (");
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun switch (bq->mode) {
1181*4882a593Smuzhiyun case BQ2415X_MODE_OFF:
1182*4882a593Smuzhiyun ret += sprintf(buf+ret, "off");
1183*4882a593Smuzhiyun break;
1184*4882a593Smuzhiyun case BQ2415X_MODE_NONE:
1185*4882a593Smuzhiyun ret += sprintf(buf+ret, "none");
1186*4882a593Smuzhiyun break;
1187*4882a593Smuzhiyun case BQ2415X_MODE_HOST_CHARGER:
1188*4882a593Smuzhiyun ret += sprintf(buf+ret, "host");
1189*4882a593Smuzhiyun break;
1190*4882a593Smuzhiyun case BQ2415X_MODE_DEDICATED_CHARGER:
1191*4882a593Smuzhiyun ret += sprintf(buf+ret, "dedicated");
1192*4882a593Smuzhiyun break;
1193*4882a593Smuzhiyun case BQ2415X_MODE_BOOST:
1194*4882a593Smuzhiyun ret += sprintf(buf+ret, "boost");
1195*4882a593Smuzhiyun break;
1196*4882a593Smuzhiyun }
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun if (bq->automode > 0)
1199*4882a593Smuzhiyun ret += sprintf(buf+ret, ")");
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun ret += sprintf(buf+ret, "\n");
1202*4882a593Smuzhiyun return ret;
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun /* show reported_mode entry (none, host, dedicated or boost) */
bq2415x_sysfs_show_reported_mode(struct device * dev,struct device_attribute * attr,char * buf)1206*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev,
1207*4882a593Smuzhiyun struct device_attribute *attr,
1208*4882a593Smuzhiyun char *buf)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1211*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun if (bq->automode < 0)
1214*4882a593Smuzhiyun return -EINVAL;
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun switch (bq->reported_mode) {
1217*4882a593Smuzhiyun case BQ2415X_MODE_OFF:
1218*4882a593Smuzhiyun return sprintf(buf, "off\n");
1219*4882a593Smuzhiyun case BQ2415X_MODE_NONE:
1220*4882a593Smuzhiyun return sprintf(buf, "none\n");
1221*4882a593Smuzhiyun case BQ2415X_MODE_HOST_CHARGER:
1222*4882a593Smuzhiyun return sprintf(buf, "host\n");
1223*4882a593Smuzhiyun case BQ2415X_MODE_DEDICATED_CHARGER:
1224*4882a593Smuzhiyun return sprintf(buf, "dedicated\n");
1225*4882a593Smuzhiyun case BQ2415X_MODE_BOOST:
1226*4882a593Smuzhiyun return sprintf(buf, "boost\n");
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun return -EINVAL;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun /* directly set raw value to chip register, format: 'register value' */
bq2415x_sysfs_set_registers(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1233*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_set_registers(struct device *dev,
1234*4882a593Smuzhiyun struct device_attribute *attr,
1235*4882a593Smuzhiyun const char *buf,
1236*4882a593Smuzhiyun size_t count)
1237*4882a593Smuzhiyun {
1238*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1239*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1240*4882a593Smuzhiyun ssize_t ret = 0;
1241*4882a593Smuzhiyun unsigned int reg;
1242*4882a593Smuzhiyun unsigned int val;
1243*4882a593Smuzhiyun
1244*4882a593Smuzhiyun if (sscanf(buf, "%x %x", ®, &val) != 2)
1245*4882a593Smuzhiyun return -EINVAL;
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun if (reg > 4 || val > 255)
1248*4882a593Smuzhiyun return -EINVAL;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun ret = bq2415x_i2c_write(bq, reg, val);
1251*4882a593Smuzhiyun if (ret < 0)
1252*4882a593Smuzhiyun return ret;
1253*4882a593Smuzhiyun return count;
1254*4882a593Smuzhiyun }
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun /* print value of chip register, format: 'register=value' */
bq2415x_sysfs_print_reg(struct bq2415x_device * bq,u8 reg,char * buf)1257*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq,
1258*4882a593Smuzhiyun u8 reg,
1259*4882a593Smuzhiyun char *buf)
1260*4882a593Smuzhiyun {
1261*4882a593Smuzhiyun int ret = bq2415x_i2c_read(bq, reg);
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyun if (ret < 0)
1264*4882a593Smuzhiyun return sprintf(buf, "%#.2x=error %d\n", reg, ret);
1265*4882a593Smuzhiyun return sprintf(buf, "%#.2x=%#.2x\n", reg, ret);
1266*4882a593Smuzhiyun }
1267*4882a593Smuzhiyun
1268*4882a593Smuzhiyun /* show all raw values of chip register, format per line: 'register=value' */
bq2415x_sysfs_show_registers(struct device * dev,struct device_attribute * attr,char * buf)1269*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_registers(struct device *dev,
1270*4882a593Smuzhiyun struct device_attribute *attr,
1271*4882a593Smuzhiyun char *buf)
1272*4882a593Smuzhiyun {
1273*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1274*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1275*4882a593Smuzhiyun ssize_t ret = 0;
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret);
1278*4882a593Smuzhiyun ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CONTROL, buf+ret);
1279*4882a593Smuzhiyun ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VOLTAGE, buf+ret);
1280*4882a593Smuzhiyun ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VENDER, buf+ret);
1281*4882a593Smuzhiyun ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CURRENT, buf+ret);
1282*4882a593Smuzhiyun return ret;
1283*4882a593Smuzhiyun }
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun /* set current and voltage limit entries (in mA or mV) */
bq2415x_sysfs_set_limit(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1286*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_set_limit(struct device *dev,
1287*4882a593Smuzhiyun struct device_attribute *attr,
1288*4882a593Smuzhiyun const char *buf,
1289*4882a593Smuzhiyun size_t count)
1290*4882a593Smuzhiyun {
1291*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1292*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1293*4882a593Smuzhiyun long val;
1294*4882a593Smuzhiyun int ret;
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun if (kstrtol(buf, 10, &val) < 0)
1297*4882a593Smuzhiyun return -EINVAL;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun if (strcmp(attr->attr.name, "current_limit") == 0)
1300*4882a593Smuzhiyun ret = bq2415x_set_current_limit(bq, val);
1301*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
1302*4882a593Smuzhiyun ret = bq2415x_set_weak_battery_voltage(bq, val);
1303*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
1304*4882a593Smuzhiyun ret = bq2415x_set_battery_regulation_voltage(bq, val);
1305*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "charge_current") == 0)
1306*4882a593Smuzhiyun ret = bq2415x_set_charge_current(bq, val);
1307*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "termination_current") == 0)
1308*4882a593Smuzhiyun ret = bq2415x_set_termination_current(bq, val);
1309*4882a593Smuzhiyun else
1310*4882a593Smuzhiyun return -EINVAL;
1311*4882a593Smuzhiyun
1312*4882a593Smuzhiyun if (ret < 0)
1313*4882a593Smuzhiyun return ret;
1314*4882a593Smuzhiyun return count;
1315*4882a593Smuzhiyun }
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun /* show current and voltage limit entries (in mA or mV) */
bq2415x_sysfs_show_limit(struct device * dev,struct device_attribute * attr,char * buf)1318*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_limit(struct device *dev,
1319*4882a593Smuzhiyun struct device_attribute *attr,
1320*4882a593Smuzhiyun char *buf)
1321*4882a593Smuzhiyun {
1322*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1323*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1324*4882a593Smuzhiyun int ret;
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun if (strcmp(attr->attr.name, "current_limit") == 0)
1327*4882a593Smuzhiyun ret = bq2415x_get_current_limit(bq);
1328*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0)
1329*4882a593Smuzhiyun ret = bq2415x_get_weak_battery_voltage(bq);
1330*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0)
1331*4882a593Smuzhiyun ret = bq2415x_get_battery_regulation_voltage(bq);
1332*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "charge_current") == 0)
1333*4882a593Smuzhiyun ret = bq2415x_get_charge_current(bq);
1334*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "termination_current") == 0)
1335*4882a593Smuzhiyun ret = bq2415x_get_termination_current(bq);
1336*4882a593Smuzhiyun else
1337*4882a593Smuzhiyun return -EINVAL;
1338*4882a593Smuzhiyun
1339*4882a593Smuzhiyun if (ret < 0)
1340*4882a593Smuzhiyun return ret;
1341*4882a593Smuzhiyun return sprintf(buf, "%d\n", ret);
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun /* set *_enable entries */
bq2415x_sysfs_set_enable(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1345*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_set_enable(struct device *dev,
1346*4882a593Smuzhiyun struct device_attribute *attr,
1347*4882a593Smuzhiyun const char *buf,
1348*4882a593Smuzhiyun size_t count)
1349*4882a593Smuzhiyun {
1350*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1351*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1352*4882a593Smuzhiyun enum bq2415x_command command;
1353*4882a593Smuzhiyun long val;
1354*4882a593Smuzhiyun int ret;
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun if (kstrtol(buf, 10, &val) < 0)
1357*4882a593Smuzhiyun return -EINVAL;
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
1360*4882a593Smuzhiyun command = val ? BQ2415X_CHARGE_TERMINATION_ENABLE :
1361*4882a593Smuzhiyun BQ2415X_CHARGE_TERMINATION_DISABLE;
1362*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
1363*4882a593Smuzhiyun command = val ? BQ2415X_HIGH_IMPEDANCE_ENABLE :
1364*4882a593Smuzhiyun BQ2415X_HIGH_IMPEDANCE_DISABLE;
1365*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
1366*4882a593Smuzhiyun command = val ? BQ2415X_OTG_PIN_ENABLE :
1367*4882a593Smuzhiyun BQ2415X_OTG_PIN_DISABLE;
1368*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
1369*4882a593Smuzhiyun command = val ? BQ2415X_STAT_PIN_ENABLE :
1370*4882a593Smuzhiyun BQ2415X_STAT_PIN_DISABLE;
1371*4882a593Smuzhiyun else
1372*4882a593Smuzhiyun return -EINVAL;
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, command);
1375*4882a593Smuzhiyun if (ret < 0)
1376*4882a593Smuzhiyun return ret;
1377*4882a593Smuzhiyun return count;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun /* show *_enable entries */
bq2415x_sysfs_show_enable(struct device * dev,struct device_attribute * attr,char * buf)1381*4882a593Smuzhiyun static ssize_t bq2415x_sysfs_show_enable(struct device *dev,
1382*4882a593Smuzhiyun struct device_attribute *attr,
1383*4882a593Smuzhiyun char *buf)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun struct power_supply *psy = dev_get_drvdata(dev);
1386*4882a593Smuzhiyun struct bq2415x_device *bq = power_supply_get_drvdata(psy);
1387*4882a593Smuzhiyun enum bq2415x_command command;
1388*4882a593Smuzhiyun int ret;
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun if (strcmp(attr->attr.name, "charge_termination_enable") == 0)
1391*4882a593Smuzhiyun command = BQ2415X_CHARGE_TERMINATION_STATUS;
1392*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
1393*4882a593Smuzhiyun command = BQ2415X_HIGH_IMPEDANCE_STATUS;
1394*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "otg_pin_enable") == 0)
1395*4882a593Smuzhiyun command = BQ2415X_OTG_PIN_STATUS;
1396*4882a593Smuzhiyun else if (strcmp(attr->attr.name, "stat_pin_enable") == 0)
1397*4882a593Smuzhiyun command = BQ2415X_STAT_PIN_STATUS;
1398*4882a593Smuzhiyun else
1399*4882a593Smuzhiyun return -EINVAL;
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun ret = bq2415x_exec_command(bq, command);
1402*4882a593Smuzhiyun if (ret < 0)
1403*4882a593Smuzhiyun return ret;
1404*4882a593Smuzhiyun return sprintf(buf, "%d\n", ret);
1405*4882a593Smuzhiyun }
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO,
1408*4882a593Smuzhiyun bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
1409*4882a593Smuzhiyun static DEVICE_ATTR(weak_battery_voltage, S_IWUSR | S_IRUGO,
1410*4882a593Smuzhiyun bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
1411*4882a593Smuzhiyun static DEVICE_ATTR(battery_regulation_voltage, S_IWUSR | S_IRUGO,
1412*4882a593Smuzhiyun bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
1413*4882a593Smuzhiyun static DEVICE_ATTR(charge_current, S_IWUSR | S_IRUGO,
1414*4882a593Smuzhiyun bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
1415*4882a593Smuzhiyun static DEVICE_ATTR(termination_current, S_IWUSR | S_IRUGO,
1416*4882a593Smuzhiyun bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit);
1417*4882a593Smuzhiyun
1418*4882a593Smuzhiyun static DEVICE_ATTR(charge_termination_enable, S_IWUSR | S_IRUGO,
1419*4882a593Smuzhiyun bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
1420*4882a593Smuzhiyun static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO,
1421*4882a593Smuzhiyun bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
1422*4882a593Smuzhiyun static DEVICE_ATTR(otg_pin_enable, S_IWUSR | S_IRUGO,
1423*4882a593Smuzhiyun bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
1424*4882a593Smuzhiyun static DEVICE_ATTR(stat_pin_enable, S_IWUSR | S_IRUGO,
1425*4882a593Smuzhiyun bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable);
1426*4882a593Smuzhiyun
1427*4882a593Smuzhiyun static DEVICE_ATTR(reported_mode, S_IRUGO,
1428*4882a593Smuzhiyun bq2415x_sysfs_show_reported_mode, NULL);
1429*4882a593Smuzhiyun static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO,
1430*4882a593Smuzhiyun bq2415x_sysfs_show_mode, bq2415x_sysfs_set_mode);
1431*4882a593Smuzhiyun static DEVICE_ATTR(timer, S_IWUSR | S_IRUGO,
1432*4882a593Smuzhiyun bq2415x_sysfs_show_timer, bq2415x_sysfs_set_timer);
1433*4882a593Smuzhiyun
1434*4882a593Smuzhiyun static DEVICE_ATTR(registers, S_IWUSR | S_IRUGO,
1435*4882a593Smuzhiyun bq2415x_sysfs_show_registers, bq2415x_sysfs_set_registers);
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun static DEVICE_ATTR(otg_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
1438*4882a593Smuzhiyun static DEVICE_ATTR(charge_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
1439*4882a593Smuzhiyun static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
1440*4882a593Smuzhiyun static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL);
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun static struct attribute *bq2415x_sysfs_attrs[] = {
1443*4882a593Smuzhiyun /*
1444*4882a593Smuzhiyun * TODO: some (appropriate) of these attrs should be switched to
1445*4882a593Smuzhiyun * use power supply class props.
1446*4882a593Smuzhiyun */
1447*4882a593Smuzhiyun &dev_attr_current_limit.attr,
1448*4882a593Smuzhiyun &dev_attr_weak_battery_voltage.attr,
1449*4882a593Smuzhiyun &dev_attr_battery_regulation_voltage.attr,
1450*4882a593Smuzhiyun &dev_attr_charge_current.attr,
1451*4882a593Smuzhiyun &dev_attr_termination_current.attr,
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun &dev_attr_charge_termination_enable.attr,
1454*4882a593Smuzhiyun &dev_attr_high_impedance_enable.attr,
1455*4882a593Smuzhiyun &dev_attr_otg_pin_enable.attr,
1456*4882a593Smuzhiyun &dev_attr_stat_pin_enable.attr,
1457*4882a593Smuzhiyun
1458*4882a593Smuzhiyun &dev_attr_reported_mode.attr,
1459*4882a593Smuzhiyun &dev_attr_mode.attr,
1460*4882a593Smuzhiyun &dev_attr_timer.attr,
1461*4882a593Smuzhiyun
1462*4882a593Smuzhiyun &dev_attr_registers.attr,
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun &dev_attr_otg_status.attr,
1465*4882a593Smuzhiyun &dev_attr_charge_status.attr,
1466*4882a593Smuzhiyun &dev_attr_boost_status.attr,
1467*4882a593Smuzhiyun &dev_attr_fault_status.attr,
1468*4882a593Smuzhiyun NULL,
1469*4882a593Smuzhiyun };
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun ATTRIBUTE_GROUPS(bq2415x_sysfs);
1472*4882a593Smuzhiyun
bq2415x_power_supply_init(struct bq2415x_device * bq)1473*4882a593Smuzhiyun static int bq2415x_power_supply_init(struct bq2415x_device *bq)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun int ret;
1476*4882a593Smuzhiyun int chip;
1477*4882a593Smuzhiyun char revstr[8];
1478*4882a593Smuzhiyun struct power_supply_config psy_cfg = {
1479*4882a593Smuzhiyun .drv_data = bq,
1480*4882a593Smuzhiyun .of_node = bq->dev->of_node,
1481*4882a593Smuzhiyun .attr_grp = bq2415x_sysfs_groups,
1482*4882a593Smuzhiyun };
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun bq->charger_desc.name = bq->name;
1485*4882a593Smuzhiyun bq->charger_desc.type = POWER_SUPPLY_TYPE_USB;
1486*4882a593Smuzhiyun bq->charger_desc.properties = bq2415x_power_supply_props;
1487*4882a593Smuzhiyun bq->charger_desc.num_properties =
1488*4882a593Smuzhiyun ARRAY_SIZE(bq2415x_power_supply_props);
1489*4882a593Smuzhiyun bq->charger_desc.get_property = bq2415x_power_supply_get_property;
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun ret = bq2415x_detect_chip(bq);
1492*4882a593Smuzhiyun if (ret < 0)
1493*4882a593Smuzhiyun chip = BQUNKNOWN;
1494*4882a593Smuzhiyun else
1495*4882a593Smuzhiyun chip = ret;
1496*4882a593Smuzhiyun
1497*4882a593Smuzhiyun ret = bq2415x_detect_revision(bq);
1498*4882a593Smuzhiyun if (ret < 0)
1499*4882a593Smuzhiyun strcpy(revstr, "unknown");
1500*4882a593Smuzhiyun else
1501*4882a593Smuzhiyun sprintf(revstr, "1.%d", ret);
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun bq->model = kasprintf(GFP_KERNEL,
1504*4882a593Smuzhiyun "chip %s, revision %s, vender code %.3d",
1505*4882a593Smuzhiyun bq2415x_chip_name[chip], revstr,
1506*4882a593Smuzhiyun bq2415x_get_vender_code(bq));
1507*4882a593Smuzhiyun if (!bq->model) {
1508*4882a593Smuzhiyun dev_err(bq->dev, "failed to allocate model name\n");
1509*4882a593Smuzhiyun return -ENOMEM;
1510*4882a593Smuzhiyun }
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun bq->charger = power_supply_register(bq->dev, &bq->charger_desc,
1513*4882a593Smuzhiyun &psy_cfg);
1514*4882a593Smuzhiyun if (IS_ERR(bq->charger)) {
1515*4882a593Smuzhiyun kfree(bq->model);
1516*4882a593Smuzhiyun return PTR_ERR(bq->charger);
1517*4882a593Smuzhiyun }
1518*4882a593Smuzhiyun
1519*4882a593Smuzhiyun return 0;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun /* main bq2415x probe function */
bq2415x_probe(struct i2c_client * client,const struct i2c_device_id * id)1523*4882a593Smuzhiyun static int bq2415x_probe(struct i2c_client *client,
1524*4882a593Smuzhiyun const struct i2c_device_id *id)
1525*4882a593Smuzhiyun {
1526*4882a593Smuzhiyun int ret;
1527*4882a593Smuzhiyun int num;
1528*4882a593Smuzhiyun char *name = NULL;
1529*4882a593Smuzhiyun struct bq2415x_device *bq;
1530*4882a593Smuzhiyun struct device_node *np = client->dev.of_node;
1531*4882a593Smuzhiyun struct bq2415x_platform_data *pdata = client->dev.platform_data;
1532*4882a593Smuzhiyun const struct acpi_device_id *acpi_id = NULL;
1533*4882a593Smuzhiyun struct power_supply *notify_psy = NULL;
1534*4882a593Smuzhiyun union power_supply_propval prop;
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun if (!np && !pdata && !ACPI_HANDLE(&client->dev)) {
1537*4882a593Smuzhiyun dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n");
1538*4882a593Smuzhiyun return -ENODEV;
1539*4882a593Smuzhiyun }
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun /* Get new ID for the new device */
1542*4882a593Smuzhiyun mutex_lock(&bq2415x_id_mutex);
1543*4882a593Smuzhiyun num = idr_alloc(&bq2415x_id, client, 0, 0, GFP_KERNEL);
1544*4882a593Smuzhiyun mutex_unlock(&bq2415x_id_mutex);
1545*4882a593Smuzhiyun if (num < 0)
1546*4882a593Smuzhiyun return num;
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun if (id) {
1549*4882a593Smuzhiyun name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
1550*4882a593Smuzhiyun } else if (ACPI_HANDLE(&client->dev)) {
1551*4882a593Smuzhiyun acpi_id =
1552*4882a593Smuzhiyun acpi_match_device(client->dev.driver->acpi_match_table,
1553*4882a593Smuzhiyun &client->dev);
1554*4882a593Smuzhiyun if (!acpi_id) {
1555*4882a593Smuzhiyun dev_err(&client->dev, "failed to match device name\n");
1556*4882a593Smuzhiyun ret = -ENODEV;
1557*4882a593Smuzhiyun goto error_1;
1558*4882a593Smuzhiyun }
1559*4882a593Smuzhiyun name = kasprintf(GFP_KERNEL, "%s-%d", acpi_id->id, num);
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun if (!name) {
1562*4882a593Smuzhiyun dev_err(&client->dev, "failed to allocate device name\n");
1563*4882a593Smuzhiyun ret = -ENOMEM;
1564*4882a593Smuzhiyun goto error_1;
1565*4882a593Smuzhiyun }
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun bq = devm_kzalloc(&client->dev, sizeof(*bq), GFP_KERNEL);
1568*4882a593Smuzhiyun if (!bq) {
1569*4882a593Smuzhiyun ret = -ENOMEM;
1570*4882a593Smuzhiyun goto error_2;
1571*4882a593Smuzhiyun }
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun i2c_set_clientdata(client, bq);
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun bq->id = num;
1576*4882a593Smuzhiyun bq->dev = &client->dev;
1577*4882a593Smuzhiyun if (id)
1578*4882a593Smuzhiyun bq->chip = id->driver_data;
1579*4882a593Smuzhiyun else if (ACPI_HANDLE(bq->dev))
1580*4882a593Smuzhiyun bq->chip = acpi_id->driver_data;
1581*4882a593Smuzhiyun bq->name = name;
1582*4882a593Smuzhiyun bq->mode = BQ2415X_MODE_OFF;
1583*4882a593Smuzhiyun bq->reported_mode = BQ2415X_MODE_OFF;
1584*4882a593Smuzhiyun bq->autotimer = 0;
1585*4882a593Smuzhiyun bq->automode = 0;
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun if (np || ACPI_HANDLE(bq->dev)) {
1588*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1589*4882a593Smuzhiyun "ti,current-limit",
1590*4882a593Smuzhiyun &bq->init_data.current_limit);
1591*4882a593Smuzhiyun if (ret)
1592*4882a593Smuzhiyun goto error_2;
1593*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1594*4882a593Smuzhiyun "ti,weak-battery-voltage",
1595*4882a593Smuzhiyun &bq->init_data.weak_battery_voltage);
1596*4882a593Smuzhiyun if (ret)
1597*4882a593Smuzhiyun goto error_2;
1598*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1599*4882a593Smuzhiyun "ti,battery-regulation-voltage",
1600*4882a593Smuzhiyun &bq->init_data.battery_regulation_voltage);
1601*4882a593Smuzhiyun if (ret)
1602*4882a593Smuzhiyun goto error_2;
1603*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1604*4882a593Smuzhiyun "ti,charge-current",
1605*4882a593Smuzhiyun &bq->init_data.charge_current);
1606*4882a593Smuzhiyun if (ret)
1607*4882a593Smuzhiyun goto error_2;
1608*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1609*4882a593Smuzhiyun "ti,termination-current",
1610*4882a593Smuzhiyun &bq->init_data.termination_current);
1611*4882a593Smuzhiyun if (ret)
1612*4882a593Smuzhiyun goto error_2;
1613*4882a593Smuzhiyun ret = device_property_read_u32(bq->dev,
1614*4882a593Smuzhiyun "ti,resistor-sense",
1615*4882a593Smuzhiyun &bq->init_data.resistor_sense);
1616*4882a593Smuzhiyun if (ret)
1617*4882a593Smuzhiyun goto error_2;
1618*4882a593Smuzhiyun if (np)
1619*4882a593Smuzhiyun bq->notify_node = of_parse_phandle(np,
1620*4882a593Smuzhiyun "ti,usb-charger-detection", 0);
1621*4882a593Smuzhiyun } else {
1622*4882a593Smuzhiyun memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
1623*4882a593Smuzhiyun }
1624*4882a593Smuzhiyun
1625*4882a593Smuzhiyun bq2415x_reset_chip(bq);
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun ret = bq2415x_power_supply_init(bq);
1628*4882a593Smuzhiyun if (ret) {
1629*4882a593Smuzhiyun dev_err(bq->dev, "failed to register power supply: %d\n", ret);
1630*4882a593Smuzhiyun goto error_2;
1631*4882a593Smuzhiyun }
1632*4882a593Smuzhiyun
1633*4882a593Smuzhiyun ret = bq2415x_set_defaults(bq);
1634*4882a593Smuzhiyun if (ret) {
1635*4882a593Smuzhiyun dev_err(bq->dev, "failed to set default values: %d\n", ret);
1636*4882a593Smuzhiyun goto error_3;
1637*4882a593Smuzhiyun }
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun if (bq->notify_node || bq->init_data.notify_device) {
1640*4882a593Smuzhiyun bq->nb.notifier_call = bq2415x_notifier_call;
1641*4882a593Smuzhiyun ret = power_supply_reg_notifier(&bq->nb);
1642*4882a593Smuzhiyun if (ret) {
1643*4882a593Smuzhiyun dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
1644*4882a593Smuzhiyun goto error_3;
1645*4882a593Smuzhiyun }
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun bq->automode = 1;
1648*4882a593Smuzhiyun dev_info(bq->dev, "automode supported, waiting for events\n");
1649*4882a593Smuzhiyun } else {
1650*4882a593Smuzhiyun bq->automode = -1;
1651*4882a593Smuzhiyun dev_info(bq->dev, "automode not supported\n");
1652*4882a593Smuzhiyun }
1653*4882a593Smuzhiyun
1654*4882a593Smuzhiyun /* Query for initial reported_mode and set it */
1655*4882a593Smuzhiyun if (bq->nb.notifier_call) {
1656*4882a593Smuzhiyun if (np) {
1657*4882a593Smuzhiyun notify_psy = power_supply_get_by_phandle(np,
1658*4882a593Smuzhiyun "ti,usb-charger-detection");
1659*4882a593Smuzhiyun if (IS_ERR(notify_psy))
1660*4882a593Smuzhiyun notify_psy = NULL;
1661*4882a593Smuzhiyun } else if (bq->init_data.notify_device) {
1662*4882a593Smuzhiyun notify_psy = power_supply_get_by_name(
1663*4882a593Smuzhiyun bq->init_data.notify_device);
1664*4882a593Smuzhiyun }
1665*4882a593Smuzhiyun }
1666*4882a593Smuzhiyun if (notify_psy) {
1667*4882a593Smuzhiyun ret = power_supply_get_property(notify_psy,
1668*4882a593Smuzhiyun POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
1669*4882a593Smuzhiyun power_supply_put(notify_psy);
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun if (ret == 0) {
1672*4882a593Smuzhiyun bq2415x_update_reported_mode(bq, prop.intval);
1673*4882a593Smuzhiyun bq2415x_set_mode(bq, bq->reported_mode);
1674*4882a593Smuzhiyun }
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work);
1678*4882a593Smuzhiyun bq2415x_set_autotimer(bq, 1);
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun dev_info(bq->dev, "driver registered\n");
1681*4882a593Smuzhiyun return 0;
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun error_3:
1684*4882a593Smuzhiyun bq2415x_power_supply_exit(bq);
1685*4882a593Smuzhiyun error_2:
1686*4882a593Smuzhiyun if (bq)
1687*4882a593Smuzhiyun of_node_put(bq->notify_node);
1688*4882a593Smuzhiyun kfree(name);
1689*4882a593Smuzhiyun error_1:
1690*4882a593Smuzhiyun mutex_lock(&bq2415x_id_mutex);
1691*4882a593Smuzhiyun idr_remove(&bq2415x_id, num);
1692*4882a593Smuzhiyun mutex_unlock(&bq2415x_id_mutex);
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun return ret;
1695*4882a593Smuzhiyun }
1696*4882a593Smuzhiyun
1697*4882a593Smuzhiyun /* main bq2415x remove function */
1698*4882a593Smuzhiyun
bq2415x_remove(struct i2c_client * client)1699*4882a593Smuzhiyun static int bq2415x_remove(struct i2c_client *client)
1700*4882a593Smuzhiyun {
1701*4882a593Smuzhiyun struct bq2415x_device *bq = i2c_get_clientdata(client);
1702*4882a593Smuzhiyun
1703*4882a593Smuzhiyun if (bq->nb.notifier_call)
1704*4882a593Smuzhiyun power_supply_unreg_notifier(&bq->nb);
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun of_node_put(bq->notify_node);
1707*4882a593Smuzhiyun bq2415x_power_supply_exit(bq);
1708*4882a593Smuzhiyun
1709*4882a593Smuzhiyun bq2415x_reset_chip(bq);
1710*4882a593Smuzhiyun
1711*4882a593Smuzhiyun mutex_lock(&bq2415x_id_mutex);
1712*4882a593Smuzhiyun idr_remove(&bq2415x_id, bq->id);
1713*4882a593Smuzhiyun mutex_unlock(&bq2415x_id_mutex);
1714*4882a593Smuzhiyun
1715*4882a593Smuzhiyun dev_info(bq->dev, "driver unregistered\n");
1716*4882a593Smuzhiyun
1717*4882a593Smuzhiyun kfree(bq->name);
1718*4882a593Smuzhiyun
1719*4882a593Smuzhiyun return 0;
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun static const struct i2c_device_id bq2415x_i2c_id_table[] = {
1723*4882a593Smuzhiyun { "bq2415x", BQUNKNOWN },
1724*4882a593Smuzhiyun { "bq24150", BQ24150 },
1725*4882a593Smuzhiyun { "bq24150a", BQ24150A },
1726*4882a593Smuzhiyun { "bq24151", BQ24151 },
1727*4882a593Smuzhiyun { "bq24151a", BQ24151A },
1728*4882a593Smuzhiyun { "bq24152", BQ24152 },
1729*4882a593Smuzhiyun { "bq24153", BQ24153 },
1730*4882a593Smuzhiyun { "bq24153a", BQ24153A },
1731*4882a593Smuzhiyun { "bq24155", BQ24155 },
1732*4882a593Smuzhiyun { "bq24156", BQ24156 },
1733*4882a593Smuzhiyun { "bq24156a", BQ24156A },
1734*4882a593Smuzhiyun { "bq24157s", BQ24157S },
1735*4882a593Smuzhiyun { "bq24158", BQ24158 },
1736*4882a593Smuzhiyun {},
1737*4882a593Smuzhiyun };
1738*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table);
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun #ifdef CONFIG_ACPI
1741*4882a593Smuzhiyun static const struct acpi_device_id bq2415x_i2c_acpi_match[] = {
1742*4882a593Smuzhiyun { "BQ2415X", BQUNKNOWN },
1743*4882a593Smuzhiyun { "BQ241500", BQ24150 },
1744*4882a593Smuzhiyun { "BQA24150", BQ24150A },
1745*4882a593Smuzhiyun { "BQ241510", BQ24151 },
1746*4882a593Smuzhiyun { "BQA24151", BQ24151A },
1747*4882a593Smuzhiyun { "BQ241520", BQ24152 },
1748*4882a593Smuzhiyun { "BQ241530", BQ24153 },
1749*4882a593Smuzhiyun { "BQA24153", BQ24153A },
1750*4882a593Smuzhiyun { "BQ241550", BQ24155 },
1751*4882a593Smuzhiyun { "BQ241560", BQ24156 },
1752*4882a593Smuzhiyun { "BQA24156", BQ24156A },
1753*4882a593Smuzhiyun { "BQS24157", BQ24157S },
1754*4882a593Smuzhiyun { "BQ241580", BQ24158 },
1755*4882a593Smuzhiyun {},
1756*4882a593Smuzhiyun };
1757*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, bq2415x_i2c_acpi_match);
1758*4882a593Smuzhiyun #endif
1759*4882a593Smuzhiyun
1760*4882a593Smuzhiyun #ifdef CONFIG_OF
1761*4882a593Smuzhiyun static const struct of_device_id bq2415x_of_match_table[] = {
1762*4882a593Smuzhiyun { .compatible = "ti,bq24150" },
1763*4882a593Smuzhiyun { .compatible = "ti,bq24150a" },
1764*4882a593Smuzhiyun { .compatible = "ti,bq24151" },
1765*4882a593Smuzhiyun { .compatible = "ti,bq24151a" },
1766*4882a593Smuzhiyun { .compatible = "ti,bq24152" },
1767*4882a593Smuzhiyun { .compatible = "ti,bq24153" },
1768*4882a593Smuzhiyun { .compatible = "ti,bq24153a" },
1769*4882a593Smuzhiyun { .compatible = "ti,bq24155" },
1770*4882a593Smuzhiyun { .compatible = "ti,bq24156" },
1771*4882a593Smuzhiyun { .compatible = "ti,bq24156a" },
1772*4882a593Smuzhiyun { .compatible = "ti,bq24157s" },
1773*4882a593Smuzhiyun { .compatible = "ti,bq24158" },
1774*4882a593Smuzhiyun {},
1775*4882a593Smuzhiyun };
1776*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, bq2415x_of_match_table);
1777*4882a593Smuzhiyun #endif
1778*4882a593Smuzhiyun
1779*4882a593Smuzhiyun static struct i2c_driver bq2415x_driver = {
1780*4882a593Smuzhiyun .driver = {
1781*4882a593Smuzhiyun .name = "bq2415x-charger",
1782*4882a593Smuzhiyun .of_match_table = of_match_ptr(bq2415x_of_match_table),
1783*4882a593Smuzhiyun .acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match),
1784*4882a593Smuzhiyun },
1785*4882a593Smuzhiyun .probe = bq2415x_probe,
1786*4882a593Smuzhiyun .remove = bq2415x_remove,
1787*4882a593Smuzhiyun .id_table = bq2415x_i2c_id_table,
1788*4882a593Smuzhiyun };
1789*4882a593Smuzhiyun module_i2c_driver(bq2415x_driver);
1790*4882a593Smuzhiyun
1791*4882a593Smuzhiyun MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
1792*4882a593Smuzhiyun MODULE_DESCRIPTION("bq2415x charger driver");
1793*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1794