thermal: generic-adc: Fix adc to temp interpolation
[sfrench/cifs-2.6.git] / drivers / thermal / armada_thermal.c
1 /*
2  * Marvell EBU Armada SoCs thermal sensor driver
3  *
4  * Copyright (C) 2013 Marvell
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  */
16 #include <linux/device.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19 #include <linux/kernel.h>
20 #include <linux/of.h>
21 #include <linux/module.h>
22 #include <linux/delay.h>
23 #include <linux/platform_device.h>
24 #include <linux/of_device.h>
25 #include <linux/thermal.h>
26 #include <linux/iopoll.h>
27 #include <linux/mfd/syscon.h>
28 #include <linux/regmap.h>
29 #include <linux/interrupt.h>
30
31 #include "thermal_core.h"
32
33 #define TO_MCELSIUS(c)                  ((c) * 1000)
34
35 /* Thermal Manager Control and Status Register */
36 #define PMU_TDC0_SW_RST_MASK            (0x1 << 1)
37 #define PMU_TM_DISABLE_OFFS             0
38 #define PMU_TM_DISABLE_MASK             (0x1 << PMU_TM_DISABLE_OFFS)
39 #define PMU_TDC0_REF_CAL_CNT_OFFS       11
40 #define PMU_TDC0_REF_CAL_CNT_MASK       (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
41 #define PMU_TDC0_OTF_CAL_MASK           (0x1 << 30)
42 #define PMU_TDC0_START_CAL_MASK         (0x1 << 25)
43
44 #define A375_UNIT_CONTROL_SHIFT         27
45 #define A375_UNIT_CONTROL_MASK          0x7
46 #define A375_READOUT_INVERT             BIT(15)
47 #define A375_HW_RESETn                  BIT(8)
48
49 /* Errata fields */
50 #define CONTROL0_TSEN_TC_TRIM_MASK      0x7
51 #define CONTROL0_TSEN_TC_TRIM_VAL       0x3
52
53 #define CONTROL0_TSEN_START             BIT(0)
54 #define CONTROL0_TSEN_RESET             BIT(1)
55 #define CONTROL0_TSEN_ENABLE            BIT(2)
56 #define CONTROL0_TSEN_AVG_BYPASS        BIT(6)
57 #define CONTROL0_TSEN_CHAN_SHIFT        13
58 #define CONTROL0_TSEN_CHAN_MASK         0xF
59 #define CONTROL0_TSEN_OSR_SHIFT         24
60 #define CONTROL0_TSEN_OSR_MAX           0x3
61 #define CONTROL0_TSEN_MODE_SHIFT        30
62 #define CONTROL0_TSEN_MODE_EXTERNAL     0x2
63 #define CONTROL0_TSEN_MODE_MASK         0x3
64
65 #define CONTROL1_TSEN_AVG_SHIFT         0
66 #define CONTROL1_TSEN_AVG_MASK          0x7
67 #define CONTROL1_EXT_TSEN_SW_RESET      BIT(7)
68 #define CONTROL1_EXT_TSEN_HW_RESETn     BIT(8)
69 #define CONTROL1_TSEN_INT_EN            BIT(25)
70 #define CONTROL1_TSEN_SELECT_OFF        21
71 #define CONTROL1_TSEN_SELECT_MASK       0x3
72
73 #define STATUS_POLL_PERIOD_US           1000
74 #define STATUS_POLL_TIMEOUT_US          100000
75 #define OVERHEAT_INT_POLL_DELAY_MS      1000
76
77 struct armada_thermal_data;
78
79 /* Marvell EBU Thermal Sensor Dev Structure */
80 struct armada_thermal_priv {
81         struct device *dev;
82         struct regmap *syscon;
83         char zone_name[THERMAL_NAME_LENGTH];
84         /* serialize temperature reads/updates */
85         struct mutex update_lock;
86         struct armada_thermal_data *data;
87         struct thermal_zone_device *overheat_sensor;
88         int interrupt_source;
89         int current_channel;
90         long current_threshold;
91         long current_hysteresis;
92 };
93
94 struct armada_thermal_data {
95         /* Initialize the thermal IC */
96         void (*init)(struct platform_device *pdev,
97                      struct armada_thermal_priv *priv);
98
99         /* Formula coeficients: temp = (b - m * reg) / div */
100         s64 coef_b;
101         s64 coef_m;
102         u32 coef_div;
103         bool inverted;
104         bool signed_sample;
105
106         /* Register shift and mask to access the sensor temperature */
107         unsigned int temp_shift;
108         unsigned int temp_mask;
109         unsigned int thresh_shift;
110         unsigned int hyst_shift;
111         unsigned int hyst_mask;
112         u32 is_valid_bit;
113
114         /* Syscon access */
115         unsigned int syscon_control0_off;
116         unsigned int syscon_control1_off;
117         unsigned int syscon_status_off;
118         unsigned int dfx_irq_cause_off;
119         unsigned int dfx_irq_mask_off;
120         unsigned int dfx_overheat_irq;
121         unsigned int dfx_server_irq_mask_off;
122         unsigned int dfx_server_irq_en;
123
124         /* One sensor is in the thermal IC, the others are in the CPUs if any */
125         unsigned int cpu_nr;
126 };
127
128 struct armada_drvdata {
129         enum drvtype {
130                 LEGACY,
131                 SYSCON
132         } type;
133         union {
134                 struct armada_thermal_priv *priv;
135                 struct thermal_zone_device *tz;
136         } data;
137 };
138
139 /*
140  * struct armada_thermal_sensor - hold the information of one thermal sensor
141  * @thermal: pointer to the local private structure
142  * @tzd: pointer to the thermal zone device
143  * @id: identifier of the thermal sensor
144  */
145 struct armada_thermal_sensor {
146         struct armada_thermal_priv *priv;
147         int id;
148 };
149
150 static void armadaxp_init(struct platform_device *pdev,
151                           struct armada_thermal_priv *priv)
152 {
153         struct armada_thermal_data *data = priv->data;
154         u32 reg;
155
156         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
157         reg |= PMU_TDC0_OTF_CAL_MASK;
158
159         /* Reference calibration value */
160         reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
161         reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
162
163         /* Reset the sensor */
164         reg |= PMU_TDC0_SW_RST_MASK;
165
166         regmap_write(priv->syscon, data->syscon_control1_off, reg);
167
168         /* Enable the sensor */
169         regmap_read(priv->syscon, data->syscon_status_off, &reg);
170         reg &= ~PMU_TM_DISABLE_MASK;
171         regmap_write(priv->syscon, data->syscon_status_off, reg);
172 }
173
174 static void armada370_init(struct platform_device *pdev,
175                            struct armada_thermal_priv *priv)
176 {
177         struct armada_thermal_data *data = priv->data;
178         u32 reg;
179
180         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
181         reg |= PMU_TDC0_OTF_CAL_MASK;
182
183         /* Reference calibration value */
184         reg &= ~PMU_TDC0_REF_CAL_CNT_MASK;
185         reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS);
186
187         /* Reset the sensor */
188         reg &= ~PMU_TDC0_START_CAL_MASK;
189
190         regmap_write(priv->syscon, data->syscon_control1_off, reg);
191
192         msleep(10);
193 }
194
195 static void armada375_init(struct platform_device *pdev,
196                            struct armada_thermal_priv *priv)
197 {
198         struct armada_thermal_data *data = priv->data;
199         u32 reg;
200
201         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
202         reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
203         reg &= ~A375_READOUT_INVERT;
204         reg &= ~A375_HW_RESETn;
205         regmap_write(priv->syscon, data->syscon_control1_off, reg);
206
207         msleep(20);
208
209         reg |= A375_HW_RESETn;
210         regmap_write(priv->syscon, data->syscon_control1_off, reg);
211
212         msleep(50);
213 }
214
215 static int armada_wait_sensor_validity(struct armada_thermal_priv *priv)
216 {
217         u32 reg;
218
219         return regmap_read_poll_timeout(priv->syscon,
220                                         priv->data->syscon_status_off, reg,
221                                         reg & priv->data->is_valid_bit,
222                                         STATUS_POLL_PERIOD_US,
223                                         STATUS_POLL_TIMEOUT_US);
224 }
225
226 static void armada380_init(struct platform_device *pdev,
227                            struct armada_thermal_priv *priv)
228 {
229         struct armada_thermal_data *data = priv->data;
230         u32 reg;
231
232         /* Disable the HW/SW reset */
233         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
234         reg |= CONTROL1_EXT_TSEN_HW_RESETn;
235         reg &= ~CONTROL1_EXT_TSEN_SW_RESET;
236         regmap_write(priv->syscon, data->syscon_control1_off, reg);
237
238         /* Set Tsen Tc Trim to correct default value (errata #132698) */
239         regmap_read(priv->syscon, data->syscon_control0_off, &reg);
240         reg &= ~CONTROL0_TSEN_TC_TRIM_MASK;
241         reg |= CONTROL0_TSEN_TC_TRIM_VAL;
242         regmap_write(priv->syscon, data->syscon_control0_off, reg);
243 }
244
245 static void armada_ap806_init(struct platform_device *pdev,
246                               struct armada_thermal_priv *priv)
247 {
248         struct armada_thermal_data *data = priv->data;
249         u32 reg;
250
251         regmap_read(priv->syscon, data->syscon_control0_off, &reg);
252         reg &= ~CONTROL0_TSEN_RESET;
253         reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE;
254
255         /* Sample every ~2ms */
256         reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
257
258         /* Enable average (2 samples by default) */
259         reg &= ~CONTROL0_TSEN_AVG_BYPASS;
260
261         regmap_write(priv->syscon, data->syscon_control0_off, reg);
262 }
263
264 static void armada_cp110_init(struct platform_device *pdev,
265                               struct armada_thermal_priv *priv)
266 {
267         struct armada_thermal_data *data = priv->data;
268         u32 reg;
269
270         armada380_init(pdev, priv);
271
272         /* Sample every ~2ms */
273         regmap_read(priv->syscon, data->syscon_control0_off, &reg);
274         reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT;
275         regmap_write(priv->syscon, data->syscon_control0_off, reg);
276
277         /* Average the output value over 2^1 = 2 samples */
278         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
279         reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT;
280         reg |= 1 << CONTROL1_TSEN_AVG_SHIFT;
281         regmap_write(priv->syscon, data->syscon_control1_off, reg);
282 }
283
284 static bool armada_is_valid(struct armada_thermal_priv *priv)
285 {
286         u32 reg;
287
288         if (!priv->data->is_valid_bit)
289                 return true;
290
291         regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
292
293         return reg & priv->data->is_valid_bit;
294 }
295
296 static void armada_enable_overheat_interrupt(struct armada_thermal_priv *priv)
297 {
298         struct armada_thermal_data *data = priv->data;
299         u32 reg;
300
301         /* Clear DFX temperature IRQ cause */
302         regmap_read(priv->syscon, data->dfx_irq_cause_off, &reg);
303
304         /* Enable DFX Temperature IRQ */
305         regmap_read(priv->syscon, data->dfx_irq_mask_off, &reg);
306         reg |= data->dfx_overheat_irq;
307         regmap_write(priv->syscon, data->dfx_irq_mask_off, reg);
308
309         /* Enable DFX server IRQ */
310         regmap_read(priv->syscon, data->dfx_server_irq_mask_off, &reg);
311         reg |= data->dfx_server_irq_en;
312         regmap_write(priv->syscon, data->dfx_server_irq_mask_off, reg);
313
314         /* Enable overheat interrupt */
315         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
316         reg |= CONTROL1_TSEN_INT_EN;
317         regmap_write(priv->syscon, data->syscon_control1_off, reg);
318 }
319
320 static void __maybe_unused
321 armada_disable_overheat_interrupt(struct armada_thermal_priv *priv)
322 {
323         struct armada_thermal_data *data = priv->data;
324         u32 reg;
325
326         regmap_read(priv->syscon, data->syscon_control1_off, &reg);
327         reg &= ~CONTROL1_TSEN_INT_EN;
328         regmap_write(priv->syscon, data->syscon_control1_off, reg);
329 }
330
331 /* There is currently no board with more than one sensor per channel */
332 static int armada_select_channel(struct armada_thermal_priv *priv, int channel)
333 {
334         struct armada_thermal_data *data = priv->data;
335         u32 ctrl0;
336
337         if (channel < 0 || channel > priv->data->cpu_nr)
338                 return -EINVAL;
339
340         if (priv->current_channel == channel)
341                 return 0;
342
343         /* Stop the measurements */
344         regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0);
345         ctrl0 &= ~CONTROL0_TSEN_START;
346         regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
347
348         /* Reset the mode, internal sensor will be automatically selected */
349         ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT);
350
351         /* Other channels are external and should be selected accordingly */
352         if (channel) {
353                 /* Change the mode to external */
354                 ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL <<
355                          CONTROL0_TSEN_MODE_SHIFT;
356                 /* Select the sensor */
357                 ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT);
358                 ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT;
359         }
360
361         /* Actually set the mode/channel */
362         regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
363         priv->current_channel = channel;
364
365         /* Re-start the measurements */
366         ctrl0 |= CONTROL0_TSEN_START;
367         regmap_write(priv->syscon, data->syscon_control0_off, ctrl0);
368
369         /*
370          * The IP has a latency of ~15ms, so after updating the selected source,
371          * we must absolutely wait for the sensor validity bit to ensure we read
372          * actual data.
373          */
374         if (armada_wait_sensor_validity(priv)) {
375                 dev_err(priv->dev,
376                         "Temperature sensor reading not valid\n");
377                 return -EIO;
378         }
379
380         return 0;
381 }
382
383 static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp)
384 {
385         u32 reg, div;
386         s64 sample, b, m;
387
388         regmap_read(priv->syscon, priv->data->syscon_status_off, &reg);
389         reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask;
390         if (priv->data->signed_sample)
391                 /* The most significant bit is the sign bit */
392                 sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1);
393         else
394                 sample = reg;
395
396         /* Get formula coeficients */
397         b = priv->data->coef_b;
398         m = priv->data->coef_m;
399         div = priv->data->coef_div;
400
401         if (priv->data->inverted)
402                 *temp = div_s64((m * sample) - b, div);
403         else
404                 *temp = div_s64(b - (m * sample), div);
405
406         return 0;
407 }
408
409 static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
410                                   int *temp)
411 {
412         struct armada_thermal_priv *priv = thermal->devdata;
413         int ret;
414
415         /* Valid check */
416         if (armada_is_valid(priv)) {
417                 dev_err(priv->dev,
418                         "Temperature sensor reading not valid\n");
419                 return -EIO;
420         }
421
422         /* Do the actual reading */
423         ret = armada_read_sensor(priv, temp);
424
425         return ret;
426 }
427
428 static struct thermal_zone_device_ops legacy_ops = {
429         .get_temp = armada_get_temp_legacy,
430 };
431
432 static int armada_get_temp(void *_sensor, int *temp)
433 {
434         struct armada_thermal_sensor *sensor = _sensor;
435         struct armada_thermal_priv *priv = sensor->priv;
436         int ret;
437
438         mutex_lock(&priv->update_lock);
439
440         /* Select the desired channel */
441         ret = armada_select_channel(priv, sensor->id);
442         if (ret)
443                 goto unlock_mutex;
444
445         /* Do the actual reading */
446         ret = armada_read_sensor(priv, temp);
447         if (ret)
448                 goto unlock_mutex;
449
450         /*
451          * Select back the interrupt source channel from which a potential
452          * critical trip point has been set.
453          */
454         ret = armada_select_channel(priv, priv->interrupt_source);
455
456 unlock_mutex:
457         mutex_unlock(&priv->update_lock);
458
459         return ret;
460 }
461
462 static struct thermal_zone_of_device_ops of_ops = {
463         .get_temp = armada_get_temp,
464 };
465
466 static unsigned int armada_mc_to_reg_temp(struct armada_thermal_data *data,
467                                           unsigned int temp_mc)
468 {
469         s64 b = data->coef_b;
470         s64 m = data->coef_m;
471         s64 div = data->coef_div;
472         unsigned int sample;
473
474         if (data->inverted)
475                 sample = div_s64(((temp_mc * div) + b), m);
476         else
477                 sample = div_s64((b - (temp_mc * div)), m);
478
479         return sample & data->temp_mask;
480 }
481
482 /*
483  * The documentation states:
484  * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2)
485  * which is the mathematical derivation for:
486  * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C
487  */
488 static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200};
489
490 static unsigned int armada_mc_to_reg_hyst(struct armada_thermal_data *data,
491                                           unsigned int hyst_mc)
492 {
493         int i;
494
495         /*
496          * We will always take the smallest possible hysteresis to avoid risking
497          * the hardware integrity by enlarging the threshold by +8°C in the
498          * worst case.
499          */
500         for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--)
501                 if (hyst_mc >= hyst_levels_mc[i])
502                         break;
503
504         return i & data->hyst_mask;
505 }
506
507 static void armada_set_overheat_thresholds(struct armada_thermal_priv *priv,
508                                            int thresh_mc, int hyst_mc)
509 {
510         struct armada_thermal_data *data = priv->data;
511         unsigned int threshold = armada_mc_to_reg_temp(data, thresh_mc);
512         unsigned int hysteresis = armada_mc_to_reg_hyst(data, hyst_mc);
513         u32 ctrl1;
514
515         regmap_read(priv->syscon, data->syscon_control1_off, &ctrl1);
516
517         /* Set Threshold */
518         if (thresh_mc >= 0) {
519                 ctrl1 &= ~(data->temp_mask << data->thresh_shift);
520                 ctrl1 |= threshold << data->thresh_shift;
521                 priv->current_threshold = thresh_mc;
522         }
523
524         /* Set Hysteresis */
525         if (hyst_mc >= 0) {
526                 ctrl1 &= ~(data->hyst_mask << data->hyst_shift);
527                 ctrl1 |= hysteresis << data->hyst_shift;
528                 priv->current_hysteresis = hyst_mc;
529         }
530
531         regmap_write(priv->syscon, data->syscon_control1_off, ctrl1);
532 }
533
534 static irqreturn_t armada_overheat_isr(int irq, void *blob)
535 {
536         /*
537          * Disable the IRQ and continue in thread context (thermal core
538          * notification and temperature monitoring).
539          */
540         disable_irq_nosync(irq);
541
542         return IRQ_WAKE_THREAD;
543 }
544
545 static irqreturn_t armada_overheat_isr_thread(int irq, void *blob)
546 {
547         struct armada_thermal_priv *priv = blob;
548         int low_threshold = priv->current_threshold - priv->current_hysteresis;
549         int temperature;
550         u32 dummy;
551         int ret;
552
553         /* Notify the core in thread context */
554         thermal_zone_device_update(priv->overheat_sensor,
555                                    THERMAL_EVENT_UNSPECIFIED);
556
557         /*
558          * The overheat interrupt must be cleared by reading the DFX interrupt
559          * cause _after_ the temperature has fallen down to the low threshold.
560          * Otherwise future interrupts might not be served.
561          */
562         do {
563                 msleep(OVERHEAT_INT_POLL_DELAY_MS);
564                 mutex_lock(&priv->update_lock);
565                 ret = armada_read_sensor(priv, &temperature);
566                 mutex_unlock(&priv->update_lock);
567                 if (ret)
568                         goto enable_irq;
569         } while (temperature >= low_threshold);
570
571         regmap_read(priv->syscon, priv->data->dfx_irq_cause_off, &dummy);
572
573         /* Notify the thermal core that the temperature is acceptable again */
574         thermal_zone_device_update(priv->overheat_sensor,
575                                    THERMAL_EVENT_UNSPECIFIED);
576
577 enable_irq:
578         enable_irq(irq);
579
580         return IRQ_HANDLED;
581 }
582
583 static const struct armada_thermal_data armadaxp_data = {
584         .init = armadaxp_init,
585         .temp_shift = 10,
586         .temp_mask = 0x1ff,
587         .coef_b = 3153000000ULL,
588         .coef_m = 10000000ULL,
589         .coef_div = 13825,
590         .syscon_status_off = 0xb0,
591         .syscon_control1_off = 0xd0,
592 };
593
594 static const struct armada_thermal_data armada370_data = {
595         .init = armada370_init,
596         .is_valid_bit = BIT(9),
597         .temp_shift = 10,
598         .temp_mask = 0x1ff,
599         .coef_b = 3153000000ULL,
600         .coef_m = 10000000ULL,
601         .coef_div = 13825,
602         .syscon_status_off = 0x0,
603         .syscon_control1_off = 0x4,
604 };
605
606 static const struct armada_thermal_data armada375_data = {
607         .init = armada375_init,
608         .is_valid_bit = BIT(10),
609         .temp_shift = 0,
610         .temp_mask = 0x1ff,
611         .coef_b = 3171900000ULL,
612         .coef_m = 10000000ULL,
613         .coef_div = 13616,
614         .syscon_status_off = 0x78,
615         .syscon_control0_off = 0x7c,
616         .syscon_control1_off = 0x80,
617 };
618
619 static const struct armada_thermal_data armada380_data = {
620         .init = armada380_init,
621         .is_valid_bit = BIT(10),
622         .temp_shift = 0,
623         .temp_mask = 0x3ff,
624         .coef_b = 1172499100ULL,
625         .coef_m = 2000096ULL,
626         .coef_div = 4201,
627         .inverted = true,
628         .syscon_control0_off = 0x70,
629         .syscon_control1_off = 0x74,
630         .syscon_status_off = 0x78,
631 };
632
633 static const struct armada_thermal_data armada_ap806_data = {
634         .init = armada_ap806_init,
635         .is_valid_bit = BIT(16),
636         .temp_shift = 0,
637         .temp_mask = 0x3ff,
638         .thresh_shift = 3,
639         .hyst_shift = 19,
640         .hyst_mask = 0x3,
641         .coef_b = -150000LL,
642         .coef_m = 423ULL,
643         .coef_div = 1,
644         .inverted = true,
645         .signed_sample = true,
646         .syscon_control0_off = 0x84,
647         .syscon_control1_off = 0x88,
648         .syscon_status_off = 0x8C,
649         .dfx_irq_cause_off = 0x108,
650         .dfx_irq_mask_off = 0x10C,
651         .dfx_overheat_irq = BIT(22),
652         .dfx_server_irq_mask_off = 0x104,
653         .dfx_server_irq_en = BIT(1),
654         .cpu_nr = 4,
655 };
656
657 static const struct armada_thermal_data armada_cp110_data = {
658         .init = armada_cp110_init,
659         .is_valid_bit = BIT(10),
660         .temp_shift = 0,
661         .temp_mask = 0x3ff,
662         .thresh_shift = 16,
663         .hyst_shift = 26,
664         .hyst_mask = 0x3,
665         .coef_b = 1172499100ULL,
666         .coef_m = 2000096ULL,
667         .coef_div = 4201,
668         .inverted = true,
669         .syscon_control0_off = 0x70,
670         .syscon_control1_off = 0x74,
671         .syscon_status_off = 0x78,
672         .dfx_irq_cause_off = 0x108,
673         .dfx_irq_mask_off = 0x10C,
674         .dfx_overheat_irq = BIT(20),
675         .dfx_server_irq_mask_off = 0x104,
676         .dfx_server_irq_en = BIT(1),
677 };
678
679 static const struct of_device_id armada_thermal_id_table[] = {
680         {
681                 .compatible = "marvell,armadaxp-thermal",
682                 .data       = &armadaxp_data,
683         },
684         {
685                 .compatible = "marvell,armada370-thermal",
686                 .data       = &armada370_data,
687         },
688         {
689                 .compatible = "marvell,armada375-thermal",
690                 .data       = &armada375_data,
691         },
692         {
693                 .compatible = "marvell,armada380-thermal",
694                 .data       = &armada380_data,
695         },
696         {
697                 .compatible = "marvell,armada-ap806-thermal",
698                 .data       = &armada_ap806_data,
699         },
700         {
701                 .compatible = "marvell,armada-cp110-thermal",
702                 .data       = &armada_cp110_data,
703         },
704         {
705                 /* sentinel */
706         },
707 };
708 MODULE_DEVICE_TABLE(of, armada_thermal_id_table);
709
710 static const struct regmap_config armada_thermal_regmap_config = {
711         .reg_bits = 32,
712         .reg_stride = 4,
713         .val_bits = 32,
714         .fast_io = true,
715 };
716
717 static int armada_thermal_probe_legacy(struct platform_device *pdev,
718                                        struct armada_thermal_priv *priv)
719 {
720         struct armada_thermal_data *data = priv->data;
721         struct resource *res;
722         void __iomem *base;
723
724         /* First memory region points towards the status register */
725         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
726         if (!res)
727                 return -EIO;
728
729         /*
730          * Edit the resource start address and length to map over all the
731          * registers, instead of pointing at them one by one.
732          */
733         res->start -= data->syscon_status_off;
734         res->end = res->start + max(data->syscon_status_off,
735                                     max(data->syscon_control0_off,
736                                         data->syscon_control1_off)) +
737                    sizeof(unsigned int) - 1;
738
739         base = devm_ioremap_resource(&pdev->dev, res);
740         if (IS_ERR(base))
741                 return PTR_ERR(base);
742
743         priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
744                                              &armada_thermal_regmap_config);
745         return PTR_ERR_OR_ZERO(priv->syscon);
746 }
747
748 static int armada_thermal_probe_syscon(struct platform_device *pdev,
749                                        struct armada_thermal_priv *priv)
750 {
751         priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node);
752         return PTR_ERR_OR_ZERO(priv->syscon);
753 }
754
755 static void armada_set_sane_name(struct platform_device *pdev,
756                                  struct armada_thermal_priv *priv)
757 {
758         const char *name = dev_name(&pdev->dev);
759         char *insane_char;
760
761         if (strlen(name) > THERMAL_NAME_LENGTH) {
762                 /*
763                  * When inside a system controller, the device name has the
764                  * form: f06f8000.system-controller:ap-thermal so stripping
765                  * after the ':' should give us a shorter but meaningful name.
766                  */
767                 name = strrchr(name, ':');
768                 if (!name)
769                         name = "armada_thermal";
770                 else
771                         name++;
772         }
773
774         /* Save the name locally */
775         strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1);
776         priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0';
777
778         /* Then check there are no '-' or hwmon core will complain */
779         do {
780                 insane_char = strpbrk(priv->zone_name, "-");
781                 if (insane_char)
782                         *insane_char = '_';
783         } while (insane_char);
784 }
785
786 /*
787  * The IP can manage to trigger interrupts on overheat situation from all the
788  * sensors. However, the interrupt source changes along with the last selected
789  * source (ie. the last read sensor), which is an inconsistent behavior. Avoid
790  * possible glitches by always selecting back only one channel (arbitrarily: the
791  * first in the DT which has a critical trip point). We also disable sensor
792  * switch during overheat situations.
793  */
794 static int armada_configure_overheat_int(struct armada_thermal_priv *priv,
795                                          struct thermal_zone_device *tz,
796                                          int sensor_id)
797 {
798         /* Retrieve the critical trip point to enable the overheat interrupt */
799         const struct thermal_trip *trips = of_thermal_get_trip_points(tz);
800         int ret;
801         int i;
802
803         if (!trips)
804                 return -EINVAL;
805
806         for (i = 0; i < of_thermal_get_ntrips(tz); i++)
807                 if (trips[i].type == THERMAL_TRIP_CRITICAL)
808                         break;
809
810         if (i == of_thermal_get_ntrips(tz))
811                 return -EINVAL;
812
813         ret = armada_select_channel(priv, sensor_id);
814         if (ret)
815                 return ret;
816
817         armada_set_overheat_thresholds(priv,
818                                        trips[i].temperature,
819                                        trips[i].hysteresis);
820         priv->overheat_sensor = tz;
821         priv->interrupt_source = sensor_id;
822
823         armada_enable_overheat_interrupt(priv);
824
825         return 0;
826 }
827
828 static int armada_thermal_probe(struct platform_device *pdev)
829 {
830         struct thermal_zone_device *tz;
831         struct armada_thermal_sensor *sensor;
832         struct armada_drvdata *drvdata;
833         const struct of_device_id *match;
834         struct armada_thermal_priv *priv;
835         int sensor_id, irq;
836         int ret;
837
838         match = of_match_device(armada_thermal_id_table, &pdev->dev);
839         if (!match)
840                 return -ENODEV;
841
842         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
843         if (!priv)
844                 return -ENOMEM;
845
846         drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
847         if (!drvdata)
848                 return -ENOMEM;
849
850         priv->dev = &pdev->dev;
851         priv->data = (struct armada_thermal_data *)match->data;
852
853         mutex_init(&priv->update_lock);
854
855         /*
856          * Legacy DT bindings only described "control1" register (also referred
857          * as "control MSB" on old documentation). Then, bindings moved to cover
858          * "control0/control LSB" and "control1/control MSB" registers within
859          * the same resource, which was then of size 8 instead of 4.
860          *
861          * The logic of defining sporadic registers is broken. For instance, it
862          * blocked the addition of the overheat interrupt feature that needed
863          * another resource somewhere else in the same memory area. One solution
864          * is to define an overall system controller and put the thermal node
865          * into it, which requires the use of regmaps across all the driver.
866          */
867         if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) {
868                 /* Ensure device name is correct for the thermal core */
869                 armada_set_sane_name(pdev, priv);
870
871                 ret = armada_thermal_probe_legacy(pdev, priv);
872                 if (ret)
873                         return ret;
874
875                 priv->data->init(pdev, priv);
876
877                 /* Wait the sensors to be valid */
878                 armada_wait_sensor_validity(priv);
879
880                 tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv,
881                                                   &legacy_ops, NULL, 0, 0);
882                 if (IS_ERR(tz)) {
883                         dev_err(&pdev->dev,
884                                 "Failed to register thermal zone device\n");
885                         return PTR_ERR(tz);
886                 }
887
888                 drvdata->type = LEGACY;
889                 drvdata->data.tz = tz;
890                 platform_set_drvdata(pdev, drvdata);
891
892                 return 0;
893         }
894
895         ret = armada_thermal_probe_syscon(pdev, priv);
896         if (ret)
897                 return ret;
898
899         priv->current_channel = -1;
900         priv->data->init(pdev, priv);
901         drvdata->type = SYSCON;
902         drvdata->data.priv = priv;
903         platform_set_drvdata(pdev, drvdata);
904
905         irq = platform_get_irq(pdev, 0);
906         if (irq == -EPROBE_DEFER)
907                 return irq;
908
909         /* The overheat interrupt feature is not mandatory */
910         if (irq > 0) {
911                 ret = devm_request_threaded_irq(&pdev->dev, irq,
912                                                 armada_overheat_isr,
913                                                 armada_overheat_isr_thread,
914                                                 0, NULL, priv);
915                 if (ret) {
916                         dev_err(&pdev->dev, "Cannot request threaded IRQ %d\n",
917                                 irq);
918                         return ret;
919                 }
920         }
921
922         /*
923          * There is one channel for the IC and one per CPU (if any), each
924          * channel has one sensor.
925          */
926         for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) {
927                 sensor = devm_kzalloc(&pdev->dev,
928                                       sizeof(struct armada_thermal_sensor),
929                                       GFP_KERNEL);
930                 if (!sensor)
931                         return -ENOMEM;
932
933                 /* Register the sensor */
934                 sensor->priv = priv;
935                 sensor->id = sensor_id;
936                 tz = devm_thermal_zone_of_sensor_register(&pdev->dev,
937                                                           sensor->id, sensor,
938                                                           &of_ops);
939                 if (IS_ERR(tz)) {
940                         dev_info(&pdev->dev, "Thermal sensor %d unavailable\n",
941                                  sensor_id);
942                         devm_kfree(&pdev->dev, sensor);
943                         continue;
944                 }
945
946                 /*
947                  * The first channel that has a critical trip point registered
948                  * in the DT will serve as interrupt source. Others possible
949                  * critical trip points will simply be ignored by the driver.
950                  */
951                 if (irq > 0 && !priv->overheat_sensor)
952                         armada_configure_overheat_int(priv, tz, sensor->id);
953         }
954
955         /* Just complain if no overheat interrupt was set up */
956         if (!priv->overheat_sensor)
957                 dev_warn(&pdev->dev, "Overheat interrupt not available\n");
958
959         return 0;
960 }
961
962 static int armada_thermal_exit(struct platform_device *pdev)
963 {
964         struct armada_drvdata *drvdata = platform_get_drvdata(pdev);
965
966         if (drvdata->type == LEGACY)
967                 thermal_zone_device_unregister(drvdata->data.tz);
968
969         return 0;
970 }
971
972 static struct platform_driver armada_thermal_driver = {
973         .probe = armada_thermal_probe,
974         .remove = armada_thermal_exit,
975         .driver = {
976                 .name = "armada_thermal",
977                 .of_match_table = armada_thermal_id_table,
978         },
979 };
980
981 module_platform_driver(armada_thermal_driver);
982
983 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
984 MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver");
985 MODULE_LICENSE("GPL v2");