1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ESWIN EIC7700 Voltage, Temperature sensor driver 4 * 5 * Copyright 2026, Beijing ESWIN Computing Technology Co., Ltd. 6 * 7 * Authors: 8 * Yulin Lu <luyulin@eswincomputing.com> 9 * Huan He <hehuan1@eswincomputing.com> 10 */ 11 12 #include <linux/bitfield.h> 13 #include <linux/clk.h> 14 #include <linux/delay.h> 15 #include <linux/device.h> 16 #include <linux/interrupt.h> 17 #include <linux/io.h> 18 #include <linux/module.h> 19 #include <linux/of.h> 20 #include <linux/platform_device.h> 21 #include <linux/pm_runtime.h> 22 #include <linux/polynomial.h> 23 #include <linux/reset.h> 24 #include "eic7700-pvt.h" 25 26 static const struct pvt_sensor_info pvt_info[] = { 27 PVT_SENSOR_INFO(0, "Temperature", hwmon_temp, TEMP), 28 PVT_SENSOR_INFO(0, "Voltage", hwmon_in, VOLT), 29 }; 30 31 static const char * const pvt_clk_names[PVT_CLK_NUM] = {"enable", "apb"}; 32 33 /* 34 * The original translation formulae of the temperature (in degrees of Celsius) 35 * to PVT data and vice-versa are following: 36 * N = 6.0818e-8*(T^4) +1.2873e-5*(T^3) + 7.2244e-3*(T^2) + 3.6484*(T^1) + 37 * 1.6198e2, 38 * T = -1.8439e-11*(N^4) + 8.0705e-8*(N^3) + -1.8501e-4*(N^2) + 39 * 3.2843e-1*(N^1) - 4.8690e1, 40 * where T = [-40, 125]C and N = [27, 771]. 41 * They must be accordingly altered to be suitable for the integer arithmetics. 42 * The technique is called 'factor redistribution', which just makes sure the 43 * multiplications and divisions are made so to have a result of the operations 44 * within the integer numbers limit. In addition we need to translate the 45 * formulae to accept millidegrees of Celsius. Here what they look like after 46 * the alterations: 47 * N = (60818e-20*(T^4) + 12873e-14*(T^3) + 72244e-9*(T^2) + 36484e-3*T + 48 * 16198e2) / 1e4, 49 * T = -18439e-12*(N^4) + 80705e-9*(N^3) - 185010e-6*(N^2) + 328430e-3*N - 50 * 48690, 51 * where T = [-40000, 125000] mC and N = [27, 771]. 52 */ 53 static const struct polynomial poly_N_to_temp = { 54 .total_divider = 1, 55 .terms = { 56 {4, -18439, 1000, 1}, 57 {3, 80705, 1000, 1}, 58 {2, -185010, 1000, 1}, 59 {1, 328430, 1000, 1}, 60 {0, -48690, 1, 1} 61 } 62 }; 63 64 /* 65 * Similar alterations are performed for the voltage conversion equations. 66 * The original formulae are: 67 * N = 1.3905e3*V - 5.7685e2, 68 * V = (N + 5.7685e2) / 1.3905e3, 69 * where V = [0.72, 0.88] V and N = [424, 646]. 70 * After the optimization they looks as follows: 71 * N = (13905e-3*V - 5768.5) / 10, 72 * V = (N * 10^5 / 13905 + 57685 * 10^3 / 13905) / 10. 73 * where V = [720, 880] mV and N = [424, 646]. 74 */ 75 static const struct polynomial poly_N_to_volt = { 76 .total_divider = 10, 77 .terms = { 78 {1, 100000, 13905, 1}, 79 {0, 57685000, 1, 13905} 80 } 81 }; 82 83 static inline u32 eic7700_pvt_update(void __iomem *reg, u32 mask, u32 data) 84 { 85 u32 old; 86 87 old = readl_relaxed(reg); 88 writel((old & ~mask) | (data & mask), reg); 89 90 return old & mask; 91 } 92 93 static inline void eic7700_pvt_set_mode(struct pvt_hwmon *pvt, u32 mode) 94 { 95 u32 old; 96 97 mode = FIELD_PREP(PVT_MODE_MASK, mode); 98 99 old = eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); 100 eic7700_pvt_update(pvt->regs + PVT_MODE, PVT_MODE_MASK, mode); 101 eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, old); 102 } 103 104 static inline void eic7700_pvt_set_trim(struct pvt_hwmon *pvt, u32 val) 105 { 106 u32 old; 107 108 old = eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); 109 writel(val, pvt->regs + PVT_TRIM); 110 eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, old); 111 } 112 113 static irqreturn_t eic7700_pvt_hard_isr(int irq, void *data) 114 { 115 struct pvt_hwmon *pvt = data; 116 u32 stat, val; 117 int active; 118 119 if (IS_ENABLED(CONFIG_PM)) { 120 active = pm_runtime_get_if_active(pvt->dev); 121 if (active <= 0) 122 return IRQ_NONE; 123 } 124 125 stat = readl(pvt->regs + PVT_INT); 126 if (!(stat & PVT_INT_STAT)) { 127 if (IS_ENABLED(CONFIG_PM)) 128 pm_runtime_put(pvt->dev); 129 return IRQ_NONE; 130 } 131 132 eic7700_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); 133 /* 134 * Read the data, update the cache and notify a waiter of this event. 135 */ 136 val = readl(pvt->regs + PVT_DATA); 137 WRITE_ONCE(pvt->data_cache, FIELD_GET(PVT_DATA_OUT, val)); 138 complete(&pvt->conversion); 139 140 if (IS_ENABLED(CONFIG_PM)) 141 pm_runtime_put(pvt->dev); 142 143 return IRQ_HANDLED; 144 } 145 146 static int eic7700_pvt_read_data(struct pvt_hwmon *pvt, 147 enum pvt_sensor_type type, long *val) 148 { 149 unsigned long timeout; 150 u32 data; 151 int ret; 152 153 /* 154 * Wait for PVT conversion to complete and update the data cache. The 155 * data read procedure is following: set the requested PVT sensor mode, 156 * enable conversion, wait until conversion is finished, then disable 157 * conversion and IRQ, and read the cached data. 158 */ 159 reinit_completion(&pvt->conversion); 160 161 eic7700_pvt_set_mode(pvt, pvt_info[type].mode); 162 eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, PVT_ENA_EN); 163 164 /* 165 * Wait with timeout since in case if the sensor is suddenly powered 166 * down the request won't be completed and the caller will hang up on 167 * this procedure until the power is back up again. Multiply the 168 * timeout by the factor of two to prevent a false timeout. 169 */ 170 timeout = 2 * usecs_to_jiffies(ktime_to_us(pvt->timeout)); 171 ret = wait_for_completion_timeout(&pvt->conversion, timeout); 172 173 eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); 174 eic7700_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); 175 176 if (!ret) 177 synchronize_irq(pvt->irq); 178 179 data = READ_ONCE(pvt->data_cache); 180 181 if (!ret) 182 return -ETIMEDOUT; 183 184 if (type == PVT_TEMP) 185 *val = polynomial_calc(&poly_N_to_temp, data); 186 else 187 *val = polynomial_calc(&poly_N_to_volt, data); 188 189 return 0; 190 } 191 192 static const struct hwmon_channel_info *pvt_channel_info[] = { 193 HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 194 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_LABEL), 195 HWMON_CHANNEL_INFO(in, HWMON_I_INPUT | HWMON_I_LABEL), 196 NULL 197 }; 198 199 static umode_t eic7700_pvt_hwmon_is_visible(const void *data, 200 enum hwmon_sensor_types type, 201 u32 attr, int ch) 202 { 203 switch (type) { 204 case hwmon_temp: 205 switch (attr) { 206 case hwmon_temp_input: 207 case hwmon_temp_label: 208 return 0444; 209 } 210 break; 211 case hwmon_in: 212 switch (attr) { 213 case hwmon_in_input: 214 case hwmon_in_label: 215 return 0444; 216 } 217 break; 218 default: 219 break; 220 } 221 222 return 0; 223 } 224 225 static int eic7700_pvt_hwmon_read(struct device *dev, 226 enum hwmon_sensor_types type, u32 attr, 227 int ch, long *val) 228 { 229 struct pvt_hwmon *pvt = dev_get_drvdata(dev); 230 int ret; 231 232 ret = pm_runtime_get_sync(pvt->dev); 233 if (ret < 0) { 234 dev_err(pvt->dev, "Failed to resume PVT device: %d\n", ret); 235 pm_runtime_put_noidle(pvt->dev); 236 return ret; 237 } 238 239 switch (type) { 240 case hwmon_temp: 241 switch (attr) { 242 case hwmon_temp_input: 243 ret = eic7700_pvt_read_data(pvt, ch, val); 244 break; 245 default: 246 ret = -EOPNOTSUPP; 247 } 248 break; 249 case hwmon_in: 250 if (attr == hwmon_in_input) 251 ret = eic7700_pvt_read_data(pvt, PVT_VOLT + ch, val); 252 else 253 ret = -EOPNOTSUPP; 254 break; 255 default: 256 ret = -EOPNOTSUPP; 257 } 258 259 pm_runtime_mark_last_busy(pvt->dev); 260 pm_runtime_put_autosuspend(pvt->dev); 261 return ret; 262 } 263 264 static int eic7700_pvt_hwmon_read_string(struct device *dev, 265 enum hwmon_sensor_types type, u32 attr, 266 int ch, const char **str) 267 { 268 switch (type) { 269 case hwmon_temp: 270 if (attr == hwmon_temp_label) { 271 *str = pvt_info[ch].label; 272 return 0; 273 } 274 break; 275 case hwmon_in: 276 if (attr == hwmon_in_label) { 277 *str = pvt_info[PVT_VOLT + ch].label; 278 return 0; 279 } 280 break; 281 default: 282 break; 283 } 284 285 return -EOPNOTSUPP; 286 } 287 288 static const struct hwmon_ops pvt_hwmon_ops = { 289 .is_visible = eic7700_pvt_hwmon_is_visible, 290 .read = eic7700_pvt_hwmon_read, 291 .read_string = eic7700_pvt_hwmon_read_string 292 }; 293 294 static const struct hwmon_chip_info pvt_hwmon_info = { 295 .ops = &pvt_hwmon_ops, 296 .info = pvt_channel_info 297 }; 298 299 static struct pvt_hwmon *eic7700_pvt_create_data(struct platform_device *pdev) 300 { 301 struct device *dev = &pdev->dev; 302 struct pvt_hwmon *pvt; 303 304 pvt = devm_kzalloc(dev, sizeof(*pvt), GFP_KERNEL); 305 if (!pvt) 306 return ERR_PTR(-ENOMEM); 307 308 pvt->dev = dev; 309 init_completion(&pvt->conversion); 310 311 return pvt; 312 } 313 314 static int eic7700_pvt_init_iface(struct pvt_hwmon *pvt) 315 { 316 /* 317 * Make sure controller are disabled so not to accidentally have ISR 318 * executed before the driver data is fully initialized. Clear the IRQ 319 * status as well. 320 */ 321 eic7700_pvt_update(pvt->regs + PVT_ENA, PVT_ENA_EN, 0); 322 eic7700_pvt_update(pvt->regs + PVT_INT, PVT_INT_CLR, PVT_INT_CLR); 323 readl(pvt->regs + PVT_INT); 324 readl(pvt->regs + PVT_DATA); 325 326 /* Setup default sensor mode and temperature trim. */ 327 eic7700_pvt_set_mode(pvt, pvt_info[PVT_TEMP].mode); 328 329 /* 330 * Max conversion latency (~333 µs) derived from PVT spec: 331 * maximum sampling rate = 3000 samples/sec. 332 */ 333 pvt->timeout = ns_to_ktime(PVT_TOUT_MIN); 334 335 eic7700_pvt_set_trim(pvt, PVT_TRIM_DEF); 336 337 return 0; 338 } 339 340 static int eic7700_pvt_request_irq(struct pvt_hwmon *pvt) 341 { 342 struct platform_device *pdev = to_platform_device(pvt->dev); 343 int ret; 344 345 pvt->irq = platform_get_irq(pdev, 0); 346 if (pvt->irq < 0) 347 return pvt->irq; 348 349 ret = devm_request_threaded_irq(pvt->dev, pvt->irq, 350 eic7700_pvt_hard_isr, NULL, 351 IRQF_TRIGGER_HIGH, "pvt", pvt); 352 if (ret) { 353 dev_err(pvt->dev, "Couldn't request PVT IRQ\n"); 354 return ret; 355 } 356 357 return 0; 358 } 359 360 static int eic7700_pvt_create_hwmon(struct pvt_hwmon *pvt) 361 { 362 pvt->hwmon = devm_hwmon_device_register_with_info(pvt->dev, "pvt", 363 pvt, &pvt_hwmon_info, 364 NULL); 365 if (IS_ERR(pvt->hwmon)) { 366 dev_err(pvt->dev, "Couldn't create hwmon device\n"); 367 return PTR_ERR(pvt->hwmon); 368 } 369 370 return 0; 371 } 372 373 static void eic7700_pvt_disable_pm_runtime(void *data) 374 { 375 struct pvt_hwmon *pvt = data; 376 377 pm_runtime_dont_use_autosuspend(pvt->dev); 378 pm_runtime_disable(pvt->dev); 379 380 if (!pm_runtime_status_suspended(pvt->dev)) { 381 clk_bulk_disable_unprepare(PVT_CLK_NUM, pvt->clks); 382 pm_runtime_set_suspended(pvt->dev); 383 } 384 } 385 386 static int eic7700_pvt_probe(struct platform_device *pdev) 387 { 388 struct reset_control *rst; 389 struct pvt_hwmon *pvt; 390 int i, ret; 391 392 pvt = eic7700_pvt_create_data(pdev); 393 if (IS_ERR(pvt)) 394 return PTR_ERR(pvt); 395 396 platform_set_drvdata(pdev, pvt); 397 398 pvt->regs = devm_platform_ioremap_resource(pdev, 0); 399 if (IS_ERR(pvt->regs)) 400 return PTR_ERR(pvt->regs); 401 402 for (i = 0; i < PVT_CLK_NUM; i++) 403 pvt->clks[i].id = pvt_clk_names[i]; 404 405 ret = devm_clk_bulk_get(&pdev->dev, PVT_CLK_NUM, pvt->clks); 406 if (ret) 407 return dev_err_probe(&pdev->dev, ret, 408 "Couldn't get clock descriptors\n"); 409 410 rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL); 411 if (IS_ERR(rst)) 412 return dev_err_probe(pvt->dev, PTR_ERR(rst), 413 "Couldn't get reset control\n"); 414 415 ret = clk_bulk_prepare_enable(PVT_CLK_NUM, pvt->clks); 416 if (ret) 417 return dev_err_probe(pvt->dev, ret, 418 "Failed to enable clocks\n"); 419 420 ret = eic7700_pvt_init_iface(pvt); 421 if (ret) { 422 clk_bulk_disable_unprepare(PVT_CLK_NUM, pvt->clks); 423 return ret; 424 } 425 426 if (IS_ENABLED(CONFIG_PM)) 427 clk_bulk_disable_unprepare(PVT_CLK_NUM, pvt->clks); 428 429 pm_runtime_enable(&pdev->dev); 430 pm_runtime_set_autosuspend_delay(&pdev->dev, 3000); 431 pm_runtime_use_autosuspend(&pdev->dev); 432 pm_runtime_get_noresume(&pdev->dev); 433 434 ret = devm_add_action_or_reset(pvt->dev, eic7700_pvt_disable_pm_runtime, 435 pvt); 436 if (ret) { 437 pm_runtime_put_noidle(&pdev->dev); 438 return dev_err_probe(&pdev->dev, ret, 439 "Can't register PM cleanup\n"); 440 } 441 442 ret = eic7700_pvt_request_irq(pvt); 443 if (ret) 444 goto err_put_pm_runtime; 445 446 ret = eic7700_pvt_create_hwmon(pvt); 447 if (ret) 448 goto err_put_pm_runtime; 449 450 pm_runtime_put_autosuspend(&pdev->dev); 451 452 return 0; 453 454 err_put_pm_runtime: 455 pm_runtime_put_noidle(&pdev->dev); 456 return ret; 457 } 458 459 static int __maybe_unused eic7700_pvt_runtime_resume(struct device *dev) 460 { 461 struct pvt_hwmon *pvt = dev_get_drvdata(dev); 462 int ret; 463 464 ret = clk_bulk_prepare_enable(PVT_CLK_NUM, pvt->clks); 465 if (ret) { 466 dev_err(dev, "Failed to enable clocks: %d\n", ret); 467 return ret; 468 } 469 470 eic7700_pvt_set_trim(pvt, PVT_TRIM_DEF); 471 472 return 0; 473 } 474 475 static int __maybe_unused eic7700_pvt_runtime_suspend(struct device *dev) 476 { 477 struct pvt_hwmon *pvt = dev_get_drvdata(dev); 478 479 clk_bulk_disable_unprepare(PVT_CLK_NUM, pvt->clks); 480 481 return 0; 482 } 483 484 static const struct dev_pm_ops eic7700_pvt_pm_ops = { 485 SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 486 RUNTIME_PM_OPS(eic7700_pvt_runtime_suspend, eic7700_pvt_runtime_resume, 487 NULL) 488 }; 489 490 static const struct of_device_id pvt_of_match[] = { 491 { .compatible = "eswin,eic7700-pvt"}, 492 { } 493 }; 494 MODULE_DEVICE_TABLE(of, pvt_of_match); 495 496 static struct platform_driver pvt_driver = { 497 .probe = eic7700_pvt_probe, 498 .driver = { 499 .name = "eic7700-pvt", 500 .of_match_table = pvt_of_match, 501 .pm = pm_ptr(&eic7700_pvt_pm_ops), 502 }, 503 }; 504 module_platform_driver(pvt_driver); 505 506 MODULE_AUTHOR("Yulin Lu <luyulin@eswincomputing.com>"); 507 MODULE_AUTHOR("Huan He <hehuan1@eswincomputing.com>"); 508 MODULE_DESCRIPTION("Eswin eic7700 PVT driver"); 509 MODULE_LICENSE("GPL"); 510