162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * TI LM363X Regulator Driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2015 Texas Instruments
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Milo Kim <milo.kim@ti.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/mfd/ti-lmu.h>
1362306a36Sopenharmony_ci#include <linux/mfd/ti-lmu-register.h>
1462306a36Sopenharmony_ci#include <linux/module.h>
1562306a36Sopenharmony_ci#include <linux/of.h>
1662306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1962306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2062306a36Sopenharmony_ci#include <linux/slab.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* LM3631 */
2362306a36Sopenharmony_ci#define LM3631_BOOST_VSEL_MAX		0x25
2462306a36Sopenharmony_ci#define LM3631_LDO_VSEL_MAX		0x28
2562306a36Sopenharmony_ci#define LM3631_CONT_VSEL_MAX		0x03
2662306a36Sopenharmony_ci#define LM3631_VBOOST_MIN		4500000
2762306a36Sopenharmony_ci#define LM3631_VCONT_MIN		1800000
2862306a36Sopenharmony_ci#define LM3631_VLDO_MIN			4000000
2962306a36Sopenharmony_ci#define ENABLE_TIME_USEC		1000
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/* LM3632 */
3262306a36Sopenharmony_ci#define LM3632_BOOST_VSEL_MAX		0x26
3362306a36Sopenharmony_ci#define LM3632_LDO_VSEL_MAX		0x28
3462306a36Sopenharmony_ci#define LM3632_VBOOST_MIN		4500000
3562306a36Sopenharmony_ci#define LM3632_VLDO_MIN			4000000
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* LM36274 */
3862306a36Sopenharmony_ci#define LM36274_BOOST_VSEL_MAX		0x3f
3962306a36Sopenharmony_ci#define LM36274_LDO_VSEL_MAX		0x32
4062306a36Sopenharmony_ci#define LM36274_VOLTAGE_MIN		4000000
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* Common */
4362306a36Sopenharmony_ci#define LM363X_STEP_50mV		50000
4462306a36Sopenharmony_ci#define LM363X_STEP_500mV		500000
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic const int ldo_cont_enable_time[] = {
4762306a36Sopenharmony_ci	0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic int lm363x_regulator_enable_time(struct regulator_dev *rdev)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	enum lm363x_regulator_id id = rdev_get_id(rdev);
5362306a36Sopenharmony_ci	unsigned int val, addr, mask;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	switch (id) {
5662306a36Sopenharmony_ci	case LM3631_LDO_CONT:
5762306a36Sopenharmony_ci		addr = LM3631_REG_ENTIME_VCONT;
5862306a36Sopenharmony_ci		mask = LM3631_ENTIME_CONT_MASK;
5962306a36Sopenharmony_ci		break;
6062306a36Sopenharmony_ci	case LM3631_LDO_OREF:
6162306a36Sopenharmony_ci		addr = LM3631_REG_ENTIME_VOREF;
6262306a36Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
6362306a36Sopenharmony_ci		break;
6462306a36Sopenharmony_ci	case LM3631_LDO_POS:
6562306a36Sopenharmony_ci		addr = LM3631_REG_ENTIME_VPOS;
6662306a36Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
6762306a36Sopenharmony_ci		break;
6862306a36Sopenharmony_ci	case LM3631_LDO_NEG:
6962306a36Sopenharmony_ci		addr = LM3631_REG_ENTIME_VNEG;
7062306a36Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
7162306a36Sopenharmony_ci		break;
7262306a36Sopenharmony_ci	default:
7362306a36Sopenharmony_ci		return 0;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	if (regmap_read(rdev->regmap, addr, &val))
7762306a36Sopenharmony_ci		return -EINVAL;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	val = (val & mask) >> LM3631_ENTIME_SHIFT;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if (id == LM3631_LDO_CONT)
8262306a36Sopenharmony_ci		return ldo_cont_enable_time[val];
8362306a36Sopenharmony_ci	else
8462306a36Sopenharmony_ci		return ENABLE_TIME_USEC * val;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic const struct regulator_ops lm363x_boost_voltage_table_ops = {
8862306a36Sopenharmony_ci	.list_voltage     = regulator_list_voltage_linear,
8962306a36Sopenharmony_ci	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
9062306a36Sopenharmony_ci	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic const struct regulator_ops lm363x_regulator_voltage_table_ops = {
9462306a36Sopenharmony_ci	.list_voltage     = regulator_list_voltage_linear,
9562306a36Sopenharmony_ci	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
9662306a36Sopenharmony_ci	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
9762306a36Sopenharmony_ci	.enable           = regulator_enable_regmap,
9862306a36Sopenharmony_ci	.disable          = regulator_disable_regmap,
9962306a36Sopenharmony_ci	.is_enabled       = regulator_is_enabled_regmap,
10062306a36Sopenharmony_ci	.enable_time      = lm363x_regulator_enable_time,
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic const struct regulator_desc lm363x_regulator_desc[] = {
10462306a36Sopenharmony_ci	/* LM3631 */
10562306a36Sopenharmony_ci	{
10662306a36Sopenharmony_ci		.name           = "vboost",
10762306a36Sopenharmony_ci		.of_match	= "vboost",
10862306a36Sopenharmony_ci		.id             = LM3631_BOOST,
10962306a36Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
11062306a36Sopenharmony_ci		.n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
11162306a36Sopenharmony_ci		.min_uV         = LM3631_VBOOST_MIN,
11262306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
11362306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
11462306a36Sopenharmony_ci		.owner          = THIS_MODULE,
11562306a36Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_BOOST,
11662306a36Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
11762306a36Sopenharmony_ci	},
11862306a36Sopenharmony_ci	{
11962306a36Sopenharmony_ci		.name           = "ldo_cont",
12062306a36Sopenharmony_ci		.of_match	= "vcont",
12162306a36Sopenharmony_ci		.id             = LM3631_LDO_CONT,
12262306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
12362306a36Sopenharmony_ci		.n_voltages     = LM3631_CONT_VSEL_MAX + 1,
12462306a36Sopenharmony_ci		.min_uV         = LM3631_VCONT_MIN,
12562306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_500mV,
12662306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
12762306a36Sopenharmony_ci		.owner          = THIS_MODULE,
12862306a36Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_CONT,
12962306a36Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_CONT_MASK,
13062306a36Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL2,
13162306a36Sopenharmony_ci		.enable_mask    = LM3631_EN_CONT_MASK,
13262306a36Sopenharmony_ci	},
13362306a36Sopenharmony_ci	{
13462306a36Sopenharmony_ci		.name           = "ldo_oref",
13562306a36Sopenharmony_ci		.of_match	= "voref",
13662306a36Sopenharmony_ci		.id             = LM3631_LDO_OREF,
13762306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
13862306a36Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
13962306a36Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
14062306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
14162306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
14262306a36Sopenharmony_ci		.owner          = THIS_MODULE,
14362306a36Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_OREF,
14462306a36Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
14562306a36Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
14662306a36Sopenharmony_ci		.enable_mask    = LM3631_EN_OREF_MASK,
14762306a36Sopenharmony_ci	},
14862306a36Sopenharmony_ci	{
14962306a36Sopenharmony_ci		.name           = "ldo_vpos",
15062306a36Sopenharmony_ci		.of_match	= "vpos",
15162306a36Sopenharmony_ci		.id             = LM3631_LDO_POS,
15262306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
15362306a36Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
15462306a36Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
15562306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
15662306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
15762306a36Sopenharmony_ci		.owner          = THIS_MODULE,
15862306a36Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_POS,
15962306a36Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
16062306a36Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
16162306a36Sopenharmony_ci		.enable_mask    = LM3631_EN_VPOS_MASK,
16262306a36Sopenharmony_ci	},
16362306a36Sopenharmony_ci	{
16462306a36Sopenharmony_ci		.name           = "ldo_vneg",
16562306a36Sopenharmony_ci		.of_match	= "vneg",
16662306a36Sopenharmony_ci		.id             = LM3631_LDO_NEG,
16762306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
16862306a36Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
16962306a36Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
17062306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
17162306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
17262306a36Sopenharmony_ci		.owner          = THIS_MODULE,
17362306a36Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_NEG,
17462306a36Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
17562306a36Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
17662306a36Sopenharmony_ci		.enable_mask    = LM3631_EN_VNEG_MASK,
17762306a36Sopenharmony_ci	},
17862306a36Sopenharmony_ci	/* LM3632 */
17962306a36Sopenharmony_ci	{
18062306a36Sopenharmony_ci		.name           = "vboost",
18162306a36Sopenharmony_ci		.of_match	= "vboost",
18262306a36Sopenharmony_ci		.id             = LM3632_BOOST,
18362306a36Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
18462306a36Sopenharmony_ci		.n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
18562306a36Sopenharmony_ci		.min_uV         = LM3632_VBOOST_MIN,
18662306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
18762306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
18862306a36Sopenharmony_ci		.owner          = THIS_MODULE,
18962306a36Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_BOOST,
19062306a36Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
19162306a36Sopenharmony_ci	},
19262306a36Sopenharmony_ci	{
19362306a36Sopenharmony_ci		.name           = "ldo_vpos",
19462306a36Sopenharmony_ci		.of_match	= "vpos",
19562306a36Sopenharmony_ci		.id             = LM3632_LDO_POS,
19662306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
19762306a36Sopenharmony_ci		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
19862306a36Sopenharmony_ci		.min_uV         = LM3632_VLDO_MIN,
19962306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
20062306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
20162306a36Sopenharmony_ci		.owner          = THIS_MODULE,
20262306a36Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_POS,
20362306a36Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
20462306a36Sopenharmony_ci		.enable_reg     = LM3632_REG_BIAS_CONFIG,
20562306a36Sopenharmony_ci		.enable_mask    = LM3632_EN_VPOS_MASK,
20662306a36Sopenharmony_ci	},
20762306a36Sopenharmony_ci	{
20862306a36Sopenharmony_ci		.name           = "ldo_vneg",
20962306a36Sopenharmony_ci		.of_match	= "vneg",
21062306a36Sopenharmony_ci		.id             = LM3632_LDO_NEG,
21162306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
21262306a36Sopenharmony_ci		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
21362306a36Sopenharmony_ci		.min_uV         = LM3632_VLDO_MIN,
21462306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
21562306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
21662306a36Sopenharmony_ci		.owner          = THIS_MODULE,
21762306a36Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_NEG,
21862306a36Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
21962306a36Sopenharmony_ci		.enable_reg     = LM3632_REG_BIAS_CONFIG,
22062306a36Sopenharmony_ci		.enable_mask    = LM3632_EN_VNEG_MASK,
22162306a36Sopenharmony_ci	},
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	/* LM36274 */
22462306a36Sopenharmony_ci	{
22562306a36Sopenharmony_ci		.name           = "vboost",
22662306a36Sopenharmony_ci		.of_match	= "vboost",
22762306a36Sopenharmony_ci		.id             = LM36274_BOOST,
22862306a36Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
22962306a36Sopenharmony_ci		.n_voltages     = LM36274_BOOST_VSEL_MAX + 1,
23062306a36Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
23162306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
23262306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
23362306a36Sopenharmony_ci		.owner          = THIS_MODULE,
23462306a36Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_BOOST,
23562306a36Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
23662306a36Sopenharmony_ci	},
23762306a36Sopenharmony_ci	{
23862306a36Sopenharmony_ci		.name           = "ldo_vpos",
23962306a36Sopenharmony_ci		.of_match	= "vpos",
24062306a36Sopenharmony_ci		.id             = LM36274_LDO_POS,
24162306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
24262306a36Sopenharmony_ci		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
24362306a36Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
24462306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
24562306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
24662306a36Sopenharmony_ci		.owner          = THIS_MODULE,
24762306a36Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_POS,
24862306a36Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
24962306a36Sopenharmony_ci		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
25062306a36Sopenharmony_ci		.enable_mask    = LM36274_EN_VPOS_MASK,
25162306a36Sopenharmony_ci	},
25262306a36Sopenharmony_ci	{
25362306a36Sopenharmony_ci		.name           = "ldo_vneg",
25462306a36Sopenharmony_ci		.of_match	= "vneg",
25562306a36Sopenharmony_ci		.id             = LM36274_LDO_NEG,
25662306a36Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
25762306a36Sopenharmony_ci		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
25862306a36Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
25962306a36Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
26062306a36Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
26162306a36Sopenharmony_ci		.owner          = THIS_MODULE,
26262306a36Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_NEG,
26362306a36Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
26462306a36Sopenharmony_ci		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
26562306a36Sopenharmony_ci		.enable_mask    = LM36274_EN_VNEG_MASK,
26662306a36Sopenharmony_ci	},
26762306a36Sopenharmony_ci};
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	/*
27262306a36Sopenharmony_ci	 * Check LCM_EN1/2_GPIO is configured.
27362306a36Sopenharmony_ci	 * Those pins are used for enabling VPOS/VNEG LDOs.
27462306a36Sopenharmony_ci	 * Do not use devm* here: the regulator core takes over the
27562306a36Sopenharmony_ci	 * lifecycle management of the GPIO descriptor.
27662306a36Sopenharmony_ci	 */
27762306a36Sopenharmony_ci	switch (id) {
27862306a36Sopenharmony_ci	case LM3632_LDO_POS:
27962306a36Sopenharmony_ci	case LM36274_LDO_POS:
28062306a36Sopenharmony_ci		return gpiod_get_index_optional(dev, "enable", 0,
28162306a36Sopenharmony_ci				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
28262306a36Sopenharmony_ci	case LM3632_LDO_NEG:
28362306a36Sopenharmony_ci	case LM36274_LDO_NEG:
28462306a36Sopenharmony_ci		return gpiod_get_index_optional(dev, "enable", 1,
28562306a36Sopenharmony_ci				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
28662306a36Sopenharmony_ci	default:
28762306a36Sopenharmony_ci		return NULL;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	int ext_en_mask = 0;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	switch (id) {
29662306a36Sopenharmony_ci	case LM3632_LDO_POS:
29762306a36Sopenharmony_ci	case LM3632_LDO_NEG:
29862306a36Sopenharmony_ci		ext_en_mask = LM3632_EXT_EN_MASK;
29962306a36Sopenharmony_ci		break;
30062306a36Sopenharmony_ci	case LM36274_LDO_POS:
30162306a36Sopenharmony_ci	case LM36274_LDO_NEG:
30262306a36Sopenharmony_ci		ext_en_mask = LM36274_EXT_EN_MASK;
30362306a36Sopenharmony_ci		break;
30462306a36Sopenharmony_ci	default:
30562306a36Sopenharmony_ci		return -ENODEV;
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
30962306a36Sopenharmony_ci				 ext_en_mask, ext_en_mask);
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic int lm363x_regulator_probe(struct platform_device *pdev)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
31562306a36Sopenharmony_ci	struct regmap *regmap = lmu->regmap;
31662306a36Sopenharmony_ci	struct regulator_config cfg = { };
31762306a36Sopenharmony_ci	struct regulator_dev *rdev;
31862306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
31962306a36Sopenharmony_ci	int id = pdev->id;
32062306a36Sopenharmony_ci	struct gpio_desc *gpiod;
32162306a36Sopenharmony_ci	int ret;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	cfg.dev = dev;
32462306a36Sopenharmony_ci	cfg.regmap = regmap;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/*
32762306a36Sopenharmony_ci	 * LM3632 LDOs can be controlled by external pin.
32862306a36Sopenharmony_ci	 * Register update is required if the pin is used.
32962306a36Sopenharmony_ci	 */
33062306a36Sopenharmony_ci	gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
33162306a36Sopenharmony_ci	if (IS_ERR(gpiod))
33262306a36Sopenharmony_ci		return PTR_ERR(gpiod);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (gpiod) {
33562306a36Sopenharmony_ci		cfg.ena_gpiod = gpiod;
33662306a36Sopenharmony_ci		ret = lm363x_regulator_set_ext_en(regmap, id);
33762306a36Sopenharmony_ci		if (ret) {
33862306a36Sopenharmony_ci			gpiod_put(gpiod);
33962306a36Sopenharmony_ci			dev_err(dev, "External pin err: %d\n", ret);
34062306a36Sopenharmony_ci			return ret;
34162306a36Sopenharmony_ci		}
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
34562306a36Sopenharmony_ci	if (IS_ERR(rdev)) {
34662306a36Sopenharmony_ci		ret = PTR_ERR(rdev);
34762306a36Sopenharmony_ci		dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
34862306a36Sopenharmony_ci		return ret;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	return 0;
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic struct platform_driver lm363x_regulator_driver = {
35562306a36Sopenharmony_ci	.probe = lm363x_regulator_probe,
35662306a36Sopenharmony_ci	.driver = {
35762306a36Sopenharmony_ci		.name = "lm363x-regulator",
35862306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
35962306a36Sopenharmony_ci	},
36062306a36Sopenharmony_ci};
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cimodule_platform_driver(lm363x_regulator_driver);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ciMODULE_DESCRIPTION("TI LM363X Regulator Driver");
36562306a36Sopenharmony_ciMODULE_AUTHOR("Milo Kim");
36662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
36762306a36Sopenharmony_ciMODULE_ALIAS("platform:lm363x-regulator");
368