1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright Axis Communications AB |
3 | |
4 | #include <linux/err.h> |
5 | #include <linux/i2c.h> |
6 | #include <linux/module.h> |
7 | #include <linux/of.h> |
8 | #include <linux/regmap.h> |
9 | #include <linux/regulator/of_regulator.h> |
10 | #include <linux/regulator/machine.h> |
11 | #include <linux/regulator/driver.h> |
12 | |
13 | #include <dt-bindings/regulator/ti,tps62864.h> |
14 | |
15 | #define TPS6286X_VOUT1 0x01 |
16 | #define TPS6286X_VOUT1_VO1_SET GENMASK(7, 0) |
17 | |
18 | #define TPS6286X_CONTROL 0x03 |
19 | #define TPS6286X_CONTROL_FPWM BIT(4) |
20 | #define TPS6286X_CONTROL_SWEN BIT(5) |
21 | |
22 | #define TPS6286X_MIN_MV 400 |
23 | #define TPS6286X_MAX_MV 1675 |
24 | #define TPS6286X_STEP_MV 5 |
25 | |
26 | static const struct regmap_config tps6286x_regmap_config = { |
27 | .reg_bits = 8, |
28 | .val_bits = 8, |
29 | }; |
30 | |
31 | static int tps6286x_set_mode(struct regulator_dev *rdev, unsigned int mode) |
32 | { |
33 | unsigned int val; |
34 | |
35 | switch (mode) { |
36 | case REGULATOR_MODE_NORMAL: |
37 | val = 0; |
38 | break; |
39 | case REGULATOR_MODE_FAST: |
40 | val = TPS6286X_CONTROL_FPWM; |
41 | break; |
42 | default: |
43 | return -EINVAL; |
44 | } |
45 | |
46 | return regmap_update_bits(map: rdev->regmap, TPS6286X_CONTROL, |
47 | TPS6286X_CONTROL_FPWM, val); |
48 | } |
49 | |
50 | static unsigned int tps6286x_get_mode(struct regulator_dev *rdev) |
51 | { |
52 | unsigned int val; |
53 | int ret; |
54 | |
55 | ret = regmap_read(map: rdev->regmap, TPS6286X_CONTROL, val: &val); |
56 | if (ret < 0) |
57 | return 0; |
58 | |
59 | return (val & TPS6286X_CONTROL_FPWM) ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; |
60 | } |
61 | |
62 | static const struct regulator_ops tps6286x_regulator_ops = { |
63 | .enable = regulator_enable_regmap, |
64 | .disable = regulator_disable_regmap, |
65 | .set_mode = tps6286x_set_mode, |
66 | .get_mode = tps6286x_get_mode, |
67 | .is_enabled = regulator_is_enabled_regmap, |
68 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
69 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
70 | .list_voltage = regulator_list_voltage_linear, |
71 | }; |
72 | |
73 | static unsigned int tps6286x_of_map_mode(unsigned int mode) |
74 | { |
75 | switch (mode) { |
76 | case TPS62864_MODE_NORMAL: |
77 | return REGULATOR_MODE_NORMAL; |
78 | case TPS62864_MODE_FPWM: |
79 | return REGULATOR_MODE_FAST; |
80 | default: |
81 | return REGULATOR_MODE_INVALID; |
82 | } |
83 | } |
84 | |
85 | static const struct regulator_desc tps6286x_reg = { |
86 | .name = "tps6286x" , |
87 | .of_match = "SW" , |
88 | .owner = THIS_MODULE, |
89 | .ops = &tps6286x_regulator_ops, |
90 | .of_map_mode = tps6286x_of_map_mode, |
91 | .regulators_node = "regulators" , |
92 | .type = REGULATOR_VOLTAGE, |
93 | .n_voltages = ((TPS6286X_MAX_MV - TPS6286X_MIN_MV) / TPS6286X_STEP_MV) + 1, |
94 | .min_uV = TPS6286X_MIN_MV * 1000, |
95 | .uV_step = TPS6286X_STEP_MV * 1000, |
96 | .vsel_reg = TPS6286X_VOUT1, |
97 | .vsel_mask = TPS6286X_VOUT1_VO1_SET, |
98 | .enable_reg = TPS6286X_CONTROL, |
99 | .enable_mask = TPS6286X_CONTROL_SWEN, |
100 | .ramp_delay = 1000, |
101 | /* tDelay + tRamp, rounded up */ |
102 | .enable_time = 3000, |
103 | }; |
104 | |
105 | static const struct of_device_id tps6286x_dt_ids[] = { |
106 | { .compatible = "ti,tps62864" , }, |
107 | { .compatible = "ti,tps62866" , }, |
108 | { .compatible = "ti,tps62868" , }, |
109 | { .compatible = "ti,tps62869" , }, |
110 | { } |
111 | }; |
112 | MODULE_DEVICE_TABLE(of, tps6286x_dt_ids); |
113 | |
114 | static int tps6286x_i2c_probe(struct i2c_client *i2c) |
115 | { |
116 | struct device *dev = &i2c->dev; |
117 | struct regulator_config config = {}; |
118 | struct regulator_dev *rdev; |
119 | struct regmap *regmap; |
120 | |
121 | regmap = devm_regmap_init_i2c(i2c, &tps6286x_regmap_config); |
122 | if (IS_ERR(ptr: regmap)) |
123 | return PTR_ERR(ptr: regmap); |
124 | |
125 | config.dev = &i2c->dev; |
126 | config.of_node = dev->of_node; |
127 | config.regmap = regmap; |
128 | |
129 | rdev = devm_regulator_register(dev: &i2c->dev, regulator_desc: &tps6286x_reg, config: &config); |
130 | if (IS_ERR(ptr: rdev)) { |
131 | dev_err(&i2c->dev, "Failed to register tps6286x regulator\n" ); |
132 | return PTR_ERR(ptr: rdev); |
133 | } |
134 | |
135 | return 0; |
136 | } |
137 | |
138 | static const struct i2c_device_id tps6286x_i2c_id[] = { |
139 | { "tps62864" , 0 }, |
140 | { "tps62866" , 0 }, |
141 | { "tps62868" , 0 }, |
142 | { "tps62869" , 0 }, |
143 | {}, |
144 | }; |
145 | MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id); |
146 | |
147 | static struct i2c_driver tps6286x_regulator_driver = { |
148 | .driver = { |
149 | .name = "tps6286x" , |
150 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
151 | .of_match_table = tps6286x_dt_ids, |
152 | }, |
153 | .probe = tps6286x_i2c_probe, |
154 | .id_table = tps6286x_i2c_id, |
155 | }; |
156 | |
157 | module_i2c_driver(tps6286x_regulator_driver); |
158 | |
159 | MODULE_LICENSE("GPL v2" ); |
160 | |