Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
f4ff4155 SK |
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 http://www.echo360.com | |
8 | * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com> | |
f4ff4155 SK |
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 powr1220_regs { | |
26 | VMON_STATUS0, | |
27 | VMON_STATUS1, | |
28 | VMON_STATUS2, | |
29 | OUTPUT_STATUS0, | |
30 | OUTPUT_STATUS1, | |
31 | OUTPUT_STATUS2, | |
32 | INPUT_STATUS, | |
33 | ADC_VALUE_LOW, | |
34 | ADC_VALUE_HIGH, | |
35 | ADC_MUX, | |
36 | UES_BYTE0, | |
37 | UES_BYTE1, | |
38 | UES_BYTE2, | |
39 | UES_BYTE3, | |
40 | GP_OUTPUT1, | |
41 | GP_OUTPUT2, | |
42 | GP_OUTPUT3, | |
43 | INPUT_VALUE, | |
44 | RESET, | |
45 | TRIM1_TRIM, | |
46 | TRIM2_TRIM, | |
47 | TRIM3_TRIM, | |
48 | TRIM4_TRIM, | |
49 | TRIM5_TRIM, | |
50 | TRIM6_TRIM, | |
51 | TRIM7_TRIM, | |
52 | TRIM8_TRIM, | |
53 | MAX_POWR1220_REGS | |
54 | }; | |
55 | ||
56 | enum powr1220_adc_values { | |
57 | VMON1, | |
58 | VMON2, | |
59 | VMON3, | |
60 | VMON4, | |
61 | VMON5, | |
62 | VMON6, | |
63 | VMON7, | |
64 | VMON8, | |
65 | VMON9, | |
66 | VMON10, | |
67 | VMON11, | |
68 | VMON12, | |
69 | VCCA, | |
70 | VCCINP, | |
71 | MAX_POWR1220_ADC_VALUES | |
72 | }; | |
73 | ||
74 | struct powr1220_data { | |
75 | struct i2c_client *client; | |
76 | struct mutex update_lock; | |
77 | bool adc_valid[MAX_POWR1220_ADC_VALUES]; | |
78 | /* the next value is in jiffies */ | |
79 | unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES]; | |
80 | ||
81 | /* values */ | |
82 | int adc_maxes[MAX_POWR1220_ADC_VALUES]; | |
83 | int adc_values[MAX_POWR1220_ADC_VALUES]; | |
84 | }; | |
85 | ||
86 | static const char * const input_names[] = { | |
87 | [VMON1] = "vmon1", | |
88 | [VMON2] = "vmon2", | |
89 | [VMON3] = "vmon3", | |
90 | [VMON4] = "vmon4", | |
91 | [VMON5] = "vmon5", | |
92 | [VMON6] = "vmon6", | |
93 | [VMON7] = "vmon7", | |
94 | [VMON8] = "vmon8", | |
95 | [VMON9] = "vmon9", | |
96 | [VMON10] = "vmon10", | |
97 | [VMON11] = "vmon11", | |
98 | [VMON12] = "vmon12", | |
99 | [VCCA] = "vcca", | |
100 | [VCCINP] = "vccinp", | |
101 | }; | |
102 | ||
103 | /* Reads the specified ADC channel */ | |
104 | static int powr1220_read_adc(struct device *dev, int ch_num) | |
105 | { | |
106 | struct powr1220_data *data = dev_get_drvdata(dev); | |
107 | int reading; | |
108 | int result; | |
109 | int adc_range = 0; | |
110 | ||
111 | mutex_lock(&data->update_lock); | |
112 | ||
113 | if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) || | |
114 | !data->adc_valid[ch_num]) { | |
115 | /* | |
116 | * figure out if we need to use the attenuator for | |
117 | * high inputs or inputs that we don't yet have a measurement | |
118 | * for. We dynamically set the attenuator depending on the | |
119 | * max reading. | |
120 | */ | |
121 | if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV || | |
122 | data->adc_maxes[ch_num] == 0) | |
123 | adc_range = 1 << 4; | |
124 | ||
125 | /* set the attenuator and mux */ | |
126 | result = i2c_smbus_write_byte_data(data->client, ADC_MUX, | |
127 | adc_range | ch_num); | |
128 | if (result) | |
129 | goto exit; | |
130 | ||
131 | /* | |
132 | * wait at least Tconvert time (200 us) for the | |
133 | * conversion to complete | |
134 | */ | |
135 | udelay(200); | |
136 | ||
137 | /* get the ADC reading */ | |
138 | result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW); | |
139 | if (result < 0) | |
140 | goto exit; | |
141 | ||
142 | reading = result >> 4; | |
143 | ||
144 | /* get the upper half of the reading */ | |
145 | result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH); | |
146 | if (result < 0) | |
147 | goto exit; | |
148 | ||
149 | reading |= result << 4; | |
150 | ||
151 | /* now convert the reading to a voltage */ | |
152 | reading *= ADC_STEP_MV; | |
153 | data->adc_values[ch_num] = reading; | |
154 | data->adc_valid[ch_num] = true; | |
155 | data->adc_last_updated[ch_num] = jiffies; | |
156 | result = reading; | |
157 | ||
158 | if (reading > data->adc_maxes[ch_num]) | |
159 | data->adc_maxes[ch_num] = reading; | |
160 | } else { | |
161 | result = data->adc_values[ch_num]; | |
162 | } | |
163 | ||
164 | exit: | |
165 | mutex_unlock(&data->update_lock); | |
166 | ||
167 | return result; | |
168 | } | |
169 | ||
170 | /* Shows the voltage associated with the specified ADC channel */ | |
e3a0ee1a GR |
171 | static ssize_t powr1220_voltage_show(struct device *dev, |
172 | struct device_attribute *dev_attr, | |
173 | char *buf) | |
f4ff4155 SK |
174 | { |
175 | struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); | |
176 | int adc_val = powr1220_read_adc(dev, attr->index); | |
177 | ||
178 | if (adc_val < 0) | |
179 | return adc_val; | |
180 | ||
181 | return sprintf(buf, "%d\n", adc_val); | |
182 | } | |
183 | ||
184 | /* Shows the maximum setting associated with the specified ADC channel */ | |
e3a0ee1a GR |
185 | static ssize_t powr1220_max_show(struct device *dev, |
186 | struct device_attribute *dev_attr, char *buf) | |
f4ff4155 SK |
187 | { |
188 | struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); | |
189 | struct powr1220_data *data = dev_get_drvdata(dev); | |
190 | ||
191 | return sprintf(buf, "%d\n", data->adc_maxes[attr->index]); | |
192 | } | |
193 | ||
194 | /* Shows the label associated with the specified ADC channel */ | |
e3a0ee1a GR |
195 | static ssize_t powr1220_label_show(struct device *dev, |
196 | struct device_attribute *dev_attr, | |
197 | char *buf) | |
f4ff4155 SK |
198 | { |
199 | struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); | |
200 | ||
201 | return sprintf(buf, "%s\n", input_names[attr->index]); | |
202 | } | |
203 | ||
e3a0ee1a GR |
204 | static SENSOR_DEVICE_ATTR_RO(in0_input, powr1220_voltage, VMON1); |
205 | static SENSOR_DEVICE_ATTR_RO(in1_input, powr1220_voltage, VMON2); | |
206 | static SENSOR_DEVICE_ATTR_RO(in2_input, powr1220_voltage, VMON3); | |
207 | static SENSOR_DEVICE_ATTR_RO(in3_input, powr1220_voltage, VMON4); | |
208 | static SENSOR_DEVICE_ATTR_RO(in4_input, powr1220_voltage, VMON5); | |
209 | static SENSOR_DEVICE_ATTR_RO(in5_input, powr1220_voltage, VMON6); | |
210 | static SENSOR_DEVICE_ATTR_RO(in6_input, powr1220_voltage, VMON7); | |
211 | static SENSOR_DEVICE_ATTR_RO(in7_input, powr1220_voltage, VMON8); | |
212 | static SENSOR_DEVICE_ATTR_RO(in8_input, powr1220_voltage, VMON9); | |
213 | static SENSOR_DEVICE_ATTR_RO(in9_input, powr1220_voltage, VMON10); | |
214 | static SENSOR_DEVICE_ATTR_RO(in10_input, powr1220_voltage, VMON11); | |
215 | static SENSOR_DEVICE_ATTR_RO(in11_input, powr1220_voltage, VMON12); | |
216 | static SENSOR_DEVICE_ATTR_RO(in12_input, powr1220_voltage, VCCA); | |
217 | static SENSOR_DEVICE_ATTR_RO(in13_input, powr1220_voltage, VCCINP); | |
218 | ||
219 | static SENSOR_DEVICE_ATTR_RO(in0_highest, powr1220_max, VMON1); | |
220 | static SENSOR_DEVICE_ATTR_RO(in1_highest, powr1220_max, VMON2); | |
221 | static SENSOR_DEVICE_ATTR_RO(in2_highest, powr1220_max, VMON3); | |
222 | static SENSOR_DEVICE_ATTR_RO(in3_highest, powr1220_max, VMON4); | |
223 | static SENSOR_DEVICE_ATTR_RO(in4_highest, powr1220_max, VMON5); | |
224 | static SENSOR_DEVICE_ATTR_RO(in5_highest, powr1220_max, VMON6); | |
225 | static SENSOR_DEVICE_ATTR_RO(in6_highest, powr1220_max, VMON7); | |
226 | static SENSOR_DEVICE_ATTR_RO(in7_highest, powr1220_max, VMON8); | |
227 | static SENSOR_DEVICE_ATTR_RO(in8_highest, powr1220_max, VMON9); | |
228 | static SENSOR_DEVICE_ATTR_RO(in9_highest, powr1220_max, VMON10); | |
229 | static SENSOR_DEVICE_ATTR_RO(in10_highest, powr1220_max, VMON11); | |
230 | static SENSOR_DEVICE_ATTR_RO(in11_highest, powr1220_max, VMON12); | |
231 | static SENSOR_DEVICE_ATTR_RO(in12_highest, powr1220_max, VCCA); | |
232 | static SENSOR_DEVICE_ATTR_RO(in13_highest, powr1220_max, VCCINP); | |
233 | ||
234 | static SENSOR_DEVICE_ATTR_RO(in0_label, powr1220_label, VMON1); | |
235 | static SENSOR_DEVICE_ATTR_RO(in1_label, powr1220_label, VMON2); | |
236 | static SENSOR_DEVICE_ATTR_RO(in2_label, powr1220_label, VMON3); | |
237 | static SENSOR_DEVICE_ATTR_RO(in3_label, powr1220_label, VMON4); | |
238 | static SENSOR_DEVICE_ATTR_RO(in4_label, powr1220_label, VMON5); | |
239 | static SENSOR_DEVICE_ATTR_RO(in5_label, powr1220_label, VMON6); | |
240 | static SENSOR_DEVICE_ATTR_RO(in6_label, powr1220_label, VMON7); | |
241 | static SENSOR_DEVICE_ATTR_RO(in7_label, powr1220_label, VMON8); | |
242 | static SENSOR_DEVICE_ATTR_RO(in8_label, powr1220_label, VMON9); | |
243 | static SENSOR_DEVICE_ATTR_RO(in9_label, powr1220_label, VMON10); | |
244 | static SENSOR_DEVICE_ATTR_RO(in10_label, powr1220_label, VMON11); | |
245 | static SENSOR_DEVICE_ATTR_RO(in11_label, powr1220_label, VMON12); | |
246 | static SENSOR_DEVICE_ATTR_RO(in12_label, powr1220_label, VCCA); | |
247 | static SENSOR_DEVICE_ATTR_RO(in13_label, powr1220_label, VCCINP); | |
f4ff4155 SK |
248 | |
249 | static struct attribute *powr1220_attrs[] = { | |
250 | &sensor_dev_attr_in0_input.dev_attr.attr, | |
251 | &sensor_dev_attr_in1_input.dev_attr.attr, | |
252 | &sensor_dev_attr_in2_input.dev_attr.attr, | |
253 | &sensor_dev_attr_in3_input.dev_attr.attr, | |
254 | &sensor_dev_attr_in4_input.dev_attr.attr, | |
255 | &sensor_dev_attr_in5_input.dev_attr.attr, | |
256 | &sensor_dev_attr_in6_input.dev_attr.attr, | |
257 | &sensor_dev_attr_in7_input.dev_attr.attr, | |
258 | &sensor_dev_attr_in8_input.dev_attr.attr, | |
259 | &sensor_dev_attr_in9_input.dev_attr.attr, | |
260 | &sensor_dev_attr_in10_input.dev_attr.attr, | |
261 | &sensor_dev_attr_in11_input.dev_attr.attr, | |
262 | &sensor_dev_attr_in12_input.dev_attr.attr, | |
263 | &sensor_dev_attr_in13_input.dev_attr.attr, | |
264 | ||
265 | &sensor_dev_attr_in0_highest.dev_attr.attr, | |
266 | &sensor_dev_attr_in1_highest.dev_attr.attr, | |
267 | &sensor_dev_attr_in2_highest.dev_attr.attr, | |
268 | &sensor_dev_attr_in3_highest.dev_attr.attr, | |
269 | &sensor_dev_attr_in4_highest.dev_attr.attr, | |
270 | &sensor_dev_attr_in5_highest.dev_attr.attr, | |
271 | &sensor_dev_attr_in6_highest.dev_attr.attr, | |
272 | &sensor_dev_attr_in7_highest.dev_attr.attr, | |
273 | &sensor_dev_attr_in8_highest.dev_attr.attr, | |
274 | &sensor_dev_attr_in9_highest.dev_attr.attr, | |
275 | &sensor_dev_attr_in10_highest.dev_attr.attr, | |
276 | &sensor_dev_attr_in11_highest.dev_attr.attr, | |
277 | &sensor_dev_attr_in12_highest.dev_attr.attr, | |
278 | &sensor_dev_attr_in13_highest.dev_attr.attr, | |
279 | ||
280 | &sensor_dev_attr_in0_label.dev_attr.attr, | |
281 | &sensor_dev_attr_in1_label.dev_attr.attr, | |
282 | &sensor_dev_attr_in2_label.dev_attr.attr, | |
283 | &sensor_dev_attr_in3_label.dev_attr.attr, | |
284 | &sensor_dev_attr_in4_label.dev_attr.attr, | |
285 | &sensor_dev_attr_in5_label.dev_attr.attr, | |
286 | &sensor_dev_attr_in6_label.dev_attr.attr, | |
287 | &sensor_dev_attr_in7_label.dev_attr.attr, | |
288 | &sensor_dev_attr_in8_label.dev_attr.attr, | |
289 | &sensor_dev_attr_in9_label.dev_attr.attr, | |
290 | &sensor_dev_attr_in10_label.dev_attr.attr, | |
291 | &sensor_dev_attr_in11_label.dev_attr.attr, | |
292 | &sensor_dev_attr_in12_label.dev_attr.attr, | |
293 | &sensor_dev_attr_in13_label.dev_attr.attr, | |
294 | ||
295 | NULL | |
296 | }; | |
297 | ||
298 | ATTRIBUTE_GROUPS(powr1220); | |
299 | ||
300 | static int powr1220_probe(struct i2c_client *client, | |
301 | const struct i2c_device_id *id) | |
302 | { | |
303 | struct powr1220_data *data; | |
304 | struct device *hwmon_dev; | |
305 | ||
306 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
307 | return -ENODEV; | |
308 | ||
309 | data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); | |
310 | if (!data) | |
311 | return -ENOMEM; | |
312 | ||
313 | mutex_init(&data->update_lock); | |
314 | data->client = client; | |
315 | ||
316 | hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, | |
317 | client->name, data, powr1220_groups); | |
318 | ||
319 | return PTR_ERR_OR_ZERO(hwmon_dev); | |
320 | } | |
321 | ||
322 | static const struct i2c_device_id powr1220_ids[] = { | |
323 | { "powr1220", 0, }, | |
324 | { } | |
325 | }; | |
326 | ||
327 | MODULE_DEVICE_TABLE(i2c, powr1220_ids); | |
328 | ||
329 | static struct i2c_driver powr1220_driver = { | |
330 | .class = I2C_CLASS_HWMON, | |
331 | .driver = { | |
332 | .name = "powr1220", | |
333 | }, | |
334 | .probe = powr1220_probe, | |
335 | .id_table = powr1220_ids, | |
336 | }; | |
337 | ||
338 | module_i2c_driver(powr1220_driver); | |
339 | ||
340 | MODULE_AUTHOR("Scott Kanowitz"); | |
341 | MODULE_DESCRIPTION("POWR1220 driver"); | |
342 | MODULE_LICENSE("GPL"); |