xref: /openbmc/linux/drivers/power/supply/max17040_battery.c (revision 6455a8a84bdfd34829d23328b9d106c2652885f2)
17b38ebdfSKrzysztof Kozlowski // SPDX-License-Identifier: GPL-2.0
27b38ebdfSKrzysztof Kozlowski //
37b38ebdfSKrzysztof Kozlowski //  max17040_battery.c
47b38ebdfSKrzysztof Kozlowski //  fuel-gauge systems for lithium-ion (Li+) batteries
57b38ebdfSKrzysztof Kozlowski //
67b38ebdfSKrzysztof Kozlowski //  Copyright (C) 2009 Samsung Electronics
77b38ebdfSKrzysztof Kozlowski //  Minkyu Kang <mk7.kang@samsung.com>
88c0984e5SSebastian Reichel 
98c0984e5SSebastian Reichel #include <linux/module.h>
108c0984e5SSebastian Reichel #include <linux/init.h>
118c0984e5SSebastian Reichel #include <linux/platform_device.h>
128c0984e5SSebastian Reichel #include <linux/mutex.h>
138c0984e5SSebastian Reichel #include <linux/err.h>
148c0984e5SSebastian Reichel #include <linux/i2c.h>
158c0984e5SSebastian Reichel #include <linux/delay.h>
162e17ed94SMatheus Castello #include <linux/interrupt.h>
178c0984e5SSebastian Reichel #include <linux/power_supply.h>
188c0984e5SSebastian Reichel #include <linux/max17040_battery.h>
19*6455a8a8SIskren Chernev #include <linux/regmap.h>
208c0984e5SSebastian Reichel #include <linux/slab.h>
218c0984e5SSebastian Reichel 
2214d60bddSLiu Xiang #define MAX17040_VCELL	0x02
2314d60bddSLiu Xiang #define MAX17040_SOC	0x04
2414d60bddSLiu Xiang #define MAX17040_MODE	0x06
2514d60bddSLiu Xiang #define MAX17040_VER	0x08
26*6455a8a8SIskren Chernev #define MAX17040_CONFIG	0x0C
2714d60bddSLiu Xiang #define MAX17040_CMD	0xFE
2814d60bddSLiu Xiang 
298c0984e5SSebastian Reichel 
308c0984e5SSebastian Reichel #define MAX17040_DELAY		1000
318c0984e5SSebastian Reichel #define MAX17040_BATTERY_FULL	95
328c0984e5SSebastian Reichel 
33*6455a8a8SIskren Chernev #define MAX17040_ATHD_MASK		0x3f
34cccdd0caSMatheus Castello #define MAX17040_ATHD_DEFAULT_POWER_UP	4
35cccdd0caSMatheus Castello 
368c0984e5SSebastian Reichel struct max17040_chip {
378c0984e5SSebastian Reichel 	struct i2c_client		*client;
38*6455a8a8SIskren Chernev 	struct regmap			*regmap;
398c0984e5SSebastian Reichel 	struct delayed_work		work;
408c0984e5SSebastian Reichel 	struct power_supply		*battery;
418c0984e5SSebastian Reichel 	struct max17040_platform_data	*pdata;
428c0984e5SSebastian Reichel 
438c0984e5SSebastian Reichel 	/* battery capacity */
448c0984e5SSebastian Reichel 	int soc;
458c0984e5SSebastian Reichel 	/* State Of Charge */
468c0984e5SSebastian Reichel 	int status;
47cccdd0caSMatheus Castello 	/* Low alert threshold from 32% to 1% of the State of Charge */
48cccdd0caSMatheus Castello 	u32 low_soc_alert;
498c0984e5SSebastian Reichel };
508c0984e5SSebastian Reichel 
51*6455a8a8SIskren Chernev static int max17040_reset(struct max17040_chip *chip)
528c0984e5SSebastian Reichel {
53*6455a8a8SIskren Chernev 	return regmap_write(chip->regmap, MAX17040_CMD, 0x0054);
548c0984e5SSebastian Reichel }
558c0984e5SSebastian Reichel 
56*6455a8a8SIskren Chernev static int max17040_set_low_soc_alert(struct max17040_chip *chip, u32 level)
578c0984e5SSebastian Reichel {
58cccdd0caSMatheus Castello 	level = 32 - level;
59*6455a8a8SIskren Chernev 	return regmap_update_bits(chip->regmap, MAX17040_CONFIG,
60*6455a8a8SIskren Chernev 			MAX17040_ATHD_MASK, level);
61cccdd0caSMatheus Castello }
62cccdd0caSMatheus Castello 
63*6455a8a8SIskren Chernev static int max17040_get_vcell(struct max17040_chip *chip)
648c0984e5SSebastian Reichel {
65*6455a8a8SIskren Chernev 	u32 vcell;
668c0984e5SSebastian Reichel 
67*6455a8a8SIskren Chernev 	regmap_read(chip->regmap, MAX17040_VCELL, &vcell);
688c0984e5SSebastian Reichel 
69*6455a8a8SIskren Chernev 	return (vcell >> 4) * 1250;
708c0984e5SSebastian Reichel }
718c0984e5SSebastian Reichel 
72*6455a8a8SIskren Chernev static int max17040_get_soc(struct max17040_chip *chip)
738c0984e5SSebastian Reichel {
74*6455a8a8SIskren Chernev 	u32 soc;
758c0984e5SSebastian Reichel 
76*6455a8a8SIskren Chernev 	regmap_read(chip->regmap, MAX17040_SOC, &soc);
778c0984e5SSebastian Reichel 
78*6455a8a8SIskren Chernev 	return soc >> 8;
798c0984e5SSebastian Reichel }
808c0984e5SSebastian Reichel 
81*6455a8a8SIskren Chernev static int max17040_get_version(struct max17040_chip *chip)
828c0984e5SSebastian Reichel {
83*6455a8a8SIskren Chernev 	int ret;
84*6455a8a8SIskren Chernev 	u32 version;
858c0984e5SSebastian Reichel 
86*6455a8a8SIskren Chernev 	ret = regmap_read(chip->regmap, MAX17040_VER, &version);
878c0984e5SSebastian Reichel 
88*6455a8a8SIskren Chernev 	return ret ? ret : version;
898c0984e5SSebastian Reichel }
908c0984e5SSebastian Reichel 
91*6455a8a8SIskren Chernev static int max17040_get_online(struct max17040_chip *chip)
928c0984e5SSebastian Reichel {
93*6455a8a8SIskren Chernev 	return chip->pdata && chip->pdata->battery_online ?
94*6455a8a8SIskren Chernev 		chip->pdata->battery_online() : 1;
958c0984e5SSebastian Reichel }
968c0984e5SSebastian Reichel 
97*6455a8a8SIskren Chernev static int max17040_get_status(struct max17040_chip *chip)
988c0984e5SSebastian Reichel {
998c0984e5SSebastian Reichel 	if (!chip->pdata || !chip->pdata->charger_online
100*6455a8a8SIskren Chernev 			|| !chip->pdata->charger_enable)
101*6455a8a8SIskren Chernev 		return POWER_SUPPLY_STATUS_UNKNOWN;
1028c0984e5SSebastian Reichel 
103*6455a8a8SIskren Chernev 	if (max17040_get_soc(chip) > MAX17040_BATTERY_FULL)
104*6455a8a8SIskren Chernev 		return POWER_SUPPLY_STATUS_FULL;
105*6455a8a8SIskren Chernev 
106*6455a8a8SIskren Chernev 	if (chip->pdata->charger_online())
1078c0984e5SSebastian Reichel 		if (chip->pdata->charger_enable())
108*6455a8a8SIskren Chernev 			return POWER_SUPPLY_STATUS_CHARGING;
1098c0984e5SSebastian Reichel 		else
110*6455a8a8SIskren Chernev 			return POWER_SUPPLY_STATUS_NOT_CHARGING;
111*6455a8a8SIskren Chernev 	else
112*6455a8a8SIskren Chernev 		return POWER_SUPPLY_STATUS_DISCHARGING;
1138c0984e5SSebastian Reichel }
1148c0984e5SSebastian Reichel 
115cccdd0caSMatheus Castello static int max17040_get_of_data(struct max17040_chip *chip)
116cccdd0caSMatheus Castello {
117cccdd0caSMatheus Castello 	struct device *dev = &chip->client->dev;
118cccdd0caSMatheus Castello 
119cccdd0caSMatheus Castello 	chip->low_soc_alert = MAX17040_ATHD_DEFAULT_POWER_UP;
120cccdd0caSMatheus Castello 	device_property_read_u32(dev,
121cccdd0caSMatheus Castello 				 "maxim,alert-low-soc-level",
122cccdd0caSMatheus Castello 				 &chip->low_soc_alert);
123cccdd0caSMatheus Castello 
124*6455a8a8SIskren Chernev 	if (chip->low_soc_alert <= 0 || chip->low_soc_alert >= 33) {
125*6455a8a8SIskren Chernev 		dev_err(dev, "maxim,alert-low-soc-level out of bounds\n");
126cccdd0caSMatheus Castello 		return -EINVAL;
127*6455a8a8SIskren Chernev 	}
128cccdd0caSMatheus Castello 
129cccdd0caSMatheus Castello 	return 0;
130cccdd0caSMatheus Castello }
131cccdd0caSMatheus Castello 
132*6455a8a8SIskren Chernev static void max17040_check_changes(struct max17040_chip *chip)
1332e17ed94SMatheus Castello {
134*6455a8a8SIskren Chernev 	chip->soc = max17040_get_soc(chip);
135*6455a8a8SIskren Chernev 	chip->status = max17040_get_status(chip);
1362e17ed94SMatheus Castello }
1372e17ed94SMatheus Castello 
138e55a5061SIskren Chernev static void max17040_queue_work(struct max17040_chip *chip)
139e55a5061SIskren Chernev {
140e55a5061SIskren Chernev 	queue_delayed_work(system_power_efficient_wq, &chip->work,
141e55a5061SIskren Chernev 			   MAX17040_DELAY);
142e55a5061SIskren Chernev }
143e55a5061SIskren Chernev 
144e55a5061SIskren Chernev static void max17040_stop_work(void *data)
145e55a5061SIskren Chernev {
146e55a5061SIskren Chernev 	struct max17040_chip *chip = data;
147e55a5061SIskren Chernev 
148e55a5061SIskren Chernev 	cancel_delayed_work_sync(&chip->work);
149e55a5061SIskren Chernev }
150e55a5061SIskren Chernev 
1518c0984e5SSebastian Reichel static void max17040_work(struct work_struct *work)
1528c0984e5SSebastian Reichel {
1538c0984e5SSebastian Reichel 	struct max17040_chip *chip;
154a08990eaSMatheus Castello 	int last_soc, last_status;
1558c0984e5SSebastian Reichel 
1568c0984e5SSebastian Reichel 	chip = container_of(work, struct max17040_chip, work.work);
157a08990eaSMatheus Castello 
158a08990eaSMatheus Castello 	/* store SOC and status to check changes */
159a08990eaSMatheus Castello 	last_soc = chip->soc;
160a08990eaSMatheus Castello 	last_status = chip->status;
161*6455a8a8SIskren Chernev 	max17040_check_changes(chip);
1628c0984e5SSebastian Reichel 
163a08990eaSMatheus Castello 	/* check changes and send uevent */
164a08990eaSMatheus Castello 	if (last_soc != chip->soc || last_status != chip->status)
165a08990eaSMatheus Castello 		power_supply_changed(chip->battery);
166a08990eaSMatheus Castello 
167e55a5061SIskren Chernev 	max17040_queue_work(chip);
1688c0984e5SSebastian Reichel }
1698c0984e5SSebastian Reichel 
1702e17ed94SMatheus Castello static irqreturn_t max17040_thread_handler(int id, void *dev)
1712e17ed94SMatheus Castello {
1722e17ed94SMatheus Castello 	struct max17040_chip *chip = dev;
1732e17ed94SMatheus Castello 
174*6455a8a8SIskren Chernev 	dev_warn(&chip->client->dev, "IRQ: Alert battery low level");
175*6455a8a8SIskren Chernev 
1762e17ed94SMatheus Castello 	/* read registers */
177*6455a8a8SIskren Chernev 	max17040_check_changes(chip);
1782e17ed94SMatheus Castello 
1792e17ed94SMatheus Castello 	/* send uevent */
1802e17ed94SMatheus Castello 	power_supply_changed(chip->battery);
1812e17ed94SMatheus Castello 
182cccdd0caSMatheus Castello 	/* reset alert bit */
183*6455a8a8SIskren Chernev 	max17040_set_low_soc_alert(chip, chip->low_soc_alert);
184cccdd0caSMatheus Castello 
1852e17ed94SMatheus Castello 	return IRQ_HANDLED;
1862e17ed94SMatheus Castello }
1872e17ed94SMatheus Castello 
1882e17ed94SMatheus Castello static int max17040_enable_alert_irq(struct max17040_chip *chip)
1892e17ed94SMatheus Castello {
1902e17ed94SMatheus Castello 	struct i2c_client *client = chip->client;
1912e17ed94SMatheus Castello 	unsigned int flags;
1922e17ed94SMatheus Castello 	int ret;
1932e17ed94SMatheus Castello 
1942e17ed94SMatheus Castello 	flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
1952e17ed94SMatheus Castello 	ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
1962e17ed94SMatheus Castello 					max17040_thread_handler, flags,
1972e17ed94SMatheus Castello 					chip->battery->desc->name, chip);
1982e17ed94SMatheus Castello 
1992e17ed94SMatheus Castello 	return ret;
2002e17ed94SMatheus Castello }
2012e17ed94SMatheus Castello 
2022f38dc4dSMatheus Castello static int max17040_prop_writeable(struct power_supply *psy,
2032f38dc4dSMatheus Castello 				   enum power_supply_property psp)
2042f38dc4dSMatheus Castello {
2052f38dc4dSMatheus Castello 	switch (psp) {
2062f38dc4dSMatheus Castello 	case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
2072f38dc4dSMatheus Castello 		return 1;
2082f38dc4dSMatheus Castello 	default:
2092f38dc4dSMatheus Castello 		return 0;
2102f38dc4dSMatheus Castello 	}
2112f38dc4dSMatheus Castello }
2122f38dc4dSMatheus Castello 
2132f38dc4dSMatheus Castello static int max17040_set_property(struct power_supply *psy,
2142f38dc4dSMatheus Castello 			    enum power_supply_property psp,
2152f38dc4dSMatheus Castello 			    const union power_supply_propval *val)
2162f38dc4dSMatheus Castello {
2172f38dc4dSMatheus Castello 	struct max17040_chip *chip = power_supply_get_drvdata(psy);
2182f38dc4dSMatheus Castello 	int ret;
2192f38dc4dSMatheus Castello 
2202f38dc4dSMatheus Castello 	switch (psp) {
2212f38dc4dSMatheus Castello 	case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
2222f38dc4dSMatheus Castello 		/* alert threshold can be programmed from 1% up to 32% */
2232f38dc4dSMatheus Castello 		if ((val->intval < 1) || (val->intval > 32)) {
2242f38dc4dSMatheus Castello 			ret = -EINVAL;
2252f38dc4dSMatheus Castello 			break;
2262f38dc4dSMatheus Castello 		}
227*6455a8a8SIskren Chernev 		ret = max17040_set_low_soc_alert(chip, val->intval);
2282f38dc4dSMatheus Castello 		chip->low_soc_alert = val->intval;
2292f38dc4dSMatheus Castello 		break;
2302f38dc4dSMatheus Castello 	default:
2312f38dc4dSMatheus Castello 		ret = -EINVAL;
2322f38dc4dSMatheus Castello 	}
2332f38dc4dSMatheus Castello 
2342f38dc4dSMatheus Castello 	return ret;
2352f38dc4dSMatheus Castello }
2362f38dc4dSMatheus Castello 
237*6455a8a8SIskren Chernev static int max17040_get_property(struct power_supply *psy,
238*6455a8a8SIskren Chernev 			    enum power_supply_property psp,
239*6455a8a8SIskren Chernev 			    union power_supply_propval *val)
240*6455a8a8SIskren Chernev {
241*6455a8a8SIskren Chernev 	struct max17040_chip *chip = power_supply_get_drvdata(psy);
242*6455a8a8SIskren Chernev 
243*6455a8a8SIskren Chernev 	switch (psp) {
244*6455a8a8SIskren Chernev 	case POWER_SUPPLY_PROP_STATUS:
245*6455a8a8SIskren Chernev 		val->intval = max17040_get_status(chip);
246*6455a8a8SIskren Chernev 		break;
247*6455a8a8SIskren Chernev 	case POWER_SUPPLY_PROP_ONLINE:
248*6455a8a8SIskren Chernev 		val->intval = max17040_get_online(chip);
249*6455a8a8SIskren Chernev 		break;
250*6455a8a8SIskren Chernev 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
251*6455a8a8SIskren Chernev 		val->intval = max17040_get_vcell(chip);
252*6455a8a8SIskren Chernev 		break;
253*6455a8a8SIskren Chernev 	case POWER_SUPPLY_PROP_CAPACITY:
254*6455a8a8SIskren Chernev 		val->intval = max17040_get_soc(chip);
255*6455a8a8SIskren Chernev 		break;
256*6455a8a8SIskren Chernev 	case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
257*6455a8a8SIskren Chernev 		val->intval = chip->low_soc_alert;
258*6455a8a8SIskren Chernev 		break;
259*6455a8a8SIskren Chernev 	default:
260*6455a8a8SIskren Chernev 		return -EINVAL;
261*6455a8a8SIskren Chernev 	}
262*6455a8a8SIskren Chernev 	return 0;
263*6455a8a8SIskren Chernev }
264*6455a8a8SIskren Chernev 
265*6455a8a8SIskren Chernev static const struct regmap_config max17040_regmap = {
266*6455a8a8SIskren Chernev 	.reg_bits	= 8,
267*6455a8a8SIskren Chernev 	.reg_stride	= 2,
268*6455a8a8SIskren Chernev 	.val_bits	= 16,
269*6455a8a8SIskren Chernev 	.val_format_endian = REGMAP_ENDIAN_BIG,
270*6455a8a8SIskren Chernev };
271*6455a8a8SIskren Chernev 
2728c0984e5SSebastian Reichel static enum power_supply_property max17040_battery_props[] = {
2738c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_STATUS,
2748c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_ONLINE,
2758c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
2768c0984e5SSebastian Reichel 	POWER_SUPPLY_PROP_CAPACITY,
2772f38dc4dSMatheus Castello 	POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
2788c0984e5SSebastian Reichel };
2798c0984e5SSebastian Reichel 
2808c0984e5SSebastian Reichel static const struct power_supply_desc max17040_battery_desc = {
2818c0984e5SSebastian Reichel 	.name			= "battery",
2828c0984e5SSebastian Reichel 	.type			= POWER_SUPPLY_TYPE_BATTERY,
2838c0984e5SSebastian Reichel 	.get_property		= max17040_get_property,
2842f38dc4dSMatheus Castello 	.set_property		= max17040_set_property,
2852f38dc4dSMatheus Castello 	.property_is_writeable  = max17040_prop_writeable,
2868c0984e5SSebastian Reichel 	.properties		= max17040_battery_props,
2878c0984e5SSebastian Reichel 	.num_properties		= ARRAY_SIZE(max17040_battery_props),
2888c0984e5SSebastian Reichel };
2898c0984e5SSebastian Reichel 
2908c0984e5SSebastian Reichel static int max17040_probe(struct i2c_client *client,
2918c0984e5SSebastian Reichel 			const struct i2c_device_id *id)
2928c0984e5SSebastian Reichel {
2934e9c406dSWolfram Sang 	struct i2c_adapter *adapter = client->adapter;
2948c0984e5SSebastian Reichel 	struct power_supply_config psy_cfg = {};
2958c0984e5SSebastian Reichel 	struct max17040_chip *chip;
296cccdd0caSMatheus Castello 	int ret;
2978c0984e5SSebastian Reichel 
2988c0984e5SSebastian Reichel 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
2998c0984e5SSebastian Reichel 		return -EIO;
3008c0984e5SSebastian Reichel 
3018c0984e5SSebastian Reichel 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
3028c0984e5SSebastian Reichel 	if (!chip)
3038c0984e5SSebastian Reichel 		return -ENOMEM;
3048c0984e5SSebastian Reichel 
3058c0984e5SSebastian Reichel 	chip->client = client;
306*6455a8a8SIskren Chernev 	chip->regmap = devm_regmap_init_i2c(client, &max17040_regmap);
3078c0984e5SSebastian Reichel 	chip->pdata = client->dev.platform_data;
308cccdd0caSMatheus Castello 	ret = max17040_get_of_data(chip);
309*6455a8a8SIskren Chernev 	if (ret)
310cccdd0caSMatheus Castello 		return ret;
3118c0984e5SSebastian Reichel 
3128c0984e5SSebastian Reichel 	i2c_set_clientdata(client, chip);
3138c0984e5SSebastian Reichel 	psy_cfg.drv_data = chip;
3148c0984e5SSebastian Reichel 
315e55a5061SIskren Chernev 	chip->battery = devm_power_supply_register(&client->dev,
3168c0984e5SSebastian Reichel 				&max17040_battery_desc, &psy_cfg);
3178c0984e5SSebastian Reichel 	if (IS_ERR(chip->battery)) {
3188c0984e5SSebastian Reichel 		dev_err(&client->dev, "failed: power supply register\n");
3198c0984e5SSebastian Reichel 		return PTR_ERR(chip->battery);
3208c0984e5SSebastian Reichel 	}
3218c0984e5SSebastian Reichel 
322*6455a8a8SIskren Chernev 	ret = max17040_get_version(chip);
323*6455a8a8SIskren Chernev 	if (ret < 0)
324*6455a8a8SIskren Chernev 		return ret;
325*6455a8a8SIskren Chernev 	dev_dbg(&chip->client->dev, "MAX17040 Fuel-Gauge Ver 0x%x\n", ret);
326*6455a8a8SIskren Chernev 
327*6455a8a8SIskren Chernev 	max17040_reset(chip);
3288c0984e5SSebastian Reichel 
3292e17ed94SMatheus Castello 	/* check interrupt */
3302e17ed94SMatheus Castello 	if (client->irq && of_device_is_compatible(client->dev.of_node,
3312e17ed94SMatheus Castello 						   "maxim,max77836-battery")) {
332*6455a8a8SIskren Chernev 		ret = max17040_set_low_soc_alert(chip, chip->low_soc_alert);
333cccdd0caSMatheus Castello 		if (ret) {
334cccdd0caSMatheus Castello 			dev_err(&client->dev,
335cccdd0caSMatheus Castello 				"Failed to set low SOC alert: err %d\n", ret);
336cccdd0caSMatheus Castello 			return ret;
337cccdd0caSMatheus Castello 		}
3382e17ed94SMatheus Castello 
3392e17ed94SMatheus Castello 		ret = max17040_enable_alert_irq(chip);
3402e17ed94SMatheus Castello 		if (ret) {
3412e17ed94SMatheus Castello 			client->irq = 0;
3422e17ed94SMatheus Castello 			dev_warn(&client->dev,
3432e17ed94SMatheus Castello 				 "Failed to get IRQ err %d\n", ret);
3442e17ed94SMatheus Castello 		}
3452e17ed94SMatheus Castello 	}
3462e17ed94SMatheus Castello 
3478c0984e5SSebastian Reichel 	INIT_DEFERRABLE_WORK(&chip->work, max17040_work);
348e55a5061SIskren Chernev 	ret = devm_add_action(&client->dev, max17040_stop_work, chip);
349e55a5061SIskren Chernev 	if (ret)
350e55a5061SIskren Chernev 		return ret;
351e55a5061SIskren Chernev 	max17040_queue_work(chip);
3528c0984e5SSebastian Reichel 
3538c0984e5SSebastian Reichel 	return 0;
3548c0984e5SSebastian Reichel }
3558c0984e5SSebastian Reichel 
3568c0984e5SSebastian Reichel #ifdef CONFIG_PM_SLEEP
3578c0984e5SSebastian Reichel 
3588c0984e5SSebastian Reichel static int max17040_suspend(struct device *dev)
3598c0984e5SSebastian Reichel {
3608c0984e5SSebastian Reichel 	struct i2c_client *client = to_i2c_client(dev);
3618c0984e5SSebastian Reichel 	struct max17040_chip *chip = i2c_get_clientdata(client);
3628c0984e5SSebastian Reichel 
3638c0984e5SSebastian Reichel 	cancel_delayed_work(&chip->work);
3642e17ed94SMatheus Castello 
365e29242adSMarek Szyprowski 	if (client->irq && device_may_wakeup(dev))
3662e17ed94SMatheus Castello 		enable_irq_wake(client->irq);
3672e17ed94SMatheus Castello 
3688c0984e5SSebastian Reichel 	return 0;
3698c0984e5SSebastian Reichel }
3708c0984e5SSebastian Reichel 
3718c0984e5SSebastian Reichel static int max17040_resume(struct device *dev)
3728c0984e5SSebastian Reichel {
3738c0984e5SSebastian Reichel 	struct i2c_client *client = to_i2c_client(dev);
3748c0984e5SSebastian Reichel 	struct max17040_chip *chip = i2c_get_clientdata(client);
3758c0984e5SSebastian Reichel 
376e29242adSMarek Szyprowski 	if (client->irq && device_may_wakeup(dev))
3772e17ed94SMatheus Castello 		disable_irq_wake(client->irq);
3782e17ed94SMatheus Castello 
379e55a5061SIskren Chernev 	max17040_queue_work(chip);
380e55a5061SIskren Chernev 
3818c0984e5SSebastian Reichel 	return 0;
3828c0984e5SSebastian Reichel }
3838c0984e5SSebastian Reichel 
3848c0984e5SSebastian Reichel static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume);
3858c0984e5SSebastian Reichel #define MAX17040_PM_OPS (&max17040_pm_ops)
3868c0984e5SSebastian Reichel 
3878c0984e5SSebastian Reichel #else
3888c0984e5SSebastian Reichel 
3898c0984e5SSebastian Reichel #define MAX17040_PM_OPS NULL
3908c0984e5SSebastian Reichel 
3918c0984e5SSebastian Reichel #endif /* CONFIG_PM_SLEEP */
3928c0984e5SSebastian Reichel 
3938c0984e5SSebastian Reichel static const struct i2c_device_id max17040_id[] = {
3948c0984e5SSebastian Reichel 	{ "max17040" },
3958c0984e5SSebastian Reichel 	{ "max77836-battery" },
3968c0984e5SSebastian Reichel 	{ }
3978c0984e5SSebastian Reichel };
3988c0984e5SSebastian Reichel MODULE_DEVICE_TABLE(i2c, max17040_id);
3998c0984e5SSebastian Reichel 
400da28122cSJavier Martinez Canillas static const struct of_device_id max17040_of_match[] = {
401da28122cSJavier Martinez Canillas 	{ .compatible = "maxim,max17040" },
402da28122cSJavier Martinez Canillas 	{ .compatible = "maxim,max77836-battery" },
403da28122cSJavier Martinez Canillas 	{ },
404da28122cSJavier Martinez Canillas };
405da28122cSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, max17040_of_match);
406da28122cSJavier Martinez Canillas 
4078c0984e5SSebastian Reichel static struct i2c_driver max17040_i2c_driver = {
4088c0984e5SSebastian Reichel 	.driver	= {
4098c0984e5SSebastian Reichel 		.name	= "max17040",
410da28122cSJavier Martinez Canillas 		.of_match_table = max17040_of_match,
4118c0984e5SSebastian Reichel 		.pm	= MAX17040_PM_OPS,
4128c0984e5SSebastian Reichel 	},
4138c0984e5SSebastian Reichel 	.probe		= max17040_probe,
4148c0984e5SSebastian Reichel 	.id_table	= max17040_id,
4158c0984e5SSebastian Reichel };
4168c0984e5SSebastian Reichel module_i2c_driver(max17040_i2c_driver);
4178c0984e5SSebastian Reichel 
4188c0984e5SSebastian Reichel MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
4198c0984e5SSebastian Reichel MODULE_DESCRIPTION("MAX17040 Fuel Gauge");
4208c0984e5SSebastian Reichel MODULE_LICENSE("GPL");
421