xref: /linux/drivers/power/supply/surface-rt-ec.c (revision 3d5e48944e824bddc20d7b874e784f7b279636fe)
1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include <linux/devm-helpers.h>
4 #include <linux/delay.h>
5 #include <linux/gpio/consumer.h>
6 #include <linux/i2c.h>
7 #include <linux/interrupt.h>
8 #include <linux/module.h>
9 #include <linux/property.h>
10 #include <linux/power_supply.h>
11 #include <linux/types.h>
12 
13 /* Register Addresses (B=byte; W=word; S=string) */
14 #define REGB_STATUS			0x02
15 #define REGW_VOLTAGE_NOW		0x20
16 #define REGW_CURRENT_NOW		0x24
17 #define REGW_CAPACITY			0x28
18 #define REGW_CHARGE_NOW			0x2a
19 #define REGW_CHARGE_FULL		0x2c
20 #define REGW_CYCLE_COUNT		0x3a
21 #define REGW_CHARGE_FULL_DESIGN		0x3c
22 #define REGW_VOLTAGE_MAX_DESIGN		0x3e
23 #define REGW_SERIAL_NUMBER		0x44
24 #define REGS_MANUFACTURER		0x46
25 #define REGS_MODEL_NAME			0x52
26 #define REGS_TECHNOLOGY			0x5a
27 #define REGB_ONLINE			0x67
28 
29 struct srt_ec_device {
30 	struct i2c_client *client;
31 
32 	struct power_supply *bat;
33 	struct power_supply *psy;
34 
35 	struct gpio_desc *enable_gpiod;
36 	struct delayed_work poll_work;
37 
38 	unsigned int technology;
39 	unsigned int capacity;
40 
41 	const char *serial;
42 	char manufacturer[13];
43 	char model_name[10];
44 };
45 
46 static const enum power_supply_property srt_bat_power_supply_props[] = {
47 	POWER_SUPPLY_PROP_CAPACITY,
48 	POWER_SUPPLY_PROP_CHARGE_NOW,
49 	POWER_SUPPLY_PROP_CHARGE_FULL,
50 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
51 	POWER_SUPPLY_PROP_CURRENT_NOW,
52 	POWER_SUPPLY_PROP_CYCLE_COUNT,
53 	POWER_SUPPLY_PROP_MANUFACTURER,
54 	POWER_SUPPLY_PROP_MODEL_NAME,
55 	POWER_SUPPLY_PROP_ONLINE,
56 	POWER_SUPPLY_PROP_PRESENT,
57 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
58 	POWER_SUPPLY_PROP_STATUS,
59 	POWER_SUPPLY_PROP_TECHNOLOGY,
60 	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
61 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
62 };
63 
64 static const enum power_supply_property srt_psy_power_supply_props[] = {
65 	POWER_SUPPLY_PROP_ONLINE,
66 	POWER_SUPPLY_PROP_PRESENT,
67 };
68 
69 static int srt_bat_get_value(struct i2c_client *client, int reg, int *val)
70 {
71 	int ret;
72 
73 	switch (reg) {
74 	case REGW_CHARGE_NOW:
75 	case REGW_CHARGE_FULL_DESIGN:
76 	case REGW_CHARGE_FULL:
77 	case REGW_VOLTAGE_MAX_DESIGN:
78 	case REGW_VOLTAGE_NOW:
79 		ret = i2c_smbus_read_word_data(client, reg);
80 		if (ret < 0)
81 			return ret;
82 
83 		*val = ret * 1000;
84 		break;
85 
86 	case REGW_CURRENT_NOW:
87 		ret = i2c_smbus_read_word_data(client, reg);
88 		if (ret < 0)
89 			return ret;
90 
91 		*val = (s16)ret * 1000;
92 		break;
93 
94 	case REGW_CAPACITY:
95 	case REGW_CYCLE_COUNT:
96 		ret = i2c_smbus_read_word_data(client, reg);
97 		if (ret < 0)
98 			return ret;
99 
100 		*val = ret;
101 		break;
102 
103 	case REGB_STATUS:
104 		ret = i2c_smbus_read_byte_data(client, reg);
105 		if (ret < 0)
106 			return ret;
107 
108 		if (ret & BIT(0))
109 			*val = POWER_SUPPLY_STATUS_CHARGING;
110 		else
111 			*val =  POWER_SUPPLY_STATUS_DISCHARGING;
112 		break;
113 
114 	case REGB_ONLINE:
115 		ret = i2c_smbus_read_byte_data(client, reg);
116 		if (ret < 0)
117 			return ret;
118 
119 		*val = (ret & BIT(1)) >> 1;
120 		break;
121 
122 	default:
123 		return -EINVAL;
124 	}
125 
126 	return 0;
127 }
128 
129 static int srt_bat_power_supply_get_property(struct power_supply *psy,
130 					     enum power_supply_property psp,
131 					     union power_supply_propval *val)
132 {
133 	struct srt_ec_device *srt = power_supply_get_drvdata(psy);
134 	struct i2c_client *client = srt->client;
135 	int ret = 0;
136 
137 	switch (psp) {
138 	case POWER_SUPPLY_PROP_MANUFACTURER:
139 		val->strval = srt->manufacturer;
140 		break;
141 	case POWER_SUPPLY_PROP_MODEL_NAME:
142 		val->strval = srt->model_name;
143 		break;
144 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
145 		val->strval = srt->serial;
146 		break;
147 	case POWER_SUPPLY_PROP_CAPACITY:
148 		ret = srt_bat_get_value(client, REGW_CAPACITY, &val->intval);
149 		break;
150 	case POWER_SUPPLY_PROP_CHARGE_NOW:
151 		ret = srt_bat_get_value(client, REGW_CHARGE_NOW, &val->intval);
152 		break;
153 	case POWER_SUPPLY_PROP_CHARGE_FULL:
154 		ret = srt_bat_get_value(client, REGW_CHARGE_FULL, &val->intval);
155 		break;
156 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
157 		ret = srt_bat_get_value(client, REGW_CHARGE_FULL_DESIGN,
158 					&val->intval);
159 		break;
160 	case POWER_SUPPLY_PROP_CURRENT_NOW:
161 		ret = srt_bat_get_value(client, REGW_CURRENT_NOW, &val->intval);
162 		break;
163 	case POWER_SUPPLY_PROP_CYCLE_COUNT:
164 		ret = srt_bat_get_value(client, REGW_CYCLE_COUNT, &val->intval);
165 		break;
166 	case POWER_SUPPLY_PROP_PRESENT:
167 		val->intval = 1;
168 		break;
169 	case POWER_SUPPLY_PROP_ONLINE:
170 		ret = srt_bat_get_value(client, REGB_ONLINE, &val->intval);
171 		break;
172 	case POWER_SUPPLY_PROP_STATUS:
173 		if (srt->capacity < 100)
174 			ret = srt_bat_get_value(client, REGB_STATUS, &val->intval);
175 		else
176 			val->intval = POWER_SUPPLY_STATUS_FULL;
177 		break;
178 	case POWER_SUPPLY_PROP_TECHNOLOGY:
179 		val->intval = srt->technology;
180 		break;
181 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
182 		ret = srt_bat_get_value(client, REGW_VOLTAGE_MAX_DESIGN,
183 					&val->intval);
184 		break;
185 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
186 		ret = srt_bat_get_value(client, REGW_VOLTAGE_NOW, &val->intval);
187 		break;
188 	default:
189 		return -EINVAL;
190 	}
191 
192 	return ret;
193 }
194 
195 static int srt_psy_power_supply_get_property(struct power_supply *psy,
196 					     enum power_supply_property psp,
197 					     union power_supply_propval *val)
198 {
199 	struct srt_ec_device *srt = power_supply_get_drvdata(psy);
200 	struct i2c_client *client = srt->client;
201 	int ret;
202 
203 	switch (psp) {
204 	case POWER_SUPPLY_PROP_ONLINE:
205 	case POWER_SUPPLY_PROP_PRESENT:
206 		ret = i2c_smbus_read_byte_data(client, REGB_ONLINE);
207 		if (ret < 0)
208 			return ret;
209 
210 		val->intval = ret & BIT(0);
211 		break;
212 	default:
213 		return -EINVAL;
214 	}
215 
216 	return 0;
217 }
218 
219 static void srt_bat_poll_work(struct work_struct *work)
220 {
221 	struct srt_ec_device *srt =
222 		container_of(work, struct srt_ec_device, poll_work.work);
223 	int ret, capacity;
224 
225 	ret = srt_bat_get_value(srt->client, REGW_CAPACITY, &capacity);
226 	if (!ret && capacity != srt->capacity) {
227 		srt->capacity = capacity;
228 		power_supply_changed(srt->bat);
229 	}
230 
231 	/* continuously send uevent notification */
232 	schedule_delayed_work(&srt->poll_work, 30 * HZ);
233 }
234 
235 static irqreturn_t srt_psy_detect_irq(int irq, void *dev_id)
236 {
237 	struct srt_ec_device *srt = dev_id;
238 
239 	power_supply_changed(srt->psy);
240 
241 	return IRQ_HANDLED;
242 }
243 
244 static const struct power_supply_desc srt_bat_power_supply_desc = {
245 	.name = "surface-rt-battery",
246 	.type = POWER_SUPPLY_TYPE_BATTERY,
247 	.properties = srt_bat_power_supply_props,
248 	.num_properties = ARRAY_SIZE(srt_bat_power_supply_props),
249 	.get_property = srt_bat_power_supply_get_property,
250 	.external_power_changed = power_supply_changed,
251 };
252 
253 static const struct power_supply_desc srt_psy_power_supply_desc = {
254 	.name = "surface-rt-ac-adapter",
255 	.type = POWER_SUPPLY_TYPE_MAINS,
256 	.properties = srt_psy_power_supply_props,
257 	.num_properties = ARRAY_SIZE(srt_psy_power_supply_props),
258 	.get_property = srt_psy_power_supply_get_property,
259 };
260 
261 static char *battery_supplied_to[] = { "surface-rt-battery" };
262 
263 static int srt_ec_probe(struct i2c_client *client)
264 {
265 	struct power_supply_config bat_cfg = {};
266 	struct power_supply_config psy_cfg = {};
267 	struct device *dev = &client->dev;
268 	struct srt_ec_device *srt;
269 	char str_buf[4];
270 	int ret;
271 
272 	srt = devm_kzalloc(dev, sizeof(*srt), GFP_KERNEL);
273 	if (!srt)
274 		return -ENOMEM;
275 
276 	i2c_set_clientdata(client, srt);
277 	srt->client = client;
278 
279 	srt->enable_gpiod = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
280 	if (IS_ERR(srt->enable_gpiod))
281 		return dev_err_probe(dev, PTR_ERR(srt->enable_gpiod),
282 				     "failed to get enable gpio\n");
283 
284 	/* wait till EC is ready */
285 	usleep_range(1000, 1500);
286 
287 	ret = i2c_smbus_read_word_data(client, REGW_SERIAL_NUMBER);
288 	if (ret < 0)
289 		return ret;
290 
291 	srt->serial = devm_kasprintf(dev, GFP_KERNEL, "%04x", ret);
292 	if (!srt->serial)
293 		return -ENOMEM;
294 
295 	ret = i2c_smbus_read_i2c_block_data(client, REGS_MANUFACTURER,
296 					    sizeof(srt->manufacturer) - 1,
297 					    srt->manufacturer);
298 	if (ret < 0)
299 		return ret;
300 
301 	ret = i2c_smbus_read_i2c_block_data(client, REGS_MODEL_NAME,
302 					    sizeof(srt->model_name) - 1,
303 					    srt->model_name);
304 	if (ret < 0)
305 		return ret;
306 
307 	ret = i2c_smbus_read_i2c_block_data(client, REGS_TECHNOLOGY,
308 					    sizeof(str_buf), str_buf);
309 	if (ret < 0)
310 		return ret;
311 
312 	if (!strncmp(str_buf, "LION", 4))
313 		srt->technology = POWER_SUPPLY_TECHNOLOGY_LION;
314 	else
315 		srt->technology = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
316 
317 	bat_cfg.drv_data = srt;
318 	bat_cfg.fwnode = dev_fwnode(dev);
319 
320 	srt->bat = devm_power_supply_register(dev, &srt_bat_power_supply_desc,
321 					      &bat_cfg);
322 	if (IS_ERR(srt->bat))
323 		return dev_err_probe(dev, PTR_ERR(srt->bat),
324 				     "failed to register battery power supply\n");
325 
326 	psy_cfg.drv_data = srt;
327 	psy_cfg.fwnode = dev_fwnode(dev);
328 	psy_cfg.supplied_to = battery_supplied_to;
329 	psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
330 
331 	srt->psy = devm_power_supply_register(dev, &srt_psy_power_supply_desc,
332 					      &psy_cfg);
333 	if (IS_ERR(srt->psy))
334 		return dev_err_probe(dev, PTR_ERR(srt->psy),
335 				     "failed to register AC power supply\n");
336 
337 	ret = devm_request_threaded_irq(dev, client->irq, NULL, srt_psy_detect_irq,
338 					IRQF_ONESHOT, client->name, srt);
339 	if (ret < 0)
340 		return dev_err_probe(dev, ret, "failed to request interrupt\n");
341 
342 	ret = devm_delayed_work_autocancel(dev, &srt->poll_work, srt_bat_poll_work);
343 	if (ret < 0)
344 		return ret;
345 
346 	schedule_delayed_work(&srt->poll_work, HZ);
347 
348 	return 0;
349 }
350 
351 static int srt_ec_suspend(struct device *dev)
352 {
353 	struct srt_ec_device *srt = dev_get_drvdata(dev);
354 
355 	cancel_delayed_work_sync(&srt->poll_work);
356 
357 	return 0;
358 }
359 
360 static int srt_ec_resume(struct device *dev)
361 {
362 	struct srt_ec_device *srt = dev_get_drvdata(dev);
363 
364 	schedule_delayed_work(&srt->poll_work, HZ);
365 
366 	return 0;
367 }
368 
369 static DEFINE_SIMPLE_DEV_PM_OPS(srt_ec_pm_ops, srt_ec_suspend, srt_ec_resume);
370 
371 static const struct of_device_id srt_ec_of_match[] = {
372 	{ .compatible = "microsoft,surface-rt-ec" },
373 	{ }
374 };
375 MODULE_DEVICE_TABLE(of, srt_ec_of_match);
376 
377 static struct i2c_driver srt_ec_driver = {
378 	.driver = {
379 		.name = "surface-rt-ec",
380 		.of_match_table = srt_ec_of_match,
381 		.pm = &srt_ec_pm_ops,
382 	},
383 	.probe = srt_ec_probe,
384 };
385 module_i2c_driver(srt_ec_driver);
386 
387 MODULE_AUTHOR("Jonas Schwöbel <jonasschwoebel@yahoo.de>");
388 MODULE_DESCRIPTION("Surface RT Embedded Controller driver");
389 MODULE_LICENSE("GPL");
390