Commit | Line | Data |
---|---|---|
87976ce2 SS |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | |
3 | * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC | |
4 | * | |
5 | * Authors: | |
6 | * Maxim Kaurkin <maxim.kaurkin@baikalelectronics.ru> | |
7 | * Serge Semin <Sergey.Semin@baikalelectronics.ru> | |
8 | * | |
9 | * Baikal-T1 Process, Voltage, Temperature sensor driver | |
10 | */ | |
11 | ||
12 | #include <linux/bitfield.h> | |
13 | #include <linux/bitops.h> | |
14 | #include <linux/clk.h> | |
15 | #include <linux/completion.h> | |
a6db1561 | 16 | #include <linux/delay.h> |
87976ce2 SS |
17 | #include <linux/device.h> |
18 | #include <linux/hwmon-sysfs.h> | |
19 | #include <linux/hwmon.h> | |
20 | #include <linux/interrupt.h> | |
21 | #include <linux/io.h> | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/ktime.h> | |
24 | #include <linux/limits.h> | |
25 | #include <linux/module.h> | |
26 | #include <linux/mutex.h> | |
27 | #include <linux/of.h> | |
28 | #include <linux/platform_device.h> | |
e0daf1a6 | 29 | #include <linux/polynomial.h> |
87976ce2 SS |
30 | #include <linux/seqlock.h> |
31 | #include <linux/sysfs.h> | |
32 | #include <linux/types.h> | |
33 | ||
34 | #include "bt1-pvt.h" | |
35 | ||
36 | /* | |
37 | * For the sake of the code simplification we created the sensors info table | |
38 | * with the sensor names, activation modes, threshold registers base address | |
39 | * and the thresholds bit fields. | |
40 | */ | |
41 | static const struct pvt_sensor_info pvt_info[] = { | |
42 | PVT_SENSOR_INFO(0, "CPU Core Temperature", hwmon_temp, TEMP, TTHRES), | |
43 | PVT_SENSOR_INFO(0, "CPU Core Voltage", hwmon_in, VOLT, VTHRES), | |
44 | PVT_SENSOR_INFO(1, "CPU Core Low-Vt", hwmon_in, LVT, LTHRES), | |
45 | PVT_SENSOR_INFO(2, "CPU Core High-Vt", hwmon_in, HVT, HTHRES), | |
46 | PVT_SENSOR_INFO(3, "CPU Core Standard-Vt", hwmon_in, SVT, STHRES), | |
47 | }; | |
48 | ||
49 | /* | |
50 | * The original translation formulae of the temperature (in degrees of Celsius) | |
51 | * to PVT data and vice-versa are following: | |
52 | * N = 1.8322e-8*(T^4) + 2.343e-5*(T^3) + 8.7018e-3*(T^2) + 3.9269*(T^1) + | |
53 | * 1.7204e2, | |
54 | * T = -1.6743e-11*(N^4) + 8.1542e-8*(N^3) + -1.8201e-4*(N^2) + | |
55 | * 3.1020e-1*(N^1) - 4.838e1, | |
56 | * where T = [-48.380, 147.438]C and N = [0, 1023]. | |
57 | * They must be accordingly altered to be suitable for the integer arithmetics. | |
58 | * The technique is called 'factor redistribution', which just makes sure the | |
59 | * multiplications and divisions are made so to have a result of the operations | |
60 | * within the integer numbers limit. In addition we need to translate the | |
61 | * formulae to accept millidegrees of Celsius. Here what they look like after | |
62 | * the alterations: | |
63 | * N = (18322e-20*(T^4) + 2343e-13*(T^3) + 87018e-9*(T^2) + 39269e-3*T + | |
64 | * 17204e2) / 1e4, | |
65 | * T = -16743e-12*(D^4) + 81542e-9*(D^3) - 182010e-6*(D^2) + 310200e-3*D - | |
66 | * 48380, | |
67 | * where T = [-48380, 147438] mC and N = [0, 1023]. | |
68 | */ | |
e0daf1a6 | 69 | static const struct polynomial __maybe_unused poly_temp_to_N = { |
87976ce2 SS |
70 | .total_divider = 10000, |
71 | .terms = { | |
72 | {4, 18322, 10000, 10000}, | |
73 | {3, 2343, 10000, 10}, | |
74 | {2, 87018, 10000, 10}, | |
75 | {1, 39269, 1000, 1}, | |
76 | {0, 1720400, 1, 1} | |
77 | } | |
78 | }; | |
79 | ||
e0daf1a6 | 80 | static const struct polynomial poly_N_to_temp = { |
87976ce2 SS |
81 | .total_divider = 1, |
82 | .terms = { | |
83 | {4, -16743, 1000, 1}, | |
84 | {3, 81542, 1000, 1}, | |
85 | {2, -182010, 1000, 1}, | |
86 | {1, 310200, 1000, 1}, | |
87 | {0, -48380, 1, 1} | |
88 | } | |
89 | }; | |
90 | ||
91 | /* | |
92 | * Similar alterations are performed for the voltage conversion equations. | |
93 | * The original formulae are: | |
94 | * N = 1.8658e3*V - 1.1572e3, | |
95 | * V = (N + 1.1572e3) / 1.8658e3, | |
96 | * where V = [0.620, 1.168] V and N = [0, 1023]. | |
97 | * After the optimization they looks as follows: | |
98 | * N = (18658e-3*V - 11572) / 10, | |
99 | * V = N * 10^5 / 18658 + 11572 * 10^4 / 18658. | |
100 | */ | |
e0daf1a6 | 101 | static const struct polynomial __maybe_unused poly_volt_to_N = { |
87976ce2 SS |
102 | .total_divider = 10, |
103 | .terms = { | |
104 | {1, 18658, 1000, 1}, | |
105 | {0, -11572, 1, 1} | |
106 | } | |
107 | }; | |
108 | ||
e0daf1a6 | 109 | static const struct polynomial poly_N_to_volt = { |
87976ce2 SS |
110 | .total_divider = 10, |
111 | .terms = { | |
112 | {1, 100000, 18658, 1}, | |
113 | {0, 115720000, 1, 18658} | |
114 | } | |
115 | }; | |
116 | ||
87976ce2 SS |
117 | static inline u32 pvt_update(void __iomem *reg, u32 mask, u32 data) |
118 | { | |
119 | u32 old; | |
120 | ||
121 | old = readl_relaxed(reg); | |
122 | writel((old & ~mask) | (data & mask), reg); | |
123 | ||
124 | return old & mask; | |
125 | } | |
126 | ||
127 | /* | |
128 | * Baikal-T1 PVT mode can be updated only when the controller is disabled. | |
129 | * So first we disable it, then set the new mode together with the controller | |
130 | * getting back enabled. The same concerns the temperature trim and | |
131 | * measurements timeout. If it is necessary the interface mutex is supposed | |
132 | * to be locked at the time the operations are performed. | |
133 | */ | |
134 | static inline void pvt_set_mode(struct pvt_hwmon *pvt, u32 mode) | |
135 | { | |
136 | u32 old; | |
137 | ||
138 | mode = FIELD_PREP(PVT_CTRL_MODE_MASK, mode); | |
139 | ||
140 | old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
141 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_MODE_MASK | PVT_CTRL_EN, | |
142 | mode | old); | |
143 | } | |
144 | ||
145 | static inline u32 pvt_calc_trim(long temp) | |
146 | { | |
147 | temp = clamp_val(temp, 0, PVT_TRIM_TEMP); | |
148 | ||
149 | return DIV_ROUND_UP(temp, PVT_TRIM_STEP); | |
150 | } | |
151 | ||
152 | static inline void pvt_set_trim(struct pvt_hwmon *pvt, u32 trim) | |
153 | { | |
154 | u32 old; | |
155 | ||
156 | trim = FIELD_PREP(PVT_CTRL_TRIM_MASK, trim); | |
157 | ||
158 | old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
159 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_TRIM_MASK | PVT_CTRL_EN, | |
160 | trim | old); | |
161 | } | |
162 | ||
163 | static inline void pvt_set_tout(struct pvt_hwmon *pvt, u32 tout) | |
164 | { | |
165 | u32 old; | |
166 | ||
167 | old = pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
168 | writel(tout, pvt->regs + PVT_TTIMEOUT); | |
169 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, old); | |
170 | } | |
171 | ||
172 | /* | |
173 | * This driver can optionally provide the hwmon alarms for each sensor the PVT | |
174 | * controller supports. The alarms functionality is made compile-time | |
175 | * configurable due to the hardware interface implementation peculiarity | |
176 | * described further in this comment. So in case if alarms are unnecessary in | |
177 | * your system design it's recommended to have them disabled to prevent the PVT | |
178 | * IRQs being periodically raised to get the data cache/alarms status up to | |
179 | * date. | |
180 | * | |
181 | * Baikal-T1 PVT embedded controller is based on the Analog Bits PVT sensor, | |
182 | * but is equipped with a dedicated control wrapper. It exposes the PVT | |
183 | * sub-block registers space via the APB3 bus. In addition the wrapper provides | |
184 | * a common interrupt vector of the sensors conversion completion events and | |
185 | * threshold value alarms. Alas the wrapper interface hasn't been fully thought | |
186 | * through. There is only one sensor can be activated at a time, for which the | |
187 | * thresholds comparator is enabled right after the data conversion is | |
188 | * completed. Due to this if alarms need to be implemented for all available | |
189 | * sensors we can't just set the thresholds and enable the interrupts. We need | |
190 | * to enable the sensors one after another and let the controller to detect | |
191 | * the alarms by itself at each conversion. This also makes pointless to handle | |
192 | * the alarms interrupts, since in occasion they happen synchronously with | |
193 | * data conversion completion. The best driver design would be to have the | |
194 | * completion interrupts enabled only and keep the converted value in the | |
195 | * driver data cache. This solution is implemented if hwmon alarms are enabled | |
196 | * in this driver. In case if the alarms are disabled, the conversion is | |
197 | * performed on demand at the time a sensors input file is read. | |
198 | */ | |
199 | ||
200 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
201 | ||
202 | #define pvt_hard_isr NULL | |
203 | ||
204 | static irqreturn_t pvt_soft_isr(int irq, void *data) | |
205 | { | |
206 | const struct pvt_sensor_info *info; | |
207 | struct pvt_hwmon *pvt = data; | |
208 | struct pvt_cache *cache; | |
209 | u32 val, thres_sts, old; | |
210 | ||
211 | /* | |
212 | * DVALID bit will be cleared by reading the data. We need to save the | |
213 | * status before the next conversion happens. Threshold events will be | |
214 | * handled a bit later. | |
215 | */ | |
216 | thres_sts = readl(pvt->regs + PVT_RAW_INTR_STAT); | |
217 | ||
218 | /* | |
219 | * Then lets recharge the PVT interface with the next sampling mode. | |
220 | * Lock the interface mutex to serialize trim, timeouts and alarm | |
221 | * thresholds settings. | |
222 | */ | |
223 | cache = &pvt->cache[pvt->sensor]; | |
224 | info = &pvt_info[pvt->sensor]; | |
225 | pvt->sensor = (pvt->sensor == PVT_SENSOR_LAST) ? | |
226 | PVT_SENSOR_FIRST : (pvt->sensor + 1); | |
227 | ||
228 | /* | |
229 | * For some reason we have to mask the interrupt before changing the | |
230 | * mode, otherwise sometimes the temperature mode doesn't get | |
231 | * activated even though the actual mode in the ctrl register | |
232 | * corresponds to one. Then we read the data. By doing so we also | |
233 | * recharge the data conversion. After this the mode corresponding | |
234 | * to the next sensor in the row is set. Finally we enable the | |
235 | * interrupts back. | |
236 | */ | |
237 | mutex_lock(&pvt->iface_mtx); | |
238 | ||
239 | old = pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, | |
240 | PVT_INTR_DVALID); | |
241 | ||
242 | val = readl(pvt->regs + PVT_DATA); | |
243 | ||
244 | pvt_set_mode(pvt, pvt_info[pvt->sensor].mode); | |
245 | ||
246 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, old); | |
247 | ||
248 | mutex_unlock(&pvt->iface_mtx); | |
249 | ||
250 | /* | |
251 | * We can now update the data cache with data just retrieved from the | |
252 | * sensor. Lock write-seqlock to make sure the reader has a coherent | |
253 | * data. | |
254 | */ | |
255 | write_seqlock(&cache->data_seqlock); | |
256 | ||
257 | cache->data = FIELD_GET(PVT_DATA_DATA_MASK, val); | |
258 | ||
259 | write_sequnlock(&cache->data_seqlock); | |
260 | ||
261 | /* | |
262 | * While PVT core is doing the next mode data conversion, we'll check | |
263 | * whether the alarms were triggered for the current sensor. Note that | |
264 | * according to the documentation only one threshold IRQ status can be | |
265 | * set at a time, that's why if-else statement is utilized. | |
266 | */ | |
267 | if ((thres_sts & info->thres_sts_lo) ^ cache->thres_sts_lo) { | |
268 | WRITE_ONCE(cache->thres_sts_lo, thres_sts & info->thres_sts_lo); | |
269 | hwmon_notify_event(pvt->hwmon, info->type, info->attr_min_alarm, | |
270 | info->channel); | |
271 | } else if ((thres_sts & info->thres_sts_hi) ^ cache->thres_sts_hi) { | |
272 | WRITE_ONCE(cache->thres_sts_hi, thres_sts & info->thres_sts_hi); | |
273 | hwmon_notify_event(pvt->hwmon, info->type, info->attr_max_alarm, | |
274 | info->channel); | |
275 | } | |
276 | ||
277 | return IRQ_HANDLED; | |
278 | } | |
279 | ||
26797d8b | 280 | static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type) |
87976ce2 SS |
281 | { |
282 | return 0644; | |
283 | } | |
284 | ||
26797d8b | 285 | static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type) |
87976ce2 SS |
286 | { |
287 | return 0444; | |
288 | } | |
289 | ||
290 | static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
291 | long *val) | |
292 | { | |
293 | struct pvt_cache *cache = &pvt->cache[type]; | |
294 | unsigned int seq; | |
295 | u32 data; | |
296 | ||
297 | do { | |
298 | seq = read_seqbegin(&cache->data_seqlock); | |
299 | data = cache->data; | |
300 | } while (read_seqretry(&cache->data_seqlock, seq)); | |
301 | ||
302 | if (type == PVT_TEMP) | |
e0daf1a6 | 303 | *val = polynomial_calc(&poly_N_to_temp, data); |
87976ce2 | 304 | else |
e0daf1a6 | 305 | *val = polynomial_calc(&poly_N_to_volt, data); |
87976ce2 SS |
306 | |
307 | return 0; | |
308 | } | |
309 | ||
310 | static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
311 | bool is_low, long *val) | |
312 | { | |
313 | u32 data; | |
314 | ||
315 | /* No need in serialization, since it is just read from MMIO. */ | |
316 | data = readl(pvt->regs + pvt_info[type].thres_base); | |
317 | ||
318 | if (is_low) | |
319 | data = FIELD_GET(PVT_THRES_LO_MASK, data); | |
320 | else | |
321 | data = FIELD_GET(PVT_THRES_HI_MASK, data); | |
322 | ||
323 | if (type == PVT_TEMP) | |
e0daf1a6 | 324 | *val = polynomial_calc(&poly_N_to_temp, data); |
87976ce2 | 325 | else |
e0daf1a6 | 326 | *val = polynomial_calc(&poly_N_to_volt, data); |
87976ce2 SS |
327 | |
328 | return 0; | |
329 | } | |
330 | ||
331 | static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
332 | bool is_low, long val) | |
333 | { | |
334 | u32 data, limit, mask; | |
335 | int ret; | |
336 | ||
337 | if (type == PVT_TEMP) { | |
338 | val = clamp(val, PVT_TEMP_MIN, PVT_TEMP_MAX); | |
e0daf1a6 | 339 | data = polynomial_calc(&poly_temp_to_N, val); |
87976ce2 SS |
340 | } else { |
341 | val = clamp(val, PVT_VOLT_MIN, PVT_VOLT_MAX); | |
e0daf1a6 | 342 | data = polynomial_calc(&poly_volt_to_N, val); |
87976ce2 SS |
343 | } |
344 | ||
345 | /* Serialize limit update, since a part of the register is changed. */ | |
346 | ret = mutex_lock_interruptible(&pvt->iface_mtx); | |
347 | if (ret) | |
348 | return ret; | |
349 | ||
350 | /* Make sure the upper and lower ranges don't intersect. */ | |
351 | limit = readl(pvt->regs + pvt_info[type].thres_base); | |
352 | if (is_low) { | |
353 | limit = FIELD_GET(PVT_THRES_HI_MASK, limit); | |
354 | data = clamp_val(data, PVT_DATA_MIN, limit); | |
355 | data = FIELD_PREP(PVT_THRES_LO_MASK, data); | |
356 | mask = PVT_THRES_LO_MASK; | |
357 | } else { | |
358 | limit = FIELD_GET(PVT_THRES_LO_MASK, limit); | |
359 | data = clamp_val(data, limit, PVT_DATA_MAX); | |
360 | data = FIELD_PREP(PVT_THRES_HI_MASK, data); | |
361 | mask = PVT_THRES_HI_MASK; | |
362 | } | |
363 | ||
364 | pvt_update(pvt->regs + pvt_info[type].thres_base, mask, data); | |
365 | ||
366 | mutex_unlock(&pvt->iface_mtx); | |
367 | ||
368 | return 0; | |
369 | } | |
370 | ||
371 | static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
372 | bool is_low, long *val) | |
373 | { | |
374 | if (is_low) | |
375 | *val = !!READ_ONCE(pvt->cache[type].thres_sts_lo); | |
376 | else | |
377 | *val = !!READ_ONCE(pvt->cache[type].thres_sts_hi); | |
378 | ||
379 | return 0; | |
380 | } | |
381 | ||
382 | static const struct hwmon_channel_info *pvt_channel_info[] = { | |
383 | HWMON_CHANNEL_INFO(chip, | |
384 | HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), | |
385 | HWMON_CHANNEL_INFO(temp, | |
386 | HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL | | |
387 | HWMON_T_MIN | HWMON_T_MIN_ALARM | | |
388 | HWMON_T_MAX | HWMON_T_MAX_ALARM | | |
389 | HWMON_T_OFFSET), | |
390 | HWMON_CHANNEL_INFO(in, | |
391 | HWMON_I_INPUT | HWMON_I_LABEL | | |
392 | HWMON_I_MIN | HWMON_I_MIN_ALARM | | |
393 | HWMON_I_MAX | HWMON_I_MAX_ALARM, | |
394 | HWMON_I_INPUT | HWMON_I_LABEL | | |
395 | HWMON_I_MIN | HWMON_I_MIN_ALARM | | |
396 | HWMON_I_MAX | HWMON_I_MAX_ALARM, | |
397 | HWMON_I_INPUT | HWMON_I_LABEL | | |
398 | HWMON_I_MIN | HWMON_I_MIN_ALARM | | |
399 | HWMON_I_MAX | HWMON_I_MAX_ALARM, | |
400 | HWMON_I_INPUT | HWMON_I_LABEL | | |
401 | HWMON_I_MIN | HWMON_I_MIN_ALARM | | |
402 | HWMON_I_MAX | HWMON_I_MAX_ALARM), | |
403 | NULL | |
404 | }; | |
405 | ||
406 | #else /* !CONFIG_SENSORS_BT1_PVT_ALARMS */ | |
407 | ||
408 | static irqreturn_t pvt_hard_isr(int irq, void *data) | |
409 | { | |
410 | struct pvt_hwmon *pvt = data; | |
411 | struct pvt_cache *cache; | |
412 | u32 val; | |
413 | ||
414 | /* | |
415 | * Mask the DVALID interrupt so after exiting from the handler a | |
416 | * repeated conversion wouldn't happen. | |
417 | */ | |
418 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, | |
419 | PVT_INTR_DVALID); | |
420 | ||
421 | /* | |
422 | * Nothing special for alarm-less driver. Just read the data, update | |
423 | * the cache and notify a waiter of this event. | |
424 | */ | |
425 | val = readl(pvt->regs + PVT_DATA); | |
426 | if (!(val & PVT_DATA_VALID)) { | |
427 | dev_err(pvt->dev, "Got IRQ when data isn't valid\n"); | |
428 | return IRQ_HANDLED; | |
429 | } | |
430 | ||
431 | cache = &pvt->cache[pvt->sensor]; | |
432 | ||
433 | WRITE_ONCE(cache->data, FIELD_GET(PVT_DATA_DATA_MASK, val)); | |
434 | ||
435 | complete(&cache->conversion); | |
436 | ||
437 | return IRQ_HANDLED; | |
438 | } | |
439 | ||
440 | #define pvt_soft_isr NULL | |
441 | ||
26797d8b | 442 | static inline umode_t pvt_limit_is_visible(enum pvt_sensor_type type) |
87976ce2 SS |
443 | { |
444 | return 0; | |
445 | } | |
446 | ||
26797d8b | 447 | static inline umode_t pvt_alarm_is_visible(enum pvt_sensor_type type) |
87976ce2 SS |
448 | { |
449 | return 0; | |
450 | } | |
451 | ||
452 | static int pvt_read_data(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
453 | long *val) | |
454 | { | |
455 | struct pvt_cache *cache = &pvt->cache[type]; | |
0ffd21d5 | 456 | unsigned long timeout; |
87976ce2 SS |
457 | u32 data; |
458 | int ret; | |
459 | ||
460 | /* | |
461 | * Lock PVT conversion interface until data cache is updated. The | |
462 | * data read procedure is following: set the requested PVT sensor | |
463 | * mode, enable IRQ and conversion, wait until conversion is finished, | |
464 | * then disable conversion and IRQ, and read the cached data. | |
465 | */ | |
466 | ret = mutex_lock_interruptible(&pvt->iface_mtx); | |
467 | if (ret) | |
468 | return ret; | |
469 | ||
470 | pvt->sensor = type; | |
471 | pvt_set_mode(pvt, pvt_info[type].mode); | |
472 | ||
473 | /* | |
474 | * Unmask the DVALID interrupt and enable the sensors conversions. | |
475 | * Do the reverse procedure when conversion is done. | |
476 | */ | |
477 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0); | |
478 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN); | |
479 | ||
0ffd21d5 SS |
480 | /* |
481 | * Wait with timeout since in case if the sensor is suddenly powered | |
482 | * down the request won't be completed and the caller will hang up on | |
483 | * this procedure until the power is back up again. Multiply the | |
484 | * timeout by the factor of two to prevent a false timeout. | |
485 | */ | |
486 | timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout)); | |
487 | ret = wait_for_completion_timeout(&cache->conversion, timeout); | |
87976ce2 SS |
488 | |
489 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
490 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, | |
491 | PVT_INTR_DVALID); | |
492 | ||
493 | data = READ_ONCE(cache->data); | |
494 | ||
495 | mutex_unlock(&pvt->iface_mtx); | |
496 | ||
0ffd21d5 SS |
497 | if (!ret) |
498 | return -ETIMEDOUT; | |
499 | ||
87976ce2 | 500 | if (type == PVT_TEMP) |
e0daf1a6 | 501 | *val = polynomial_calc(&poly_N_to_temp, data); |
87976ce2 | 502 | else |
e0daf1a6 | 503 | *val = polynomial_calc(&poly_N_to_volt, data); |
87976ce2 SS |
504 | |
505 | return 0; | |
506 | } | |
507 | ||
508 | static int pvt_read_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
509 | bool is_low, long *val) | |
510 | { | |
511 | return -EOPNOTSUPP; | |
512 | } | |
513 | ||
514 | static int pvt_write_limit(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
515 | bool is_low, long val) | |
516 | { | |
517 | return -EOPNOTSUPP; | |
518 | } | |
519 | ||
520 | static int pvt_read_alarm(struct pvt_hwmon *pvt, enum pvt_sensor_type type, | |
521 | bool is_low, long *val) | |
522 | { | |
523 | return -EOPNOTSUPP; | |
524 | } | |
525 | ||
526 | static const struct hwmon_channel_info *pvt_channel_info[] = { | |
527 | HWMON_CHANNEL_INFO(chip, | |
528 | HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL), | |
529 | HWMON_CHANNEL_INFO(temp, | |
530 | HWMON_T_INPUT | HWMON_T_TYPE | HWMON_T_LABEL | | |
531 | HWMON_T_OFFSET), | |
532 | HWMON_CHANNEL_INFO(in, | |
533 | HWMON_I_INPUT | HWMON_I_LABEL, | |
534 | HWMON_I_INPUT | HWMON_I_LABEL, | |
535 | HWMON_I_INPUT | HWMON_I_LABEL, | |
536 | HWMON_I_INPUT | HWMON_I_LABEL), | |
537 | NULL | |
538 | }; | |
539 | ||
540 | #endif /* !CONFIG_SENSORS_BT1_PVT_ALARMS */ | |
541 | ||
542 | static inline bool pvt_hwmon_channel_is_valid(enum hwmon_sensor_types type, | |
543 | int ch) | |
544 | { | |
545 | switch (type) { | |
546 | case hwmon_temp: | |
547 | if (ch < 0 || ch >= PVT_TEMP_CHS) | |
548 | return false; | |
549 | break; | |
550 | case hwmon_in: | |
551 | if (ch < 0 || ch >= PVT_VOLT_CHS) | |
552 | return false; | |
553 | break; | |
554 | default: | |
555 | break; | |
556 | } | |
557 | ||
558 | /* The rest of the types are independent from the channel number. */ | |
559 | return true; | |
560 | } | |
561 | ||
562 | static umode_t pvt_hwmon_is_visible(const void *data, | |
563 | enum hwmon_sensor_types type, | |
564 | u32 attr, int ch) | |
565 | { | |
566 | if (!pvt_hwmon_channel_is_valid(type, ch)) | |
567 | return 0; | |
568 | ||
569 | switch (type) { | |
570 | case hwmon_chip: | |
571 | switch (attr) { | |
572 | case hwmon_chip_update_interval: | |
573 | return 0644; | |
574 | } | |
575 | break; | |
576 | case hwmon_temp: | |
577 | switch (attr) { | |
578 | case hwmon_temp_input: | |
579 | case hwmon_temp_type: | |
580 | case hwmon_temp_label: | |
581 | return 0444; | |
582 | case hwmon_temp_min: | |
583 | case hwmon_temp_max: | |
584 | return pvt_limit_is_visible(ch); | |
585 | case hwmon_temp_min_alarm: | |
586 | case hwmon_temp_max_alarm: | |
587 | return pvt_alarm_is_visible(ch); | |
588 | case hwmon_temp_offset: | |
589 | return 0644; | |
590 | } | |
591 | break; | |
592 | case hwmon_in: | |
593 | switch (attr) { | |
594 | case hwmon_in_input: | |
595 | case hwmon_in_label: | |
596 | return 0444; | |
597 | case hwmon_in_min: | |
598 | case hwmon_in_max: | |
599 | return pvt_limit_is_visible(PVT_VOLT + ch); | |
600 | case hwmon_in_min_alarm: | |
601 | case hwmon_in_max_alarm: | |
602 | return pvt_alarm_is_visible(PVT_VOLT + ch); | |
603 | } | |
604 | break; | |
605 | default: | |
606 | break; | |
607 | } | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | static int pvt_read_trim(struct pvt_hwmon *pvt, long *val) | |
613 | { | |
614 | u32 data; | |
615 | ||
616 | data = readl(pvt->regs + PVT_CTRL); | |
617 | *val = FIELD_GET(PVT_CTRL_TRIM_MASK, data) * PVT_TRIM_STEP; | |
618 | ||
619 | return 0; | |
620 | } | |
621 | ||
622 | static int pvt_write_trim(struct pvt_hwmon *pvt, long val) | |
623 | { | |
624 | u32 trim; | |
625 | int ret; | |
626 | ||
627 | /* | |
628 | * Serialize trim update, since a part of the register is changed and | |
629 | * the controller is supposed to be disabled during this operation. | |
630 | */ | |
631 | ret = mutex_lock_interruptible(&pvt->iface_mtx); | |
632 | if (ret) | |
633 | return ret; | |
634 | ||
635 | trim = pvt_calc_trim(val); | |
636 | pvt_set_trim(pvt, trim); | |
637 | ||
638 | mutex_unlock(&pvt->iface_mtx); | |
639 | ||
640 | return 0; | |
641 | } | |
642 | ||
643 | static int pvt_read_timeout(struct pvt_hwmon *pvt, long *val) | |
644 | { | |
0015503e | 645 | int ret; |
87976ce2 | 646 | |
0015503e SS |
647 | ret = mutex_lock_interruptible(&pvt->iface_mtx); |
648 | if (ret) | |
649 | return ret; | |
87976ce2 SS |
650 | |
651 | /* Return the result in msec as hwmon sysfs interface requires. */ | |
0015503e SS |
652 | *val = ktime_to_ms(pvt->timeout); |
653 | ||
654 | mutex_unlock(&pvt->iface_mtx); | |
87976ce2 SS |
655 | |
656 | return 0; | |
657 | } | |
658 | ||
659 | static int pvt_write_timeout(struct pvt_hwmon *pvt, long val) | |
660 | { | |
661 | unsigned long rate; | |
0015503e | 662 | ktime_t kt, cache; |
87976ce2 SS |
663 | u32 data; |
664 | int ret; | |
665 | ||
666 | rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk); | |
667 | if (!rate) | |
668 | return -ENODEV; | |
669 | ||
670 | /* | |
671 | * If alarms are enabled, the requested timeout must be divided | |
672 | * between all available sensors to have the requested delay | |
673 | * applicable to each individual sensor. | |
674 | */ | |
0015503e | 675 | cache = kt = ms_to_ktime(val); |
87976ce2 SS |
676 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) |
677 | kt = ktime_divns(kt, PVT_SENSORS_NUM); | |
678 | #endif | |
679 | ||
680 | /* | |
681 | * Subtract a constant lag, which always persists due to the limited | |
682 | * PVT sampling rate. Make sure the timeout is not negative. | |
683 | */ | |
684 | kt = ktime_sub_ns(kt, PVT_TOUT_MIN); | |
685 | if (ktime_to_ns(kt) < 0) | |
686 | kt = ktime_set(0, 0); | |
687 | ||
688 | /* | |
689 | * Finally recalculate the timeout in terms of the reference clock | |
690 | * period. | |
691 | */ | |
692 | data = ktime_divns(kt * rate, NSEC_PER_SEC); | |
693 | ||
694 | /* | |
695 | * Update the measurements delay, but lock the interface first, since | |
696 | * we have to disable PVT in order to have the new delay actually | |
697 | * updated. | |
698 | */ | |
699 | ret = mutex_lock_interruptible(&pvt->iface_mtx); | |
700 | if (ret) | |
701 | return ret; | |
702 | ||
703 | pvt_set_tout(pvt, data); | |
0015503e | 704 | pvt->timeout = cache; |
87976ce2 SS |
705 | |
706 | mutex_unlock(&pvt->iface_mtx); | |
707 | ||
708 | return 0; | |
709 | } | |
710 | ||
711 | static int pvt_hwmon_read(struct device *dev, enum hwmon_sensor_types type, | |
712 | u32 attr, int ch, long *val) | |
713 | { | |
714 | struct pvt_hwmon *pvt = dev_get_drvdata(dev); | |
715 | ||
716 | if (!pvt_hwmon_channel_is_valid(type, ch)) | |
717 | return -EINVAL; | |
718 | ||
719 | switch (type) { | |
720 | case hwmon_chip: | |
721 | switch (attr) { | |
722 | case hwmon_chip_update_interval: | |
723 | return pvt_read_timeout(pvt, val); | |
724 | } | |
725 | break; | |
726 | case hwmon_temp: | |
727 | switch (attr) { | |
728 | case hwmon_temp_input: | |
729 | return pvt_read_data(pvt, ch, val); | |
730 | case hwmon_temp_type: | |
731 | *val = 1; | |
732 | return 0; | |
733 | case hwmon_temp_min: | |
734 | return pvt_read_limit(pvt, ch, true, val); | |
735 | case hwmon_temp_max: | |
736 | return pvt_read_limit(pvt, ch, false, val); | |
737 | case hwmon_temp_min_alarm: | |
738 | return pvt_read_alarm(pvt, ch, true, val); | |
739 | case hwmon_temp_max_alarm: | |
740 | return pvt_read_alarm(pvt, ch, false, val); | |
741 | case hwmon_temp_offset: | |
742 | return pvt_read_trim(pvt, val); | |
743 | } | |
744 | break; | |
745 | case hwmon_in: | |
746 | switch (attr) { | |
747 | case hwmon_in_input: | |
748 | return pvt_read_data(pvt, PVT_VOLT + ch, val); | |
749 | case hwmon_in_min: | |
750 | return pvt_read_limit(pvt, PVT_VOLT + ch, true, val); | |
751 | case hwmon_in_max: | |
752 | return pvt_read_limit(pvt, PVT_VOLT + ch, false, val); | |
753 | case hwmon_in_min_alarm: | |
754 | return pvt_read_alarm(pvt, PVT_VOLT + ch, true, val); | |
755 | case hwmon_in_max_alarm: | |
756 | return pvt_read_alarm(pvt, PVT_VOLT + ch, false, val); | |
757 | } | |
758 | break; | |
759 | default: | |
760 | break; | |
761 | } | |
762 | ||
763 | return -EOPNOTSUPP; | |
764 | } | |
765 | ||
766 | static int pvt_hwmon_read_string(struct device *dev, | |
767 | enum hwmon_sensor_types type, | |
768 | u32 attr, int ch, const char **str) | |
769 | { | |
770 | if (!pvt_hwmon_channel_is_valid(type, ch)) | |
771 | return -EINVAL; | |
772 | ||
773 | switch (type) { | |
774 | case hwmon_temp: | |
775 | switch (attr) { | |
776 | case hwmon_temp_label: | |
777 | *str = pvt_info[ch].label; | |
778 | return 0; | |
779 | } | |
780 | break; | |
781 | case hwmon_in: | |
782 | switch (attr) { | |
783 | case hwmon_in_label: | |
784 | *str = pvt_info[PVT_VOLT + ch].label; | |
785 | return 0; | |
786 | } | |
787 | break; | |
788 | default: | |
789 | break; | |
790 | } | |
791 | ||
792 | return -EOPNOTSUPP; | |
793 | } | |
794 | ||
795 | static int pvt_hwmon_write(struct device *dev, enum hwmon_sensor_types type, | |
796 | u32 attr, int ch, long val) | |
797 | { | |
798 | struct pvt_hwmon *pvt = dev_get_drvdata(dev); | |
799 | ||
800 | if (!pvt_hwmon_channel_is_valid(type, ch)) | |
801 | return -EINVAL; | |
802 | ||
803 | switch (type) { | |
804 | case hwmon_chip: | |
805 | switch (attr) { | |
806 | case hwmon_chip_update_interval: | |
807 | return pvt_write_timeout(pvt, val); | |
808 | } | |
809 | break; | |
810 | case hwmon_temp: | |
811 | switch (attr) { | |
812 | case hwmon_temp_min: | |
813 | return pvt_write_limit(pvt, ch, true, val); | |
814 | case hwmon_temp_max: | |
815 | return pvt_write_limit(pvt, ch, false, val); | |
816 | case hwmon_temp_offset: | |
817 | return pvt_write_trim(pvt, val); | |
818 | } | |
819 | break; | |
820 | case hwmon_in: | |
821 | switch (attr) { | |
822 | case hwmon_in_min: | |
823 | return pvt_write_limit(pvt, PVT_VOLT + ch, true, val); | |
824 | case hwmon_in_max: | |
825 | return pvt_write_limit(pvt, PVT_VOLT + ch, false, val); | |
826 | } | |
827 | break; | |
828 | default: | |
829 | break; | |
830 | } | |
831 | ||
832 | return -EOPNOTSUPP; | |
833 | } | |
834 | ||
835 | static const struct hwmon_ops pvt_hwmon_ops = { | |
836 | .is_visible = pvt_hwmon_is_visible, | |
837 | .read = pvt_hwmon_read, | |
838 | .read_string = pvt_hwmon_read_string, | |
839 | .write = pvt_hwmon_write | |
840 | }; | |
841 | ||
842 | static const struct hwmon_chip_info pvt_hwmon_info = { | |
843 | .ops = &pvt_hwmon_ops, | |
844 | .info = pvt_channel_info | |
845 | }; | |
846 | ||
847 | static void pvt_clear_data(void *data) | |
848 | { | |
849 | struct pvt_hwmon *pvt = data; | |
850 | #if !defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
851 | int idx; | |
852 | ||
853 | for (idx = 0; idx < PVT_SENSORS_NUM; ++idx) | |
854 | complete_all(&pvt->cache[idx].conversion); | |
855 | #endif | |
856 | ||
857 | mutex_destroy(&pvt->iface_mtx); | |
858 | } | |
859 | ||
860 | static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev) | |
861 | { | |
862 | struct device *dev = &pdev->dev; | |
863 | struct pvt_hwmon *pvt; | |
864 | int ret, idx; | |
865 | ||
866 | pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL); | |
867 | if (!pvt) | |
868 | return ERR_PTR(-ENOMEM); | |
869 | ||
870 | ret = devm_add_action(dev, pvt_clear_data, pvt); | |
871 | if (ret) { | |
872 | dev_err(dev, "Can't add PVT data clear action\n"); | |
873 | return ERR_PTR(ret); | |
874 | } | |
875 | ||
876 | pvt->dev = dev; | |
877 | pvt->sensor = PVT_SENSOR_FIRST; | |
878 | mutex_init(&pvt->iface_mtx); | |
879 | ||
880 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
881 | for (idx = 0; idx < PVT_SENSORS_NUM; ++idx) | |
882 | seqlock_init(&pvt->cache[idx].data_seqlock); | |
883 | #else | |
884 | for (idx = 0; idx < PVT_SENSORS_NUM; ++idx) | |
885 | init_completion(&pvt->cache[idx].conversion); | |
886 | #endif | |
887 | ||
888 | return pvt; | |
889 | } | |
890 | ||
891 | static int pvt_request_regs(struct pvt_hwmon *pvt) | |
892 | { | |
893 | struct platform_device *pdev = to_platform_device(pvt->dev); | |
894 | struct resource *res; | |
895 | ||
896 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
897 | if (!res) { | |
898 | dev_err(pvt->dev, "Couldn't find PVT memresource\n"); | |
899 | return -EINVAL; | |
900 | } | |
901 | ||
902 | pvt->regs = devm_ioremap_resource(pvt->dev, res); | |
4943c603 | 903 | if (IS_ERR(pvt->regs)) |
87976ce2 | 904 | return PTR_ERR(pvt->regs); |
87976ce2 SS |
905 | |
906 | return 0; | |
907 | } | |
908 | ||
909 | static void pvt_disable_clks(void *data) | |
910 | { | |
911 | struct pvt_hwmon *pvt = data; | |
912 | ||
913 | clk_bulk_disable_unprepare(PVT_CLOCK_NUM, pvt->clks); | |
914 | } | |
915 | ||
916 | static int pvt_request_clks(struct pvt_hwmon *pvt) | |
917 | { | |
918 | int ret; | |
919 | ||
920 | pvt->clks[PVT_CLOCK_APB].id = "pclk"; | |
921 | pvt->clks[PVT_CLOCK_REF].id = "ref"; | |
922 | ||
923 | ret = devm_clk_bulk_get(pvt->dev, PVT_CLOCK_NUM, pvt->clks); | |
924 | if (ret) { | |
925 | dev_err(pvt->dev, "Couldn't get PVT clocks descriptors\n"); | |
926 | return ret; | |
927 | } | |
928 | ||
929 | ret = clk_bulk_prepare_enable(PVT_CLOCK_NUM, pvt->clks); | |
930 | if (ret) { | |
931 | dev_err(pvt->dev, "Couldn't enable the PVT clocks\n"); | |
932 | return ret; | |
933 | } | |
934 | ||
935 | ret = devm_add_action_or_reset(pvt->dev, pvt_disable_clks, pvt); | |
936 | if (ret) { | |
937 | dev_err(pvt->dev, "Can't add PVT clocks disable action\n"); | |
938 | return ret; | |
939 | } | |
940 | ||
941 | return 0; | |
942 | } | |
943 | ||
a6db1561 SS |
944 | static int pvt_check_pwr(struct pvt_hwmon *pvt) |
945 | { | |
946 | unsigned long tout; | |
947 | int ret = 0; | |
948 | u32 data; | |
949 | ||
950 | /* | |
951 | * Test out the sensor conversion functionality. If it is not done on | |
952 | * time then the domain must have been unpowered and we won't be able | |
953 | * to use the device later in this driver. | |
954 | * Note If the power source is lost during the normal driver work the | |
955 | * data read procedure will either return -ETIMEDOUT (for the | |
956 | * alarm-less driver configuration) or just stop the repeated | |
957 | * conversion. In the later case alas we won't be able to detect the | |
958 | * problem. | |
959 | */ | |
960 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_ALL, PVT_INTR_ALL); | |
961 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN); | |
962 | pvt_set_tout(pvt, 0); | |
963 | readl(pvt->regs + PVT_DATA); | |
964 | ||
965 | tout = PVT_TOUT_MIN / NSEC_PER_USEC; | |
966 | usleep_range(tout, 2 * tout); | |
967 | ||
968 | data = readl(pvt->regs + PVT_DATA); | |
969 | if (!(data & PVT_DATA_VALID)) { | |
970 | ret = -ENODEV; | |
971 | dev_err(pvt->dev, "Sensor is powered down\n"); | |
972 | } | |
973 | ||
974 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
975 | ||
976 | return ret; | |
977 | } | |
978 | ||
0015503e | 979 | static int pvt_init_iface(struct pvt_hwmon *pvt) |
87976ce2 | 980 | { |
0015503e | 981 | unsigned long rate; |
87976ce2 SS |
982 | u32 trim, temp; |
983 | ||
0015503e SS |
984 | rate = clk_get_rate(pvt->clks[PVT_CLOCK_REF].clk); |
985 | if (!rate) { | |
986 | dev_err(pvt->dev, "Invalid reference clock rate\n"); | |
987 | return -ENODEV; | |
988 | } | |
989 | ||
87976ce2 SS |
990 | /* |
991 | * Make sure all interrupts and controller are disabled so not to | |
992 | * accidentally have ISR executed before the driver data is fully | |
993 | * initialized. Clear the IRQ status as well. | |
994 | */ | |
995 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_ALL, PVT_INTR_ALL); | |
996 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
997 | readl(pvt->regs + PVT_CLR_INTR); | |
998 | readl(pvt->regs + PVT_DATA); | |
999 | ||
1000 | /* Setup default sensor mode, timeout and temperature trim. */ | |
1001 | pvt_set_mode(pvt, pvt_info[pvt->sensor].mode); | |
1002 | pvt_set_tout(pvt, PVT_TOUT_DEF); | |
1003 | ||
0015503e SS |
1004 | /* |
1005 | * Preserve the current ref-clock based delay (Ttotal) between the | |
1006 | * sensors data samples in the driver data so not to recalculate it | |
1007 | * each time on the data requests and timeout reads. It consists of the | |
1008 | * delay introduced by the internal ref-clock timer (N / Fclk) and the | |
1009 | * constant timeout caused by each conversion latency (Tmin): | |
1010 | * Ttotal = N / Fclk + Tmin | |
1011 | * If alarms are enabled the sensors are polled one after another and | |
1012 | * in order to get the next measurement of a particular sensor the | |
1013 | * caller will have to wait for at most until all the others are | |
1014 | * polled. In that case the formulae will look a bit different: | |
1015 | * Ttotal = 5 * (N / Fclk + Tmin) | |
1016 | */ | |
1017 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
1018 | pvt->timeout = ktime_set(PVT_SENSORS_NUM * PVT_TOUT_DEF, 0); | |
1019 | pvt->timeout = ktime_divns(pvt->timeout, rate); | |
1020 | pvt->timeout = ktime_add_ns(pvt->timeout, PVT_SENSORS_NUM * PVT_TOUT_MIN); | |
1021 | #else | |
1022 | pvt->timeout = ktime_set(PVT_TOUT_DEF, 0); | |
1023 | pvt->timeout = ktime_divns(pvt->timeout, rate); | |
1024 | pvt->timeout = ktime_add_ns(pvt->timeout, PVT_TOUT_MIN); | |
1025 | #endif | |
1026 | ||
87976ce2 SS |
1027 | trim = PVT_TRIM_DEF; |
1028 | if (!of_property_read_u32(pvt->dev->of_node, | |
1029 | "baikal,pvt-temp-offset-millicelsius", &temp)) | |
1030 | trim = pvt_calc_trim(temp); | |
1031 | ||
1032 | pvt_set_trim(pvt, trim); | |
0015503e SS |
1033 | |
1034 | return 0; | |
87976ce2 SS |
1035 | } |
1036 | ||
1037 | static int pvt_request_irq(struct pvt_hwmon *pvt) | |
1038 | { | |
1039 | struct platform_device *pdev = to_platform_device(pvt->dev); | |
1040 | int ret; | |
1041 | ||
1042 | pvt->irq = platform_get_irq(pdev, 0); | |
1043 | if (pvt->irq < 0) | |
1044 | return pvt->irq; | |
1045 | ||
1046 | ret = devm_request_threaded_irq(pvt->dev, pvt->irq, | |
1047 | pvt_hard_isr, pvt_soft_isr, | |
1048 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
1049 | IRQF_SHARED | IRQF_TRIGGER_HIGH | | |
1050 | IRQF_ONESHOT, | |
1051 | #else | |
1052 | IRQF_SHARED | IRQF_TRIGGER_HIGH, | |
1053 | #endif | |
1054 | "pvt", pvt); | |
1055 | if (ret) { | |
1056 | dev_err(pvt->dev, "Couldn't request PVT IRQ\n"); | |
1057 | return ret; | |
1058 | } | |
1059 | ||
1060 | return 0; | |
1061 | } | |
1062 | ||
1063 | static int pvt_create_hwmon(struct pvt_hwmon *pvt) | |
1064 | { | |
1065 | pvt->hwmon = devm_hwmon_device_register_with_info(pvt->dev, "pvt", pvt, | |
1066 | &pvt_hwmon_info, NULL); | |
1067 | if (IS_ERR(pvt->hwmon)) { | |
1068 | dev_err(pvt->dev, "Couldn't create hwmon device\n"); | |
1069 | return PTR_ERR(pvt->hwmon); | |
1070 | } | |
1071 | ||
1072 | return 0; | |
1073 | } | |
1074 | ||
1075 | #if defined(CONFIG_SENSORS_BT1_PVT_ALARMS) | |
1076 | ||
1077 | static void pvt_disable_iface(void *data) | |
1078 | { | |
1079 | struct pvt_hwmon *pvt = data; | |
1080 | ||
1081 | mutex_lock(&pvt->iface_mtx); | |
1082 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, 0); | |
1083 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, | |
1084 | PVT_INTR_DVALID); | |
1085 | mutex_unlock(&pvt->iface_mtx); | |
1086 | } | |
1087 | ||
1088 | static int pvt_enable_iface(struct pvt_hwmon *pvt) | |
1089 | { | |
1090 | int ret; | |
1091 | ||
1092 | ret = devm_add_action(pvt->dev, pvt_disable_iface, pvt); | |
1093 | if (ret) { | |
1094 | dev_err(pvt->dev, "Can't add PVT disable interface action\n"); | |
1095 | return ret; | |
1096 | } | |
1097 | ||
1098 | /* | |
1099 | * Enable sensors data conversion and IRQ. We need to lock the | |
1100 | * interface mutex since hwmon has just been created and the | |
1101 | * corresponding sysfs files are accessible from user-space, | |
1102 | * which theoretically may cause races. | |
1103 | */ | |
1104 | mutex_lock(&pvt->iface_mtx); | |
1105 | pvt_update(pvt->regs + PVT_INTR_MASK, PVT_INTR_DVALID, 0); | |
1106 | pvt_update(pvt->regs + PVT_CTRL, PVT_CTRL_EN, PVT_CTRL_EN); | |
1107 | mutex_unlock(&pvt->iface_mtx); | |
1108 | ||
1109 | return 0; | |
1110 | } | |
1111 | ||
1112 | #else /* !CONFIG_SENSORS_BT1_PVT_ALARMS */ | |
1113 | ||
1114 | static int pvt_enable_iface(struct pvt_hwmon *pvt) | |
1115 | { | |
1116 | return 0; | |
1117 | } | |
1118 | ||
1119 | #endif /* !CONFIG_SENSORS_BT1_PVT_ALARMS */ | |
1120 | ||
1121 | static int pvt_probe(struct platform_device *pdev) | |
1122 | { | |
1123 | struct pvt_hwmon *pvt; | |
1124 | int ret; | |
1125 | ||
1126 | pvt = pvt_create_data(pdev); | |
1127 | if (IS_ERR(pvt)) | |
1128 | return PTR_ERR(pvt); | |
1129 | ||
1130 | ret = pvt_request_regs(pvt); | |
1131 | if (ret) | |
1132 | return ret; | |
1133 | ||
1134 | ret = pvt_request_clks(pvt); | |
1135 | if (ret) | |
1136 | return ret; | |
1137 | ||
a6db1561 SS |
1138 | ret = pvt_check_pwr(pvt); |
1139 | if (ret) | |
1140 | return ret; | |
1141 | ||
0015503e SS |
1142 | ret = pvt_init_iface(pvt); |
1143 | if (ret) | |
1144 | return ret; | |
87976ce2 SS |
1145 | |
1146 | ret = pvt_request_irq(pvt); | |
1147 | if (ret) | |
1148 | return ret; | |
1149 | ||
1150 | ret = pvt_create_hwmon(pvt); | |
1151 | if (ret) | |
1152 | return ret; | |
1153 | ||
1154 | ret = pvt_enable_iface(pvt); | |
1155 | if (ret) | |
1156 | return ret; | |
1157 | ||
1158 | return 0; | |
1159 | } | |
1160 | ||
1161 | static const struct of_device_id pvt_of_match[] = { | |
1162 | { .compatible = "baikal,bt1-pvt" }, | |
1163 | { } | |
1164 | }; | |
1165 | MODULE_DEVICE_TABLE(of, pvt_of_match); | |
1166 | ||
1167 | static struct platform_driver pvt_driver = { | |
1168 | .probe = pvt_probe, | |
1169 | .driver = { | |
1170 | .name = "bt1-pvt", | |
1171 | .of_match_table = pvt_of_match | |
1172 | } | |
1173 | }; | |
1174 | module_platform_driver(pvt_driver); | |
1175 | ||
1176 | MODULE_AUTHOR("Maxim Kaurkin <maxim.kaurkin@baikalelectronics.ru>"); | |
1177 | MODULE_DESCRIPTION("Baikal-T1 PVT driver"); | |
1178 | MODULE_LICENSE("GPL v2"); |