Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal

Pull thermal soc updates from Eduardo Valentin:

- thermal core has a new devm_* API for registering cooling devices. I
took the entire series, that is why you see changes on drivers/hwmon
in this pull (Guenter Roeck)

- rockchip thermal driver gains support to PX30 SoC (Elaine Zhang)

- the generic-adc thermal driver now considers the lookup table DT
property as optional (Jean-Francois Dagenais)

- Refactoring of tsens thermal driver (Amit Kucheria)

- Cleanups on cpu cooling driver (Daniel Lezcano)

- broadcom thermal driver dropped support to ACPI (Srinath Mannam)

- tegra thermal driver gains support to OC hw throttle and GPU throtle
(Wei Ni)

- Fixes in several thermal drivers.

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (59 commits)
hwmon: (pwm-fan) Use devm_thermal_of_cooling_device_register
hwmon: (npcm750-pwm-fan) Use devm_thermal_of_cooling_device_register
hwmon: (mlxreg-fan) Use devm_thermal_of_cooling_device_register
hwmon: (gpio-fan) Use devm_thermal_of_cooling_device_register
hwmon: (aspeed-pwm-tacho) Use devm_thermal_of_cooling_device_register
thermal: rcar_gen3_thermal: Fix to show correct trip points number
thermal: rcar_thermal: update calculation formula for R-Car Gen3 SoCs
thermal: cpu_cooling: Actually trace CPU load in thermal_power_cpu_get_power
thermal: rockchip: Support the PX30 SoC in thermal driver
dt-bindings: rockchip-thermal: Support the PX30 SoC compatible
thermal: rockchip: fix up the tsadc pinctrl setting error
thermal: broadcom: Remove ACPI support
thermal: Fix build error of missing devm_ioremap_resource on UM
thermal/drivers/cpu_cooling: Remove pointless field
thermal/drivers/cpu_cooling: Add Software Package Data Exchange (SPDX)
thermal/drivers/cpu_cooling: Fixup the header and copyright
thermal/drivers/cpu_cooling: Remove pointless test in power2state()
thermal: rcar_gen3_thermal: disable interrupt in .remove
thermal: rcar_gen3_thermal: fix interrupt type
thermal: Introduce devm_thermal_of_cooling_device_register
...

+2344 -610
+33
Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt
··· 1 + Amazon's Annapurna Labs Thermal Sensor 2 + 3 + Simple thermal device that allows temperature reading by a single MMIO 4 + transaction. 5 + 6 + Required properties: 7 + - compatible: "amazon,al-thermal". 8 + - reg: The physical base address and length of the sensor's registers. 9 + - #thermal-sensor-cells: Must be 1. See ./thermal.txt for a description. 10 + 11 + Example: 12 + thermal: thermal { 13 + compatible = "amazon,al-thermal"; 14 + reg = <0x0 0x05002860 0x0 0x1>; 15 + #thermal-sensor-cells = <0x1>; 16 + }; 17 + 18 + thermal-zones { 19 + thermal-z0 { 20 + polling-delay-passive = <250>; 21 + polling-delay = <1000>; 22 + thermal-sensors = <&thermal 0>; 23 + trips { 24 + critical { 25 + temperature = <105000>; 26 + hysteresis = <2000>; 27 + type = "critical"; 28 + }; 29 + }; 30 + 31 + }; 32 + }; 33 +
+57 -5
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
··· 52 52 Must set as following values: 53 53 TEGRA_SOCTHERM_THROT_LEVEL_LOW, TEGRA_SOCTHERM_THROT_LEVEL_MED 54 54 TEGRA_SOCTHERM_THROT_LEVEL_HIGH, TEGRA_SOCTHERM_THROT_LEVEL_NONE 55 + - nvidia,gpu-throt-level: This property is for Tegra124 and Tegra210. 56 + It is the level of pulse skippers, which used to throttle clock 57 + frequencies. It indicates gpu clock throttling depth and can be 58 + programmed to any of the following values which represent a throttling 59 + percentage: 60 + TEGRA_SOCTHERM_THROT_LEVEL_NONE (0%) 61 + TEGRA_SOCTHERM_THROT_LEVEL_LOW (50%), 62 + TEGRA_SOCTHERM_THROT_LEVEL_MED (75%), 63 + TEGRA_SOCTHERM_THROT_LEVEL_HIGH (85%). 55 64 - #cooling-cells: Should be 1. This cooling device only support on/off state. 56 65 See ./thermal.txt for a description of this property. 57 66 67 + Optional properties: The following properties are T210 specific and 68 + valid only for OCx throttle events. 69 + - nvidia,count-threshold: Specifies the number of OC events that are 70 + required for triggering an interrupt. Interrupts are not triggered if 71 + the property is missing. A value of 0 will interrupt on every OC alarm. 72 + - nvidia,polarity-active-low: Configures the polarity of the OC alaram 73 + signal. If present, this means assert low, otherwise assert high. 74 + - nvidia,alarm-filter: Number of clocks to filter event. When the filter 75 + expires (which means the OC event has not occurred for a long time), 76 + the counter is cleared and filter is rearmed. Default value is 0. 77 + - nvidia,throttle-period-us: Specifies the number of uSec for which 78 + throttling is engaged after the OC event is deasserted. Default value 79 + is 0. 80 + 81 + Optional properties: 82 + - nvidia,thermtrips : When present, this property specifies the temperature at 83 + which the soctherm hardware will assert the thermal trigger signal to the 84 + Power Management IC, which can be configured to reset or shutdown the device. 85 + It is an array of pairs where each pair represents a tsensor id followed by a 86 + temperature in milli Celcius. In the absence of this property the critical 87 + trip point will be used for thermtrip temperature. 88 + 58 89 Note: 59 - - the "critical" type trip points will be set to SOC_THERM hardware as the 60 - shut down temperature. Once the temperature of this thermal zone is higher 61 - than it, the system will be shutdown or reset by hardware. 90 + - the "critical" type trip points will be used to set the temperature at which 91 + the SOC_THERM hardware will assert a thermal trigger if the "nvidia,thermtrips" 92 + property is missing. When the thermtrips property is present, the breach of a 93 + critical trip point is reported back to the thermal framework to implement 94 + software shutdown. 95 + 62 96 - the "hot" type trip points will be set to SOC_THERM hardware as the throttle 63 97 temperature. Once the the temperature of this thermal zone is higher 64 98 than it, it will trigger the HW throttle event. ··· 113 79 114 80 #thermal-sensor-cells = <1>; 115 81 82 + nvidia,thermtrips = <TEGRA124_SOCTHERM_SENSOR_CPU 102500 83 + TEGRA124_SOCTHERM_SENSOR_GPU 103000>; 84 + 116 85 throttle-cfgs { 117 86 /* 118 87 * When the "heavy" cooling device triggered, 119 - * the HW will skip cpu clock's pulse in 85% depth 88 + * the HW will skip cpu clock's pulse in 85% depth, 89 + * skip gpu clock's pulse in 85% level 120 90 */ 121 91 throttle_heavy: heavy { 122 92 nvidia,priority = <100>; 123 93 nvidia,cpu-throt-percent = <85>; 94 + nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_HIGH>; 124 95 125 96 #cooling-cells = <1>; 126 97 }; 127 98 128 99 /* 129 100 * When the "light" cooling device triggered, 130 - * the HW will skip cpu clock's pulse in 50% depth 101 + * the HW will skip cpu clock's pulse in 50% depth, 102 + * skip gpu clock's pulse in 50% level 131 103 */ 132 104 throttle_light: light { 133 105 nvidia,priority = <80>; 134 106 nvidia,cpu-throt-percent = <50>; 107 + nvidia,gpu-throt-level = <TEGRA_SOCTHERM_THROT_LEVEL_LOW>; 135 108 136 109 #cooling-cells = <1>; 137 110 }; ··· 148 107 * arbiter will select the highest priority as the final throttle 149 108 * settings to skip cpu pulse. 150 109 */ 110 + 111 + throttle_oc1: oc1 { 112 + nvidia,priority = <50>; 113 + nvidia,polarity-active-low; 114 + nvidia,count-threshold = <100>; 115 + nvidia,alarm-filter = <5100000>; 116 + nvidia,throttle-period-us = <0>; 117 + nvidia,cpu-throt-percent = <75>; 118 + nvidia,gpu-throt-level = 119 + <TEGRA_SOCTHERM_THROT_LEVEL_MED>; 120 + }; 151 121 }; 152 122 }; 153 123
+14
Documentation/devicetree/bindings/thermal/qcom-tsens.txt
··· 6 6 - "qcom,msm8916-tsens" (MSM8916) 7 7 - "qcom,msm8974-tsens" (MSM8974) 8 8 - "qcom,msm8996-tsens" (MSM8996) 9 + - "qcom,qcs404-tsens", "qcom,tsens-v1" (QCS404) 9 10 - "qcom,msm8998-tsens", "qcom,tsens-v2" (MSM8998) 10 11 - "qcom,sdm845-tsens", "qcom,tsens-v2" (SDM845) 11 12 The generic "qcom,tsens-v2" property must be used as a fallback for any SoC 12 13 with version 2 of the TSENS IP. MSM8996 is the only exception because the 13 14 generic property did not exist when support was added. 15 + Similarly, the generic "qcom,tsens-v1" property must be used as a fallback for 16 + any SoC with version 1 of the TSENS IP. 14 17 15 18 - reg: Address range of the thermal registers. 16 19 New platforms containing v2.x.y of the TSENS IP must specify the SROT and TM ··· 40 37 reg = <0xc263000 0x1ff>, /* TM */ 41 38 <0xc222000 0x1ff>; /* SROT */ 42 39 #qcom,sensors = <13>; 40 + #thermal-sensor-cells = <1>; 41 + }; 42 + 43 + Example 3 (for any platform containing v1 of the TSENS IP): 44 + tsens: thermal-sensor@4a9000 { 45 + compatible = "qcom,qcs404-tsens", "qcom,tsens-v1"; 46 + reg = <0x004a9000 0x1000>, /* TM */ 47 + <0x004a8000 0x1000>; /* SROT */ 48 + nvmem-cells = <&tsens_caldata>; 49 + nvmem-cell-names = "calib"; 50 + #qcom,sensors = <10>; 43 51 #thermal-sensor-cells = <1>; 44 52 };
+1
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
··· 2 2 3 3 Required properties: 4 4 - compatible : should be "rockchip,<name>-tsadc" 5 + "rockchip,px30-tsadc": found on PX30 SoCs 5 6 "rockchip,rv1108-tsadc": found on RV1108 SoCs 6 7 "rockchip,rk3228-tsadc": found on RK3228 SoCs 7 8 "rockchip,rk3288-tsadc": found on RK3288 SoCs
+8 -2
Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
··· 8 8 Required properties: 9 9 =================== 10 10 - compatible: Must be "generic-adc-thermal". 11 + - #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description 12 + of this property. 13 + Optional properties: 14 + =================== 11 15 - temperature-lookup-table: Two dimensional array of Integer; lookup table 12 16 to map the relation between ADC value and 13 17 temperature. When ADC is read, the value is 14 18 looked up on the table to get the equivalent 15 19 temperature. 20 + 16 21 The first value of the each row of array is the 17 22 temperature in milliCelsius and second value of 18 23 the each row of array is the ADC read value. 19 - - #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description 20 - of this property. 24 + 25 + If not specified, driver assumes the ADC channel 26 + gives milliCelsius directly. 21 27 22 28 Example : 23 29 #include <dt-bindings/thermal/thermal.h>
+6
MAINTAINERS
··· 742 742 F: include/linux/altera_uart.h 743 743 F: include/linux/altera_jtaguart.h 744 744 745 + AMAZON ANNAPURNA LABS THERMAL MMIO DRIVER 746 + M: Talel Shenhar <talel@amazon.com> 747 + S: Maintained 748 + F: Documentation/devicetree/bindings/thermal/amazon,al-thermal.txt 749 + F: drivers/thermal/thermal_mmio.c 750 + 745 751 AMAZON ETHERNET DRIVERS 746 752 M: Netanel Belgazal <netanel@amazon.com> 747 753 R: Saeed Bishara <saeedb@amazon.com>
+2 -4
drivers/hwmon/aspeed-pwm-tacho.c
··· 830 830 } 831 831 snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%pOFn%d", child, pwm_port); 832 832 833 - cdev->tcdev = thermal_of_cooling_device_register(child, 834 - cdev->name, 835 - cdev, 836 - &aspeed_pwm_cool_ops); 833 + cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child, 834 + cdev->name, cdev, &aspeed_pwm_cool_ops); 837 835 if (IS_ERR(cdev->tcdev)) 838 836 return PTR_ERR(cdev->tcdev); 839 837
+9 -16
drivers/hwmon/gpio-fan.c
··· 498 498 }; 499 499 MODULE_DEVICE_TABLE(of, of_gpio_fan_match); 500 500 501 + static void gpio_fan_stop(void *data) 502 + { 503 + set_fan_speed(data, 0); 504 + } 505 + 501 506 static int gpio_fan_probe(struct platform_device *pdev) 502 507 { 503 508 int err; ··· 537 532 err = fan_ctrl_init(fan_data); 538 533 if (err) 539 534 return err; 535 + devm_add_action_or_reset(dev, gpio_fan_stop, fan_data); 540 536 } 541 537 542 538 /* Make this driver part of hwmon class. */ ··· 549 543 return PTR_ERR(fan_data->hwmon_dev); 550 544 551 545 /* Optional cooling device register for Device tree platforms */ 552 - fan_data->cdev = thermal_of_cooling_device_register(np, 553 - "gpio-fan", 554 - fan_data, 555 - &gpio_fan_cool_ops); 546 + fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np, 547 + "gpio-fan", fan_data, &gpio_fan_cool_ops); 556 548 557 549 dev_info(dev, "GPIO fan initialized\n"); 558 550 559 551 return 0; 560 552 } 561 553 562 - static int gpio_fan_remove(struct platform_device *pdev) 554 + static void gpio_fan_shutdown(struct platform_device *pdev) 563 555 { 564 556 struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); 565 557 566 - if (!IS_ERR(fan_data->cdev)) 567 - thermal_cooling_device_unregister(fan_data->cdev); 568 - 569 558 if (fan_data->gpios) 570 559 set_fan_speed(fan_data, 0); 571 - 572 - return 0; 573 - } 574 - 575 - static void gpio_fan_shutdown(struct platform_device *pdev) 576 - { 577 - gpio_fan_remove(pdev); 578 560 } 579 561 580 562 #ifdef CONFIG_PM_SLEEP ··· 596 602 597 603 static struct platform_driver gpio_fan_driver = { 598 604 .probe = gpio_fan_probe, 599 - .remove = gpio_fan_remove, 600 605 .shutdown = gpio_fan_shutdown, 601 606 .driver = { 602 607 .name = "gpio-fan",
+10 -21
drivers/hwmon/mlxreg-fan.c
··· 465 465 static int mlxreg_fan_probe(struct platform_device *pdev) 466 466 { 467 467 struct mlxreg_core_platform_data *pdata; 468 + struct device *dev = &pdev->dev; 468 469 struct mlxreg_fan *fan; 469 470 struct device *hwm; 470 471 int err; 471 472 472 - pdata = dev_get_platdata(&pdev->dev); 473 + pdata = dev_get_platdata(dev); 473 474 if (!pdata) { 474 - dev_err(&pdev->dev, "Failed to get platform data.\n"); 475 + dev_err(dev, "Failed to get platform data.\n"); 475 476 return -EINVAL; 476 477 } 477 478 478 - fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL); 479 + fan = devm_kzalloc(dev, sizeof(*fan), GFP_KERNEL); 479 480 if (!fan) 480 481 return -ENOMEM; 481 482 482 - fan->dev = &pdev->dev; 483 + fan->dev = dev; 483 484 fan->regmap = pdata->regmap; 484 - platform_set_drvdata(pdev, fan); 485 485 486 486 err = mlxreg_fan_config(fan, pdata); 487 487 if (err) 488 488 return err; 489 489 490 - hwm = devm_hwmon_device_register_with_info(&pdev->dev, "mlxreg_fan", 490 + hwm = devm_hwmon_device_register_with_info(dev, "mlxreg_fan", 491 491 fan, 492 492 &mlxreg_fan_hwmon_chip_info, 493 493 NULL); 494 494 if (IS_ERR(hwm)) { 495 - dev_err(&pdev->dev, "Failed to register hwmon device\n"); 495 + dev_err(dev, "Failed to register hwmon device\n"); 496 496 return PTR_ERR(hwm); 497 497 } 498 498 499 499 if (IS_REACHABLE(CONFIG_THERMAL)) { 500 - fan->cdev = thermal_cooling_device_register("mlxreg_fan", fan, 501 - &mlxreg_fan_cooling_ops); 500 + fan->cdev = devm_thermal_of_cooling_device_register(dev, 501 + NULL, "mlxreg_fan", fan, &mlxreg_fan_cooling_ops); 502 502 if (IS_ERR(fan->cdev)) { 503 - dev_err(&pdev->dev, "Failed to register cooling device\n"); 503 + dev_err(dev, "Failed to register cooling device\n"); 504 504 return PTR_ERR(fan->cdev); 505 505 } 506 506 } 507 - 508 - return 0; 509 - } 510 - 511 - static int mlxreg_fan_remove(struct platform_device *pdev) 512 - { 513 - struct mlxreg_fan *fan = platform_get_drvdata(pdev); 514 - 515 - if (IS_REACHABLE(CONFIG_THERMAL)) 516 - thermal_cooling_device_unregister(fan->cdev); 517 507 518 508 return 0; 519 509 } ··· 513 523 .name = "mlxreg-fan", 514 524 }, 515 525 .probe = mlxreg_fan_probe, 516 - .remove = mlxreg_fan_remove, 517 526 }; 518 527 519 528 module_platform_driver(mlxreg_fan_driver);
+2 -4
drivers/hwmon/npcm750-pwm-fan.c
··· 846 846 snprintf(cdev->name, THERMAL_NAME_LENGTH, "%pOFn%d", child, 847 847 pwm_port); 848 848 849 - cdev->tcdev = thermal_of_cooling_device_register(child, 850 - cdev->name, 851 - cdev, 852 - &npcm7xx_pwm_cool_ops); 849 + cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child, 850 + cdev->name, cdev, &npcm7xx_pwm_cool_ops); 853 851 if (IS_ERR(cdev->tcdev)) 854 852 return PTR_ERR(cdev->tcdev); 855 853
+38 -59
drivers/hwmon/pwm-fan.c
··· 273 273 return 0; 274 274 } 275 275 276 + static void pwm_fan_regulator_disable(void *data) 277 + { 278 + regulator_disable(data); 279 + } 280 + 281 + static void pwm_fan_pwm_disable(void *__ctx) 282 + { 283 + struct pwm_fan_ctx *ctx = __ctx; 284 + pwm_disable(ctx->pwm); 285 + del_timer_sync(&ctx->rpm_timer); 286 + } 287 + 276 288 static int pwm_fan_probe(struct platform_device *pdev) 277 289 { 278 290 struct thermal_cooling_device *cdev; 291 + struct device *dev = &pdev->dev; 279 292 struct pwm_fan_ctx *ctx; 280 293 struct device *hwmon; 281 294 int ret; 282 295 struct pwm_state state = { }; 283 296 u32 ppr = 2; 284 297 285 - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); 298 + ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 286 299 if (!ctx) 287 300 return -ENOMEM; 288 301 289 302 mutex_init(&ctx->lock); 290 303 291 - ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL); 304 + ctx->pwm = devm_of_pwm_get(dev, dev->of_node, NULL); 292 305 if (IS_ERR(ctx->pwm)) { 293 306 ret = PTR_ERR(ctx->pwm); 294 307 295 308 if (ret != -EPROBE_DEFER) 296 - dev_err(&pdev->dev, "Could not get PWM: %d\n", ret); 309 + dev_err(dev, "Could not get PWM: %d\n", ret); 297 310 298 311 return ret; 299 312 } ··· 317 304 if (ctx->irq == -EPROBE_DEFER) 318 305 return ctx->irq; 319 306 320 - ctx->reg_en = devm_regulator_get_optional(&pdev->dev, "fan"); 307 + ctx->reg_en = devm_regulator_get_optional(dev, "fan"); 321 308 if (IS_ERR(ctx->reg_en)) { 322 309 if (PTR_ERR(ctx->reg_en) != -ENODEV) 323 310 return PTR_ERR(ctx->reg_en); ··· 326 313 } else { 327 314 ret = regulator_enable(ctx->reg_en); 328 315 if (ret) { 329 - dev_err(&pdev->dev, 330 - "Failed to enable fan supply: %d\n", ret); 316 + dev_err(dev, "Failed to enable fan supply: %d\n", ret); 331 317 return ret; 332 318 } 319 + devm_add_action_or_reset(dev, pwm_fan_regulator_disable, 320 + ctx->reg_en); 333 321 } 334 322 335 323 ctx->pwm_value = MAX_PWM; ··· 342 328 343 329 ret = pwm_apply_state(ctx->pwm, &state); 344 330 if (ret) { 345 - dev_err(&pdev->dev, "Failed to configure PWM: %d\n", ret); 346 - goto err_reg_disable; 331 + dev_err(dev, "Failed to configure PWM: %d\n", ret); 332 + return ret; 347 333 } 348 - 349 334 timer_setup(&ctx->rpm_timer, sample_timer, 0); 335 + devm_add_action_or_reset(dev, pwm_fan_pwm_disable, ctx); 350 336 351 - of_property_read_u32(pdev->dev.of_node, "pulses-per-revolution", &ppr); 337 + of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr); 352 338 ctx->pulses_per_revolution = ppr; 353 339 if (!ctx->pulses_per_revolution) { 354 - dev_err(&pdev->dev, "pulses-per-revolution can't be zero.\n"); 355 - ret = -EINVAL; 356 - goto err_pwm_disable; 340 + dev_err(dev, "pulses-per-revolution can't be zero.\n"); 341 + return -EINVAL; 357 342 } 358 343 359 344 if (ctx->irq > 0) { 360 - ret = devm_request_irq(&pdev->dev, ctx->irq, pulse_handler, 0, 345 + ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0, 361 346 pdev->name, ctx); 362 347 if (ret) { 363 - dev_err(&pdev->dev, 364 - "Failed to request interrupt: %d\n", ret); 365 - goto err_pwm_disable; 348 + dev_err(dev, "Failed to request interrupt: %d\n", ret); 349 + return ret; 366 350 } 367 351 ctx->sample_start = ktime_get(); 368 352 mod_timer(&ctx->rpm_timer, jiffies + HZ); 369 353 } 370 354 371 - hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan", 355 + hwmon = devm_hwmon_device_register_with_groups(dev, "pwmfan", 372 356 ctx, pwm_fan_groups); 373 357 if (IS_ERR(hwmon)) { 374 - ret = PTR_ERR(hwmon); 375 - dev_err(&pdev->dev, 376 - "Failed to register hwmon device: %d\n", ret); 377 - goto err_del_timer; 358 + dev_err(dev, "Failed to register hwmon device\n"); 359 + return PTR_ERR(hwmon); 378 360 } 379 361 380 - ret = pwm_fan_of_get_cooling_data(&pdev->dev, ctx); 362 + ret = pwm_fan_of_get_cooling_data(dev, ctx); 381 363 if (ret) 382 - goto err_del_timer; 364 + return ret; 383 365 384 366 ctx->pwm_fan_state = ctx->pwm_fan_max_state; 385 367 if (IS_ENABLED(CONFIG_THERMAL)) { 386 - cdev = thermal_of_cooling_device_register(pdev->dev.of_node, 387 - "pwm-fan", ctx, 388 - &pwm_fan_cooling_ops); 368 + cdev = devm_thermal_of_cooling_device_register(dev, 369 + dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops); 389 370 if (IS_ERR(cdev)) { 390 371 ret = PTR_ERR(cdev); 391 - dev_err(&pdev->dev, 372 + dev_err(dev, 392 373 "Failed to register pwm-fan as cooling device: %d\n", 393 374 ret); 394 - goto err_del_timer; 375 + return ret; 395 376 } 396 377 ctx->cdev = cdev; 397 378 thermal_cdev_update(cdev); 398 379 } 399 - 400 - return 0; 401 - 402 - err_del_timer: 403 - del_timer_sync(&ctx->rpm_timer); 404 - 405 - err_pwm_disable: 406 - state.enabled = false; 407 - pwm_apply_state(ctx->pwm, &state); 408 - 409 - err_reg_disable: 410 - if (ctx->reg_en) 411 - regulator_disable(ctx->reg_en); 412 - 413 - return ret; 414 - } 415 - 416 - static int pwm_fan_remove(struct platform_device *pdev) 417 - { 418 - struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev); 419 - 420 - thermal_cooling_device_unregister(ctx->cdev); 421 - del_timer_sync(&ctx->rpm_timer); 422 - 423 - if (ctx->pwm_value) 424 - pwm_disable(ctx->pwm); 425 - 426 - if (ctx->reg_en) 427 - regulator_disable(ctx->reg_en); 428 380 429 381 return 0; 430 382 } ··· 460 480 461 481 static struct platform_driver pwm_fan_driver = { 462 482 .probe = pwm_fan_probe, 463 - .remove = pwm_fan_remove, 464 483 .driver = { 465 484 .name = "pwm-fan", 466 485 .pm = &pwm_fan_pm,
+11
drivers/thermal/Kconfig
··· 200 200 because userland can easily disable the thermal policy by simply 201 201 flooding this sysfs node with low temperature values. 202 202 203 + config THERMAL_MMIO 204 + tristate "Generic Thermal MMIO driver" 205 + depends on OF || COMPILE_TEST 206 + depends on HAS_IOMEM 207 + help 208 + This option enables the generic thermal MMIO driver that will use 209 + memory-mapped reads to get the temperature. Any HW/System that 210 + allows temperature reading by a single memory-mapped reading, be it 211 + register or shared memory, is a potential candidate to work with this 212 + driver. 213 + 203 214 config HISI_THERMAL 204 215 tristate "Hisilicon thermal driver" 205 216 depends on ARCH_HISI || COMPILE_TEST
+1
drivers/thermal/Makefile
··· 29 29 30 30 # platform thermal drivers 31 31 obj-y += broadcom/ 32 + obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o 32 33 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 33 34 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o 34 35 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
-8
drivers/thermal/broadcom/sr-thermal.c
··· 3 3 * Copyright (C) 2018 Broadcom 4 4 */ 5 5 6 - #include <linux/acpi.h> 7 6 #include <linux/module.h> 8 7 #include <linux/of_address.h> 9 8 #include <linux/platform_device.h> ··· 99 100 }; 100 101 MODULE_DEVICE_TABLE(of, sr_thermal_of_match); 101 102 102 - static const struct acpi_device_id sr_thermal_acpi_ids[] = { 103 - { .id = "BRCM0500" }, 104 - { /* sentinel */ } 105 - }; 106 - MODULE_DEVICE_TABLE(acpi, sr_thermal_acpi_ids); 107 - 108 103 static struct platform_driver sr_thermal_driver = { 109 104 .probe = sr_thermal_probe, 110 105 .driver = { 111 106 .name = "sr-thermal", 112 107 .of_match_table = sr_thermal_of_match, 113 - .acpi_match_table = ACPI_PTR(sr_thermal_acpi_ids), 114 108 }, 115 109 }; 116 110 module_platform_driver(sr_thermal_driver);
+7 -23
drivers/thermal/cpu_cooling.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 3 * linux/drivers/thermal/cpu_cooling.c 3 4 * 4 5 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) 5 - * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org> 6 6 * 7 - * Copyright (C) 2014 Viresh Kumar <viresh.kumar@linaro.org> 7 + * Copyright (C) 2012-2018 Linaro Limited. 8 8 * 9 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 - * This program is free software; you can redistribute it and/or modify 11 - * it under the terms of the GNU General Public License as published by 12 - * the Free Software Foundation; version 2 of the License. 9 + * Authors: Amit Daniel <amit.kachhap@linaro.org> 10 + * Viresh Kumar <viresh.kumar@linaro.org> 13 11 * 14 - * This program is distributed in the hope that it will be useful, but 15 - * WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 - * General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License along 20 - * with this program; if not, write to the Free Software Foundation, Inc., 21 - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 22 - * 23 - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 12 */ 25 13 #include <linux/module.h> 26 14 #include <linux/thermal.h> ··· 87 99 unsigned int clipped_freq; 88 100 unsigned int max_level; 89 101 struct freq_table *freq_table; /* In descending order */ 90 - struct thermal_cooling_device *cdev; 91 102 struct cpufreq_policy *policy; 92 103 struct list_head node; 93 104 struct time_in_idle *idle_time; ··· 194 207 195 208 dev = get_cpu_device(cpu); 196 209 if (unlikely(!dev)) { 197 - dev_warn(&cpufreq_cdev->cdev->device, 198 - "No cpu device for cpu %d\n", cpu); 210 + pr_warn("No cpu device for cpu %d\n", cpu); 199 211 return -ENODEV; 200 212 } 201 213 ··· 444 458 load = 0; 445 459 446 460 total_load += load; 447 - if (trace_thermal_power_cpu_limit_enabled() && load_cpu) 461 + if (load_cpu) 448 462 load_cpu[i] = load; 449 463 450 464 i++; ··· 527 541 struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; 528 542 struct cpufreq_policy *policy = cpufreq_cdev->policy; 529 543 530 - power = power > 0 ? power : 0; 531 544 last_load = cpufreq_cdev->last_load ?: 1; 532 545 normalised_power = (power * 100) / last_load; 533 546 target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power); ··· 677 692 goto remove_ida; 678 693 679 694 cpufreq_cdev->clipped_freq = cpufreq_cdev->freq_table[0].frequency; 680 - cpufreq_cdev->cdev = cdev; 681 695 682 696 mutex_lock(&cooling_list_lock); 683 697 /* Register the notifier for first cpufreq cooling device */ ··· 794 810 cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block, 795 811 CPUFREQ_POLICY_NOTIFIER); 796 812 797 - thermal_cooling_device_unregister(cpufreq_cdev->cdev); 813 + thermal_cooling_device_unregister(cdev); 798 814 ida_simple_remove(&cpufreq_ida, cpufreq_cdev->id); 799 815 kfree(cpufreq_cdev->idle_time); 800 816 kfree(cpufreq_cdev->freq_table);
+3
drivers/thermal/of-thermal.c
··· 5 5 * Copyright (C) 2013 Texas Instruments 6 6 * Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@ti.com> 7 7 */ 8 + 9 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 + 8 11 #include <linux/thermal.h> 9 12 #include <linux/slab.h> 10 13 #include <linux/types.h>
+3 -1
drivers/thermal/qcom/Makefile
··· 1 1 obj-$(CONFIG_QCOM_TSENS) += qcom_tsens.o 2 - qcom_tsens-y += tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-v2.o 2 + 3 + qcom_tsens-y += tsens.o tsens-common.o tsens-v0_1.o \ 4 + tsens-8960.o tsens-v2.o tsens-v1.o 3 5 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
-105
drivers/thermal/qcom/tsens-8916.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 - */ 5 - 6 - #include <linux/platform_device.h> 7 - #include "tsens.h" 8 - 9 - /* eeprom layout data for 8916 */ 10 - #define BASE0_MASK 0x0000007f 11 - #define BASE1_MASK 0xfe000000 12 - #define BASE0_SHIFT 0 13 - #define BASE1_SHIFT 25 14 - 15 - #define S0_P1_MASK 0x00000f80 16 - #define S1_P1_MASK 0x003e0000 17 - #define S2_P1_MASK 0xf8000000 18 - #define S3_P1_MASK 0x000003e0 19 - #define S4_P1_MASK 0x000f8000 20 - 21 - #define S0_P2_MASK 0x0001f000 22 - #define S1_P2_MASK 0x07c00000 23 - #define S2_P2_MASK 0x0000001f 24 - #define S3_P2_MASK 0x00007c00 25 - #define S4_P2_MASK 0x01f00000 26 - 27 - #define S0_P1_SHIFT 7 28 - #define S1_P1_SHIFT 17 29 - #define S2_P1_SHIFT 27 30 - #define S3_P1_SHIFT 5 31 - #define S4_P1_SHIFT 15 32 - 33 - #define S0_P2_SHIFT 12 34 - #define S1_P2_SHIFT 22 35 - #define S2_P2_SHIFT 0 36 - #define S3_P2_SHIFT 10 37 - #define S4_P2_SHIFT 20 38 - 39 - #define CAL_SEL_MASK 0xe0000000 40 - #define CAL_SEL_SHIFT 29 41 - 42 - static int calibrate_8916(struct tsens_device *tmdev) 43 - { 44 - int base0 = 0, base1 = 0, i; 45 - u32 p1[5], p2[5]; 46 - int mode = 0; 47 - u32 *qfprom_cdata, *qfprom_csel; 48 - 49 - qfprom_cdata = (u32 *)qfprom_read(tmdev->dev, "calib"); 50 - if (IS_ERR(qfprom_cdata)) 51 - return PTR_ERR(qfprom_cdata); 52 - 53 - qfprom_csel = (u32 *)qfprom_read(tmdev->dev, "calib_sel"); 54 - if (IS_ERR(qfprom_csel)) 55 - return PTR_ERR(qfprom_csel); 56 - 57 - mode = (qfprom_csel[0] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; 58 - dev_dbg(tmdev->dev, "calibration mode is %d\n", mode); 59 - 60 - switch (mode) { 61 - case TWO_PT_CALIB: 62 - base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT; 63 - p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; 64 - p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; 65 - p2[2] = (qfprom_cdata[1] & S2_P2_MASK) >> S2_P2_SHIFT; 66 - p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; 67 - p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; 68 - for (i = 0; i < tmdev->num_sensors; i++) 69 - p2[i] = ((base1 + p2[i]) << 3); 70 - /* Fall through */ 71 - case ONE_PT_CALIB2: 72 - base0 = (qfprom_cdata[0] & BASE0_MASK); 73 - p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; 74 - p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; 75 - p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; 76 - p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; 77 - p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; 78 - for (i = 0; i < tmdev->num_sensors; i++) 79 - p1[i] = (((base0) + p1[i]) << 3); 80 - break; 81 - default: 82 - for (i = 0; i < tmdev->num_sensors; i++) { 83 - p1[i] = 500; 84 - p2[i] = 780; 85 - } 86 - break; 87 - } 88 - 89 - compute_intercept_slope(tmdev, p1, p2, mode); 90 - 91 - return 0; 92 - } 93 - 94 - static const struct tsens_ops ops_8916 = { 95 - .init = init_common, 96 - .calibrate = calibrate_8916, 97 - .get_temp = get_temp_common, 98 - }; 99 - 100 - const struct tsens_data data_8916 = { 101 - .num_sensors = 5, 102 - .ops = &ops_8916, 103 - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 }, 104 - .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, 105 - };
+42 -42
drivers/thermal/qcom/tsens-8960.c
··· 56 56 #define TRDY_MASK BIT(7) 57 57 #define TIMEOUT_US 100 58 58 59 - static int suspend_8960(struct tsens_device *tmdev) 59 + static int suspend_8960(struct tsens_priv *priv) 60 60 { 61 61 int ret; 62 62 unsigned int mask; 63 - struct regmap *map = tmdev->tm_map; 63 + struct regmap *map = priv->tm_map; 64 64 65 - ret = regmap_read(map, THRESHOLD_ADDR, &tmdev->ctx.threshold); 65 + ret = regmap_read(map, THRESHOLD_ADDR, &priv->ctx.threshold); 66 66 if (ret) 67 67 return ret; 68 68 69 - ret = regmap_read(map, CNTL_ADDR, &tmdev->ctx.control); 69 + ret = regmap_read(map, CNTL_ADDR, &priv->ctx.control); 70 70 if (ret) 71 71 return ret; 72 72 73 - if (tmdev->num_sensors > 1) 73 + if (priv->num_sensors > 1) 74 74 mask = SLP_CLK_ENA | EN; 75 75 else 76 76 mask = SLP_CLK_ENA_8660 | EN; ··· 82 82 return 0; 83 83 } 84 84 85 - static int resume_8960(struct tsens_device *tmdev) 85 + static int resume_8960(struct tsens_priv *priv) 86 86 { 87 87 int ret; 88 - struct regmap *map = tmdev->tm_map; 88 + struct regmap *map = priv->tm_map; 89 89 90 90 ret = regmap_update_bits(map, CNTL_ADDR, SW_RST, SW_RST); 91 91 if (ret) ··· 95 95 * Separate CONFIG restore is not needed only for 8660 as 96 96 * config is part of CTRL Addr and its restored as such 97 97 */ 98 - if (tmdev->num_sensors > 1) { 98 + if (priv->num_sensors > 1) { 99 99 ret = regmap_update_bits(map, CONFIG_ADDR, CONFIG_MASK, CONFIG); 100 100 if (ret) 101 101 return ret; 102 102 } 103 103 104 - ret = regmap_write(map, THRESHOLD_ADDR, tmdev->ctx.threshold); 104 + ret = regmap_write(map, THRESHOLD_ADDR, priv->ctx.threshold); 105 105 if (ret) 106 106 return ret; 107 107 108 - ret = regmap_write(map, CNTL_ADDR, tmdev->ctx.control); 108 + ret = regmap_write(map, CNTL_ADDR, priv->ctx.control); 109 109 if (ret) 110 110 return ret; 111 111 112 112 return 0; 113 113 } 114 114 115 - static int enable_8960(struct tsens_device *tmdev, int id) 115 + static int enable_8960(struct tsens_priv *priv, int id) 116 116 { 117 117 int ret; 118 118 u32 reg, mask; 119 119 120 - ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg); 120 + ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg); 121 121 if (ret) 122 122 return ret; 123 123 124 124 mask = BIT(id + SENSOR0_SHIFT); 125 - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg | SW_RST); 125 + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg | SW_RST); 126 126 if (ret) 127 127 return ret; 128 128 129 - if (tmdev->num_sensors > 1) 129 + if (priv->num_sensors > 1) 130 130 reg |= mask | SLP_CLK_ENA | EN; 131 131 else 132 132 reg |= mask | SLP_CLK_ENA_8660 | EN; 133 133 134 - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg); 134 + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg); 135 135 if (ret) 136 136 return ret; 137 137 138 138 return 0; 139 139 } 140 140 141 - static void disable_8960(struct tsens_device *tmdev) 141 + static void disable_8960(struct tsens_priv *priv) 142 142 { 143 143 int ret; 144 144 u32 reg_cntl; 145 145 u32 mask; 146 146 147 - mask = GENMASK(tmdev->num_sensors - 1, 0); 147 + mask = GENMASK(priv->num_sensors - 1, 0); 148 148 mask <<= SENSOR0_SHIFT; 149 149 mask |= EN; 150 150 151 - ret = regmap_read(tmdev->tm_map, CNTL_ADDR, &reg_cntl); 151 + ret = regmap_read(priv->tm_map, CNTL_ADDR, &reg_cntl); 152 152 if (ret) 153 153 return; 154 154 155 155 reg_cntl &= ~mask; 156 156 157 - if (tmdev->num_sensors > 1) 157 + if (priv->num_sensors > 1) 158 158 reg_cntl &= ~SLP_CLK_ENA; 159 159 else 160 160 reg_cntl &= ~SLP_CLK_ENA_8660; 161 161 162 - regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); 162 + regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 163 163 } 164 164 165 - static int init_8960(struct tsens_device *tmdev) 165 + static int init_8960(struct tsens_priv *priv) 166 166 { 167 167 int ret, i; 168 168 u32 reg_cntl; 169 169 170 - tmdev->tm_map = dev_get_regmap(tmdev->dev, NULL); 171 - if (!tmdev->tm_map) 170 + priv->tm_map = dev_get_regmap(priv->dev, NULL); 171 + if (!priv->tm_map) 172 172 return -ENODEV; 173 173 174 174 /* ··· 177 177 * but the control registers stay in the same place, i.e 178 178 * directly after the first 5 status registers. 179 179 */ 180 - for (i = 0; i < tmdev->num_sensors; i++) { 180 + for (i = 0; i < priv->num_sensors; i++) { 181 181 if (i >= 5) 182 - tmdev->sensor[i].status = S0_STATUS_ADDR + 40; 183 - tmdev->sensor[i].status += i * 4; 182 + priv->sensor[i].status = S0_STATUS_ADDR + 40; 183 + priv->sensor[i].status += i * 4; 184 184 } 185 185 186 186 reg_cntl = SW_RST; 187 - ret = regmap_update_bits(tmdev->tm_map, CNTL_ADDR, SW_RST, reg_cntl); 187 + ret = regmap_update_bits(priv->tm_map, CNTL_ADDR, SW_RST, reg_cntl); 188 188 if (ret) 189 189 return ret; 190 190 191 - if (tmdev->num_sensors > 1) { 191 + if (priv->num_sensors > 1) { 192 192 reg_cntl |= SLP_CLK_ENA | (MEASURE_PERIOD << 18); 193 193 reg_cntl &= ~SW_RST; 194 - ret = regmap_update_bits(tmdev->tm_map, CONFIG_ADDR, 194 + ret = regmap_update_bits(priv->tm_map, CONFIG_ADDR, 195 195 CONFIG_MASK, CONFIG); 196 196 } else { 197 197 reg_cntl |= SLP_CLK_ENA_8660 | (MEASURE_PERIOD << 16); ··· 199 199 reg_cntl |= CONFIG_8660 << CONFIG_SHIFT_8660; 200 200 } 201 201 202 - reg_cntl |= GENMASK(tmdev->num_sensors - 1, 0) << SENSOR0_SHIFT; 203 - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); 202 + reg_cntl |= GENMASK(priv->num_sensors - 1, 0) << SENSOR0_SHIFT; 203 + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 204 204 if (ret) 205 205 return ret; 206 206 207 207 reg_cntl |= EN; 208 - ret = regmap_write(tmdev->tm_map, CNTL_ADDR, reg_cntl); 208 + ret = regmap_write(priv->tm_map, CNTL_ADDR, reg_cntl); 209 209 if (ret) 210 210 return ret; 211 211 212 212 return 0; 213 213 } 214 214 215 - static int calibrate_8960(struct tsens_device *tmdev) 215 + static int calibrate_8960(struct tsens_priv *priv) 216 216 { 217 217 int i; 218 218 char *data; 219 219 220 - ssize_t num_read = tmdev->num_sensors; 221 - struct tsens_sensor *s = tmdev->sensor; 220 + ssize_t num_read = priv->num_sensors; 221 + struct tsens_sensor *s = priv->sensor; 222 222 223 - data = qfprom_read(tmdev->dev, "calib"); 223 + data = qfprom_read(priv->dev, "calib"); 224 224 if (IS_ERR(data)) 225 - data = qfprom_read(tmdev->dev, "calib_backup"); 225 + data = qfprom_read(priv->dev, "calib_backup"); 226 226 if (IS_ERR(data)) 227 227 return PTR_ERR(data); 228 228 ··· 243 243 return adc_code * slope + offset; 244 244 } 245 245 246 - static int get_temp_8960(struct tsens_device *tmdev, int id, int *temp) 246 + static int get_temp_8960(struct tsens_priv *priv, int id, int *temp) 247 247 { 248 248 int ret; 249 249 u32 code, trdy; 250 - const struct tsens_sensor *s = &tmdev->sensor[id]; 250 + const struct tsens_sensor *s = &priv->sensor[id]; 251 251 unsigned long timeout; 252 252 253 253 timeout = jiffies + usecs_to_jiffies(TIMEOUT_US); 254 254 do { 255 - ret = regmap_read(tmdev->tm_map, INT_STATUS_ADDR, &trdy); 255 + ret = regmap_read(priv->tm_map, INT_STATUS_ADDR, &trdy); 256 256 if (ret) 257 257 return ret; 258 258 if (!(trdy & TRDY_MASK)) 259 259 continue; 260 - ret = regmap_read(tmdev->tm_map, s->status, &code); 260 + ret = regmap_read(priv->tm_map, s->status, &code); 261 261 if (ret) 262 262 return ret; 263 263 *temp = code_to_mdegC(code, s); ··· 277 277 .resume = resume_8960, 278 278 }; 279 279 280 - const struct tsens_data data_8960 = { 280 + const struct tsens_plat_data data_8960 = { 281 281 .num_sensors = 11, 282 282 .ops = &ops_8960, 283 283 };
+156 -10
drivers/thermal/qcom/tsens-8974.c drivers/thermal/qcom/tsens-v0_1.c
··· 6 6 #include <linux/platform_device.h> 7 7 #include "tsens.h" 8 8 9 + /* ----- SROT ------ */ 10 + #define SROT_CTRL_OFF 0x0000 11 + 12 + /* ----- TM ------ */ 13 + #define TM_INT_EN_OFF 0x0000 14 + #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 15 + #define TM_Sn_STATUS_OFF 0x0030 16 + #define TM_TRDY_OFF 0x005c 17 + 18 + /* eeprom layout data for 8916 */ 19 + #define MSM8916_BASE0_MASK 0x0000007f 20 + #define MSM8916_BASE1_MASK 0xfe000000 21 + #define MSM8916_BASE0_SHIFT 0 22 + #define MSM8916_BASE1_SHIFT 25 23 + 24 + #define MSM8916_S0_P1_MASK 0x00000f80 25 + #define MSM8916_S1_P1_MASK 0x003e0000 26 + #define MSM8916_S2_P1_MASK 0xf8000000 27 + #define MSM8916_S3_P1_MASK 0x000003e0 28 + #define MSM8916_S4_P1_MASK 0x000f8000 29 + 30 + #define MSM8916_S0_P2_MASK 0x0001f000 31 + #define MSM8916_S1_P2_MASK 0x07c00000 32 + #define MSM8916_S2_P2_MASK 0x0000001f 33 + #define MSM8916_S3_P2_MASK 0x00007c00 34 + #define MSM8916_S4_P2_MASK 0x01f00000 35 + 36 + #define MSM8916_S0_P1_SHIFT 7 37 + #define MSM8916_S1_P1_SHIFT 17 38 + #define MSM8916_S2_P1_SHIFT 27 39 + #define MSM8916_S3_P1_SHIFT 5 40 + #define MSM8916_S4_P1_SHIFT 15 41 + 42 + #define MSM8916_S0_P2_SHIFT 12 43 + #define MSM8916_S1_P2_SHIFT 22 44 + #define MSM8916_S2_P2_SHIFT 0 45 + #define MSM8916_S3_P2_SHIFT 10 46 + #define MSM8916_S4_P2_SHIFT 20 47 + 48 + #define MSM8916_CAL_SEL_MASK 0xe0000000 49 + #define MSM8916_CAL_SEL_SHIFT 29 50 + 9 51 /* eeprom layout data for 8974 */ 10 52 #define BASE1_MASK 0xff 11 53 #define S0_P1_MASK 0x3f00 ··· 133 91 134 92 #define BIT_APPEND 0x3 135 93 136 - static int calibrate_8974(struct tsens_device *tmdev) 94 + static int calibrate_8916(struct tsens_priv *priv) 95 + { 96 + int base0 = 0, base1 = 0, i; 97 + u32 p1[5], p2[5]; 98 + int mode = 0; 99 + u32 *qfprom_cdata, *qfprom_csel; 100 + 101 + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 102 + if (IS_ERR(qfprom_cdata)) 103 + return PTR_ERR(qfprom_cdata); 104 + 105 + qfprom_csel = (u32 *)qfprom_read(priv->dev, "calib_sel"); 106 + if (IS_ERR(qfprom_csel)) 107 + return PTR_ERR(qfprom_csel); 108 + 109 + mode = (qfprom_csel[0] & MSM8916_CAL_SEL_MASK) >> MSM8916_CAL_SEL_SHIFT; 110 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 111 + 112 + switch (mode) { 113 + case TWO_PT_CALIB: 114 + base1 = (qfprom_cdata[1] & MSM8916_BASE1_MASK) >> MSM8916_BASE1_SHIFT; 115 + p2[0] = (qfprom_cdata[0] & MSM8916_S0_P2_MASK) >> MSM8916_S0_P2_SHIFT; 116 + p2[1] = (qfprom_cdata[0] & MSM8916_S1_P2_MASK) >> MSM8916_S1_P2_SHIFT; 117 + p2[2] = (qfprom_cdata[1] & MSM8916_S2_P2_MASK) >> MSM8916_S2_P2_SHIFT; 118 + p2[3] = (qfprom_cdata[1] & MSM8916_S3_P2_MASK) >> MSM8916_S3_P2_SHIFT; 119 + p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; 120 + for (i = 0; i < priv->num_sensors; i++) 121 + p2[i] = ((base1 + p2[i]) << 3); 122 + /* Fall through */ 123 + case ONE_PT_CALIB2: 124 + base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); 125 + p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; 126 + p1[1] = (qfprom_cdata[0] & MSM8916_S1_P1_MASK) >> MSM8916_S1_P1_SHIFT; 127 + p1[2] = (qfprom_cdata[0] & MSM8916_S2_P1_MASK) >> MSM8916_S2_P1_SHIFT; 128 + p1[3] = (qfprom_cdata[1] & MSM8916_S3_P1_MASK) >> MSM8916_S3_P1_SHIFT; 129 + p1[4] = (qfprom_cdata[1] & MSM8916_S4_P1_MASK) >> MSM8916_S4_P1_SHIFT; 130 + for (i = 0; i < priv->num_sensors; i++) 131 + p1[i] = (((base0) + p1[i]) << 3); 132 + break; 133 + default: 134 + for (i = 0; i < priv->num_sensors; i++) { 135 + p1[i] = 500; 136 + p2[i] = 780; 137 + } 138 + break; 139 + } 140 + 141 + compute_intercept_slope(priv, p1, p2, mode); 142 + 143 + return 0; 144 + } 145 + 146 + static int calibrate_8974(struct tsens_priv *priv) 137 147 { 138 148 int base1 = 0, base2 = 0, i; 139 149 u32 p1[11], p2[11]; ··· 193 99 u32 *calib, *bkp; 194 100 u32 calib_redun_sel; 195 101 196 - calib = (u32 *)qfprom_read(tmdev->dev, "calib"); 102 + calib = (u32 *)qfprom_read(priv->dev, "calib"); 197 103 if (IS_ERR(calib)) 198 104 return PTR_ERR(calib); 199 105 200 - bkp = (u32 *)qfprom_read(tmdev->dev, "calib_backup"); 106 + bkp = (u32 *)qfprom_read(priv->dev, "calib_backup"); 201 107 if (IS_ERR(bkp)) 202 108 return PTR_ERR(bkp); 203 109 ··· 278 184 279 185 switch (mode) { 280 186 case ONE_PT_CALIB: 281 - for (i = 0; i < tmdev->num_sensors; i++) 187 + for (i = 0; i < priv->num_sensors; i++) 282 188 p1[i] += (base1 << 2) | BIT_APPEND; 283 189 break; 284 190 case TWO_PT_CALIB: 285 - for (i = 0; i < tmdev->num_sensors; i++) { 191 + for (i = 0; i < priv->num_sensors; i++) { 286 192 p2[i] += base2; 287 193 p2[i] <<= 2; 288 194 p2[i] |= BIT_APPEND; 289 195 } 290 196 /* Fall through */ 291 197 case ONE_PT_CALIB2: 292 - for (i = 0; i < tmdev->num_sensors; i++) { 198 + for (i = 0; i < priv->num_sensors; i++) { 293 199 p1[i] += base1; 294 200 p1[i] <<= 2; 295 201 p1[i] |= BIT_APPEND; 296 202 } 297 203 break; 298 204 default: 299 - for (i = 0; i < tmdev->num_sensors; i++) 205 + for (i = 0; i < priv->num_sensors; i++) 300 206 p2[i] = 780; 301 207 p1[0] = 502; 302 208 p1[1] = 509; ··· 312 218 break; 313 219 } 314 220 315 - compute_intercept_slope(tmdev, p1, p2, mode); 221 + compute_intercept_slope(priv, p1, p2, mode); 316 222 317 223 return 0; 318 224 } 225 + 226 + /* v0.1: 8916, 8974 */ 227 + 228 + static const struct tsens_features tsens_v0_1_feat = { 229 + .ver_major = VER_0_1, 230 + .crit_int = 0, 231 + .adc = 1, 232 + .srot_split = 1, 233 + .max_sensors = 11, 234 + }; 235 + 236 + static const struct reg_field tsens_v0_1_regfields[MAX_REGFIELDS] = { 237 + /* ----- SROT ------ */ 238 + /* No VERSION information */ 239 + 240 + /* CTRL_OFFSET */ 241 + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), 242 + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), 243 + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13), 244 + 245 + /* ----- TM ------ */ 246 + /* INTERRUPT ENABLE */ 247 + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), 248 + 249 + /* Sn_STATUS */ 250 + REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), 251 + /* No VALID field on v0.1 */ 252 + REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), 253 + REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), 254 + REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), 255 + /* No CRITICAL field on v0.1 */ 256 + REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), 257 + 258 + /* TRDY: 1=ready, 0=in progress */ 259 + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 260 + }; 261 + 262 + static const struct tsens_ops ops_8916 = { 263 + .init = init_common, 264 + .calibrate = calibrate_8916, 265 + .get_temp = get_temp_common, 266 + }; 267 + 268 + const struct tsens_plat_data data_8916 = { 269 + .num_sensors = 5, 270 + .ops = &ops_8916, 271 + .hw_ids = (unsigned int []){0, 1, 2, 4, 5 }, 272 + 273 + .feat = &tsens_v0_1_feat, 274 + .fields = tsens_v0_1_regfields, 275 + }; 319 276 320 277 static const struct tsens_ops ops_8974 = { 321 278 .init = init_common, ··· 374 229 .get_temp = get_temp_common, 375 230 }; 376 231 377 - const struct tsens_data data_8974 = { 232 + const struct tsens_plat_data data_8974 = { 378 233 .num_sensors = 11, 379 234 .ops = &ops_8974, 380 - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x0 }, 235 + .feat = &tsens_v0_1_feat, 236 + .fields = tsens_v0_1_regfields, 381 237 };
+113 -48
drivers/thermal/qcom/tsens-common.c
··· 12 12 #include <linux/regmap.h> 13 13 #include "tsens.h" 14 14 15 - /* SROT */ 16 - #define TSENS_EN BIT(0) 17 - 18 - /* TM */ 19 - #define STATUS_OFFSET 0x30 20 - #define SN_ADDR_OFFSET 0x4 21 - #define SN_ST_TEMP_MASK 0x3ff 22 - #define CAL_DEGC_PT1 30 23 - #define CAL_DEGC_PT2 120 24 - #define SLOPE_FACTOR 1000 25 - #define SLOPE_DEFAULT 3200 26 - 27 15 char *qfprom_read(struct device *dev, const char *cname) 28 16 { 29 17 struct nvmem_cell *cell; ··· 34 46 * and offset values are derived from tz->tzp->slope and tz->tzp->offset 35 47 * resp. 36 48 */ 37 - void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1, 49 + void compute_intercept_slope(struct tsens_priv *priv, u32 *p1, 38 50 u32 *p2, u32 mode) 39 51 { 40 52 int i; 41 53 int num, den; 42 54 43 - for (i = 0; i < tmdev->num_sensors; i++) { 44 - dev_dbg(tmdev->dev, 55 + for (i = 0; i < priv->num_sensors; i++) { 56 + dev_dbg(priv->dev, 45 57 "sensor%d - data_point1:%#x data_point2:%#x\n", 46 58 i, p1[i], p2[i]); 47 59 48 - tmdev->sensor[i].slope = SLOPE_DEFAULT; 60 + priv->sensor[i].slope = SLOPE_DEFAULT; 49 61 if (mode == TWO_PT_CALIB) { 50 62 /* 51 63 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/ ··· 54 66 num = p2[i] - p1[i]; 55 67 num *= SLOPE_FACTOR; 56 68 den = CAL_DEGC_PT2 - CAL_DEGC_PT1; 57 - tmdev->sensor[i].slope = num / den; 69 + priv->sensor[i].slope = num / den; 58 70 } 59 71 60 - tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - 72 + priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - 61 73 (CAL_DEGC_PT1 * 62 - tmdev->sensor[i].slope); 63 - dev_dbg(tmdev->dev, "offset:%d\n", tmdev->sensor[i].offset); 74 + priv->sensor[i].slope); 75 + dev_dbg(priv->dev, "offset:%d\n", priv->sensor[i].offset); 64 76 } 77 + } 78 + 79 + bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id) 80 + { 81 + u32 val; 82 + int ret; 83 + 84 + if ((hw_id > (priv->num_sensors - 1)) || (hw_id < 0)) 85 + return -EINVAL; 86 + ret = regmap_field_read(priv->rf[SENSOR_EN], &val); 87 + if (ret) 88 + return ret; 89 + 90 + return val & (1 << hw_id); 65 91 } 66 92 67 93 static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s) ··· 97 95 return degc; 98 96 } 99 97 100 - int get_temp_common(struct tsens_device *tmdev, int id, int *temp) 98 + int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp) 101 99 { 102 - struct tsens_sensor *s = &tmdev->sensor[id]; 103 - u32 code; 104 - unsigned int status_reg; 105 - int last_temp = 0, ret; 100 + struct tsens_sensor *s = &priv->sensor[i]; 101 + u32 temp_idx = LAST_TEMP_0 + s->hw_id; 102 + u32 valid_idx = VALID_0 + s->hw_id; 103 + u32 last_temp = 0, valid, mask; 104 + int ret; 106 105 107 - status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * SN_ADDR_OFFSET; 108 - ret = regmap_read(tmdev->tm_map, status_reg, &code); 106 + ret = regmap_field_read(priv->rf[valid_idx], &valid); 109 107 if (ret) 110 108 return ret; 111 - last_temp = code & SN_ST_TEMP_MASK; 109 + while (!valid) { 110 + /* Valid bit is 0 for 6 AHB clock cycles. 111 + * At 19.2MHz, 1 AHB clock is ~60ns. 112 + * We should enter this loop very, very rarely. 113 + */ 114 + ndelay(400); 115 + ret = regmap_field_read(priv->rf[valid_idx], &valid); 116 + if (ret) 117 + return ret; 118 + } 119 + 120 + /* Valid bit is set, OK to read the temperature */ 121 + ret = regmap_field_read(priv->rf[temp_idx], &last_temp); 122 + if (ret) 123 + return ret; 124 + 125 + if (priv->feat->adc) { 126 + /* Convert temperature from ADC code to milliCelsius */ 127 + *temp = code_to_degc(last_temp, s) * 1000; 128 + } else { 129 + mask = GENMASK(priv->fields[LAST_TEMP_0].msb, 130 + priv->fields[LAST_TEMP_0].lsb); 131 + /* Convert temperature from deciCelsius to milliCelsius */ 132 + *temp = sign_extend32(last_temp, fls(mask) - 1) * 100; 133 + } 134 + 135 + return 0; 136 + } 137 + 138 + int get_temp_common(struct tsens_priv *priv, int i, int *temp) 139 + { 140 + struct tsens_sensor *s = &priv->sensor[i]; 141 + int last_temp = 0, ret; 142 + 143 + ret = regmap_field_read(priv->rf[LAST_TEMP_0 + s->hw_id], &last_temp); 144 + if (ret) 145 + return ret; 112 146 113 147 *temp = code_to_degc(last_temp, s) * 1000; 114 148 ··· 165 127 .reg_stride = 4, 166 128 }; 167 129 168 - int __init init_common(struct tsens_device *tmdev) 130 + int __init init_common(struct tsens_priv *priv) 169 131 { 170 132 void __iomem *tm_base, *srot_base; 133 + struct device *dev = priv->dev; 171 134 struct resource *res; 172 - u32 code; 173 - int ret; 174 - struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node); 175 - u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET]; 135 + u32 enabled; 136 + int ret, i, j; 137 + struct platform_device *op = of_find_device_by_node(priv->dev->of_node); 176 138 177 139 if (!op) 178 140 return -EINVAL; 179 141 180 142 if (op->num_resources > 1) { 181 143 /* DT with separate SROT and TM address space */ 182 - tmdev->tm_offset = 0; 144 + priv->tm_offset = 0; 183 145 res = platform_get_resource(op, IORESOURCE_MEM, 1); 184 146 srot_base = devm_ioremap_resource(&op->dev, res); 185 147 if (IS_ERR(srot_base)) { ··· 187 149 goto err_put_device; 188 150 } 189 151 190 - tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base, 152 + priv->srot_map = devm_regmap_init_mmio(dev, srot_base, 191 153 &tsens_srot_config); 192 - if (IS_ERR(tmdev->srot_map)) { 193 - ret = PTR_ERR(tmdev->srot_map); 154 + if (IS_ERR(priv->srot_map)) { 155 + ret = PTR_ERR(priv->srot_map); 194 156 goto err_put_device; 195 157 } 196 - 197 158 } else { 198 159 /* old DTs where SROT and TM were in a contiguous 2K block */ 199 - tmdev->tm_offset = 0x1000; 160 + priv->tm_offset = 0x1000; 200 161 } 201 162 202 163 res = platform_get_resource(op, IORESOURCE_MEM, 0); ··· 205 168 goto err_put_device; 206 169 } 207 170 208 - tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config); 209 - if (IS_ERR(tmdev->tm_map)) { 210 - ret = PTR_ERR(tmdev->tm_map); 171 + priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config); 172 + if (IS_ERR(priv->tm_map)) { 173 + ret = PTR_ERR(priv->tm_map); 211 174 goto err_put_device; 212 175 } 213 176 214 - if (tmdev->srot_map) { 215 - ret = regmap_read(tmdev->srot_map, ctrl_offset, &code); 216 - if (ret) 177 + priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map, 178 + priv->fields[TSENS_EN]); 179 + if (IS_ERR(priv->rf[TSENS_EN])) { 180 + ret = PTR_ERR(priv->rf[TSENS_EN]); 181 + goto err_put_device; 182 + } 183 + ret = regmap_field_read(priv->rf[TSENS_EN], &enabled); 184 + if (ret) 185 + goto err_put_device; 186 + if (!enabled) { 187 + dev_err(dev, "tsens device is not enabled\n"); 188 + ret = -ENODEV; 189 + goto err_put_device; 190 + } 191 + 192 + priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map, 193 + priv->fields[SENSOR_EN]); 194 + if (IS_ERR(priv->rf[SENSOR_EN])) { 195 + ret = PTR_ERR(priv->rf[SENSOR_EN]); 196 + goto err_put_device; 197 + } 198 + /* now alloc regmap_fields in tm_map */ 199 + for (i = 0, j = LAST_TEMP_0; i < priv->feat->max_sensors; i++, j++) { 200 + priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, 201 + priv->fields[j]); 202 + if (IS_ERR(priv->rf[j])) { 203 + ret = PTR_ERR(priv->rf[j]); 217 204 goto err_put_device; 218 - if (!(code & TSENS_EN)) { 219 - dev_err(tmdev->dev, "tsens device is not enabled\n"); 220 - ret = -ENODEV; 205 + } 206 + } 207 + for (i = 0, j = VALID_0; i < priv->feat->max_sensors; i++, j++) { 208 + priv->rf[j] = devm_regmap_field_alloc(dev, priv->tm_map, 209 + priv->fields[j]); 210 + if (IS_ERR(priv->rf[j])) { 211 + ret = PTR_ERR(priv->rf[j]); 221 212 goto err_put_device; 222 213 } 223 214 }
+193
drivers/thermal/qcom/tsens-v1.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2019, Linaro Limited 4 + */ 5 + 6 + #include <linux/bitops.h> 7 + #include <linux/regmap.h> 8 + #include <linux/delay.h> 9 + #include "tsens.h" 10 + 11 + /* ----- SROT ------ */ 12 + #define SROT_HW_VER_OFF 0x0000 13 + #define SROT_CTRL_OFF 0x0004 14 + 15 + /* ----- TM ------ */ 16 + #define TM_INT_EN_OFF 0x0000 17 + #define TM_Sn_UPPER_LOWER_STATUS_CTRL_OFF 0x0004 18 + #define TM_Sn_STATUS_OFF 0x0044 19 + #define TM_TRDY_OFF 0x0084 20 + 21 + /* eeprom layout data for qcs404/405 (v1) */ 22 + #define BASE0_MASK 0x000007f8 23 + #define BASE1_MASK 0x0007f800 24 + #define BASE0_SHIFT 3 25 + #define BASE1_SHIFT 11 26 + 27 + #define S0_P1_MASK 0x0000003f 28 + #define S1_P1_MASK 0x0003f000 29 + #define S2_P1_MASK 0x3f000000 30 + #define S3_P1_MASK 0x000003f0 31 + #define S4_P1_MASK 0x003f0000 32 + #define S5_P1_MASK 0x0000003f 33 + #define S6_P1_MASK 0x0003f000 34 + #define S7_P1_MASK 0x3f000000 35 + #define S8_P1_MASK 0x000003f0 36 + #define S9_P1_MASK 0x003f0000 37 + 38 + #define S0_P2_MASK 0x00000fc0 39 + #define S1_P2_MASK 0x00fc0000 40 + #define S2_P2_MASK_1_0 0xc0000000 41 + #define S2_P2_MASK_5_2 0x0000000f 42 + #define S3_P2_MASK 0x0000fc00 43 + #define S4_P2_MASK 0x0fc00000 44 + #define S5_P2_MASK 0x00000fc0 45 + #define S6_P2_MASK 0x00fc0000 46 + #define S7_P2_MASK_1_0 0xc0000000 47 + #define S7_P2_MASK_5_2 0x0000000f 48 + #define S8_P2_MASK 0x0000fc00 49 + #define S9_P2_MASK 0x0fc00000 50 + 51 + #define S0_P1_SHIFT 0 52 + #define S0_P2_SHIFT 6 53 + #define S1_P1_SHIFT 12 54 + #define S1_P2_SHIFT 18 55 + #define S2_P1_SHIFT 24 56 + #define S2_P2_SHIFT_1_0 30 57 + 58 + #define S2_P2_SHIFT_5_2 0 59 + #define S3_P1_SHIFT 4 60 + #define S3_P2_SHIFT 10 61 + #define S4_P1_SHIFT 16 62 + #define S4_P2_SHIFT 22 63 + 64 + #define S5_P1_SHIFT 0 65 + #define S5_P2_SHIFT 6 66 + #define S6_P1_SHIFT 12 67 + #define S6_P2_SHIFT 18 68 + #define S7_P1_SHIFT 24 69 + #define S7_P2_SHIFT_1_0 30 70 + 71 + #define S7_P2_SHIFT_5_2 0 72 + #define S8_P1_SHIFT 4 73 + #define S8_P2_SHIFT 10 74 + #define S9_P1_SHIFT 16 75 + #define S9_P2_SHIFT 22 76 + 77 + #define CAL_SEL_MASK 7 78 + #define CAL_SEL_SHIFT 0 79 + 80 + static int calibrate_v1(struct tsens_priv *priv) 81 + { 82 + u32 base0 = 0, base1 = 0; 83 + u32 p1[10], p2[10]; 84 + u32 mode = 0, lsb = 0, msb = 0; 85 + u32 *qfprom_cdata; 86 + int i; 87 + 88 + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); 89 + if (IS_ERR(qfprom_cdata)) 90 + return PTR_ERR(qfprom_cdata); 91 + 92 + mode = (qfprom_cdata[4] & CAL_SEL_MASK) >> CAL_SEL_SHIFT; 93 + dev_dbg(priv->dev, "calibration mode is %d\n", mode); 94 + 95 + switch (mode) { 96 + case TWO_PT_CALIB: 97 + base1 = (qfprom_cdata[4] & BASE1_MASK) >> BASE1_SHIFT; 98 + p2[0] = (qfprom_cdata[0] & S0_P2_MASK) >> S0_P2_SHIFT; 99 + p2[1] = (qfprom_cdata[0] & S1_P2_MASK) >> S1_P2_SHIFT; 100 + /* This value is split over two registers, 2 bits and 4 bits */ 101 + lsb = (qfprom_cdata[0] & S2_P2_MASK_1_0) >> S2_P2_SHIFT_1_0; 102 + msb = (qfprom_cdata[1] & S2_P2_MASK_5_2) >> S2_P2_SHIFT_5_2; 103 + p2[2] = msb << 2 | lsb; 104 + p2[3] = (qfprom_cdata[1] & S3_P2_MASK) >> S3_P2_SHIFT; 105 + p2[4] = (qfprom_cdata[1] & S4_P2_MASK) >> S4_P2_SHIFT; 106 + p2[5] = (qfprom_cdata[2] & S5_P2_MASK) >> S5_P2_SHIFT; 107 + p2[6] = (qfprom_cdata[2] & S6_P2_MASK) >> S6_P2_SHIFT; 108 + /* This value is split over two registers, 2 bits and 4 bits */ 109 + lsb = (qfprom_cdata[2] & S7_P2_MASK_1_0) >> S7_P2_SHIFT_1_0; 110 + msb = (qfprom_cdata[3] & S7_P2_MASK_5_2) >> S7_P2_SHIFT_5_2; 111 + p2[7] = msb << 2 | lsb; 112 + p2[8] = (qfprom_cdata[3] & S8_P2_MASK) >> S8_P2_SHIFT; 113 + p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT; 114 + for (i = 0; i < priv->num_sensors; i++) 115 + p2[i] = ((base1 + p2[i]) << 2); 116 + /* Fall through */ 117 + case ONE_PT_CALIB2: 118 + base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT; 119 + p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; 120 + p1[1] = (qfprom_cdata[0] & S1_P1_MASK) >> S1_P1_SHIFT; 121 + p1[2] = (qfprom_cdata[0] & S2_P1_MASK) >> S2_P1_SHIFT; 122 + p1[3] = (qfprom_cdata[1] & S3_P1_MASK) >> S3_P1_SHIFT; 123 + p1[4] = (qfprom_cdata[1] & S4_P1_MASK) >> S4_P1_SHIFT; 124 + p1[5] = (qfprom_cdata[2] & S5_P1_MASK) >> S5_P1_SHIFT; 125 + p1[6] = (qfprom_cdata[2] & S6_P1_MASK) >> S6_P1_SHIFT; 126 + p1[7] = (qfprom_cdata[2] & S7_P1_MASK) >> S7_P1_SHIFT; 127 + p1[8] = (qfprom_cdata[3] & S8_P1_MASK) >> S8_P1_SHIFT; 128 + p1[9] = (qfprom_cdata[3] & S9_P1_MASK) >> S9_P1_SHIFT; 129 + for (i = 0; i < priv->num_sensors; i++) 130 + p1[i] = (((base0) + p1[i]) << 2); 131 + break; 132 + default: 133 + for (i = 0; i < priv->num_sensors; i++) { 134 + p1[i] = 500; 135 + p2[i] = 780; 136 + } 137 + break; 138 + } 139 + 140 + compute_intercept_slope(priv, p1, p2, mode); 141 + 142 + return 0; 143 + } 144 + 145 + /* v1.x: qcs404,405 */ 146 + 147 + static const struct tsens_features tsens_v1_feat = { 148 + .ver_major = VER_1_X, 149 + .crit_int = 0, 150 + .adc = 1, 151 + .srot_split = 1, 152 + .max_sensors = 11, 153 + }; 154 + 155 + static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = { 156 + /* ----- SROT ------ */ 157 + /* VERSION */ 158 + [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31), 159 + [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27), 160 + [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15), 161 + /* CTRL_OFFSET */ 162 + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), 163 + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), 164 + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 13), 165 + 166 + /* ----- TM ------ */ 167 + /* INTERRUPT ENABLE */ 168 + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 0), 169 + 170 + /* Sn_STATUS */ 171 + REG_FIELD_FOR_EACH_SENSOR11(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 9), 172 + REG_FIELD_FOR_EACH_SENSOR11(VALID, TM_Sn_STATUS_OFF, 14, 14), 173 + REG_FIELD_FOR_EACH_SENSOR11(MIN_STATUS, TM_Sn_STATUS_OFF, 10, 10), 174 + REG_FIELD_FOR_EACH_SENSOR11(LOWER_STATUS, TM_Sn_STATUS_OFF, 11, 11), 175 + REG_FIELD_FOR_EACH_SENSOR11(UPPER_STATUS, TM_Sn_STATUS_OFF, 12, 12), 176 + /* No CRITICAL field on v1.x */ 177 + REG_FIELD_FOR_EACH_SENSOR11(MAX_STATUS, TM_Sn_STATUS_OFF, 13, 13), 178 + 179 + /* TRDY: 1=ready, 0=in progress */ 180 + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 181 + }; 182 + 183 + static const struct tsens_ops ops_generic_v1 = { 184 + .init = init_common, 185 + .calibrate = calibrate_v1, 186 + .get_temp = get_temp_tsens_valid, 187 + }; 188 + 189 + const struct tsens_plat_data data_tsens_v1 = { 190 + .ops = &ops_generic_v1, 191 + .feat = &tsens_v1_feat, 192 + .fields = tsens_v1_regfields, 193 + };
+58 -53
drivers/thermal/qcom/tsens-v2.c
··· 4 4 * Copyright (c) 2018, Linaro Limited 5 5 */ 6 6 7 - #include <linux/regmap.h> 8 7 #include <linux/bitops.h> 8 + #include <linux/regmap.h> 9 9 #include "tsens.h" 10 10 11 - #define STATUS_OFFSET 0xa0 12 - #define LAST_TEMP_MASK 0xfff 13 - #define STATUS_VALID_BIT BIT(21) 11 + /* ----- SROT ------ */ 12 + #define SROT_HW_VER_OFF 0x0000 13 + #define SROT_CTRL_OFF 0x0004 14 14 15 - static int get_temp_tsens_v2(struct tsens_device *tmdev, int id, int *temp) 16 - { 17 - struct tsens_sensor *s = &tmdev->sensor[id]; 18 - u32 code; 19 - unsigned int status_reg; 20 - u32 last_temp = 0, last_temp2 = 0, last_temp3 = 0; 21 - int ret; 15 + /* ----- TM ------ */ 16 + #define TM_INT_EN_OFF 0x0004 17 + #define TM_UPPER_LOWER_INT_STATUS_OFF 0x0008 18 + #define TM_UPPER_LOWER_INT_CLEAR_OFF 0x000c 19 + #define TM_UPPER_LOWER_INT_MASK_OFF 0x0010 20 + #define TM_CRITICAL_INT_STATUS_OFF 0x0014 21 + #define TM_CRITICAL_INT_CLEAR_OFF 0x0018 22 + #define TM_CRITICAL_INT_MASK_OFF 0x001c 23 + #define TM_Sn_UPPER_LOWER_THRESHOLD_OFF 0x0020 24 + #define TM_Sn_CRITICAL_THRESHOLD_OFF 0x0060 25 + #define TM_Sn_STATUS_OFF 0x00a0 26 + #define TM_TRDY_OFF 0x00e4 22 27 23 - status_reg = tmdev->tm_offset + STATUS_OFFSET + s->hw_id * 4; 24 - ret = regmap_read(tmdev->tm_map, status_reg, &code); 25 - if (ret) 26 - return ret; 27 - last_temp = code & LAST_TEMP_MASK; 28 - if (code & STATUS_VALID_BIT) 29 - goto done; 28 + /* v2.x: 8996, 8998, sdm845 */ 30 29 31 - /* Try a second time */ 32 - ret = regmap_read(tmdev->tm_map, status_reg, &code); 33 - if (ret) 34 - return ret; 35 - if (code & STATUS_VALID_BIT) { 36 - last_temp = code & LAST_TEMP_MASK; 37 - goto done; 38 - } else { 39 - last_temp2 = code & LAST_TEMP_MASK; 40 - } 30 + static const struct tsens_features tsens_v2_feat = { 31 + .ver_major = VER_2_X, 32 + .crit_int = 1, 33 + .adc = 0, 34 + .srot_split = 1, 35 + .max_sensors = 16, 36 + }; 41 37 42 - /* Try a third/last time */ 43 - ret = regmap_read(tmdev->tm_map, status_reg, &code); 44 - if (ret) 45 - return ret; 46 - if (code & STATUS_VALID_BIT) { 47 - last_temp = code & LAST_TEMP_MASK; 48 - goto done; 49 - } else { 50 - last_temp3 = code & LAST_TEMP_MASK; 51 - } 38 + static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = { 39 + /* ----- SROT ------ */ 40 + /* VERSION */ 41 + [VER_MAJOR] = REG_FIELD(SROT_HW_VER_OFF, 28, 31), 42 + [VER_MINOR] = REG_FIELD(SROT_HW_VER_OFF, 16, 27), 43 + [VER_STEP] = REG_FIELD(SROT_HW_VER_OFF, 0, 15), 44 + /* CTRL_OFF */ 45 + [TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0), 46 + [TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1), 47 + [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18), 52 48 53 - if (last_temp == last_temp2) 54 - last_temp = last_temp2; 55 - else if (last_temp2 == last_temp3) 56 - last_temp = last_temp3; 57 - done: 58 - /* Convert temperature from deciCelsius to milliCelsius */ 59 - *temp = sign_extend32(last_temp, fls(LAST_TEMP_MASK) - 1) * 100; 49 + /* ----- TM ------ */ 50 + /* INTERRUPT ENABLE */ 51 + /* v2 has separate enables for UPPER/LOWER/CRITICAL interrupts */ 52 + [INT_EN] = REG_FIELD(TM_INT_EN_OFF, 0, 2), 60 53 61 - return 0; 62 - } 54 + /* Sn_STATUS */ 55 + REG_FIELD_FOR_EACH_SENSOR16(LAST_TEMP, TM_Sn_STATUS_OFF, 0, 11), 56 + REG_FIELD_FOR_EACH_SENSOR16(VALID, TM_Sn_STATUS_OFF, 21, 21), 57 + REG_FIELD_FOR_EACH_SENSOR16(MIN_STATUS, TM_Sn_STATUS_OFF, 16, 16), 58 + REG_FIELD_FOR_EACH_SENSOR16(LOWER_STATUS, TM_Sn_STATUS_OFF, 17, 17), 59 + REG_FIELD_FOR_EACH_SENSOR16(UPPER_STATUS, TM_Sn_STATUS_OFF, 18, 18), 60 + REG_FIELD_FOR_EACH_SENSOR16(CRITICAL_STATUS, TM_Sn_STATUS_OFF, 19, 19), 61 + REG_FIELD_FOR_EACH_SENSOR16(MAX_STATUS, TM_Sn_STATUS_OFF, 20, 20), 62 + 63 + /* TRDY: 1=ready, 0=in progress */ 64 + [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 65 + }; 63 66 64 67 static const struct tsens_ops ops_generic_v2 = { 65 68 .init = init_common, 66 - .get_temp = get_temp_tsens_v2, 69 + .get_temp = get_temp_tsens_valid, 67 70 }; 68 71 69 - const struct tsens_data data_tsens_v2 = { 70 - .ops = &ops_generic_v2, 71 - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 }, 72 + const struct tsens_plat_data data_tsens_v2 = { 73 + .ops = &ops_generic_v2, 74 + .feat = &tsens_v2_feat, 75 + .fields = tsens_v2_regfields, 72 76 }; 73 77 74 78 /* Kept around for backward compatibility with old msm8996.dtsi */ 75 - const struct tsens_data data_8996 = { 79 + const struct tsens_plat_data data_8996 = { 76 80 .num_sensors = 13, 77 81 .ops = &ops_generic_v2, 78 - .reg_offsets = { [SROT_CTRL_OFFSET] = 0x4 }, 82 + .feat = &tsens_v2_feat, 83 + .fields = tsens_v2_regfields, 79 84 };
+54 -46
drivers/thermal/qcom/tsens.c
··· 15 15 static int tsens_get_temp(void *data, int *temp) 16 16 { 17 17 const struct tsens_sensor *s = data; 18 - struct tsens_device *tmdev = s->tmdev; 18 + struct tsens_priv *priv = s->priv; 19 19 20 - return tmdev->ops->get_temp(tmdev, s->id, temp); 20 + return priv->ops->get_temp(priv, s->id, temp); 21 21 } 22 22 23 - static int tsens_get_trend(void *p, int trip, enum thermal_trend *trend) 23 + static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend) 24 24 { 25 - const struct tsens_sensor *s = p; 26 - struct tsens_device *tmdev = s->tmdev; 25 + const struct tsens_sensor *s = data; 26 + struct tsens_priv *priv = s->priv; 27 27 28 - if (tmdev->ops->get_trend) 29 - return tmdev->ops->get_trend(tmdev, s->id, trend); 28 + if (priv->ops->get_trend) 29 + return priv->ops->get_trend(priv, s->id, trend); 30 30 31 31 return -ENOTSUPP; 32 32 } 33 33 34 34 static int __maybe_unused tsens_suspend(struct device *dev) 35 35 { 36 - struct tsens_device *tmdev = dev_get_drvdata(dev); 36 + struct tsens_priv *priv = dev_get_drvdata(dev); 37 37 38 - if (tmdev->ops && tmdev->ops->suspend) 39 - return tmdev->ops->suspend(tmdev); 38 + if (priv->ops && priv->ops->suspend) 39 + return priv->ops->suspend(priv); 40 40 41 41 return 0; 42 42 } 43 43 44 44 static int __maybe_unused tsens_resume(struct device *dev) 45 45 { 46 - struct tsens_device *tmdev = dev_get_drvdata(dev); 46 + struct tsens_priv *priv = dev_get_drvdata(dev); 47 47 48 - if (tmdev->ops && tmdev->ops->resume) 49 - return tmdev->ops->resume(tmdev); 48 + if (priv->ops && priv->ops->resume) 49 + return priv->ops->resume(priv); 50 50 51 51 return 0; 52 52 } ··· 64 64 .compatible = "qcom,msm8996-tsens", 65 65 .data = &data_8996, 66 66 }, { 67 + .compatible = "qcom,tsens-v1", 68 + .data = &data_tsens_v1, 69 + }, { 67 70 .compatible = "qcom,tsens-v2", 68 71 .data = &data_tsens_v2, 69 72 }, ··· 79 76 .get_trend = tsens_get_trend, 80 77 }; 81 78 82 - static int tsens_register(struct tsens_device *tmdev) 79 + static int tsens_register(struct tsens_priv *priv) 83 80 { 84 81 int i; 85 82 struct thermal_zone_device *tzd; 86 83 87 - for (i = 0; i < tmdev->num_sensors; i++) { 88 - tmdev->sensor[i].tmdev = tmdev; 89 - tmdev->sensor[i].id = i; 90 - tzd = devm_thermal_zone_of_sensor_register(tmdev->dev, i, 91 - &tmdev->sensor[i], 84 + for (i = 0; i < priv->num_sensors; i++) { 85 + if (!is_sensor_enabled(priv, priv->sensor[i].hw_id)) { 86 + dev_err(priv->dev, "sensor %d: disabled\n", 87 + priv->sensor[i].hw_id); 88 + continue; 89 + } 90 + priv->sensor[i].priv = priv; 91 + priv->sensor[i].id = i; 92 + tzd = devm_thermal_zone_of_sensor_register(priv->dev, i, 93 + &priv->sensor[i], 92 94 &tsens_of_ops); 93 95 if (IS_ERR(tzd)) 94 96 continue; 95 - tmdev->sensor[i].tzd = tzd; 96 - if (tmdev->ops->enable) 97 - tmdev->ops->enable(tmdev, i); 97 + priv->sensor[i].tzd = tzd; 98 + if (priv->ops->enable) 99 + priv->ops->enable(priv, i); 98 100 } 99 101 return 0; 100 102 } ··· 109 101 int ret, i; 110 102 struct device *dev; 111 103 struct device_node *np; 112 - struct tsens_device *tmdev; 113 - const struct tsens_data *data; 104 + struct tsens_priv *priv; 105 + const struct tsens_plat_data *data; 114 106 const struct of_device_id *id; 115 107 u32 num_sensors; 116 108 ··· 137 129 return -EINVAL; 138 130 } 139 131 140 - tmdev = devm_kzalloc(dev, 141 - struct_size(tmdev, sensor, num_sensors), 132 + priv = devm_kzalloc(dev, 133 + struct_size(priv, sensor, num_sensors), 142 134 GFP_KERNEL); 143 - if (!tmdev) 135 + if (!priv) 144 136 return -ENOMEM; 145 137 146 - tmdev->dev = dev; 147 - tmdev->num_sensors = num_sensors; 148 - tmdev->ops = data->ops; 149 - for (i = 0; i < tmdev->num_sensors; i++) { 138 + priv->dev = dev; 139 + priv->num_sensors = num_sensors; 140 + priv->ops = data->ops; 141 + for (i = 0; i < priv->num_sensors; i++) { 150 142 if (data->hw_ids) 151 - tmdev->sensor[i].hw_id = data->hw_ids[i]; 143 + priv->sensor[i].hw_id = data->hw_ids[i]; 152 144 else 153 - tmdev->sensor[i].hw_id = i; 145 + priv->sensor[i].hw_id = i; 154 146 } 155 - for (i = 0; i < REG_ARRAY_SIZE; i++) { 156 - tmdev->reg_offsets[i] = data->reg_offsets[i]; 157 - } 147 + priv->feat = data->feat; 148 + priv->fields = data->fields; 158 149 159 - if (!tmdev->ops || !tmdev->ops->init || !tmdev->ops->get_temp) 150 + if (!priv->ops || !priv->ops->init || !priv->ops->get_temp) 160 151 return -EINVAL; 161 152 162 - ret = tmdev->ops->init(tmdev); 153 + ret = priv->ops->init(priv); 163 154 if (ret < 0) { 164 155 dev_err(dev, "tsens init failed\n"); 165 156 return ret; 166 157 } 167 158 168 - if (tmdev->ops->calibrate) { 169 - ret = tmdev->ops->calibrate(tmdev); 159 + if (priv->ops->calibrate) { 160 + ret = priv->ops->calibrate(priv); 170 161 if (ret < 0) { 171 - dev_err(dev, "tsens calibration failed\n"); 162 + if (ret != -EPROBE_DEFER) 163 + dev_err(dev, "tsens calibration failed\n"); 172 164 return ret; 173 165 } 174 166 } 175 167 176 - ret = tsens_register(tmdev); 168 + ret = tsens_register(priv); 177 169 178 - platform_set_drvdata(pdev, tmdev); 170 + platform_set_drvdata(pdev, priv); 179 171 180 172 return ret; 181 173 } 182 174 183 175 static int tsens_remove(struct platform_device *pdev) 184 176 { 185 - struct tsens_device *tmdev = platform_get_drvdata(pdev); 177 + struct tsens_priv *priv = platform_get_drvdata(pdev); 186 178 187 - if (tmdev->ops->disable) 188 - tmdev->ops->disable(tmdev); 179 + if (priv->ops->disable) 180 + priv->ops->disable(priv); 189 181 190 182 return 0; 191 183 }
+267 -34
drivers/thermal/qcom/tsens.h
··· 9 9 #define ONE_PT_CALIB 0x1 10 10 #define ONE_PT_CALIB2 0x2 11 11 #define TWO_PT_CALIB 0x3 12 + #define CAL_DEGC_PT1 30 13 + #define CAL_DEGC_PT2 120 14 + #define SLOPE_FACTOR 1000 15 + #define SLOPE_DEFAULT 3200 16 + 12 17 13 18 #include <linux/thermal.h> 19 + #include <linux/regmap.h> 14 20 15 - struct tsens_device; 21 + struct tsens_priv; 16 22 23 + enum tsens_ver { 24 + VER_0_1 = 0, 25 + VER_1_X, 26 + VER_2_X, 27 + }; 28 + 29 + /** 30 + * struct tsens_sensor - data for each sensor connected to the tsens device 31 + * @priv: tsens device instance that this sensor is connected to 32 + * @tzd: pointer to the thermal zone that this sensor is in 33 + * @offset: offset of temperature adjustment curve 34 + * @id: Sensor ID 35 + * @hw_id: HW ID can be used in case of platform-specific IDs 36 + * @slope: slope of temperature adjustment curve 37 + * @status: 8960-specific variable to track 8960 and 8660 status register offset 38 + */ 17 39 struct tsens_sensor { 18 - struct tsens_device *tmdev; 40 + struct tsens_priv *priv; 19 41 struct thermal_zone_device *tzd; 20 42 int offset; 21 - int id; 22 - int hw_id; 43 + unsigned int id; 44 + unsigned int hw_id; 23 45 int slope; 24 46 u32 status; 25 47 }; ··· 59 37 */ 60 38 struct tsens_ops { 61 39 /* mandatory callbacks */ 62 - int (*init)(struct tsens_device *); 63 - int (*calibrate)(struct tsens_device *); 64 - int (*get_temp)(struct tsens_device *, int, int *); 40 + int (*init)(struct tsens_priv *priv); 41 + int (*calibrate)(struct tsens_priv *priv); 42 + int (*get_temp)(struct tsens_priv *priv, int i, int *temp); 65 43 /* optional callbacks */ 66 - int (*enable)(struct tsens_device *, int); 67 - void (*disable)(struct tsens_device *); 68 - int (*suspend)(struct tsens_device *); 69 - int (*resume)(struct tsens_device *); 70 - int (*get_trend)(struct tsens_device *, int, enum thermal_trend *); 44 + int (*enable)(struct tsens_priv *priv, int i); 45 + void (*disable)(struct tsens_priv *priv); 46 + int (*suspend)(struct tsens_priv *priv); 47 + int (*resume)(struct tsens_priv *priv); 48 + int (*get_trend)(struct tsens_priv *priv, int i, enum thermal_trend *trend); 71 49 }; 72 50 73 - enum reg_list { 74 - SROT_CTRL_OFFSET, 51 + #define REG_FIELD_FOR_EACH_SENSOR11(_name, _offset, _startbit, _stopbit) \ 52 + [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \ 53 + [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \ 54 + [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \ 55 + [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \ 56 + [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \ 57 + [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \ 58 + [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \ 59 + [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \ 60 + [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \ 61 + [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \ 62 + [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit) 75 63 76 - REG_ARRAY_SIZE, 64 + #define REG_FIELD_FOR_EACH_SENSOR16(_name, _offset, _startbit, _stopbit) \ 65 + [_name##_##0] = REG_FIELD(_offset, _startbit, _stopbit), \ 66 + [_name##_##1] = REG_FIELD(_offset + 4, _startbit, _stopbit), \ 67 + [_name##_##2] = REG_FIELD(_offset + 8, _startbit, _stopbit), \ 68 + [_name##_##3] = REG_FIELD(_offset + 12, _startbit, _stopbit), \ 69 + [_name##_##4] = REG_FIELD(_offset + 16, _startbit, _stopbit), \ 70 + [_name##_##5] = REG_FIELD(_offset + 20, _startbit, _stopbit), \ 71 + [_name##_##6] = REG_FIELD(_offset + 24, _startbit, _stopbit), \ 72 + [_name##_##7] = REG_FIELD(_offset + 28, _startbit, _stopbit), \ 73 + [_name##_##8] = REG_FIELD(_offset + 32, _startbit, _stopbit), \ 74 + [_name##_##9] = REG_FIELD(_offset + 36, _startbit, _stopbit), \ 75 + [_name##_##10] = REG_FIELD(_offset + 40, _startbit, _stopbit), \ 76 + [_name##_##11] = REG_FIELD(_offset + 44, _startbit, _stopbit), \ 77 + [_name##_##12] = REG_FIELD(_offset + 48, _startbit, _stopbit), \ 78 + [_name##_##13] = REG_FIELD(_offset + 52, _startbit, _stopbit), \ 79 + [_name##_##14] = REG_FIELD(_offset + 56, _startbit, _stopbit), \ 80 + [_name##_##15] = REG_FIELD(_offset + 60, _startbit, _stopbit) 81 + 82 + /* reg_field IDs to use as an index into an array */ 83 + enum regfield_ids { 84 + /* ----- SROT ------ */ 85 + /* HW_VER */ 86 + VER_MAJOR = 0, 87 + VER_MINOR, 88 + VER_STEP, 89 + /* CTRL_OFFSET */ 90 + TSENS_EN = 3, 91 + TSENS_SW_RST, 92 + SENSOR_EN, 93 + CODE_OR_TEMP, 94 + 95 + /* ----- TM ------ */ 96 + /* STATUS */ 97 + LAST_TEMP_0 = 7, /* Last temperature reading */ 98 + LAST_TEMP_1, 99 + LAST_TEMP_2, 100 + LAST_TEMP_3, 101 + LAST_TEMP_4, 102 + LAST_TEMP_5, 103 + LAST_TEMP_6, 104 + LAST_TEMP_7, 105 + LAST_TEMP_8, 106 + LAST_TEMP_9, 107 + LAST_TEMP_10, 108 + LAST_TEMP_11, 109 + LAST_TEMP_12, 110 + LAST_TEMP_13, 111 + LAST_TEMP_14, 112 + LAST_TEMP_15, 113 + VALID_0 = 23, /* VALID reading or not */ 114 + VALID_1, 115 + VALID_2, 116 + VALID_3, 117 + VALID_4, 118 + VALID_5, 119 + VALID_6, 120 + VALID_7, 121 + VALID_8, 122 + VALID_9, 123 + VALID_10, 124 + VALID_11, 125 + VALID_12, 126 + VALID_13, 127 + VALID_14, 128 + VALID_15, 129 + MIN_STATUS_0, /* MIN threshold violated */ 130 + MIN_STATUS_1, 131 + MIN_STATUS_2, 132 + MIN_STATUS_3, 133 + MIN_STATUS_4, 134 + MIN_STATUS_5, 135 + MIN_STATUS_6, 136 + MIN_STATUS_7, 137 + MIN_STATUS_8, 138 + MIN_STATUS_9, 139 + MIN_STATUS_10, 140 + MIN_STATUS_11, 141 + MIN_STATUS_12, 142 + MIN_STATUS_13, 143 + MIN_STATUS_14, 144 + MIN_STATUS_15, 145 + MAX_STATUS_0, /* MAX threshold violated */ 146 + MAX_STATUS_1, 147 + MAX_STATUS_2, 148 + MAX_STATUS_3, 149 + MAX_STATUS_4, 150 + MAX_STATUS_5, 151 + MAX_STATUS_6, 152 + MAX_STATUS_7, 153 + MAX_STATUS_8, 154 + MAX_STATUS_9, 155 + MAX_STATUS_10, 156 + MAX_STATUS_11, 157 + MAX_STATUS_12, 158 + MAX_STATUS_13, 159 + MAX_STATUS_14, 160 + MAX_STATUS_15, 161 + LOWER_STATUS_0, /* LOWER threshold violated */ 162 + LOWER_STATUS_1, 163 + LOWER_STATUS_2, 164 + LOWER_STATUS_3, 165 + LOWER_STATUS_4, 166 + LOWER_STATUS_5, 167 + LOWER_STATUS_6, 168 + LOWER_STATUS_7, 169 + LOWER_STATUS_8, 170 + LOWER_STATUS_9, 171 + LOWER_STATUS_10, 172 + LOWER_STATUS_11, 173 + LOWER_STATUS_12, 174 + LOWER_STATUS_13, 175 + LOWER_STATUS_14, 176 + LOWER_STATUS_15, 177 + UPPER_STATUS_0, /* UPPER threshold violated */ 178 + UPPER_STATUS_1, 179 + UPPER_STATUS_2, 180 + UPPER_STATUS_3, 181 + UPPER_STATUS_4, 182 + UPPER_STATUS_5, 183 + UPPER_STATUS_6, 184 + UPPER_STATUS_7, 185 + UPPER_STATUS_8, 186 + UPPER_STATUS_9, 187 + UPPER_STATUS_10, 188 + UPPER_STATUS_11, 189 + UPPER_STATUS_12, 190 + UPPER_STATUS_13, 191 + UPPER_STATUS_14, 192 + UPPER_STATUS_15, 193 + CRITICAL_STATUS_0, /* CRITICAL threshold violated */ 194 + CRITICAL_STATUS_1, 195 + CRITICAL_STATUS_2, 196 + CRITICAL_STATUS_3, 197 + CRITICAL_STATUS_4, 198 + CRITICAL_STATUS_5, 199 + CRITICAL_STATUS_6, 200 + CRITICAL_STATUS_7, 201 + CRITICAL_STATUS_8, 202 + CRITICAL_STATUS_9, 203 + CRITICAL_STATUS_10, 204 + CRITICAL_STATUS_11, 205 + CRITICAL_STATUS_12, 206 + CRITICAL_STATUS_13, 207 + CRITICAL_STATUS_14, 208 + CRITICAL_STATUS_15, 209 + /* TRDY */ 210 + TRDY, 211 + /* INTERRUPT ENABLE */ 212 + INT_EN, /* Pre-V1, V1.x */ 213 + LOW_INT_EN, /* V2.x */ 214 + UP_INT_EN, /* V2.x */ 215 + CRIT_INT_EN, /* V2.x */ 216 + 217 + /* Keep last */ 218 + MAX_REGFIELDS 77 219 }; 78 220 79 221 /** 80 - * struct tsens_data - tsens instance specific data 81 - * @num_sensors: Max number of sensors supported by platform 82 - * @ops: operations the tsens instance supports 83 - * @hw_ids: Subset of sensors ids supported by platform, if not the first n 84 - * @reg_offsets: Register offsets for commonly used registers 222 + * struct tsens_features - Features supported by the IP 223 + * @ver_major: Major number of IP version 224 + * @crit_int: does the IP support critical interrupts? 225 + * @adc: do the sensors only output adc code (instead of temperature)? 226 + * @srot_split: does the IP neatly splits the register space into SROT and TM, 227 + * with SROT only being available to secure boot firmware? 228 + * @max_sensors: maximum sensors supported by this version of the IP 85 229 */ 86 - struct tsens_data { 87 - const u32 num_sensors; 88 - const struct tsens_ops *ops; 89 - const u16 reg_offsets[REG_ARRAY_SIZE]; 90 - unsigned int *hw_ids; 230 + struct tsens_features { 231 + unsigned int ver_major; 232 + unsigned int crit_int:1; 233 + unsigned int adc:1; 234 + unsigned int srot_split:1; 235 + unsigned int max_sensors; 91 236 }; 92 237 93 - /* Registers to be saved/restored across a context loss */ 238 + /** 239 + * struct tsens_plat_data - tsens compile-time platform data 240 + * @num_sensors: Number of sensors supported by platform 241 + * @ops: operations the tsens instance supports 242 + * @hw_ids: Subset of sensors ids supported by platform, if not the first n 243 + * @feat: features of the IP 244 + * @fields: bitfield locations 245 + */ 246 + struct tsens_plat_data { 247 + const u32 num_sensors; 248 + const struct tsens_ops *ops; 249 + unsigned int *hw_ids; 250 + const struct tsens_features *feat; 251 + const struct reg_field *fields; 252 + }; 253 + 254 + /** 255 + * struct tsens_context - Registers to be saved/restored across a context loss 256 + */ 94 257 struct tsens_context { 95 258 int threshold; 96 259 int control; 97 260 }; 98 261 99 - struct tsens_device { 262 + /** 263 + * struct tsens_priv - private data for each instance of the tsens IP 264 + * @dev: pointer to struct device 265 + * @num_sensors: number of sensors enabled on this device 266 + * @tm_map: pointer to TM register address space 267 + * @srot_map: pointer to SROT register address space 268 + * @tm_offset: deal with old device trees that don't address TM and SROT 269 + * address space separately 270 + * @rf: array of regmap_fields used to store value of the field 271 + * @ctx: registers to be saved and restored during suspend/resume 272 + * @feat: features of the IP 273 + * @fields: bitfield locations 274 + * @ops: pointer to list of callbacks supported by this device 275 + * @sensor: list of sensors attached to this device 276 + */ 277 + struct tsens_priv { 100 278 struct device *dev; 101 279 u32 num_sensors; 102 280 struct regmap *tm_map; 103 281 struct regmap *srot_map; 104 282 u32 tm_offset; 105 - u16 reg_offsets[REG_ARRAY_SIZE]; 283 + struct regmap_field *rf[MAX_REGFIELDS]; 106 284 struct tsens_context ctx; 285 + const struct tsens_features *feat; 286 + const struct reg_field *fields; 107 287 const struct tsens_ops *ops; 108 288 struct tsens_sensor sensor[0]; 109 289 }; 110 290 111 - char *qfprom_read(struct device *, const char *); 112 - void compute_intercept_slope(struct tsens_device *, u32 *, u32 *, u32); 113 - int init_common(struct tsens_device *); 114 - int get_temp_common(struct tsens_device *, int, int *); 291 + char *qfprom_read(struct device *dev, const char *cname); 292 + void compute_intercept_slope(struct tsens_priv *priv, u32 *pt1, u32 *pt2, u32 mode); 293 + int init_common(struct tsens_priv *priv); 294 + int get_temp_tsens_valid(struct tsens_priv *priv, int i, int *temp); 295 + int get_temp_common(struct tsens_priv *priv, int i, int *temp); 296 + bool is_sensor_enabled(struct tsens_priv *priv, u32 hw_id); 297 + 298 + /* TSENS target */ 299 + extern const struct tsens_plat_data data_8960; 300 + 301 + /* TSENS v0.1 targets */ 302 + extern const struct tsens_plat_data data_8916, data_8974; 115 303 116 304 /* TSENS v1 targets */ 117 - extern const struct tsens_data data_8916, data_8974, data_8960; 305 + extern const struct tsens_plat_data data_tsens_v1; 306 + 118 307 /* TSENS v2 targets */ 119 - extern const struct tsens_data data_8996, data_tsens_v2; 308 + extern const struct tsens_plat_data data_8996, data_tsens_v2; 120 309 121 310 #endif /* __QCOM_TSENS_H__ */
-5
drivers/thermal/qoriq_thermal.c
··· 193 193 struct qoriq_tmu_data *data; 194 194 struct device_node *np = pdev->dev.of_node; 195 195 196 - if (!np) { 197 - dev_err(&pdev->dev, "Device OF-Node is NULL"); 198 - return -ENODEV; 199 - } 200 - 201 196 data = devm_kzalloc(&pdev->dev, sizeof(struct qoriq_tmu_data), 202 197 GFP_KERNEL); 203 198 if (!data)
+14 -37
drivers/thermal/rcar_gen3_thermal.c
··· 14 14 #include <linux/of_device.h> 15 15 #include <linux/platform_device.h> 16 16 #include <linux/pm_runtime.h> 17 - #include <linux/spinlock.h> 18 17 #include <linux/sys_soc.h> 19 18 #include <linux/thermal.h> 20 19 ··· 81 82 struct rcar_gen3_thermal_priv { 82 83 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; 83 84 unsigned int num_tscs; 84 - spinlock_t lock; /* Protect interrupts on and off */ 85 85 void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); 86 86 }; 87 87 ··· 230 232 { 231 233 struct rcar_gen3_thermal_priv *priv = data; 232 234 u32 status; 233 - int i, ret = IRQ_HANDLED; 235 + int i; 234 236 235 - spin_lock(&priv->lock); 236 237 for (i = 0; i < priv->num_tscs; i++) { 237 238 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 238 239 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 239 240 if (status) 240 - ret = IRQ_WAKE_THREAD; 241 + thermal_zone_device_update(priv->tscs[i]->zone, 242 + THERMAL_EVENT_UNSPECIFIED); 241 243 } 242 - 243 - if (ret == IRQ_WAKE_THREAD) 244 - rcar_thermal_irq_set(priv, false); 245 - 246 - spin_unlock(&priv->lock); 247 - 248 - return ret; 249 - } 250 - 251 - static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data) 252 - { 253 - struct rcar_gen3_thermal_priv *priv = data; 254 - unsigned long flags; 255 - int i; 256 - 257 - for (i = 0; i < priv->num_tscs; i++) 258 - thermal_zone_device_update(priv->tscs[i]->zone, 259 - THERMAL_EVENT_UNSPECIFIED); 260 - 261 - spin_lock_irqsave(&priv->lock, flags); 262 - rcar_thermal_irq_set(priv, true); 263 - spin_unlock_irqrestore(&priv->lock, flags); 264 244 265 245 return IRQ_HANDLED; 266 246 } ··· 283 307 284 308 usleep_range(1000, 2000); 285 309 286 - rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 310 + rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0); 287 311 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 288 312 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2); 289 313 ··· 307 331 static int rcar_gen3_thermal_remove(struct platform_device *pdev) 308 332 { 309 333 struct device *dev = &pdev->dev; 334 + struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev); 335 + 336 + rcar_thermal_irq_set(priv, false); 310 337 311 338 pm_runtime_put(dev); 312 339 pm_runtime_disable(dev); ··· 350 371 if (soc_device_match(r8a7795es1)) 351 372 priv->thermal_init = rcar_gen3_thermal_init_r8a7795es1; 352 373 353 - spin_lock_init(&priv->lock); 354 - 355 374 platform_set_drvdata(pdev, priv); 356 375 357 376 /* ··· 367 390 if (!irqname) 368 391 return -ENOMEM; 369 392 370 - ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq, 371 - rcar_gen3_thermal_irq_thread, 372 - IRQF_SHARED, irqname, priv); 393 + ret = devm_request_threaded_irq(dev, irq, NULL, 394 + rcar_gen3_thermal_irq, 395 + IRQF_ONESHOT, irqname, priv); 373 396 if (ret) 374 397 return ret; 375 398 } ··· 410 433 } 411 434 tsc->zone = zone; 412 435 413 - ret = of_thermal_get_ntrips(tsc->zone); 414 - if (ret < 0) 415 - goto error_unregister; 416 - 417 436 tsc->zone->tzp->no_hwmon = false; 418 437 ret = thermal_add_hwmon_sysfs(tsc->zone); 419 438 if (ret) ··· 420 447 rcar_gen3_hwmon_action(zone); 421 448 goto error_unregister; 422 449 } 450 + 451 + ret = of_thermal_get_ntrips(tsc->zone); 452 + if (ret < 0) 453 + goto error_unregister; 423 454 424 455 dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret); 425 456 }
+10 -1
drivers/thermal/rcar_thermal.c
··· 52 52 unsigned int irq_per_ch : 1; 53 53 unsigned int needs_suspend_resume : 1; 54 54 unsigned int nirqs; 55 + unsigned int ctemp_bands; 55 56 }; 56 57 57 58 static const struct rcar_thermal_chip rcar_thermal = { ··· 61 60 .irq_per_ch = 0, 62 61 .needs_suspend_resume = 0, 63 62 .nirqs = 1, 63 + .ctemp_bands = 1, 64 64 }; 65 65 66 66 static const struct rcar_thermal_chip rcar_gen2_thermal = { ··· 70 68 .irq_per_ch = 0, 71 69 .needs_suspend_resume = 0, 72 70 .nirqs = 1, 71 + .ctemp_bands = 1, 73 72 }; 74 73 75 74 static const struct rcar_thermal_chip rcar_gen3_thermal = { ··· 83 80 * interrupts to detect a temperature change, rise or fall. 84 81 */ 85 82 .nirqs = 2, 83 + .ctemp_bands = 2, 86 84 }; 87 85 88 86 struct rcar_thermal_priv { ··· 267 263 return ret; 268 264 269 265 mutex_lock(&priv->lock); 270 - tmp = MCELSIUS((priv->ctemp * 5) - 65); 266 + if (priv->chip->ctemp_bands == 1) 267 + tmp = MCELSIUS((priv->ctemp * 5) - 65); 268 + else if (priv->ctemp < 24) 269 + tmp = MCELSIUS(((priv->ctemp * 55) - 720) / 10); 270 + else 271 + tmp = MCELSIUS((priv->ctemp * 5) - 60); 271 272 mutex_unlock(&priv->lock); 272 273 273 274 if ((tmp < MCELSIUS(-45)) || (tmp > MCELSIUS(125))) {
+71 -3
drivers/thermal/rockchip_thermal.c
··· 172 172 int tshut_temp; 173 173 enum tshut_mode tshut_mode; 174 174 enum tshut_polarity tshut_polarity; 175 + struct pinctrl *pinctrl; 176 + struct pinctrl_state *gpio_state; 177 + struct pinctrl_state *otp_state; 175 178 }; 176 179 177 180 /** ··· 225 222 #define GRF_TSADC_TESTBIT_L 0x0e648 226 223 #define GRF_TSADC_TESTBIT_H 0x0e64c 227 224 225 + #define PX30_GRF_SOC_CON2 0x0408 226 + 228 227 #define GRF_SARADC_TESTBIT_ON (0x10001 << 2) 229 228 #define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) 230 229 #define GRF_TSADC_VCM_EN_L (0x10001 << 7) 231 230 #define GRF_TSADC_VCM_EN_H (0x10001 << 7) 231 + 232 + #define GRF_CON_TSADC_CH_INV (0x10001 << 1) 232 233 233 234 /** 234 235 * struct tsadc_table - code to temperature conversion table ··· 696 689 regs + TSADCV2_AUTO_CON); 697 690 } 698 691 692 + static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs, 693 + enum tshut_polarity tshut_polarity) 694 + { 695 + rk_tsadcv2_initialize(grf, regs, tshut_polarity); 696 + regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV); 697 + } 698 + 699 699 static void rk_tsadcv2_irq_ack(void __iomem *regs) 700 700 { 701 701 u32 val; ··· 831 817 832 818 writel_relaxed(val, regs + TSADCV2_INT_EN); 833 819 } 820 + 821 + static const struct rockchip_tsadc_chip px30_tsadc_data = { 822 + .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ 823 + .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */ 824 + .chn_num = 2, /* 2 channels for tsadc */ 825 + 826 + .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ 827 + .tshut_temp = 95000, 828 + 829 + .initialize = rk_tsadcv4_initialize, 830 + .irq_ack = rk_tsadcv3_irq_ack, 831 + .control = rk_tsadcv3_control, 832 + .get_temp = rk_tsadcv2_get_temp, 833 + .set_alarm_temp = rk_tsadcv2_alarm_temp, 834 + .set_tshut_temp = rk_tsadcv2_tshut_temp, 835 + .set_tshut_mode = rk_tsadcv2_tshut_mode, 836 + 837 + .table = { 838 + .id = rk3328_code_table, 839 + .length = ARRAY_SIZE(rk3328_code_table), 840 + .data_mask = TSADCV2_DATA_MASK, 841 + .mode = ADC_INCREMENT, 842 + }, 843 + }; 834 844 835 845 static const struct rockchip_tsadc_chip rv1108_tsadc_data = { 836 846 .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */ ··· 1028 990 }; 1029 991 1030 992 static const struct of_device_id of_rockchip_thermal_match[] = { 993 + { .compatible = "rockchip,px30-tsadc", 994 + .data = (void *)&px30_tsadc_data, 995 + }, 1031 996 { 1032 997 .compatible = "rockchip,rv1108-tsadc", 1033 998 .data = (void *)&rv1108_tsadc_data, ··· 1283 1242 return error; 1284 1243 } 1285 1244 1245 + thermal->chip->control(thermal->regs, false); 1246 + 1286 1247 error = clk_prepare_enable(thermal->clk); 1287 1248 if (error) { 1288 1249 dev_err(&pdev->dev, "failed to enable converter clock: %d\n", ··· 1309 1266 1310 1267 thermal->chip->initialize(thermal->grf, thermal->regs, 1311 1268 thermal->tshut_polarity); 1269 + 1270 + if (thermal->tshut_mode == TSHUT_MODE_GPIO) { 1271 + thermal->pinctrl = devm_pinctrl_get(&pdev->dev); 1272 + if (IS_ERR(thermal->pinctrl)) { 1273 + dev_err(&pdev->dev, "failed to find thermal pinctrl\n"); 1274 + return PTR_ERR(thermal->pinctrl); 1275 + } 1276 + 1277 + thermal->gpio_state = pinctrl_lookup_state(thermal->pinctrl, 1278 + "gpio"); 1279 + if (IS_ERR_OR_NULL(thermal->gpio_state)) { 1280 + dev_err(&pdev->dev, "failed to find thermal gpio state\n"); 1281 + return -EINVAL; 1282 + } 1283 + 1284 + thermal->otp_state = pinctrl_lookup_state(thermal->pinctrl, 1285 + "otpout"); 1286 + if (IS_ERR_OR_NULL(thermal->otp_state)) { 1287 + dev_err(&pdev->dev, "failed to find thermal otpout state\n"); 1288 + return -EINVAL; 1289 + } 1290 + 1291 + pinctrl_select_state(thermal->pinctrl, thermal->otp_state); 1292 + } 1312 1293 1313 1294 for (i = 0; i < thermal->chip->chn_num; i++) { 1314 1295 error = rockchip_thermal_register_sensor(pdev, thermal, ··· 1404 1337 1405 1338 clk_disable(thermal->pclk); 1406 1339 clk_disable(thermal->clk); 1407 - 1408 - pinctrl_pm_select_sleep_state(dev); 1340 + if (thermal->tshut_mode == TSHUT_MODE_GPIO) 1341 + pinctrl_select_state(thermal->pinctrl, thermal->gpio_state); 1409 1342 1410 1343 return 0; 1411 1344 } ··· 1450 1383 for (i = 0; i < thermal->chip->chn_num; i++) 1451 1384 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); 1452 1385 1453 - pinctrl_pm_select_default_state(dev); 1386 + if (thermal->tshut_mode == TSHUT_MODE_GPIO) 1387 + pinctrl_select_state(thermal->pinctrl, thermal->otp_state); 1454 1388 1455 1389 return 0; 1456 1390 }
+11 -11
drivers/thermal/st/Kconfig
··· 3 3 # 4 4 5 5 config ST_THERMAL 6 - tristate "Thermal sensors on STMicroelectronics STi series of SoCs" 7 - help 8 - Support for thermal sensors on STMicroelectronics STi series of SoCs. 6 + tristate "Thermal sensors on STMicroelectronics STi series of SoCs" 7 + help 8 + Support for thermal sensors on STMicroelectronics STi series of SoCs. 9 9 10 10 config ST_THERMAL_SYSCFG 11 11 select ST_THERMAL ··· 16 16 tristate "STi series memory mapped access based thermal sensors" 17 17 18 18 config STM32_THERMAL 19 - tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs" 20 - depends on MACH_STM32MP157 21 - default y 22 - help 23 - Support for thermal framework on STMicroelectronics STM32 series of 24 - SoCs. This thermal driver allows to access to general thermal framework 25 - functionalities and to acces to SoC sensor functionalities. This 26 - configuration is fully dependent of MACH_STM32MP157. 19 + tristate "Thermal framework support on STMicroelectronics STM32 series of SoCs" 20 + depends on MACH_STM32MP157 21 + default y 22 + help 23 + Support for thermal framework on STMicroelectronics STM32 series of 24 + SoCs. This thermal driver allows to access to general thermal framework 25 + functionalities and to acces to SoC sensor functionalities. This 26 + configuration is fully dependent of MACH_STM32MP157.
+2 -4
drivers/thermal/st/stm_thermal.c
··· 570 570 static int stm_thermal_suspend(struct device *dev) 571 571 { 572 572 int ret; 573 - struct platform_device *pdev = to_platform_device(dev); 574 - struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev); 573 + struct stm_thermal_sensor *sensor = dev_get_drvdata(dev); 575 574 576 575 ret = stm_thermal_sensor_off(sensor); 577 576 if (ret) ··· 584 585 static int stm_thermal_resume(struct device *dev) 585 586 { 586 587 int ret; 587 - struct platform_device *pdev = to_platform_device(dev); 588 - struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev); 588 + struct stm_thermal_sensor *sensor = dev_get_drvdata(dev); 589 589 590 590 ret = stm_thermal_prepare(sensor); 591 591 if (ret)
+2 -2
drivers/thermal/tegra/Kconfig
··· 14 14 tristate "Tegra BPMP thermal sensing" 15 15 depends on TEGRA_BPMP || COMPILE_TEST 16 16 help 17 - Enable this option for support for sensing system temperature of NVIDIA 18 - Tegra systems-on-chip with the BPMP coprocessor (Tegra186). 17 + Enable this option for support for sensing system temperature of NVIDIA 18 + Tegra systems-on-chip with the BPMP coprocessor (Tegra186). 19 19 20 20 endmenu
+903 -56
drivers/thermal/tegra/soctherm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 3 + * Copyright (c) 2014 - 2018, NVIDIA CORPORATION. All rights reserved. 3 4 * 4 5 * Author: 5 6 * Mikko Perttunen <mperttunen@nvidia.com> ··· 23 22 #include <linux/err.h> 24 23 #include <linux/interrupt.h> 25 24 #include <linux/io.h> 25 + #include <linux/irq.h> 26 + #include <linux/irqdomain.h> 26 27 #include <linux/module.h> 27 28 #include <linux/of.h> 28 29 #include <linux/platform_device.h> ··· 88 85 #define THERMCTL_LVL0_UP_STATS 0x10 89 86 #define THERMCTL_LVL0_DN_STATS 0x14 90 87 88 + #define THERMCTL_INTR_STATUS 0x84 89 + 90 + #define TH_INTR_MD0_MASK BIT(25) 91 + #define TH_INTR_MU0_MASK BIT(24) 92 + #define TH_INTR_GD0_MASK BIT(17) 93 + #define TH_INTR_GU0_MASK BIT(16) 94 + #define TH_INTR_CD0_MASK BIT(9) 95 + #define TH_INTR_CU0_MASK BIT(8) 96 + #define TH_INTR_PD0_MASK BIT(1) 97 + #define TH_INTR_PU0_MASK BIT(0) 98 + #define TH_INTR_IGNORE_MASK 0xFCFCFCFC 99 + 91 100 #define THERMCTL_STATS_CTL 0x94 92 101 #define STATS_CTL_CLR_DN 0x8 93 102 #define STATS_CTL_EN_DN 0x4 94 103 #define STATS_CTL_CLR_UP 0x2 95 104 #define STATS_CTL_EN_UP 0x1 105 + 106 + #define OC1_CFG 0x310 107 + #define OC1_CFG_LONG_LATENCY_MASK BIT(6) 108 + #define OC1_CFG_HW_RESTORE_MASK BIT(5) 109 + #define OC1_CFG_PWR_GOOD_MASK_MASK BIT(4) 110 + #define OC1_CFG_THROTTLE_MODE_MASK (0x3 << 2) 111 + #define OC1_CFG_ALARM_POLARITY_MASK BIT(1) 112 + #define OC1_CFG_EN_THROTTLE_MASK BIT(0) 113 + 114 + #define OC1_CNT_THRESHOLD 0x314 115 + #define OC1_THROTTLE_PERIOD 0x318 116 + #define OC1_ALARM_COUNT 0x31c 117 + #define OC1_FILTER 0x320 118 + #define OC1_STATS 0x3a8 119 + 120 + #define OC_INTR_STATUS 0x39c 121 + #define OC_INTR_ENABLE 0x3a0 122 + #define OC_INTR_DISABLE 0x3a4 123 + #define OC_STATS_CTL 0x3c4 124 + #define OC_STATS_CTL_CLR_ALL 0x2 125 + #define OC_STATS_CTL_EN_ALL 0x1 126 + 127 + #define OC_INTR_OC1_MASK BIT(0) 128 + #define OC_INTR_OC2_MASK BIT(1) 129 + #define OC_INTR_OC3_MASK BIT(2) 130 + #define OC_INTR_OC4_MASK BIT(3) 131 + #define OC_INTR_OC5_MASK BIT(4) 96 132 97 133 #define THROT_GLOBAL_CFG 0x400 98 134 #define THROT_GLOBAL_ENB_MASK BIT(0) ··· 202 160 /* get dividend from the depth */ 203 161 #define THROT_DEPTH_DIVIDEND(depth) ((256 * (100 - (depth)) / 100) - 1) 204 162 163 + /* gk20a nv_therm interface N:3 Mapping. Levels defined in tegra124-sochterm.h 164 + * level vector 165 + * NONE 3'b000 166 + * LOW 3'b001 167 + * MED 3'b011 168 + * HIGH 3'b111 169 + */ 170 + #define THROT_LEVEL_TO_DEPTH(level) ((0x1 << (level)) - 1) 171 + 205 172 /* get THROT_PSKIP_xxx offset per LIGHT/HEAVY throt and CPU/GPU dev */ 206 173 #define THROT_OFFSET 0x30 207 174 #define THROT_PSKIP_CTRL(throt, dev) (THROT_PSKIP_CTRL_LITE_CPU + \ ··· 224 173 #define THROT_DELAY_CTRL(throt) (THROT_DELAY_LITE + \ 225 174 (THROT_OFFSET * throt)) 226 175 176 + #define ALARM_OFFSET 0x14 177 + #define ALARM_CFG(throt) (OC1_CFG + \ 178 + (ALARM_OFFSET * (throt - THROTTLE_OC1))) 179 + 180 + #define ALARM_CNT_THRESHOLD(throt) (OC1_CNT_THRESHOLD + \ 181 + (ALARM_OFFSET * (throt - THROTTLE_OC1))) 182 + 183 + #define ALARM_THROTTLE_PERIOD(throt) (OC1_THROTTLE_PERIOD + \ 184 + (ALARM_OFFSET * (throt - THROTTLE_OC1))) 185 + 186 + #define ALARM_ALARM_COUNT(throt) (OC1_ALARM_COUNT + \ 187 + (ALARM_OFFSET * (throt - THROTTLE_OC1))) 188 + 189 + #define ALARM_FILTER(throt) (OC1_FILTER + \ 190 + (ALARM_OFFSET * (throt - THROTTLE_OC1))) 191 + 192 + #define ALARM_STATS(throt) (OC1_STATS + \ 193 + (4 * (throt - THROTTLE_OC1))) 194 + 227 195 /* get CCROC_THROT_PSKIP_xxx offset per HIGH/MED/LOW vect*/ 228 196 #define CCROC_THROT_OFFSET 0x0c 229 197 #define CCROC_THROT_PSKIP_CTRL_CPU_REG(vect) (CCROC_THROT_PSKIP_CTRL_CPU + \ ··· 254 184 #define THERMCTL_LVL_REGS_SIZE 0x20 255 185 #define THERMCTL_LVL_REG(rg, lv) ((rg) + ((lv) * THERMCTL_LVL_REGS_SIZE)) 256 186 187 + #define OC_THROTTLE_MODE_DISABLED 0 188 + #define OC_THROTTLE_MODE_BRIEF 2 189 + 257 190 static const int min_low_temp = -127000; 258 191 static const int max_high_temp = 127000; 259 192 260 193 enum soctherm_throttle_id { 261 194 THROTTLE_LIGHT = 0, 262 195 THROTTLE_HEAVY, 196 + THROTTLE_OC1, 197 + THROTTLE_OC2, 198 + THROTTLE_OC3, 199 + THROTTLE_OC4, 200 + THROTTLE_OC5, /* OC5 is reserved */ 263 201 THROTTLE_SIZE, 202 + }; 203 + 204 + enum soctherm_oc_irq_id { 205 + TEGRA_SOC_OC_IRQ_1, 206 + TEGRA_SOC_OC_IRQ_2, 207 + TEGRA_SOC_OC_IRQ_3, 208 + TEGRA_SOC_OC_IRQ_4, 209 + TEGRA_SOC_OC_IRQ_5, 210 + TEGRA_SOC_OC_IRQ_MAX, 264 211 }; 265 212 266 213 enum soctherm_throttle_dev_id { ··· 289 202 static const char *const throt_names[] = { 290 203 [THROTTLE_LIGHT] = "light", 291 204 [THROTTLE_HEAVY] = "heavy", 205 + [THROTTLE_OC1] = "oc1", 206 + [THROTTLE_OC2] = "oc2", 207 + [THROTTLE_OC3] = "oc3", 208 + [THROTTLE_OC4] = "oc4", 209 + [THROTTLE_OC5] = "oc5", 292 210 }; 293 211 294 212 struct tegra_soctherm; ··· 305 213 const struct tegra_tsensor_group *sg; 306 214 }; 307 215 216 + struct soctherm_oc_cfg { 217 + u32 active_low; 218 + u32 throt_period; 219 + u32 alarm_cnt_thresh; 220 + u32 alarm_filter; 221 + u32 mode; 222 + bool intr_en; 223 + }; 224 + 308 225 struct soctherm_throt_cfg { 309 226 const char *name; 310 227 unsigned int id; 311 228 u8 priority; 312 229 u8 cpu_throt_level; 313 230 u32 cpu_throt_depth; 231 + u32 gpu_throt_level; 232 + struct soctherm_oc_cfg oc_cfg; 314 233 struct thermal_cooling_device *cdev; 315 234 bool init; 316 235 }; ··· 334 231 void __iomem *clk_regs; 335 232 void __iomem *ccroc_regs; 336 233 234 + int thermal_irq; 235 + int edp_irq; 236 + 337 237 u32 *calib; 338 238 struct thermal_zone_device **thermctl_tzs; 339 239 struct tegra_soctherm_soc *soc; ··· 344 238 struct soctherm_throt_cfg throt_cfgs[THROTTLE_SIZE]; 345 239 346 240 struct dentry *debugfs_dir; 241 + 242 + struct mutex thermctl_lock; 347 243 }; 244 + 245 + struct soctherm_oc_irq_chip_data { 246 + struct mutex irq_lock; /* serialize OC IRQs */ 247 + struct irq_chip irq_chip; 248 + struct irq_domain *domain; 249 + int irq_enable; 250 + }; 251 + 252 + static struct soctherm_oc_irq_chip_data soc_irq_cdata; 348 253 349 254 /** 350 255 * ccroc_writel() - writes a value to a CCROC register ··· 563 446 return NULL; 564 447 } 565 448 449 + static int tsensor_group_thermtrip_get(struct tegra_soctherm *ts, int id) 450 + { 451 + int i, temp = min_low_temp; 452 + struct tsensor_group_thermtrips *tt = ts->soc->thermtrips; 453 + 454 + if (id >= TEGRA124_SOCTHERM_SENSOR_NUM) 455 + return temp; 456 + 457 + if (tt) { 458 + for (i = 0; i < ts->soc->num_ttgs; i++) { 459 + if (tt[i].id == id) 460 + return tt[i].temp; 461 + } 462 + } 463 + 464 + return temp; 465 + } 466 + 566 467 static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) 567 468 { 568 469 struct tegra_thermctl_zone *zone = data; ··· 599 464 return ret; 600 465 601 466 if (type == THERMAL_TRIP_CRITICAL) { 602 - return thermtrip_program(dev, sg, temp); 467 + /* 468 + * If thermtrips property is set in DT, 469 + * doesn't need to program critical type trip to HW, 470 + * if not, program critical trip to HW. 471 + */ 472 + if (min_low_temp == tsensor_group_thermtrip_get(ts, sg->id)) 473 + return thermtrip_program(dev, sg, temp); 474 + else 475 + return 0; 476 + 603 477 } else if (type == THERMAL_TRIP_HOT) { 604 478 int i; 605 479 ··· 663 519 return 0; 664 520 } 665 521 522 + static void thermal_irq_enable(struct tegra_thermctl_zone *zn) 523 + { 524 + u32 r; 525 + 526 + /* multiple zones could be handling and setting trips at once */ 527 + mutex_lock(&zn->ts->thermctl_lock); 528 + r = readl(zn->ts->regs + THERMCTL_INTR_ENABLE); 529 + r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, TH_INTR_UP_DN_EN); 530 + writel(r, zn->ts->regs + THERMCTL_INTR_ENABLE); 531 + mutex_unlock(&zn->ts->thermctl_lock); 532 + } 533 + 534 + static void thermal_irq_disable(struct tegra_thermctl_zone *zn) 535 + { 536 + u32 r; 537 + 538 + /* multiple zones could be handling and setting trips at once */ 539 + mutex_lock(&zn->ts->thermctl_lock); 540 + r = readl(zn->ts->regs + THERMCTL_INTR_DISABLE); 541 + r = REG_SET_MASK(r, zn->sg->thermctl_isr_mask, 0); 542 + writel(r, zn->ts->regs + THERMCTL_INTR_DISABLE); 543 + mutex_unlock(&zn->ts->thermctl_lock); 544 + } 545 + 546 + static int tegra_thermctl_set_trips(void *data, int lo, int hi) 547 + { 548 + struct tegra_thermctl_zone *zone = data; 549 + u32 r; 550 + 551 + thermal_irq_disable(zone); 552 + 553 + r = readl(zone->ts->regs + zone->sg->thermctl_lvl0_offset); 554 + r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 0); 555 + writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset); 556 + 557 + lo = enforce_temp_range(zone->dev, lo) / zone->ts->soc->thresh_grain; 558 + hi = enforce_temp_range(zone->dev, hi) / zone->ts->soc->thresh_grain; 559 + dev_dbg(zone->dev, "%s hi:%d, lo:%d\n", __func__, hi, lo); 560 + 561 + r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_up_thresh_mask, hi); 562 + r = REG_SET_MASK(r, zone->sg->thermctl_lvl0_dn_thresh_mask, lo); 563 + r = REG_SET_MASK(r, THERMCTL_LVL0_CPU0_EN_MASK, 1); 564 + writel(r, zone->ts->regs + zone->sg->thermctl_lvl0_offset); 565 + 566 + thermal_irq_enable(zone); 567 + 568 + return 0; 569 + } 570 + 666 571 static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { 667 572 .get_temp = tegra_thermctl_get_temp, 668 573 .set_trip_temp = tegra_thermctl_set_trip_temp, 669 574 .get_trend = tegra_thermctl_get_trend, 575 + .set_trips = tegra_thermctl_set_trips, 670 576 }; 671 577 672 578 static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) ··· 749 555 * @dev: struct device * of the SOC_THERM instance 750 556 * 751 557 * Configure the SOC_THERM HW trip points, setting "THERMTRIP" 752 - * "THROTTLE" trip points , using "critical" or "hot" type trip_temp 558 + * "THROTTLE" trip points , using "thermtrips", "critical" or "hot" 559 + * type trip_temp 753 560 * from thermal zone. 754 561 * After they have been configured, THERMTRIP or THROTTLE will take 755 562 * action when the configured SoC thermal sensor group reaches a ··· 772 577 { 773 578 struct tegra_soctherm *ts = dev_get_drvdata(dev); 774 579 struct soctherm_throt_cfg *stc; 775 - int i, trip, temperature; 776 - int ret; 580 + int i, trip, temperature, ret; 777 581 778 - ret = tz->ops->get_crit_temp(tz, &temperature); 779 - if (ret) { 780 - dev_warn(dev, "thermtrip: %s: missing critical temperature\n", 781 - sg->name); 782 - goto set_throttle; 783 - } 582 + /* Get thermtrips. If missing, try to get critical trips. */ 583 + temperature = tsensor_group_thermtrip_get(ts, sg->id); 584 + if (min_low_temp == temperature) 585 + if (tz->ops->get_crit_temp(tz, &temperature)) 586 + temperature = max_high_temp; 784 587 785 588 ret = thermtrip_program(dev, sg, temperature); 786 589 if (ret) { 787 - dev_err(dev, "thermtrip: %s: error during enable\n", 788 - sg->name); 590 + dev_err(dev, "thermtrip: %s: error during enable\n", sg->name); 789 591 return ret; 790 592 } 791 593 792 - dev_info(dev, 793 - "thermtrip: will shut down when %s reaches %d mC\n", 594 + dev_info(dev, "thermtrip: will shut down when %s reaches %d mC\n", 794 595 sg->name, temperature); 795 596 796 - set_throttle: 797 597 ret = get_hot_temp(tz, &trip, &temperature); 798 598 if (ret) { 799 599 dev_info(dev, "throttrip: %s: missing hot temperature\n", ··· 796 606 return 0; 797 607 } 798 608 799 - for (i = 0; i < THROTTLE_SIZE; i++) { 609 + for (i = 0; i < THROTTLE_OC1; i++) { 800 610 struct thermal_cooling_device *cdev; 801 611 802 612 if (!ts->throt_cfgs[i].init) ··· 825 635 dev_info(dev, "throttrip: %s: missing throttle cdev\n", 826 636 sg->name); 827 637 638 + return 0; 639 + } 640 + 641 + static irqreturn_t soctherm_thermal_isr(int irq, void *dev_id) 642 + { 643 + struct tegra_soctherm *ts = dev_id; 644 + u32 r; 645 + 646 + /* Case for no lock: 647 + * Although interrupts are enabled in set_trips, there is still no need 648 + * to lock here because the interrupts are disabled before programming 649 + * new trip points. Hence there cant be a interrupt on the same sensor. 650 + * An interrupt can however occur on a sensor while trips are being 651 + * programmed on a different one. This beign a LEVEL interrupt won't 652 + * cause a new interrupt but this is taken care of by the re-reading of 653 + * the STATUS register in the thread function. 654 + */ 655 + r = readl(ts->regs + THERMCTL_INTR_STATUS); 656 + writel(r, ts->regs + THERMCTL_INTR_DISABLE); 657 + 658 + return IRQ_WAKE_THREAD; 659 + } 660 + 661 + /** 662 + * soctherm_thermal_isr_thread() - Handles a thermal interrupt request 663 + * @irq: The interrupt number being requested; not used 664 + * @dev_id: Opaque pointer to tegra_soctherm; 665 + * 666 + * Clears the interrupt status register if there are expected 667 + * interrupt bits set. 668 + * The interrupt(s) are then handled by updating the corresponding 669 + * thermal zones. 670 + * 671 + * An error is logged if any unexpected interrupt bits are set. 672 + * 673 + * Disabled interrupts are re-enabled. 674 + * 675 + * Return: %IRQ_HANDLED. Interrupt was handled and no further processing 676 + * is needed. 677 + */ 678 + static irqreturn_t soctherm_thermal_isr_thread(int irq, void *dev_id) 679 + { 680 + struct tegra_soctherm *ts = dev_id; 681 + struct thermal_zone_device *tz; 682 + u32 st, ex = 0, cp = 0, gp = 0, pl = 0, me = 0; 683 + 684 + st = readl(ts->regs + THERMCTL_INTR_STATUS); 685 + 686 + /* deliberately clear expected interrupts handled in SW */ 687 + cp |= st & TH_INTR_CD0_MASK; 688 + cp |= st & TH_INTR_CU0_MASK; 689 + 690 + gp |= st & TH_INTR_GD0_MASK; 691 + gp |= st & TH_INTR_GU0_MASK; 692 + 693 + pl |= st & TH_INTR_PD0_MASK; 694 + pl |= st & TH_INTR_PU0_MASK; 695 + 696 + me |= st & TH_INTR_MD0_MASK; 697 + me |= st & TH_INTR_MU0_MASK; 698 + 699 + ex |= cp | gp | pl | me; 700 + if (ex) { 701 + writel(ex, ts->regs + THERMCTL_INTR_STATUS); 702 + st &= ~ex; 703 + 704 + if (cp) { 705 + tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_CPU]; 706 + thermal_zone_device_update(tz, 707 + THERMAL_EVENT_UNSPECIFIED); 708 + } 709 + 710 + if (gp) { 711 + tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_GPU]; 712 + thermal_zone_device_update(tz, 713 + THERMAL_EVENT_UNSPECIFIED); 714 + } 715 + 716 + if (pl) { 717 + tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_PLLX]; 718 + thermal_zone_device_update(tz, 719 + THERMAL_EVENT_UNSPECIFIED); 720 + } 721 + 722 + if (me) { 723 + tz = ts->thermctl_tzs[TEGRA124_SOCTHERM_SENSOR_MEM]; 724 + thermal_zone_device_update(tz, 725 + THERMAL_EVENT_UNSPECIFIED); 726 + } 727 + } 728 + 729 + /* deliberately ignore expected interrupts NOT handled in SW */ 730 + ex |= TH_INTR_IGNORE_MASK; 731 + st &= ~ex; 732 + 733 + if (st) { 734 + /* Whine about any other unexpected INTR bits still set */ 735 + pr_err("soctherm: Ignored unexpected INTRs 0x%08x\n", st); 736 + writel(st, ts->regs + THERMCTL_INTR_STATUS); 737 + } 738 + 739 + return IRQ_HANDLED; 740 + } 741 + 742 + /** 743 + * soctherm_oc_intr_enable() - Enables the soctherm over-current interrupt 744 + * @alarm: The soctherm throttle id 745 + * @enable: Flag indicating enable the soctherm over-current 746 + * interrupt or disable it 747 + * 748 + * Enables a specific over-current pins @alarm to raise an interrupt if the flag 749 + * is set and the alarm corresponds to OC1, OC2, OC3, or OC4. 750 + */ 751 + static void soctherm_oc_intr_enable(struct tegra_soctherm *ts, 752 + enum soctherm_throttle_id alarm, 753 + bool enable) 754 + { 755 + u32 r; 756 + 757 + if (!enable) 758 + return; 759 + 760 + r = readl(ts->regs + OC_INTR_ENABLE); 761 + switch (alarm) { 762 + case THROTTLE_OC1: 763 + r = REG_SET_MASK(r, OC_INTR_OC1_MASK, 1); 764 + break; 765 + case THROTTLE_OC2: 766 + r = REG_SET_MASK(r, OC_INTR_OC2_MASK, 1); 767 + break; 768 + case THROTTLE_OC3: 769 + r = REG_SET_MASK(r, OC_INTR_OC3_MASK, 1); 770 + break; 771 + case THROTTLE_OC4: 772 + r = REG_SET_MASK(r, OC_INTR_OC4_MASK, 1); 773 + break; 774 + default: 775 + r = 0; 776 + break; 777 + } 778 + writel(r, ts->regs + OC_INTR_ENABLE); 779 + } 780 + 781 + /** 782 + * soctherm_handle_alarm() - Handles soctherm alarms 783 + * @alarm: The soctherm throttle id 784 + * 785 + * "Handles" over-current alarms (OC1, OC2, OC3, and OC4) by printing 786 + * a warning or informative message. 787 + * 788 + * Return: -EINVAL for @alarm = THROTTLE_OC3, otherwise 0 (success). 789 + */ 790 + static int soctherm_handle_alarm(enum soctherm_throttle_id alarm) 791 + { 792 + int rv = -EINVAL; 793 + 794 + switch (alarm) { 795 + case THROTTLE_OC1: 796 + pr_debug("soctherm: Successfully handled OC1 alarm\n"); 797 + rv = 0; 798 + break; 799 + 800 + case THROTTLE_OC2: 801 + pr_debug("soctherm: Successfully handled OC2 alarm\n"); 802 + rv = 0; 803 + break; 804 + 805 + case THROTTLE_OC3: 806 + pr_debug("soctherm: Successfully handled OC3 alarm\n"); 807 + rv = 0; 808 + break; 809 + 810 + case THROTTLE_OC4: 811 + pr_debug("soctherm: Successfully handled OC4 alarm\n"); 812 + rv = 0; 813 + break; 814 + 815 + default: 816 + break; 817 + } 818 + 819 + if (rv) 820 + pr_err("soctherm: ERROR in handling %s alarm\n", 821 + throt_names[alarm]); 822 + 823 + return rv; 824 + } 825 + 826 + /** 827 + * soctherm_edp_isr_thread() - log an over-current interrupt request 828 + * @irq: OC irq number. Currently not being used. See description 829 + * @arg: a void pointer for callback, currently not being used 830 + * 831 + * Over-current events are handled in hardware. This function is called to log 832 + * and handle any OC events that happened. Additionally, it checks every 833 + * over-current interrupt registers for registers are set but 834 + * was not expected (i.e. any discrepancy in interrupt status) by the function, 835 + * the discrepancy will logged. 836 + * 837 + * Return: %IRQ_HANDLED 838 + */ 839 + static irqreturn_t soctherm_edp_isr_thread(int irq, void *arg) 840 + { 841 + struct tegra_soctherm *ts = arg; 842 + u32 st, ex, oc1, oc2, oc3, oc4; 843 + 844 + st = readl(ts->regs + OC_INTR_STATUS); 845 + 846 + /* deliberately clear expected interrupts handled in SW */ 847 + oc1 = st & OC_INTR_OC1_MASK; 848 + oc2 = st & OC_INTR_OC2_MASK; 849 + oc3 = st & OC_INTR_OC3_MASK; 850 + oc4 = st & OC_INTR_OC4_MASK; 851 + ex = oc1 | oc2 | oc3 | oc4; 852 + 853 + pr_err("soctherm: OC ALARM 0x%08x\n", ex); 854 + if (ex) { 855 + writel(st, ts->regs + OC_INTR_STATUS); 856 + st &= ~ex; 857 + 858 + if (oc1 && !soctherm_handle_alarm(THROTTLE_OC1)) 859 + soctherm_oc_intr_enable(ts, THROTTLE_OC1, true); 860 + 861 + if (oc2 && !soctherm_handle_alarm(THROTTLE_OC2)) 862 + soctherm_oc_intr_enable(ts, THROTTLE_OC2, true); 863 + 864 + if (oc3 && !soctherm_handle_alarm(THROTTLE_OC3)) 865 + soctherm_oc_intr_enable(ts, THROTTLE_OC3, true); 866 + 867 + if (oc4 && !soctherm_handle_alarm(THROTTLE_OC4)) 868 + soctherm_oc_intr_enable(ts, THROTTLE_OC4, true); 869 + 870 + if (oc1 && soc_irq_cdata.irq_enable & BIT(0)) 871 + handle_nested_irq( 872 + irq_find_mapping(soc_irq_cdata.domain, 0)); 873 + 874 + if (oc2 && soc_irq_cdata.irq_enable & BIT(1)) 875 + handle_nested_irq( 876 + irq_find_mapping(soc_irq_cdata.domain, 1)); 877 + 878 + if (oc3 && soc_irq_cdata.irq_enable & BIT(2)) 879 + handle_nested_irq( 880 + irq_find_mapping(soc_irq_cdata.domain, 2)); 881 + 882 + if (oc4 && soc_irq_cdata.irq_enable & BIT(3)) 883 + handle_nested_irq( 884 + irq_find_mapping(soc_irq_cdata.domain, 3)); 885 + } 886 + 887 + if (st) { 888 + pr_err("soctherm: Ignored unexpected OC ALARM 0x%08x\n", st); 889 + writel(st, ts->regs + OC_INTR_STATUS); 890 + } 891 + 892 + return IRQ_HANDLED; 893 + } 894 + 895 + /** 896 + * soctherm_edp_isr() - Disables any active interrupts 897 + * @irq: The interrupt request number 898 + * @arg: Opaque pointer to an argument 899 + * 900 + * Writes to the OC_INTR_DISABLE register the over current interrupt status, 901 + * masking any asserted interrupts. Doing this prevents the same interrupts 902 + * from triggering this isr repeatedly. The thread woken by this isr will 903 + * handle asserted interrupts and subsequently unmask/re-enable them. 904 + * 905 + * The OC_INTR_DISABLE register indicates which OC interrupts 906 + * have been disabled. 907 + * 908 + * Return: %IRQ_WAKE_THREAD, handler requests to wake the handler thread 909 + */ 910 + static irqreturn_t soctherm_edp_isr(int irq, void *arg) 911 + { 912 + struct tegra_soctherm *ts = arg; 913 + u32 r; 914 + 915 + if (!ts) 916 + return IRQ_NONE; 917 + 918 + r = readl(ts->regs + OC_INTR_STATUS); 919 + writel(r, ts->regs + OC_INTR_DISABLE); 920 + 921 + return IRQ_WAKE_THREAD; 922 + } 923 + 924 + /** 925 + * soctherm_oc_irq_lock() - locks the over-current interrupt request 926 + * @data: Interrupt request data 927 + * 928 + * Looks up the chip data from @data and locks the mutex associated with 929 + * a particular over-current interrupt request. 930 + */ 931 + static void soctherm_oc_irq_lock(struct irq_data *data) 932 + { 933 + struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data); 934 + 935 + mutex_lock(&d->irq_lock); 936 + } 937 + 938 + /** 939 + * soctherm_oc_irq_sync_unlock() - Unlocks the OC interrupt request 940 + * @data: Interrupt request data 941 + * 942 + * Looks up the interrupt request data @data and unlocks the mutex associated 943 + * with a particular over-current interrupt request. 944 + */ 945 + static void soctherm_oc_irq_sync_unlock(struct irq_data *data) 946 + { 947 + struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data); 948 + 949 + mutex_unlock(&d->irq_lock); 950 + } 951 + 952 + /** 953 + * soctherm_oc_irq_enable() - Enables the SOC_THERM over-current interrupt queue 954 + * @data: irq_data structure of the chip 955 + * 956 + * Sets the irq_enable bit of SOC_THERM allowing SOC_THERM 957 + * to respond to over-current interrupts. 958 + * 959 + */ 960 + static void soctherm_oc_irq_enable(struct irq_data *data) 961 + { 962 + struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data); 963 + 964 + d->irq_enable |= BIT(data->hwirq); 965 + } 966 + 967 + /** 968 + * soctherm_oc_irq_disable() - Disables overcurrent interrupt requests 969 + * @irq_data: The interrupt request information 970 + * 971 + * Clears the interrupt request enable bit of the overcurrent 972 + * interrupt request chip data. 973 + * 974 + * Return: Nothing is returned (void) 975 + */ 976 + static void soctherm_oc_irq_disable(struct irq_data *data) 977 + { 978 + struct soctherm_oc_irq_chip_data *d = irq_data_get_irq_chip_data(data); 979 + 980 + d->irq_enable &= ~BIT(data->hwirq); 981 + } 982 + 983 + static int soctherm_oc_irq_set_type(struct irq_data *data, unsigned int type) 984 + { 985 + return 0; 986 + } 987 + 988 + /** 989 + * soctherm_oc_irq_map() - SOC_THERM interrupt request domain mapper 990 + * @h: Interrupt request domain 991 + * @virq: Virtual interrupt request number 992 + * @hw: Hardware interrupt request number 993 + * 994 + * Mapping callback function for SOC_THERM's irq_domain. When a SOC_THERM 995 + * interrupt request is called, the irq_domain takes the request's virtual 996 + * request number (much like a virtual memory address) and maps it to a 997 + * physical hardware request number. 998 + * 999 + * When a mapping doesn't already exist for a virtual request number, the 1000 + * irq_domain calls this function to associate the virtual request number with 1001 + * a hardware request number. 1002 + * 1003 + * Return: 0 1004 + */ 1005 + static int soctherm_oc_irq_map(struct irq_domain *h, unsigned int virq, 1006 + irq_hw_number_t hw) 1007 + { 1008 + struct soctherm_oc_irq_chip_data *data = h->host_data; 1009 + 1010 + irq_set_chip_data(virq, data); 1011 + irq_set_chip(virq, &data->irq_chip); 1012 + irq_set_nested_thread(virq, 1); 1013 + return 0; 1014 + } 1015 + 1016 + /** 1017 + * soctherm_irq_domain_xlate_twocell() - xlate for soctherm interrupts 1018 + * @d: Interrupt request domain 1019 + * @intspec: Array of u32s from DTs "interrupt" property 1020 + * @intsize: Number of values inside the intspec array 1021 + * @out_hwirq: HW IRQ value associated with this interrupt 1022 + * @out_type: The IRQ SENSE type for this interrupt. 1023 + * 1024 + * This Device Tree IRQ specifier translation function will translate a 1025 + * specific "interrupt" as defined by 2 DT values where the cell values map 1026 + * the hwirq number + 1 and linux irq flags. Since the output is the hwirq 1027 + * number, this function will subtract 1 from the value listed in DT. 1028 + * 1029 + * Return: 0 1030 + */ 1031 + static int soctherm_irq_domain_xlate_twocell(struct irq_domain *d, 1032 + struct device_node *ctrlr, const u32 *intspec, unsigned int intsize, 1033 + irq_hw_number_t *out_hwirq, unsigned int *out_type) 1034 + { 1035 + if (WARN_ON(intsize < 2)) 1036 + return -EINVAL; 1037 + 1038 + /* 1039 + * The HW value is 1 index less than the DT IRQ values. 1040 + * i.e. OC4 goes to HW index 3. 1041 + */ 1042 + *out_hwirq = intspec[0] - 1; 1043 + *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; 1044 + return 0; 1045 + } 1046 + 1047 + static const struct irq_domain_ops soctherm_oc_domain_ops = { 1048 + .map = soctherm_oc_irq_map, 1049 + .xlate = soctherm_irq_domain_xlate_twocell, 1050 + }; 1051 + 1052 + /** 1053 + * soctherm_oc_int_init() - Initial enabling of the over 1054 + * current interrupts 1055 + * @np: The devicetree node for soctherm 1056 + * @num_irqs: The number of new interrupt requests 1057 + * 1058 + * Sets the over current interrupt request chip data 1059 + * 1060 + * Return: 0 on success or if overcurrent interrupts are not enabled, 1061 + * -ENOMEM (out of memory), or irq_base if the function failed to 1062 + * allocate the irqs 1063 + */ 1064 + static int soctherm_oc_int_init(struct device_node *np, int num_irqs) 1065 + { 1066 + if (!num_irqs) { 1067 + pr_info("%s(): OC interrupts are not enabled\n", __func__); 1068 + return 0; 1069 + } 1070 + 1071 + mutex_init(&soc_irq_cdata.irq_lock); 1072 + soc_irq_cdata.irq_enable = 0; 1073 + 1074 + soc_irq_cdata.irq_chip.name = "soc_therm_oc"; 1075 + soc_irq_cdata.irq_chip.irq_bus_lock = soctherm_oc_irq_lock; 1076 + soc_irq_cdata.irq_chip.irq_bus_sync_unlock = 1077 + soctherm_oc_irq_sync_unlock; 1078 + soc_irq_cdata.irq_chip.irq_disable = soctherm_oc_irq_disable; 1079 + soc_irq_cdata.irq_chip.irq_enable = soctherm_oc_irq_enable; 1080 + soc_irq_cdata.irq_chip.irq_set_type = soctherm_oc_irq_set_type; 1081 + soc_irq_cdata.irq_chip.irq_set_wake = NULL; 1082 + 1083 + soc_irq_cdata.domain = irq_domain_add_linear(np, num_irqs, 1084 + &soctherm_oc_domain_ops, 1085 + &soc_irq_cdata); 1086 + 1087 + if (!soc_irq_cdata.domain) { 1088 + pr_err("%s: Failed to create IRQ domain\n", __func__); 1089 + return -ENOMEM; 1090 + } 1091 + 1092 + pr_debug("%s(): OC interrupts enabled successful\n", __func__); 828 1093 return 0; 829 1094 } 830 1095 ··· 1574 929 .set_cur_state = throt_set_cdev_state, 1575 930 }; 1576 931 932 + static int soctherm_thermtrips_parse(struct platform_device *pdev) 933 + { 934 + struct device *dev = &pdev->dev; 935 + struct tegra_soctherm *ts = dev_get_drvdata(dev); 936 + struct tsensor_group_thermtrips *tt = ts->soc->thermtrips; 937 + const int max_num_prop = ts->soc->num_ttgs * 2; 938 + u32 *tlb; 939 + int i, j, n, ret; 940 + 941 + if (!tt) 942 + return -ENOMEM; 943 + 944 + n = of_property_count_u32_elems(dev->of_node, "nvidia,thermtrips"); 945 + if (n <= 0) { 946 + dev_info(dev, 947 + "missing thermtrips, will use critical trips as shut down temp\n"); 948 + return n; 949 + } 950 + 951 + n = min(max_num_prop, n); 952 + 953 + tlb = devm_kcalloc(&pdev->dev, max_num_prop, sizeof(u32), GFP_KERNEL); 954 + if (!tlb) 955 + return -ENOMEM; 956 + ret = of_property_read_u32_array(dev->of_node, "nvidia,thermtrips", 957 + tlb, n); 958 + if (ret) { 959 + dev_err(dev, "invalid num ele: thermtrips:%d\n", ret); 960 + return ret; 961 + } 962 + 963 + i = 0; 964 + for (j = 0; j < n; j = j + 2) { 965 + if (tlb[j] >= TEGRA124_SOCTHERM_SENSOR_NUM) 966 + continue; 967 + 968 + tt[i].id = tlb[j]; 969 + tt[i].temp = tlb[j + 1]; 970 + i++; 971 + } 972 + 973 + return 0; 974 + } 975 + 976 + static void soctherm_oc_cfg_parse(struct device *dev, 977 + struct device_node *np_oc, 978 + struct soctherm_throt_cfg *stc) 979 + { 980 + u32 val; 981 + 982 + if (of_property_read_bool(np_oc, "nvidia,polarity-active-low")) 983 + stc->oc_cfg.active_low = 1; 984 + else 985 + stc->oc_cfg.active_low = 0; 986 + 987 + if (!of_property_read_u32(np_oc, "nvidia,count-threshold", &val)) { 988 + stc->oc_cfg.intr_en = 1; 989 + stc->oc_cfg.alarm_cnt_thresh = val; 990 + } 991 + 992 + if (!of_property_read_u32(np_oc, "nvidia,throttle-period-us", &val)) 993 + stc->oc_cfg.throt_period = val; 994 + 995 + if (!of_property_read_u32(np_oc, "nvidia,alarm-filter", &val)) 996 + stc->oc_cfg.alarm_filter = val; 997 + 998 + /* BRIEF throttling by default, do not support STICKY */ 999 + stc->oc_cfg.mode = OC_THROTTLE_MODE_BRIEF; 1000 + } 1001 + 1002 + static int soctherm_throt_cfg_parse(struct device *dev, 1003 + struct device_node *np, 1004 + struct soctherm_throt_cfg *stc) 1005 + { 1006 + struct tegra_soctherm *ts = dev_get_drvdata(dev); 1007 + int ret; 1008 + u32 val; 1009 + 1010 + ret = of_property_read_u32(np, "nvidia,priority", &val); 1011 + if (ret) { 1012 + dev_err(dev, "throttle-cfg: %s: invalid priority\n", stc->name); 1013 + return -EINVAL; 1014 + } 1015 + stc->priority = val; 1016 + 1017 + ret = of_property_read_u32(np, ts->soc->use_ccroc ? 1018 + "nvidia,cpu-throt-level" : 1019 + "nvidia,cpu-throt-percent", &val); 1020 + if (!ret) { 1021 + if (ts->soc->use_ccroc && 1022 + val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH) 1023 + stc->cpu_throt_level = val; 1024 + else if (!ts->soc->use_ccroc && val <= 100) 1025 + stc->cpu_throt_depth = val; 1026 + else 1027 + goto err; 1028 + } else { 1029 + goto err; 1030 + } 1031 + 1032 + ret = of_property_read_u32(np, "nvidia,gpu-throt-level", &val); 1033 + if (!ret && val <= TEGRA_SOCTHERM_THROT_LEVEL_HIGH) 1034 + stc->gpu_throt_level = val; 1035 + else 1036 + goto err; 1037 + 1038 + return 0; 1039 + 1040 + err: 1041 + dev_err(dev, "throttle-cfg: %s: no throt prop or invalid prop\n", 1042 + stc->name); 1043 + return -EINVAL; 1044 + } 1045 + 1577 1046 /** 1578 1047 * soctherm_init_hw_throt_cdev() - Parse the HW throttle configurations 1579 1048 * and register them as cooling devices. ··· 1698 939 struct tegra_soctherm *ts = dev_get_drvdata(dev); 1699 940 struct device_node *np_stc, *np_stcc; 1700 941 const char *name; 1701 - u32 val; 1702 - int i, r; 942 + int i; 1703 943 1704 944 for (i = 0; i < THROTTLE_SIZE; i++) { 1705 945 ts->throt_cfgs[i].name = throt_names[i]; ··· 1716 958 for_each_child_of_node(np_stc, np_stcc) { 1717 959 struct soctherm_throt_cfg *stc; 1718 960 struct thermal_cooling_device *tcd; 961 + int err; 1719 962 1720 963 name = np_stcc->name; 1721 964 stc = find_throttle_cfg_by_name(ts, name); ··· 1726 967 continue; 1727 968 } 1728 969 1729 - r = of_property_read_u32(np_stcc, "nvidia,priority", &val); 1730 - if (r) { 1731 - dev_info(dev, 1732 - "throttle-cfg: %s: missing priority\n", name); 970 + if (stc->init) { 971 + dev_err(dev, "throttle-cfg: %s: redefined!\n", name); 972 + of_node_put(np_stcc); 973 + break; 974 + } 975 + 976 + err = soctherm_throt_cfg_parse(dev, np_stcc, stc); 977 + if (err) 1733 978 continue; 1734 - } 1735 - stc->priority = val; 1736 979 1737 - if (ts->soc->use_ccroc) { 1738 - r = of_property_read_u32(np_stcc, 1739 - "nvidia,cpu-throt-level", 1740 - &val); 1741 - if (r) { 1742 - dev_info(dev, 1743 - "throttle-cfg: %s: missing cpu-throt-level\n", 1744 - name); 1745 - continue; 1746 - } 1747 - stc->cpu_throt_level = val; 980 + if (stc->id >= THROTTLE_OC1) { 981 + soctherm_oc_cfg_parse(dev, np_stcc, stc); 982 + stc->init = true; 1748 983 } else { 1749 - r = of_property_read_u32(np_stcc, 1750 - "nvidia,cpu-throt-percent", 1751 - &val); 1752 - if (r) { 1753 - dev_info(dev, 1754 - "throttle-cfg: %s: missing cpu-throt-percent\n", 1755 - name); 1756 - continue; 1757 - } 1758 - stc->cpu_throt_depth = val; 1759 - } 1760 984 1761 - tcd = thermal_of_cooling_device_register(np_stcc, 985 + tcd = thermal_of_cooling_device_register(np_stcc, 1762 986 (char *)name, ts, 1763 987 &throt_cooling_ops); 1764 - of_node_put(np_stcc); 1765 - if (IS_ERR_OR_NULL(tcd)) { 1766 - dev_err(dev, 1767 - "throttle-cfg: %s: failed to register cooling device\n", 1768 - name); 1769 - continue; 988 + if (IS_ERR_OR_NULL(tcd)) { 989 + dev_err(dev, 990 + "throttle-cfg: %s: failed to register cooling device\n", 991 + name); 992 + continue; 993 + } 994 + stc->cdev = tcd; 995 + stc->init = true; 1770 996 } 1771 997 1772 - stc->cdev = tcd; 1773 - stc->init = true; 1774 998 } 1775 999 1776 1000 of_node_put(np_stc); ··· 1883 1141 } 1884 1142 1885 1143 /** 1144 + * throttlectl_gpu_level_select() - selects throttling level for GPU 1145 + * @throt: the LIGHT/HEAVY of throttle event id 1146 + * 1147 + * This function programs soctherm's interface to GK20a NV_THERM to select 1148 + * pre-configured "Low", "Medium" or "Heavy" throttle levels. 1149 + * 1150 + * Return: boolean true if HW was programmed 1151 + */ 1152 + static void throttlectl_gpu_level_select(struct tegra_soctherm *ts, 1153 + enum soctherm_throttle_id throt) 1154 + { 1155 + u32 r, level, throt_vect; 1156 + 1157 + level = ts->throt_cfgs[throt].gpu_throt_level; 1158 + throt_vect = THROT_LEVEL_TO_DEPTH(level); 1159 + r = readl(ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU)); 1160 + r = REG_SET_MASK(r, THROT_PSKIP_CTRL_ENABLE_MASK, 1); 1161 + r = REG_SET_MASK(r, THROT_PSKIP_CTRL_VECT_GPU_MASK, throt_vect); 1162 + writel(r, ts->regs + THROT_PSKIP_CTRL(throt, THROTTLE_DEV_GPU)); 1163 + } 1164 + 1165 + static int soctherm_oc_cfg_program(struct tegra_soctherm *ts, 1166 + enum soctherm_throttle_id throt) 1167 + { 1168 + u32 r; 1169 + struct soctherm_oc_cfg *oc = &ts->throt_cfgs[throt].oc_cfg; 1170 + 1171 + if (oc->mode == OC_THROTTLE_MODE_DISABLED) 1172 + return -EINVAL; 1173 + 1174 + r = REG_SET_MASK(0, OC1_CFG_HW_RESTORE_MASK, 1); 1175 + r = REG_SET_MASK(r, OC1_CFG_THROTTLE_MODE_MASK, oc->mode); 1176 + r = REG_SET_MASK(r, OC1_CFG_ALARM_POLARITY_MASK, oc->active_low); 1177 + r = REG_SET_MASK(r, OC1_CFG_EN_THROTTLE_MASK, 1); 1178 + writel(r, ts->regs + ALARM_CFG(throt)); 1179 + writel(oc->throt_period, ts->regs + ALARM_THROTTLE_PERIOD(throt)); 1180 + writel(oc->alarm_cnt_thresh, ts->regs + ALARM_CNT_THRESHOLD(throt)); 1181 + writel(oc->alarm_filter, ts->regs + ALARM_FILTER(throt)); 1182 + soctherm_oc_intr_enable(ts, throt, oc->intr_en); 1183 + 1184 + return 0; 1185 + } 1186 + 1187 + /** 1886 1188 * soctherm_throttle_program() - programs pulse skippers' configuration 1887 1189 * @throt: the LIGHT/HEAVY of the throttle event id. 1888 1190 * ··· 1942 1156 if (!stc.init) 1943 1157 return; 1944 1158 1159 + if ((throt >= THROTTLE_OC1) && (soctherm_oc_cfg_program(ts, throt))) 1160 + return; 1161 + 1945 1162 /* Setup PSKIP parameters */ 1946 1163 if (ts->soc->use_ccroc) 1947 1164 throttlectl_cpu_level_select(ts, throt); 1948 1165 else 1949 1166 throttlectl_cpu_mn(ts, throt); 1167 + 1168 + throttlectl_gpu_level_select(ts, throt); 1950 1169 1951 1170 r = REG_SET_MASK(0, THROT_PRIORITY_LITE_PRIO_MASK, stc.priority); 1952 1171 writel(r, ts->regs + THROT_PRIORITY_CTRL(throt)); ··· 2004 1213 v = STATS_CTL_CLR_DN | STATS_CTL_EN_DN | 2005 1214 STATS_CTL_CLR_UP | STATS_CTL_EN_UP; 2006 1215 writel(v, ts->regs + THERMCTL_STATS_CTL); 1216 + } 1217 + 1218 + static int soctherm_interrupts_init(struct platform_device *pdev, 1219 + struct tegra_soctherm *tegra) 1220 + { 1221 + struct device_node *np = pdev->dev.of_node; 1222 + int ret; 1223 + 1224 + ret = soctherm_oc_int_init(np, TEGRA_SOC_OC_IRQ_MAX); 1225 + if (ret < 0) { 1226 + dev_err(&pdev->dev, "soctherm_oc_int_init failed\n"); 1227 + return ret; 1228 + } 1229 + 1230 + tegra->thermal_irq = platform_get_irq(pdev, 0); 1231 + if (tegra->thermal_irq < 0) { 1232 + dev_dbg(&pdev->dev, "get 'thermal_irq' failed.\n"); 1233 + return 0; 1234 + } 1235 + 1236 + tegra->edp_irq = platform_get_irq(pdev, 1); 1237 + if (tegra->edp_irq < 0) { 1238 + dev_dbg(&pdev->dev, "get 'edp_irq' failed.\n"); 1239 + return 0; 1240 + } 1241 + 1242 + ret = devm_request_threaded_irq(&pdev->dev, 1243 + tegra->thermal_irq, 1244 + soctherm_thermal_isr, 1245 + soctherm_thermal_isr_thread, 1246 + IRQF_ONESHOT, 1247 + dev_name(&pdev->dev), 1248 + tegra); 1249 + if (ret < 0) { 1250 + dev_err(&pdev->dev, "request_irq 'thermal_irq' failed.\n"); 1251 + return ret; 1252 + } 1253 + 1254 + ret = devm_request_threaded_irq(&pdev->dev, 1255 + tegra->edp_irq, 1256 + soctherm_edp_isr, 1257 + soctherm_edp_isr_thread, 1258 + IRQF_ONESHOT, 1259 + "soctherm_edp", 1260 + tegra); 1261 + if (ret < 0) { 1262 + dev_err(&pdev->dev, "request_irq 'edp_irq' failed.\n"); 1263 + return ret; 1264 + } 1265 + 1266 + return 0; 2007 1267 } 2008 1268 2009 1269 static void soctherm_init(struct platform_device *pdev) ··· 2134 1292 if (!tegra) 2135 1293 return -ENOMEM; 2136 1294 1295 + mutex_init(&tegra->thermctl_lock); 2137 1296 dev_set_drvdata(&pdev->dev, tegra); 2138 1297 2139 1298 tegra->soc = soc; ··· 2213 1370 if (err) 2214 1371 return err; 2215 1372 1373 + soctherm_thermtrips_parse(pdev); 1374 + 2216 1375 soctherm_init_hw_throt_cdev(pdev); 2217 1376 2218 1377 soctherm_init(pdev); ··· 2250 1405 if (err) 2251 1406 goto disable_clocks; 2252 1407 } 1408 + 1409 + err = soctherm_interrupts_init(pdev, tegra); 2253 1410 2254 1411 soctherm_debug_init(pdev); 2255 1412
+16
drivers/thermal/tegra/soctherm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 1 2 /* 2 3 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 4 * ··· 29 28 30 29 #define THERMCTL_THERMTRIP_CTL 0x80 31 30 /* BITs are defined in device file */ 31 + 32 + #define THERMCTL_INTR_ENABLE 0x88 33 + #define THERMCTL_INTR_DISABLE 0x8c 34 + #define TH_INTR_UP_DN_EN 0x3 35 + #define THERM_IRQ_MEM_MASK (TH_INTR_UP_DN_EN << 24) 36 + #define THERM_IRQ_GPU_MASK (TH_INTR_UP_DN_EN << 16) 37 + #define THERM_IRQ_CPU_MASK (TH_INTR_UP_DN_EN << 8) 38 + #define THERM_IRQ_TSENSE_MASK (TH_INTR_UP_DN_EN << 0) 32 39 33 40 #define SENSOR_PDIV 0x1c0 34 41 #define SENSOR_PDIV_CPU_MASK (0xf << 12) ··· 79 70 u32 thermtrip_enable_mask; 80 71 u32 thermtrip_any_en_mask; 81 72 u32 thermtrip_threshold_mask; 73 + u32 thermctl_isr_mask; 82 74 u16 thermctl_lvl0_offset; 83 75 u32 thermctl_lvl0_up_thresh_mask; 84 76 u32 thermctl_lvl0_dn_thresh_mask; ··· 100 90 */ 101 91 const s32 fuse_corr_alpha, fuse_corr_beta; 102 92 const struct tegra_tsensor_group *group; 93 + }; 94 + 95 + struct tsensor_group_thermtrips { 96 + u8 id; 97 + u32 temp; 103 98 }; 104 99 105 100 struct tegra_soctherm_fuse { ··· 128 113 const int thresh_grain; 129 114 const unsigned int bptt; 130 115 const bool use_ccroc; 116 + struct tsensor_group_thermtrips *thermtrips; 131 117 }; 132 118 133 119 int tegra_calc_shared_calib(const struct tegra_soctherm_fuse *tfuse,
+6 -1
drivers/thermal/tegra/tegra124-soctherm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 + * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved. 3 4 * 4 5 * This software is licensed under the terms of the GNU General Public 5 6 * License version 2, as published by the Free Software Foundation, and ··· 56 55 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 57 56 .thermtrip_enable_mask = TEGRA124_THERMTRIP_CPU_EN_MASK, 58 57 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_CPU_THRESH_MASK, 58 + .thermctl_isr_mask = THERM_IRQ_CPU_MASK, 59 59 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU, 60 60 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK, 61 61 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK, ··· 75 73 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 76 74 .thermtrip_enable_mask = TEGRA124_THERMTRIP_GPU_EN_MASK, 77 75 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK, 76 + .thermctl_isr_mask = THERM_IRQ_GPU_MASK, 78 77 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU, 79 78 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK, 80 79 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK, ··· 92 89 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 93 90 .thermtrip_enable_mask = TEGRA124_THERMTRIP_TSENSE_EN_MASK, 94 91 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_TSENSE_THRESH_MASK, 92 + .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK, 95 93 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE, 96 94 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK, 97 95 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK, ··· 111 107 .thermtrip_any_en_mask = TEGRA124_THERMTRIP_ANY_EN_MASK, 112 108 .thermtrip_enable_mask = TEGRA124_THERMTRIP_MEM_EN_MASK, 113 109 .thermtrip_threshold_mask = TEGRA124_THERMTRIP_GPUMEM_THRESH_MASK, 110 + .thermctl_isr_mask = THERM_IRQ_MEM_MASK, 114 111 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM, 115 112 .thermctl_lvl0_up_thresh_mask = TEGRA124_THERMCTL_LVL0_UP_THRESH_MASK, 116 113 .thermctl_lvl0_dn_thresh_mask = TEGRA124_THERMCTL_LVL0_DN_THRESH_MASK,
+6 -1
drivers/thermal/tegra/tegra132-soctherm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 + * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved. 3 4 * 4 5 * This software is licensed under the terms of the GNU General Public 5 6 * License version 2, as published by the Free Software Foundation, and ··· 56 55 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 57 56 .thermtrip_enable_mask = TEGRA132_THERMTRIP_CPU_EN_MASK, 58 57 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_CPU_THRESH_MASK, 58 + .thermctl_isr_mask = THERM_IRQ_CPU_MASK, 59 59 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU, 60 60 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK, 61 61 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK, ··· 75 73 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 76 74 .thermtrip_enable_mask = TEGRA132_THERMTRIP_GPU_EN_MASK, 77 75 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK, 76 + .thermctl_isr_mask = THERM_IRQ_GPU_MASK, 78 77 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU, 79 78 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK, 80 79 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK, ··· 92 89 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 93 90 .thermtrip_enable_mask = TEGRA132_THERMTRIP_TSENSE_EN_MASK, 94 91 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_TSENSE_THRESH_MASK, 92 + .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK, 95 93 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE, 96 94 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK, 97 95 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK, ··· 111 107 .thermtrip_any_en_mask = TEGRA132_THERMTRIP_ANY_EN_MASK, 112 108 .thermtrip_enable_mask = TEGRA132_THERMTRIP_MEM_EN_MASK, 113 109 .thermtrip_threshold_mask = TEGRA132_THERMTRIP_GPUMEM_THRESH_MASK, 110 + .thermctl_isr_mask = THERM_IRQ_MEM_MASK, 114 111 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM, 115 112 .thermctl_lvl0_up_thresh_mask = TEGRA132_THERMCTL_LVL0_UP_THRESH_MASK, 116 113 .thermctl_lvl0_dn_thresh_mask = TEGRA132_THERMCTL_LVL0_DN_THRESH_MASK,
+14 -1
drivers/thermal/tegra/tegra210-soctherm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 1 2 /* 2 - * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 + * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved. 3 4 * 4 5 * This software is licensed under the terms of the GNU General Public 5 6 * License version 2, as published by the Free Software Foundation, and ··· 57 56 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 58 57 .thermtrip_enable_mask = TEGRA210_THERMTRIP_CPU_EN_MASK, 59 58 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_CPU_THRESH_MASK, 59 + .thermctl_isr_mask = THERM_IRQ_CPU_MASK, 60 60 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_CPU, 61 61 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, 62 62 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, ··· 76 74 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 77 75 .thermtrip_enable_mask = TEGRA210_THERMTRIP_GPU_EN_MASK, 78 76 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, 77 + .thermctl_isr_mask = THERM_IRQ_GPU_MASK, 79 78 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_GPU, 80 79 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, 81 80 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, ··· 93 90 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 94 91 .thermtrip_enable_mask = TEGRA210_THERMTRIP_TSENSE_EN_MASK, 95 92 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_TSENSE_THRESH_MASK, 93 + .thermctl_isr_mask = THERM_IRQ_TSENSE_MASK, 96 94 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_TSENSE, 97 95 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, 98 96 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, ··· 112 108 .thermtrip_any_en_mask = TEGRA210_THERMTRIP_ANY_EN_MASK, 113 109 .thermtrip_enable_mask = TEGRA210_THERMTRIP_MEM_EN_MASK, 114 110 .thermtrip_threshold_mask = TEGRA210_THERMTRIP_GPUMEM_THRESH_MASK, 111 + .thermctl_isr_mask = THERM_IRQ_MEM_MASK, 115 112 .thermctl_lvl0_offset = THERMCTL_LEVEL0_GROUP_MEM, 116 113 .thermctl_lvl0_up_thresh_mask = TEGRA210_THERMCTL_LVL0_UP_THRESH_MASK, 117 114 .thermctl_lvl0_dn_thresh_mask = TEGRA210_THERMCTL_LVL0_DN_THRESH_MASK, ··· 208 203 .fuse_spare_realignment = 0, 209 204 }; 210 205 206 + struct tsensor_group_thermtrips tegra210_tsensor_thermtrips[] = { 207 + {.id = TEGRA124_SOCTHERM_SENSOR_NUM}, 208 + {.id = TEGRA124_SOCTHERM_SENSOR_NUM}, 209 + {.id = TEGRA124_SOCTHERM_SENSOR_NUM}, 210 + {.id = TEGRA124_SOCTHERM_SENSOR_NUM}, 211 + }; 212 + 211 213 const struct tegra_soctherm_soc tegra210_soctherm = { 212 214 .tsensors = tegra210_tsensors, 213 215 .num_tsensors = ARRAY_SIZE(tegra210_tsensors), ··· 224 212 .thresh_grain = TEGRA210_THRESH_GRAIN, 225 213 .bptt = TEGRA210_BPTT, 226 214 .use_ccroc = false, 215 + .thermtrips = tegra210_tsensor_thermtrips, 227 216 };
+6 -3
drivers/thermal/thermal-generic-adc.c
··· 29 29 int temp, temp_hi, temp_lo, adc_hi, adc_lo; 30 30 int i; 31 31 32 + if (!gti->lookup_table) 33 + return val; 34 + 32 35 for (i = 0; i < gti->nlookup_table; i++) { 33 36 if (val >= gti->lookup_table[2 * i + 1]) 34 37 break; ··· 84 81 85 82 ntable = of_property_count_elems_of_size(np, "temperature-lookup-table", 86 83 sizeof(u32)); 87 - if (ntable < 0) { 88 - dev_err(dev, "Lookup table is not provided\n"); 89 - return ntable; 84 + if (ntable <= 0) { 85 + dev_notice(dev, "no lookup table, assuming DAC channel returns milliCelcius\n"); 86 + return 0; 90 87 } 91 88 92 89 if (ntable % 2) {
+49
drivers/thermal/thermal_core.c
··· 1046 1046 } 1047 1047 EXPORT_SYMBOL_GPL(thermal_of_cooling_device_register); 1048 1048 1049 + static void thermal_cooling_device_release(struct device *dev, void *res) 1050 + { 1051 + thermal_cooling_device_unregister( 1052 + *(struct thermal_cooling_device **)res); 1053 + } 1054 + 1055 + /** 1056 + * devm_thermal_of_cooling_device_register() - register an OF thermal cooling 1057 + * device 1058 + * @dev: a valid struct device pointer of a sensor device. 1059 + * @np: a pointer to a device tree node. 1060 + * @type: the thermal cooling device type. 1061 + * @devdata: device private data. 1062 + * @ops: standard thermal cooling devices callbacks. 1063 + * 1064 + * This function will register a cooling device with device tree node reference. 1065 + * This interface function adds a new thermal cooling device (fan/processor/...) 1066 + * to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself 1067 + * to all the thermal zone devices registered at the same time. 1068 + * 1069 + * Return: a pointer to the created struct thermal_cooling_device or an 1070 + * ERR_PTR. Caller must check return value with IS_ERR*() helpers. 1071 + */ 1072 + struct thermal_cooling_device * 1073 + devm_thermal_of_cooling_device_register(struct device *dev, 1074 + struct device_node *np, 1075 + char *type, void *devdata, 1076 + const struct thermal_cooling_device_ops *ops) 1077 + { 1078 + struct thermal_cooling_device **ptr, *tcd; 1079 + 1080 + ptr = devres_alloc(thermal_cooling_device_release, sizeof(*ptr), 1081 + GFP_KERNEL); 1082 + if (!ptr) 1083 + return ERR_PTR(-ENOMEM); 1084 + 1085 + tcd = __thermal_cooling_device_register(np, type, devdata, ops); 1086 + if (IS_ERR(tcd)) { 1087 + devres_free(ptr); 1088 + return tcd; 1089 + } 1090 + 1091 + *ptr = tcd; 1092 + devres_add(dev, ptr); 1093 + 1094 + return tcd; 1095 + } 1096 + EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register); 1097 + 1049 1098 static void __unbind(struct thermal_zone_device *tz, int mask, 1050 1099 struct thermal_cooling_device *cdev) 1051 1100 {
+129
drivers/thermal/thermal_mmio.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <linux/of_address.h> 8 + #include <linux/platform_device.h> 9 + #include <linux/thermal.h> 10 + 11 + struct thermal_mmio { 12 + void __iomem *mmio_base; 13 + u32 (*read_mmio)(void __iomem *mmio_base); 14 + u32 mask; 15 + int factor; 16 + }; 17 + 18 + static u32 thermal_mmio_readb(void __iomem *mmio_base) 19 + { 20 + return readb(mmio_base); 21 + } 22 + 23 + static int thermal_mmio_get_temperature(void *private, int *temp) 24 + { 25 + int t; 26 + struct thermal_mmio *sensor = 27 + (struct thermal_mmio *)private; 28 + 29 + t = sensor->read_mmio(sensor->mmio_base) & sensor->mask; 30 + t *= sensor->factor; 31 + 32 + *temp = t; 33 + 34 + return 0; 35 + } 36 + 37 + static struct thermal_zone_of_device_ops thermal_mmio_ops = { 38 + .get_temp = thermal_mmio_get_temperature, 39 + }; 40 + 41 + static int thermal_mmio_probe(struct platform_device *pdev) 42 + { 43 + struct resource *resource; 44 + struct thermal_mmio *sensor; 45 + int (*sensor_init_func)(struct platform_device *pdev, 46 + struct thermal_mmio *sensor); 47 + struct thermal_zone_device *thermal_zone; 48 + int ret; 49 + int temperature; 50 + 51 + sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL); 52 + if (!sensor) 53 + return -ENOMEM; 54 + 55 + resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); 56 + if (IS_ERR(resource)) { 57 + dev_err(&pdev->dev, 58 + "fail to get platform memory resource (%ld)\n", 59 + PTR_ERR(resource)); 60 + return PTR_ERR(resource); 61 + } 62 + 63 + sensor->mmio_base = devm_ioremap_resource(&pdev->dev, resource); 64 + if (IS_ERR(sensor->mmio_base)) { 65 + dev_err(&pdev->dev, "failed to ioremap memory (%ld)\n", 66 + PTR_ERR(sensor->mmio_base)); 67 + return PTR_ERR(sensor->mmio_base); 68 + } 69 + 70 + sensor_init_func = device_get_match_data(&pdev->dev); 71 + if (sensor_init_func) { 72 + ret = sensor_init_func(pdev, sensor); 73 + if (ret) { 74 + dev_err(&pdev->dev, 75 + "failed to initialize sensor (%d)\n", 76 + ret); 77 + return ret; 78 + } 79 + } 80 + 81 + thermal_zone = devm_thermal_zone_of_sensor_register(&pdev->dev, 82 + 0, 83 + sensor, 84 + &thermal_mmio_ops); 85 + if (IS_ERR(thermal_zone)) { 86 + dev_err(&pdev->dev, 87 + "failed to register sensor (%ld)\n", 88 + PTR_ERR(thermal_zone)); 89 + return PTR_ERR(thermal_zone); 90 + } 91 + 92 + thermal_mmio_get_temperature(sensor, &temperature); 93 + dev_info(&pdev->dev, 94 + "thermal mmio sensor %s registered, current temperature: %d\n", 95 + pdev->name, temperature); 96 + 97 + return 0; 98 + } 99 + 100 + static int al_thermal_init(struct platform_device *pdev, 101 + struct thermal_mmio *sensor) 102 + { 103 + sensor->read_mmio = thermal_mmio_readb; 104 + sensor->mask = 0xff; 105 + sensor->factor = 1000; 106 + 107 + return 0; 108 + } 109 + 110 + static const struct of_device_id thermal_mmio_id_table[] = { 111 + { .compatible = "amazon,al-thermal", .data = al_thermal_init}, 112 + {} 113 + }; 114 + MODULE_DEVICE_TABLE(of, thermal_mmio_id_table); 115 + 116 + static struct platform_driver thermal_mmio_driver = { 117 + .probe = thermal_mmio_probe, 118 + .driver = { 119 + .name = "thermal-mmio", 120 + .owner = THIS_MODULE, 121 + .of_match_table = of_match_ptr(thermal_mmio_id_table), 122 + }, 123 + }; 124 + 125 + module_platform_driver(thermal_mmio_driver); 126 + 127 + MODULE_AUTHOR("Talel Shenhar <talel@amazon.com>"); 128 + MODULE_DESCRIPTION("Thermal MMIO Driver"); 129 + MODULE_LICENSE("GPL v2");
+4 -4
include/dt-bindings/thermal/tegra124-soctherm.h
··· 12 12 #define TEGRA124_SOCTHERM_SENSOR_PLLX 3 13 13 #define TEGRA124_SOCTHERM_SENSOR_NUM 4 14 14 15 - #define TEGRA_SOCTHERM_THROT_LEVEL_LOW 0 16 - #define TEGRA_SOCTHERM_THROT_LEVEL_MED 1 17 - #define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2 18 - #define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1 15 + #define TEGRA_SOCTHERM_THROT_LEVEL_NONE 0 16 + #define TEGRA_SOCTHERM_THROT_LEVEL_LOW 1 17 + #define TEGRA_SOCTHERM_THROT_LEVEL_MED 2 18 + #define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 3 19 19 20 20 #endif
+13
include/linux/thermal.h
··· 447 447 struct thermal_cooling_device * 448 448 thermal_of_cooling_device_register(struct device_node *np, char *, void *, 449 449 const struct thermal_cooling_device_ops *); 450 + struct thermal_cooling_device * 451 + devm_thermal_of_cooling_device_register(struct device *dev, 452 + struct device_node *np, 453 + char *type, void *devdata, 454 + const struct thermal_cooling_device_ops *ops); 450 455 void thermal_cooling_device_unregister(struct thermal_cooling_device *); 451 456 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name); 452 457 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); ··· 508 503 thermal_of_cooling_device_register(struct device_node *np, 509 504 char *type, void *devdata, const struct thermal_cooling_device_ops *ops) 510 505 { return ERR_PTR(-ENODEV); } 506 + static inline struct thermal_cooling_device * 507 + devm_thermal_of_cooling_device_register(struct device *dev, 508 + struct device_node *np, 509 + char *type, void *devdata, 510 + const struct thermal_cooling_device_ops *ops) 511 + { 512 + return ERR_PTR(-ENODEV); 513 + } 511 514 static inline void thermal_cooling_device_unregister( 512 515 struct thermal_cooling_device *cdev) 513 516 { }