1fd2f02f9SAxel Lin // SPDX-License-Identifier: GPL-2.0+
2fd2f02f9SAxel Lin //
3fd2f02f9SAxel Lin // da9211-regulator.c - Regulator device driver for DA9211/DA9212
4fd2f02f9SAxel Lin // /DA9213/DA9223/DA9214/DA9224/DA9215/DA9225
5fd2f02f9SAxel Lin // Copyright (C) 2015  Dialog Semiconductor Ltd.
61028a37dSJames Ban 
71028a37dSJames Ban #include <linux/err.h>
81028a37dSJames Ban #include <linux/i2c.h>
91028a37dSJames Ban #include <linux/module.h>
101028a37dSJames Ban #include <linux/init.h>
111028a37dSJames Ban #include <linux/slab.h>
121028a37dSJames Ban #include <linux/regulator/driver.h>
131028a37dSJames Ban #include <linux/regulator/machine.h>
141028a37dSJames Ban #include <linux/regmap.h>
151028a37dSJames Ban #include <linux/irq.h>
161028a37dSJames Ban #include <linux/interrupt.h>
1711da04afSLinus Walleij #include <linux/gpio/consumer.h>
18bf3baca6SJames Ban #include <linux/regulator/of_regulator.h>
191028a37dSJames Ban #include <linux/regulator/da9211.h>
206c8b6595SAnand K Mistry #include <dt-bindings/regulator/dlg,da9211-regulator.h>
211028a37dSJames Ban #include "da9211-regulator.h"
221028a37dSJames Ban 
23005547e0SJames Ban /* DEVICE IDs */
24005547e0SJames Ban #define DA9211_DEVICE_ID	0x22
25005547e0SJames Ban #define DA9213_DEVICE_ID	0x23
267bd39354SJames Ban #define DA9215_DEVICE_ID	0x24
27005547e0SJames Ban 
281028a37dSJames Ban /* DA9211 REGULATOR IDs */
291028a37dSJames Ban #define DA9211_ID_BUCKA	0
301028a37dSJames Ban #define DA9211_ID_BUCKB	1
311028a37dSJames Ban 
321028a37dSJames Ban struct da9211 {
331028a37dSJames Ban 	struct device *dev;
341028a37dSJames Ban 	struct regmap *regmap;
351028a37dSJames Ban 	struct da9211_pdata *pdata;
361028a37dSJames Ban 	struct regulator_dev *rdev[DA9211_MAX_REGULATORS];
371028a37dSJames Ban 	int num_regulator;
381028a37dSJames Ban 	int chip_irq;
39005547e0SJames Ban 	int chip_id;
401028a37dSJames Ban };
411028a37dSJames Ban 
421028a37dSJames Ban static const struct regmap_range_cfg da9211_regmap_range[] = {
431028a37dSJames Ban 	{
441028a37dSJames Ban 		.selector_reg = DA9211_REG_PAGE_CON,
451028a37dSJames Ban 		.selector_mask  = DA9211_REG_PAGE_MASK,
461028a37dSJames Ban 		.selector_shift = DA9211_REG_PAGE_SHIFT,
471028a37dSJames Ban 		.window_start = 0,
481028a37dSJames Ban 		.window_len = 256,
491028a37dSJames Ban 		.range_min = 0,
50005547e0SJames Ban 		.range_max = 5*128,
511028a37dSJames Ban 	},
521028a37dSJames Ban };
531028a37dSJames Ban 
da9211_volatile_reg(struct device * dev,unsigned int reg)54989e08c3SHsin-Yi Wang static bool da9211_volatile_reg(struct device *dev, unsigned int reg)
55989e08c3SHsin-Yi Wang {
56989e08c3SHsin-Yi Wang 	switch (reg) {
57989e08c3SHsin-Yi Wang 	case DA9211_REG_STATUS_A:
58989e08c3SHsin-Yi Wang 	case DA9211_REG_STATUS_B:
59989e08c3SHsin-Yi Wang 	case DA9211_REG_EVENT_A:
60989e08c3SHsin-Yi Wang 	case DA9211_REG_EVENT_B:
61989e08c3SHsin-Yi Wang 		return true;
62989e08c3SHsin-Yi Wang 	}
63989e08c3SHsin-Yi Wang 	return false;
64989e08c3SHsin-Yi Wang }
65989e08c3SHsin-Yi Wang 
661028a37dSJames Ban static const struct regmap_config da9211_regmap_config = {
671028a37dSJames Ban 	.reg_bits = 8,
681028a37dSJames Ban 	.val_bits = 8,
69005547e0SJames Ban 	.max_register = 5 * 128,
70989e08c3SHsin-Yi Wang 	.volatile_reg = da9211_volatile_reg,
71989e08c3SHsin-Yi Wang 	.cache_type = REGCACHE_RBTREE,
721028a37dSJames Ban 	.ranges = da9211_regmap_range,
731028a37dSJames Ban 	.num_ranges = ARRAY_SIZE(da9211_regmap_range),
741028a37dSJames Ban };
751028a37dSJames Ban 
761028a37dSJames Ban /* Default limits measured in millivolts and milliamps */
771028a37dSJames Ban #define DA9211_MIN_MV		300
781028a37dSJames Ban #define DA9211_MAX_MV		1570
791028a37dSJames Ban #define DA9211_STEP_MV		10
801028a37dSJames Ban 
81005547e0SJames Ban /* Current limits for DA9211 buck (uA) indices
82005547e0SJames Ban  * corresponds with register values
83005547e0SJames Ban  */
841028a37dSJames Ban static const int da9211_current_limits[] = {
851028a37dSJames Ban 	2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000,
861028a37dSJames Ban 	3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000
871028a37dSJames Ban };
88005547e0SJames Ban /* Current limits for DA9213 buck (uA) indices
89005547e0SJames Ban  * corresponds with register values
90005547e0SJames Ban  */
91005547e0SJames Ban static const int da9213_current_limits[] = {
92005547e0SJames Ban 	3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000,
93005547e0SJames Ban 	4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000
94005547e0SJames Ban };
957bd39354SJames Ban /* Current limits for DA9215 buck (uA) indices
967bd39354SJames Ban  * corresponds with register values
977bd39354SJames Ban  */
987bd39354SJames Ban static const int da9215_current_limits[] = {
997bd39354SJames Ban 	4000000, 4200000, 4400000, 4600000, 4800000, 5000000, 5200000, 5400000,
1007bd39354SJames Ban 	5600000, 5800000, 6000000, 6200000, 6400000, 6600000, 6800000, 7000000
1017bd39354SJames Ban };
1021028a37dSJames Ban 
da9211_map_buck_mode(unsigned int mode)1036f1f1a80SAnand K Mistry static unsigned int da9211_map_buck_mode(unsigned int mode)
1046f1f1a80SAnand K Mistry {
1056f1f1a80SAnand K Mistry 	switch (mode) {
1066f1f1a80SAnand K Mistry 	case DA9211_BUCK_MODE_SLEEP:
1076f1f1a80SAnand K Mistry 		return REGULATOR_MODE_STANDBY;
1086f1f1a80SAnand K Mistry 	case DA9211_BUCK_MODE_SYNC:
1096f1f1a80SAnand K Mistry 		return REGULATOR_MODE_FAST;
1106f1f1a80SAnand K Mistry 	case DA9211_BUCK_MODE_AUTO:
1116f1f1a80SAnand K Mistry 		return REGULATOR_MODE_NORMAL;
1126f1f1a80SAnand K Mistry 	default:
1136f1f1a80SAnand K Mistry 		return REGULATOR_MODE_INVALID;
1146f1f1a80SAnand K Mistry 	}
1156f1f1a80SAnand K Mistry }
1166f1f1a80SAnand K Mistry 
da9211_buck_get_mode(struct regulator_dev * rdev)1171028a37dSJames Ban static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev)
1181028a37dSJames Ban {
1191028a37dSJames Ban 	int id = rdev_get_id(rdev);
1201028a37dSJames Ban 	struct da9211 *chip = rdev_get_drvdata(rdev);
1211028a37dSJames Ban 	unsigned int data;
1221028a37dSJames Ban 	int ret, mode = 0;
1231028a37dSJames Ban 
1241028a37dSJames Ban 	ret = regmap_read(chip->regmap, DA9211_REG_BUCKA_CONF+id, &data);
1251028a37dSJames Ban 	if (ret < 0)
1261028a37dSJames Ban 		return ret;
1271028a37dSJames Ban 
1281028a37dSJames Ban 	switch (data & 0x03) {
1291028a37dSJames Ban 	case DA9211_BUCK_MODE_SYNC:
1301028a37dSJames Ban 		mode = REGULATOR_MODE_FAST;
1311028a37dSJames Ban 		break;
1321028a37dSJames Ban 	case DA9211_BUCK_MODE_AUTO:
1331028a37dSJames Ban 		mode = REGULATOR_MODE_NORMAL;
1341028a37dSJames Ban 		break;
1351028a37dSJames Ban 	case DA9211_BUCK_MODE_SLEEP:
1361028a37dSJames Ban 		mode = REGULATOR_MODE_STANDBY;
1371028a37dSJames Ban 		break;
1381028a37dSJames Ban 	}
1391028a37dSJames Ban 
1401028a37dSJames Ban 	return mode;
1411028a37dSJames Ban }
1421028a37dSJames Ban 
da9211_buck_set_mode(struct regulator_dev * rdev,unsigned int mode)1431028a37dSJames Ban static int da9211_buck_set_mode(struct regulator_dev *rdev,
1441028a37dSJames Ban 					unsigned int mode)
1451028a37dSJames Ban {
1461028a37dSJames Ban 	int id = rdev_get_id(rdev);
1471028a37dSJames Ban 	struct da9211 *chip = rdev_get_drvdata(rdev);
1481028a37dSJames Ban 	int val = 0;
1491028a37dSJames Ban 
1501028a37dSJames Ban 	switch (mode) {
1511028a37dSJames Ban 	case REGULATOR_MODE_FAST:
1521028a37dSJames Ban 		val = DA9211_BUCK_MODE_SYNC;
1531028a37dSJames Ban 		break;
1541028a37dSJames Ban 	case REGULATOR_MODE_NORMAL:
1551028a37dSJames Ban 		val = DA9211_BUCK_MODE_AUTO;
1561028a37dSJames Ban 		break;
1571028a37dSJames Ban 	case REGULATOR_MODE_STANDBY:
1581028a37dSJames Ban 		val = DA9211_BUCK_MODE_SLEEP;
1591028a37dSJames Ban 		break;
1601028a37dSJames Ban 	}
1611028a37dSJames Ban 
1621028a37dSJames Ban 	return regmap_update_bits(chip->regmap, DA9211_REG_BUCKA_CONF+id,
1631028a37dSJames Ban 					0x03, val);
1641028a37dSJames Ban }
1651028a37dSJames Ban 
da9211_set_current_limit(struct regulator_dev * rdev,int min,int max)1661028a37dSJames Ban static int da9211_set_current_limit(struct regulator_dev *rdev, int min,
1671028a37dSJames Ban 				    int max)
1681028a37dSJames Ban {
1691028a37dSJames Ban 	int id = rdev_get_id(rdev);
1701028a37dSJames Ban 	struct da9211 *chip = rdev_get_drvdata(rdev);
171005547e0SJames Ban 	int i, max_size;
172005547e0SJames Ban 	const int *current_limits;
173005547e0SJames Ban 
174005547e0SJames Ban 	switch (chip->chip_id) {
175005547e0SJames Ban 	case DA9211:
176005547e0SJames Ban 		current_limits = da9211_current_limits;
177005547e0SJames Ban 		max_size = ARRAY_SIZE(da9211_current_limits)-1;
178005547e0SJames Ban 		break;
179005547e0SJames Ban 	case DA9213:
180005547e0SJames Ban 		current_limits = da9213_current_limits;
181005547e0SJames Ban 		max_size = ARRAY_SIZE(da9213_current_limits)-1;
182005547e0SJames Ban 		break;
1837bd39354SJames Ban 	case DA9215:
1847bd39354SJames Ban 		current_limits = da9215_current_limits;
1857bd39354SJames Ban 		max_size = ARRAY_SIZE(da9215_current_limits)-1;
1867bd39354SJames Ban 		break;
187005547e0SJames Ban 	default:
188005547e0SJames Ban 		return -EINVAL;
189005547e0SJames Ban 	}
1901028a37dSJames Ban 
1911028a37dSJames Ban 	/* search for closest to maximum */
192005547e0SJames Ban 	for (i = max_size; i >= 0; i--) {
193005547e0SJames Ban 		if (min <= current_limits[i] &&
194005547e0SJames Ban 		    max >= current_limits[i]) {
1951028a37dSJames Ban 				return regmap_update_bits(chip->regmap,
1961028a37dSJames Ban 					DA9211_REG_BUCK_ILIM,
1971028a37dSJames Ban 					(0x0F << id*4), (i << id*4));
1981028a37dSJames Ban 		}
1991028a37dSJames Ban 	}
2001028a37dSJames Ban 
2011028a37dSJames Ban 	return -EINVAL;
2021028a37dSJames Ban }
2031028a37dSJames Ban 
da9211_get_current_limit(struct regulator_dev * rdev)2041028a37dSJames Ban static int da9211_get_current_limit(struct regulator_dev *rdev)
2051028a37dSJames Ban {
2061028a37dSJames Ban 	int id = rdev_get_id(rdev);
2071028a37dSJames Ban 	struct da9211 *chip = rdev_get_drvdata(rdev);
2081028a37dSJames Ban 	unsigned int data;
2091028a37dSJames Ban 	int ret;
210005547e0SJames Ban 	const int *current_limits;
211005547e0SJames Ban 
212005547e0SJames Ban 	switch (chip->chip_id) {
213005547e0SJames Ban 	case DA9211:
214005547e0SJames Ban 		current_limits = da9211_current_limits;
215005547e0SJames Ban 		break;
216005547e0SJames Ban 	case DA9213:
217005547e0SJames Ban 		current_limits = da9213_current_limits;
218005547e0SJames Ban 		break;
2197bd39354SJames Ban 	case DA9215:
2207bd39354SJames Ban 		current_limits = da9215_current_limits;
2217bd39354SJames Ban 		break;
222005547e0SJames Ban 	default:
223005547e0SJames Ban 		return -EINVAL;
224005547e0SJames Ban 	}
2251028a37dSJames Ban 
2261028a37dSJames Ban 	ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data);
2271028a37dSJames Ban 	if (ret < 0)
2281028a37dSJames Ban 		return ret;
2291028a37dSJames Ban 
230005547e0SJames Ban 	/* select one of 16 values: 0000 (2000mA or 3000mA)
231005547e0SJames Ban 	 * to 1111 (5000mA or 6000mA).
232005547e0SJames Ban 	 */
2331028a37dSJames Ban 	data = (data >> id*4) & 0x0F;
234005547e0SJames Ban 	return current_limits[data];
2351028a37dSJames Ban }
2361028a37dSJames Ban 
23771242b49SJulia Lawall static const struct regulator_ops da9211_buck_ops = {
2381028a37dSJames Ban 	.get_mode = da9211_buck_get_mode,
2391028a37dSJames Ban 	.set_mode = da9211_buck_set_mode,
2401028a37dSJames Ban 	.enable = regulator_enable_regmap,
2411028a37dSJames Ban 	.disable = regulator_disable_regmap,
2421028a37dSJames Ban 	.is_enabled = regulator_is_enabled_regmap,
2431028a37dSJames Ban 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
2441028a37dSJames Ban 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
2451028a37dSJames Ban 	.list_voltage = regulator_list_voltage_linear,
2461028a37dSJames Ban 	.set_current_limit = da9211_set_current_limit,
2471028a37dSJames Ban 	.get_current_limit = da9211_get_current_limit,
2481028a37dSJames Ban };
2491028a37dSJames Ban 
2501028a37dSJames Ban #define DA9211_BUCK(_id) \
2511028a37dSJames Ban {\
2521028a37dSJames Ban 	.name = #_id,\
2531028a37dSJames Ban 	.ops = &da9211_buck_ops,\
2541028a37dSJames Ban 	.type = REGULATOR_VOLTAGE,\
2551028a37dSJames Ban 	.id = DA9211_ID_##_id,\
2561028a37dSJames Ban 	.n_voltages = (DA9211_MAX_MV - DA9211_MIN_MV) / DA9211_STEP_MV + 1,\
2571028a37dSJames Ban 	.min_uV = (DA9211_MIN_MV * 1000),\
2581028a37dSJames Ban 	.uV_step = (DA9211_STEP_MV * 1000),\
2591028a37dSJames Ban 	.enable_reg = DA9211_REG_BUCKA_CONT + DA9211_ID_##_id,\
2601028a37dSJames Ban 	.enable_mask = DA9211_BUCKA_EN,\
2611028a37dSJames Ban 	.vsel_reg = DA9211_REG_VBUCKA_A + DA9211_ID_##_id * 2,\
2621028a37dSJames Ban 	.vsel_mask = DA9211_VBUCK_MASK,\
2631028a37dSJames Ban 	.owner = THIS_MODULE,\
2646f1f1a80SAnand K Mistry 	.of_map_mode = da9211_map_buck_mode,\
2651028a37dSJames Ban }
2661028a37dSJames Ban 
2671028a37dSJames Ban static struct regulator_desc da9211_regulators[] = {
2681028a37dSJames Ban 	DA9211_BUCK(BUCKA),
2691028a37dSJames Ban 	DA9211_BUCK(BUCKB),
2701028a37dSJames Ban };
2711028a37dSJames Ban 
272bf3baca6SJames Ban #ifdef CONFIG_OF
273bf3baca6SJames Ban static struct of_regulator_match da9211_matches[] = {
2746f1f1a80SAnand K Mistry 	[DA9211_ID_BUCKA] = {
2756f1f1a80SAnand K Mistry 		.name = "BUCKA",
2766f1f1a80SAnand K Mistry 		.desc = &da9211_regulators[DA9211_ID_BUCKA],
2776f1f1a80SAnand K Mistry 	},
2786f1f1a80SAnand K Mistry 	[DA9211_ID_BUCKB] = {
2796f1f1a80SAnand K Mistry 		.name = "BUCKB",
2806f1f1a80SAnand K Mistry 		.desc = &da9211_regulators[DA9211_ID_BUCKB],
2816f1f1a80SAnand K Mistry 	},
282bf3baca6SJames Ban 	};
283bf3baca6SJames Ban 
da9211_parse_regulators_dt(struct device * dev)284bf3baca6SJames Ban static struct da9211_pdata *da9211_parse_regulators_dt(
285bf3baca6SJames Ban 		struct device *dev)
286bf3baca6SJames Ban {
287bf3baca6SJames Ban 	struct da9211_pdata *pdata;
288bf3baca6SJames Ban 	struct device_node *node;
289bf3baca6SJames Ban 	int i, num, n;
290bf3baca6SJames Ban 
291bf3baca6SJames Ban 	node = of_get_child_by_name(dev->of_node, "regulators");
292bf3baca6SJames Ban 	if (!node) {
293bf3baca6SJames Ban 		dev_err(dev, "regulators node not found\n");
294bf3baca6SJames Ban 		return ERR_PTR(-ENODEV);
295bf3baca6SJames Ban 	}
296bf3baca6SJames Ban 
297bf3baca6SJames Ban 	num = of_regulator_match(dev, node, da9211_matches,
298bf3baca6SJames Ban 				 ARRAY_SIZE(da9211_matches));
299bf3baca6SJames Ban 	of_node_put(node);
300bf3baca6SJames Ban 	if (num < 0) {
301bf3baca6SJames Ban 		dev_err(dev, "Failed to match regulators\n");
302bf3baca6SJames Ban 		return ERR_PTR(-EINVAL);
303bf3baca6SJames Ban 	}
304bf3baca6SJames Ban 
305bf3baca6SJames Ban 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
306bf3baca6SJames Ban 	if (!pdata)
307bf3baca6SJames Ban 		return ERR_PTR(-ENOMEM);
308bf3baca6SJames Ban 
309bf3baca6SJames Ban 	pdata->num_buck = num;
310bf3baca6SJames Ban 
311bf3baca6SJames Ban 	n = 0;
312bf3baca6SJames Ban 	for (i = 0; i < ARRAY_SIZE(da9211_matches); i++) {
313bf3baca6SJames Ban 		if (!da9211_matches[i].init_data)
314bf3baca6SJames Ban 			continue;
315bf3baca6SJames Ban 
316bf3baca6SJames Ban 		pdata->init_data[n] = da9211_matches[i].init_data;
317076c3b8eSJames Ban 		pdata->reg_node[n] = da9211_matches[i].of_node;
31861d2fc3cSDmitry Torokhov 		pdata->gpiod_ren[n] = devm_fwnode_gpiod_get(dev,
31961d2fc3cSDmitry Torokhov 					of_fwnode_handle(pdata->reg_node[n]),
32061d2fc3cSDmitry Torokhov 					"enable",
32161d2fc3cSDmitry Torokhov 					GPIOD_OUT_HIGH |
32261d2fc3cSDmitry Torokhov 						GPIOD_FLAGS_BIT_NONEXCLUSIVE,
32311da04afSLinus Walleij 					"da9211-enable");
324025bf377SWaibel Georg 		if (IS_ERR(pdata->gpiod_ren[n]))
325025bf377SWaibel Georg 			pdata->gpiod_ren[n] = NULL;
326bf3baca6SJames Ban 		n++;
327c2a946e0SFengguang Wu 	}
328bf3baca6SJames Ban 
329bf3baca6SJames Ban 	return pdata;
330bf3baca6SJames Ban }
331bf3baca6SJames Ban #else
da9211_parse_regulators_dt(struct device * dev)332bf3baca6SJames Ban static struct da9211_pdata *da9211_parse_regulators_dt(
333bf3baca6SJames Ban 		struct device *dev)
334bf3baca6SJames Ban {
335bf3baca6SJames Ban 	return ERR_PTR(-ENODEV);
336bf3baca6SJames Ban }
337bf3baca6SJames Ban #endif
338bf3baca6SJames Ban 
da9211_irq_handler(int irq,void * data)3391028a37dSJames Ban static irqreturn_t da9211_irq_handler(int irq, void *data)
3401028a37dSJames Ban {
3411028a37dSJames Ban 	struct da9211 *chip = data;
3421028a37dSJames Ban 	int reg_val, err, ret = IRQ_NONE;
3431028a37dSJames Ban 
3441028a37dSJames Ban 	err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, &reg_val);
3451028a37dSJames Ban 	if (err < 0)
3461028a37dSJames Ban 		goto error_i2c;
3471028a37dSJames Ban 
3481028a37dSJames Ban 	if (reg_val & DA9211_E_OV_CURR_A) {
3491028a37dSJames Ban 		regulator_notifier_call_chain(chip->rdev[0],
350a46a0730SGeert Uytterhoeven 			REGULATOR_EVENT_OVER_CURRENT, NULL);
3511028a37dSJames Ban 
3521028a37dSJames Ban 		err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
3531028a37dSJames Ban 			DA9211_E_OV_CURR_A);
3541028a37dSJames Ban 		if (err < 0)
3551028a37dSJames Ban 			goto error_i2c;
3561028a37dSJames Ban 
3571028a37dSJames Ban 		ret = IRQ_HANDLED;
3581028a37dSJames Ban 	}
3591028a37dSJames Ban 
3601028a37dSJames Ban 	if (reg_val & DA9211_E_OV_CURR_B) {
3611028a37dSJames Ban 		regulator_notifier_call_chain(chip->rdev[1],
362a46a0730SGeert Uytterhoeven 			REGULATOR_EVENT_OVER_CURRENT, NULL);
3631028a37dSJames Ban 
3641028a37dSJames Ban 		err = regmap_write(chip->regmap, DA9211_REG_EVENT_B,
3651028a37dSJames Ban 			DA9211_E_OV_CURR_B);
3661028a37dSJames Ban 		if (err < 0)
3671028a37dSJames Ban 			goto error_i2c;
3681028a37dSJames Ban 
3691028a37dSJames Ban 		ret = IRQ_HANDLED;
3701028a37dSJames Ban 	}
3711028a37dSJames Ban 
3721028a37dSJames Ban 	return ret;
3731028a37dSJames Ban 
3741028a37dSJames Ban error_i2c:
3751028a37dSJames Ban 	dev_err(chip->dev, "I2C error : %d\n", err);
3761028a37dSJames Ban 	return IRQ_NONE;
3771028a37dSJames Ban }
3781028a37dSJames Ban 
da9211_regulator_init(struct da9211 * chip)3791028a37dSJames Ban static int da9211_regulator_init(struct da9211 *chip)
3801028a37dSJames Ban {
3811028a37dSJames Ban 	struct regulator_config config = { };
3821028a37dSJames Ban 	int i, ret;
3831028a37dSJames Ban 	unsigned int data;
3841028a37dSJames Ban 
3851028a37dSJames Ban 	ret = regmap_read(chip->regmap, DA9211_REG_CONFIG_E, &data);
3861028a37dSJames Ban 	if (ret < 0) {
387767e8aabSGeert Uytterhoeven 		dev_err(chip->dev, "Failed to read CONFIG_E reg: %d\n", ret);
388516c1514SAxel Lin 		return ret;
3891028a37dSJames Ban 	}
3901028a37dSJames Ban 
3911028a37dSJames Ban 	data &= DA9211_SLAVE_SEL;
3921028a37dSJames Ban 	/* If configuration for 1/2 bucks is different between platform data
3931028a37dSJames Ban 	 * and the register, driver should exit.
3941028a37dSJames Ban 	 */
3957bd39354SJames Ban 	if (chip->pdata->num_buck == 1 && data == 0x00)
3961028a37dSJames Ban 		chip->num_regulator = 1;
3977bd39354SJames Ban 	else if (chip->pdata->num_buck == 2 && data != 0x00)
3981028a37dSJames Ban 		chip->num_regulator = 2;
3997bd39354SJames Ban 	else {
4001028a37dSJames Ban 		dev_err(chip->dev, "Configuration is mismatched\n");
401516c1514SAxel Lin 		return -EINVAL;
4021028a37dSJames Ban 	}
4031028a37dSJames Ban 
4041028a37dSJames Ban 	for (i = 0; i < chip->num_regulator; i++) {
405bf3baca6SJames Ban 		config.init_data = chip->pdata->init_data[i];
4061028a37dSJames Ban 		config.dev = chip->dev;
4071028a37dSJames Ban 		config.driver_data = chip;
4081028a37dSJames Ban 		config.regmap = chip->regmap;
409076c3b8eSJames Ban 		config.of_node = chip->pdata->reg_node[i];
4101028a37dSJames Ban 
41111da04afSLinus Walleij 		if (chip->pdata->gpiod_ren[i])
41211da04afSLinus Walleij 			config.ena_gpiod = chip->pdata->gpiod_ren[i];
41311da04afSLinus Walleij 		else
41411da04afSLinus Walleij 			config.ena_gpiod = NULL;
4158c7dd8bcSJames Ban 
416b23328d7SLinus Walleij 		/*
417b23328d7SLinus Walleij 		 * Hand the GPIO descriptor management over to the regulator
418b23328d7SLinus Walleij 		 * core, remove it from GPIO devres management.
419b23328d7SLinus Walleij 		 */
420b23328d7SLinus Walleij 		if (config.ena_gpiod)
421b23328d7SLinus Walleij 			devm_gpiod_unhinge(chip->dev, config.ena_gpiod);
4221028a37dSJames Ban 		chip->rdev[i] = devm_regulator_register(chip->dev,
4231028a37dSJames Ban 			&da9211_regulators[i], &config);
4241028a37dSJames Ban 		if (IS_ERR(chip->rdev[i])) {
4251028a37dSJames Ban 			dev_err(chip->dev,
4261028a37dSJames Ban 				"Failed to register DA9211 regulator\n");
427516c1514SAxel Lin 			return PTR_ERR(chip->rdev[i]);
4281028a37dSJames Ban 		}
4291028a37dSJames Ban 
4301028a37dSJames Ban 		if (chip->chip_irq != 0) {
4311028a37dSJames Ban 			ret = regmap_update_bits(chip->regmap,
4324e7089f3SJames Ban 				DA9211_REG_MASK_B, DA9211_M_OV_CURR_A << i, 0);
4331028a37dSJames Ban 			if (ret < 0) {
4341028a37dSJames Ban 				dev_err(chip->dev,
4351028a37dSJames Ban 					"Failed to update mask reg: %d\n", ret);
436516c1514SAxel Lin 				return ret;
4371028a37dSJames Ban 			}
4381028a37dSJames Ban 		}
4391028a37dSJames Ban 	}
4401028a37dSJames Ban 
4411028a37dSJames Ban 	return 0;
4421028a37dSJames Ban }
443bf3baca6SJames Ban 
4441028a37dSJames Ban /*
4451028a37dSJames Ban  * I2C driver interface functions
4461028a37dSJames Ban  */
da9211_i2c_probe(struct i2c_client * i2c)44777e29598SAxel Lin static int da9211_i2c_probe(struct i2c_client *i2c)
4481028a37dSJames Ban {
4491028a37dSJames Ban 	struct da9211 *chip;
4501028a37dSJames Ban 	int error, ret;
451005547e0SJames Ban 	unsigned int data;
4521028a37dSJames Ban 
4531028a37dSJames Ban 	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL);
4541d3e6a69SAxel Lin 	if (!chip)
4551d3e6a69SAxel Lin 		return -ENOMEM;
4561028a37dSJames Ban 
4571028a37dSJames Ban 	chip->dev = &i2c->dev;
4581028a37dSJames Ban 	chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config);
4591028a37dSJames Ban 	if (IS_ERR(chip->regmap)) {
4601028a37dSJames Ban 		error = PTR_ERR(chip->regmap);
461005547e0SJames Ban 		dev_err(chip->dev, "Failed to allocate register map: %d\n",
4621028a37dSJames Ban 			error);
4631028a37dSJames Ban 		return error;
4641028a37dSJames Ban 	}
4651028a37dSJames Ban 
4661028a37dSJames Ban 	i2c_set_clientdata(i2c, chip);
4671028a37dSJames Ban 
4681028a37dSJames Ban 	chip->pdata = i2c->dev.platform_data;
469005547e0SJames Ban 
470005547e0SJames Ban 	ret = regmap_read(chip->regmap, DA9211_REG_DEVICE_ID, &data);
471005547e0SJames Ban 	if (ret < 0) {
472005547e0SJames Ban 		dev_err(chip->dev, "Failed to read DEVICE_ID reg: %d\n", ret);
473005547e0SJames Ban 		return ret;
474005547e0SJames Ban 	}
475005547e0SJames Ban 
476005547e0SJames Ban 	switch (data) {
477005547e0SJames Ban 	case DA9211_DEVICE_ID:
478005547e0SJames Ban 		chip->chip_id = DA9211;
479005547e0SJames Ban 		break;
480005547e0SJames Ban 	case DA9213_DEVICE_ID:
481005547e0SJames Ban 		chip->chip_id = DA9213;
482005547e0SJames Ban 		break;
4837bd39354SJames Ban 	case DA9215_DEVICE_ID:
4847bd39354SJames Ban 		chip->chip_id = DA9215;
4857bd39354SJames Ban 		break;
486005547e0SJames Ban 	default:
487005547e0SJames Ban 		dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data);
4881028a37dSJames Ban 		return -ENODEV;
4891028a37dSJames Ban 	}
4901028a37dSJames Ban 
491bf3baca6SJames Ban 	if (!chip->pdata)
492bf3baca6SJames Ban 		chip->pdata = da9211_parse_regulators_dt(chip->dev);
493bf3baca6SJames Ban 
494bf3baca6SJames Ban 	if (IS_ERR(chip->pdata)) {
495bf3baca6SJames Ban 		dev_err(chip->dev, "No regulators defined for the platform\n");
496bf3baca6SJames Ban 		return PTR_ERR(chip->pdata);
497bf3baca6SJames Ban 	}
498bf3baca6SJames Ban 
4991028a37dSJames Ban 	chip->chip_irq = i2c->irq;
5001028a37dSJames Ban 
50102228f6aSRicardo Ribalda 	ret = da9211_regulator_init(chip);
50202228f6aSRicardo Ribalda 	if (ret < 0) {
50302228f6aSRicardo Ribalda 		dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
50402228f6aSRicardo Ribalda 		return ret;
50502228f6aSRicardo Ribalda 	}
50602228f6aSRicardo Ribalda 
5071028a37dSJames Ban 	if (chip->chip_irq != 0) {
5081028a37dSJames Ban 		ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
5091028a37dSJames Ban 					da9211_irq_handler,
5101028a37dSJames Ban 					IRQF_TRIGGER_LOW|IRQF_ONESHOT,
5111028a37dSJames Ban 					"da9211", chip);
5121028a37dSJames Ban 		if (ret != 0) {
5131028a37dSJames Ban 			dev_err(chip->dev, "Failed to request IRQ: %d\n",
5141028a37dSJames Ban 				chip->chip_irq);
5151028a37dSJames Ban 			return ret;
5161028a37dSJames Ban 		}
5171028a37dSJames Ban 	} else {
5181028a37dSJames Ban 		dev_warn(chip->dev, "No IRQ configured\n");
5191028a37dSJames Ban 	}
5201028a37dSJames Ban 
5211028a37dSJames Ban 	return ret;
5221028a37dSJames Ban }
5231028a37dSJames Ban 
5241028a37dSJames Ban static const struct i2c_device_id da9211_i2c_id[] = {
5256a52f563SAxel Lin 	{"da9211", DA9211},
5267524c1ceSJames Ban 	{"da9212", DA9212},
5276a52f563SAxel Lin 	{"da9213", DA9213},
528707ce9eaSJames Ban 	{"da9223", DA9223},
5297524c1ceSJames Ban 	{"da9214", DA9214},
530707ce9eaSJames Ban 	{"da9224", DA9224},
5317bd39354SJames Ban 	{"da9215", DA9215},
532707ce9eaSJames Ban 	{"da9225", DA9225},
5331028a37dSJames Ban 	{},
5341028a37dSJames Ban };
5351028a37dSJames Ban MODULE_DEVICE_TABLE(i2c, da9211_i2c_id);
5361028a37dSJames Ban 
5376a52f563SAxel Lin #ifdef CONFIG_OF
5386a52f563SAxel Lin static const struct of_device_id da9211_dt_ids[] = {
5396a52f563SAxel Lin 	{ .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] },
5407524c1ceSJames Ban 	{ .compatible = "dlg,da9212", .data = &da9211_i2c_id[1] },
5417524c1ceSJames Ban 	{ .compatible = "dlg,da9213", .data = &da9211_i2c_id[2] },
542707ce9eaSJames Ban 	{ .compatible = "dlg,da9223", .data = &da9211_i2c_id[3] },
543707ce9eaSJames Ban 	{ .compatible = "dlg,da9214", .data = &da9211_i2c_id[4] },
544707ce9eaSJames Ban 	{ .compatible = "dlg,da9224", .data = &da9211_i2c_id[5] },
545707ce9eaSJames Ban 	{ .compatible = "dlg,da9215", .data = &da9211_i2c_id[6] },
546707ce9eaSJames Ban 	{ .compatible = "dlg,da9225", .data = &da9211_i2c_id[7] },
5476a52f563SAxel Lin 	{},
5486a52f563SAxel Lin };
5496a52f563SAxel Lin MODULE_DEVICE_TABLE(of, da9211_dt_ids);
5506a52f563SAxel Lin #endif
5516a52f563SAxel Lin 
5521028a37dSJames Ban static struct i2c_driver da9211_regulator_driver = {
5531028a37dSJames Ban 	.driver = {
5541028a37dSJames Ban 		.name = "da9211",
555259b93b2SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
5566a52f563SAxel Lin 		.of_match_table = of_match_ptr(da9211_dt_ids),
5571028a37dSJames Ban 	},
558*964e1865SUwe Kleine-König 	.probe = da9211_i2c_probe,
5591028a37dSJames Ban 	.id_table = da9211_i2c_id,
5601028a37dSJames Ban };
5611028a37dSJames Ban 
5621028a37dSJames Ban module_i2c_driver(da9211_regulator_driver);
5631028a37dSJames Ban 
5641028a37dSJames Ban MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
565707ce9eaSJames Ban MODULE_DESCRIPTION("DA9211/DA9212/DA9213/DA9223/DA9214/DA9224/DA9215/DA9225 regulator driver");
5667bd39354SJames Ban MODULE_LICENSE("GPL");
567