1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas RZ/G2L TSU Thermal Sensor Driver 4 * 5 * Copyright (C) 2021 Renesas Electronics Corporation 6 */ 7 #include <linux/delay.h> 8 #include <linux/err.h> 9 #include <linux/io.h> 10 #include <linux/iopoll.h> 11 #include <linux/math.h> 12 #include <linux/module.h> 13 #include <linux/of_device.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/reset.h> 17 #include <linux/thermal.h> 18 #include <linux/units.h> 19 20 #include "thermal_hwmon.h" 21 22 #define CTEMP_MASK 0xFFF 23 24 /* default calibration values, if FUSE values are missing */ 25 #define SW_CALIB0_VAL 3148 26 #define SW_CALIB1_VAL 503 27 28 /* Register offsets */ 29 #define TSU_SM 0x00 30 #define TSU_ST 0x04 31 #define TSU_SAD 0x0C 32 #define TSU_SS 0x10 33 34 #define OTPTSUTRIM_REG(n) (0x18 + ((n) * 0x4)) 35 #define OTPTSUTRIM_EN_MASK BIT(31) 36 #define OTPTSUTRIM_MASK GENMASK(11, 0) 37 38 /* Sensor Mode Register(TSU_SM) */ 39 #define TSU_SM_EN_TS BIT(0) 40 #define TSU_SM_ADC_EN_TS BIT(1) 41 #define TSU_SM_NORMAL_MODE (TSU_SM_EN_TS | TSU_SM_ADC_EN_TS) 42 43 /* TSU_ST bits */ 44 #define TSU_ST_START BIT(0) 45 46 #define TSU_SS_CONV_RUNNING BIT(0) 47 48 #define TS_CODE_AVE_SCALE(x) ((x) * 1000000) 49 #define MCELSIUS(temp) ((temp) * MILLIDEGREE_PER_DEGREE) 50 #define TS_CODE_CAP_TIMES 8 /* Total number of ADC data samples */ 51 52 #define RZG2L_THERMAL_GRAN 500 /* milli Celsius */ 53 #define RZG2L_TSU_SS_TIMEOUT_US 1000 54 55 #define CURVATURE_CORRECTION_CONST 13 56 57 struct rzg2l_thermal_priv { 58 struct device *dev; 59 void __iomem *base; 60 struct thermal_zone_device *zone; 61 struct reset_control *rstc; 62 u32 calib0, calib1; 63 }; 64 65 static inline u32 rzg2l_thermal_read(struct rzg2l_thermal_priv *priv, u32 reg) 66 { 67 return ioread32(priv->base + reg); 68 } 69 70 static inline void rzg2l_thermal_write(struct rzg2l_thermal_priv *priv, u32 reg, 71 u32 data) 72 { 73 iowrite32(data, priv->base + reg); 74 } 75 76 static int rzg2l_thermal_get_temp(struct thermal_zone_device *tz, int *temp) 77 { 78 struct rzg2l_thermal_priv *priv = thermal_zone_device_priv(tz); 79 u32 result = 0, dsensor, ts_code_ave; 80 int val, i; 81 82 for (i = 0; i < TS_CODE_CAP_TIMES ; i++) { 83 /* 84 * TSU repeats measurement at 20 microseconds intervals and 85 * automatically updates the results of measurement. As per 86 * the HW manual for measuring temperature we need to read 8 87 * values consecutively and then take the average. 88 * ts_code_ave = (ts_code[0] + ⋯ + ts_code[7]) / 8 89 */ 90 result += rzg2l_thermal_read(priv, TSU_SAD) & CTEMP_MASK; 91 usleep_range(20, 30); 92 } 93 94 ts_code_ave = result / TS_CODE_CAP_TIMES; 95 96 /* 97 * Calculate actual sensor value by applying curvature correction formula 98 * dsensor = ts_code_ave / (1 + ts_code_ave * 0.000013). Here we are doing 99 * integer calculation by scaling all the values by 1000000. 100 */ 101 dsensor = TS_CODE_AVE_SCALE(ts_code_ave) / 102 (TS_CODE_AVE_SCALE(1) + (ts_code_ave * CURVATURE_CORRECTION_CONST)); 103 104 /* 105 * The temperature Tj is calculated by the formula 106 * Tj = (dsensor − calib1) * 165/ (calib0 − calib1) − 40 107 * where calib0 and calib1 are the calibration values. 108 */ 109 val = ((dsensor - priv->calib1) * (MCELSIUS(165) / 110 (priv->calib0 - priv->calib1))) - MCELSIUS(40); 111 112 *temp = roundup(val, RZG2L_THERMAL_GRAN); 113 114 return 0; 115 } 116 117 static const struct thermal_zone_device_ops rzg2l_tz_of_ops = { 118 .get_temp = rzg2l_thermal_get_temp, 119 }; 120 121 static int rzg2l_thermal_init(struct rzg2l_thermal_priv *priv) 122 { 123 u32 reg_val; 124 125 rzg2l_thermal_write(priv, TSU_SM, TSU_SM_NORMAL_MODE); 126 rzg2l_thermal_write(priv, TSU_ST, 0); 127 128 /* 129 * Before setting the START bit, TSU should be in normal operating 130 * mode. As per the HW manual, it will take 60 µs to place the TSU 131 * into normal operating mode. 132 */ 133 usleep_range(60, 80); 134 135 reg_val = rzg2l_thermal_read(priv, TSU_ST); 136 reg_val |= TSU_ST_START; 137 rzg2l_thermal_write(priv, TSU_ST, reg_val); 138 139 return readl_poll_timeout(priv->base + TSU_SS, reg_val, 140 reg_val == TSU_SS_CONV_RUNNING, 50, 141 RZG2L_TSU_SS_TIMEOUT_US); 142 } 143 144 static void rzg2l_thermal_reset_assert_pm_disable_put(struct platform_device *pdev) 145 { 146 struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev); 147 148 pm_runtime_put(&pdev->dev); 149 pm_runtime_disable(&pdev->dev); 150 reset_control_assert(priv->rstc); 151 } 152 153 static int rzg2l_thermal_remove(struct platform_device *pdev) 154 { 155 struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev); 156 157 thermal_remove_hwmon_sysfs(priv->zone); 158 rzg2l_thermal_reset_assert_pm_disable_put(pdev); 159 160 return 0; 161 } 162 163 static int rzg2l_thermal_probe(struct platform_device *pdev) 164 { 165 struct thermal_zone_device *zone; 166 struct rzg2l_thermal_priv *priv; 167 struct device *dev = &pdev->dev; 168 int ret; 169 170 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 171 if (!priv) 172 return -ENOMEM; 173 174 priv->base = devm_platform_ioremap_resource(pdev, 0); 175 if (IS_ERR(priv->base)) 176 return PTR_ERR(priv->base); 177 178 priv->dev = dev; 179 priv->rstc = devm_reset_control_get_exclusive(dev, NULL); 180 if (IS_ERR(priv->rstc)) 181 return dev_err_probe(dev, PTR_ERR(priv->rstc), 182 "failed to get cpg reset"); 183 184 ret = reset_control_deassert(priv->rstc); 185 if (ret) 186 return dev_err_probe(dev, ret, "failed to deassert"); 187 188 pm_runtime_enable(dev); 189 pm_runtime_get_sync(dev); 190 191 priv->calib0 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0)); 192 if (priv->calib0 & OTPTSUTRIM_EN_MASK) 193 priv->calib0 &= OTPTSUTRIM_MASK; 194 else 195 priv->calib0 = SW_CALIB0_VAL; 196 197 priv->calib1 = rzg2l_thermal_read(priv, OTPTSUTRIM_REG(1)); 198 if (priv->calib1 & OTPTSUTRIM_EN_MASK) 199 priv->calib1 &= OTPTSUTRIM_MASK; 200 else 201 priv->calib1 = SW_CALIB1_VAL; 202 203 platform_set_drvdata(pdev, priv); 204 ret = rzg2l_thermal_init(priv); 205 if (ret) { 206 dev_err(dev, "Failed to start TSU"); 207 goto err; 208 } 209 210 zone = devm_thermal_of_zone_register(dev, 0, priv, 211 &rzg2l_tz_of_ops); 212 if (IS_ERR(zone)) { 213 dev_err(dev, "Can't register thermal zone"); 214 ret = PTR_ERR(zone); 215 goto err; 216 } 217 218 priv->zone = zone; 219 ret = thermal_add_hwmon_sysfs(priv->zone); 220 if (ret) 221 goto err; 222 223 dev_dbg(dev, "TSU probed with %s calibration values", 224 rzg2l_thermal_read(priv, OTPTSUTRIM_REG(0)) ? "hw" : "sw"); 225 226 return 0; 227 228 err: 229 rzg2l_thermal_reset_assert_pm_disable_put(pdev); 230 return ret; 231 } 232 233 static const struct of_device_id rzg2l_thermal_dt_ids[] = { 234 { .compatible = "renesas,rzg2l-tsu", }, 235 { /* sentinel */ } 236 }; 237 MODULE_DEVICE_TABLE(of, rzg2l_thermal_dt_ids); 238 239 static struct platform_driver rzg2l_thermal_driver = { 240 .driver = { 241 .name = "rzg2l_thermal", 242 .of_match_table = rzg2l_thermal_dt_ids, 243 }, 244 .probe = rzg2l_thermal_probe, 245 .remove = rzg2l_thermal_remove, 246 }; 247 module_platform_driver(rzg2l_thermal_driver); 248 249 MODULE_DESCRIPTION("Renesas RZ/G2L TSU Thermal Sensor Driver"); 250 MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>"); 251 MODULE_LICENSE("GPL v2"); 252