1e8858ba8SMarkuss Broks // SPDX-License-Identifier: GPL-2.0-only
2e8858ba8SMarkuss Broks 
3e8858ba8SMarkuss Broks #include <linux/mfd/sm5703.h>
4e8858ba8SMarkuss Broks #include <linux/module.h>
5e8858ba8SMarkuss Broks #include <linux/mod_devicetable.h>
6e8858ba8SMarkuss Broks #include <linux/platform_device.h>
7e8858ba8SMarkuss Broks #include <linux/regmap.h>
8e8858ba8SMarkuss Broks #include <linux/regulator/driver.h>
9e8858ba8SMarkuss Broks #include <linux/regulator/of_regulator.h>
10e8858ba8SMarkuss Broks 
11e8858ba8SMarkuss Broks enum sm5703_regulators {
12e8858ba8SMarkuss Broks 	SM5703_BUCK,
13e8858ba8SMarkuss Broks 	SM5703_LDO1,
14e8858ba8SMarkuss Broks 	SM5703_LDO2,
15e8858ba8SMarkuss Broks 	SM5703_LDO3,
16e8858ba8SMarkuss Broks 	SM5703_USBLDO1,
17e8858ba8SMarkuss Broks 	SM5703_USBLDO2,
18e8858ba8SMarkuss Broks 	SM5703_VBUS,
19e8858ba8SMarkuss Broks 	SM5703_MAX_REGULATORS,
20e8858ba8SMarkuss Broks };
21e8858ba8SMarkuss Broks 
22e8858ba8SMarkuss Broks static const int sm5703_ldo_voltagemap[] = {
23e8858ba8SMarkuss Broks 	1500000, 1800000, 2600000, 2800000, 3000000, 3300000,
24e8858ba8SMarkuss Broks };
25e8858ba8SMarkuss Broks 
26e8858ba8SMarkuss Broks static const int sm5703_buck_voltagemap[] = {
27e8858ba8SMarkuss Broks 	1000000, 1000000, 1000000, 1000000,
28e8858ba8SMarkuss Broks 	1000000, 1000000, 1000000, 1000000,
29e8858ba8SMarkuss Broks 	1000000, 1000000, 1000000, 1100000,
30e8858ba8SMarkuss Broks 	1200000, 1300000, 1400000, 1500000,
31e8858ba8SMarkuss Broks 	1600000, 1700000, 1800000, 1900000,
32e8858ba8SMarkuss Broks 	2000000, 2100000, 2200000, 2300000,
33e8858ba8SMarkuss Broks 	2400000, 2500000, 2600000, 2700000,
34e8858ba8SMarkuss Broks 	2800000, 2900000, 3000000, 3000000,
35e8858ba8SMarkuss Broks };
36e8858ba8SMarkuss Broks 
37e8858ba8SMarkuss Broks #define SM5703USBLDO(_name, _id)					\
38e8858ba8SMarkuss Broks 	[SM5703_USBLDO ## _id] = {					\
39e8858ba8SMarkuss Broks 		.name = _name,						\
40e8858ba8SMarkuss Broks 		.of_match = _name,					\
41e8858ba8SMarkuss Broks 		.regulators_node = "regulators",			\
42e8858ba8SMarkuss Broks 		.type = REGULATOR_VOLTAGE,				\
43e8858ba8SMarkuss Broks 		.id = SM5703_USBLDO ## _id,				\
44e8858ba8SMarkuss Broks 		.ops = &sm5703_regulator_ops_fixed,			\
45*7c750406SAxel Lin 		.n_voltages = 1,					\
46e8858ba8SMarkuss Broks 		.fixed_uV = SM5703_USBLDO_MICROVOLT,			\
47e8858ba8SMarkuss Broks 		.enable_reg = SM5703_REG_USBLDO12,			\
48e8858ba8SMarkuss Broks 		.enable_mask = SM5703_REG_EN_USBLDO ##_id,		\
49e8858ba8SMarkuss Broks 		.owner			= THIS_MODULE,			\
50e8858ba8SMarkuss Broks 	}
51e8858ba8SMarkuss Broks 
52e8858ba8SMarkuss Broks #define SM5703VBUS(_name)						\
53e8858ba8SMarkuss Broks 	[SM5703_VBUS] = {						\
54e8858ba8SMarkuss Broks 		.name = _name,						\
55e8858ba8SMarkuss Broks 		.of_match = _name,					\
56e8858ba8SMarkuss Broks 		.regulators_node = "regulators",			\
57e8858ba8SMarkuss Broks 		.type = REGULATOR_VOLTAGE,				\
58e8858ba8SMarkuss Broks 		.id = SM5703_VBUS,					\
59e8858ba8SMarkuss Broks 		.ops = &sm5703_regulator_ops_fixed,			\
60*7c750406SAxel Lin 		.n_voltages = 1,					\
61e8858ba8SMarkuss Broks 		.fixed_uV = SM5703_VBUS_MICROVOLT,			\
62e8858ba8SMarkuss Broks 		.enable_reg = SM5703_REG_CNTL,				\
63e8858ba8SMarkuss Broks 		.enable_mask = SM5703_OPERATION_MODE_MASK,		\
64e8858ba8SMarkuss Broks 		.enable_val = SM5703_OPERATION_MODE_USB_OTG_MODE,	\
65e8858ba8SMarkuss Broks 		.disable_val = SM5703_OPERATION_MODE_CHARGING_ON,	\
66e8858ba8SMarkuss Broks 		.owner			= THIS_MODULE,			\
67e8858ba8SMarkuss Broks 	}
68e8858ba8SMarkuss Broks 
69e8858ba8SMarkuss Broks #define SM5703BUCK(_name)						\
70e8858ba8SMarkuss Broks 	[SM5703_BUCK] = {						\
71e8858ba8SMarkuss Broks 		.name = _name,						\
72e8858ba8SMarkuss Broks 		.of_match = _name,					\
73e8858ba8SMarkuss Broks 		.regulators_node = "regulators",			\
74e8858ba8SMarkuss Broks 		.type = REGULATOR_VOLTAGE,				\
75e8858ba8SMarkuss Broks 		.id = SM5703_BUCK,					\
76e8858ba8SMarkuss Broks 		.ops = &sm5703_regulator_ops,				\
77e8858ba8SMarkuss Broks 		.n_voltages = ARRAY_SIZE(sm5703_buck_voltagemap),	\
78e8858ba8SMarkuss Broks 		.volt_table = sm5703_buck_voltagemap,			\
79e8858ba8SMarkuss Broks 		.vsel_reg = SM5703_REG_BUCK,				\
80e8858ba8SMarkuss Broks 		.vsel_mask = SM5703_BUCK_VOLT_MASK,			\
81e8858ba8SMarkuss Broks 		.enable_reg = SM5703_REG_BUCK,				\
82e8858ba8SMarkuss Broks 		.enable_mask = SM5703_REG_EN_BUCK,			\
83e8858ba8SMarkuss Broks 		.owner			= THIS_MODULE,			\
84e8858ba8SMarkuss Broks 	}
85e8858ba8SMarkuss Broks 
86e8858ba8SMarkuss Broks #define SM5703LDO(_name, _id)						\
87e8858ba8SMarkuss Broks 	[SM5703_LDO ## _id] = {						\
88e8858ba8SMarkuss Broks 		.name = _name,						\
89e8858ba8SMarkuss Broks 		.of_match = _name,					\
90e8858ba8SMarkuss Broks 		.regulators_node = "regulators",			\
91e8858ba8SMarkuss Broks 		.type = REGULATOR_VOLTAGE,				\
92e8858ba8SMarkuss Broks 		.id = SM5703_LDO ## _id,				\
93e8858ba8SMarkuss Broks 		.ops = &sm5703_regulator_ops,				\
94e8858ba8SMarkuss Broks 		.n_voltages = ARRAY_SIZE(sm5703_ldo_voltagemap),	\
95e8858ba8SMarkuss Broks 		.volt_table = sm5703_ldo_voltagemap,			\
96e8858ba8SMarkuss Broks 		.vsel_reg = SM5703_REG_LDO ##_id,			\
97e8858ba8SMarkuss Broks 		.vsel_mask = SM5703_LDO_VOLT_MASK,			\
98e8858ba8SMarkuss Broks 		.enable_reg = SM5703_REG_LDO ##_id,			\
99e8858ba8SMarkuss Broks 		.enable_mask = SM5703_LDO_EN,				\
100e8858ba8SMarkuss Broks 		.owner			= THIS_MODULE,			\
101e8858ba8SMarkuss Broks 	}
102e8858ba8SMarkuss Broks 
103e8858ba8SMarkuss Broks static const struct regulator_ops sm5703_regulator_ops = {
104e8858ba8SMarkuss Broks 	.enable			= regulator_enable_regmap,
105e8858ba8SMarkuss Broks 	.disable		= regulator_disable_regmap,
106e8858ba8SMarkuss Broks 	.is_enabled		= regulator_is_enabled_regmap,
107e8858ba8SMarkuss Broks 	.list_voltage		= regulator_list_voltage_table,
108e8858ba8SMarkuss Broks 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
109e8858ba8SMarkuss Broks 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
110e8858ba8SMarkuss Broks };
111e8858ba8SMarkuss Broks 
112e8858ba8SMarkuss Broks static const struct regulator_ops sm5703_regulator_ops_fixed = {
113e8858ba8SMarkuss Broks 	.enable			= regulator_enable_regmap,
114e8858ba8SMarkuss Broks 	.disable		= regulator_disable_regmap,
115e8858ba8SMarkuss Broks 	.is_enabled		= regulator_is_enabled_regmap,
116e8858ba8SMarkuss Broks };
117e8858ba8SMarkuss Broks 
118e8858ba8SMarkuss Broks static struct regulator_desc sm5703_regulators_desc[SM5703_MAX_REGULATORS] = {
119e8858ba8SMarkuss Broks 	SM5703BUCK("buck"),
120e8858ba8SMarkuss Broks 	SM5703LDO("ldo1", 1),
121e8858ba8SMarkuss Broks 	SM5703LDO("ldo2", 2),
122e8858ba8SMarkuss Broks 	SM5703LDO("ldo3", 3),
123e8858ba8SMarkuss Broks 	SM5703USBLDO("usbldo1", 1),
124e8858ba8SMarkuss Broks 	SM5703USBLDO("usbldo2", 2),
125e8858ba8SMarkuss Broks 	SM5703VBUS("vbus"),
126e8858ba8SMarkuss Broks };
127e8858ba8SMarkuss Broks 
sm5703_regulator_probe(struct platform_device * pdev)128e8858ba8SMarkuss Broks static int sm5703_regulator_probe(struct platform_device *pdev)
129e8858ba8SMarkuss Broks {
130e8858ba8SMarkuss Broks 	struct device *dev = &pdev->dev;
131e8858ba8SMarkuss Broks 	struct regulator_config config = { NULL, };
132e8858ba8SMarkuss Broks 	struct regulator_dev *rdev;
133e8858ba8SMarkuss Broks 	struct sm5703_dev *sm5703 = dev_get_drvdata(pdev->dev.parent);
134e8858ba8SMarkuss Broks 	int i;
135e8858ba8SMarkuss Broks 
136e8858ba8SMarkuss Broks 	config.dev = dev->parent;
137e8858ba8SMarkuss Broks 	config.regmap = sm5703->regmap;
138e8858ba8SMarkuss Broks 
139e8858ba8SMarkuss Broks 	for (i = 0; i < SM5703_MAX_REGULATORS; i++) {
140e8858ba8SMarkuss Broks 		rdev = devm_regulator_register(dev,
141e8858ba8SMarkuss Broks 					       &sm5703_regulators_desc[i],
142e8858ba8SMarkuss Broks 					       &config);
143e8858ba8SMarkuss Broks 		if (IS_ERR(rdev))
144e8858ba8SMarkuss Broks 			return dev_err_probe(dev, PTR_ERR(rdev),
145e8858ba8SMarkuss Broks 					     "Failed to register a regulator\n");
146e8858ba8SMarkuss Broks 	}
147e8858ba8SMarkuss Broks 
148e8858ba8SMarkuss Broks 	return 0;
149e8858ba8SMarkuss Broks }
150e8858ba8SMarkuss Broks 
151e8858ba8SMarkuss Broks static const struct platform_device_id sm5703_regulator_id[] = {
152e8858ba8SMarkuss Broks 	{ "sm5703-regulator", 0 },
153e8858ba8SMarkuss Broks 	{}
154e8858ba8SMarkuss Broks };
155e8858ba8SMarkuss Broks MODULE_DEVICE_TABLE(platform, sm5703_regulator_id);
156e8858ba8SMarkuss Broks 
157e8858ba8SMarkuss Broks static struct platform_driver sm5703_regulator_driver = {
158e8858ba8SMarkuss Broks 	.driver = {
159e8858ba8SMarkuss Broks 		.name = "sm5703-regulator",
160e8858ba8SMarkuss Broks 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
161e8858ba8SMarkuss Broks 	},
162e8858ba8SMarkuss Broks 	.probe	= sm5703_regulator_probe,
163e8858ba8SMarkuss Broks 	.id_table	= sm5703_regulator_id,
164e8858ba8SMarkuss Broks };
165e8858ba8SMarkuss Broks 
166e8858ba8SMarkuss Broks module_platform_driver(sm5703_regulator_driver);
167e8858ba8SMarkuss Broks 
168e8858ba8SMarkuss Broks MODULE_DESCRIPTION("Silicon Mitus SM5703 LDO/Buck/USB regulator driver");
169e8858ba8SMarkuss Broks MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>");
170 MODULE_LICENSE("GPL");
171