0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/delay.h>
0011 #include <linux/err.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/io.h>
0014 #include <linux/iopoll.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_address.h>
0018 #include <linux/of_device.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/thermal.h>
0021
0022 #include "../thermal_core.h"
0023 #include "../thermal_hwmon.h"
0024
0025
0026 #define DTS_CFGR1_OFFSET 0x0
0027 #define DTS_T0VALR1_OFFSET 0x8
0028 #define DTS_RAMPVALR_OFFSET 0X10
0029 #define DTS_ITR1_OFFSET 0x14
0030 #define DTS_DR_OFFSET 0x1C
0031 #define DTS_SR_OFFSET 0x20
0032 #define DTS_ITENR_OFFSET 0x24
0033 #define DTS_ICIFR_OFFSET 0x28
0034
0035
0036 #define HSREF_CLK_DIV_MASK GENMASK(30, 24)
0037 #define TS1_SMP_TIME_MASK GENMASK(19, 16)
0038 #define TS1_INTRIG_SEL_MASK GENMASK(11, 8)
0039
0040
0041 #define TS1_T0_MASK GENMASK(17, 16)
0042 #define TS1_FMT0_MASK GENMASK(15, 0)
0043
0044
0045 #define TS1_RAMP_COEFF_MASK GENMASK(15, 0)
0046
0047
0048 #define TS1_HITTHD_MASK GENMASK(31, 16)
0049 #define TS1_LITTHD_MASK GENMASK(15, 0)
0050
0051
0052 #define TS1_MFREQ_MASK GENMASK(15, 0)
0053
0054
0055 #define ITENR_MASK (GENMASK(2, 0) | GENMASK(6, 4))
0056
0057
0058 #define ICIFR_MASK (GENMASK(2, 0) | GENMASK(6, 4))
0059
0060
0061 #define TS1_T0_POS 16
0062 #define TS1_HITTHD_POS 16
0063 #define TS1_LITTHD_POS 0
0064 #define HSREF_CLK_DIV_POS 24
0065
0066
0067 #define TS1_EN BIT(0)
0068 #define TS1_START BIT(4)
0069 #define REFCLK_SEL BIT(20)
0070 #define REFCLK_LSE REFCLK_SEL
0071 #define Q_MEAS_OPT BIT(21)
0072 #define CALIBRATION_CONTROL Q_MEAS_OPT
0073
0074
0075 #define TS_RDY BIT(15)
0076
0077 #define HIGH_THRESHOLD BIT(2)
0078 #define LOW_THRESHOLD BIT(1)
0079
0080
0081 #define ADJUST 100
0082 #define ONE_MHZ 1000000
0083 #define POLL_TIMEOUT 5000
0084 #define STARTUP_TIME 40
0085 #define TS1_T0_VAL0 30000
0086 #define TS1_T0_VAL1 130000
0087 #define NO_HW_TRIG 0
0088 #define SAMPLING_TIME 15
0089
0090 struct stm_thermal_sensor {
0091 struct device *dev;
0092 struct thermal_zone_device *th_dev;
0093 enum thermal_device_mode mode;
0094 struct clk *clk;
0095 unsigned int low_temp_enabled;
0096 unsigned int high_temp_enabled;
0097 int irq;
0098 void __iomem *base;
0099 int t0, fmt0, ramp_coeff;
0100 };
0101
0102 static int stm_enable_irq(struct stm_thermal_sensor *sensor)
0103 {
0104 u32 value;
0105
0106 dev_dbg(sensor->dev, "low:%d high:%d\n", sensor->low_temp_enabled,
0107 sensor->high_temp_enabled);
0108
0109
0110 value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
0111 value &= ~(LOW_THRESHOLD | HIGH_THRESHOLD);
0112
0113 if (sensor->low_temp_enabled)
0114 value |= HIGH_THRESHOLD;
0115
0116 if (sensor->high_temp_enabled)
0117 value |= LOW_THRESHOLD;
0118
0119
0120 writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
0121
0122 return 0;
0123 }
0124
0125 static irqreturn_t stm_thermal_irq_handler(int irq, void *sdata)
0126 {
0127 struct stm_thermal_sensor *sensor = sdata;
0128
0129 dev_dbg(sensor->dev, "sr:%d\n",
0130 readl_relaxed(sensor->base + DTS_SR_OFFSET));
0131
0132 thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
0133
0134 stm_enable_irq(sensor);
0135
0136
0137 writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
0138
0139 return IRQ_HANDLED;
0140 }
0141
0142 static int stm_sensor_power_on(struct stm_thermal_sensor *sensor)
0143 {
0144 int ret;
0145 u32 value;
0146
0147
0148 value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
0149 value |= TS1_EN;
0150 writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
0151
0152
0153
0154
0155
0156
0157 ret = readl_poll_timeout(sensor->base + DTS_SR_OFFSET,
0158 value, (value & TS_RDY),
0159 STARTUP_TIME, POLL_TIMEOUT);
0160 if (ret)
0161 return ret;
0162
0163
0164 value = readl_relaxed(sensor->base +
0165 DTS_CFGR1_OFFSET);
0166 value |= TS1_START;
0167 writel_relaxed(value, sensor->base +
0168 DTS_CFGR1_OFFSET);
0169
0170 sensor->mode = THERMAL_DEVICE_ENABLED;
0171
0172 return 0;
0173 }
0174
0175 static int stm_sensor_power_off(struct stm_thermal_sensor *sensor)
0176 {
0177 u32 value;
0178
0179 sensor->mode = THERMAL_DEVICE_DISABLED;
0180
0181
0182 value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
0183 value &= ~TS1_START;
0184 writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
0185
0186
0187 usleep_range(STARTUP_TIME, POLL_TIMEOUT);
0188
0189
0190 value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
0191 value &= ~TS1_EN;
0192 writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
0193
0194
0195 return readl_poll_timeout(sensor->base + DTS_SR_OFFSET, value,
0196 !(value & TS_RDY),
0197 STARTUP_TIME, POLL_TIMEOUT);
0198 }
0199
0200 static int stm_thermal_calibration(struct stm_thermal_sensor *sensor)
0201 {
0202 u32 value, clk_freq;
0203 u32 prescaler;
0204
0205
0206 clk_freq = clk_get_rate(sensor->clk);
0207 if (!clk_freq)
0208 return -EINVAL;
0209
0210 prescaler = 0;
0211 clk_freq /= ONE_MHZ;
0212 if (clk_freq) {
0213 while (prescaler <= clk_freq)
0214 prescaler++;
0215 }
0216
0217 value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
0218
0219
0220 value &= ~HSREF_CLK_DIV_MASK;
0221
0222
0223 value |= (prescaler << HSREF_CLK_DIV_POS);
0224
0225
0226 value &= ~REFCLK_SEL;
0227
0228
0229 value |= TS1_SMP_TIME_MASK;
0230
0231
0232 value &= ~CALIBRATION_CONTROL;
0233
0234
0235 value &= ~TS1_INTRIG_SEL_MASK;
0236 value |= NO_HW_TRIG;
0237
0238 writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
0239
0240 return 0;
0241 }
0242
0243
0244 static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor)
0245 {
0246
0247 sensor->t0 = readl_relaxed(sensor->base + DTS_T0VALR1_OFFSET) &
0248 TS1_T0_MASK;
0249 if (!sensor->t0)
0250 sensor->t0 = TS1_T0_VAL0;
0251 else
0252 sensor->t0 = TS1_T0_VAL1;
0253
0254
0255 sensor->fmt0 = ADJUST * (readl_relaxed(sensor->base +
0256 DTS_T0VALR1_OFFSET) & TS1_FMT0_MASK);
0257
0258
0259 sensor->ramp_coeff = readl_relaxed(sensor->base + DTS_RAMPVALR_OFFSET) &
0260 TS1_RAMP_COEFF_MASK;
0261
0262 if (!sensor->fmt0 || !sensor->ramp_coeff) {
0263 dev_err(sensor->dev, "%s: wrong setting\n", __func__);
0264 return -EINVAL;
0265 }
0266
0267 dev_dbg(sensor->dev, "%s: T0 = %doC, FMT0 = %dHz, RAMP_COEFF = %dHz/oC",
0268 __func__, sensor->t0, sensor->fmt0, sensor->ramp_coeff);
0269
0270 return 0;
0271 }
0272
0273 static int stm_thermal_calculate_threshold(struct stm_thermal_sensor *sensor,
0274 int temp, u32 *th)
0275 {
0276 int freqM;
0277
0278
0279 freqM = ((temp - sensor->t0) * sensor->ramp_coeff) / 1000 +
0280 sensor->fmt0;
0281
0282
0283 *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM;
0284 if (!*th)
0285 return -EINVAL;
0286
0287 dev_dbg(sensor->dev, "freqM=%d Hz, threshold=0x%x", freqM, *th);
0288
0289 return 0;
0290 }
0291
0292
0293 static int stm_disable_irq(struct stm_thermal_sensor *sensor)
0294 {
0295 u32 value;
0296
0297
0298 value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
0299 value &= ~ITENR_MASK;
0300 writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
0301
0302 return 0;
0303 }
0304
0305 static int stm_thermal_set_trips(void *data, int low, int high)
0306 {
0307 struct stm_thermal_sensor *sensor = data;
0308 u32 itr1, th;
0309 int ret;
0310
0311 dev_dbg(sensor->dev, "set trips %d <--> %d\n", low, high);
0312
0313
0314 itr1 = readl_relaxed(sensor->base + DTS_ITR1_OFFSET);
0315 itr1 &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK);
0316
0317
0318
0319
0320
0321
0322 if (low > -INT_MAX) {
0323 sensor->low_temp_enabled = 1;
0324
0325 ret = stm_thermal_calculate_threshold(sensor, low - 500, &th);
0326 if (ret)
0327 return ret;
0328
0329 itr1 |= (TS1_HITTHD_MASK & (th << TS1_HITTHD_POS));
0330 } else {
0331 sensor->low_temp_enabled = 0;
0332 }
0333
0334
0335 if (high < INT_MAX) {
0336 sensor->high_temp_enabled = 1;
0337 ret = stm_thermal_calculate_threshold(sensor, high, &th);
0338 if (ret)
0339 return ret;
0340
0341 itr1 |= (TS1_LITTHD_MASK & (th << TS1_LITTHD_POS));
0342 } else {
0343 sensor->high_temp_enabled = 0;
0344 }
0345
0346
0347 writel_relaxed(itr1, sensor->base + DTS_ITR1_OFFSET);
0348
0349 return 0;
0350 }
0351
0352
0353 static int stm_thermal_get_temp(void *data, int *temp)
0354 {
0355 struct stm_thermal_sensor *sensor = data;
0356 u32 periods;
0357 int freqM, ret;
0358
0359 if (sensor->mode != THERMAL_DEVICE_ENABLED)
0360 return -EAGAIN;
0361
0362
0363 ret = readl_relaxed_poll_timeout(sensor->base + DTS_DR_OFFSET, periods,
0364 (periods & TS1_MFREQ_MASK),
0365 STARTUP_TIME, POLL_TIMEOUT);
0366 if (ret)
0367 return ret;
0368
0369
0370 freqM = (clk_get_rate(sensor->clk) * SAMPLING_TIME) / periods;
0371 if (!freqM)
0372 return -EINVAL;
0373
0374
0375 *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + sensor->t0;
0376
0377 return 0;
0378 }
0379
0380
0381 static int stm_register_irq(struct stm_thermal_sensor *sensor)
0382 {
0383 struct device *dev = sensor->dev;
0384 struct platform_device *pdev = to_platform_device(dev);
0385 int ret;
0386
0387 sensor->irq = platform_get_irq(pdev, 0);
0388 if (sensor->irq < 0)
0389 return sensor->irq;
0390
0391 ret = devm_request_threaded_irq(dev, sensor->irq,
0392 NULL,
0393 stm_thermal_irq_handler,
0394 IRQF_ONESHOT,
0395 dev->driver->name, sensor);
0396 if (ret) {
0397 dev_err(dev, "%s: Failed to register IRQ %d\n", __func__,
0398 sensor->irq);
0399 return ret;
0400 }
0401
0402 dev_dbg(dev, "%s: thermal IRQ registered", __func__);
0403
0404 return 0;
0405 }
0406
0407 static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor)
0408 {
0409 int ret;
0410
0411 stm_disable_irq(sensor);
0412
0413 ret = stm_sensor_power_off(sensor);
0414 if (ret)
0415 return ret;
0416
0417 clk_disable_unprepare(sensor->clk);
0418
0419 return 0;
0420 }
0421
0422 static int stm_thermal_prepare(struct stm_thermal_sensor *sensor)
0423 {
0424 int ret;
0425
0426 ret = clk_prepare_enable(sensor->clk);
0427 if (ret)
0428 return ret;
0429
0430 ret = stm_thermal_read_factory_settings(sensor);
0431 if (ret)
0432 goto thermal_unprepare;
0433
0434 ret = stm_thermal_calibration(sensor);
0435 if (ret)
0436 goto thermal_unprepare;
0437
0438 return 0;
0439
0440 thermal_unprepare:
0441 clk_disable_unprepare(sensor->clk);
0442
0443 return ret;
0444 }
0445
0446 #ifdef CONFIG_PM_SLEEP
0447 static int stm_thermal_suspend(struct device *dev)
0448 {
0449 struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
0450
0451 return stm_thermal_sensor_off(sensor);
0452 }
0453
0454 static int stm_thermal_resume(struct device *dev)
0455 {
0456 int ret;
0457 struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
0458
0459 ret = stm_thermal_prepare(sensor);
0460 if (ret)
0461 return ret;
0462
0463 ret = stm_sensor_power_on(sensor);
0464 if (ret)
0465 return ret;
0466
0467 thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
0468 stm_enable_irq(sensor);
0469
0470 return 0;
0471 }
0472 #endif
0473
0474 static SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops,
0475 stm_thermal_suspend, stm_thermal_resume);
0476
0477 static const struct thermal_zone_of_device_ops stm_tz_ops = {
0478 .get_temp = stm_thermal_get_temp,
0479 .set_trips = stm_thermal_set_trips,
0480 };
0481
0482 static const struct of_device_id stm_thermal_of_match[] = {
0483 { .compatible = "st,stm32-thermal"},
0484 { }
0485 };
0486 MODULE_DEVICE_TABLE(of, stm_thermal_of_match);
0487
0488 static int stm_thermal_probe(struct platform_device *pdev)
0489 {
0490 struct stm_thermal_sensor *sensor;
0491 struct resource *res;
0492 void __iomem *base;
0493 int ret;
0494
0495 if (!pdev->dev.of_node) {
0496 dev_err(&pdev->dev, "%s: device tree node not found\n",
0497 __func__);
0498 return -EINVAL;
0499 }
0500
0501 sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
0502 if (!sensor)
0503 return -ENOMEM;
0504
0505 platform_set_drvdata(pdev, sensor);
0506
0507 sensor->dev = &pdev->dev;
0508
0509 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0510 base = devm_ioremap_resource(&pdev->dev, res);
0511 if (IS_ERR(base))
0512 return PTR_ERR(base);
0513
0514
0515 sensor->base = base;
0516
0517 sensor->clk = devm_clk_get(&pdev->dev, "pclk");
0518 if (IS_ERR(sensor->clk)) {
0519 dev_err(&pdev->dev, "%s: failed to fetch PCLK clock\n",
0520 __func__);
0521 return PTR_ERR(sensor->clk);
0522 }
0523
0524 stm_disable_irq(sensor);
0525
0526
0527 writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
0528
0529
0530 ret = stm_thermal_prepare(sensor);
0531 if (ret) {
0532 dev_err(&pdev->dev, "Error prepare sensor: %d\n", ret);
0533 return ret;
0534 }
0535
0536 ret = stm_sensor_power_on(sensor);
0537 if (ret) {
0538 dev_err(&pdev->dev, "Error power on sensor: %d\n", ret);
0539 return ret;
0540 }
0541
0542 sensor->th_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
0543 sensor,
0544 &stm_tz_ops);
0545
0546 if (IS_ERR(sensor->th_dev)) {
0547 dev_err(&pdev->dev, "%s: thermal zone sensor registering KO\n",
0548 __func__);
0549 ret = PTR_ERR(sensor->th_dev);
0550 return ret;
0551 }
0552
0553
0554 ret = stm_register_irq(sensor);
0555 if (ret)
0556 goto err_tz;
0557
0558 stm_enable_irq(sensor);
0559
0560
0561
0562
0563
0564 sensor->th_dev->tzp->no_hwmon = false;
0565 ret = thermal_add_hwmon_sysfs(sensor->th_dev);
0566 if (ret)
0567 goto err_tz;
0568
0569 dev_info(&pdev->dev, "%s: Driver initialized successfully\n",
0570 __func__);
0571
0572 return 0;
0573
0574 err_tz:
0575 thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
0576 return ret;
0577 }
0578
0579 static int stm_thermal_remove(struct platform_device *pdev)
0580 {
0581 struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
0582
0583 stm_thermal_sensor_off(sensor);
0584 thermal_remove_hwmon_sysfs(sensor->th_dev);
0585 thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
0586
0587 return 0;
0588 }
0589
0590 static struct platform_driver stm_thermal_driver = {
0591 .driver = {
0592 .name = "stm_thermal",
0593 .pm = &stm_thermal_pm_ops,
0594 .of_match_table = stm_thermal_of_match,
0595 },
0596 .probe = stm_thermal_probe,
0597 .remove = stm_thermal_remove,
0598 };
0599 module_platform_driver(stm_thermal_driver);
0600
0601 MODULE_DESCRIPTION("STMicroelectronics STM32 Thermal Sensor Driver");
0602 MODULE_AUTHOR("David Hernandez Sanchez <david.hernandezsanchez@st.com>");
0603 MODULE_LICENSE("GPL v2");
0604 MODULE_ALIAS("platform:stm_thermal");