root/drivers/thermal/qoriq_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tmu_write
  2. tmu_read
  3. tmu_get_temp
  4. qoriq_tmu_register_tmu_zone
  5. qoriq_tmu_calibration
  6. qoriq_tmu_init_device
  7. qoriq_tmu_probe
  8. qoriq_tmu_remove
  9. qoriq_tmu_suspend
  10. qoriq_tmu_resume

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Copyright 2016 Freescale Semiconductor, Inc.
   4 
   5 #include <linux/clk.h>
   6 #include <linux/module.h>
   7 #include <linux/platform_device.h>
   8 #include <linux/err.h>
   9 #include <linux/io.h>
  10 #include <linux/of.h>
  11 #include <linux/of_address.h>
  12 #include <linux/thermal.h>
  13 
  14 #include "thermal_core.h"
  15 
  16 #define SITES_MAX       16
  17 
  18 /*
  19  * QorIQ TMU Registers
  20  */
  21 struct qoriq_tmu_site_regs {
  22         u32 tritsr;             /* Immediate Temperature Site Register */
  23         u32 tratsr;             /* Average Temperature Site Register */
  24         u8 res0[0x8];
  25 };
  26 
  27 struct qoriq_tmu_regs {
  28         u32 tmr;                /* Mode Register */
  29 #define TMR_DISABLE     0x0
  30 #define TMR_ME          0x80000000
  31 #define TMR_ALPF        0x0c000000
  32         u32 tsr;                /* Status Register */
  33         u32 tmtmir;             /* Temperature measurement interval Register */
  34 #define TMTMIR_DEFAULT  0x0000000f
  35         u8 res0[0x14];
  36         u32 tier;               /* Interrupt Enable Register */
  37 #define TIER_DISABLE    0x0
  38         u32 tidr;               /* Interrupt Detect Register */
  39         u32 tiscr;              /* Interrupt Site Capture Register */
  40         u32 ticscr;             /* Interrupt Critical Site Capture Register */
  41         u8 res1[0x10];
  42         u32 tmhtcrh;            /* High Temperature Capture Register */
  43         u32 tmhtcrl;            /* Low Temperature Capture Register */
  44         u8 res2[0x8];
  45         u32 tmhtitr;            /* High Temperature Immediate Threshold */
  46         u32 tmhtatr;            /* High Temperature Average Threshold */
  47         u32 tmhtactr;   /* High Temperature Average Crit Threshold */
  48         u8 res3[0x24];
  49         u32 ttcfgr;             /* Temperature Configuration Register */
  50         u32 tscfgr;             /* Sensor Configuration Register */
  51         u8 res4[0x78];
  52         struct qoriq_tmu_site_regs site[SITES_MAX];
  53         u8 res5[0x9f8];
  54         u32 ipbrr0;             /* IP Block Revision Register 0 */
  55         u32 ipbrr1;             /* IP Block Revision Register 1 */
  56         u8 res6[0x310];
  57         u32 ttr0cr;             /* Temperature Range 0 Control Register */
  58         u32 ttr1cr;             /* Temperature Range 1 Control Register */
  59         u32 ttr2cr;             /* Temperature Range 2 Control Register */
  60         u32 ttr3cr;             /* Temperature Range 3 Control Register */
  61 };
  62 
  63 struct qoriq_tmu_data;
  64 
  65 /*
  66  * Thermal zone data
  67  */
  68 struct qoriq_sensor {
  69         struct thermal_zone_device      *tzd;
  70         struct qoriq_tmu_data           *qdata;
  71         int                             id;
  72 };
  73 
  74 struct qoriq_tmu_data {
  75         struct qoriq_tmu_regs __iomem *regs;
  76         struct clk *clk;
  77         bool little_endian;
  78         struct qoriq_sensor     *sensor[SITES_MAX];
  79 };
  80 
  81 static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
  82 {
  83         if (p->little_endian)
  84                 iowrite32(val, addr);
  85         else
  86                 iowrite32be(val, addr);
  87 }
  88 
  89 static u32 tmu_read(struct qoriq_tmu_data *p, void __iomem *addr)
  90 {
  91         if (p->little_endian)
  92                 return ioread32(addr);
  93         else
  94                 return ioread32be(addr);
  95 }
  96 
  97 static int tmu_get_temp(void *p, int *temp)
  98 {
  99         struct qoriq_sensor *qsensor = p;
 100         struct qoriq_tmu_data *qdata = qsensor->qdata;
 101         u32 val;
 102 
 103         val = tmu_read(qdata, &qdata->regs->site[qsensor->id].tritsr);
 104         *temp = (val & 0xff) * 1000;
 105 
 106         return 0;
 107 }
 108 
 109 static const struct thermal_zone_of_device_ops tmu_tz_ops = {
 110         .get_temp = tmu_get_temp,
 111 };
 112 
 113 static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
 114 {
 115         struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev);
 116         int id, sites = 0;
 117 
 118         for (id = 0; id < SITES_MAX; id++) {
 119                 qdata->sensor[id] = devm_kzalloc(&pdev->dev,
 120                                 sizeof(struct qoriq_sensor), GFP_KERNEL);
 121                 if (!qdata->sensor[id])
 122                         return -ENOMEM;
 123 
 124                 qdata->sensor[id]->id = id;
 125                 qdata->sensor[id]->qdata = qdata;
 126                 qdata->sensor[id]->tzd = devm_thermal_zone_of_sensor_register(
 127                                 &pdev->dev, id, qdata->sensor[id], &tmu_tz_ops);
 128                 if (IS_ERR(qdata->sensor[id]->tzd)) {
 129                         if (PTR_ERR(qdata->sensor[id]->tzd) == -ENODEV)
 130                                 continue;
 131                         else
 132                                 return PTR_ERR(qdata->sensor[id]->tzd);
 133                 }
 134 
 135                 sites |= 0x1 << (15 - id);
 136         }
 137 
 138         /* Enable monitoring */
 139         if (sites != 0)
 140                 tmu_write(qdata, sites | TMR_ME | TMR_ALPF, &qdata->regs->tmr);
 141 
 142         return 0;
 143 }
 144 
 145 static int qoriq_tmu_calibration(struct platform_device *pdev)
 146 {
 147         int i, val, len;
 148         u32 range[4];
 149         const u32 *calibration;
 150         struct device_node *np = pdev->dev.of_node;
 151         struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
 152 
 153         if (of_property_read_u32_array(np, "fsl,tmu-range", range, 4)) {
 154                 dev_err(&pdev->dev, "missing calibration range.\n");
 155                 return -ENODEV;
 156         }
 157 
 158         /* Init temperature range registers */
 159         tmu_write(data, range[0], &data->regs->ttr0cr);
 160         tmu_write(data, range[1], &data->regs->ttr1cr);
 161         tmu_write(data, range[2], &data->regs->ttr2cr);
 162         tmu_write(data, range[3], &data->regs->ttr3cr);
 163 
 164         calibration = of_get_property(np, "fsl,tmu-calibration", &len);
 165         if (calibration == NULL || len % 8) {
 166                 dev_err(&pdev->dev, "invalid calibration data.\n");
 167                 return -ENODEV;
 168         }
 169 
 170         for (i = 0; i < len; i += 8, calibration += 2) {
 171                 val = of_read_number(calibration, 1);
 172                 tmu_write(data, val, &data->regs->ttcfgr);
 173                 val = of_read_number(calibration + 1, 1);
 174                 tmu_write(data, val, &data->regs->tscfgr);
 175         }
 176 
 177         return 0;
 178 }
 179 
 180 static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
 181 {
 182         /* Disable interrupt, using polling instead */
 183         tmu_write(data, TIER_DISABLE, &data->regs->tier);
 184 
 185         /* Set update_interval */
 186         tmu_write(data, TMTMIR_DEFAULT, &data->regs->tmtmir);
 187 
 188         /* Disable monitoring */
 189         tmu_write(data, TMR_DISABLE, &data->regs->tmr);
 190 }
 191 
 192 static int qoriq_tmu_probe(struct platform_device *pdev)
 193 {
 194         int ret;
 195         struct qoriq_tmu_data *data;
 196         struct device_node *np = pdev->dev.of_node;
 197 
 198         data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data),
 199                             GFP_KERNEL);
 200         if (!data)
 201                 return -ENOMEM;
 202 
 203         platform_set_drvdata(pdev, data);
 204 
 205         data->little_endian = of_property_read_bool(np, "little-endian");
 206 
 207         data->regs = devm_platform_ioremap_resource(pdev, 0);
 208         if (IS_ERR(data->regs)) {
 209                 dev_err(&pdev->dev, "Failed to get memory region\n");
 210                 return PTR_ERR(data->regs);
 211         }
 212 
 213         data->clk = devm_clk_get_optional(&pdev->dev, NULL);
 214         if (IS_ERR(data->clk))
 215                 return PTR_ERR(data->clk);
 216 
 217         ret = clk_prepare_enable(data->clk);
 218         if (ret) {
 219                 dev_err(&pdev->dev, "Failed to enable clock\n");
 220                 return ret;
 221         }
 222 
 223         qoriq_tmu_init_device(data);    /* TMU initialization */
 224 
 225         ret = qoriq_tmu_calibration(pdev);      /* TMU calibration */
 226         if (ret < 0)
 227                 goto err;
 228 
 229         ret = qoriq_tmu_register_tmu_zone(pdev);
 230         if (ret < 0) {
 231                 dev_err(&pdev->dev, "Failed to register sensors\n");
 232                 ret = -ENODEV;
 233                 goto err;
 234         }
 235 
 236         return 0;
 237 
 238 err:
 239         clk_disable_unprepare(data->clk);
 240         platform_set_drvdata(pdev, NULL);
 241 
 242         return ret;
 243 }
 244 
 245 static int qoriq_tmu_remove(struct platform_device *pdev)
 246 {
 247         struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
 248 
 249         /* Disable monitoring */
 250         tmu_write(data, TMR_DISABLE, &data->regs->tmr);
 251 
 252         clk_disable_unprepare(data->clk);
 253 
 254         platform_set_drvdata(pdev, NULL);
 255 
 256         return 0;
 257 }
 258 
 259 static int __maybe_unused qoriq_tmu_suspend(struct device *dev)
 260 {
 261         u32 tmr;
 262         struct qoriq_tmu_data *data = dev_get_drvdata(dev);
 263 
 264         /* Disable monitoring */
 265         tmr = tmu_read(data, &data->regs->tmr);
 266         tmr &= ~TMR_ME;
 267         tmu_write(data, tmr, &data->regs->tmr);
 268 
 269         clk_disable_unprepare(data->clk);
 270 
 271         return 0;
 272 }
 273 
 274 static int __maybe_unused qoriq_tmu_resume(struct device *dev)
 275 {
 276         u32 tmr;
 277         int ret;
 278         struct qoriq_tmu_data *data = dev_get_drvdata(dev);
 279 
 280         ret = clk_prepare_enable(data->clk);
 281         if (ret)
 282                 return ret;
 283 
 284         /* Enable monitoring */
 285         tmr = tmu_read(data, &data->regs->tmr);
 286         tmr |= TMR_ME;
 287         tmu_write(data, tmr, &data->regs->tmr);
 288 
 289         return 0;
 290 }
 291 
 292 static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
 293                          qoriq_tmu_suspend, qoriq_tmu_resume);
 294 
 295 static const struct of_device_id qoriq_tmu_match[] = {
 296         { .compatible = "fsl,qoriq-tmu", },
 297         { .compatible = "fsl,imx8mq-tmu", },
 298         {},
 299 };
 300 MODULE_DEVICE_TABLE(of, qoriq_tmu_match);
 301 
 302 static struct platform_driver qoriq_tmu = {
 303         .driver = {
 304                 .name           = "qoriq_thermal",
 305                 .pm             = &qoriq_tmu_pm_ops,
 306                 .of_match_table = qoriq_tmu_match,
 307         },
 308         .probe  = qoriq_tmu_probe,
 309         .remove = qoriq_tmu_remove,
 310 };
 311 module_platform_driver(qoriq_tmu);
 312 
 313 MODULE_AUTHOR("Jia Hongtao <hongtao.jia@nxp.com>");
 314 MODULE_DESCRIPTION("QorIQ Thermal Monitoring Unit driver");
 315 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */