Lines Matching +full:thermal +full:- +full:calibration
1 // SPDX-License-Identifier: GPL-2.0
3 * Tegra30 SoC Thermal Sensor driver
9 * Copyright (C) 2021 GRATE-DRIVER project
26 #include <linux/thermal.h>
95 err = reset_control_assert(ts->rst); in tegra_tsensor_hw_enable()
97 dev_err(ts->dev, "failed to assert hardware reset: %d\n", err); in tegra_tsensor_hw_enable()
101 err = clk_prepare_enable(ts->clk); in tegra_tsensor_hw_enable()
103 dev_err(ts->dev, "failed to enable clock: %d\n", err); in tegra_tsensor_hw_enable()
109 err = reset_control_deassert(ts->rst); in tegra_tsensor_hw_enable()
111 dev_err(ts->dev, "failed to deassert hardware reset: %d\n", err); in tegra_tsensor_hw_enable()
128 writel_relaxed(val, ts->regs + 0x40 + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_hw_enable()
129 writel_relaxed(val, ts->regs + 0x80 + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_hw_enable()
134 clk_disable_unprepare(ts->clk); in tegra_tsensor_hw_enable()
143 err = reset_control_assert(ts->rst); in tegra_tsensor_hw_disable()
145 dev_err(ts->dev, "failed to assert hardware reset: %d\n", err); in tegra_tsensor_hw_disable()
149 clk_disable_unprepare(ts->clk); in tegra_tsensor_hw_disable()
164 const struct tegra_tsensor *ts = tsc->ts; in tegra_tsensor_get_temp()
172 err = readl_relaxed_poll_timeout(tsc->regs + TSENSOR_SENSOR0_STATUS0, val, in tegra_tsensor_get_temp()
177 dev_err_once(ts->dev, "ch%u: counter invalid\n", tsc->id); in tegra_tsensor_get_temp()
181 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_TS_STATUS1); in tegra_tsensor_get_temp()
190 dev_err_once(ts->dev, "ch%u: counter overflow\n", tsc->id); in tegra_tsensor_get_temp()
191 return -EINVAL; in tegra_tsensor_get_temp()
198 c1 = DIV_ROUND_CLOSEST(ts->calib.a * counter + ts->calib.b, 1000000); in tegra_tsensor_get_temp()
200 c2 = DIV_ROUND_CLOSEST(ts->calib.p, c1); in tegra_tsensor_get_temp()
201 c3 = c1 * ts->calib.m; in tegra_tsensor_get_temp()
202 c4 = ts->calib.n; in tegra_tsensor_get_temp()
213 c1 = DIV_ROUND_CLOSEST(ts->calib.p - temp * 1000, ts->calib.m); in tegra_tsensor_temp_to_counter()
214 c2 = -ts->calib.r - int_sqrt(ts->calib.r * ts->calib.r - c1); in tegra_tsensor_temp_to_counter()
216 return DIV_ROUND_CLOSEST(c2 * 1000000 - ts->calib.b, ts->calib.a); in tegra_tsensor_temp_to_counter()
222 const struct tegra_tsensor *ts = tsc->ts; in tegra_tsensor_set_trips()
232 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG1); in tegra_tsensor_set_trips()
237 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG1); in tegra_tsensor_set_trips()
251 const struct tegra_tsensor_channel *tsc = &ts->ch[id]; in tegra_tsensor_handle_channel_interrupt()
254 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_STATUS0); in tegra_tsensor_handle_channel_interrupt()
255 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_STATUS0); in tegra_tsensor_handle_channel_interrupt()
258 dev_err_ratelimited(ts->dev, "ch%u: counter overflowed\n", id); in tegra_tsensor_handle_channel_interrupt()
263 thermal_zone_device_update(tsc->tzd, THERMAL_EVENT_UNSPECIFIED); in tegra_tsensor_handle_channel_interrupt()
274 for (i = 0; i < ARRAY_SIZE(ts->ch); i++) in tegra_tsensor_isr()
283 const struct tegra_tsensor_channel *tsc = &ts->ch[id]; in tegra_tsensor_disable_hw_channel()
284 struct thermal_zone_device *tzd = tsc->tzd; in tegra_tsensor_disable_hw_channel()
293 dev_err(ts->dev, "ch%u: failed to disable zone: %d\n", id, err); in tegra_tsensor_disable_hw_channel()
299 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_disable_hw_channel()
301 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_disable_hw_channel()
315 if (trip->type == THERMAL_TRIP_HOT) in tegra_tsensor_get_trips_cb()
316 temps->hot_trip = trip->temperature; in tegra_tsensor_get_trips_cb()
317 else if (trip->type == THERMAL_TRIP_CRITICAL) in tegra_tsensor_get_trips_cb()
318 temps->crit_trip = trip->temperature; in tegra_tsensor_get_trips_cb()
328 * use it for the default trip if unspecified in a device-tree. in tegra_tsensor_get_hw_channel_trips()
330 temps->hot_trip = 85000; in tegra_tsensor_get_hw_channel_trips()
331 temps->crit_trip = 90000; in tegra_tsensor_get_hw_channel_trips()
335 /* clamp hardware trips to the calibration limits */ in tegra_tsensor_get_hw_channel_trips()
336 temps->hot_trip = clamp(temps->hot_trip, 25000, 90000); in tegra_tsensor_get_hw_channel_trips()
345 temps->crit_trip = clamp(temps->crit_trip + 5000, 25000, 90000); in tegra_tsensor_get_hw_channel_trips()
351 const struct tegra_tsensor_channel *tsc = &ts->ch[id]; in tegra_tsensor_enable_hw_channel()
352 struct thermal_zone_device *tzd = tsc->tzd; in tegra_tsensor_enable_hw_channel()
358 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_enable_hw_channel()
360 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_enable_hw_channel()
367 dev_info_once(ts->dev, "ch%u: PMC emergency shutdown trip set to %dC\n", in tegra_tsensor_enable_hw_channel()
374 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG1); in tegra_tsensor_enable_hw_channel()
377 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG1); in tegra_tsensor_enable_hw_channel()
380 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG2); in tegra_tsensor_enable_hw_channel()
383 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG2); in tegra_tsensor_enable_hw_channel()
390 * to integrate it properly with the thermal framework. in tegra_tsensor_enable_hw_channel()
392 * Thermal levels supported by hardware: in tegra_tsensor_enable_hw_channel()
399 val = readl_relaxed(tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_enable_hw_channel()
407 writel_relaxed(val, tsc->regs + TSENSOR_SENSOR0_CONFIG0); in tegra_tsensor_enable_hw_channel()
411 dev_err(ts->dev, "ch%u: failed to enable zone: %d\n", id, err); in tegra_tsensor_enable_hw_channel()
434 dev_err_probe(ts->dev, err, "failed to get ATE version\n"); in tegra_tsensor_nvmem_setup()
439 dev_info(ts->dev, "unsupported ATE version: %u\n", ate_ver); in tegra_tsensor_nvmem_setup()
440 return -ENODEV; in tegra_tsensor_nvmem_setup()
449 dev_info_once(ts->dev, in tegra_tsensor_nvmem_setup()
451 ts->swap_channels = true; in tegra_tsensor_nvmem_setup()
456 dev_err(ts->dev, "failed to get calibration data: %d\n", err); in tegra_tsensor_nvmem_setup()
473 if (c2_90C - c1_25C <= t2_90C - t1_25C) { in tegra_tsensor_nvmem_setup()
474 dev_err(ts->dev, "invalid calibration data: %d %d %u %u\n", in tegra_tsensor_nvmem_setup()
476 return -EINVAL; in tegra_tsensor_nvmem_setup()
479 /* all calibration coefficients are premultiplied by 1000000 */ in tegra_tsensor_nvmem_setup()
481 ts->calib.a = DIV_ROUND_CLOSEST((t2_90C - t1_25C) * 1000000, in tegra_tsensor_nvmem_setup()
482 (c2_90C - c1_25C)); in tegra_tsensor_nvmem_setup()
484 ts->calib.b = t1_25C * 1000000 - ts->calib.a * c1_25C; in tegra_tsensor_nvmem_setup()
487 ts->calib.m = -2775; in tegra_tsensor_nvmem_setup()
488 ts->calib.n = 1338811; in tegra_tsensor_nvmem_setup()
489 ts->calib.p = -7300000; in tegra_tsensor_nvmem_setup()
491 ts->calib.m = -3512; in tegra_tsensor_nvmem_setup()
492 ts->calib.n = 1528943; in tegra_tsensor_nvmem_setup()
493 ts->calib.p = -11100000; in tegra_tsensor_nvmem_setup()
497 ts->calib.r = DIV_ROUND_CLOSEST(ts->calib.n, ts->calib.m * 2); in tegra_tsensor_nvmem_setup()
499 dev_info_once(ts->dev, in tegra_tsensor_nvmem_setup()
500 "calibration: %d %d %u %u ATE ver: %u SoC rev: %u\n", in tegra_tsensor_nvmem_setup()
510 struct tegra_tsensor_channel *tsc = &ts->ch[id]; in tegra_tsensor_register_channel()
511 unsigned int hw_id = ts->swap_channels ? !id : id; in tegra_tsensor_register_channel()
513 tsc->ts = ts; in tegra_tsensor_register_channel()
514 tsc->id = id; in tegra_tsensor_register_channel()
515 tsc->regs = ts->regs + 0x40 * (hw_id + 1); in tegra_tsensor_register_channel()
517 tsc->tzd = devm_thermal_of_zone_register(ts->dev, id, tsc, &ops); in tegra_tsensor_register_channel()
518 if (IS_ERR(tsc->tzd)) { in tegra_tsensor_register_channel()
519 if (PTR_ERR(tsc->tzd) != -ENODEV) in tegra_tsensor_register_channel()
520 return dev_err_probe(ts->dev, PTR_ERR(tsc->tzd), in tegra_tsensor_register_channel()
521 "failed to register thermal zone\n"); in tegra_tsensor_register_channel()
524 * It's okay if sensor isn't assigned to any thermal zone in tegra_tsensor_register_channel()
525 * in a device-tree. in tegra_tsensor_register_channel()
527 tsc->tzd = NULL; in tegra_tsensor_register_channel()
531 devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd); in tegra_tsensor_register_channel()
542 ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL); in tegra_tsensor_probe()
544 return -ENOMEM; in tegra_tsensor_probe()
550 ts->dev = &pdev->dev; in tegra_tsensor_probe()
553 ts->regs = devm_platform_ioremap_resource(pdev, 0); in tegra_tsensor_probe()
554 if (IS_ERR(ts->regs)) in tegra_tsensor_probe()
555 return PTR_ERR(ts->regs); in tegra_tsensor_probe()
557 ts->clk = devm_clk_get(&pdev->dev, NULL); in tegra_tsensor_probe()
558 if (IS_ERR(ts->clk)) in tegra_tsensor_probe()
559 return dev_err_probe(&pdev->dev, PTR_ERR(ts->clk), in tegra_tsensor_probe()
562 ts->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); in tegra_tsensor_probe()
563 if (IS_ERR(ts->rst)) in tegra_tsensor_probe()
564 return dev_err_probe(&pdev->dev, PTR_ERR(ts->rst), in tegra_tsensor_probe()
575 err = devm_add_action_or_reset(&pdev->dev, in tegra_tsensor_probe()
581 for (i = 0; i < ARRAY_SIZE(ts->ch); i++) { in tegra_tsensor_probe()
595 for (i = 0; i < ARRAY_SIZE(ts->ch); i++) { in tegra_tsensor_probe()
601 err = devm_request_threaded_irq(&pdev->dev, irq, NULL, in tegra_tsensor_probe()
605 return dev_err_probe(&pdev->dev, err, in tegra_tsensor_probe()
617 for (i = 0; i < ARRAY_SIZE(ts->ch); i++) { in tegra_tsensor_suspend()
630 while (i--) in tegra_tsensor_suspend()
646 for (i = 0; i < ARRAY_SIZE(ts->ch); i++) { in tegra_tsensor_resume()
661 { .compatible = "nvidia,tegra30-tsensor", },
669 .name = "tegra30-tsensor",
676 MODULE_DESCRIPTION("NVIDIA Tegra30 Thermal Sensor driver");