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