linux/drivers/thermal/st/stm_thermal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
   4 * Author: David Hernandez Sanchez <david.hernandezsanchez@st.com> for
   5 * STMicroelectronics.
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/clk-provider.h>
  10#include <linux/delay.h>
  11#include <linux/err.h>
  12#include <linux/interrupt.h>
  13#include <linux/io.h>
  14#include <linux/iopoll.h>
  15#include <linux/module.h>
  16#include <linux/of.h>
  17#include <linux/of_address.h>
  18#include <linux/of_device.h>
  19#include <linux/platform_device.h>
  20#include <linux/thermal.h>
  21
  22#include "../thermal_core.h"
  23#include "../thermal_hwmon.h"
  24
  25/* DTS register offsets */
  26#define DTS_CFGR1_OFFSET        0x0
  27#define DTS_T0VALR1_OFFSET      0x8
  28#define DTS_RAMPVALR_OFFSET     0X10
  29#define DTS_ITR1_OFFSET         0x14
  30#define DTS_DR_OFFSET           0x1C
  31#define DTS_SR_OFFSET           0x20
  32#define DTS_ITENR_OFFSET        0x24
  33#define DTS_ICIFR_OFFSET        0x28
  34
  35/* DTS_CFGR1 register mask definitions */
  36#define HSREF_CLK_DIV_MASK      GENMASK(30, 24)
  37#define TS1_SMP_TIME_MASK       GENMASK(19, 16)
  38#define TS1_INTRIG_SEL_MASK     GENMASK(11, 8)
  39
  40/* DTS_T0VALR1 register mask definitions */
  41#define TS1_T0_MASK             GENMASK(17, 16)
  42#define TS1_FMT0_MASK           GENMASK(15, 0)
  43
  44/* DTS_RAMPVALR register mask definitions */
  45#define TS1_RAMP_COEFF_MASK     GENMASK(15, 0)
  46
  47/* DTS_ITR1 register mask definitions */
  48#define TS1_HITTHD_MASK         GENMASK(31, 16)
  49#define TS1_LITTHD_MASK         GENMASK(15, 0)
  50
  51/* DTS_DR register mask definitions */
  52#define TS1_MFREQ_MASK          GENMASK(15, 0)
  53
  54/* DTS_ITENR register mask definitions */
  55#define ITENR_MASK              (GENMASK(2, 0) | GENMASK(6, 4))
  56
  57/* DTS_ICIFR register mask definitions */
  58#define ICIFR_MASK              (GENMASK(2, 0) | GENMASK(6, 4))
  59
  60/* Less significant bit position definitions */
  61#define TS1_T0_POS              16
  62#define TS1_HITTHD_POS          16
  63#define TS1_LITTHD_POS          0
  64#define HSREF_CLK_DIV_POS       24
  65
  66/* DTS_CFGR1 bit definitions */
  67#define TS1_EN                  BIT(0)
  68#define TS1_START               BIT(4)
  69#define REFCLK_SEL              BIT(20)
  70#define REFCLK_LSE              REFCLK_SEL
  71#define Q_MEAS_OPT              BIT(21)
  72#define CALIBRATION_CONTROL     Q_MEAS_OPT
  73
  74/* DTS_SR bit definitions */
  75#define TS_RDY                  BIT(15)
  76/* Bit definitions below are common for DTS_SR, DTS_ITENR and DTS_CIFR */
  77#define HIGH_THRESHOLD          BIT(2)
  78#define LOW_THRESHOLD           BIT(1)
  79
  80/* Constants */
  81#define ADJUST                  100
  82#define ONE_MHZ                 1000000
  83#define POLL_TIMEOUT            5000
  84#define STARTUP_TIME            40
  85#define TS1_T0_VAL0             30000  /* 30 celsius */
  86#define TS1_T0_VAL1             130000 /* 130 celsius */
  87#define NO_HW_TRIG              0
  88#define SAMPLING_TIME           15
  89
  90struct stm_thermal_sensor {
  91        struct device *dev;
  92        struct thermal_zone_device *th_dev;
  93        enum thermal_device_mode mode;
  94        struct clk *clk;
  95        unsigned int low_temp_enabled;
  96        unsigned int high_temp_enabled;
  97        int irq;
  98        void __iomem *base;
  99        int t0, fmt0, ramp_coeff;
 100};
 101
 102static int stm_enable_irq(struct stm_thermal_sensor *sensor)
 103{
 104        u32 value;
 105
 106        dev_dbg(sensor->dev, "low:%d high:%d\n", sensor->low_temp_enabled,
 107                sensor->high_temp_enabled);
 108
 109        /* Disable IT generation for low and high thresholds */
 110        value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
 111        value &= ~(LOW_THRESHOLD | HIGH_THRESHOLD);
 112
 113        if (sensor->low_temp_enabled)
 114                value |= HIGH_THRESHOLD;
 115
 116        if (sensor->high_temp_enabled)
 117                value |= LOW_THRESHOLD;
 118
 119        /* Enable interrupts */
 120        writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
 121
 122        return 0;
 123}
 124
 125static irqreturn_t stm_thermal_irq_handler(int irq, void *sdata)
 126{
 127        struct stm_thermal_sensor *sensor = sdata;
 128
 129        dev_dbg(sensor->dev, "sr:%d\n",
 130                readl_relaxed(sensor->base + DTS_SR_OFFSET));
 131
 132        thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
 133
 134        stm_enable_irq(sensor);
 135
 136        /* Acknoledge all DTS irqs */
 137        writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
 138
 139        return IRQ_HANDLED;
 140}
 141
 142static int stm_sensor_power_on(struct stm_thermal_sensor *sensor)
 143{
 144        int ret;
 145        u32 value;
 146
 147        /* Enable sensor */
 148        value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
 149        value |= TS1_EN;
 150        writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
 151
 152        /*
 153         * The DTS block can be enabled by setting TSx_EN bit in
 154         * DTS_CFGRx register. It requires a startup time of
 155         * 40μs. Use 5 ms as arbitrary timeout.
 156         */
 157        ret = readl_poll_timeout(sensor->base + DTS_SR_OFFSET,
 158                                 value, (value & TS_RDY),
 159                                 STARTUP_TIME, POLL_TIMEOUT);
 160        if (ret)
 161                return ret;
 162
 163        /* Start continuous measuring */
 164        value = readl_relaxed(sensor->base +
 165                              DTS_CFGR1_OFFSET);
 166        value |= TS1_START;
 167        writel_relaxed(value, sensor->base +
 168                       DTS_CFGR1_OFFSET);
 169
 170        sensor->mode = THERMAL_DEVICE_ENABLED;
 171
 172        return 0;
 173}
 174
 175static int stm_sensor_power_off(struct stm_thermal_sensor *sensor)
 176{
 177        u32 value;
 178
 179        sensor->mode = THERMAL_DEVICE_DISABLED;
 180
 181        /* Stop measuring */
 182        value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
 183        value &= ~TS1_START;
 184        writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
 185
 186        /* Ensure stop is taken into account */
 187        usleep_range(STARTUP_TIME, POLL_TIMEOUT);
 188
 189        /* Disable sensor */
 190        value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
 191        value &= ~TS1_EN;
 192        writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
 193
 194        /* Ensure disable is taken into account */
 195        return readl_poll_timeout(sensor->base + DTS_SR_OFFSET, value,
 196                                  !(value & TS_RDY),
 197                                  STARTUP_TIME, POLL_TIMEOUT);
 198}
 199
 200static int stm_thermal_calibration(struct stm_thermal_sensor *sensor)
 201{
 202        u32 value, clk_freq;
 203        u32 prescaler;
 204
 205        /* Figure out prescaler value for PCLK during calibration */
 206        clk_freq = clk_get_rate(sensor->clk);
 207        if (!clk_freq)
 208                return -EINVAL;
 209
 210        prescaler = 0;
 211        clk_freq /= ONE_MHZ;
 212        if (clk_freq) {
 213                while (prescaler <= clk_freq)
 214                        prescaler++;
 215        }
 216
 217        value = readl_relaxed(sensor->base + DTS_CFGR1_OFFSET);
 218
 219        /* Clear prescaler */
 220        value &= ~HSREF_CLK_DIV_MASK;
 221
 222        /* Set prescaler. pclk_freq/prescaler < 1MHz */
 223        value |= (prescaler << HSREF_CLK_DIV_POS);
 224
 225        /* Select PCLK as reference clock */
 226        value &= ~REFCLK_SEL;
 227
 228        /* Set maximal sampling time for better precision */
 229        value |= TS1_SMP_TIME_MASK;
 230
 231        /* Measure with calibration */
 232        value &= ~CALIBRATION_CONTROL;
 233
 234        /* select trigger */
 235        value &= ~TS1_INTRIG_SEL_MASK;
 236        value |= NO_HW_TRIG;
 237
 238        writel_relaxed(value, sensor->base + DTS_CFGR1_OFFSET);
 239
 240        return 0;
 241}
 242
 243/* Fill in DTS structure with factory sensor values */
 244static int stm_thermal_read_factory_settings(struct stm_thermal_sensor *sensor)
 245{
 246        /* Retrieve engineering calibration temperature */
 247        sensor->t0 = readl_relaxed(sensor->base + DTS_T0VALR1_OFFSET) &
 248                                        TS1_T0_MASK;
 249        if (!sensor->t0)
 250                sensor->t0 = TS1_T0_VAL0;
 251        else
 252                sensor->t0 = TS1_T0_VAL1;
 253
 254        /* Retrieve fmt0 and put it on Hz */
 255        sensor->fmt0 = ADJUST * (readl_relaxed(sensor->base +
 256                                 DTS_T0VALR1_OFFSET) & TS1_FMT0_MASK);
 257
 258        /* Retrieve ramp coefficient */
 259        sensor->ramp_coeff = readl_relaxed(sensor->base + DTS_RAMPVALR_OFFSET) &
 260                                           TS1_RAMP_COEFF_MASK;
 261
 262        if (!sensor->fmt0 || !sensor->ramp_coeff) {
 263                dev_err(sensor->dev, "%s: wrong setting\n", __func__);
 264                return -EINVAL;
 265        }
 266
 267        dev_dbg(sensor->dev, "%s: T0 = %doC, FMT0 = %dHz, RAMP_COEFF = %dHz/oC",
 268                __func__, sensor->t0, sensor->fmt0, sensor->ramp_coeff);
 269
 270        return 0;
 271}
 272
 273static int stm_thermal_calculate_threshold(struct stm_thermal_sensor *sensor,
 274                                           int temp, u32 *th)
 275{
 276        int freqM;
 277
 278        /* Figure out the CLK_PTAT frequency for a given temperature */
 279        freqM = ((temp - sensor->t0) * sensor->ramp_coeff) / 1000 +
 280                sensor->fmt0;
 281
 282        /* Figure out the threshold sample number */
 283        *th = clk_get_rate(sensor->clk) * SAMPLING_TIME / freqM;
 284        if (!*th)
 285                return -EINVAL;
 286
 287        dev_dbg(sensor->dev, "freqM=%d Hz, threshold=0x%x", freqM, *th);
 288
 289        return 0;
 290}
 291
 292/* Disable temperature interrupt */
 293static int stm_disable_irq(struct stm_thermal_sensor *sensor)
 294{
 295        u32 value;
 296
 297        /* Disable IT generation */
 298        value = readl_relaxed(sensor->base + DTS_ITENR_OFFSET);
 299        value &= ~ITENR_MASK;
 300        writel_relaxed(value, sensor->base + DTS_ITENR_OFFSET);
 301
 302        return 0;
 303}
 304
 305static int stm_thermal_set_trips(void *data, int low, int high)
 306{
 307        struct stm_thermal_sensor *sensor = data;
 308        u32 itr1, th;
 309        int ret;
 310
 311        dev_dbg(sensor->dev, "set trips %d <--> %d\n", low, high);
 312
 313        /* Erase threshold content */
 314        itr1 = readl_relaxed(sensor->base + DTS_ITR1_OFFSET);
 315        itr1 &= ~(TS1_LITTHD_MASK | TS1_HITTHD_MASK);
 316
 317        /*
 318         * Disable low-temp if "low" is too small. As per thermal framework
 319         * API, we use -INT_MAX rather than INT_MIN.
 320         */
 321
 322        if (low > -INT_MAX) {
 323                sensor->low_temp_enabled = 1;
 324                /* add 0.5 of hysteresis due to measurement error */
 325                ret = stm_thermal_calculate_threshold(sensor, low - 500, &th);
 326                if (ret)
 327                        return ret;
 328
 329                itr1 |= (TS1_HITTHD_MASK  & (th << TS1_HITTHD_POS));
 330        } else {
 331                sensor->low_temp_enabled = 0;
 332        }
 333
 334        /* Disable high-temp if "high" is too big. */
 335        if (high < INT_MAX) {
 336                sensor->high_temp_enabled = 1;
 337                ret = stm_thermal_calculate_threshold(sensor, high, &th);
 338                if (ret)
 339                        return ret;
 340
 341                itr1 |= (TS1_LITTHD_MASK  & (th << TS1_LITTHD_POS));
 342        } else {
 343                sensor->high_temp_enabled = 0;
 344        }
 345
 346        /* Write new threshod values*/
 347        writel_relaxed(itr1, sensor->base + DTS_ITR1_OFFSET);
 348
 349        return 0;
 350}
 351
 352/* Callback to get temperature from HW */
 353static int stm_thermal_get_temp(void *data, int *temp)
 354{
 355        struct stm_thermal_sensor *sensor = data;
 356        u32 periods;
 357        int freqM, ret;
 358
 359        if (sensor->mode != THERMAL_DEVICE_ENABLED)
 360                return -EAGAIN;
 361
 362        /* Retrieve the number of periods sampled */
 363        ret = readl_relaxed_poll_timeout(sensor->base + DTS_DR_OFFSET, periods,
 364                                         (periods & TS1_MFREQ_MASK),
 365                                         STARTUP_TIME, POLL_TIMEOUT);
 366        if (ret)
 367                return ret;
 368
 369        /* Figure out the CLK_PTAT frequency */
 370        freqM = (clk_get_rate(sensor->clk) * SAMPLING_TIME) / periods;
 371        if (!freqM)
 372                return -EINVAL;
 373
 374        /* Figure out the temperature in mili celsius */
 375        *temp = (freqM - sensor->fmt0) * 1000 / sensor->ramp_coeff + sensor->t0;
 376
 377        return 0;
 378}
 379
 380/* Registers DTS irq to be visible by GIC */
 381static int stm_register_irq(struct stm_thermal_sensor *sensor)
 382{
 383        struct device *dev = sensor->dev;
 384        struct platform_device *pdev = to_platform_device(dev);
 385        int ret;
 386
 387        sensor->irq = platform_get_irq(pdev, 0);
 388        if (sensor->irq < 0)
 389                return sensor->irq;
 390
 391        ret = devm_request_threaded_irq(dev, sensor->irq,
 392                                        NULL,
 393                                        stm_thermal_irq_handler,
 394                                        IRQF_ONESHOT,
 395                                        dev->driver->name, sensor);
 396        if (ret) {
 397                dev_err(dev, "%s: Failed to register IRQ %d\n", __func__,
 398                        sensor->irq);
 399                return ret;
 400        }
 401
 402        dev_dbg(dev, "%s: thermal IRQ registered", __func__);
 403
 404        return 0;
 405}
 406
 407static int stm_thermal_sensor_off(struct stm_thermal_sensor *sensor)
 408{
 409        int ret;
 410
 411        stm_disable_irq(sensor);
 412
 413        ret = stm_sensor_power_off(sensor);
 414        if (ret)
 415                return ret;
 416
 417        clk_disable_unprepare(sensor->clk);
 418
 419        return 0;
 420}
 421
 422static int stm_thermal_prepare(struct stm_thermal_sensor *sensor)
 423{
 424        int ret;
 425
 426        ret = clk_prepare_enable(sensor->clk);
 427        if (ret)
 428                return ret;
 429
 430        ret = stm_thermal_read_factory_settings(sensor);
 431        if (ret)
 432                goto thermal_unprepare;
 433
 434        ret = stm_thermal_calibration(sensor);
 435        if (ret)
 436                goto thermal_unprepare;
 437
 438        return 0;
 439
 440thermal_unprepare:
 441        clk_disable_unprepare(sensor->clk);
 442
 443        return ret;
 444}
 445
 446#ifdef CONFIG_PM_SLEEP
 447static int stm_thermal_suspend(struct device *dev)
 448{
 449        struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
 450
 451        return stm_thermal_sensor_off(sensor);
 452}
 453
 454static int stm_thermal_resume(struct device *dev)
 455{
 456        int ret;
 457        struct stm_thermal_sensor *sensor = dev_get_drvdata(dev);
 458
 459        ret = stm_thermal_prepare(sensor);
 460        if (ret)
 461                return ret;
 462
 463        ret = stm_sensor_power_on(sensor);
 464        if (ret)
 465                return ret;
 466
 467        thermal_zone_device_update(sensor->th_dev, THERMAL_EVENT_UNSPECIFIED);
 468        stm_enable_irq(sensor);
 469
 470        return 0;
 471}
 472#endif /* CONFIG_PM_SLEEP */
 473
 474static SIMPLE_DEV_PM_OPS(stm_thermal_pm_ops,
 475                         stm_thermal_suspend, stm_thermal_resume);
 476
 477static const struct thermal_zone_of_device_ops stm_tz_ops = {
 478        .get_temp       = stm_thermal_get_temp,
 479        .set_trips      = stm_thermal_set_trips,
 480};
 481
 482static const struct of_device_id stm_thermal_of_match[] = {
 483                { .compatible = "st,stm32-thermal"},
 484        { /* sentinel */ }
 485};
 486MODULE_DEVICE_TABLE(of, stm_thermal_of_match);
 487
 488static int stm_thermal_probe(struct platform_device *pdev)
 489{
 490        struct stm_thermal_sensor *sensor;
 491        struct resource *res;
 492        void __iomem *base;
 493        int ret;
 494
 495        if (!pdev->dev.of_node) {
 496                dev_err(&pdev->dev, "%s: device tree node not found\n",
 497                        __func__);
 498                return -EINVAL;
 499        }
 500
 501        sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
 502        if (!sensor)
 503                return -ENOMEM;
 504
 505        platform_set_drvdata(pdev, sensor);
 506
 507        sensor->dev = &pdev->dev;
 508
 509        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 510        base = devm_ioremap_resource(&pdev->dev, res);
 511        if (IS_ERR(base))
 512                return PTR_ERR(base);
 513
 514        /* Populate sensor */
 515        sensor->base = base;
 516
 517        sensor->clk = devm_clk_get(&pdev->dev, "pclk");
 518        if (IS_ERR(sensor->clk)) {
 519                dev_err(&pdev->dev, "%s: failed to fetch PCLK clock\n",
 520                        __func__);
 521                return PTR_ERR(sensor->clk);
 522        }
 523
 524        stm_disable_irq(sensor);
 525
 526        /* Clear irq flags */
 527        writel_relaxed(ICIFR_MASK, sensor->base + DTS_ICIFR_OFFSET);
 528
 529        /* Configure and enable HW sensor */
 530        ret = stm_thermal_prepare(sensor);
 531        if (ret) {
 532                dev_err(&pdev->dev, "Error prepare sensor: %d\n", ret);
 533                return ret;
 534        }
 535
 536        ret = stm_sensor_power_on(sensor);
 537        if (ret) {
 538                dev_err(&pdev->dev, "Error power on sensor: %d\n", ret);
 539                return ret;
 540        }
 541
 542        sensor->th_dev = devm_thermal_zone_of_sensor_register(&pdev->dev, 0,
 543                                                              sensor,
 544                                                              &stm_tz_ops);
 545
 546        if (IS_ERR(sensor->th_dev)) {
 547                dev_err(&pdev->dev, "%s: thermal zone sensor registering KO\n",
 548                        __func__);
 549                ret = PTR_ERR(sensor->th_dev);
 550                return ret;
 551        }
 552
 553        /* Register IRQ into GIC */
 554        ret = stm_register_irq(sensor);
 555        if (ret)
 556                goto err_tz;
 557
 558        stm_enable_irq(sensor);
 559
 560        /*
 561         * Thermal_zone doesn't enable hwmon as default,
 562         * enable it here
 563         */
 564        sensor->th_dev->tzp->no_hwmon = false;
 565        ret = thermal_add_hwmon_sysfs(sensor->th_dev);
 566        if (ret)
 567                goto err_tz;
 568
 569        dev_info(&pdev->dev, "%s: Driver initialized successfully\n",
 570                 __func__);
 571
 572        return 0;
 573
 574err_tz:
 575        thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
 576        return ret;
 577}
 578
 579static int stm_thermal_remove(struct platform_device *pdev)
 580{
 581        struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev);
 582
 583        stm_thermal_sensor_off(sensor);
 584        thermal_remove_hwmon_sysfs(sensor->th_dev);
 585        thermal_zone_of_sensor_unregister(&pdev->dev, sensor->th_dev);
 586
 587        return 0;
 588}
 589
 590static struct platform_driver stm_thermal_driver = {
 591        .driver = {
 592                .name   = "stm_thermal",
 593                .pm     = &stm_thermal_pm_ops,
 594                .of_match_table = stm_thermal_of_match,
 595        },
 596        .probe          = stm_thermal_probe,
 597        .remove         = stm_thermal_remove,
 598};
 599module_platform_driver(stm_thermal_driver);
 600
 601MODULE_DESCRIPTION("STMicroelectronics STM32 Thermal Sensor Driver");
 602MODULE_AUTHOR("David Hernandez Sanchez <david.hernandezsanchez@st.com>");
 603MODULE_LICENSE("GPL v2");
 604MODULE_ALIAS("platform:stm_thermal");
 605