2 * Marvell EBU Armada SoCs thermal sensor driver
4 * Copyright (C) 2013 Marvell
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.
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.
16 #include <linux/device.h>
17 #include <linux/err.h>
19 #include <linux/kernel.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>
30 /* Thermal Manager Control and Status Register */
31 #define PMU_TDC0_SW_RST_MASK (0x1 << 1)
32 #define PMU_TM_DISABLE_OFFS 0
33 #define PMU_TM_DISABLE_MASK (0x1 << PMU_TM_DISABLE_OFFS)
34 #define PMU_TDC0_REF_CAL_CNT_OFFS 11
35 #define PMU_TDC0_REF_CAL_CNT_MASK (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS)
36 #define PMU_TDC0_OTF_CAL_MASK (0x1 << 30)
37 #define PMU_TDC0_START_CAL_MASK (0x1 << 25)
39 #define A375_UNIT_CONTROL_SHIFT 27
40 #define A375_UNIT_CONTROL_MASK 0x7
41 #define A375_READOUT_INVERT BIT(15)
42 #define A375_HW_RESETn BIT(8)
45 #define CONTROL0_TSEN_TC_TRIM_MASK 0x7
46 #define CONTROL0_TSEN_TC_TRIM_VAL 0x3
48 #define CONTROL0_TSEN_START BIT(0)
49 #define CONTROL0_TSEN_RESET BIT(1)
50 #define CONTROL0_TSEN_ENABLE BIT(2)
51 #define CONTROL0_TSEN_AVG_BYPASS BIT(6)
52 #define CONTROL0_TSEN_CHAN_SHIFT 13
53 #define CONTROL0_TSEN_CHAN_MASK 0xF
54 #define CONTROL0_TSEN_OSR_SHIFT 24
55 #define CONTROL0_TSEN_OSR_MAX 0x3
56 #define CONTROL0_TSEN_MODE_SHIFT 30
57 #define CONTROL0_TSEN_MODE_EXTERNAL 0x2
58 #define CONTROL0_TSEN_MODE_MASK 0x3
60 #define CONTROL1_TSEN_AVG_SHIFT 0
61 #define CONTROL1_TSEN_AVG_MASK 0x7
62 #define CONTROL1_EXT_TSEN_SW_RESET BIT(7)
63 #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8)
65 #define STATUS_POLL_PERIOD_US 1000
66 #define STATUS_POLL_TIMEOUT_US 100000
68 struct armada_thermal_data
;
70 /* Marvell EBU Thermal Sensor Dev Structure */
71 struct armada_thermal_priv
{
73 struct regmap
*syscon
;
74 char zone_name
[THERMAL_NAME_LENGTH
];
75 /* serialize temperature reads/updates */
76 struct mutex update_lock
;
77 struct armada_thermal_data
*data
;
81 struct armada_thermal_data
{
82 /* Initialize the thermal IC */
83 void (*init
)(struct platform_device
*pdev
,
84 struct armada_thermal_priv
*priv
);
86 /* Formula coeficients: temp = (b - m * reg) / div */
93 /* Register shift and mask to access the sensor temperature */
94 unsigned int temp_shift
;
95 unsigned int temp_mask
;
99 unsigned int syscon_control0_off
;
100 unsigned int syscon_control1_off
;
101 unsigned int syscon_status_off
;
103 /* One sensor is in the thermal IC, the others are in the CPUs if any */
107 struct armada_drvdata
{
113 struct armada_thermal_priv
*priv
;
114 struct thermal_zone_device
*tz
;
119 * struct armada_thermal_sensor - hold the information of one thermal sensor
120 * @thermal: pointer to the local private structure
121 * @tzd: pointer to the thermal zone device
122 * @id: identifier of the thermal sensor
124 struct armada_thermal_sensor
{
125 struct armada_thermal_priv
*priv
;
129 static void armadaxp_init(struct platform_device
*pdev
,
130 struct armada_thermal_priv
*priv
)
132 struct armada_thermal_data
*data
= priv
->data
;
135 regmap_read(priv
->syscon
, data
->syscon_control1_off
, ®
);
136 reg
|= PMU_TDC0_OTF_CAL_MASK
;
138 /* Reference calibration value */
139 reg
&= ~PMU_TDC0_REF_CAL_CNT_MASK
;
140 reg
|= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS
);
142 /* Reset the sensor */
143 reg
|= PMU_TDC0_SW_RST_MASK
;
145 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
147 /* Enable the sensor */
148 regmap_read(priv
->syscon
, data
->syscon_status_off
, ®
);
149 reg
&= ~PMU_TM_DISABLE_MASK
;
150 regmap_write(priv
->syscon
, data
->syscon_status_off
, reg
);
153 static void armada370_init(struct platform_device
*pdev
,
154 struct armada_thermal_priv
*priv
)
156 struct armada_thermal_data
*data
= priv
->data
;
159 regmap_read(priv
->syscon
, data
->syscon_control1_off
, ®
);
160 reg
|= PMU_TDC0_OTF_CAL_MASK
;
162 /* Reference calibration value */
163 reg
&= ~PMU_TDC0_REF_CAL_CNT_MASK
;
164 reg
|= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS
);
166 /* Reset the sensor */
167 reg
&= ~PMU_TDC0_START_CAL_MASK
;
169 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
174 static void armada375_init(struct platform_device
*pdev
,
175 struct armada_thermal_priv
*priv
)
177 struct armada_thermal_data
*data
= priv
->data
;
180 regmap_read(priv
->syscon
, data
->syscon_control1_off
, ®
);
181 reg
&= ~(A375_UNIT_CONTROL_MASK
<< A375_UNIT_CONTROL_SHIFT
);
182 reg
&= ~A375_READOUT_INVERT
;
183 reg
&= ~A375_HW_RESETn
;
184 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
188 reg
|= A375_HW_RESETn
;
189 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
194 static int armada_wait_sensor_validity(struct armada_thermal_priv
*priv
)
198 return regmap_read_poll_timeout(priv
->syscon
,
199 priv
->data
->syscon_status_off
, reg
,
200 reg
& priv
->data
->is_valid_bit
,
201 STATUS_POLL_PERIOD_US
,
202 STATUS_POLL_TIMEOUT_US
);
205 static void armada380_init(struct platform_device
*pdev
,
206 struct armada_thermal_priv
*priv
)
208 struct armada_thermal_data
*data
= priv
->data
;
211 /* Disable the HW/SW reset */
212 regmap_read(priv
->syscon
, data
->syscon_control1_off
, ®
);
213 reg
|= CONTROL1_EXT_TSEN_HW_RESETn
;
214 reg
&= ~CONTROL1_EXT_TSEN_SW_RESET
;
215 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
217 /* Set Tsen Tc Trim to correct default value (errata #132698) */
218 regmap_read(priv
->syscon
, data
->syscon_control0_off
, ®
);
219 reg
&= ~CONTROL0_TSEN_TC_TRIM_MASK
;
220 reg
|= CONTROL0_TSEN_TC_TRIM_VAL
;
221 regmap_write(priv
->syscon
, data
->syscon_control0_off
, reg
);
224 static void armada_ap806_init(struct platform_device
*pdev
,
225 struct armada_thermal_priv
*priv
)
227 struct armada_thermal_data
*data
= priv
->data
;
230 regmap_read(priv
->syscon
, data
->syscon_control0_off
, ®
);
231 reg
&= ~CONTROL0_TSEN_RESET
;
232 reg
|= CONTROL0_TSEN_START
| CONTROL0_TSEN_ENABLE
;
234 /* Sample every ~2ms */
235 reg
|= CONTROL0_TSEN_OSR_MAX
<< CONTROL0_TSEN_OSR_SHIFT
;
237 /* Enable average (2 samples by default) */
238 reg
&= ~CONTROL0_TSEN_AVG_BYPASS
;
240 regmap_write(priv
->syscon
, data
->syscon_control0_off
, reg
);
243 static void armada_cp110_init(struct platform_device
*pdev
,
244 struct armada_thermal_priv
*priv
)
246 struct armada_thermal_data
*data
= priv
->data
;
249 armada380_init(pdev
, priv
);
251 /* Sample every ~2ms */
252 regmap_read(priv
->syscon
, data
->syscon_control0_off
, ®
);
253 reg
|= CONTROL0_TSEN_OSR_MAX
<< CONTROL0_TSEN_OSR_SHIFT
;
254 regmap_write(priv
->syscon
, data
->syscon_control0_off
, reg
);
256 /* Average the output value over 2^1 = 2 samples */
257 regmap_read(priv
->syscon
, data
->syscon_control1_off
, ®
);
258 reg
&= ~CONTROL1_TSEN_AVG_MASK
<< CONTROL1_TSEN_AVG_SHIFT
;
259 reg
|= 1 << CONTROL1_TSEN_AVG_SHIFT
;
260 regmap_write(priv
->syscon
, data
->syscon_control1_off
, reg
);
263 static bool armada_is_valid(struct armada_thermal_priv
*priv
)
267 if (!priv
->data
->is_valid_bit
)
270 regmap_read(priv
->syscon
, priv
->data
->syscon_status_off
, ®
);
272 return reg
& priv
->data
->is_valid_bit
;
275 /* There is currently no board with more than one sensor per channel */
276 static int armada_select_channel(struct armada_thermal_priv
*priv
, int channel
)
278 struct armada_thermal_data
*data
= priv
->data
;
281 if (channel
< 0 || channel
> priv
->data
->cpu_nr
)
284 if (priv
->current_channel
== channel
)
287 /* Stop the measurements */
288 regmap_read(priv
->syscon
, data
->syscon_control0_off
, &ctrl0
);
289 ctrl0
&= ~CONTROL0_TSEN_START
;
290 regmap_write(priv
->syscon
, data
->syscon_control0_off
, ctrl0
);
292 /* Reset the mode, internal sensor will be automatically selected */
293 ctrl0
&= ~(CONTROL0_TSEN_MODE_MASK
<< CONTROL0_TSEN_MODE_SHIFT
);
295 /* Other channels are external and should be selected accordingly */
297 /* Change the mode to external */
298 ctrl0
|= CONTROL0_TSEN_MODE_EXTERNAL
<<
299 CONTROL0_TSEN_MODE_SHIFT
;
300 /* Select the sensor */
301 ctrl0
&= ~(CONTROL0_TSEN_CHAN_MASK
<< CONTROL0_TSEN_CHAN_SHIFT
);
302 ctrl0
|= (channel
- 1) << CONTROL0_TSEN_CHAN_SHIFT
;
305 /* Actually set the mode/channel */
306 regmap_write(priv
->syscon
, data
->syscon_control0_off
, ctrl0
);
307 priv
->current_channel
= channel
;
309 /* Re-start the measurements */
310 ctrl0
|= CONTROL0_TSEN_START
;
311 regmap_write(priv
->syscon
, data
->syscon_control0_off
, ctrl0
);
314 * The IP has a latency of ~15ms, so after updating the selected source,
315 * we must absolutely wait for the sensor validity bit to ensure we read
318 if (armada_wait_sensor_validity(priv
)) {
320 "Temperature sensor reading not valid\n");
327 static int armada_read_sensor(struct armada_thermal_priv
*priv
, int *temp
)
332 regmap_read(priv
->syscon
, priv
->data
->syscon_status_off
, ®
);
333 reg
= (reg
>> priv
->data
->temp_shift
) & priv
->data
->temp_mask
;
334 if (priv
->data
->signed_sample
)
335 /* The most significant bit is the sign bit */
336 sample
= sign_extend32(reg
, fls(priv
->data
->temp_mask
) - 1);
340 /* Get formula coeficients */
341 b
= priv
->data
->coef_b
;
342 m
= priv
->data
->coef_m
;
343 div
= priv
->data
->coef_div
;
345 if (priv
->data
->inverted
)
346 *temp
= div_s64((m
* sample
) - b
, div
);
348 *temp
= div_s64(b
- (m
* sample
), div
);
353 static int armada_get_temp_legacy(struct thermal_zone_device
*thermal
,
356 struct armada_thermal_priv
*priv
= thermal
->devdata
;
360 if (!armada_is_valid(priv
)) {
362 "Temperature sensor reading not valid\n");
366 /* Do the actual reading */
367 ret
= armada_read_sensor(priv
, temp
);
372 static struct thermal_zone_device_ops legacy_ops
= {
373 .get_temp
= armada_get_temp_legacy
,
376 static int armada_get_temp(void *_sensor
, int *temp
)
378 struct armada_thermal_sensor
*sensor
= _sensor
;
379 struct armada_thermal_priv
*priv
= sensor
->priv
;
382 mutex_lock(&priv
->update_lock
);
384 /* Select the desired channel */
385 ret
= armada_select_channel(priv
, sensor
->id
);
389 /* Do the actual reading */
390 ret
= armada_read_sensor(priv
, temp
);
393 mutex_unlock(&priv
->update_lock
);
398 static struct thermal_zone_of_device_ops of_ops
= {
399 .get_temp
= armada_get_temp
,
402 static const struct armada_thermal_data armadaxp_data
= {
403 .init
= armadaxp_init
,
406 .coef_b
= 3153000000ULL,
407 .coef_m
= 10000000ULL,
409 .syscon_status_off
= 0xb0,
410 .syscon_control1_off
= 0xd0,
413 static const struct armada_thermal_data armada370_data
= {
414 .init
= armada370_init
,
415 .is_valid_bit
= BIT(9),
418 .coef_b
= 3153000000ULL,
419 .coef_m
= 10000000ULL,
421 .syscon_status_off
= 0x0,
422 .syscon_control1_off
= 0x4,
425 static const struct armada_thermal_data armada375_data
= {
426 .init
= armada375_init
,
427 .is_valid_bit
= BIT(10),
430 .coef_b
= 3171900000ULL,
431 .coef_m
= 10000000ULL,
433 .syscon_status_off
= 0x78,
434 .syscon_control0_off
= 0x7c,
435 .syscon_control1_off
= 0x80,
438 static const struct armada_thermal_data armada380_data
= {
439 .init
= armada380_init
,
440 .is_valid_bit
= BIT(10),
443 .coef_b
= 1172499100ULL,
444 .coef_m
= 2000096ULL,
447 .syscon_control0_off
= 0x70,
448 .syscon_control1_off
= 0x74,
449 .syscon_status_off
= 0x78,
452 static const struct armada_thermal_data armada_ap806_data
= {
453 .init
= armada_ap806_init
,
454 .is_valid_bit
= BIT(16),
461 .signed_sample
= true,
462 .syscon_control0_off
= 0x84,
463 .syscon_control1_off
= 0x88,
464 .syscon_status_off
= 0x8C,
468 static const struct armada_thermal_data armada_cp110_data
= {
469 .init
= armada_cp110_init
,
470 .is_valid_bit
= BIT(10),
473 .coef_b
= 1172499100ULL,
474 .coef_m
= 2000096ULL,
477 .syscon_control0_off
= 0x70,
478 .syscon_control1_off
= 0x74,
479 .syscon_status_off
= 0x78,
482 static const struct of_device_id armada_thermal_id_table
[] = {
484 .compatible
= "marvell,armadaxp-thermal",
485 .data
= &armadaxp_data
,
488 .compatible
= "marvell,armada370-thermal",
489 .data
= &armada370_data
,
492 .compatible
= "marvell,armada375-thermal",
493 .data
= &armada375_data
,
496 .compatible
= "marvell,armada380-thermal",
497 .data
= &armada380_data
,
500 .compatible
= "marvell,armada-ap806-thermal",
501 .data
= &armada_ap806_data
,
504 .compatible
= "marvell,armada-cp110-thermal",
505 .data
= &armada_cp110_data
,
511 MODULE_DEVICE_TABLE(of
, armada_thermal_id_table
);
513 static const struct regmap_config armada_thermal_regmap_config
= {
520 static int armada_thermal_probe_legacy(struct platform_device
*pdev
,
521 struct armada_thermal_priv
*priv
)
523 struct armada_thermal_data
*data
= priv
->data
;
524 struct resource
*res
;
527 /* First memory region points towards the status register */
528 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
533 * Edit the resource start address and length to map over all the
534 * registers, instead of pointing at them one by one.
536 res
->start
-= data
->syscon_status_off
;
537 res
->end
= res
->start
+ max(data
->syscon_status_off
,
538 max(data
->syscon_control0_off
,
539 data
->syscon_control1_off
)) +
540 sizeof(unsigned int) - 1;
542 base
= devm_ioremap_resource(&pdev
->dev
, res
);
544 return PTR_ERR(base
);
546 priv
->syscon
= devm_regmap_init_mmio(&pdev
->dev
, base
,
547 &armada_thermal_regmap_config
);
548 if (IS_ERR(priv
->syscon
))
549 return PTR_ERR(priv
->syscon
);
554 static int armada_thermal_probe_syscon(struct platform_device
*pdev
,
555 struct armada_thermal_priv
*priv
)
557 priv
->syscon
= syscon_node_to_regmap(pdev
->dev
.parent
->of_node
);
558 if (IS_ERR(priv
->syscon
))
559 return PTR_ERR(priv
->syscon
);
564 static void armada_set_sane_name(struct platform_device
*pdev
,
565 struct armada_thermal_priv
*priv
)
567 const char *name
= dev_name(&pdev
->dev
);
570 if (strlen(name
) > THERMAL_NAME_LENGTH
) {
572 * When inside a system controller, the device name has the
573 * form: f06f8000.system-controller:ap-thermal so stripping
574 * after the ':' should give us a shorter but meaningful name.
576 name
= strrchr(name
, ':');
578 name
= "armada_thermal";
583 /* Save the name locally */
584 strncpy(priv
->zone_name
, name
, THERMAL_NAME_LENGTH
- 1);
585 priv
->zone_name
[THERMAL_NAME_LENGTH
- 1] = '\0';
587 /* Then check there are no '-' or hwmon core will complain */
589 insane_char
= strpbrk(priv
->zone_name
, "-");
592 } while (insane_char
);
595 static int armada_thermal_probe(struct platform_device
*pdev
)
597 struct thermal_zone_device
*tz
;
598 struct armada_thermal_sensor
*sensor
;
599 struct armada_drvdata
*drvdata
;
600 const struct of_device_id
*match
;
601 struct armada_thermal_priv
*priv
;
605 match
= of_match_device(armada_thermal_id_table
, &pdev
->dev
);
609 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
613 drvdata
= devm_kzalloc(&pdev
->dev
, sizeof(*drvdata
), GFP_KERNEL
);
617 priv
->dev
= &pdev
->dev
;
618 priv
->data
= (struct armada_thermal_data
*)match
->data
;
620 mutex_init(&priv
->update_lock
);
623 * Legacy DT bindings only described "control1" register (also referred
624 * as "control MSB" on old documentation). Then, bindings moved to cover
625 * "control0/control LSB" and "control1/control MSB" registers within
626 * the same resource, which was then of size 8 instead of 4.
628 * The logic of defining sporadic registers is broken. For instance, it
629 * blocked the addition of the overheat interrupt feature that needed
630 * another resource somewhere else in the same memory area. One solution
631 * is to define an overall system controller and put the thermal node
632 * into it, which requires the use of regmaps across all the driver.
634 if (IS_ERR(syscon_node_to_regmap(pdev
->dev
.parent
->of_node
))) {
635 /* Ensure device name is correct for the thermal core */
636 armada_set_sane_name(pdev
, priv
);
638 ret
= armada_thermal_probe_legacy(pdev
, priv
);
642 priv
->data
->init(pdev
, priv
);
644 /* Wait the sensors to be valid */
645 armada_wait_sensor_validity(priv
);
647 tz
= thermal_zone_device_register(priv
->zone_name
, 0, 0, priv
,
648 &legacy_ops
, NULL
, 0, 0);
651 "Failed to register thermal zone device\n");
655 drvdata
->type
= LEGACY
;
656 drvdata
->data
.tz
= tz
;
657 platform_set_drvdata(pdev
, drvdata
);
662 ret
= armada_thermal_probe_syscon(pdev
, priv
);
666 priv
->current_channel
= -1;
667 priv
->data
->init(pdev
, priv
);
668 drvdata
->type
= SYSCON
;
669 drvdata
->data
.priv
= priv
;
670 platform_set_drvdata(pdev
, drvdata
);
673 * There is one channel for the IC and one per CPU (if any), each
674 * channel has one sensor.
676 for (sensor_id
= 0; sensor_id
<= priv
->data
->cpu_nr
; sensor_id
++) {
677 sensor
= devm_kzalloc(&pdev
->dev
,
678 sizeof(struct armada_thermal_sensor
),
683 /* Register the sensor */
685 sensor
->id
= sensor_id
;
686 tz
= devm_thermal_zone_of_sensor_register(&pdev
->dev
,
690 dev_info(&pdev
->dev
, "Thermal sensor %d unavailable\n",
692 devm_kfree(&pdev
->dev
, sensor
);
700 static int armada_thermal_exit(struct platform_device
*pdev
)
702 struct armada_drvdata
*drvdata
= platform_get_drvdata(pdev
);
704 if (drvdata
->type
== LEGACY
)
705 thermal_zone_device_unregister(drvdata
->data
.tz
);
710 static struct platform_driver armada_thermal_driver
= {
711 .probe
= armada_thermal_probe
,
712 .remove
= armada_thermal_exit
,
714 .name
= "armada_thermal",
715 .of_match_table
= armada_thermal_id_table
,
719 module_platform_driver(armada_thermal_driver
);
721 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
722 MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver");
723 MODULE_LICENSE("GPL v2");