1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * powr1220.c - Driver for the Lattice POWR1220 programmable power supply |
4 | * and monitor. Users can read all ADC inputs along with their labels |
5 | * using the sysfs nodes. |
6 | * |
7 | * Copyright (c) 2014 Echo360 https://www.echo360.com |
8 | * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com> |
9 | */ |
10 | |
11 | #include <linux/module.h> |
12 | #include <linux/init.h> |
13 | #include <linux/slab.h> |
14 | #include <linux/jiffies.h> |
15 | #include <linux/i2c.h> |
16 | #include <linux/hwmon.h> |
17 | #include <linux/hwmon-sysfs.h> |
18 | #include <linux/err.h> |
19 | #include <linux/mutex.h> |
20 | #include <linux/delay.h> |
21 | |
22 | #define ADC_STEP_MV 2 |
23 | #define ADC_MAX_LOW_MEASUREMENT_MV 2000 |
24 | |
25 | enum powr1xxx_chips { powr1014, powr1220 }; |
26 | |
27 | enum powr1220_regs { |
28 | VMON_STATUS0, |
29 | VMON_STATUS1, |
30 | VMON_STATUS2, |
31 | OUTPUT_STATUS0, |
32 | OUTPUT_STATUS1, |
33 | OUTPUT_STATUS2, |
34 | INPUT_STATUS, |
35 | ADC_VALUE_LOW, |
36 | ADC_VALUE_HIGH, |
37 | ADC_MUX, |
38 | UES_BYTE0, |
39 | UES_BYTE1, |
40 | UES_BYTE2, |
41 | UES_BYTE3, |
42 | GP_OUTPUT1, |
43 | GP_OUTPUT2, |
44 | GP_OUTPUT3, |
45 | INPUT_VALUE, |
46 | RESET, |
47 | TRIM1_TRIM, |
48 | TRIM2_TRIM, |
49 | TRIM3_TRIM, |
50 | TRIM4_TRIM, |
51 | TRIM5_TRIM, |
52 | TRIM6_TRIM, |
53 | TRIM7_TRIM, |
54 | TRIM8_TRIM, |
55 | MAX_POWR1220_REGS |
56 | }; |
57 | |
58 | enum powr1220_adc_values { |
59 | VMON1, |
60 | VMON2, |
61 | VMON3, |
62 | VMON4, |
63 | VMON5, |
64 | VMON6, |
65 | VMON7, |
66 | VMON8, |
67 | VMON9, |
68 | VMON10, |
69 | VMON11, |
70 | VMON12, |
71 | VCCA, |
72 | VCCINP, |
73 | MAX_POWR1220_ADC_VALUES |
74 | }; |
75 | |
76 | struct powr1220_data { |
77 | struct i2c_client *client; |
78 | struct mutex update_lock; |
79 | u8 max_channels; |
80 | bool adc_valid[MAX_POWR1220_ADC_VALUES]; |
81 | /* the next value is in jiffies */ |
82 | unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES]; |
83 | |
84 | /* values */ |
85 | int adc_maxes[MAX_POWR1220_ADC_VALUES]; |
86 | int adc_values[MAX_POWR1220_ADC_VALUES]; |
87 | }; |
88 | |
89 | static const char * const input_names[] = { |
90 | [VMON1] = "vmon1" , |
91 | [VMON2] = "vmon2" , |
92 | [VMON3] = "vmon3" , |
93 | [VMON4] = "vmon4" , |
94 | [VMON5] = "vmon5" , |
95 | [VMON6] = "vmon6" , |
96 | [VMON7] = "vmon7" , |
97 | [VMON8] = "vmon8" , |
98 | [VMON9] = "vmon9" , |
99 | [VMON10] = "vmon10" , |
100 | [VMON11] = "vmon11" , |
101 | [VMON12] = "vmon12" , |
102 | [VCCA] = "vcca" , |
103 | [VCCINP] = "vccinp" , |
104 | }; |
105 | |
106 | /* Reads the specified ADC channel */ |
107 | static int powr1220_read_adc(struct device *dev, int ch_num) |
108 | { |
109 | struct powr1220_data *data = dev_get_drvdata(dev); |
110 | int reading; |
111 | int result; |
112 | int adc_range = 0; |
113 | |
114 | mutex_lock(&data->update_lock); |
115 | |
116 | if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) || |
117 | !data->adc_valid[ch_num]) { |
118 | /* |
119 | * figure out if we need to use the attenuator for |
120 | * high inputs or inputs that we don't yet have a measurement |
121 | * for. We dynamically set the attenuator depending on the |
122 | * max reading. |
123 | */ |
124 | if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV || |
125 | data->adc_maxes[ch_num] == 0) |
126 | adc_range = 1 << 4; |
127 | |
128 | /* set the attenuator and mux */ |
129 | result = i2c_smbus_write_byte_data(client: data->client, command: ADC_MUX, |
130 | value: adc_range | ch_num); |
131 | if (result) |
132 | goto exit; |
133 | |
134 | /* |
135 | * wait at least Tconvert time (200 us) for the |
136 | * conversion to complete |
137 | */ |
138 | udelay(200); |
139 | |
140 | /* get the ADC reading */ |
141 | result = i2c_smbus_read_byte_data(client: data->client, command: ADC_VALUE_LOW); |
142 | if (result < 0) |
143 | goto exit; |
144 | |
145 | reading = result >> 4; |
146 | |
147 | /* get the upper half of the reading */ |
148 | result = i2c_smbus_read_byte_data(client: data->client, command: ADC_VALUE_HIGH); |
149 | if (result < 0) |
150 | goto exit; |
151 | |
152 | reading |= result << 4; |
153 | |
154 | /* now convert the reading to a voltage */ |
155 | reading *= ADC_STEP_MV; |
156 | data->adc_values[ch_num] = reading; |
157 | data->adc_valid[ch_num] = true; |
158 | data->adc_last_updated[ch_num] = jiffies; |
159 | result = reading; |
160 | |
161 | if (reading > data->adc_maxes[ch_num]) |
162 | data->adc_maxes[ch_num] = reading; |
163 | } else { |
164 | result = data->adc_values[ch_num]; |
165 | } |
166 | |
167 | exit: |
168 | mutex_unlock(lock: &data->update_lock); |
169 | |
170 | return result; |
171 | } |
172 | |
173 | static umode_t |
174 | powr1220_is_visible(const void *data, enum hwmon_sensor_types type, u32 |
175 | attr, int channel) |
176 | { |
177 | struct powr1220_data *chip_data = (struct powr1220_data *)data; |
178 | |
179 | if (channel >= chip_data->max_channels) |
180 | return 0; |
181 | |
182 | switch (type) { |
183 | case hwmon_in: |
184 | switch (attr) { |
185 | case hwmon_in_input: |
186 | case hwmon_in_highest: |
187 | case hwmon_in_label: |
188 | return 0444; |
189 | default: |
190 | break; |
191 | } |
192 | break; |
193 | default: |
194 | break; |
195 | } |
196 | |
197 | return 0; |
198 | } |
199 | |
200 | static int |
201 | powr1220_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr, |
202 | int channel, const char **str) |
203 | { |
204 | switch (type) { |
205 | case hwmon_in: |
206 | switch (attr) { |
207 | case hwmon_in_label: |
208 | *str = input_names[channel]; |
209 | return 0; |
210 | default: |
211 | return -EOPNOTSUPP; |
212 | } |
213 | break; |
214 | default: |
215 | return -EOPNOTSUPP; |
216 | } |
217 | |
218 | return -EOPNOTSUPP; |
219 | } |
220 | |
221 | static int |
222 | powr1220_read(struct device *dev, enum hwmon_sensor_types type, u32 |
223 | attr, int channel, long *val) |
224 | { |
225 | struct powr1220_data *data = dev_get_drvdata(dev); |
226 | int ret; |
227 | |
228 | switch (type) { |
229 | case hwmon_in: |
230 | switch (attr) { |
231 | case hwmon_in_input: |
232 | ret = powr1220_read_adc(dev, ch_num: channel); |
233 | if (ret < 0) |
234 | return ret; |
235 | *val = ret; |
236 | break; |
237 | case hwmon_in_highest: |
238 | *val = data->adc_maxes[channel]; |
239 | break; |
240 | default: |
241 | return -EOPNOTSUPP; |
242 | } |
243 | break; |
244 | default: |
245 | return -EOPNOTSUPP; |
246 | } |
247 | |
248 | return 0; |
249 | } |
250 | |
251 | static const struct hwmon_channel_info * const powr1220_info[] = { |
252 | HWMON_CHANNEL_INFO(in, |
253 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
254 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
255 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
256 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
257 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
258 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
259 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
260 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
261 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
262 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
263 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
264 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
265 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL, |
266 | HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL), |
267 | |
268 | NULL |
269 | }; |
270 | |
271 | static const struct hwmon_ops powr1220_hwmon_ops = { |
272 | .read = powr1220_read, |
273 | .read_string = powr1220_read_string, |
274 | .is_visible = powr1220_is_visible, |
275 | }; |
276 | |
277 | static const struct hwmon_chip_info powr1220_chip_info = { |
278 | .ops = &powr1220_hwmon_ops, |
279 | .info = powr1220_info, |
280 | }; |
281 | |
282 | static const struct i2c_device_id powr1220_ids[]; |
283 | |
284 | static int powr1220_probe(struct i2c_client *client) |
285 | { |
286 | struct powr1220_data *data; |
287 | struct device *hwmon_dev; |
288 | |
289 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
290 | return -ENODEV; |
291 | |
292 | data = devm_kzalloc(dev: &client->dev, size: sizeof(*data), GFP_KERNEL); |
293 | if (!data) |
294 | return -ENOMEM; |
295 | |
296 | switch (i2c_match_id(id: powr1220_ids, client)->driver_data) { |
297 | case powr1014: |
298 | data->max_channels = 10; |
299 | break; |
300 | default: |
301 | data->max_channels = 12; |
302 | break; |
303 | } |
304 | |
305 | mutex_init(&data->update_lock); |
306 | data->client = client; |
307 | |
308 | hwmon_dev = devm_hwmon_device_register_with_info(dev: &client->dev, |
309 | name: client->name, |
310 | drvdata: data, |
311 | info: &powr1220_chip_info, |
312 | NULL); |
313 | |
314 | return PTR_ERR_OR_ZERO(ptr: hwmon_dev); |
315 | } |
316 | |
317 | static const struct i2c_device_id powr1220_ids[] = { |
318 | { "powr1014" , powr1014, }, |
319 | { "powr1220" , powr1220, }, |
320 | { } |
321 | }; |
322 | |
323 | MODULE_DEVICE_TABLE(i2c, powr1220_ids); |
324 | |
325 | static struct i2c_driver powr1220_driver = { |
326 | .driver = { |
327 | .name = "powr1220" , |
328 | }, |
329 | .probe = powr1220_probe, |
330 | .id_table = powr1220_ids, |
331 | }; |
332 | |
333 | module_i2c_driver(powr1220_driver); |
334 | |
335 | MODULE_AUTHOR("Scott Kanowitz" ); |
336 | MODULE_DESCRIPTION("POWR1220 driver" ); |
337 | MODULE_LICENSE("GPL" ); |
338 | |