Commit | Line | Data |
---|---|---|
e2a01b4e VW |
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_device.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(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(rdev->regmap, TPS6286X_CONTROL, &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 = of_match_ptr("SW"), | |
88 | .owner = THIS_MODULE, | |
89 | .ops = &tps6286x_regulator_ops, | |
90 | .of_map_mode = tps6286x_of_map_mode, | |
91 | .regulators_node = of_match_ptr("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 | const struct i2c_device_id *id) | |
116 | { | |
117 | struct device *dev = &i2c->dev; | |
118 | struct regulator_config config = {}; | |
119 | struct regulator_dev *rdev; | |
120 | struct regmap *regmap; | |
121 | ||
122 | regmap = devm_regmap_init_i2c(i2c, &tps6286x_regmap_config); | |
123 | if (IS_ERR(regmap)) | |
124 | return PTR_ERR(regmap); | |
125 | ||
126 | config.dev = &i2c->dev; | |
127 | config.of_node = dev->of_node; | |
128 | config.regmap = regmap; | |
129 | ||
130 | rdev = devm_regulator_register(&i2c->dev, &tps6286x_reg, &config); | |
131 | if (IS_ERR(rdev)) { | |
132 | dev_err(&i2c->dev, "Failed to register tps6286x regulator\n"); | |
133 | return PTR_ERR(rdev); | |
134 | } | |
135 | ||
136 | return 0; | |
137 | } | |
138 | ||
139 | static const struct i2c_device_id tps6286x_i2c_id[] = { | |
140 | { "tps62864", 0 }, | |
141 | { "tps62866", 0 }, | |
142 | { "tps62868", 0 }, | |
143 | { "tps62869", 0 }, | |
144 | {}, | |
145 | }; | |
146 | MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id); | |
147 | ||
148 | static struct i2c_driver tps6286x_regulator_driver = { | |
149 | .driver = { | |
150 | .name = "tps6286x", | |
151 | .of_match_table = of_match_ptr(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"); |