1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * ST Thermal Sensor Driver for memory mapped sensors.
4 * Author: Ajit Pal Singh <ajitpal.singh@st.com>
6 * Copyright (C) 2003-2014 STMicroelectronics (R&D) Limited
10 #include <linux/module.h>
12 #include "st_thermal.h"
14 #define STIH416_MPE_CONF 0x0
15 #define STIH416_MPE_STATUS 0x4
16 #define STIH416_MPE_INT_THRESH 0x8
17 #define STIH416_MPE_INT_EN 0xC
19 /* Power control bits for the memory mapped thermal sensor */
20 #define THERMAL_PDN BIT(4)
21 #define THERMAL_SRSTN BIT(10)
23 static const struct reg_field st_mmap_thermal_regfields
[MAX_REGFIELDS
] = {
25 * According to the STIH416 MPE temp sensor data sheet -
26 * the PDN (Power Down Bit) and SRSTN (Soft Reset Bit) need to be
27 * written simultaneously for powering on and off the temperature
28 * sensor. regmap_update_bits() will be used to update the register.
30 [INT_THRESH_HI
] = REG_FIELD(STIH416_MPE_INT_THRESH
, 0, 7),
31 [DCORRECT
] = REG_FIELD(STIH416_MPE_CONF
, 5, 9),
32 [OVERFLOW
] = REG_FIELD(STIH416_MPE_STATUS
, 9, 9),
33 [DATA
] = REG_FIELD(STIH416_MPE_STATUS
, 11, 18),
34 [INT_ENABLE
] = REG_FIELD(STIH416_MPE_INT_EN
, 0, 0),
37 static irqreturn_t
st_mmap_thermal_trip_handler(int irq
, void *sdata
)
39 struct st_thermal_sensor
*sensor
= sdata
;
41 thermal_zone_device_update(sensor
->thermal_dev
,
42 THERMAL_EVENT_UNSPECIFIED
);
47 /* Private ops for the Memory Mapped based thermal sensors */
48 static int st_mmap_power_ctrl(struct st_thermal_sensor
*sensor
,
49 enum st_thermal_power_state power_state
)
51 const unsigned int mask
= (THERMAL_PDN
| THERMAL_SRSTN
);
52 const unsigned int val
= power_state
? mask
: 0;
54 return regmap_update_bits(sensor
->regmap
, STIH416_MPE_CONF
, mask
, val
);
57 static int st_mmap_alloc_regfields(struct st_thermal_sensor
*sensor
)
59 struct device
*dev
= sensor
->dev
;
60 struct regmap
*regmap
= sensor
->regmap
;
61 const struct reg_field
*reg_fields
= sensor
->cdata
->reg_fields
;
63 sensor
->int_thresh_hi
= devm_regmap_field_alloc(dev
, regmap
,
64 reg_fields
[INT_THRESH_HI
]);
65 sensor
->int_enable
= devm_regmap_field_alloc(dev
, regmap
,
66 reg_fields
[INT_ENABLE
]);
68 if (IS_ERR(sensor
->int_thresh_hi
) || IS_ERR(sensor
->int_enable
)) {
69 dev_err(dev
, "failed to alloc mmap regfields\n");
76 static int st_mmap_enable_irq(struct st_thermal_sensor
*sensor
)
80 /* Set upper critical threshold */
81 ret
= regmap_field_write(sensor
->int_thresh_hi
,
82 sensor
->cdata
->crit_temp
-
83 sensor
->cdata
->temp_adjust_val
);
87 return regmap_field_write(sensor
->int_enable
, 1);
90 static int st_mmap_register_enable_irq(struct st_thermal_sensor
*sensor
)
92 struct device
*dev
= sensor
->dev
;
93 struct platform_device
*pdev
= to_platform_device(dev
);
96 sensor
->irq
= platform_get_irq(pdev
, 0);
100 ret
= devm_request_threaded_irq(dev
, sensor
->irq
,
101 NULL
, st_mmap_thermal_trip_handler
,
102 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
103 dev
->driver
->name
, sensor
);
105 dev_err(dev
, "failed to register IRQ %d\n", sensor
->irq
);
109 return st_mmap_enable_irq(sensor
);
112 static const struct regmap_config st_416mpe_regmap_config
= {
118 static int st_mmap_regmap_init(struct st_thermal_sensor
*sensor
)
120 struct device
*dev
= sensor
->dev
;
121 struct platform_device
*pdev
= to_platform_device(dev
);
123 sensor
->mmio_base
= devm_platform_get_and_ioremap_resource(pdev
, 0, NULL
);
124 if (IS_ERR(sensor
->mmio_base
))
125 return PTR_ERR(sensor
->mmio_base
);
127 sensor
->regmap
= devm_regmap_init_mmio(dev
, sensor
->mmio_base
,
128 &st_416mpe_regmap_config
);
129 if (IS_ERR(sensor
->regmap
)) {
130 dev_err(dev
, "failed to initialise regmap\n");
131 return PTR_ERR(sensor
->regmap
);
137 static const struct st_thermal_sensor_ops st_mmap_sensor_ops
= {
138 .power_ctrl
= st_mmap_power_ctrl
,
139 .alloc_regfields
= st_mmap_alloc_regfields
,
140 .regmap_init
= st_mmap_regmap_init
,
141 .register_enable_irq
= st_mmap_register_enable_irq
,
142 .enable_irq
= st_mmap_enable_irq
,
145 /* Compatible device data stih407 thermal sensor */
146 static const struct st_thermal_compat_data st_407_cdata
= {
147 .reg_fields
= st_mmap_thermal_regfields
,
148 .ops
= &st_mmap_sensor_ops
,
149 .calibration_val
= 16,
150 .temp_adjust_val
= -95,
154 static const struct of_device_id st_mmap_thermal_of_match
[] = {
155 { .compatible
= "st,stih407-thermal", .data
= &st_407_cdata
},
158 MODULE_DEVICE_TABLE(of
, st_mmap_thermal_of_match
);
160 static int st_mmap_probe(struct platform_device
*pdev
)
162 return st_thermal_register(pdev
, st_mmap_thermal_of_match
);
165 static void st_mmap_remove(struct platform_device
*pdev
)
167 st_thermal_unregister(pdev
);
170 static struct platform_driver st_mmap_thermal_driver
= {
172 .name
= "st_thermal_mmap",
173 .pm
= pm_sleep_ptr(&st_thermal_pm_ops
),
174 .of_match_table
= st_mmap_thermal_of_match
,
176 .probe
= st_mmap_probe
,
177 .remove
= st_mmap_remove
,
180 module_platform_driver(st_mmap_thermal_driver
);
182 MODULE_AUTHOR("STMicroelectronics (R&D) Limited <ajitpal.singh@st.com>");
183 MODULE_DESCRIPTION("STMicroelectronics STi SoC Thermal Sensor Driver");
184 MODULE_LICENSE("GPL v2");