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