1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Renesas RZ/G3S TSU Thermal Sensor Driver 4 * 5 * Copyright (C) 2024 Renesas Electronics Corporation 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/delay.h> 10 #include <linux/iio/consumer.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/reset.h> 16 #include <linux/thermal.h> 17 #include <linux/units.h> 18 19 #include "../thermal_hwmon.h" 20 21 #define TSU_SM 0x0 22 #define TSU_SM_EN BIT(0) 23 #define TSU_SM_OE BIT(1) 24 #define OTPTSUTRIM_REG(n) (0x18 + (n) * 0x4) 25 #define OTPTSUTRIM_EN_MASK BIT(31) 26 #define OTPTSUTRIM_MASK GENMASK(11, 0) 27 28 #define TSU_READ_STEPS 8 29 30 /* Default calibration values, if FUSE values are missing. */ 31 #define SW_CALIB0_VAL 1297 32 #define SW_CALIB1_VAL 751 33 34 #define MCELSIUS(temp) ((temp) * MILLIDEGREE_PER_DEGREE) 35 36 /** 37 * struct rzg3s_thermal_priv - RZ/G3S thermal private data structure 38 * @base: TSU base address 39 * @dev: device pointer 40 * @tz: thermal zone pointer 41 * @rstc: reset control 42 * @channel: IIO channel to read the TSU 43 * @mode: current device mode 44 * @calib0: calibration value 45 * @calib1: calibration value 46 */ 47 struct rzg3s_thermal_priv { 48 void __iomem *base; 49 struct device *dev; 50 struct thermal_zone_device *tz; 51 struct reset_control *rstc; 52 struct iio_channel *channel; 53 enum thermal_device_mode mode; 54 u16 calib0; 55 u16 calib1; 56 }; 57 58 static int rzg3s_thermal_get_temp(struct thermal_zone_device *tz, int *temp) 59 { 60 struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz); 61 int ts_code_ave = 0; 62 63 if (priv->mode != THERMAL_DEVICE_ENABLED) 64 return -EAGAIN; 65 66 for (u8 i = 0; i < TSU_READ_STEPS; i++) { 67 int ret, val; 68 69 ret = iio_read_channel_raw(priv->channel, &val); 70 if (ret < 0) 71 return ret; 72 73 ts_code_ave += val; 74 /* 75 * According to the HW manual (Rev.1.10, section 40.4.4 Procedure for Measuring 76 * the Temperature) we need to wait here at leat 3us. 77 */ 78 usleep_range(5, 10); 79 } 80 81 ts_code_ave = DIV_ROUND_CLOSEST(MCELSIUS(ts_code_ave), TSU_READ_STEPS); 82 83 /* 84 * According to the HW manual (Rev.1.10, section 40.4.4 Procedure for Measuring the 85 * Temperature) the computation formula is as follows: 86 * 87 * Tj = (ts_code_ave - priv->calib1) * 165 / (priv->calib0 - priv->calib1) - 40 88 * 89 * Convert everything to milli Celsius before applying the formula to avoid 90 * losing precision. 91 */ 92 93 *temp = div_s64((s64)(ts_code_ave - MCELSIUS(priv->calib1)) * MCELSIUS(165), 94 MCELSIUS(priv->calib0 - priv->calib1)) - MCELSIUS(40); 95 96 /* Report it in milli degrees Celsius and round it up to 0.5 degrees Celsius. */ 97 *temp = roundup(*temp, 500); 98 99 return 0; 100 } 101 102 static void rzg3s_thermal_set_mode(struct rzg3s_thermal_priv *priv, 103 enum thermal_device_mode mode) 104 { 105 struct device *dev = priv->dev; 106 int ret; 107 108 ret = pm_runtime_resume_and_get(dev); 109 if (ret) 110 return; 111 112 if (mode == THERMAL_DEVICE_DISABLED) { 113 writel(0, priv->base + TSU_SM); 114 } else { 115 writel(TSU_SM_EN, priv->base + TSU_SM); 116 /* 117 * According to the HW manual (Rev.1.10, section 40.4.1 Procedure for 118 * Starting the TSU) we need to wait here 30us or more. 119 */ 120 usleep_range(30, 40); 121 122 writel(TSU_SM_OE | TSU_SM_EN, priv->base + TSU_SM); 123 /* 124 * According to the HW manual (Rev.1.10, section 40.4.1 Procedure for 125 * Starting the TSU) we need to wait here 50us or more. 126 */ 127 usleep_range(50, 60); 128 } 129 130 pm_runtime_put_autosuspend(dev); 131 } 132 133 static int rzg3s_thermal_change_mode(struct thermal_zone_device *tz, 134 enum thermal_device_mode mode) 135 { 136 struct rzg3s_thermal_priv *priv = thermal_zone_device_priv(tz); 137 138 if (priv->mode == mode) 139 return 0; 140 141 rzg3s_thermal_set_mode(priv, mode); 142 priv->mode = mode; 143 144 return 0; 145 } 146 147 static const struct thermal_zone_device_ops rzg3s_tz_of_ops = { 148 .get_temp = rzg3s_thermal_get_temp, 149 .change_mode = rzg3s_thermal_change_mode, 150 }; 151 152 static int rzg3s_thermal_read_calib(struct rzg3s_thermal_priv *priv) 153 { 154 struct device *dev = priv->dev; 155 u32 val; 156 int ret; 157 158 ret = pm_runtime_resume_and_get(dev); 159 if (ret) 160 return ret; 161 162 val = readl(priv->base + OTPTSUTRIM_REG(0)); 163 if (val & OTPTSUTRIM_EN_MASK) 164 priv->calib0 = FIELD_GET(OTPTSUTRIM_MASK, val); 165 else 166 priv->calib0 = SW_CALIB0_VAL; 167 168 val = readl(priv->base + OTPTSUTRIM_REG(1)); 169 if (val & OTPTSUTRIM_EN_MASK) 170 priv->calib1 = FIELD_GET(OTPTSUTRIM_MASK, val); 171 else 172 priv->calib1 = SW_CALIB1_VAL; 173 174 pm_runtime_put_autosuspend(dev); 175 176 return 0; 177 } 178 179 static int rzg3s_thermal_probe(struct platform_device *pdev) 180 { 181 struct rzg3s_thermal_priv *priv; 182 struct device *dev = &pdev->dev; 183 int ret; 184 185 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 186 if (!priv) 187 return -ENOMEM; 188 189 priv->base = devm_platform_ioremap_resource(pdev, 0); 190 if (IS_ERR(priv->base)) 191 return PTR_ERR(priv->base); 192 193 priv->channel = devm_iio_channel_get(dev, "tsu"); 194 if (IS_ERR(priv->channel)) 195 return dev_err_probe(dev, PTR_ERR(priv->channel), "Failed to get IIO channel!\n"); 196 197 priv->rstc = devm_reset_control_get_exclusive_deasserted(dev, NULL); 198 if (IS_ERR(priv->rstc)) 199 return dev_err_probe(dev, PTR_ERR(priv->rstc), "Failed to get reset!\n"); 200 201 priv->dev = dev; 202 priv->mode = THERMAL_DEVICE_DISABLED; 203 platform_set_drvdata(pdev, priv); 204 205 pm_runtime_set_autosuspend_delay(dev, 300); 206 pm_runtime_use_autosuspend(dev); 207 ret = devm_pm_runtime_enable(dev); 208 if (ret) 209 return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n"); 210 211 ret = rzg3s_thermal_read_calib(priv); 212 if (ret) 213 return dev_err_probe(dev, ret, "Failed to read calibration data!\n"); 214 215 priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &rzg3s_tz_of_ops); 216 if (IS_ERR(priv->tz)) 217 return dev_err_probe(dev, PTR_ERR(priv->tz), "Failed to register thermal zone!\n"); 218 219 ret = devm_thermal_add_hwmon_sysfs(dev, priv->tz); 220 if (ret) 221 return dev_err_probe(dev, ret, "Failed to add hwmon sysfs!\n"); 222 223 return 0; 224 } 225 226 static int rzg3s_thermal_suspend(struct device *dev) 227 { 228 struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev); 229 230 rzg3s_thermal_set_mode(priv, THERMAL_DEVICE_DISABLED); 231 232 return reset_control_assert(priv->rstc); 233 } 234 235 static int rzg3s_thermal_resume(struct device *dev) 236 { 237 struct rzg3s_thermal_priv *priv = dev_get_drvdata(dev); 238 int ret; 239 240 ret = reset_control_deassert(priv->rstc); 241 if (ret) 242 return ret; 243 244 if (priv->mode != THERMAL_DEVICE_DISABLED) 245 rzg3s_thermal_set_mode(priv, priv->mode); 246 247 return 0; 248 } 249 250 static const struct dev_pm_ops rzg3s_thermal_pm_ops = { 251 SYSTEM_SLEEP_PM_OPS(rzg3s_thermal_suspend, rzg3s_thermal_resume) 252 }; 253 254 static const struct of_device_id rzg3s_thermal_dt_ids[] = { 255 { .compatible = "renesas,r9a08g045-tsu" }, 256 { /* sentinel */ } 257 }; 258 MODULE_DEVICE_TABLE(of, rzg3s_thermal_dt_ids); 259 260 static struct platform_driver rzg3s_thermal_driver = { 261 .driver = { 262 .name = "rzg3s-thermal", 263 .of_match_table = rzg3s_thermal_dt_ids, 264 .pm = pm_ptr(&rzg3s_thermal_pm_ops), 265 }, 266 .probe = rzg3s_thermal_probe, 267 }; 268 module_platform_driver(rzg3s_thermal_driver); 269 270 MODULE_DESCRIPTION("Renesas RZ/G3S Thermal Sensor Unit Driver"); 271 MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>"); 272 MODULE_LICENSE("GPL"); 273