1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for SBS compliant Smart Battery System Managers
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * The device communicates via i2c at address 0x0a and multiplexes access to up
6*4882a593Smuzhiyun * to four smart batteries at address 0x0b.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * Via sysfs interface the online state and charge type are presented.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Datasheet SBSM: http://sbs-forum.org/specs/sbsm100b.pdf
11*4882a593Smuzhiyun * Datasheet LTC1760: http://cds.linear.com/docs/en/datasheet/1760fb.pdf
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * Karl-Heinz Schneider <karl-heinz@schneider-inet.de>
14*4882a593Smuzhiyun */
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <linux/gpio.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/i2c.h>
19*4882a593Smuzhiyun #include <linux/i2c-mux.h>
20*4882a593Smuzhiyun #include <linux/power_supply.h>
21*4882a593Smuzhiyun #include <linux/property.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define SBSM_MAX_BATS 4
24*4882a593Smuzhiyun #define SBSM_RETRY_CNT 3
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /* registers addresses */
27*4882a593Smuzhiyun #define SBSM_CMD_BATSYSSTATE 0x01
28*4882a593Smuzhiyun #define SBSM_CMD_BATSYSSTATECONT 0x02
29*4882a593Smuzhiyun #define SBSM_CMD_BATSYSINFO 0x04
30*4882a593Smuzhiyun #define SBSM_CMD_LTC 0x3c
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define SBSM_MASK_BAT_SUPPORTED GENMASK(3, 0)
33*4882a593Smuzhiyun #define SBSM_MASK_CHARGE_BAT GENMASK(7, 4)
34*4882a593Smuzhiyun #define SBSM_BIT_AC_PRESENT BIT(0)
35*4882a593Smuzhiyun #define SBSM_BIT_TURBO BIT(7)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define SBSM_SMB_BAT_OFFSET 11
38*4882a593Smuzhiyun struct sbsm_data {
39*4882a593Smuzhiyun struct i2c_client *client;
40*4882a593Smuzhiyun struct i2c_mux_core *muxc;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun struct power_supply *psy;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun u8 cur_chan; /* currently selected channel */
45*4882a593Smuzhiyun struct gpio_chip chip;
46*4882a593Smuzhiyun bool is_ltc1760; /* special capabilities */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun unsigned int supported_bats;
49*4882a593Smuzhiyun unsigned int last_state;
50*4882a593Smuzhiyun unsigned int last_state_cont;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static enum power_supply_property sbsm_props[] = {
54*4882a593Smuzhiyun POWER_SUPPLY_PROP_ONLINE,
55*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_TYPE,
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
sbsm_read_word(struct i2c_client * client,u8 address)58*4882a593Smuzhiyun static int sbsm_read_word(struct i2c_client *client, u8 address)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun int reg, retries;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
63*4882a593Smuzhiyun reg = i2c_smbus_read_word_data(client, address);
64*4882a593Smuzhiyun if (reg >= 0)
65*4882a593Smuzhiyun break;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun if (reg < 0) {
69*4882a593Smuzhiyun dev_err(&client->dev, "failed to read register 0x%02x\n",
70*4882a593Smuzhiyun address);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun return reg;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
sbsm_write_word(struct i2c_client * client,u8 address,u16 word)76*4882a593Smuzhiyun static int sbsm_write_word(struct i2c_client *client, u8 address, u16 word)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun int ret, retries;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun for (retries = SBSM_RETRY_CNT; retries > 0; retries--) {
81*4882a593Smuzhiyun ret = i2c_smbus_write_word_data(client, address, word);
82*4882a593Smuzhiyun if (ret >= 0)
83*4882a593Smuzhiyun break;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun if (ret < 0)
86*4882a593Smuzhiyun dev_err(&client->dev, "failed to write to register 0x%02x\n",
87*4882a593Smuzhiyun address);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun return ret;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
sbsm_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)92*4882a593Smuzhiyun static int sbsm_get_property(struct power_supply *psy,
93*4882a593Smuzhiyun enum power_supply_property psp,
94*4882a593Smuzhiyun union power_supply_propval *val)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun struct sbsm_data *data = power_supply_get_drvdata(psy);
97*4882a593Smuzhiyun int regval = 0;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun switch (psp) {
100*4882a593Smuzhiyun case POWER_SUPPLY_PROP_ONLINE:
101*4882a593Smuzhiyun regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATECONT);
102*4882a593Smuzhiyun if (regval < 0)
103*4882a593Smuzhiyun return regval;
104*4882a593Smuzhiyun val->intval = !!(regval & SBSM_BIT_AC_PRESENT);
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_TYPE:
108*4882a593Smuzhiyun regval = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
109*4882a593Smuzhiyun if (regval < 0)
110*4882a593Smuzhiyun return regval;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun if ((regval & SBSM_MASK_CHARGE_BAT) == 0) {
113*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
114*4882a593Smuzhiyun return 0;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (data->is_ltc1760) {
119*4882a593Smuzhiyun /* charge mode fast if turbo is active */
120*4882a593Smuzhiyun regval = sbsm_read_word(data->client, SBSM_CMD_LTC);
121*4882a593Smuzhiyun if (regval < 0)
122*4882a593Smuzhiyun return regval;
123*4882a593Smuzhiyun else if (regval & SBSM_BIT_TURBO)
124*4882a593Smuzhiyun val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun break;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun default:
129*4882a593Smuzhiyun return -EINVAL;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
sbsm_prop_is_writeable(struct power_supply * psy,enum power_supply_property psp)135*4882a593Smuzhiyun static int sbsm_prop_is_writeable(struct power_supply *psy,
136*4882a593Smuzhiyun enum power_supply_property psp)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun struct sbsm_data *data = power_supply_get_drvdata(psy);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun return (psp == POWER_SUPPLY_PROP_CHARGE_TYPE) && data->is_ltc1760;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
sbsm_set_property(struct power_supply * psy,enum power_supply_property psp,const union power_supply_propval * val)143*4882a593Smuzhiyun static int sbsm_set_property(struct power_supply *psy,
144*4882a593Smuzhiyun enum power_supply_property psp,
145*4882a593Smuzhiyun const union power_supply_propval *val)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun struct sbsm_data *data = power_supply_get_drvdata(psy);
148*4882a593Smuzhiyun int ret = -EINVAL;
149*4882a593Smuzhiyun u16 regval;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun switch (psp) {
152*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_TYPE:
153*4882a593Smuzhiyun /* write 1 to TURBO if type fast is given */
154*4882a593Smuzhiyun if (!data->is_ltc1760)
155*4882a593Smuzhiyun break;
156*4882a593Smuzhiyun regval = val->intval ==
157*4882a593Smuzhiyun POWER_SUPPLY_CHARGE_TYPE_FAST ? SBSM_BIT_TURBO : 0;
158*4882a593Smuzhiyun ret = sbsm_write_word(data->client, SBSM_CMD_LTC, regval);
159*4882a593Smuzhiyun break;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun default:
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun return ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /*
169*4882a593Smuzhiyun * Switch to battery
170*4882a593Smuzhiyun * Parameter chan is directly the content of SMB_BAT* nibble
171*4882a593Smuzhiyun */
sbsm_select(struct i2c_mux_core * muxc,u32 chan)172*4882a593Smuzhiyun static int sbsm_select(struct i2c_mux_core *muxc, u32 chan)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun struct sbsm_data *data = i2c_mux_priv(muxc);
175*4882a593Smuzhiyun struct device *dev = &data->client->dev;
176*4882a593Smuzhiyun int ret = 0;
177*4882a593Smuzhiyun u16 reg;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (data->cur_chan == chan)
180*4882a593Smuzhiyun return ret;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* chan goes from 1 ... 4 */
183*4882a593Smuzhiyun reg = BIT(SBSM_SMB_BAT_OFFSET + chan);
184*4882a593Smuzhiyun ret = sbsm_write_word(data->client, SBSM_CMD_BATSYSSTATE, reg);
185*4882a593Smuzhiyun if (ret)
186*4882a593Smuzhiyun dev_err(dev, "Failed to select channel %i\n", chan);
187*4882a593Smuzhiyun else
188*4882a593Smuzhiyun data->cur_chan = chan;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return ret;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
sbsm_gpio_get_value(struct gpio_chip * gc,unsigned int off)193*4882a593Smuzhiyun static int sbsm_gpio_get_value(struct gpio_chip *gc, unsigned int off)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun struct sbsm_data *data = gpiochip_get_data(gc);
196*4882a593Smuzhiyun int ret;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun ret = sbsm_read_word(data->client, SBSM_CMD_BATSYSSTATE);
199*4882a593Smuzhiyun if (ret < 0)
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun return ret & BIT(off);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /*
206*4882a593Smuzhiyun * This needs to be defined or the GPIO lib fails to register the pin.
207*4882a593Smuzhiyun * But the 'gpio' is always an input.
208*4882a593Smuzhiyun */
sbsm_gpio_direction_input(struct gpio_chip * gc,unsigned int off)209*4882a593Smuzhiyun static int sbsm_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun return 0;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
sbsm_do_alert(struct device * dev,void * d)214*4882a593Smuzhiyun static int sbsm_do_alert(struct device *dev, void *d)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun struct i2c_client *client = i2c_verify_client(dev);
217*4882a593Smuzhiyun struct i2c_driver *driver;
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (!client || client->addr != 0x0b)
220*4882a593Smuzhiyun return 0;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun device_lock(dev);
223*4882a593Smuzhiyun if (client->dev.driver) {
224*4882a593Smuzhiyun driver = to_i2c_driver(client->dev.driver);
225*4882a593Smuzhiyun if (driver->alert)
226*4882a593Smuzhiyun driver->alert(client, I2C_PROTOCOL_SMBUS_ALERT, 0);
227*4882a593Smuzhiyun else
228*4882a593Smuzhiyun dev_warn(&client->dev, "no driver alert()!\n");
229*4882a593Smuzhiyun } else {
230*4882a593Smuzhiyun dev_dbg(&client->dev, "alert with no driver\n");
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun device_unlock(dev);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun return -EBUSY;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
sbsm_alert(struct i2c_client * client,enum i2c_alert_protocol prot,unsigned int d)237*4882a593Smuzhiyun static void sbsm_alert(struct i2c_client *client, enum i2c_alert_protocol prot,
238*4882a593Smuzhiyun unsigned int d)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun struct sbsm_data *sbsm = i2c_get_clientdata(client);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun int ret, i, irq_bat = 0, state = 0;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATE);
245*4882a593Smuzhiyun if (ret >= 0) {
246*4882a593Smuzhiyun irq_bat = ret ^ sbsm->last_state;
247*4882a593Smuzhiyun sbsm->last_state = ret;
248*4882a593Smuzhiyun state = ret;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun ret = sbsm_read_word(sbsm->client, SBSM_CMD_BATSYSSTATECONT);
252*4882a593Smuzhiyun if ((ret >= 0) &&
253*4882a593Smuzhiyun ((ret ^ sbsm->last_state_cont) & SBSM_BIT_AC_PRESENT)) {
254*4882a593Smuzhiyun irq_bat |= sbsm->supported_bats & state;
255*4882a593Smuzhiyun power_supply_changed(sbsm->psy);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun sbsm->last_state_cont = ret;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun for (i = 0; i < SBSM_MAX_BATS; i++) {
260*4882a593Smuzhiyun if (irq_bat & BIT(i)) {
261*4882a593Smuzhiyun device_for_each_child(&sbsm->muxc->adapter[i]->dev,
262*4882a593Smuzhiyun NULL, sbsm_do_alert);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
sbsm_gpio_setup(struct sbsm_data * data)267*4882a593Smuzhiyun static int sbsm_gpio_setup(struct sbsm_data *data)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun struct gpio_chip *gc = &data->chip;
270*4882a593Smuzhiyun struct i2c_client *client = data->client;
271*4882a593Smuzhiyun struct device *dev = &client->dev;
272*4882a593Smuzhiyun int ret;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (!device_property_present(dev, "gpio-controller"))
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun ret = sbsm_read_word(client, SBSM_CMD_BATSYSSTATE);
278*4882a593Smuzhiyun if (ret < 0)
279*4882a593Smuzhiyun return ret;
280*4882a593Smuzhiyun data->last_state = ret;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun ret = sbsm_read_word(client, SBSM_CMD_BATSYSSTATECONT);
283*4882a593Smuzhiyun if (ret < 0)
284*4882a593Smuzhiyun return ret;
285*4882a593Smuzhiyun data->last_state_cont = ret;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun gc->get = sbsm_gpio_get_value;
288*4882a593Smuzhiyun gc->direction_input = sbsm_gpio_direction_input;
289*4882a593Smuzhiyun gc->can_sleep = true;
290*4882a593Smuzhiyun gc->base = -1;
291*4882a593Smuzhiyun gc->ngpio = SBSM_MAX_BATS;
292*4882a593Smuzhiyun gc->label = client->name;
293*4882a593Smuzhiyun gc->parent = dev;
294*4882a593Smuzhiyun gc->owner = THIS_MODULE;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun ret = devm_gpiochip_add_data(dev, gc, data);
297*4882a593Smuzhiyun if (ret) {
298*4882a593Smuzhiyun dev_err(dev, "devm_gpiochip_add_data failed: %d\n", ret);
299*4882a593Smuzhiyun return ret;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun return ret;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun static const struct power_supply_desc sbsm_default_psy_desc = {
306*4882a593Smuzhiyun .type = POWER_SUPPLY_TYPE_MAINS,
307*4882a593Smuzhiyun .properties = sbsm_props,
308*4882a593Smuzhiyun .num_properties = ARRAY_SIZE(sbsm_props),
309*4882a593Smuzhiyun .get_property = &sbsm_get_property,
310*4882a593Smuzhiyun .set_property = &sbsm_set_property,
311*4882a593Smuzhiyun .property_is_writeable = &sbsm_prop_is_writeable,
312*4882a593Smuzhiyun };
313*4882a593Smuzhiyun
sbsm_probe(struct i2c_client * client,const struct i2c_device_id * id)314*4882a593Smuzhiyun static int sbsm_probe(struct i2c_client *client,
315*4882a593Smuzhiyun const struct i2c_device_id *id)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun struct i2c_adapter *adapter = client->adapter;
318*4882a593Smuzhiyun struct sbsm_data *data;
319*4882a593Smuzhiyun struct device *dev = &client->dev;
320*4882a593Smuzhiyun struct power_supply_desc *psy_desc;
321*4882a593Smuzhiyun struct power_supply_config psy_cfg = {};
322*4882a593Smuzhiyun int ret = 0, i;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* Device listens only at address 0x0a */
325*4882a593Smuzhiyun if (client->addr != 0x0a)
326*4882a593Smuzhiyun return -EINVAL;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
329*4882a593Smuzhiyun return -EPFNOSUPPORT;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
332*4882a593Smuzhiyun if (!data)
333*4882a593Smuzhiyun return -ENOMEM;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun i2c_set_clientdata(client, data);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun data->client = client;
338*4882a593Smuzhiyun data->is_ltc1760 = !!strstr(id->name, "ltc1760");
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun ret = sbsm_read_word(client, SBSM_CMD_BATSYSINFO);
341*4882a593Smuzhiyun if (ret < 0)
342*4882a593Smuzhiyun return ret;
343*4882a593Smuzhiyun data->supported_bats = ret & SBSM_MASK_BAT_SUPPORTED;
344*4882a593Smuzhiyun data->muxc = i2c_mux_alloc(adapter, dev, SBSM_MAX_BATS, 0,
345*4882a593Smuzhiyun I2C_MUX_LOCKED, &sbsm_select, NULL);
346*4882a593Smuzhiyun if (!data->muxc) {
347*4882a593Smuzhiyun dev_err(dev, "failed to alloc i2c mux\n");
348*4882a593Smuzhiyun ret = -ENOMEM;
349*4882a593Smuzhiyun goto err_mux_alloc;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun data->muxc->priv = data;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun /* register muxed i2c channels. One for each supported battery */
354*4882a593Smuzhiyun for (i = 0; i < SBSM_MAX_BATS; ++i) {
355*4882a593Smuzhiyun if (data->supported_bats & BIT(i)) {
356*4882a593Smuzhiyun ret = i2c_mux_add_adapter(data->muxc, 0, i + 1, 0);
357*4882a593Smuzhiyun if (ret)
358*4882a593Smuzhiyun break;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun if (ret) {
362*4882a593Smuzhiyun dev_err(dev, "failed to register i2c mux channel %d\n", i + 1);
363*4882a593Smuzhiyun goto err_mux_register;
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun psy_desc = devm_kmemdup(dev, &sbsm_default_psy_desc,
367*4882a593Smuzhiyun sizeof(struct power_supply_desc),
368*4882a593Smuzhiyun GFP_KERNEL);
369*4882a593Smuzhiyun if (!psy_desc) {
370*4882a593Smuzhiyun ret = -ENOMEM;
371*4882a593Smuzhiyun goto err_psy;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun psy_desc->name = devm_kasprintf(dev, GFP_KERNEL, "sbsm-%s",
375*4882a593Smuzhiyun dev_name(&client->dev));
376*4882a593Smuzhiyun if (!psy_desc->name) {
377*4882a593Smuzhiyun ret = -ENOMEM;
378*4882a593Smuzhiyun goto err_psy;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun ret = sbsm_gpio_setup(data);
381*4882a593Smuzhiyun if (ret < 0)
382*4882a593Smuzhiyun goto err_psy;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun psy_cfg.drv_data = data;
385*4882a593Smuzhiyun psy_cfg.of_node = dev->of_node;
386*4882a593Smuzhiyun data->psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
387*4882a593Smuzhiyun if (IS_ERR(data->psy)) {
388*4882a593Smuzhiyun ret = PTR_ERR(data->psy);
389*4882a593Smuzhiyun dev_err(dev, "failed to register power supply %s\n",
390*4882a593Smuzhiyun psy_desc->name);
391*4882a593Smuzhiyun goto err_psy;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun return 0;
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun err_psy:
397*4882a593Smuzhiyun err_mux_register:
398*4882a593Smuzhiyun i2c_mux_del_adapters(data->muxc);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun err_mux_alloc:
401*4882a593Smuzhiyun return ret;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
sbsm_remove(struct i2c_client * client)404*4882a593Smuzhiyun static int sbsm_remove(struct i2c_client *client)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun struct sbsm_data *data = i2c_get_clientdata(client);
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun i2c_mux_del_adapters(data->muxc);
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun static const struct i2c_device_id sbsm_ids[] = {
413*4882a593Smuzhiyun { "sbs-manager", 0 },
414*4882a593Smuzhiyun { "ltc1760", 0 },
415*4882a593Smuzhiyun { }
416*4882a593Smuzhiyun };
417*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, sbsm_ids);
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun #ifdef CONFIG_OF
420*4882a593Smuzhiyun static const struct of_device_id sbsm_dt_ids[] = {
421*4882a593Smuzhiyun { .compatible = "sbs,sbs-manager" },
422*4882a593Smuzhiyun { .compatible = "lltc,ltc1760" },
423*4882a593Smuzhiyun { }
424*4882a593Smuzhiyun };
425*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, sbsm_dt_ids);
426*4882a593Smuzhiyun #endif
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun static struct i2c_driver sbsm_driver = {
429*4882a593Smuzhiyun .driver = {
430*4882a593Smuzhiyun .name = "sbsm",
431*4882a593Smuzhiyun .of_match_table = of_match_ptr(sbsm_dt_ids),
432*4882a593Smuzhiyun },
433*4882a593Smuzhiyun .probe = sbsm_probe,
434*4882a593Smuzhiyun .remove = sbsm_remove,
435*4882a593Smuzhiyun .alert = sbsm_alert,
436*4882a593Smuzhiyun .id_table = sbsm_ids
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun module_i2c_driver(sbsm_driver);
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun MODULE_LICENSE("GPL");
441*4882a593Smuzhiyun MODULE_AUTHOR("Karl-Heinz Schneider <karl-heinz@schneider-inet.de>");
442*4882a593Smuzhiyun MODULE_DESCRIPTION("SBSM Smart Battery System Manager");
443