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