1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23a8d1a73SMilo Kim /*
33a8d1a73SMilo Kim  * TI LM363X Regulator Driver
43a8d1a73SMilo Kim  *
53a8d1a73SMilo Kim  * Copyright 2015 Texas Instruments
63a8d1a73SMilo Kim  *
73a8d1a73SMilo Kim  * Author: Milo Kim <milo.kim@ti.com>
83a8d1a73SMilo Kim  */
93a8d1a73SMilo Kim 
103a8d1a73SMilo Kim #include <linux/err.h>
113a8d1a73SMilo Kim #include <linux/kernel.h>
123a8d1a73SMilo Kim #include <linux/mfd/ti-lmu.h>
133a8d1a73SMilo Kim #include <linux/mfd/ti-lmu-register.h>
143a8d1a73SMilo Kim #include <linux/module.h>
153a8d1a73SMilo Kim #include <linux/of.h>
16b2d751b7SLinus Walleij #include <linux/gpio/consumer.h>
173a8d1a73SMilo Kim #include <linux/platform_device.h>
183a8d1a73SMilo Kim #include <linux/regulator/driver.h>
193a8d1a73SMilo Kim #include <linux/regulator/of_regulator.h>
203a8d1a73SMilo Kim #include <linux/slab.h>
213a8d1a73SMilo Kim 
223a8d1a73SMilo Kim /* LM3631 */
233a8d1a73SMilo Kim #define LM3631_BOOST_VSEL_MAX		0x25
243a8d1a73SMilo Kim #define LM3631_LDO_VSEL_MAX		0x28
253a8d1a73SMilo Kim #define LM3631_CONT_VSEL_MAX		0x03
263a8d1a73SMilo Kim #define LM3631_VBOOST_MIN		4500000
273a8d1a73SMilo Kim #define LM3631_VCONT_MIN		1800000
283a8d1a73SMilo Kim #define LM3631_VLDO_MIN			4000000
293a8d1a73SMilo Kim #define ENABLE_TIME_USEC		1000
303a8d1a73SMilo Kim 
313a8d1a73SMilo Kim /* LM3632 */
323a8d1a73SMilo Kim #define LM3632_BOOST_VSEL_MAX		0x26
331e2cc8c5SAxel Lin #define LM3632_LDO_VSEL_MAX		0x28
343a8d1a73SMilo Kim #define LM3632_VBOOST_MIN		4500000
353a8d1a73SMilo Kim #define LM3632_VLDO_MIN			4000000
363a8d1a73SMilo Kim 
37bff5e807SDan Murphy /* LM36274 */
38bff5e807SDan Murphy #define LM36274_BOOST_VSEL_MAX		0x3f
39962f170dSAxel Lin #define LM36274_LDO_VSEL_MAX		0x32
40bff5e807SDan Murphy #define LM36274_VOLTAGE_MIN		4000000
41bff5e807SDan Murphy 
423a8d1a73SMilo Kim /* Common */
433a8d1a73SMilo Kim #define LM363X_STEP_50mV		50000
443a8d1a73SMilo Kim #define LM363X_STEP_500mV		500000
453a8d1a73SMilo Kim 
46faa5cf3aSAxel Lin static const int ldo_cont_enable_time[] = {
473a8d1a73SMilo Kim 	0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
483a8d1a73SMilo Kim };
493a8d1a73SMilo Kim 
lm363x_regulator_enable_time(struct regulator_dev * rdev)503a8d1a73SMilo Kim static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
513a8d1a73SMilo Kim {
523a8d1a73SMilo Kim 	enum lm363x_regulator_id id = rdev_get_id(rdev);
538a76f107SAxel Lin 	unsigned int val, addr, mask;
543a8d1a73SMilo Kim 
553a8d1a73SMilo Kim 	switch (id) {
563a8d1a73SMilo Kim 	case LM3631_LDO_CONT:
573a8d1a73SMilo Kim 		addr = LM3631_REG_ENTIME_VCONT;
583a8d1a73SMilo Kim 		mask = LM3631_ENTIME_CONT_MASK;
593a8d1a73SMilo Kim 		break;
603a8d1a73SMilo Kim 	case LM3631_LDO_OREF:
613a8d1a73SMilo Kim 		addr = LM3631_REG_ENTIME_VOREF;
623a8d1a73SMilo Kim 		mask = LM3631_ENTIME_MASK;
633a8d1a73SMilo Kim 		break;
643a8d1a73SMilo Kim 	case LM3631_LDO_POS:
653a8d1a73SMilo Kim 		addr = LM3631_REG_ENTIME_VPOS;
663a8d1a73SMilo Kim 		mask = LM3631_ENTIME_MASK;
673a8d1a73SMilo Kim 		break;
683a8d1a73SMilo Kim 	case LM3631_LDO_NEG:
693a8d1a73SMilo Kim 		addr = LM3631_REG_ENTIME_VNEG;
703a8d1a73SMilo Kim 		mask = LM3631_ENTIME_MASK;
713a8d1a73SMilo Kim 		break;
723a8d1a73SMilo Kim 	default:
733a8d1a73SMilo Kim 		return 0;
743a8d1a73SMilo Kim 	}
753a8d1a73SMilo Kim 
768a76f107SAxel Lin 	if (regmap_read(rdev->regmap, addr, &val))
773a8d1a73SMilo Kim 		return -EINVAL;
783a8d1a73SMilo Kim 
793a8d1a73SMilo Kim 	val = (val & mask) >> LM3631_ENTIME_SHIFT;
803a8d1a73SMilo Kim 
813a8d1a73SMilo Kim 	if (id == LM3631_LDO_CONT)
823a8d1a73SMilo Kim 		return ldo_cont_enable_time[val];
833a8d1a73SMilo Kim 	else
843a8d1a73SMilo Kim 		return ENABLE_TIME_USEC * val;
853a8d1a73SMilo Kim }
863a8d1a73SMilo Kim 
8755c083d8SAxel Lin static const struct regulator_ops lm363x_boost_voltage_table_ops = {
883a8d1a73SMilo Kim 	.list_voltage     = regulator_list_voltage_linear,
893a8d1a73SMilo Kim 	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
903a8d1a73SMilo Kim 	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
913a8d1a73SMilo Kim };
923a8d1a73SMilo Kim 
9355c083d8SAxel Lin static const struct regulator_ops lm363x_regulator_voltage_table_ops = {
943a8d1a73SMilo Kim 	.list_voltage     = regulator_list_voltage_linear,
953a8d1a73SMilo Kim 	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
963a8d1a73SMilo Kim 	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
973a8d1a73SMilo Kim 	.enable           = regulator_enable_regmap,
983a8d1a73SMilo Kim 	.disable          = regulator_disable_regmap,
993a8d1a73SMilo Kim 	.is_enabled       = regulator_is_enabled_regmap,
1003a8d1a73SMilo Kim 	.enable_time      = lm363x_regulator_enable_time,
1013a8d1a73SMilo Kim };
1023a8d1a73SMilo Kim 
1033a8d1a73SMilo Kim static const struct regulator_desc lm363x_regulator_desc[] = {
1043a8d1a73SMilo Kim 	/* LM3631 */
1053a8d1a73SMilo Kim 	{
1063a8d1a73SMilo Kim 		.name           = "vboost",
1073a8d1a73SMilo Kim 		.of_match	= "vboost",
1083a8d1a73SMilo Kim 		.id             = LM3631_BOOST,
1093a8d1a73SMilo Kim 		.ops            = &lm363x_boost_voltage_table_ops,
1103a8d1a73SMilo Kim 		.n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
1113a8d1a73SMilo Kim 		.min_uV         = LM3631_VBOOST_MIN,
1123a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
1133a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1143a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1153a8d1a73SMilo Kim 		.vsel_reg       = LM3631_REG_VOUT_BOOST,
1163a8d1a73SMilo Kim 		.vsel_mask      = LM3631_VOUT_MASK,
1173a8d1a73SMilo Kim 	},
1183a8d1a73SMilo Kim 	{
1193a8d1a73SMilo Kim 		.name           = "ldo_cont",
1203a8d1a73SMilo Kim 		.of_match	= "vcont",
1213a8d1a73SMilo Kim 		.id             = LM3631_LDO_CONT,
1223a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
1233a8d1a73SMilo Kim 		.n_voltages     = LM3631_CONT_VSEL_MAX + 1,
1243a8d1a73SMilo Kim 		.min_uV         = LM3631_VCONT_MIN,
1253a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_500mV,
1263a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1273a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1283a8d1a73SMilo Kim 		.vsel_reg       = LM3631_REG_VOUT_CONT,
1293a8d1a73SMilo Kim 		.vsel_mask      = LM3631_VOUT_CONT_MASK,
1303a8d1a73SMilo Kim 		.enable_reg     = LM3631_REG_LDO_CTRL2,
1313a8d1a73SMilo Kim 		.enable_mask    = LM3631_EN_CONT_MASK,
1323a8d1a73SMilo Kim 	},
1333a8d1a73SMilo Kim 	{
1343a8d1a73SMilo Kim 		.name           = "ldo_oref",
1353a8d1a73SMilo Kim 		.of_match	= "voref",
1363a8d1a73SMilo Kim 		.id             = LM3631_LDO_OREF,
1373a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
1383a8d1a73SMilo Kim 		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1393a8d1a73SMilo Kim 		.min_uV         = LM3631_VLDO_MIN,
1403a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
1413a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1423a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1433a8d1a73SMilo Kim 		.vsel_reg       = LM3631_REG_VOUT_OREF,
1443a8d1a73SMilo Kim 		.vsel_mask      = LM3631_VOUT_MASK,
1453a8d1a73SMilo Kim 		.enable_reg     = LM3631_REG_LDO_CTRL1,
1463a8d1a73SMilo Kim 		.enable_mask    = LM3631_EN_OREF_MASK,
1473a8d1a73SMilo Kim 	},
1483a8d1a73SMilo Kim 	{
1493a8d1a73SMilo Kim 		.name           = "ldo_vpos",
1503a8d1a73SMilo Kim 		.of_match	= "vpos",
1513a8d1a73SMilo Kim 		.id             = LM3631_LDO_POS,
1523a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
1533a8d1a73SMilo Kim 		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1543a8d1a73SMilo Kim 		.min_uV         = LM3631_VLDO_MIN,
1553a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
1563a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1573a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1583a8d1a73SMilo Kim 		.vsel_reg       = LM3631_REG_VOUT_POS,
1593a8d1a73SMilo Kim 		.vsel_mask      = LM3631_VOUT_MASK,
1603a8d1a73SMilo Kim 		.enable_reg     = LM3631_REG_LDO_CTRL1,
1613a8d1a73SMilo Kim 		.enable_mask    = LM3631_EN_VPOS_MASK,
1623a8d1a73SMilo Kim 	},
1633a8d1a73SMilo Kim 	{
1643a8d1a73SMilo Kim 		.name           = "ldo_vneg",
1653a8d1a73SMilo Kim 		.of_match	= "vneg",
1663a8d1a73SMilo Kim 		.id             = LM3631_LDO_NEG,
1673a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
1683a8d1a73SMilo Kim 		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1693a8d1a73SMilo Kim 		.min_uV         = LM3631_VLDO_MIN,
1703a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
1713a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1723a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1733a8d1a73SMilo Kim 		.vsel_reg       = LM3631_REG_VOUT_NEG,
1743a8d1a73SMilo Kim 		.vsel_mask      = LM3631_VOUT_MASK,
1753a8d1a73SMilo Kim 		.enable_reg     = LM3631_REG_LDO_CTRL1,
1763a8d1a73SMilo Kim 		.enable_mask    = LM3631_EN_VNEG_MASK,
1773a8d1a73SMilo Kim 	},
1783a8d1a73SMilo Kim 	/* LM3632 */
1793a8d1a73SMilo Kim 	{
1803a8d1a73SMilo Kim 		.name           = "vboost",
1813a8d1a73SMilo Kim 		.of_match	= "vboost",
1823a8d1a73SMilo Kim 		.id             = LM3632_BOOST,
1833a8d1a73SMilo Kim 		.ops            = &lm363x_boost_voltage_table_ops,
1843a8d1a73SMilo Kim 		.n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
1853a8d1a73SMilo Kim 		.min_uV         = LM3632_VBOOST_MIN,
1863a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
1873a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
1883a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
1893a8d1a73SMilo Kim 		.vsel_reg       = LM3632_REG_VOUT_BOOST,
1903a8d1a73SMilo Kim 		.vsel_mask      = LM3632_VOUT_MASK,
1913a8d1a73SMilo Kim 	},
1923a8d1a73SMilo Kim 	{
1933a8d1a73SMilo Kim 		.name           = "ldo_vpos",
1943a8d1a73SMilo Kim 		.of_match	= "vpos",
1953a8d1a73SMilo Kim 		.id             = LM3632_LDO_POS,
1963a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
1973a8d1a73SMilo Kim 		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
1983a8d1a73SMilo Kim 		.min_uV         = LM3632_VLDO_MIN,
1993a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
2003a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
2013a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
2023a8d1a73SMilo Kim 		.vsel_reg       = LM3632_REG_VOUT_POS,
2033a8d1a73SMilo Kim 		.vsel_mask      = LM3632_VOUT_MASK,
2043a8d1a73SMilo Kim 		.enable_reg     = LM3632_REG_BIAS_CONFIG,
2053a8d1a73SMilo Kim 		.enable_mask    = LM3632_EN_VPOS_MASK,
2063a8d1a73SMilo Kim 	},
2073a8d1a73SMilo Kim 	{
2083a8d1a73SMilo Kim 		.name           = "ldo_vneg",
2093a8d1a73SMilo Kim 		.of_match	= "vneg",
2103a8d1a73SMilo Kim 		.id             = LM3632_LDO_NEG,
2113a8d1a73SMilo Kim 		.ops            = &lm363x_regulator_voltage_table_ops,
2123a8d1a73SMilo Kim 		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
2133a8d1a73SMilo Kim 		.min_uV         = LM3632_VLDO_MIN,
2143a8d1a73SMilo Kim 		.uV_step        = LM363X_STEP_50mV,
2153a8d1a73SMilo Kim 		.type           = REGULATOR_VOLTAGE,
2163a8d1a73SMilo Kim 		.owner          = THIS_MODULE,
2173a8d1a73SMilo Kim 		.vsel_reg       = LM3632_REG_VOUT_NEG,
2183a8d1a73SMilo Kim 		.vsel_mask      = LM3632_VOUT_MASK,
2193a8d1a73SMilo Kim 		.enable_reg     = LM3632_REG_BIAS_CONFIG,
2203a8d1a73SMilo Kim 		.enable_mask    = LM3632_EN_VNEG_MASK,
2213a8d1a73SMilo Kim 	},
222bff5e807SDan Murphy 
223bff5e807SDan Murphy 	/* LM36274 */
224bff5e807SDan Murphy 	{
225bff5e807SDan Murphy 		.name           = "vboost",
226bff5e807SDan Murphy 		.of_match	= "vboost",
227bff5e807SDan Murphy 		.id             = LM36274_BOOST,
228bff5e807SDan Murphy 		.ops            = &lm363x_boost_voltage_table_ops,
229962f170dSAxel Lin 		.n_voltages     = LM36274_BOOST_VSEL_MAX + 1,
230bff5e807SDan Murphy 		.min_uV         = LM36274_VOLTAGE_MIN,
231bff5e807SDan Murphy 		.uV_step        = LM363X_STEP_50mV,
232bff5e807SDan Murphy 		.type           = REGULATOR_VOLTAGE,
233bff5e807SDan Murphy 		.owner          = THIS_MODULE,
234bff5e807SDan Murphy 		.vsel_reg       = LM36274_REG_VOUT_BOOST,
235bff5e807SDan Murphy 		.vsel_mask      = LM36274_VOUT_MASK,
236bff5e807SDan Murphy 	},
237bff5e807SDan Murphy 	{
238bff5e807SDan Murphy 		.name           = "ldo_vpos",
239bff5e807SDan Murphy 		.of_match	= "vpos",
240bff5e807SDan Murphy 		.id             = LM36274_LDO_POS,
241bff5e807SDan Murphy 		.ops            = &lm363x_regulator_voltage_table_ops,
242962f170dSAxel Lin 		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
243bff5e807SDan Murphy 		.min_uV         = LM36274_VOLTAGE_MIN,
244bff5e807SDan Murphy 		.uV_step        = LM363X_STEP_50mV,
245bff5e807SDan Murphy 		.type           = REGULATOR_VOLTAGE,
246bff5e807SDan Murphy 		.owner          = THIS_MODULE,
247bff5e807SDan Murphy 		.vsel_reg       = LM36274_REG_VOUT_POS,
248bff5e807SDan Murphy 		.vsel_mask      = LM36274_VOUT_MASK,
249bff5e807SDan Murphy 		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
250bff5e807SDan Murphy 		.enable_mask    = LM36274_EN_VPOS_MASK,
251bff5e807SDan Murphy 	},
252bff5e807SDan Murphy 	{
253bff5e807SDan Murphy 		.name           = "ldo_vneg",
254bff5e807SDan Murphy 		.of_match	= "vneg",
255bff5e807SDan Murphy 		.id             = LM36274_LDO_NEG,
256bff5e807SDan Murphy 		.ops            = &lm363x_regulator_voltage_table_ops,
257962f170dSAxel Lin 		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
258bff5e807SDan Murphy 		.min_uV         = LM36274_VOLTAGE_MIN,
259bff5e807SDan Murphy 		.uV_step        = LM363X_STEP_50mV,
260bff5e807SDan Murphy 		.type           = REGULATOR_VOLTAGE,
261bff5e807SDan Murphy 		.owner          = THIS_MODULE,
262bff5e807SDan Murphy 		.vsel_reg       = LM36274_REG_VOUT_NEG,
263bff5e807SDan Murphy 		.vsel_mask      = LM36274_VOUT_MASK,
264bff5e807SDan Murphy 		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
265bff5e807SDan Murphy 		.enable_mask    = LM36274_EN_VNEG_MASK,
266bff5e807SDan Murphy 	},
2673a8d1a73SMilo Kim };
2683a8d1a73SMilo Kim 
lm363x_regulator_of_get_enable_gpio(struct device * dev,int id)269b2d751b7SLinus Walleij static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
2703a8d1a73SMilo Kim {
2713a8d1a73SMilo Kim 	/*
2723a8d1a73SMilo Kim 	 * Check LCM_EN1/2_GPIO is configured.
2733a8d1a73SMilo Kim 	 * Those pins are used for enabling VPOS/VNEG LDOs.
274e8a33aa0SLinus Walleij 	 * Do not use devm* here: the regulator core takes over the
275e8a33aa0SLinus Walleij 	 * lifecycle management of the GPIO descriptor.
2763a8d1a73SMilo Kim 	 */
2773a8d1a73SMilo Kim 	switch (id) {
2783a8d1a73SMilo Kim 	case LM3632_LDO_POS:
279bff5e807SDan Murphy 	case LM36274_LDO_POS:
280e8a33aa0SLinus Walleij 		return gpiod_get_index_optional(dev, "enable", 0,
28163239e4bSLinus Walleij 				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
2823a8d1a73SMilo Kim 	case LM3632_LDO_NEG:
283bff5e807SDan Murphy 	case LM36274_LDO_NEG:
284e8a33aa0SLinus Walleij 		return gpiod_get_index_optional(dev, "enable", 1,
28563239e4bSLinus Walleij 				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
2863a8d1a73SMilo Kim 	default:
287b2d751b7SLinus Walleij 		return NULL;
2883a8d1a73SMilo Kim 	}
2893a8d1a73SMilo Kim }
2903a8d1a73SMilo Kim 
lm363x_regulator_set_ext_en(struct regmap * regmap,int id)291bff5e807SDan Murphy static int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
292bff5e807SDan Murphy {
293bff5e807SDan Murphy 	int ext_en_mask = 0;
294bff5e807SDan Murphy 
295bff5e807SDan Murphy 	switch (id) {
296bff5e807SDan Murphy 	case LM3632_LDO_POS:
297bff5e807SDan Murphy 	case LM3632_LDO_NEG:
298bff5e807SDan Murphy 		ext_en_mask = LM3632_EXT_EN_MASK;
299bff5e807SDan Murphy 		break;
300bff5e807SDan Murphy 	case LM36274_LDO_POS:
301bff5e807SDan Murphy 	case LM36274_LDO_NEG:
302bff5e807SDan Murphy 		ext_en_mask = LM36274_EXT_EN_MASK;
303bff5e807SDan Murphy 		break;
304bff5e807SDan Murphy 	default:
305bff5e807SDan Murphy 		return -ENODEV;
306bff5e807SDan Murphy 	}
307bff5e807SDan Murphy 
308bff5e807SDan Murphy 	return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
309bff5e807SDan Murphy 				 ext_en_mask, ext_en_mask);
310bff5e807SDan Murphy }
311bff5e807SDan Murphy 
lm363x_regulator_probe(struct platform_device * pdev)3123a8d1a73SMilo Kim static int lm363x_regulator_probe(struct platform_device *pdev)
3133a8d1a73SMilo Kim {
3143a8d1a73SMilo Kim 	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
3153a8d1a73SMilo Kim 	struct regmap *regmap = lmu->regmap;
3163a8d1a73SMilo Kim 	struct regulator_config cfg = { };
3173a8d1a73SMilo Kim 	struct regulator_dev *rdev;
3183a8d1a73SMilo Kim 	struct device *dev = &pdev->dev;
3193a8d1a73SMilo Kim 	int id = pdev->id;
320b2d751b7SLinus Walleij 	struct gpio_desc *gpiod;
321b2d751b7SLinus Walleij 	int ret;
3223a8d1a73SMilo Kim 
3233a8d1a73SMilo Kim 	cfg.dev = dev;
3243a8d1a73SMilo Kim 	cfg.regmap = regmap;
3253a8d1a73SMilo Kim 
3263a8d1a73SMilo Kim 	/*
3273a8d1a73SMilo Kim 	 * LM3632 LDOs can be controlled by external pin.
3283a8d1a73SMilo Kim 	 * Register update is required if the pin is used.
3293a8d1a73SMilo Kim 	 */
330b2d751b7SLinus Walleij 	gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
331c68f47aaSAxel Lin 	if (IS_ERR(gpiod))
332c68f47aaSAxel Lin 		return PTR_ERR(gpiod);
333c68f47aaSAxel Lin 
334b2d751b7SLinus Walleij 	if (gpiod) {
335b2d751b7SLinus Walleij 		cfg.ena_gpiod = gpiod;
336bff5e807SDan Murphy 		ret = lm363x_regulator_set_ext_en(regmap, id);
3373a8d1a73SMilo Kim 		if (ret) {
338e8a33aa0SLinus Walleij 			gpiod_put(gpiod);
3393a8d1a73SMilo Kim 			dev_err(dev, "External pin err: %d\n", ret);
3403a8d1a73SMilo Kim 			return ret;
3413a8d1a73SMilo Kim 		}
3423a8d1a73SMilo Kim 	}
3433a8d1a73SMilo Kim 
3443a8d1a73SMilo Kim 	rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
3453a8d1a73SMilo Kim 	if (IS_ERR(rdev)) {
3463a8d1a73SMilo Kim 		ret = PTR_ERR(rdev);
3473a8d1a73SMilo Kim 		dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
3483a8d1a73SMilo Kim 		return ret;
3493a8d1a73SMilo Kim 	}
3503a8d1a73SMilo Kim 
3513a8d1a73SMilo Kim 	return 0;
3523a8d1a73SMilo Kim }
3533a8d1a73SMilo Kim 
3543a8d1a73SMilo Kim static struct platform_driver lm363x_regulator_driver = {
3553a8d1a73SMilo Kim 	.probe = lm363x_regulator_probe,
3563a8d1a73SMilo Kim 	.driver = {
3573a8d1a73SMilo Kim 		.name = "lm363x-regulator",
358*259b93b2SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
3593a8d1a73SMilo Kim 	},
3603a8d1a73SMilo Kim };
3613a8d1a73SMilo Kim 
3623a8d1a73SMilo Kim module_platform_driver(lm363x_regulator_driver);
3633a8d1a73SMilo Kim 
3643a8d1a73SMilo Kim MODULE_DESCRIPTION("TI LM363X Regulator Driver");
3653a8d1a73SMilo Kim MODULE_AUTHOR("Milo Kim");
3663a8d1a73SMilo Kim MODULE_LICENSE("GPL v2");
3673a8d1a73SMilo Kim MODULE_ALIAS("platform:lm363x-regulator");
368