18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * TI LM363X Regulator Driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2015 Texas Instruments
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Author: Milo Kim <milo.kim@ti.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/err.h>
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/mfd/ti-lmu.h>
138c2ecf20Sopenharmony_ci#include <linux/mfd/ti-lmu-register.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/of.h>
168c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
178c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
188c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h>
198c2ecf20Sopenharmony_ci#include <linux/regulator/of_regulator.h>
208c2ecf20Sopenharmony_ci#include <linux/slab.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* LM3631 */
238c2ecf20Sopenharmony_ci#define LM3631_BOOST_VSEL_MAX		0x25
248c2ecf20Sopenharmony_ci#define LM3631_LDO_VSEL_MAX		0x28
258c2ecf20Sopenharmony_ci#define LM3631_CONT_VSEL_MAX		0x03
268c2ecf20Sopenharmony_ci#define LM3631_VBOOST_MIN		4500000
278c2ecf20Sopenharmony_ci#define LM3631_VCONT_MIN		1800000
288c2ecf20Sopenharmony_ci#define LM3631_VLDO_MIN			4000000
298c2ecf20Sopenharmony_ci#define ENABLE_TIME_USEC		1000
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* LM3632 */
328c2ecf20Sopenharmony_ci#define LM3632_BOOST_VSEL_MAX		0x26
338c2ecf20Sopenharmony_ci#define LM3632_LDO_VSEL_MAX		0x28
348c2ecf20Sopenharmony_ci#define LM3632_VBOOST_MIN		4500000
358c2ecf20Sopenharmony_ci#define LM3632_VLDO_MIN			4000000
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* LM36274 */
388c2ecf20Sopenharmony_ci#define LM36274_BOOST_VSEL_MAX		0x3f
398c2ecf20Sopenharmony_ci#define LM36274_LDO_VSEL_MAX		0x32
408c2ecf20Sopenharmony_ci#define LM36274_VOLTAGE_MIN		4000000
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* Common */
438c2ecf20Sopenharmony_ci#define LM363X_STEP_50mV		50000
448c2ecf20Sopenharmony_ci#define LM363X_STEP_500mV		500000
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic const int ldo_cont_enable_time[] = {
478c2ecf20Sopenharmony_ci	0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic int lm363x_regulator_enable_time(struct regulator_dev *rdev)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	enum lm363x_regulator_id id = rdev_get_id(rdev);
538c2ecf20Sopenharmony_ci	unsigned int val, addr, mask;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	switch (id) {
568c2ecf20Sopenharmony_ci	case LM3631_LDO_CONT:
578c2ecf20Sopenharmony_ci		addr = LM3631_REG_ENTIME_VCONT;
588c2ecf20Sopenharmony_ci		mask = LM3631_ENTIME_CONT_MASK;
598c2ecf20Sopenharmony_ci		break;
608c2ecf20Sopenharmony_ci	case LM3631_LDO_OREF:
618c2ecf20Sopenharmony_ci		addr = LM3631_REG_ENTIME_VOREF;
628c2ecf20Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
638c2ecf20Sopenharmony_ci		break;
648c2ecf20Sopenharmony_ci	case LM3631_LDO_POS:
658c2ecf20Sopenharmony_ci		addr = LM3631_REG_ENTIME_VPOS;
668c2ecf20Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
678c2ecf20Sopenharmony_ci		break;
688c2ecf20Sopenharmony_ci	case LM3631_LDO_NEG:
698c2ecf20Sopenharmony_ci		addr = LM3631_REG_ENTIME_VNEG;
708c2ecf20Sopenharmony_ci		mask = LM3631_ENTIME_MASK;
718c2ecf20Sopenharmony_ci		break;
728c2ecf20Sopenharmony_ci	default:
738c2ecf20Sopenharmony_ci		return 0;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	if (regmap_read(rdev->regmap, addr, &val))
778c2ecf20Sopenharmony_ci		return -EINVAL;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	val = (val & mask) >> LM3631_ENTIME_SHIFT;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	if (id == LM3631_LDO_CONT)
828c2ecf20Sopenharmony_ci		return ldo_cont_enable_time[val];
838c2ecf20Sopenharmony_ci	else
848c2ecf20Sopenharmony_ci		return ENABLE_TIME_USEC * val;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic const struct regulator_ops lm363x_boost_voltage_table_ops = {
888c2ecf20Sopenharmony_ci	.list_voltage     = regulator_list_voltage_linear,
898c2ecf20Sopenharmony_ci	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
908c2ecf20Sopenharmony_ci	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic const struct regulator_ops lm363x_regulator_voltage_table_ops = {
948c2ecf20Sopenharmony_ci	.list_voltage     = regulator_list_voltage_linear,
958c2ecf20Sopenharmony_ci	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
968c2ecf20Sopenharmony_ci	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
978c2ecf20Sopenharmony_ci	.enable           = regulator_enable_regmap,
988c2ecf20Sopenharmony_ci	.disable          = regulator_disable_regmap,
998c2ecf20Sopenharmony_ci	.is_enabled       = regulator_is_enabled_regmap,
1008c2ecf20Sopenharmony_ci	.enable_time      = lm363x_regulator_enable_time,
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic const struct regulator_desc lm363x_regulator_desc[] = {
1048c2ecf20Sopenharmony_ci	/* LM3631 */
1058c2ecf20Sopenharmony_ci	{
1068c2ecf20Sopenharmony_ci		.name           = "vboost",
1078c2ecf20Sopenharmony_ci		.of_match	= "vboost",
1088c2ecf20Sopenharmony_ci		.id             = LM3631_BOOST,
1098c2ecf20Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
1108c2ecf20Sopenharmony_ci		.n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
1118c2ecf20Sopenharmony_ci		.min_uV         = LM3631_VBOOST_MIN,
1128c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
1138c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1148c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1158c2ecf20Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_BOOST,
1168c2ecf20Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
1178c2ecf20Sopenharmony_ci	},
1188c2ecf20Sopenharmony_ci	{
1198c2ecf20Sopenharmony_ci		.name           = "ldo_cont",
1208c2ecf20Sopenharmony_ci		.of_match	= "vcont",
1218c2ecf20Sopenharmony_ci		.id             = LM3631_LDO_CONT,
1228c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
1238c2ecf20Sopenharmony_ci		.n_voltages     = LM3631_CONT_VSEL_MAX + 1,
1248c2ecf20Sopenharmony_ci		.min_uV         = LM3631_VCONT_MIN,
1258c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_500mV,
1268c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1278c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1288c2ecf20Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_CONT,
1298c2ecf20Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_CONT_MASK,
1308c2ecf20Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL2,
1318c2ecf20Sopenharmony_ci		.enable_mask    = LM3631_EN_CONT_MASK,
1328c2ecf20Sopenharmony_ci	},
1338c2ecf20Sopenharmony_ci	{
1348c2ecf20Sopenharmony_ci		.name           = "ldo_oref",
1358c2ecf20Sopenharmony_ci		.of_match	= "voref",
1368c2ecf20Sopenharmony_ci		.id             = LM3631_LDO_OREF,
1378c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
1388c2ecf20Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1398c2ecf20Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
1408c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
1418c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1428c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1438c2ecf20Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_OREF,
1448c2ecf20Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
1458c2ecf20Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
1468c2ecf20Sopenharmony_ci		.enable_mask    = LM3631_EN_OREF_MASK,
1478c2ecf20Sopenharmony_ci	},
1488c2ecf20Sopenharmony_ci	{
1498c2ecf20Sopenharmony_ci		.name           = "ldo_vpos",
1508c2ecf20Sopenharmony_ci		.of_match	= "vpos",
1518c2ecf20Sopenharmony_ci		.id             = LM3631_LDO_POS,
1528c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
1538c2ecf20Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1548c2ecf20Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
1558c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
1568c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1578c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1588c2ecf20Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_POS,
1598c2ecf20Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
1608c2ecf20Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
1618c2ecf20Sopenharmony_ci		.enable_mask    = LM3631_EN_VPOS_MASK,
1628c2ecf20Sopenharmony_ci	},
1638c2ecf20Sopenharmony_ci	{
1648c2ecf20Sopenharmony_ci		.name           = "ldo_vneg",
1658c2ecf20Sopenharmony_ci		.of_match	= "vneg",
1668c2ecf20Sopenharmony_ci		.id             = LM3631_LDO_NEG,
1678c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
1688c2ecf20Sopenharmony_ci		.n_voltages     = LM3631_LDO_VSEL_MAX + 1,
1698c2ecf20Sopenharmony_ci		.min_uV         = LM3631_VLDO_MIN,
1708c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
1718c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1728c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1738c2ecf20Sopenharmony_ci		.vsel_reg       = LM3631_REG_VOUT_NEG,
1748c2ecf20Sopenharmony_ci		.vsel_mask      = LM3631_VOUT_MASK,
1758c2ecf20Sopenharmony_ci		.enable_reg     = LM3631_REG_LDO_CTRL1,
1768c2ecf20Sopenharmony_ci		.enable_mask    = LM3631_EN_VNEG_MASK,
1778c2ecf20Sopenharmony_ci	},
1788c2ecf20Sopenharmony_ci	/* LM3632 */
1798c2ecf20Sopenharmony_ci	{
1808c2ecf20Sopenharmony_ci		.name           = "vboost",
1818c2ecf20Sopenharmony_ci		.of_match	= "vboost",
1828c2ecf20Sopenharmony_ci		.id             = LM3632_BOOST,
1838c2ecf20Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
1848c2ecf20Sopenharmony_ci		.n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
1858c2ecf20Sopenharmony_ci		.min_uV         = LM3632_VBOOST_MIN,
1868c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
1878c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
1888c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
1898c2ecf20Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_BOOST,
1908c2ecf20Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
1918c2ecf20Sopenharmony_ci	},
1928c2ecf20Sopenharmony_ci	{
1938c2ecf20Sopenharmony_ci		.name           = "ldo_vpos",
1948c2ecf20Sopenharmony_ci		.of_match	= "vpos",
1958c2ecf20Sopenharmony_ci		.id             = LM3632_LDO_POS,
1968c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
1978c2ecf20Sopenharmony_ci		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
1988c2ecf20Sopenharmony_ci		.min_uV         = LM3632_VLDO_MIN,
1998c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
2008c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
2018c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
2028c2ecf20Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_POS,
2038c2ecf20Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
2048c2ecf20Sopenharmony_ci		.enable_reg     = LM3632_REG_BIAS_CONFIG,
2058c2ecf20Sopenharmony_ci		.enable_mask    = LM3632_EN_VPOS_MASK,
2068c2ecf20Sopenharmony_ci	},
2078c2ecf20Sopenharmony_ci	{
2088c2ecf20Sopenharmony_ci		.name           = "ldo_vneg",
2098c2ecf20Sopenharmony_ci		.of_match	= "vneg",
2108c2ecf20Sopenharmony_ci		.id             = LM3632_LDO_NEG,
2118c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
2128c2ecf20Sopenharmony_ci		.n_voltages     = LM3632_LDO_VSEL_MAX + 1,
2138c2ecf20Sopenharmony_ci		.min_uV         = LM3632_VLDO_MIN,
2148c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
2158c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
2168c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
2178c2ecf20Sopenharmony_ci		.vsel_reg       = LM3632_REG_VOUT_NEG,
2188c2ecf20Sopenharmony_ci		.vsel_mask      = LM3632_VOUT_MASK,
2198c2ecf20Sopenharmony_ci		.enable_reg     = LM3632_REG_BIAS_CONFIG,
2208c2ecf20Sopenharmony_ci		.enable_mask    = LM3632_EN_VNEG_MASK,
2218c2ecf20Sopenharmony_ci	},
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* LM36274 */
2248c2ecf20Sopenharmony_ci	{
2258c2ecf20Sopenharmony_ci		.name           = "vboost",
2268c2ecf20Sopenharmony_ci		.of_match	= "vboost",
2278c2ecf20Sopenharmony_ci		.id             = LM36274_BOOST,
2288c2ecf20Sopenharmony_ci		.ops            = &lm363x_boost_voltage_table_ops,
2298c2ecf20Sopenharmony_ci		.n_voltages     = LM36274_BOOST_VSEL_MAX + 1,
2308c2ecf20Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
2318c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
2328c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
2338c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
2348c2ecf20Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_BOOST,
2358c2ecf20Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
2368c2ecf20Sopenharmony_ci	},
2378c2ecf20Sopenharmony_ci	{
2388c2ecf20Sopenharmony_ci		.name           = "ldo_vpos",
2398c2ecf20Sopenharmony_ci		.of_match	= "vpos",
2408c2ecf20Sopenharmony_ci		.id             = LM36274_LDO_POS,
2418c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
2428c2ecf20Sopenharmony_ci		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
2438c2ecf20Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
2448c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
2458c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
2468c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
2478c2ecf20Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_POS,
2488c2ecf20Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
2498c2ecf20Sopenharmony_ci		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
2508c2ecf20Sopenharmony_ci		.enable_mask    = LM36274_EN_VPOS_MASK,
2518c2ecf20Sopenharmony_ci	},
2528c2ecf20Sopenharmony_ci	{
2538c2ecf20Sopenharmony_ci		.name           = "ldo_vneg",
2548c2ecf20Sopenharmony_ci		.of_match	= "vneg",
2558c2ecf20Sopenharmony_ci		.id             = LM36274_LDO_NEG,
2568c2ecf20Sopenharmony_ci		.ops            = &lm363x_regulator_voltage_table_ops,
2578c2ecf20Sopenharmony_ci		.n_voltages     = LM36274_LDO_VSEL_MAX + 1,
2588c2ecf20Sopenharmony_ci		.min_uV         = LM36274_VOLTAGE_MIN,
2598c2ecf20Sopenharmony_ci		.uV_step        = LM363X_STEP_50mV,
2608c2ecf20Sopenharmony_ci		.type           = REGULATOR_VOLTAGE,
2618c2ecf20Sopenharmony_ci		.owner          = THIS_MODULE,
2628c2ecf20Sopenharmony_ci		.vsel_reg       = LM36274_REG_VOUT_NEG,
2638c2ecf20Sopenharmony_ci		.vsel_mask      = LM36274_VOUT_MASK,
2648c2ecf20Sopenharmony_ci		.enable_reg     = LM36274_REG_BIAS_CONFIG_1,
2658c2ecf20Sopenharmony_ci		.enable_mask    = LM36274_EN_VNEG_MASK,
2668c2ecf20Sopenharmony_ci	},
2678c2ecf20Sopenharmony_ci};
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	/*
2728c2ecf20Sopenharmony_ci	 * Check LCM_EN1/2_GPIO is configured.
2738c2ecf20Sopenharmony_ci	 * Those pins are used for enabling VPOS/VNEG LDOs.
2748c2ecf20Sopenharmony_ci	 * Do not use devm* here: the regulator core takes over the
2758c2ecf20Sopenharmony_ci	 * lifecycle management of the GPIO descriptor.
2768c2ecf20Sopenharmony_ci	 */
2778c2ecf20Sopenharmony_ci	switch (id) {
2788c2ecf20Sopenharmony_ci	case LM3632_LDO_POS:
2798c2ecf20Sopenharmony_ci	case LM36274_LDO_POS:
2808c2ecf20Sopenharmony_ci		return gpiod_get_index_optional(dev, "enable", 0,
2818c2ecf20Sopenharmony_ci				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
2828c2ecf20Sopenharmony_ci	case LM3632_LDO_NEG:
2838c2ecf20Sopenharmony_ci	case LM36274_LDO_NEG:
2848c2ecf20Sopenharmony_ci		return gpiod_get_index_optional(dev, "enable", 1,
2858c2ecf20Sopenharmony_ci				GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
2868c2ecf20Sopenharmony_ci	default:
2878c2ecf20Sopenharmony_ci		return NULL;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	int ext_en_mask = 0;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	switch (id) {
2968c2ecf20Sopenharmony_ci	case LM3632_LDO_POS:
2978c2ecf20Sopenharmony_ci	case LM3632_LDO_NEG:
2988c2ecf20Sopenharmony_ci		ext_en_mask = LM3632_EXT_EN_MASK;
2998c2ecf20Sopenharmony_ci		break;
3008c2ecf20Sopenharmony_ci	case LM36274_LDO_POS:
3018c2ecf20Sopenharmony_ci	case LM36274_LDO_NEG:
3028c2ecf20Sopenharmony_ci		ext_en_mask = LM36274_EXT_EN_MASK;
3038c2ecf20Sopenharmony_ci		break;
3048c2ecf20Sopenharmony_ci	default:
3058c2ecf20Sopenharmony_ci		return -ENODEV;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
3098c2ecf20Sopenharmony_ci				 ext_en_mask, ext_en_mask);
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic int lm363x_regulator_probe(struct platform_device *pdev)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
3158c2ecf20Sopenharmony_ci	struct regmap *regmap = lmu->regmap;
3168c2ecf20Sopenharmony_ci	struct regulator_config cfg = { };
3178c2ecf20Sopenharmony_ci	struct regulator_dev *rdev;
3188c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
3198c2ecf20Sopenharmony_ci	int id = pdev->id;
3208c2ecf20Sopenharmony_ci	struct gpio_desc *gpiod;
3218c2ecf20Sopenharmony_ci	int ret;
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	cfg.dev = dev;
3248c2ecf20Sopenharmony_ci	cfg.regmap = regmap;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/*
3278c2ecf20Sopenharmony_ci	 * LM3632 LDOs can be controlled by external pin.
3288c2ecf20Sopenharmony_ci	 * Register update is required if the pin is used.
3298c2ecf20Sopenharmony_ci	 */
3308c2ecf20Sopenharmony_ci	gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
3318c2ecf20Sopenharmony_ci	if (IS_ERR(gpiod))
3328c2ecf20Sopenharmony_ci		return PTR_ERR(gpiod);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	if (gpiod) {
3358c2ecf20Sopenharmony_ci		cfg.ena_gpiod = gpiod;
3368c2ecf20Sopenharmony_ci		ret = lm363x_regulator_set_ext_en(regmap, id);
3378c2ecf20Sopenharmony_ci		if (ret) {
3388c2ecf20Sopenharmony_ci			gpiod_put(gpiod);
3398c2ecf20Sopenharmony_ci			dev_err(dev, "External pin err: %d\n", ret);
3408c2ecf20Sopenharmony_ci			return ret;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
3458c2ecf20Sopenharmony_ci	if (IS_ERR(rdev)) {
3468c2ecf20Sopenharmony_ci		ret = PTR_ERR(rdev);
3478c2ecf20Sopenharmony_ci		dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
3488c2ecf20Sopenharmony_ci		return ret;
3498c2ecf20Sopenharmony_ci	}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	return 0;
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic struct platform_driver lm363x_regulator_driver = {
3558c2ecf20Sopenharmony_ci	.probe = lm363x_regulator_probe,
3568c2ecf20Sopenharmony_ci	.driver = {
3578c2ecf20Sopenharmony_ci		.name = "lm363x-regulator",
3588c2ecf20Sopenharmony_ci	},
3598c2ecf20Sopenharmony_ci};
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cimodule_platform_driver(lm363x_regulator_driver);
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TI LM363X Regulator Driver");
3648c2ecf20Sopenharmony_ciMODULE_AUTHOR("Milo Kim");
3658c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
3668c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:lm363x-regulator");
367