linux/drivers/thermal/qoriq_thermal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Copyright 2016 Freescale Semiconductor, Inc.
   4
   5#include <linux/clk.h>
   6#include <linux/err.h>
   7#include <linux/io.h>
   8#include <linux/module.h>
   9#include <linux/of.h>
  10#include <linux/platform_device.h>
  11#include <linux/regmap.h>
  12#include <linux/sizes.h>
  13#include <linux/thermal.h>
  14#include <linux/units.h>
  15
  16#include "thermal_core.h"
  17#include "thermal_hwmon.h"
  18
  19#define SITES_MAX               16
  20#define TMR_DISABLE             0x0
  21#define TMR_ME                  0x80000000
  22#define TMR_ALPF                0x0c000000
  23#define TMR_ALPF_V2             0x03000000
  24#define TMTMIR_DEFAULT  0x0000000f
  25#define TIER_DISABLE    0x0
  26#define TEUMR0_V2               0x51009c00
  27#define TMSARA_V2               0xe
  28#define TMU_VER1                0x1
  29#define TMU_VER2                0x2
  30
  31#define REGS_TMR        0x000   /* Mode Register */
  32#define TMR_DISABLE     0x0
  33#define TMR_ME          0x80000000
  34#define TMR_ALPF        0x0c000000
  35#define TMR_MSITE_ALL   GENMASK(15, 0)
  36
  37#define REGS_TMTMIR     0x008   /* Temperature measurement interval Register */
  38#define TMTMIR_DEFAULT  0x0000000f
  39
  40#define REGS_V2_TMSR    0x008   /* monitor site register */
  41
  42#define REGS_V2_TMTMIR  0x00c   /* Temperature measurement interval Register */
  43
  44#define REGS_TIER       0x020   /* Interrupt Enable Register */
  45#define TIER_DISABLE    0x0
  46
  47
  48#define REGS_TTCFGR     0x080   /* Temperature Configuration Register */
  49#define REGS_TSCFGR     0x084   /* Sensor Configuration Register */
  50
  51#define REGS_TRITSR(n)  (0x100 + 16 * (n)) /* Immediate Temperature
  52                                            * Site Register
  53                                            */
  54#define TRITSR_V        BIT(31)
  55#define REGS_V2_TMSAR(n)        (0x304 + 16 * (n))      /* TMU monitoring
  56                                                * site adjustment register
  57                                                */
  58#define REGS_TTRnCR(n)  (0xf10 + 4 * (n)) /* Temperature Range n
  59                                           * Control Register
  60                                           */
  61#define REGS_IPBRR(n)           (0xbf8 + 4 * (n)) /* IP Block Revision
  62                                                   * Register n
  63                                                   */
  64#define REGS_V2_TEUMR(n)        (0xf00 + 4 * (n))
  65
  66/*
  67 * Thermal zone data
  68 */
  69struct qoriq_sensor {
  70        int                             id;
  71};
  72
  73struct qoriq_tmu_data {
  74        int ver;
  75        struct regmap *regmap;
  76        struct clk *clk;
  77        struct qoriq_sensor     sensor[SITES_MAX];
  78};
  79
  80static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
  81{
  82        return container_of(s, struct qoriq_tmu_data, sensor[s->id]);
  83}
  84
  85static int tmu_get_temp(void *p, int *temp)
  86{
  87        struct qoriq_sensor *qsensor = p;
  88        struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
  89        u32 val;
  90        /*
  91         * REGS_TRITSR(id) has the following layout:
  92         *
  93         * For TMU Rev1:
  94         * 31  ... 7 6 5 4 3 2 1 0
  95         *  V          TEMP
  96         *
  97         * Where V bit signifies if the measurement is ready and is
  98         * within sensor range. TEMP is an 8 bit value representing
  99         * temperature in Celsius.
 100
 101         * For TMU Rev2:
 102         * 31  ... 8 7 6 5 4 3 2 1 0
 103         *  V          TEMP
 104         *
 105         * Where V bit signifies if the measurement is ready and is
 106         * within sensor range. TEMP is an 9 bit value representing
 107         * temperature in KelVin.
 108         */
 109        if (regmap_read_poll_timeout(qdata->regmap,
 110                                     REGS_TRITSR(qsensor->id),
 111                                     val,
 112                                     val & TRITSR_V,
 113                                     USEC_PER_MSEC,
 114                                     10 * USEC_PER_MSEC))
 115                return -ENODATA;
 116
 117        if (qdata->ver == TMU_VER1)
 118                *temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
 119        else
 120                *temp = kelvin_to_millicelsius(val & GENMASK(8, 0));
 121
 122        return 0;
 123}
 124
 125static const struct thermal_zone_of_device_ops tmu_tz_ops = {
 126        .get_temp = tmu_get_temp,
 127};
 128
 129static int qoriq_tmu_register_tmu_zone(struct device *dev,
 130                                       struct qoriq_tmu_data *qdata)
 131{
 132        int id;
 133
 134        if (qdata->ver == TMU_VER1) {
 135                regmap_write(qdata->regmap, REGS_TMR,
 136                             TMR_MSITE_ALL | TMR_ME | TMR_ALPF);
 137        } else {
 138                regmap_write(qdata->regmap, REGS_V2_TMSR, TMR_MSITE_ALL);
 139                regmap_write(qdata->regmap, REGS_TMR, TMR_ME | TMR_ALPF_V2);
 140        }
 141
 142        for (id = 0; id < SITES_MAX; id++) {
 143                struct thermal_zone_device *tzd;
 144                struct qoriq_sensor *sensor = &qdata->sensor[id];
 145                int ret;
 146
 147                sensor->id = id;
 148
 149                tzd = devm_thermal_zone_of_sensor_register(dev, id,
 150                                                           sensor,
 151                                                           &tmu_tz_ops);
 152                ret = PTR_ERR_OR_ZERO(tzd);
 153                if (ret) {
 154                        if (ret == -ENODEV)
 155                                continue;
 156
 157                        regmap_write(qdata->regmap, REGS_TMR, TMR_DISABLE);
 158                        return ret;
 159                }
 160
 161                if (devm_thermal_add_hwmon_sysfs(tzd))
 162                        dev_warn(dev,
 163                                 "Failed to add hwmon sysfs attributes\n");
 164
 165        }
 166
 167        return 0;
 168}
 169
 170static int qoriq_tmu_calibration(struct device *dev,
 171                                 struct qoriq_tmu_data *data)
 172{
 173        int i, val, len;
 174        u32 range[4];
 175        const u32 *calibration;
 176        struct device_node *np = dev->of_node;
 177
 178        len = of_property_count_u32_elems(np, "fsl,tmu-range");
 179        if (len < 0 || len > 4) {
 180                dev_err(dev, "invalid range data.\n");
 181                return len;
 182        }
 183
 184        val = of_property_read_u32_array(np, "fsl,tmu-range", range, len);
 185        if (val != 0) {
 186                dev_err(dev, "failed to read range data.\n");
 187                return val;
 188        }
 189
 190        /* Init temperature range registers */
 191        for (i = 0; i < len; i++)
 192                regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
 193
 194        calibration = of_get_property(np, "fsl,tmu-calibration", &len);
 195        if (calibration == NULL || len % 8) {
 196                dev_err(dev, "invalid calibration data.\n");
 197                return -ENODEV;
 198        }
 199
 200        for (i = 0; i < len; i += 8, calibration += 2) {
 201                val = of_read_number(calibration, 1);
 202                regmap_write(data->regmap, REGS_TTCFGR, val);
 203                val = of_read_number(calibration + 1, 1);
 204                regmap_write(data->regmap, REGS_TSCFGR, val);
 205        }
 206
 207        return 0;
 208}
 209
 210static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
 211{
 212        int i;
 213
 214        /* Disable interrupt, using polling instead */
 215        regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
 216
 217        /* Set update_interval */
 218
 219        if (data->ver == TMU_VER1) {
 220                regmap_write(data->regmap, REGS_TMTMIR, TMTMIR_DEFAULT);
 221        } else {
 222                regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT);
 223                regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
 224                for (i = 0; i < SITES_MAX; i++)
 225                        regmap_write(data->regmap, REGS_V2_TMSAR(i), TMSARA_V2);
 226        }
 227
 228        /* Disable monitoring */
 229        regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
 230}
 231
 232static const struct regmap_range qoriq_yes_ranges[] = {
 233        regmap_reg_range(REGS_TMR, REGS_TSCFGR),
 234        regmap_reg_range(REGS_TTRnCR(0), REGS_TTRnCR(3)),
 235        regmap_reg_range(REGS_V2_TEUMR(0), REGS_V2_TEUMR(2)),
 236        regmap_reg_range(REGS_V2_TMSAR(0), REGS_V2_TMSAR(15)),
 237        regmap_reg_range(REGS_IPBRR(0), REGS_IPBRR(1)),
 238        /* Read only registers below */
 239        regmap_reg_range(REGS_TRITSR(0), REGS_TRITSR(15)),
 240};
 241
 242static const struct regmap_access_table qoriq_wr_table = {
 243        .yes_ranges     = qoriq_yes_ranges,
 244        .n_yes_ranges   = ARRAY_SIZE(qoriq_yes_ranges) - 1,
 245};
 246
 247static const struct regmap_access_table qoriq_rd_table = {
 248        .yes_ranges     = qoriq_yes_ranges,
 249        .n_yes_ranges   = ARRAY_SIZE(qoriq_yes_ranges),
 250};
 251
 252static void qoriq_tmu_action(void *p)
 253{
 254        struct qoriq_tmu_data *data = p;
 255
 256        regmap_write(data->regmap, REGS_TMR, TMR_DISABLE);
 257        clk_disable_unprepare(data->clk);
 258}
 259
 260static int qoriq_tmu_probe(struct platform_device *pdev)
 261{
 262        int ret;
 263        u32 ver;
 264        struct qoriq_tmu_data *data;
 265        struct device_node *np = pdev->dev.of_node;
 266        struct device *dev = &pdev->dev;
 267        const bool little_endian = of_property_read_bool(np, "little-endian");
 268        const enum regmap_endian format_endian =
 269                little_endian ? REGMAP_ENDIAN_LITTLE : REGMAP_ENDIAN_BIG;
 270        const struct regmap_config regmap_config = {
 271                .reg_bits               = 32,
 272                .val_bits               = 32,
 273                .reg_stride             = 4,
 274                .rd_table               = &qoriq_rd_table,
 275                .wr_table               = &qoriq_wr_table,
 276                .val_format_endian      = format_endian,
 277                .max_register           = SZ_4K,
 278        };
 279        void __iomem *base;
 280
 281        data = devm_kzalloc(dev, sizeof(struct qoriq_tmu_data),
 282                            GFP_KERNEL);
 283        if (!data)
 284                return -ENOMEM;
 285
 286        base = devm_platform_ioremap_resource(pdev, 0);
 287        ret = PTR_ERR_OR_ZERO(base);
 288        if (ret) {
 289                dev_err(dev, "Failed to get memory region\n");
 290                return ret;
 291        }
 292
 293        data->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
 294        ret = PTR_ERR_OR_ZERO(data->regmap);
 295        if (ret) {
 296                dev_err(dev, "Failed to init regmap (%d)\n", ret);
 297                return ret;
 298        }
 299
 300        data->clk = devm_clk_get_optional(dev, NULL);
 301        if (IS_ERR(data->clk))
 302                return PTR_ERR(data->clk);
 303
 304        ret = clk_prepare_enable(data->clk);
 305        if (ret) {
 306                dev_err(dev, "Failed to enable clock\n");
 307                return ret;
 308        }
 309
 310        ret = devm_add_action_or_reset(dev, qoriq_tmu_action, data);
 311        if (ret)
 312                return ret;
 313
 314        /* version register offset at: 0xbf8 on both v1 and v2 */
 315        ret = regmap_read(data->regmap, REGS_IPBRR(0), &ver);
 316        if (ret) {
 317                dev_err(&pdev->dev, "Failed to read IP block version\n");
 318                return ret;
 319        }
 320        data->ver = (ver >> 8) & 0xff;
 321
 322        qoriq_tmu_init_device(data);    /* TMU initialization */
 323
 324        ret = qoriq_tmu_calibration(dev, data); /* TMU calibration */
 325        if (ret < 0)
 326                return ret;
 327
 328        ret = qoriq_tmu_register_tmu_zone(dev, data);
 329        if (ret < 0) {
 330                dev_err(dev, "Failed to register sensors\n");
 331                return ret;
 332        }
 333
 334        platform_set_drvdata(pdev, data);
 335
 336        return 0;
 337}
 338
 339static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
 340{
 341        struct qoriq_tmu_data *data = dev_get_drvdata(dev);
 342        int ret;
 343
 344        ret = regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, 0);
 345        if (ret)
 346                return ret;
 347
 348        clk_disable_unprepare(data->clk);
 349
 350        return 0;
 351}
 352
 353static int __maybe_unused qoriq_tmu_resume(struct device *dev)
 354{
 355        int ret;
 356        struct qoriq_tmu_data *data = dev_get_drvdata(dev);
 357
 358        ret = clk_prepare_enable(data->clk);
 359        if (ret)
 360                return ret;
 361
 362        /* Enable monitoring */
 363        return regmap_update_bits(data->regmap, REGS_TMR, TMR_ME, TMR_ME);
 364}
 365
 366static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
 367                         qoriq_tmu_suspend, qoriq_tmu_resume);
 368
 369static const struct of_device_id qoriq_tmu_match[] = {
 370        { .compatible = "fsl,qoriq-tmu", },
 371        { .compatible = "fsl,imx8mq-tmu", },
 372        {},
 373};
 374MODULE_DEVICE_TABLE(of, qoriq_tmu_match);
 375
 376static struct platform_driver qoriq_tmu = {
 377        .driver = {
 378                .name           = "qoriq_thermal",
 379                .pm             = &qoriq_tmu_pm_ops,
 380                .of_match_table = qoriq_tmu_match,
 381        },
 382        .probe  = qoriq_tmu_probe,
 383};
 384module_platform_driver(qoriq_tmu);
 385
 386MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
 387MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
 388MODULE_LICENSE("GPL v2");
 389