1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * 1-wire client/driver for the Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010 Indesign, LLC
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Clifton Barnes <cabarnes@indesign-llc.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Based on ds2760_battery and ds2782_battery drivers
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/param.h>
15*4882a593Smuzhiyun #include <linux/pm.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/power_supply.h>
18*4882a593Smuzhiyun #include <linux/idr.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include <linux/w1.h>
21*4882a593Smuzhiyun #include "../../w1/slaves/w1_ds2780.h"
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /* Current unit measurement in uA for a 1 milli-ohm sense resistor */
24*4882a593Smuzhiyun #define DS2780_CURRENT_UNITS 1563
25*4882a593Smuzhiyun /* Charge unit measurement in uAh for a 1 milli-ohm sense resistor */
26*4882a593Smuzhiyun #define DS2780_CHARGE_UNITS 6250
27*4882a593Smuzhiyun /* Number of bytes in user EEPROM space */
28*4882a593Smuzhiyun #define DS2780_USER_EEPROM_SIZE (DS2780_EEPROM_BLOCK0_END - \
29*4882a593Smuzhiyun DS2780_EEPROM_BLOCK0_START + 1)
30*4882a593Smuzhiyun /* Number of bytes in parameter EEPROM space */
31*4882a593Smuzhiyun #define DS2780_PARAM_EEPROM_SIZE (DS2780_EEPROM_BLOCK1_END - \
32*4882a593Smuzhiyun DS2780_EEPROM_BLOCK1_START + 1)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun struct ds2780_device_info {
35*4882a593Smuzhiyun struct device *dev;
36*4882a593Smuzhiyun struct power_supply *bat;
37*4882a593Smuzhiyun struct power_supply_desc bat_desc;
38*4882a593Smuzhiyun struct device *w1_dev;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun enum current_types {
42*4882a593Smuzhiyun CURRENT_NOW,
43*4882a593Smuzhiyun CURRENT_AVG,
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun static const char model[] = "DS2780";
47*4882a593Smuzhiyun static const char manufacturer[] = "Maxim/Dallas";
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun static inline struct ds2780_device_info *
to_ds2780_device_info(struct power_supply * psy)50*4882a593Smuzhiyun to_ds2780_device_info(struct power_supply *psy)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun return power_supply_get_drvdata(psy);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
ds2780_battery_io(struct ds2780_device_info * dev_info,char * buf,int addr,size_t count,int io)55*4882a593Smuzhiyun static inline int ds2780_battery_io(struct ds2780_device_info *dev_info,
56*4882a593Smuzhiyun char *buf, int addr, size_t count, int io)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun return w1_ds2780_io(dev_info->w1_dev, buf, addr, count, io);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
ds2780_read8(struct ds2780_device_info * dev_info,u8 * val,int addr)61*4882a593Smuzhiyun static inline int ds2780_read8(struct ds2780_device_info *dev_info, u8 *val,
62*4882a593Smuzhiyun int addr)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun return ds2780_battery_io(dev_info, val, addr, sizeof(u8), 0);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun
ds2780_read16(struct ds2780_device_info * dev_info,s16 * val,int addr)67*4882a593Smuzhiyun static int ds2780_read16(struct ds2780_device_info *dev_info, s16 *val,
68*4882a593Smuzhiyun int addr)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun int ret;
71*4882a593Smuzhiyun u8 raw[2];
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun ret = ds2780_battery_io(dev_info, raw, addr, sizeof(raw), 0);
74*4882a593Smuzhiyun if (ret < 0)
75*4882a593Smuzhiyun return ret;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun *val = (raw[0] << 8) | raw[1];
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun return 0;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
ds2780_read_block(struct ds2780_device_info * dev_info,u8 * val,int addr,size_t count)82*4882a593Smuzhiyun static inline int ds2780_read_block(struct ds2780_device_info *dev_info,
83*4882a593Smuzhiyun u8 *val, int addr, size_t count)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun return ds2780_battery_io(dev_info, val, addr, count, 0);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
ds2780_write(struct ds2780_device_info * dev_info,u8 * val,int addr,size_t count)88*4882a593Smuzhiyun static inline int ds2780_write(struct ds2780_device_info *dev_info, u8 *val,
89*4882a593Smuzhiyun int addr, size_t count)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun return ds2780_battery_io(dev_info, val, addr, count, 1);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
ds2780_store_eeprom(struct device * dev,int addr)94*4882a593Smuzhiyun static inline int ds2780_store_eeprom(struct device *dev, int addr)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_COPY_DATA);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
ds2780_recall_eeprom(struct device * dev,int addr)99*4882a593Smuzhiyun static inline int ds2780_recall_eeprom(struct device *dev, int addr)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return w1_ds2780_eeprom_cmd(dev, addr, W1_DS2780_RECALL_DATA);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
ds2780_save_eeprom(struct ds2780_device_info * dev_info,int reg)104*4882a593Smuzhiyun static int ds2780_save_eeprom(struct ds2780_device_info *dev_info, int reg)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun int ret;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun ret = ds2780_store_eeprom(dev_info->w1_dev, reg);
109*4882a593Smuzhiyun if (ret < 0)
110*4882a593Smuzhiyun return ret;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun ret = ds2780_recall_eeprom(dev_info->w1_dev, reg);
113*4882a593Smuzhiyun if (ret < 0)
114*4882a593Smuzhiyun return ret;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* Set sense resistor value in mhos */
ds2780_set_sense_register(struct ds2780_device_info * dev_info,u8 conductance)120*4882a593Smuzhiyun static int ds2780_set_sense_register(struct ds2780_device_info *dev_info,
121*4882a593Smuzhiyun u8 conductance)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun int ret;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun ret = ds2780_write(dev_info, &conductance,
126*4882a593Smuzhiyun DS2780_RSNSP_REG, sizeof(u8));
127*4882a593Smuzhiyun if (ret < 0)
128*4882a593Smuzhiyun return ret;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun return ds2780_save_eeprom(dev_info, DS2780_RSNSP_REG);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /* Get RSGAIN value from 0 to 1.999 in steps of 0.001 */
ds2780_get_rsgain_register(struct ds2780_device_info * dev_info,u16 * rsgain)134*4882a593Smuzhiyun static int ds2780_get_rsgain_register(struct ds2780_device_info *dev_info,
135*4882a593Smuzhiyun u16 *rsgain)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun return ds2780_read16(dev_info, rsgain, DS2780_RSGAIN_MSB_REG);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* Set RSGAIN value from 0 to 1.999 in steps of 0.001 */
ds2780_set_rsgain_register(struct ds2780_device_info * dev_info,u16 rsgain)141*4882a593Smuzhiyun static int ds2780_set_rsgain_register(struct ds2780_device_info *dev_info,
142*4882a593Smuzhiyun u16 rsgain)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun int ret;
145*4882a593Smuzhiyun u8 raw[] = {rsgain >> 8, rsgain & 0xFF};
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun ret = ds2780_write(dev_info, raw,
148*4882a593Smuzhiyun DS2780_RSGAIN_MSB_REG, sizeof(raw));
149*4882a593Smuzhiyun if (ret < 0)
150*4882a593Smuzhiyun return ret;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun return ds2780_save_eeprom(dev_info, DS2780_RSGAIN_MSB_REG);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
ds2780_get_voltage(struct ds2780_device_info * dev_info,int * voltage_uV)155*4882a593Smuzhiyun static int ds2780_get_voltage(struct ds2780_device_info *dev_info,
156*4882a593Smuzhiyun int *voltage_uV)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun int ret;
159*4882a593Smuzhiyun s16 voltage_raw;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /*
162*4882a593Smuzhiyun * The voltage value is located in 10 bits across the voltage MSB
163*4882a593Smuzhiyun * and LSB registers in two's complement form
164*4882a593Smuzhiyun * Sign bit of the voltage value is in bit 7 of the voltage MSB register
165*4882a593Smuzhiyun * Bits 9 - 3 of the voltage value are in bits 6 - 0 of the
166*4882a593Smuzhiyun * voltage MSB register
167*4882a593Smuzhiyun * Bits 2 - 0 of the voltage value are in bits 7 - 5 of the
168*4882a593Smuzhiyun * voltage LSB register
169*4882a593Smuzhiyun */
170*4882a593Smuzhiyun ret = ds2780_read16(dev_info, &voltage_raw,
171*4882a593Smuzhiyun DS2780_VOLT_MSB_REG);
172*4882a593Smuzhiyun if (ret < 0)
173*4882a593Smuzhiyun return ret;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /*
176*4882a593Smuzhiyun * DS2780 reports voltage in units of 4.88mV, but the battery class
177*4882a593Smuzhiyun * reports in units of uV, so convert by multiplying by 4880.
178*4882a593Smuzhiyun */
179*4882a593Smuzhiyun *voltage_uV = (voltage_raw / 32) * 4880;
180*4882a593Smuzhiyun return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
ds2780_get_temperature(struct ds2780_device_info * dev_info,int * temperature)183*4882a593Smuzhiyun static int ds2780_get_temperature(struct ds2780_device_info *dev_info,
184*4882a593Smuzhiyun int *temperature)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun int ret;
187*4882a593Smuzhiyun s16 temperature_raw;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /*
190*4882a593Smuzhiyun * The temperature value is located in 10 bits across the temperature
191*4882a593Smuzhiyun * MSB and LSB registers in two's complement form
192*4882a593Smuzhiyun * Sign bit of the temperature value is in bit 7 of the temperature
193*4882a593Smuzhiyun * MSB register
194*4882a593Smuzhiyun * Bits 9 - 3 of the temperature value are in bits 6 - 0 of the
195*4882a593Smuzhiyun * temperature MSB register
196*4882a593Smuzhiyun * Bits 2 - 0 of the temperature value are in bits 7 - 5 of the
197*4882a593Smuzhiyun * temperature LSB register
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun ret = ds2780_read16(dev_info, &temperature_raw,
200*4882a593Smuzhiyun DS2780_TEMP_MSB_REG);
201*4882a593Smuzhiyun if (ret < 0)
202*4882a593Smuzhiyun return ret;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /*
205*4882a593Smuzhiyun * Temperature is measured in units of 0.125 degrees celcius, the
206*4882a593Smuzhiyun * power_supply class measures temperature in tenths of degrees
207*4882a593Smuzhiyun * celsius. The temperature value is stored as a 10 bit number, plus
208*4882a593Smuzhiyun * sign in the upper bits of a 16 bit register.
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun *temperature = ((temperature_raw / 32) * 125) / 100;
211*4882a593Smuzhiyun return 0;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
ds2780_get_current(struct ds2780_device_info * dev_info,enum current_types type,int * current_uA)214*4882a593Smuzhiyun static int ds2780_get_current(struct ds2780_device_info *dev_info,
215*4882a593Smuzhiyun enum current_types type, int *current_uA)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun int ret, sense_res;
218*4882a593Smuzhiyun s16 current_raw;
219*4882a593Smuzhiyun u8 sense_res_raw, reg_msb;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /*
222*4882a593Smuzhiyun * The units of measurement for current are dependent on the value of
223*4882a593Smuzhiyun * the sense resistor.
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
226*4882a593Smuzhiyun if (ret < 0)
227*4882a593Smuzhiyun return ret;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun if (sense_res_raw == 0) {
230*4882a593Smuzhiyun dev_err(dev_info->dev, "sense resistor value is 0\n");
231*4882a593Smuzhiyun return -EINVAL;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun sense_res = 1000 / sense_res_raw;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (type == CURRENT_NOW)
236*4882a593Smuzhiyun reg_msb = DS2780_CURRENT_MSB_REG;
237*4882a593Smuzhiyun else if (type == CURRENT_AVG)
238*4882a593Smuzhiyun reg_msb = DS2780_IAVG_MSB_REG;
239*4882a593Smuzhiyun else
240*4882a593Smuzhiyun return -EINVAL;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /*
243*4882a593Smuzhiyun * The current value is located in 16 bits across the current MSB
244*4882a593Smuzhiyun * and LSB registers in two's complement form
245*4882a593Smuzhiyun * Sign bit of the current value is in bit 7 of the current MSB register
246*4882a593Smuzhiyun * Bits 14 - 8 of the current value are in bits 6 - 0 of the current
247*4882a593Smuzhiyun * MSB register
248*4882a593Smuzhiyun * Bits 7 - 0 of the current value are in bits 7 - 0 of the current
249*4882a593Smuzhiyun * LSB register
250*4882a593Smuzhiyun */
251*4882a593Smuzhiyun ret = ds2780_read16(dev_info, ¤t_raw, reg_msb);
252*4882a593Smuzhiyun if (ret < 0)
253*4882a593Smuzhiyun return ret;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun *current_uA = current_raw * (DS2780_CURRENT_UNITS / sense_res);
256*4882a593Smuzhiyun return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
ds2780_get_accumulated_current(struct ds2780_device_info * dev_info,int * accumulated_current)259*4882a593Smuzhiyun static int ds2780_get_accumulated_current(struct ds2780_device_info *dev_info,
260*4882a593Smuzhiyun int *accumulated_current)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun int ret, sense_res;
263*4882a593Smuzhiyun s16 current_raw;
264*4882a593Smuzhiyun u8 sense_res_raw;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /*
267*4882a593Smuzhiyun * The units of measurement for accumulated current are dependent on
268*4882a593Smuzhiyun * the value of the sense resistor.
269*4882a593Smuzhiyun */
270*4882a593Smuzhiyun ret = ds2780_read8(dev_info, &sense_res_raw, DS2780_RSNSP_REG);
271*4882a593Smuzhiyun if (ret < 0)
272*4882a593Smuzhiyun return ret;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (sense_res_raw == 0) {
275*4882a593Smuzhiyun dev_err(dev_info->dev, "sense resistor value is 0\n");
276*4882a593Smuzhiyun return -ENXIO;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun sense_res = 1000 / sense_res_raw;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /*
281*4882a593Smuzhiyun * The ACR value is located in 16 bits across the ACR MSB and
282*4882a593Smuzhiyun * LSB registers
283*4882a593Smuzhiyun * Bits 15 - 8 of the ACR value are in bits 7 - 0 of the ACR
284*4882a593Smuzhiyun * MSB register
285*4882a593Smuzhiyun * Bits 7 - 0 of the ACR value are in bits 7 - 0 of the ACR
286*4882a593Smuzhiyun * LSB register
287*4882a593Smuzhiyun */
288*4882a593Smuzhiyun ret = ds2780_read16(dev_info, ¤t_raw, DS2780_ACR_MSB_REG);
289*4882a593Smuzhiyun if (ret < 0)
290*4882a593Smuzhiyun return ret;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun *accumulated_current = current_raw * (DS2780_CHARGE_UNITS / sense_res);
293*4882a593Smuzhiyun return 0;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
ds2780_get_capacity(struct ds2780_device_info * dev_info,int * capacity)296*4882a593Smuzhiyun static int ds2780_get_capacity(struct ds2780_device_info *dev_info,
297*4882a593Smuzhiyun int *capacity)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun int ret;
300*4882a593Smuzhiyun u8 raw;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun ret = ds2780_read8(dev_info, &raw, DS2780_RARC_REG);
303*4882a593Smuzhiyun if (ret < 0)
304*4882a593Smuzhiyun return ret;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun *capacity = raw;
307*4882a593Smuzhiyun return raw;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
ds2780_get_status(struct ds2780_device_info * dev_info,int * status)310*4882a593Smuzhiyun static int ds2780_get_status(struct ds2780_device_info *dev_info, int *status)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun int ret, current_uA, capacity;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun ret = ds2780_get_current(dev_info, CURRENT_NOW, ¤t_uA);
315*4882a593Smuzhiyun if (ret < 0)
316*4882a593Smuzhiyun return ret;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun ret = ds2780_get_capacity(dev_info, &capacity);
319*4882a593Smuzhiyun if (ret < 0)
320*4882a593Smuzhiyun return ret;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if (capacity == 100)
323*4882a593Smuzhiyun *status = POWER_SUPPLY_STATUS_FULL;
324*4882a593Smuzhiyun else if (current_uA == 0)
325*4882a593Smuzhiyun *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
326*4882a593Smuzhiyun else if (current_uA < 0)
327*4882a593Smuzhiyun *status = POWER_SUPPLY_STATUS_DISCHARGING;
328*4882a593Smuzhiyun else
329*4882a593Smuzhiyun *status = POWER_SUPPLY_STATUS_CHARGING;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
ds2780_get_charge_now(struct ds2780_device_info * dev_info,int * charge_now)334*4882a593Smuzhiyun static int ds2780_get_charge_now(struct ds2780_device_info *dev_info,
335*4882a593Smuzhiyun int *charge_now)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun int ret;
338*4882a593Smuzhiyun u16 charge_raw;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /*
341*4882a593Smuzhiyun * The RAAC value is located in 16 bits across the RAAC MSB and
342*4882a593Smuzhiyun * LSB registers
343*4882a593Smuzhiyun * Bits 15 - 8 of the RAAC value are in bits 7 - 0 of the RAAC
344*4882a593Smuzhiyun * MSB register
345*4882a593Smuzhiyun * Bits 7 - 0 of the RAAC value are in bits 7 - 0 of the RAAC
346*4882a593Smuzhiyun * LSB register
347*4882a593Smuzhiyun */
348*4882a593Smuzhiyun ret = ds2780_read16(dev_info, &charge_raw, DS2780_RAAC_MSB_REG);
349*4882a593Smuzhiyun if (ret < 0)
350*4882a593Smuzhiyun return ret;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun *charge_now = charge_raw * 1600;
353*4882a593Smuzhiyun return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
ds2780_get_control_register(struct ds2780_device_info * dev_info,u8 * control_reg)356*4882a593Smuzhiyun static int ds2780_get_control_register(struct ds2780_device_info *dev_info,
357*4882a593Smuzhiyun u8 *control_reg)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun return ds2780_read8(dev_info, control_reg, DS2780_CONTROL_REG);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
ds2780_set_control_register(struct ds2780_device_info * dev_info,u8 control_reg)362*4882a593Smuzhiyun static int ds2780_set_control_register(struct ds2780_device_info *dev_info,
363*4882a593Smuzhiyun u8 control_reg)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun int ret;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun ret = ds2780_write(dev_info, &control_reg,
368*4882a593Smuzhiyun DS2780_CONTROL_REG, sizeof(u8));
369*4882a593Smuzhiyun if (ret < 0)
370*4882a593Smuzhiyun return ret;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun return ds2780_save_eeprom(dev_info, DS2780_CONTROL_REG);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
ds2780_battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)375*4882a593Smuzhiyun static int ds2780_battery_get_property(struct power_supply *psy,
376*4882a593Smuzhiyun enum power_supply_property psp,
377*4882a593Smuzhiyun union power_supply_propval *val)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int ret = 0;
380*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun switch (psp) {
383*4882a593Smuzhiyun case POWER_SUPPLY_PROP_VOLTAGE_NOW:
384*4882a593Smuzhiyun ret = ds2780_get_voltage(dev_info, &val->intval);
385*4882a593Smuzhiyun break;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun case POWER_SUPPLY_PROP_TEMP:
388*4882a593Smuzhiyun ret = ds2780_get_temperature(dev_info, &val->intval);
389*4882a593Smuzhiyun break;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun case POWER_SUPPLY_PROP_MODEL_NAME:
392*4882a593Smuzhiyun val->strval = model;
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun case POWER_SUPPLY_PROP_MANUFACTURER:
396*4882a593Smuzhiyun val->strval = manufacturer;
397*4882a593Smuzhiyun break;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CURRENT_NOW:
400*4882a593Smuzhiyun ret = ds2780_get_current(dev_info, CURRENT_NOW, &val->intval);
401*4882a593Smuzhiyun break;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CURRENT_AVG:
404*4882a593Smuzhiyun ret = ds2780_get_current(dev_info, CURRENT_AVG, &val->intval);
405*4882a593Smuzhiyun break;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun case POWER_SUPPLY_PROP_STATUS:
408*4882a593Smuzhiyun ret = ds2780_get_status(dev_info, &val->intval);
409*4882a593Smuzhiyun break;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CAPACITY:
412*4882a593Smuzhiyun ret = ds2780_get_capacity(dev_info, &val->intval);
413*4882a593Smuzhiyun break;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_COUNTER:
416*4882a593Smuzhiyun ret = ds2780_get_accumulated_current(dev_info, &val->intval);
417*4882a593Smuzhiyun break;
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun case POWER_SUPPLY_PROP_CHARGE_NOW:
420*4882a593Smuzhiyun ret = ds2780_get_charge_now(dev_info, &val->intval);
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun default:
424*4882a593Smuzhiyun ret = -EINVAL;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun return ret;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun static enum power_supply_property ds2780_battery_props[] = {
431*4882a593Smuzhiyun POWER_SUPPLY_PROP_STATUS,
432*4882a593Smuzhiyun POWER_SUPPLY_PROP_VOLTAGE_NOW,
433*4882a593Smuzhiyun POWER_SUPPLY_PROP_TEMP,
434*4882a593Smuzhiyun POWER_SUPPLY_PROP_MODEL_NAME,
435*4882a593Smuzhiyun POWER_SUPPLY_PROP_MANUFACTURER,
436*4882a593Smuzhiyun POWER_SUPPLY_PROP_CURRENT_NOW,
437*4882a593Smuzhiyun POWER_SUPPLY_PROP_CURRENT_AVG,
438*4882a593Smuzhiyun POWER_SUPPLY_PROP_CAPACITY,
439*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_COUNTER,
440*4882a593Smuzhiyun POWER_SUPPLY_PROP_CHARGE_NOW,
441*4882a593Smuzhiyun };
442*4882a593Smuzhiyun
ds2780_get_pmod_enabled(struct device * dev,struct device_attribute * attr,char * buf)443*4882a593Smuzhiyun static ssize_t ds2780_get_pmod_enabled(struct device *dev,
444*4882a593Smuzhiyun struct device_attribute *attr,
445*4882a593Smuzhiyun char *buf)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun int ret;
448*4882a593Smuzhiyun u8 control_reg;
449*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
450*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun /* Get power mode */
453*4882a593Smuzhiyun ret = ds2780_get_control_register(dev_info, &control_reg);
454*4882a593Smuzhiyun if (ret < 0)
455*4882a593Smuzhiyun return ret;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun return sprintf(buf, "%d\n",
458*4882a593Smuzhiyun !!(control_reg & DS2780_CONTROL_REG_PMOD));
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
ds2780_set_pmod_enabled(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)461*4882a593Smuzhiyun static ssize_t ds2780_set_pmod_enabled(struct device *dev,
462*4882a593Smuzhiyun struct device_attribute *attr,
463*4882a593Smuzhiyun const char *buf,
464*4882a593Smuzhiyun size_t count)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun int ret;
467*4882a593Smuzhiyun u8 control_reg, new_setting;
468*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
469*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun /* Set power mode */
472*4882a593Smuzhiyun ret = ds2780_get_control_register(dev_info, &control_reg);
473*4882a593Smuzhiyun if (ret < 0)
474*4882a593Smuzhiyun return ret;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun ret = kstrtou8(buf, 0, &new_setting);
477*4882a593Smuzhiyun if (ret < 0)
478*4882a593Smuzhiyun return ret;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if ((new_setting != 0) && (new_setting != 1)) {
481*4882a593Smuzhiyun dev_err(dev_info->dev, "Invalid pmod setting (0 or 1)\n");
482*4882a593Smuzhiyun return -EINVAL;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun if (new_setting)
486*4882a593Smuzhiyun control_reg |= DS2780_CONTROL_REG_PMOD;
487*4882a593Smuzhiyun else
488*4882a593Smuzhiyun control_reg &= ~DS2780_CONTROL_REG_PMOD;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun ret = ds2780_set_control_register(dev_info, control_reg);
491*4882a593Smuzhiyun if (ret < 0)
492*4882a593Smuzhiyun return ret;
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun return count;
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
ds2780_get_sense_resistor_value(struct device * dev,struct device_attribute * attr,char * buf)497*4882a593Smuzhiyun static ssize_t ds2780_get_sense_resistor_value(struct device *dev,
498*4882a593Smuzhiyun struct device_attribute *attr,
499*4882a593Smuzhiyun char *buf)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun int ret;
502*4882a593Smuzhiyun u8 sense_resistor;
503*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
504*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun ret = ds2780_read8(dev_info, &sense_resistor, DS2780_RSNSP_REG);
507*4882a593Smuzhiyun if (ret < 0)
508*4882a593Smuzhiyun return ret;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun ret = sprintf(buf, "%d\n", sense_resistor);
511*4882a593Smuzhiyun return ret;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun
ds2780_set_sense_resistor_value(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)514*4882a593Smuzhiyun static ssize_t ds2780_set_sense_resistor_value(struct device *dev,
515*4882a593Smuzhiyun struct device_attribute *attr,
516*4882a593Smuzhiyun const char *buf,
517*4882a593Smuzhiyun size_t count)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int ret;
520*4882a593Smuzhiyun u8 new_setting;
521*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
522*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun ret = kstrtou8(buf, 0, &new_setting);
525*4882a593Smuzhiyun if (ret < 0)
526*4882a593Smuzhiyun return ret;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun ret = ds2780_set_sense_register(dev_info, new_setting);
529*4882a593Smuzhiyun if (ret < 0)
530*4882a593Smuzhiyun return ret;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun return count;
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
ds2780_get_rsgain_setting(struct device * dev,struct device_attribute * attr,char * buf)535*4882a593Smuzhiyun static ssize_t ds2780_get_rsgain_setting(struct device *dev,
536*4882a593Smuzhiyun struct device_attribute *attr,
537*4882a593Smuzhiyun char *buf)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun int ret;
540*4882a593Smuzhiyun u16 rsgain;
541*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
542*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ret = ds2780_get_rsgain_register(dev_info, &rsgain);
545*4882a593Smuzhiyun if (ret < 0)
546*4882a593Smuzhiyun return ret;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun return sprintf(buf, "%d\n", rsgain);
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun
ds2780_set_rsgain_setting(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)551*4882a593Smuzhiyun static ssize_t ds2780_set_rsgain_setting(struct device *dev,
552*4882a593Smuzhiyun struct device_attribute *attr,
553*4882a593Smuzhiyun const char *buf,
554*4882a593Smuzhiyun size_t count)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun int ret;
557*4882a593Smuzhiyun u16 new_setting;
558*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
559*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun ret = kstrtou16(buf, 0, &new_setting);
562*4882a593Smuzhiyun if (ret < 0)
563*4882a593Smuzhiyun return ret;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun /* Gain can only be from 0 to 1.999 in steps of .001 */
566*4882a593Smuzhiyun if (new_setting > 1999) {
567*4882a593Smuzhiyun dev_err(dev_info->dev, "Invalid rsgain setting (0 - 1999)\n");
568*4882a593Smuzhiyun return -EINVAL;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun ret = ds2780_set_rsgain_register(dev_info, new_setting);
572*4882a593Smuzhiyun if (ret < 0)
573*4882a593Smuzhiyun return ret;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun return count;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
ds2780_get_pio_pin(struct device * dev,struct device_attribute * attr,char * buf)578*4882a593Smuzhiyun static ssize_t ds2780_get_pio_pin(struct device *dev,
579*4882a593Smuzhiyun struct device_attribute *attr,
580*4882a593Smuzhiyun char *buf)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun int ret;
583*4882a593Smuzhiyun u8 sfr;
584*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
585*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun ret = ds2780_read8(dev_info, &sfr, DS2780_SFR_REG);
588*4882a593Smuzhiyun if (ret < 0)
589*4882a593Smuzhiyun return ret;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun ret = sprintf(buf, "%d\n", sfr & DS2780_SFR_REG_PIOSC);
592*4882a593Smuzhiyun return ret;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
ds2780_set_pio_pin(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)595*4882a593Smuzhiyun static ssize_t ds2780_set_pio_pin(struct device *dev,
596*4882a593Smuzhiyun struct device_attribute *attr,
597*4882a593Smuzhiyun const char *buf,
598*4882a593Smuzhiyun size_t count)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun int ret;
601*4882a593Smuzhiyun u8 new_setting;
602*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
603*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun ret = kstrtou8(buf, 0, &new_setting);
606*4882a593Smuzhiyun if (ret < 0)
607*4882a593Smuzhiyun return ret;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun if ((new_setting != 0) && (new_setting != 1)) {
610*4882a593Smuzhiyun dev_err(dev_info->dev, "Invalid pio_pin setting (0 or 1)\n");
611*4882a593Smuzhiyun return -EINVAL;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun ret = ds2780_write(dev_info, &new_setting,
615*4882a593Smuzhiyun DS2780_SFR_REG, sizeof(u8));
616*4882a593Smuzhiyun if (ret < 0)
617*4882a593Smuzhiyun return ret;
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun return count;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
ds2780_read_param_eeprom_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)622*4882a593Smuzhiyun static ssize_t ds2780_read_param_eeprom_bin(struct file *filp,
623*4882a593Smuzhiyun struct kobject *kobj,
624*4882a593Smuzhiyun struct bin_attribute *bin_attr,
625*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun struct device *dev = container_of(kobj, struct device, kobj);
628*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
629*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun return ds2780_read_block(dev_info, buf,
632*4882a593Smuzhiyun DS2780_EEPROM_BLOCK1_START + off, count);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
ds2780_write_param_eeprom_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)635*4882a593Smuzhiyun static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
636*4882a593Smuzhiyun struct kobject *kobj,
637*4882a593Smuzhiyun struct bin_attribute *bin_attr,
638*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun struct device *dev = container_of(kobj, struct device, kobj);
641*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
642*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
643*4882a593Smuzhiyun int ret;
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun ret = ds2780_write(dev_info, buf,
646*4882a593Smuzhiyun DS2780_EEPROM_BLOCK1_START + off, count);
647*4882a593Smuzhiyun if (ret < 0)
648*4882a593Smuzhiyun return ret;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK1_START);
651*4882a593Smuzhiyun if (ret < 0)
652*4882a593Smuzhiyun return ret;
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun return count;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun static struct bin_attribute ds2780_param_eeprom_bin_attr = {
658*4882a593Smuzhiyun .attr = {
659*4882a593Smuzhiyun .name = "param_eeprom",
660*4882a593Smuzhiyun .mode = S_IRUGO | S_IWUSR,
661*4882a593Smuzhiyun },
662*4882a593Smuzhiyun .size = DS2780_PARAM_EEPROM_SIZE,
663*4882a593Smuzhiyun .read = ds2780_read_param_eeprom_bin,
664*4882a593Smuzhiyun .write = ds2780_write_param_eeprom_bin,
665*4882a593Smuzhiyun };
666*4882a593Smuzhiyun
ds2780_read_user_eeprom_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)667*4882a593Smuzhiyun static ssize_t ds2780_read_user_eeprom_bin(struct file *filp,
668*4882a593Smuzhiyun struct kobject *kobj,
669*4882a593Smuzhiyun struct bin_attribute *bin_attr,
670*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun struct device *dev = container_of(kobj, struct device, kobj);
673*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
674*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun return ds2780_read_block(dev_info, buf,
677*4882a593Smuzhiyun DS2780_EEPROM_BLOCK0_START + off, count);
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun
ds2780_write_user_eeprom_bin(struct file * filp,struct kobject * kobj,struct bin_attribute * bin_attr,char * buf,loff_t off,size_t count)680*4882a593Smuzhiyun static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
681*4882a593Smuzhiyun struct kobject *kobj,
682*4882a593Smuzhiyun struct bin_attribute *bin_attr,
683*4882a593Smuzhiyun char *buf, loff_t off, size_t count)
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun struct device *dev = container_of(kobj, struct device, kobj);
686*4882a593Smuzhiyun struct power_supply *psy = to_power_supply(dev);
687*4882a593Smuzhiyun struct ds2780_device_info *dev_info = to_ds2780_device_info(psy);
688*4882a593Smuzhiyun int ret;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun ret = ds2780_write(dev_info, buf,
691*4882a593Smuzhiyun DS2780_EEPROM_BLOCK0_START + off, count);
692*4882a593Smuzhiyun if (ret < 0)
693*4882a593Smuzhiyun return ret;
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun ret = ds2780_save_eeprom(dev_info, DS2780_EEPROM_BLOCK0_START);
696*4882a593Smuzhiyun if (ret < 0)
697*4882a593Smuzhiyun return ret;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun return count;
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun static struct bin_attribute ds2780_user_eeprom_bin_attr = {
703*4882a593Smuzhiyun .attr = {
704*4882a593Smuzhiyun .name = "user_eeprom",
705*4882a593Smuzhiyun .mode = S_IRUGO | S_IWUSR,
706*4882a593Smuzhiyun },
707*4882a593Smuzhiyun .size = DS2780_USER_EEPROM_SIZE,
708*4882a593Smuzhiyun .read = ds2780_read_user_eeprom_bin,
709*4882a593Smuzhiyun .write = ds2780_write_user_eeprom_bin,
710*4882a593Smuzhiyun };
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun static DEVICE_ATTR(pmod_enabled, S_IRUGO | S_IWUSR, ds2780_get_pmod_enabled,
713*4882a593Smuzhiyun ds2780_set_pmod_enabled);
714*4882a593Smuzhiyun static DEVICE_ATTR(sense_resistor_value, S_IRUGO | S_IWUSR,
715*4882a593Smuzhiyun ds2780_get_sense_resistor_value, ds2780_set_sense_resistor_value);
716*4882a593Smuzhiyun static DEVICE_ATTR(rsgain_setting, S_IRUGO | S_IWUSR, ds2780_get_rsgain_setting,
717*4882a593Smuzhiyun ds2780_set_rsgain_setting);
718*4882a593Smuzhiyun static DEVICE_ATTR(pio_pin, S_IRUGO | S_IWUSR, ds2780_get_pio_pin,
719*4882a593Smuzhiyun ds2780_set_pio_pin);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun static struct attribute *ds2780_sysfs_attrs[] = {
722*4882a593Smuzhiyun &dev_attr_pmod_enabled.attr,
723*4882a593Smuzhiyun &dev_attr_sense_resistor_value.attr,
724*4882a593Smuzhiyun &dev_attr_rsgain_setting.attr,
725*4882a593Smuzhiyun &dev_attr_pio_pin.attr,
726*4882a593Smuzhiyun NULL
727*4882a593Smuzhiyun };
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun static struct bin_attribute *ds2780_sysfs_bin_attrs[] = {
730*4882a593Smuzhiyun &ds2780_param_eeprom_bin_attr,
731*4882a593Smuzhiyun &ds2780_user_eeprom_bin_attr,
732*4882a593Smuzhiyun NULL
733*4882a593Smuzhiyun };
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun static const struct attribute_group ds2780_sysfs_group = {
736*4882a593Smuzhiyun .attrs = ds2780_sysfs_attrs,
737*4882a593Smuzhiyun .bin_attrs = ds2780_sysfs_bin_attrs,
738*4882a593Smuzhiyun };
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun static const struct attribute_group *ds2780_sysfs_groups[] = {
741*4882a593Smuzhiyun &ds2780_sysfs_group,
742*4882a593Smuzhiyun NULL,
743*4882a593Smuzhiyun };
744*4882a593Smuzhiyun
ds2780_battery_probe(struct platform_device * pdev)745*4882a593Smuzhiyun static int ds2780_battery_probe(struct platform_device *pdev)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun struct power_supply_config psy_cfg = {};
748*4882a593Smuzhiyun struct ds2780_device_info *dev_info;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun dev_info = devm_kzalloc(&pdev->dev, sizeof(*dev_info), GFP_KERNEL);
751*4882a593Smuzhiyun if (!dev_info)
752*4882a593Smuzhiyun return -ENOMEM;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun platform_set_drvdata(pdev, dev_info);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun dev_info->dev = &pdev->dev;
757*4882a593Smuzhiyun dev_info->w1_dev = pdev->dev.parent;
758*4882a593Smuzhiyun dev_info->bat_desc.name = dev_name(&pdev->dev);
759*4882a593Smuzhiyun dev_info->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
760*4882a593Smuzhiyun dev_info->bat_desc.properties = ds2780_battery_props;
761*4882a593Smuzhiyun dev_info->bat_desc.num_properties = ARRAY_SIZE(ds2780_battery_props);
762*4882a593Smuzhiyun dev_info->bat_desc.get_property = ds2780_battery_get_property;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun psy_cfg.drv_data = dev_info;
765*4882a593Smuzhiyun psy_cfg.attr_grp = ds2780_sysfs_groups;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun dev_info->bat = devm_power_supply_register(&pdev->dev,
768*4882a593Smuzhiyun &dev_info->bat_desc,
769*4882a593Smuzhiyun &psy_cfg);
770*4882a593Smuzhiyun if (IS_ERR(dev_info->bat)) {
771*4882a593Smuzhiyun dev_err(dev_info->dev, "failed to register battery\n");
772*4882a593Smuzhiyun return PTR_ERR(dev_info->bat);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun return 0;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun static struct platform_driver ds2780_battery_driver = {
779*4882a593Smuzhiyun .driver = {
780*4882a593Smuzhiyun .name = "ds2780-battery",
781*4882a593Smuzhiyun },
782*4882a593Smuzhiyun .probe = ds2780_battery_probe,
783*4882a593Smuzhiyun };
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun module_platform_driver(ds2780_battery_driver);
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun MODULE_LICENSE("GPL");
788*4882a593Smuzhiyun MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>");
789*4882a593Smuzhiyun MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauge IC driver");
790*4882a593Smuzhiyun MODULE_ALIAS("platform:ds2780-battery");
791