1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk> 4 * Copyright (C) 2021 Samin Guo <samin.guo@starfivetech.com> 5 */ 6 7 #include <linux/bits.h> 8 #include <linux/clk.h> 9 #include <linux/delay.h> 10 #include <linux/hwmon.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/reset.h> 17 18 /* 19 * TempSensor reset. The RSTN can be de-asserted once the analog core has 20 * powered up. Trst(min 100ns) 21 * 0:reset 1:de-assert 22 */ 23 #define SFCTEMP_RSTN BIT(0) 24 25 /* 26 * TempSensor analog core power down. The analog core will be powered up 27 * Tpu(min 50us) after PD is de-asserted. RSTN should be held low until the 28 * analog core is powered up. 29 * 0:power up 1:power down 30 */ 31 #define SFCTEMP_PD BIT(1) 32 33 /* 34 * TempSensor start conversion enable. 35 * 0:disable 1:enable 36 */ 37 #define SFCTEMP_RUN BIT(2) 38 39 /* 40 * TempSensor conversion value output. 41 * Temp(C)=DOUT*Y/4094 - K 42 */ 43 #define SFCTEMP_DOUT_POS 16 44 #define SFCTEMP_DOUT_MSK GENMASK(27, 16) 45 46 /* DOUT to Celcius conversion constants */ 47 #define SFCTEMP_Y1000 237500L 48 #define SFCTEMP_Z 4094L 49 #define SFCTEMP_K1000 81100L 50 51 struct sfctemp { 52 /* serialize access to hardware register and enabled below */ 53 struct mutex lock; 54 void __iomem *regs; 55 struct clk *clk_sense; 56 struct clk *clk_bus; 57 struct reset_control *rst_sense; 58 struct reset_control *rst_bus; 59 bool enabled; 60 }; 61 62 static void sfctemp_power_up(struct sfctemp *sfctemp) 63 { 64 /* make sure we're powered down first */ 65 writel(SFCTEMP_PD, sfctemp->regs); 66 udelay(1); 67 68 writel(0, sfctemp->regs); 69 /* wait t_pu(50us) + t_rst(100ns) */ 70 usleep_range(60, 200); 71 72 /* de-assert reset */ 73 writel(SFCTEMP_RSTN, sfctemp->regs); 74 udelay(1); /* wait t_su(500ps) */ 75 } 76 77 static void sfctemp_power_down(struct sfctemp *sfctemp) 78 { 79 writel(SFCTEMP_PD, sfctemp->regs); 80 } 81 82 static void sfctemp_run(struct sfctemp *sfctemp) 83 { 84 writel(SFCTEMP_RSTN | SFCTEMP_RUN, sfctemp->regs); 85 udelay(1); 86 } 87 88 static void sfctemp_stop(struct sfctemp *sfctemp) 89 { 90 writel(SFCTEMP_RSTN, sfctemp->regs); 91 } 92 93 static int sfctemp_enable(struct sfctemp *sfctemp) 94 { 95 int ret = 0; 96 97 mutex_lock(&sfctemp->lock); 98 if (sfctemp->enabled) 99 goto done; 100 101 ret = clk_prepare_enable(sfctemp->clk_bus); 102 if (ret) 103 goto err; 104 ret = reset_control_deassert(sfctemp->rst_bus); 105 if (ret) 106 goto err_disable_bus; 107 108 ret = clk_prepare_enable(sfctemp->clk_sense); 109 if (ret) 110 goto err_assert_bus; 111 ret = reset_control_deassert(sfctemp->rst_sense); 112 if (ret) 113 goto err_disable_sense; 114 115 sfctemp_power_up(sfctemp); 116 sfctemp_run(sfctemp); 117 sfctemp->enabled = true; 118 done: 119 mutex_unlock(&sfctemp->lock); 120 return ret; 121 122 err_disable_sense: 123 clk_disable_unprepare(sfctemp->clk_sense); 124 err_assert_bus: 125 reset_control_assert(sfctemp->rst_bus); 126 err_disable_bus: 127 clk_disable_unprepare(sfctemp->clk_bus); 128 err: 129 mutex_unlock(&sfctemp->lock); 130 return ret; 131 } 132 133 static int sfctemp_disable(struct sfctemp *sfctemp) 134 { 135 mutex_lock(&sfctemp->lock); 136 if (!sfctemp->enabled) 137 goto done; 138 139 sfctemp_stop(sfctemp); 140 sfctemp_power_down(sfctemp); 141 reset_control_assert(sfctemp->rst_sense); 142 clk_disable_unprepare(sfctemp->clk_sense); 143 reset_control_assert(sfctemp->rst_bus); 144 clk_disable_unprepare(sfctemp->clk_bus); 145 sfctemp->enabled = false; 146 done: 147 mutex_unlock(&sfctemp->lock); 148 return 0; 149 } 150 151 static void sfctemp_disable_action(void *data) 152 { 153 sfctemp_disable(data); 154 } 155 156 static int sfctemp_convert(struct sfctemp *sfctemp, long *val) 157 { 158 int ret; 159 160 mutex_lock(&sfctemp->lock); 161 if (!sfctemp->enabled) { 162 ret = -ENODATA; 163 goto out; 164 } 165 166 /* calculate temperature in milli Celcius */ 167 *val = (long)((readl(sfctemp->regs) & SFCTEMP_DOUT_MSK) >> SFCTEMP_DOUT_POS) 168 * SFCTEMP_Y1000 / SFCTEMP_Z - SFCTEMP_K1000; 169 170 ret = 0; 171 out: 172 mutex_unlock(&sfctemp->lock); 173 return ret; 174 } 175 176 static umode_t sfctemp_is_visible(const void *data, enum hwmon_sensor_types type, 177 u32 attr, int channel) 178 { 179 switch (type) { 180 case hwmon_temp: 181 switch (attr) { 182 case hwmon_temp_enable: 183 return 0644; 184 case hwmon_temp_input: 185 return 0444; 186 default: 187 return 0; 188 } 189 default: 190 return 0; 191 } 192 } 193 194 static int sfctemp_read(struct device *dev, enum hwmon_sensor_types type, 195 u32 attr, int channel, long *val) 196 { 197 struct sfctemp *sfctemp = dev_get_drvdata(dev); 198 199 switch (type) { 200 case hwmon_temp: 201 switch (attr) { 202 case hwmon_temp_enable: 203 *val = sfctemp->enabled; 204 return 0; 205 case hwmon_temp_input: 206 return sfctemp_convert(sfctemp, val); 207 default: 208 return -EINVAL; 209 } 210 default: 211 return -EINVAL; 212 } 213 } 214 215 static int sfctemp_write(struct device *dev, enum hwmon_sensor_types type, 216 u32 attr, int channel, long val) 217 { 218 struct sfctemp *sfctemp = dev_get_drvdata(dev); 219 220 switch (type) { 221 case hwmon_temp: 222 switch (attr) { 223 case hwmon_temp_enable: 224 if (val == 0) 225 return sfctemp_disable(sfctemp); 226 if (val == 1) 227 return sfctemp_enable(sfctemp); 228 return -EINVAL; 229 default: 230 return -EINVAL; 231 } 232 default: 233 return -EINVAL; 234 } 235 } 236 237 static const struct hwmon_channel_info *sfctemp_info[] = { 238 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 239 HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT), 240 NULL 241 }; 242 243 static const struct hwmon_ops sfctemp_hwmon_ops = { 244 .is_visible = sfctemp_is_visible, 245 .read = sfctemp_read, 246 .write = sfctemp_write, 247 }; 248 249 static const struct hwmon_chip_info sfctemp_chip_info = { 250 .ops = &sfctemp_hwmon_ops, 251 .info = sfctemp_info, 252 }; 253 254 static int sfctemp_probe(struct platform_device *pdev) 255 { 256 struct device *dev = &pdev->dev; 257 struct device *hwmon_dev; 258 struct sfctemp *sfctemp; 259 int ret; 260 261 sfctemp = devm_kzalloc(dev, sizeof(*sfctemp), GFP_KERNEL); 262 if (!sfctemp) 263 return -ENOMEM; 264 265 dev_set_drvdata(dev, sfctemp); 266 mutex_init(&sfctemp->lock); 267 268 sfctemp->regs = devm_platform_ioremap_resource(pdev, 0); 269 if (IS_ERR(sfctemp->regs)) 270 return PTR_ERR(sfctemp->regs); 271 272 sfctemp->clk_sense = devm_clk_get(dev, "sense"); 273 if (IS_ERR(sfctemp->clk_sense)) 274 return dev_err_probe(dev, PTR_ERR(sfctemp->clk_sense), 275 "error getting sense clock\n"); 276 277 sfctemp->clk_bus = devm_clk_get(dev, "bus"); 278 if (IS_ERR(sfctemp->clk_bus)) 279 return dev_err_probe(dev, PTR_ERR(sfctemp->clk_bus), 280 "error getting bus clock\n"); 281 282 sfctemp->rst_sense = devm_reset_control_get_exclusive(dev, "sense"); 283 if (IS_ERR(sfctemp->rst_sense)) 284 return dev_err_probe(dev, PTR_ERR(sfctemp->rst_sense), 285 "error getting sense reset\n"); 286 287 sfctemp->rst_bus = devm_reset_control_get_exclusive(dev, "bus"); 288 if (IS_ERR(sfctemp->rst_bus)) 289 return dev_err_probe(dev, PTR_ERR(sfctemp->rst_bus), 290 "error getting busreset\n"); 291 292 ret = reset_control_assert(sfctemp->rst_sense); 293 if (ret) 294 return dev_err_probe(dev, ret, "error asserting sense reset\n"); 295 296 ret = reset_control_assert(sfctemp->rst_bus); 297 if (ret) 298 return dev_err_probe(dev, ret, "error asserting bus reset\n"); 299 300 ret = devm_add_action(dev, sfctemp_disable_action, sfctemp); 301 if (ret) 302 return ret; 303 304 ret = sfctemp_enable(sfctemp); 305 if (ret) 306 return dev_err_probe(dev, ret, "error enabling temperature sensor\n"); 307 308 hwmon_dev = devm_hwmon_device_register_with_info(dev, "sfctemp", sfctemp, 309 &sfctemp_chip_info, NULL); 310 return PTR_ERR_OR_ZERO(hwmon_dev); 311 } 312 313 static const struct of_device_id sfctemp_of_match[] = { 314 { .compatible = "starfive,jh7100-temp" }, 315 { .compatible = "starfive,jh7110-temp" }, 316 { /* sentinel */ } 317 }; 318 MODULE_DEVICE_TABLE(of, sfctemp_of_match); 319 320 static struct platform_driver sfctemp_driver = { 321 .probe = sfctemp_probe, 322 .driver = { 323 .name = "sfctemp", 324 .of_match_table = sfctemp_of_match, 325 }, 326 }; 327 module_platform_driver(sfctemp_driver); 328 329 MODULE_AUTHOR("Emil Renner Berthing"); 330 MODULE_DESCRIPTION("StarFive JH71x0 temperature sensor driver"); 331 MODULE_LICENSE("GPL"); 332