1f059b46eSHans de Goede // SPDX-License-Identifier: GPL-2.0+
2f059b46eSHans de Goede /*
3f059b46eSHans de Goede  * Battery monitor driver for the uPI uG3105 battery monitor
4f059b46eSHans de Goede  *
5f059b46eSHans de Goede  * Note the uG3105 is not a full-featured autonomous fuel-gauge. Instead it is
6f059b46eSHans de Goede  * expected to be use in combination with some always on microcontroller reading
7f059b46eSHans de Goede  * its coulomb-counter before it can wrap (must be read every 400 seconds!).
8f059b46eSHans de Goede  *
9f059b46eSHans de Goede  * Since Linux does not monitor coulomb-counter changes while the device
10f059b46eSHans de Goede  * is off or suspended, the coulomb counter is not used atm.
11f059b46eSHans de Goede  *
12f059b46eSHans de Goede  * Possible improvements:
13f059b46eSHans de Goede  * 1. Activate commented out total_coulomb_count code
14f059b46eSHans de Goede  * 2. Reset total_coulomb_count val to 0 when the battery is as good as empty
15f059b46eSHans de Goede  *    and remember that we did this (and clear the flag for this on susp/resume)
16f059b46eSHans de Goede  * 3. When the battery is full check if the flag that we set total_coulomb_count
17f059b46eSHans de Goede  *    to when the battery was empty is set. If so we now know the capacity,
18f059b46eSHans de Goede  *    not the design, but actual capacity, of the battery
19f059b46eSHans de Goede  * 4. Add some mechanism (needs userspace help, or maybe use efivar?) to remember
20f059b46eSHans de Goede  *    the actual capacity of the battery over reboots
21f059b46eSHans de Goede  * 5. When we know the actual capacity at probe time, add energy_now and
22f059b46eSHans de Goede  *    energy_full attributes. Guess boot + resume energy_now value based on ocv
23f059b46eSHans de Goede  *    and then use total_coulomb_count to report energy_now over time, resetting
24f059b46eSHans de Goede  *    things to adjust for drift when empty/full. This should give more accurate
25f059b46eSHans de Goede  *    readings, esp. in the 30-70% range and allow userspace to estimate time
26f059b46eSHans de Goede  *    remaining till empty/full
27f059b46eSHans de Goede  * 6. Maybe unregister + reregister the psy device when we learn the actual
28f059b46eSHans de Goede  *    capacity during run-time ?
29f059b46eSHans de Goede  *
30f059b46eSHans de Goede  * The above will also require some sort of mwh_per_unit calculation. Testing
31f059b46eSHans de Goede  * has shown that an estimated 7404mWh increase of the battery's energy results
32f059b46eSHans de Goede  * in a total_coulomb_count increase of 3277 units with a 5 milli-ohm sense R.
33f059b46eSHans de Goede  *
34f059b46eSHans de Goede  * Copyright (C) 2021 Hans de Goede <hdegoede@redhat.com>
35f059b46eSHans de Goede  */
36f059b46eSHans de Goede 
37f059b46eSHans de Goede #include <linux/devm-helpers.h>
38f059b46eSHans de Goede #include <linux/module.h>
39f059b46eSHans de Goede #include <linux/mutex.h>
40f059b46eSHans de Goede #include <linux/slab.h>
41f059b46eSHans de Goede #include <linux/i2c.h>
42f059b46eSHans de Goede #include <linux/mod_devicetable.h>
43f059b46eSHans de Goede #include <linux/power_supply.h>
44f059b46eSHans de Goede #include <linux/workqueue.h>
45f059b46eSHans de Goede 
46f059b46eSHans de Goede #define UG3105_MOV_AVG_WINDOW					8
47f059b46eSHans de Goede #define UG3105_INIT_POLL_TIME					(5 * HZ)
48f059b46eSHans de Goede #define UG3105_POLL_TIME					(30 * HZ)
49f059b46eSHans de Goede #define UG3105_SETTLE_TIME					(1 * HZ)
50f059b46eSHans de Goede 
51f059b46eSHans de Goede #define UG3105_INIT_POLL_COUNT					30
52f059b46eSHans de Goede 
53f059b46eSHans de Goede #define UG3105_REG_MODE						0x00
54f059b46eSHans de Goede #define UG3105_REG_CTRL1					0x01
55f059b46eSHans de Goede #define UG3105_REG_COULOMB_CNT					0x02
56f059b46eSHans de Goede #define UG3105_REG_BAT_VOLT					0x08
57f059b46eSHans de Goede #define UG3105_REG_BAT_CURR					0x0c
58f059b46eSHans de Goede 
59f059b46eSHans de Goede #define UG3105_MODE_STANDBY					0x00
60f059b46eSHans de Goede #define UG3105_MODE_RUN						0x10
61f059b46eSHans de Goede 
62f059b46eSHans de Goede #define UG3105_CTRL1_RESET_COULOMB_CNT				0x03
63f059b46eSHans de Goede 
64f059b46eSHans de Goede #define UG3105_CURR_HYST_UA					65000
65f059b46eSHans de Goede 
66f059b46eSHans de Goede #define UG3105_LOW_BAT_UV					3700000
67f059b46eSHans de Goede #define UG3105_FULL_BAT_HYST_UV					38000
68f059b46eSHans de Goede 
69f059b46eSHans de Goede struct ug3105_chip {
70f059b46eSHans de Goede 	struct i2c_client *client;
71f059b46eSHans de Goede 	struct power_supply *psy;
72f059b46eSHans de Goede 	struct power_supply_battery_info *info;
73f059b46eSHans de Goede 	struct delayed_work work;
74f059b46eSHans de Goede 	struct mutex lock;
75f059b46eSHans de Goede 	int ocv[UG3105_MOV_AVG_WINDOW];		/* micro-volt */
76f059b46eSHans de Goede 	int intern_res[UG3105_MOV_AVG_WINDOW];	/* milli-ohm */
77f059b46eSHans de Goede 	int poll_count;
78f059b46eSHans de Goede 	int ocv_avg_index;
79f059b46eSHans de Goede 	int ocv_avg;				/* micro-volt */
80f059b46eSHans de Goede 	int intern_res_poll_count;
81f059b46eSHans de Goede 	int intern_res_avg_index;
82f059b46eSHans de Goede 	int intern_res_avg;			/* milli-ohm */
83f059b46eSHans de Goede 	int volt;				/* micro-volt */
84f059b46eSHans de Goede 	int curr;				/* micro-ampere */
85f059b46eSHans de Goede 	int total_coulomb_count;
86f059b46eSHans de Goede 	int uv_per_unit;
87f059b46eSHans de Goede 	int ua_per_unit;
88f059b46eSHans de Goede 	int status;
89f059b46eSHans de Goede 	int capacity;
90f059b46eSHans de Goede 	bool supplied;
91f059b46eSHans de Goede };
92f059b46eSHans de Goede 
ug3105_read_word(struct i2c_client * client,u8 reg)93f059b46eSHans de Goede static int ug3105_read_word(struct i2c_client *client, u8 reg)
94f059b46eSHans de Goede {
95f059b46eSHans de Goede 	int val;
96f059b46eSHans de Goede 
97f059b46eSHans de Goede 	val = i2c_smbus_read_word_data(client, reg);
98f059b46eSHans de Goede 	if (val < 0)
99f059b46eSHans de Goede 		dev_err(&client->dev, "Error reading reg 0x%02x\n", reg);
100f059b46eSHans de Goede 
101f059b46eSHans de Goede 	return val;
102f059b46eSHans de Goede }
103f059b46eSHans de Goede 
ug3105_get_status(struct ug3105_chip * chip)104f059b46eSHans de Goede static int ug3105_get_status(struct ug3105_chip *chip)
105f059b46eSHans de Goede {
106f059b46eSHans de Goede 	int full = chip->info->constant_charge_voltage_max_uv - UG3105_FULL_BAT_HYST_UV;
107f059b46eSHans de Goede 
108f059b46eSHans de Goede 	if (chip->curr > UG3105_CURR_HYST_UA)
109f059b46eSHans de Goede 		return POWER_SUPPLY_STATUS_CHARGING;
110f059b46eSHans de Goede 
111f059b46eSHans de Goede 	if (chip->curr < -UG3105_CURR_HYST_UA)
112f059b46eSHans de Goede 		return POWER_SUPPLY_STATUS_DISCHARGING;
113f059b46eSHans de Goede 
114f059b46eSHans de Goede 	if (chip->supplied && chip->ocv_avg > full)
115f059b46eSHans de Goede 		return POWER_SUPPLY_STATUS_FULL;
116f059b46eSHans de Goede 
117f059b46eSHans de Goede 	return POWER_SUPPLY_STATUS_NOT_CHARGING;
118f059b46eSHans de Goede }
119f059b46eSHans de Goede 
ug3105_get_capacity(struct ug3105_chip * chip)120f059b46eSHans de Goede static int ug3105_get_capacity(struct ug3105_chip *chip)
121f059b46eSHans de Goede {
122f059b46eSHans de Goede 	/*
123f059b46eSHans de Goede 	 * OCV voltages in uV for 0-110% in 5% increments, the 100-110% is
124f059b46eSHans de Goede 	 * for LiPo HV (High-Voltage) bateries which can go up to 4.35V
125f059b46eSHans de Goede 	 * instead of the usual 4.2V.
126f059b46eSHans de Goede 	 */
127f059b46eSHans de Goede 	static const int ocv_capacity_tbl[23] = {
128f059b46eSHans de Goede 		3350000,
129f059b46eSHans de Goede 		3610000,
130f059b46eSHans de Goede 		3690000,
131f059b46eSHans de Goede 		3710000,
132f059b46eSHans de Goede 		3730000,
133f059b46eSHans de Goede 		3750000,
134f059b46eSHans de Goede 		3770000,
135f059b46eSHans de Goede 		3786667,
136f059b46eSHans de Goede 		3803333,
137f059b46eSHans de Goede 		3820000,
138f059b46eSHans de Goede 		3836667,
139f059b46eSHans de Goede 		3853333,
140f059b46eSHans de Goede 		3870000,
141f059b46eSHans de Goede 		3907500,
142f059b46eSHans de Goede 		3945000,
143f059b46eSHans de Goede 		3982500,
144f059b46eSHans de Goede 		4020000,
145f059b46eSHans de Goede 		4075000,
146f059b46eSHans de Goede 		4110000,
147f059b46eSHans de Goede 		4150000,
148f059b46eSHans de Goede 		4200000,
149f059b46eSHans de Goede 		4250000,
150f059b46eSHans de Goede 		4300000,
151f059b46eSHans de Goede 	};
152f059b46eSHans de Goede 	int i, ocv_diff, ocv_step;
153f059b46eSHans de Goede 
154f059b46eSHans de Goede 	if (chip->ocv_avg < ocv_capacity_tbl[0])
155f059b46eSHans de Goede 		return 0;
156f059b46eSHans de Goede 
157f059b46eSHans de Goede 	if (chip->status == POWER_SUPPLY_STATUS_FULL)
158f059b46eSHans de Goede 		return 100;
159f059b46eSHans de Goede 
160f059b46eSHans de Goede 	for (i = 1; i < ARRAY_SIZE(ocv_capacity_tbl); i++) {
161f059b46eSHans de Goede 		if (chip->ocv_avg > ocv_capacity_tbl[i])
162f059b46eSHans de Goede 			continue;
163f059b46eSHans de Goede 
164f059b46eSHans de Goede 		ocv_diff = ocv_capacity_tbl[i] - chip->ocv_avg;
165f059b46eSHans de Goede 		ocv_step = ocv_capacity_tbl[i] - ocv_capacity_tbl[i - 1];
166f059b46eSHans de Goede 		/* scale 0-110% down to 0-100% for LiPo HV */
167f059b46eSHans de Goede 		if (chip->info->constant_charge_voltage_max_uv >= 4300000)
168f059b46eSHans de Goede 			return (i * 500 - ocv_diff * 500 / ocv_step) / 110;
169f059b46eSHans de Goede 		else
170f059b46eSHans de Goede 			return i * 5 - ocv_diff * 5 / ocv_step;
171f059b46eSHans de Goede 	}
172f059b46eSHans de Goede 
173f059b46eSHans de Goede 	return 100;
174f059b46eSHans de Goede }
175f059b46eSHans de Goede 
ug3105_work(struct work_struct * work)176f059b46eSHans de Goede static void ug3105_work(struct work_struct *work)
177f059b46eSHans de Goede {
178f059b46eSHans de Goede 	struct ug3105_chip *chip = container_of(work, struct ug3105_chip,
179f059b46eSHans de Goede 						work.work);
180f059b46eSHans de Goede 	int i, val, curr_diff, volt_diff, res, win_size;
181f059b46eSHans de Goede 	bool prev_supplied = chip->supplied;
182f059b46eSHans de Goede 	int prev_status = chip->status;
183f059b46eSHans de Goede 	int prev_volt = chip->volt;
184f059b46eSHans de Goede 	int prev_curr = chip->curr;
185f059b46eSHans de Goede 	struct power_supply *psy;
186f059b46eSHans de Goede 
187f059b46eSHans de Goede 	mutex_lock(&chip->lock);
188f059b46eSHans de Goede 
189f059b46eSHans de Goede 	psy = chip->psy;
190f059b46eSHans de Goede 	if (!psy)
191f059b46eSHans de Goede 		goto out;
192f059b46eSHans de Goede 
193f059b46eSHans de Goede 	val = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
194f059b46eSHans de Goede 	if (val < 0)
195f059b46eSHans de Goede 		goto out;
196f059b46eSHans de Goede 	chip->volt = val * chip->uv_per_unit;
197f059b46eSHans de Goede 
198f059b46eSHans de Goede 	val = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
199f059b46eSHans de Goede 	if (val < 0)
200f059b46eSHans de Goede 		goto out;
201f059b46eSHans de Goede 	chip->curr = (s16)val * chip->ua_per_unit;
202f059b46eSHans de Goede 
203f059b46eSHans de Goede 	chip->ocv[chip->ocv_avg_index] =
204f059b46eSHans de Goede 		chip->volt - chip->curr * chip->intern_res_avg / 1000;
205f059b46eSHans de Goede 	chip->ocv_avg_index = (chip->ocv_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
206f059b46eSHans de Goede 	chip->poll_count++;
207f059b46eSHans de Goede 
208f059b46eSHans de Goede 	/*
209f059b46eSHans de Goede 	 * See possible improvements comment above.
210f059b46eSHans de Goede 	 *
211f059b46eSHans de Goede 	 * Read + reset coulomb counter every 10 polls (every 300 seconds)
212f059b46eSHans de Goede 	 * if ((chip->poll_count % 10) == 0) {
213f059b46eSHans de Goede 	 *	val = ug3105_read_word(chip->client, UG3105_REG_COULOMB_CNT);
214f059b46eSHans de Goede 	 *	if (val < 0)
215f059b46eSHans de Goede 	 *		goto out;
216f059b46eSHans de Goede 	 *
217f059b46eSHans de Goede 	 *	i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1,
218f059b46eSHans de Goede 	 *				  UG3105_CTRL1_RESET_COULOMB_CNT);
219f059b46eSHans de Goede 	 *
220f059b46eSHans de Goede 	 *	chip->total_coulomb_count += (s16)val;
221f059b46eSHans de Goede 	 *	dev_dbg(&chip->client->dev, "coulomb count %d total %d\n",
222f059b46eSHans de Goede 	 *		(s16)val, chip->total_coulomb_count);
223f059b46eSHans de Goede 	 * }
224f059b46eSHans de Goede 	 */
225f059b46eSHans de Goede 
226f059b46eSHans de Goede 	chip->ocv_avg = 0;
227f059b46eSHans de Goede 	win_size = min(chip->poll_count, UG3105_MOV_AVG_WINDOW);
228f059b46eSHans de Goede 	for (i = 0; i < win_size; i++)
229f059b46eSHans de Goede 		chip->ocv_avg += chip->ocv[i];
230f059b46eSHans de Goede 	chip->ocv_avg /= win_size;
231f059b46eSHans de Goede 
232f059b46eSHans de Goede 	chip->supplied = power_supply_am_i_supplied(psy);
233f059b46eSHans de Goede 	chip->status = ug3105_get_status(chip);
234f059b46eSHans de Goede 	chip->capacity = ug3105_get_capacity(chip);
235f059b46eSHans de Goede 
236f059b46eSHans de Goede 	/*
237f059b46eSHans de Goede 	 * Skip internal resistance calc on charger [un]plug and
238f059b46eSHans de Goede 	 * when the battery is almost empty (voltage low).
239f059b46eSHans de Goede 	 */
240f059b46eSHans de Goede 	if (chip->supplied != prev_supplied ||
241f059b46eSHans de Goede 	    chip->volt < UG3105_LOW_BAT_UV ||
242f059b46eSHans de Goede 	    chip->poll_count < 2)
243f059b46eSHans de Goede 		goto out;
244f059b46eSHans de Goede 
245f059b46eSHans de Goede 	/*
246f059b46eSHans de Goede 	 * Assuming that the OCV voltage does not change significantly
247f059b46eSHans de Goede 	 * between 2 polls, then we can calculate the internal resistance
248f059b46eSHans de Goede 	 * on a significant current change by attributing all voltage
249f059b46eSHans de Goede 	 * change between the 2 readings to the internal resistance.
250f059b46eSHans de Goede 	 */
251f059b46eSHans de Goede 	curr_diff = abs(chip->curr - prev_curr);
252f059b46eSHans de Goede 	if (curr_diff < UG3105_CURR_HYST_UA)
253f059b46eSHans de Goede 		goto out;
254f059b46eSHans de Goede 
255f059b46eSHans de Goede 	volt_diff = abs(chip->volt - prev_volt);
256f059b46eSHans de Goede 	res = volt_diff * 1000 / curr_diff;
257f059b46eSHans de Goede 
258f059b46eSHans de Goede 	if ((res < (chip->intern_res_avg * 2 / 3)) ||
259f059b46eSHans de Goede 	    (res > (chip->intern_res_avg * 4 / 3))) {
260f059b46eSHans de Goede 		dev_dbg(&chip->client->dev, "Ignoring outlier internal resistance %d mOhm\n", res);
261f059b46eSHans de Goede 		goto out;
262f059b46eSHans de Goede 	}
263f059b46eSHans de Goede 
264f059b46eSHans de Goede 	dev_dbg(&chip->client->dev, "Internal resistance %d mOhm\n", res);
265f059b46eSHans de Goede 
266f059b46eSHans de Goede 	chip->intern_res[chip->intern_res_avg_index] = res;
267f059b46eSHans de Goede 	chip->intern_res_avg_index = (chip->intern_res_avg_index + 1) % UG3105_MOV_AVG_WINDOW;
268f059b46eSHans de Goede 	chip->intern_res_poll_count++;
269f059b46eSHans de Goede 
270f059b46eSHans de Goede 	chip->intern_res_avg = 0;
271f059b46eSHans de Goede 	win_size = min(chip->intern_res_poll_count, UG3105_MOV_AVG_WINDOW);
272f059b46eSHans de Goede 	for (i = 0; i < win_size; i++)
273f059b46eSHans de Goede 		chip->intern_res_avg += chip->intern_res[i];
274f059b46eSHans de Goede 	chip->intern_res_avg /= win_size;
275f059b46eSHans de Goede 
276f059b46eSHans de Goede out:
277f059b46eSHans de Goede 	mutex_unlock(&chip->lock);
278f059b46eSHans de Goede 
279f059b46eSHans de Goede 	queue_delayed_work(system_wq, &chip->work,
280f059b46eSHans de Goede 			   (chip->poll_count <= UG3105_INIT_POLL_COUNT) ?
281f059b46eSHans de Goede 					UG3105_INIT_POLL_TIME : UG3105_POLL_TIME);
282f059b46eSHans de Goede 
283f059b46eSHans de Goede 	if (chip->status != prev_status && psy)
284f059b46eSHans de Goede 		power_supply_changed(psy);
285f059b46eSHans de Goede }
286f059b46eSHans de Goede 
287f059b46eSHans de Goede static enum power_supply_property ug3105_battery_props[] = {
288f059b46eSHans de Goede 	POWER_SUPPLY_PROP_STATUS,
289f059b46eSHans de Goede 	POWER_SUPPLY_PROP_PRESENT,
290f059b46eSHans de Goede 	POWER_SUPPLY_PROP_TECHNOLOGY,
291f059b46eSHans de Goede 	POWER_SUPPLY_PROP_SCOPE,
292f059b46eSHans de Goede 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
293f059b46eSHans de Goede 	POWER_SUPPLY_PROP_VOLTAGE_OCV,
294f059b46eSHans de Goede 	POWER_SUPPLY_PROP_CURRENT_NOW,
295f059b46eSHans de Goede 	POWER_SUPPLY_PROP_CAPACITY,
296f059b46eSHans de Goede };
297f059b46eSHans de Goede 
ug3105_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)298f059b46eSHans de Goede static int ug3105_get_property(struct power_supply *psy,
299f059b46eSHans de Goede 			       enum power_supply_property psp,
300f059b46eSHans de Goede 			       union power_supply_propval *val)
301f059b46eSHans de Goede {
302f059b46eSHans de Goede 	struct ug3105_chip *chip = power_supply_get_drvdata(psy);
303f059b46eSHans de Goede 	int ret = 0;
304f059b46eSHans de Goede 
305f059b46eSHans de Goede 	mutex_lock(&chip->lock);
306f059b46eSHans de Goede 
307f059b46eSHans de Goede 	if (!chip->psy) {
308f059b46eSHans de Goede 		ret = -EAGAIN;
309f059b46eSHans de Goede 		goto out;
310f059b46eSHans de Goede 	}
311f059b46eSHans de Goede 
312f059b46eSHans de Goede 	switch (psp) {
313f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_STATUS:
314f059b46eSHans de Goede 		val->intval = chip->status;
315f059b46eSHans de Goede 		break;
316f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_PRESENT:
317f059b46eSHans de Goede 		val->intval = 1;
318f059b46eSHans de Goede 		break;
319f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_TECHNOLOGY:
320f059b46eSHans de Goede 		val->intval = chip->info->technology;
321f059b46eSHans de Goede 		break;
322f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_SCOPE:
323f059b46eSHans de Goede 		val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
324f059b46eSHans de Goede 		break;
325f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
326f059b46eSHans de Goede 		ret = ug3105_read_word(chip->client, UG3105_REG_BAT_VOLT);
327f059b46eSHans de Goede 		if (ret < 0)
328f059b46eSHans de Goede 			break;
329f059b46eSHans de Goede 		val->intval = ret * chip->uv_per_unit;
330f059b46eSHans de Goede 		ret = 0;
331f059b46eSHans de Goede 		break;
332f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_VOLTAGE_OCV:
333f059b46eSHans de Goede 		val->intval = chip->ocv_avg;
334f059b46eSHans de Goede 		break;
335f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_CURRENT_NOW:
336f059b46eSHans de Goede 		ret = ug3105_read_word(chip->client, UG3105_REG_BAT_CURR);
337f059b46eSHans de Goede 		if (ret < 0)
338f059b46eSHans de Goede 			break;
339f059b46eSHans de Goede 		val->intval = (s16)ret * chip->ua_per_unit;
340f059b46eSHans de Goede 		ret = 0;
341f059b46eSHans de Goede 		break;
342f059b46eSHans de Goede 	case POWER_SUPPLY_PROP_CAPACITY:
343f059b46eSHans de Goede 		val->intval = chip->capacity;
344f059b46eSHans de Goede 		break;
345f059b46eSHans de Goede 	default:
346f059b46eSHans de Goede 		ret = -EINVAL;
347f059b46eSHans de Goede 	}
348f059b46eSHans de Goede 
349f059b46eSHans de Goede out:
350f059b46eSHans de Goede 	mutex_unlock(&chip->lock);
351f059b46eSHans de Goede 	return ret;
352f059b46eSHans de Goede }
353f059b46eSHans de Goede 
ug3105_external_power_changed(struct power_supply * psy)354f059b46eSHans de Goede static void ug3105_external_power_changed(struct power_supply *psy)
355f059b46eSHans de Goede {
356f059b46eSHans de Goede 	struct ug3105_chip *chip = power_supply_get_drvdata(psy);
357f059b46eSHans de Goede 
358f059b46eSHans de Goede 	dev_dbg(&chip->client->dev, "external power changed\n");
359f059b46eSHans de Goede 	mod_delayed_work(system_wq, &chip->work, UG3105_SETTLE_TIME);
360f059b46eSHans de Goede }
361f059b46eSHans de Goede 
362f059b46eSHans de Goede static const struct power_supply_desc ug3105_psy_desc = {
363f059b46eSHans de Goede 	.name		= "ug3105_battery",
364f059b46eSHans de Goede 	.type		= POWER_SUPPLY_TYPE_BATTERY,
365f059b46eSHans de Goede 	.get_property	= ug3105_get_property,
366f059b46eSHans de Goede 	.external_power_changed	= ug3105_external_power_changed,
367f059b46eSHans de Goede 	.properties	= ug3105_battery_props,
368f059b46eSHans de Goede 	.num_properties	= ARRAY_SIZE(ug3105_battery_props),
369f059b46eSHans de Goede };
370f059b46eSHans de Goede 
ug3105_init(struct ug3105_chip * chip)371f059b46eSHans de Goede static void ug3105_init(struct ug3105_chip *chip)
372f059b46eSHans de Goede {
373f059b46eSHans de Goede 	chip->poll_count = 0;
374f059b46eSHans de Goede 	chip->ocv_avg_index = 0;
375f059b46eSHans de Goede 	chip->total_coulomb_count = 0;
376f059b46eSHans de Goede 	i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
377f059b46eSHans de Goede 				  UG3105_MODE_RUN);
378f059b46eSHans de Goede 	i2c_smbus_write_byte_data(chip->client, UG3105_REG_CTRL1,
379f059b46eSHans de Goede 				  UG3105_CTRL1_RESET_COULOMB_CNT);
380f059b46eSHans de Goede 	queue_delayed_work(system_wq, &chip->work, 0);
381f059b46eSHans de Goede 	flush_delayed_work(&chip->work);
382f059b46eSHans de Goede }
383f059b46eSHans de Goede 
ug3105_probe(struct i2c_client * client)384f059b46eSHans de Goede static int ug3105_probe(struct i2c_client *client)
385f059b46eSHans de Goede {
386f059b46eSHans de Goede 	struct power_supply_config psy_cfg = {};
387f059b46eSHans de Goede 	struct device *dev = &client->dev;
388f059b46eSHans de Goede 	u32 curr_sense_res_uohm = 10000;
389f059b46eSHans de Goede 	struct power_supply *psy;
390f059b46eSHans de Goede 	struct ug3105_chip *chip;
391f059b46eSHans de Goede 	int ret;
392f059b46eSHans de Goede 
393f059b46eSHans de Goede 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
394f059b46eSHans de Goede 	if (!chip)
395f059b46eSHans de Goede 		return -ENOMEM;
396f059b46eSHans de Goede 
397f059b46eSHans de Goede 	chip->client = client;
398f059b46eSHans de Goede 	mutex_init(&chip->lock);
399f059b46eSHans de Goede 	ret = devm_delayed_work_autocancel(dev, &chip->work, ug3105_work);
400f059b46eSHans de Goede 	if (ret)
401f059b46eSHans de Goede 		return ret;
402f059b46eSHans de Goede 
403f059b46eSHans de Goede 	psy_cfg.drv_data = chip;
404f059b46eSHans de Goede 	psy = devm_power_supply_register(dev, &ug3105_psy_desc, &psy_cfg);
405f059b46eSHans de Goede 	if (IS_ERR(psy))
406f059b46eSHans de Goede 		return PTR_ERR(psy);
407f059b46eSHans de Goede 
408f059b46eSHans de Goede 	ret = power_supply_get_battery_info(psy, &chip->info);
409f059b46eSHans de Goede 	if (ret)
410f059b46eSHans de Goede 		return ret;
411f059b46eSHans de Goede 
412f059b46eSHans de Goede 	if (chip->info->factory_internal_resistance_uohm == -EINVAL ||
413f059b46eSHans de Goede 	    chip->info->constant_charge_voltage_max_uv == -EINVAL) {
414f059b46eSHans de Goede 		dev_err(dev, "error required properties are missing\n");
415f059b46eSHans de Goede 		return -ENODEV;
416f059b46eSHans de Goede 	}
417f059b46eSHans de Goede 
418f059b46eSHans de Goede 	device_property_read_u32(dev, "upisemi,rsns-microohm", &curr_sense_res_uohm);
419f059b46eSHans de Goede 
420f059b46eSHans de Goede 	/*
421f059b46eSHans de Goede 	 * DAC maximum is 4.5V divided by 65536 steps + an unknown factor of 10
422f059b46eSHans de Goede 	 * coming from somewhere for some reason (verified with a volt-meter).
423f059b46eSHans de Goede 	 */
424f059b46eSHans de Goede 	chip->uv_per_unit = 45000000/65536;
425f059b46eSHans de Goede 	/* Datasheet says 8.1 uV per unit for the current ADC */
426f059b46eSHans de Goede 	chip->ua_per_unit = 8100000 / curr_sense_res_uohm;
427f059b46eSHans de Goede 
428f059b46eSHans de Goede 	/* Use provided internal resistance as start point (in milli-ohm) */
429f059b46eSHans de Goede 	chip->intern_res_avg = chip->info->factory_internal_resistance_uohm / 1000;
430f059b46eSHans de Goede 	/* Also add it to the internal resistance moving average window */
431f059b46eSHans de Goede 	chip->intern_res[0] = chip->intern_res_avg;
432f059b46eSHans de Goede 	chip->intern_res_avg_index = 1;
433f059b46eSHans de Goede 	chip->intern_res_poll_count = 1;
434f059b46eSHans de Goede 
435f059b46eSHans de Goede 	mutex_lock(&chip->lock);
436f059b46eSHans de Goede 	chip->psy = psy;
437f059b46eSHans de Goede 	mutex_unlock(&chip->lock);
438f059b46eSHans de Goede 
439f059b46eSHans de Goede 	ug3105_init(chip);
440f059b46eSHans de Goede 
441f059b46eSHans de Goede 	i2c_set_clientdata(client, chip);
442f059b46eSHans de Goede 	return 0;
443f059b46eSHans de Goede }
444f059b46eSHans de Goede 
ug3105_suspend(struct device * dev)445f059b46eSHans de Goede static int __maybe_unused ug3105_suspend(struct device *dev)
446f059b46eSHans de Goede {
447f059b46eSHans de Goede 	struct ug3105_chip *chip = dev_get_drvdata(dev);
448f059b46eSHans de Goede 
449f059b46eSHans de Goede 	cancel_delayed_work_sync(&chip->work);
450f059b46eSHans de Goede 	i2c_smbus_write_byte_data(chip->client, UG3105_REG_MODE,
451f059b46eSHans de Goede 				  UG3105_MODE_STANDBY);
452f059b46eSHans de Goede 
453f059b46eSHans de Goede 	return 0;
454f059b46eSHans de Goede }
455f059b46eSHans de Goede 
ug3105_resume(struct device * dev)456f059b46eSHans de Goede static int __maybe_unused ug3105_resume(struct device *dev)
457f059b46eSHans de Goede {
458f059b46eSHans de Goede 	struct ug3105_chip *chip = dev_get_drvdata(dev);
459f059b46eSHans de Goede 
460f059b46eSHans de Goede 	ug3105_init(chip);
461f059b46eSHans de Goede 
462f059b46eSHans de Goede 	return 0;
463f059b46eSHans de Goede }
464f059b46eSHans de Goede 
465f059b46eSHans de Goede static SIMPLE_DEV_PM_OPS(ug3105_pm_ops, ug3105_suspend,
466f059b46eSHans de Goede 			ug3105_resume);
467f059b46eSHans de Goede 
468f059b46eSHans de Goede static const struct i2c_device_id ug3105_id[] = {
469f059b46eSHans de Goede 	{ "ug3105" },
470f059b46eSHans de Goede 	{ }
471f059b46eSHans de Goede };
472f059b46eSHans de Goede MODULE_DEVICE_TABLE(i2c, ug3105_id);
473f059b46eSHans de Goede 
474f059b46eSHans de Goede static struct i2c_driver ug3105_i2c_driver = {
475f059b46eSHans de Goede 	.driver	= {
476f059b46eSHans de Goede 		.name = "ug3105",
477f059b46eSHans de Goede 		.pm = &ug3105_pm_ops,
478f059b46eSHans de Goede 	},
479*fe20b1dcSUwe Kleine-König 	.probe = ug3105_probe,
480f059b46eSHans de Goede 	.id_table = ug3105_id,
481f059b46eSHans de Goede };
482f059b46eSHans de Goede module_i2c_driver(ug3105_i2c_driver);
483f059b46eSHans de Goede 
484f059b46eSHans de Goede MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com");
485f059b46eSHans de Goede MODULE_DESCRIPTION("uPI uG3105 battery monitor driver");
486f059b46eSHans de Goede MODULE_LICENSE("GPL");
487