Merge tag 'thermal-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/therma...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 10 Jul 2021 18:43:25 +0000 (11:43 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 10 Jul 2021 18:43:25 +0000 (11:43 -0700)
Pull thermal updates from Daniel Lezcano:

 - Add rk3568 sensor support (Finley Xiao)

 - Add missing MODULE_DEVICE_TABLE for the Spreadtrum sensor (Chunyan
   Zhang)

 - Export additionnal attributes for the int340x thermal processor
   (Srinivas Pandruvada)

 - Add SC7280 compatible for the tsens driver (Rajeshwari Ravindra
   Kamble)

 - Fix kernel documentation for thermal_zone_device_unregister() and use
   devm_platform_get_and_ioremap_resource() (Yang Yingliang)

 - Fix coefficient calculations for the rcar_gen3 sensor driver (Niklas
   Söderlund)

 - Fix shadowing variable rcar_gen3_ths_tj_1 (Geert Uytterhoeven)

 - Add missing of_node_put() for the iMX and Spreadtrum sensors
   (Krzysztof Kozlowski)

 - Add tegra3 thermal sensor DT bindings (Dmitry Osipenko)

 - Stop the thermal zone monitoring when unregistering it to prevent a
   temperature update without the 'get_temp' callback (Dmitry Osipenko)

 - Add rk3568 DT bindings, convert bindings to yaml schemas and add the
   corresponding compatible in the Rockchip sensor (Ezequiel Garcia)

 - Add the sc8180x compatible for the Qualcomm tsensor (Bjorn Andersson)

 - Use the find_first_zero_bit() function instead of custom code (Andy
   Shevchenko)

 - Fix the kernel doc for the device cooling device (Yang Li)

 - Reorg the processor thermal int340x to set the scene for the PCI mmio
   driver (Srinivas Pandruvada)

 - Add PCI MMIO driver for the int340x processor thermal driver
   (Srinivas Pandruvada)

 - Add hwmon sensors for the mediatek sensor (Frank Wunderlich)

 - Fix warning for return value reported by Smatch for the int340x
   thermal processor (Srinivas Pandruvada)

 - Fix wrong register access and decoding for the int340x thermal
   processor (Srinivas Pandruvada)

* tag 'thermal-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux: (23 commits)
  thermal/drivers/int340x/processor_thermal: Fix tcc setting
  thermal/drivers/int340x/processor_thermal: Fix warning for return value
  thermal/drivers/mediatek: Add sensors-support
  thermal/drivers/int340x/processor_thermal: Add PCI MMIO based thermal driver
  thermal/drivers/int340x/processor_thermal: Split enumeration and processing part
  thermal: devfreq_cooling: Fix kernel-doc
  thermal/drivers/intel/intel_soc_dts_iosf: Switch to use find_first_zero_bit()
  dt-bindings: thermal: tsens: Add sc8180x compatible
  dt-bindings: rockchip-thermal: Support the RK3568 SoC compatible
  dt-bindings: thermal: convert rockchip-thermal to json-schema
  thermal/core/thermal_of: Stop zone device before unregistering it
  dt-bindings: thermal: Add binding for Tegra30 thermal sensor
  thermal/drivers/sprd: Add missing of_node_put for loop iteration
  thermal/drivers/imx_sc: Add missing of_node_put for loop iteration
  thermal/drivers/rcar_gen3_thermal: Do not shadow rcar_gen3_ths_tj_1
  thermal/drivers/rcar_gen3_thermal: Fix coefficient calculations
  thermal/drivers/st: Use devm_platform_get_and_ioremap_resource()
  thermal/core: Correct function name thermal_zone_device_unregister()
  dt-bindings: thermal: tsens: Add compatible string to TSENS binding for SC7280
  thermal/drivers/int340x: processor_thermal: Export additional attributes
  ...

22 files changed:
Documentation/devicetree/bindings/thermal/nvidia,tegra30-tsensor.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt [deleted file]
Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml [new file with mode: 0644]
drivers/thermal/devfreq_cooling.c
drivers/thermal/imx_sc_thermal.c
drivers/thermal/intel/int340x_thermal/Makefile
drivers/thermal/intel/int340x_thermal/int3401_thermal.c [new file with mode: 0644]
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c [new file with mode: 0644]
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c [new file with mode: 0644]
drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
drivers/thermal/intel/intel_soc_dts_iosf.c
drivers/thermal/mtk_thermal.c
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/rockchip_thermal.c
drivers/thermal/sprd_thermal.c
drivers/thermal/st/st_thermal_memmap.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_of.c

diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra30-tsensor.yaml b/Documentation/devicetree/bindings/thermal/nvidia,tegra30-tsensor.yaml
new file mode 100644 (file)
index 0000000..a35da25
--- /dev/null
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/nvidia,tegra30-tsensor.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra30 Thermal Sensor
+
+maintainers:
+  - Dmitry Osipenko <digetx@gmail.com>
+  - Jon Hunter <jonathanh@nvidia.com>
+  - Thierry Reding <thierry.reding@gmail.com>
+
+description: |
+  TSENSOR provides thermal and voltage sensors which monitor temperature
+  and voltage of the chip. Sensors are placed across the die to gauge the
+  temperature of the whole chip. The TSENSOR module:
+
+    Generates an interrupt to SW to lower temperature via DVFS on reaching
+    a certain thermal/voltage threshold.
+
+    Generates a signal to the CAR to reduce CPU frequency by half on reaching
+    a certain thermal/voltage threshold.
+
+    Generates a signal to the PMC when the temperature reaches dangerously high
+    levels to reset the chip and sets a flag in the PMC.
+
+  TSENSOR has two channels which monitor two different spots of the SoC.
+
+properties:
+  compatible:
+    const: nvidia,tegra30-tsensor
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  assigned-clock-parents: true
+  assigned-clock-rates: true
+  assigned-clocks: true
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - interrupts
+  - "#thermal-sensor-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    thermal-sensor@70014000 {
+      compatible = "nvidia,tegra30-tsensor";
+      reg = <0x70014000 0x500>;
+      interrupts = <0 102 4>;
+      clocks = <&clk 100>;
+      resets = <&rst 100>;
+
+      #thermal-sensor-cells = <1>;
+    };
index 0b3b6af..4a2eaf2 100644 (file)
@@ -46,6 +46,8 @@ properties:
               - qcom,msm8996-tsens
               - qcom,msm8998-tsens
               - qcom,sc7180-tsens
+              - qcom,sc7280-tsens
+              - qcom,sc8180x-tsens
               - qcom,sdm845-tsens
               - qcom,sm8150-tsens
               - qcom,sm8250-tsens
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
deleted file mode 100644 (file)
index 7f94669..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-* Temperature Sensor ADC (TSADC) on rockchip SoCs
-
-Required properties:
-- compatible : should be "rockchip,<name>-tsadc"
-   "rockchip,px30-tsadc":   found on PX30 SoCs
-   "rockchip,rv1108-tsadc": found on RV1108 SoCs
-   "rockchip,rk3228-tsadc": found on RK3228 SoCs
-   "rockchip,rk3288-tsadc": found on RK3288 SoCs
-   "rockchip,rk3328-tsadc": found on RK3328 SoCs
-   "rockchip,rk3368-tsadc": found on RK3368 SoCs
-   "rockchip,rk3399-tsadc": found on RK3399 SoCs
-- reg : physical base address of the controller and length of memory mapped
-       region.
-- interrupts : The interrupt number to the cpu. The interrupt specifier format
-              depends on the interrupt controller.
-- clocks : Must contain an entry for each entry in clock-names.
-- clock-names : Shall be "tsadc" for the converter-clock, and "apb_pclk" for
-               the peripheral clock.
-- resets : Must contain an entry for each entry in reset-names.
-          See ../reset/reset.txt for details.
-- reset-names : Must include the name "tsadc-apb".
-- pinctrl-names : The pin control state names;
-- pinctrl-0 : The "init" pinctrl state, it will be set before device probe.
-- pinctrl-1 : The "default" pinctrl state, it will be set after reset the
-             TSADC controller.
-- pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.
-- #thermal-sensor-cells : Should be 1. See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for a description.
-
-Optional properties:
-- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
-- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
-- rockchip,hw-tshut-polarity : The hardware-controlled active polarity 0:LOW
-                              1:HIGH.
-- rockchip,grf : The phandle of the syscon node for the general register file.
-
-Exiample:
-tsadc: tsadc@ff280000 {
-       compatible = "rockchip,rk3288-tsadc";
-       reg = <0xff280000 0x100>;
-       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-       clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
-       clock-names = "tsadc", "apb_pclk";
-       resets = <&cru SRST_TSADC>;
-       reset-names = "tsadc-apb";
-       pinctrl-names = "init", "default", "sleep";
-       pinctrl-0 = <&otp_gpio>;
-       pinctrl-1 = <&otp_out>;
-       pinctrl-2 = <&otp_gpio>;
-       #thermal-sensor-cells = <1>;
-       rockchip,hw-tshut-temp = <95000>;
-       rockchip,hw-tshut-mode = <0>;
-       rockchip,hw-tshut-polarity = <0>;
-};
-
-Example: referring to thermal sensors:
-thermal-zones {
-       cpu_thermal: cpu_thermal {
-               polling-delay-passive = <1000>; /* milliseconds */
-               polling-delay = <5000>; /* milliseconds */
-
-               /* sensor       ID */
-               thermal-sensors = <&tsadc       1>;
-
-               trips {
-                       cpu_alert0: cpu_alert {
-                               temperature = <70000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "passive";
-                       };
-                       cpu_crit: cpu_crit {
-                               temperature = <90000>; /* millicelsius */
-                               hysteresis = <2000>; /* millicelsius */
-                               type = "critical";
-                       };
-               };
-
-               cooling-maps {
-                       map0 {
-                               trip = <&cpu_alert0>;
-                               cooling-device =
-                                   <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-                       };
-               };
-       };
-};
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml b/Documentation/devicetree/bindings/thermal/rockchip-thermal.yaml
new file mode 100644 (file)
index 0000000..b96ea27
--- /dev/null
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/rockchip-thermal.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Temperature Sensor ADC (TSADC) on Rockchip SoCs
+
+maintainers:
+  - Heiko Stuebner <heiko@sntech.de>
+
+properties:
+  compatible:
+    enum:
+      - rockchip,px30-tsadc # PX30 SoCs
+      - rockchip,rv1108-tsadc # RV1108 SoCs
+      - rockchip,rk3228-tsadc # RK3228 SoCs
+      - rockchip,rk3288-tsadc # RK3288 SoCs
+      - rockchip,rk3328-tsadc # RK3328 SoCs
+      - rockchip,rk3368-tsadc # RK3368 SoCs
+      - rockchip,rk3399-tsadc # RK3399 SoCs
+      - rockchip,rk3568-tsadc # RK3568 SoCs
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    minItems: 2
+    maxItems: 2
+
+  clock-names:
+    items:
+      - const: tsadc
+      - const: apb_pclk
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: tsadc-apb
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  rockchip,grf:
+    description: The phandle of the syscon node for the general register file.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  rockchip,hw-tshut-temp:
+    description: The hardware-controlled shutdown temperature value.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  rockchip,hw-tshut-mode:
+    description: The hardware-controlled shutdown mode 0:CRU 1:GPIO.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+  rockchip,hw-tshut-polarity:
+    description: The hardware-controlled active polarity 0:LOW 1:HIGH.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - "#thermal-sensor-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/rk3288-cru.h>
+
+    tsadc: tsadc@ff280000 {
+        compatible = "rockchip,rk3288-tsadc";
+        reg = <0xff280000 0x100>;
+        interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+        clock-names = "tsadc", "apb_pclk";
+        resets = <&cru SRST_TSADC>;
+        reset-names = "tsadc-apb";
+        #thermal-sensor-cells = <1>;
+        rockchip,hw-tshut-temp = <95000>;
+        rockchip,hw-tshut-mode = <0>;
+        rockchip,hw-tshut-polarity = <0>;
+    };
index 3a788ac..5a86cff 100644 (file)
@@ -458,7 +458,7 @@ struct thermal_cooling_device *devfreq_cooling_register(struct devfreq *df)
 EXPORT_SYMBOL_GPL(devfreq_cooling_register);
 
 /**
- * devfreq_cooling_em_register_power() - Register devfreq cooling device with
+ * devfreq_cooling_em_register() - Register devfreq cooling device with
  *             power information and automatically register Energy Model (EM)
  * @df:                Pointer to devfreq device.
  * @dfc_power: Pointer to devfreq_cooling_power.
index b01d28e..8d76dbf 100644 (file)
@@ -93,6 +93,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
        for_each_available_child_of_node(np, child) {
                sensor = devm_kzalloc(&pdev->dev, sizeof(*sensor), GFP_KERNEL);
                if (!sensor) {
+                       of_node_put(child);
                        of_node_put(sensor_np);
                        return -ENOMEM;
                }
@@ -104,6 +105,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev,
                                "failed to get valid sensor resource id: %d\n",
                                ret);
+                       of_node_put(child);
                        break;
                }
 
@@ -114,6 +116,7 @@ static int imx_sc_thermal_probe(struct platform_device *pdev)
                if (IS_ERR(sensor->tzd)) {
                        dev_err(&pdev->dev, "failed to register thermal zone\n");
                        ret = PTR_ERR(sensor->tzd);
+                       of_node_put(child);
                        break;
                }
 
index 38a2731..4e852ce 100644 (file)
@@ -4,6 +4,9 @@ obj-$(CONFIG_INT340X_THERMAL)   += int340x_thermal_zone.o
 obj-$(CONFIG_INT340X_THERMAL)  += int3402_thermal.o
 obj-$(CONFIG_INT340X_THERMAL)  += int3403_thermal.o
 obj-$(CONFIG_INT340X_THERMAL)  += processor_thermal_device.o
+obj-$(CONFIG_INT340X_THERMAL)  += int3401_thermal.o
+obj-$(CONFIG_INT340X_THERMAL)  += processor_thermal_device_pci_legacy.o
+obj-$(CONFIG_INT340X_THERMAL)  += processor_thermal_device_pci.o
 obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o
 obj-$(CONFIG_INT340X_THERMAL)  += processor_thermal_rfim.o
 obj-$(CONFIG_INT340X_THERMAL)  += processor_thermal_mbox.o
diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c
new file mode 100644 (file)
index 0000000..acebc8b
--- /dev/null
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * INT3401 processor thermal device
+ * Copyright (c) 2020, Intel Corporation.
+ */
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#include "int340x_thermal_zone.h"
+#include "processor_thermal_device.h"
+
+static const struct acpi_device_id int3401_device_ids[] = {
+       {"INT3401", 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, int3401_device_ids);
+
+static int int3401_add(struct platform_device *pdev)
+{
+       struct proc_thermal_device *proc_priv;
+       int ret;
+
+       proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
+       if (!proc_priv)
+               return -ENOMEM;
+
+       ret = proc_thermal_add(&pdev->dev, proc_priv);
+       if (ret)
+               return ret;
+
+       platform_set_drvdata(pdev, proc_priv);
+
+       return ret;
+}
+
+static int int3401_remove(struct platform_device *pdev)
+{
+       proc_thermal_remove(platform_get_drvdata(pdev));
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int int3401_thermal_resume(struct device *dev)
+{
+       return proc_thermal_resume(dev);
+}
+#else
+#define int3401_thermal_resume NULL
+#endif
+
+static SIMPLE_DEV_PM_OPS(int3401_proc_thermal_pm, NULL, int3401_thermal_resume);
+
+static struct platform_driver int3401_driver = {
+       .probe = int3401_add,
+       .remove = int3401_remove,
+       .driver = {
+               .name = "int3401 thermal",
+               .acpi_match_table = int3401_device_ids,
+               .pm = &int3401_proc_thermal_pm,
+       },
+};
+
+static int __init proc_thermal_init(void)
+{
+       return platform_driver_register(&int3401_driver);
+}
+
+static void __exit proc_thermal_exit(void)
+{
+       platform_driver_unregister(&int3401_driver);
+}
+
+module_init(proc_thermal_init);
+module_exit(proc_thermal_exit);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
+MODULE_LICENSE("GPL v2");
index 9e6f2a8..0f0038a 100644 (file)
@@ -3,34 +3,17 @@
  * processor_thermal_device.c
  * Copyright (c) 2014, Intel Corporation.
  */
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/acpi.h>
 #include <linux/thermal.h>
-#include <linux/cpuhotplug.h>
 #include "int340x_thermal_zone.h"
 #include "processor_thermal_device.h"
 #include "../intel_soc_dts_iosf.h"
 
 #define DRV_NAME "proc_thermal"
 
-enum proc_thermal_emum_mode_type {
-       PROC_THERMAL_NONE,
-       PROC_THERMAL_PCI,
-       PROC_THERMAL_PLATFORM_DEV
-};
-
-/*
- * We can have only one type of enumeration, PCI or Platform,
- * not both. So we don't need instance specific data.
- */
-static enum proc_thermal_emum_mode_type proc_thermal_emum_mode =
-                                                       PROC_THERMAL_NONE;
-
 #define POWER_LIMIT_SHOW(index, suffix) \
 static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
                                        struct device_attribute *attr, \
@@ -38,11 +21,6 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
 { \
        struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); \
        \
-       if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
-               dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
-               return 0; \
-       } \
-       \
        return sprintf(buf, "%lu\n",\
        (unsigned long)proc_dev->power_limits[index].suffix * 1000); \
 }
@@ -100,24 +78,27 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
        if (err)
                return err;
 
-       val = (val >> 24) & 0xff;
+       val = (val >> 24) & 0x3f;
        return sprintf(buf, "%d\n", (int)val);
 }
 
-static int tcc_offset_update(int tcc)
+static int tcc_offset_update(unsigned int tcc)
 {
        u64 val;
        int err;
 
-       if (!tcc)
+       if (tcc > 63)
                return -EINVAL;
 
        err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
        if (err)
                return err;
 
-       val &= ~GENMASK_ULL(31, 24);
-       val |= (tcc & 0xff) << 24;
+       if (val & BIT(31))
+               return -EPERM;
+
+       val &= ~GENMASK_ULL(29, 24);
+       val |= (tcc & 0x3f) << 24;
 
        err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
        if (err)
@@ -126,14 +107,15 @@ static int tcc_offset_update(int tcc)
        return 0;
 }
 
-static int tcc_offset_save;
+static unsigned int tcc_offset_save;
 
 static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
                                struct device_attribute *attr, const char *buf,
                                size_t count)
 {
+       unsigned int tcc;
        u64 val;
-       int tcc, err;
+       int err;
 
        err = rdmsrl_safe(MSR_PLATFORM_INFO, &val);
        if (err)
@@ -142,7 +124,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
        if (!(val & BIT(30)))
                return -EACCES;
 
-       if (kstrtoint(buf, 0, &tcc))
+       if (kstrtouint(buf, 0, &tcc))
                return -EINVAL;
 
        err = tcc_offset_update(tcc);
@@ -291,11 +273,8 @@ static void proc_thermal_notify(acpi_handle handle, u32 event, void *data)
        }
 }
 
-
-static int proc_thermal_add(struct device *dev,
-                           struct proc_thermal_device **priv)
+int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
 {
-       struct proc_thermal_device *proc_priv;
        struct acpi_device *adev;
        acpi_status status;
        unsigned long long tmp;
@@ -306,13 +285,8 @@ static int proc_thermal_add(struct device *dev,
        if (!adev)
                return -ENODEV;
 
-       proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL);
-       if (!proc_priv)
-               return -ENOMEM;
-
        proc_priv->dev = dev;
        proc_priv->adev = adev;
-       *priv = proc_priv;
 
        ret = proc_thermal_read_ppcc(proc_priv);
        if (ret)
@@ -338,15 +312,29 @@ static int proc_thermal_add(struct device *dev,
        if (ret)
                goto remove_zone;
 
+       ret = sysfs_create_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr);
+       if (ret)
+               goto remove_notify;
+
+       ret = sysfs_create_group(&dev->kobj, &power_limit_attribute_group);
+       if (ret) {
+               sysfs_remove_file(&dev->kobj, &dev_attr_tcc_offset_degree_celsius.attr);
+               goto remove_notify;
+       }
+
        return 0;
 
+remove_notify:
+       acpi_remove_notify_handler(adev->handle,
+                                   ACPI_DEVICE_NOTIFY, proc_thermal_notify);
 remove_zone:
        int340x_thermal_zone_remove(proc_priv->int340x_zone);
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(proc_thermal_add);
 
-static void proc_thermal_remove(struct proc_thermal_device *proc_priv)
+void proc_thermal_remove(struct proc_thermal_device *proc_priv)
 {
        acpi_remove_notify_handler(proc_priv->adev->handle,
                                   ACPI_DEVICE_NOTIFY, proc_thermal_notify);
@@ -355,60 +343,24 @@ static void proc_thermal_remove(struct proc_thermal_device *proc_priv)
        sysfs_remove_group(&proc_priv->dev->kobj,
                           &power_limit_attribute_group);
 }
+EXPORT_SYMBOL_GPL(proc_thermal_remove);
 
-static int int3401_add(struct platform_device *pdev)
+int proc_thermal_resume(struct device *dev)
 {
-       struct proc_thermal_device *proc_priv;
-       int ret;
-
-       if (proc_thermal_emum_mode == PROC_THERMAL_PCI) {
-               dev_err(&pdev->dev, "error: enumerated as PCI dev\n");
-               return -ENODEV;
-       }
-
-       ret = proc_thermal_add(&pdev->dev, &proc_priv);
-       if (ret)
-               return ret;
-
-       platform_set_drvdata(pdev, proc_priv);
-       proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
-
-       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
-
-       ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group);
-       if (ret)
-               sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
+       struct proc_thermal_device *proc_dev;
 
-       return ret;
-}
+       proc_dev = dev_get_drvdata(dev);
+       proc_thermal_read_ppcc(proc_dev);
 
-static int int3401_remove(struct platform_device *pdev)
-{
-       proc_thermal_remove(platform_get_drvdata(pdev));
+       tcc_offset_update(tcc_offset_save);
 
        return 0;
 }
-
-static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid)
-{
-       struct proc_thermal_device *proc_priv;
-       struct pci_dev *pdev = devid;
-
-       proc_priv = pci_get_drvdata(pdev);
-
-       intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts);
-
-       return IRQ_HANDLED;
-}
+EXPORT_SYMBOL_GPL(proc_thermal_resume);
 
 #define MCHBAR 0
 
-static int proc_thermal_set_mmio_base(struct pci_dev *pdev,
-                                     struct proc_thermal_device *proc_priv)
+static int proc_thermal_set_mmio_base(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
 {
        int ret;
 
@@ -423,9 +375,9 @@ static int proc_thermal_set_mmio_base(struct pci_dev *pdev,
        return 0;
 }
 
-static int proc_thermal_mmio_add(struct pci_dev *pdev,
-                                struct proc_thermal_device *proc_priv,
-                                kernel_ulong_t feature_mask)
+int proc_thermal_mmio_add(struct pci_dev *pdev,
+                         struct proc_thermal_device *proc_priv,
+                         kernel_ulong_t feature_mask)
 {
        int ret;
 
@@ -471,11 +423,10 @@ err_rem_rapl:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(proc_thermal_mmio_add);
 
-static void proc_thermal_mmio_remove(struct pci_dev *pdev)
+void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
 {
-       struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
-
        if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_RAPL)
                proc_thermal_rapl_remove();
 
@@ -486,181 +437,7 @@ static void proc_thermal_mmio_remove(struct pci_dev *pdev)
        if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX)
                proc_thermal_mbox_remove(pdev);
 }
-
-static int  proc_thermal_pci_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *id)
-{
-       struct proc_thermal_device *proc_priv;
-       int ret;
-
-       if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) {
-               dev_err(&pdev->dev, "error: enumerated as platform dev\n");
-               return -ENODEV;
-       }
-
-       ret = pcim_enable_device(pdev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "error: could not enable device\n");
-               return ret;
-       }
-
-       ret = proc_thermal_add(&pdev->dev, &proc_priv);
-       if (ret)
-               return ret;
-
-       pci_set_drvdata(pdev, proc_priv);
-       proc_thermal_emum_mode = PROC_THERMAL_PCI;
-
-       if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) {
-               /*
-                * Enumerate additional DTS sensors available via IOSF.
-                * But we are not treating as a failure condition, if
-                * there are no aux DTSs enabled or fails. This driver
-                * already exposes sensors, which can be accessed via
-                * ACPI/MSR. So we don't want to fail for auxiliary DTSs.
-                */
-               proc_priv->soc_dts = intel_soc_dts_iosf_init(
-                                       INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
-
-               if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
-                       ret = pci_enable_msi(pdev);
-                       if (!ret) {
-                               ret = request_threaded_irq(pdev->irq, NULL,
-                                               proc_thermal_pci_msi_irq,
-                                               IRQF_ONESHOT, "proc_thermal",
-                                               pdev);
-                               if (ret) {
-                                       intel_soc_dts_iosf_exit(
-                                                       proc_priv->soc_dts);
-                                       pci_disable_msi(pdev);
-                                       proc_priv->soc_dts = NULL;
-                               }
-                       }
-               } else
-                       dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
-       }
-
-       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
-
-       ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&pdev->dev.kobj, &power_limit_attribute_group);
-       if (ret) {
-               sysfs_remove_file(&pdev->dev.kobj, &dev_attr_tcc_offset_degree_celsius.attr);
-               return ret;
-       }
-
-       ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
-       if (ret) {
-               proc_thermal_remove(proc_priv);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void  proc_thermal_pci_remove(struct pci_dev *pdev)
-{
-       struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
-
-       if (proc_priv->soc_dts) {
-               intel_soc_dts_iosf_exit(proc_priv->soc_dts);
-               if (pdev->irq) {
-                       free_irq(pdev->irq, pdev);
-                       pci_disable_msi(pdev);
-               }
-       }
-
-       proc_thermal_mmio_remove(pdev);
-       proc_thermal_remove(proc_priv);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int proc_thermal_resume(struct device *dev)
-{
-       struct proc_thermal_device *proc_dev;
-
-       proc_dev = dev_get_drvdata(dev);
-       proc_thermal_read_ppcc(proc_dev);
-
-       tcc_offset_update(tcc_offset_save);
-
-       return 0;
-}
-#else
-#define proc_thermal_resume NULL
-#endif
-
-static SIMPLE_DEV_PM_OPS(proc_thermal_pm, NULL, proc_thermal_resume);
-
-static const struct pci_device_id proc_thermal_pci_ids[] = {
-       { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
-       { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
-       { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) },
-       { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
-       { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) },
-       { },
-};
-
-MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
-
-static struct pci_driver proc_thermal_pci_driver = {
-       .name           = DRV_NAME,
-       .probe          = proc_thermal_pci_probe,
-       .remove         = proc_thermal_pci_remove,
-       .id_table       = proc_thermal_pci_ids,
-       .driver.pm      = &proc_thermal_pm,
-};
-
-static const struct acpi_device_id int3401_device_ids[] = {
-       {"INT3401", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, int3401_device_ids);
-
-static struct platform_driver int3401_driver = {
-       .probe = int3401_add,
-       .remove = int3401_remove,
-       .driver = {
-               .name = "int3401 thermal",
-               .acpi_match_table = int3401_device_ids,
-               .pm = &proc_thermal_pm,
-       },
-};
-
-static int __init proc_thermal_init(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&int3401_driver);
-       if (ret)
-               return ret;
-
-       ret = pci_register_driver(&proc_thermal_pci_driver);
-
-       return ret;
-}
-
-static void __exit proc_thermal_exit(void)
-{
-       platform_driver_unregister(&int3401_driver);
-       pci_unregister_driver(&proc_thermal_pci_driver);
-}
-
-module_init(proc_thermal_init);
-module_exit(proc_thermal_exit);
+EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
 
 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
index b9ed645..5a1cfe4 100644 (file)
@@ -44,6 +44,7 @@ struct proc_thermal_device {
        struct intel_soc_dts_sensors *soc_dts;
        u32 mmio_feature_mask;
        void __iomem *mmio_base;
+       void *priv_data;
 };
 
 struct rapl_mmio_regs {
@@ -79,4 +80,12 @@ void proc_thermal_rfim_remove(struct pci_dev *pdev);
 int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
 void proc_thermal_mbox_remove(struct pci_dev *pdev);
 
+int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp);
+int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv);
+void proc_thermal_remove(struct proc_thermal_device *proc_priv);
+int proc_thermal_resume(struct device *dev);
+int proc_thermal_mmio_add(struct pci_dev *pdev,
+                         struct proc_thermal_device *proc_priv,
+                         kernel_ulong_t feature_mask);
+void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *proc_priv);
 #endif
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
new file mode 100644 (file)
index 0000000..11dd2e8
--- /dev/null
@@ -0,0 +1,373 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Processor thermal device for newer processors
+ * Copyright (c) 2020, Intel Corporation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/thermal.h>
+
+#include "int340x_thermal_zone.h"
+#include "processor_thermal_device.h"
+
+#define DRV_NAME "proc_thermal_pci"
+
+struct proc_thermal_pci {
+       struct pci_dev *pdev;
+       struct proc_thermal_device *proc_priv;
+       struct thermal_zone_device *tzone;
+       struct delayed_work work;
+       int stored_thres;
+       int no_legacy;
+};
+
+enum proc_thermal_mmio_type {
+       PROC_THERMAL_MMIO_TJMAX,
+       PROC_THERMAL_MMIO_PP0_TEMP,
+       PROC_THERMAL_MMIO_PP1_TEMP,
+       PROC_THERMAL_MMIO_PKG_TEMP,
+       PROC_THERMAL_MMIO_THRES_0,
+       PROC_THERMAL_MMIO_THRES_1,
+       PROC_THERMAL_MMIO_INT_ENABLE_0,
+       PROC_THERMAL_MMIO_INT_ENABLE_1,
+       PROC_THERMAL_MMIO_INT_STATUS_0,
+       PROC_THERMAL_MMIO_INT_STATUS_1,
+       PROC_THERMAL_MMIO_MAX
+};
+
+struct proc_thermal_mmio_info {
+       enum proc_thermal_mmio_type mmio_type;
+       u64     mmio_addr;
+       u64     shift;
+       u64     mask;
+};
+
+static struct proc_thermal_mmio_info proc_thermal_mmio_info[] = {
+       { PROC_THERMAL_MMIO_TJMAX, 0x599c, 16, 0xff },
+       { PROC_THERMAL_MMIO_PP0_TEMP, 0x597c, 0, 0xff },
+       { PROC_THERMAL_MMIO_PP1_TEMP, 0x5980, 0, 0xff },
+       { PROC_THERMAL_MMIO_PKG_TEMP, 0x5978, 0, 0xff },
+       { PROC_THERMAL_MMIO_THRES_0, 0x5820, 8, 0x7F },
+       { PROC_THERMAL_MMIO_THRES_1, 0x5820, 16, 0x7F },
+       { PROC_THERMAL_MMIO_INT_ENABLE_0, 0x5820, 15, 0x01 },
+       { PROC_THERMAL_MMIO_INT_ENABLE_1, 0x5820, 23, 0x01 },
+       { PROC_THERMAL_MMIO_INT_STATUS_0, 0x7200, 6, 0x01 },
+       { PROC_THERMAL_MMIO_INT_STATUS_1, 0x7200, 8, 0x01 },
+};
+
+#define B0D4_THERMAL_NOTIFY_DELAY      1000
+static int notify_delay_ms = B0D4_THERMAL_NOTIFY_DELAY;
+
+static void proc_thermal_mmio_read(struct proc_thermal_pci *pci_info,
+                                   enum proc_thermal_mmio_type type,
+                                   u32 *value)
+{
+       *value = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
+                               proc_thermal_mmio_info[type].mmio_addr));
+       *value >>= proc_thermal_mmio_info[type].shift;
+       *value &= proc_thermal_mmio_info[type].mask;
+}
+
+static void proc_thermal_mmio_write(struct proc_thermal_pci *pci_info,
+                                    enum proc_thermal_mmio_type type,
+                                    u32 value)
+{
+       u32 current_val;
+       u32 mask;
+
+       current_val = ioread32(((u8 __iomem *)pci_info->proc_priv->mmio_base +
+                               proc_thermal_mmio_info[type].mmio_addr));
+       mask = proc_thermal_mmio_info[type].mask << proc_thermal_mmio_info[type].shift;
+       current_val &= ~mask;
+
+       value &= proc_thermal_mmio_info[type].mask;
+       value <<= proc_thermal_mmio_info[type].shift;
+
+       current_val |= value;
+       iowrite32(current_val, ((u8 __iomem *)pci_info->proc_priv->mmio_base +
+                               proc_thermal_mmio_info[type].mmio_addr));
+}
+
+/*
+ * To avoid sending two many messages to user space, we have 1 second delay.
+ * On interrupt we are disabling interrupt and enabling after 1 second.
+ * This workload function is delayed by 1 second.
+ */
+static void proc_thermal_threshold_work_fn(struct work_struct *work)
+{
+       struct delayed_work *delayed_work = to_delayed_work(work);
+       struct proc_thermal_pci *pci_info = container_of(delayed_work,
+                                               struct proc_thermal_pci, work);
+       struct thermal_zone_device *tzone = pci_info->tzone;
+
+       if (tzone)
+               thermal_zone_device_update(tzone, THERMAL_TRIP_VIOLATED);
+
+       /* Enable interrupt flag */
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
+}
+
+static void pkg_thermal_schedule_work(struct delayed_work *work)
+{
+       unsigned long ms = msecs_to_jiffies(notify_delay_ms);
+
+       schedule_delayed_work(work, ms);
+}
+
+static irqreturn_t proc_thermal_irq_handler(int irq, void *devid)
+{
+       struct proc_thermal_pci *pci_info = devid;
+       u32 status;
+
+       proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status);
+
+       /* Disable enable interrupt flag */
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
+       pci_write_config_byte(pci_info->pdev, 0xdc, 0x01);
+
+       pkg_thermal_schedule_work(&pci_info->work);
+
+       return IRQ_HANDLED;
+}
+
+static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+{
+       struct proc_thermal_pci *pci_info = tzd->devdata;
+       u32 _temp;
+
+       proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_PKG_TEMP, &_temp);
+       *temp = (unsigned long)_temp * 1000;
+
+       return 0;
+}
+
+static int sys_get_trip_temp(struct thermal_zone_device *tzd,
+                            int trip, int *temp)
+{
+       struct proc_thermal_pci *pci_info = tzd->devdata;
+       u32 _temp;
+
+       proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_THRES_0, &_temp);
+       if (!_temp) {
+               *temp = THERMAL_TEMP_INVALID;
+       } else {
+               int tjmax;
+
+               proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
+               _temp = tjmax - _temp;
+               *temp = (unsigned long)_temp * 1000;
+       }
+
+       return 0;
+}
+
+static int sys_get_trip_type(struct thermal_zone_device *tzd, int trip,
+                             enum thermal_trip_type *type)
+{
+       *type = THERMAL_TRIP_PASSIVE;
+
+       return 0;
+}
+
+static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
+{
+       struct proc_thermal_pci *pci_info = tzd->devdata;
+       int tjmax, _temp;
+
+       if (temp <= 0) {
+               cancel_delayed_work_sync(&pci_info->work);
+               proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
+               proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
+               thermal_zone_device_disable(tzd);
+               pci_info->stored_thres = 0;
+               return 0;
+       }
+
+       proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_TJMAX, &tjmax);
+       _temp = tjmax - (temp / 1000);
+       if (_temp < 0)
+               return -EINVAL;
+
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, _temp);
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
+
+       thermal_zone_device_enable(tzd);
+       pci_info->stored_thres = temp;
+
+       return 0;
+}
+
+static struct thermal_zone_device_ops tzone_ops = {
+       .get_temp = sys_get_curr_temp,
+       .get_trip_temp = sys_get_trip_temp,
+       .get_trip_type = sys_get_trip_type,
+       .set_trip_temp  = sys_set_trip_temp,
+};
+
+static struct thermal_zone_params tzone_params = {
+       .governor_name = "user_space",
+       .no_hwmon = true,
+};
+
+static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct proc_thermal_device *proc_priv;
+       struct proc_thermal_pci *pci_info;
+       int irq_flag = 0, irq, ret;
+
+       proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
+       if (!proc_priv)
+               return -ENOMEM;
+
+       pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
+       if (!pci_info)
+               return -ENOMEM;
+
+       pci_info->pdev = pdev;
+       ret = pcim_enable_device(pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "error: could not enable device\n");
+               return ret;
+       }
+
+       pci_set_master(pdev);
+
+       INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn);
+
+       ret = proc_thermal_add(&pdev->dev, proc_priv);
+       if (ret) {
+               dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n");
+               pci_info->no_legacy = 1;
+       }
+
+       proc_priv->priv_data = pci_info;
+       pci_info->proc_priv = proc_priv;
+       pci_set_drvdata(pdev, proc_priv);
+
+       ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
+       if (ret)
+               goto err_ret_thermal;
+
+       pci_info->tzone = thermal_zone_device_register("TCPU_PCI", 1, 1, pci_info,
+                                                       &tzone_ops,
+                                                       &tzone_params, 0, 0);
+       if (IS_ERR(pci_info->tzone)) {
+               ret = PTR_ERR(pci_info->tzone);
+               goto err_ret_mmio;
+       }
+
+       /* request and enable interrupt */
+       ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to allocate vectors!\n");
+               goto err_ret_tzone;
+       }
+       if (!pdev->msi_enabled && !pdev->msix_enabled)
+               irq_flag = IRQF_SHARED;
+
+       irq =  pci_irq_vector(pdev, 0);
+       ret = devm_request_threaded_irq(&pdev->dev, irq,
+                                       proc_thermal_irq_handler, NULL,
+                                       irq_flag, KBUILD_MODNAME, pci_info);
+       if (ret) {
+               dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq);
+               goto err_free_vectors;
+       }
+
+       return 0;
+
+err_free_vectors:
+       pci_free_irq_vectors(pdev);
+err_ret_tzone:
+       thermal_zone_device_unregister(pci_info->tzone);
+err_ret_mmio:
+       proc_thermal_mmio_remove(pdev, proc_priv);
+err_ret_thermal:
+       if (!pci_info->no_legacy)
+               proc_thermal_remove(proc_priv);
+       pci_disable_device(pdev);
+
+       return ret;
+}
+
+static void proc_thermal_pci_remove(struct pci_dev *pdev)
+{
+       struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
+       struct proc_thermal_pci *pci_info = proc_priv->priv_data;
+
+       cancel_delayed_work_sync(&pci_info->work);
+
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
+       proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
+
+       devm_free_irq(&pdev->dev, pdev->irq, pci_info);
+       pci_free_irq_vectors(pdev);
+
+       thermal_zone_device_unregister(pci_info->tzone);
+       proc_thermal_mmio_remove(pdev, pci_info->proc_priv);
+       if (!pci_info->no_legacy)
+               proc_thermal_remove(proc_priv);
+       pci_disable_device(pdev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int proc_thermal_pci_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct proc_thermal_device *proc_priv;
+       struct proc_thermal_pci *pci_info;
+
+       proc_priv = pci_get_drvdata(pdev);
+       pci_info = proc_priv->priv_data;
+
+       if (pci_info->stored_thres) {
+               proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0,
+                                        pci_info->stored_thres / 1000);
+               proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 1);
+       }
+
+       if (!pci_info->no_legacy)
+               return proc_thermal_resume(dev);
+
+       return 0;
+}
+#else
+#define proc_thermal_pci_resume NULL
+#endif
+
+static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
+
+static const struct pci_device_id proc_thermal_pci_ids[] = {
+       { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) },
+       { },
+};
+
+MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
+
+static struct pci_driver proc_thermal_pci_driver = {
+       .name           = DRV_NAME,
+       .probe          = proc_thermal_pci_probe,
+       .remove = proc_thermal_pci_remove,
+       .id_table       = proc_thermal_pci_ids,
+       .driver.pm      = &proc_thermal_pci_pm,
+};
+
+static int __init proc_thermal_init(void)
+{
+       return pci_register_driver(&proc_thermal_pci_driver);
+}
+
+static void __exit proc_thermal_exit(void)
+{
+       pci_unregister_driver(&proc_thermal_pci_driver);
+}
+
+module_init(proc_thermal_init);
+module_exit(proc_thermal_exit);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c
new file mode 100644 (file)
index 0000000..f5fc179
--- /dev/null
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * B0D4 processor thermal device
+ * Copyright (c) 2020, Intel Corporation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/thermal.h>
+
+#include "int340x_thermal_zone.h"
+#include "processor_thermal_device.h"
+#include "../intel_soc_dts_iosf.h"
+
+#define DRV_NAME "proc_thermal"
+
+static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid)
+{
+       struct proc_thermal_device *proc_priv;
+       struct pci_dev *pdev = devid;
+
+       proc_priv = pci_get_drvdata(pdev);
+
+       intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts);
+
+       return IRQ_HANDLED;
+}
+
+static int proc_thermal_pci_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *id)
+{
+       struct proc_thermal_device *proc_priv;
+       int ret;
+
+       ret = pcim_enable_device(pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "error: could not enable device\n");
+               return ret;
+       }
+
+       proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL);
+       if (!proc_priv)
+               return -ENOMEM;
+
+       ret = proc_thermal_add(&pdev->dev, proc_priv);
+       if (ret)
+               return ret;
+
+       pci_set_drvdata(pdev, proc_priv);
+
+       if (pdev->device == PCI_DEVICE_ID_INTEL_BSW_THERMAL) {
+               /*
+                * Enumerate additional DTS sensors available via IOSF.
+                * But we are not treating as a failure condition, if
+                * there are no aux DTSs enabled or fails. This driver
+                * already exposes sensors, which can be accessed via
+                * ACPI/MSR. So we don't want to fail for auxiliary DTSs.
+                */
+               proc_priv->soc_dts = intel_soc_dts_iosf_init(
+                                       INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
+
+               if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
+                       ret = pci_enable_msi(pdev);
+                       if (!ret) {
+                               ret = request_threaded_irq(pdev->irq, NULL,
+                                               proc_thermal_pci_msi_irq,
+                                               IRQF_ONESHOT, "proc_thermal",
+                                               pdev);
+                               if (ret) {
+                                       intel_soc_dts_iosf_exit(
+                                                       proc_priv->soc_dts);
+                                       pci_disable_msi(pdev);
+                                       proc_priv->soc_dts = NULL;
+                               }
+                       }
+               } else
+                       dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
+       } else {
+
+       }
+
+       ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data);
+       if (ret) {
+               proc_thermal_remove(proc_priv);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void proc_thermal_pci_remove(struct pci_dev *pdev)
+{
+       struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
+
+       if (proc_priv->soc_dts) {
+               intel_soc_dts_iosf_exit(proc_priv->soc_dts);
+               if (pdev->irq) {
+                       free_irq(pdev->irq, pdev);
+                       pci_disable_msi(pdev);
+               }
+       }
+
+       proc_thermal_mmio_remove(pdev, proc_priv);
+       proc_thermal_remove(proc_priv);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int proc_thermal_pci_resume(struct device *dev)
+{
+       return proc_thermal_resume(dev);
+}
+#else
+#define proc_thermal_pci_resume NULL
+#endif
+
+static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, NULL, proc_thermal_pci_resume);
+
+static const struct pci_device_id proc_thermal_pci_ids[] = {
+       { PCI_DEVICE_DATA(INTEL, BDW_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, BSW_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, BXT0_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, BXT1_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, BXTX_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, BXTP_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, CNL_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, CFL_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, GLK_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, HSB_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
+       { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) },
+       { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) },
+       { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) },
+       { },
+};
+
+MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids);
+
+static struct pci_driver proc_thermal_pci_driver = {
+       .name           = DRV_NAME,
+       .probe          = proc_thermal_pci_probe,
+       .remove         = proc_thermal_pci_remove,
+       .id_table       = proc_thermal_pci_ids,
+       .driver.pm      = &proc_thermal_pci_pm,
+};
+
+static int __init proc_thermal_init(void)
+{
+       return pci_register_driver(&proc_thermal_pci_driver);
+}
+
+static void __exit proc_thermal_exit(void)
+{
+       pci_unregister_driver(&proc_thermal_pci_driver);
+}
+
+module_init(proc_thermal_init);
+module_exit(proc_thermal_exit);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
+MODULE_LICENSE("GPL v2");
index 990f51f..59e93b0 100644 (file)
@@ -23,7 +23,7 @@
 
 static DEFINE_MUTEX(mbox_lock);
 
-static int send_mbox_cmd(struct pci_dev *pdev, u8 cmd_id, u32 cmd_data, u8 *cmd_resp)
+static int send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp)
 {
        struct proc_thermal_device *proc_priv;
        u32 retries, data;
@@ -82,6 +82,12 @@ unlock_mbox:
        return ret;
 }
 
+int processor_thermal_send_mbox_cmd(struct pci_dev *pdev, u16 cmd_id, u32 cmd_data, u32 *cmd_resp)
+{
+       return send_mbox_cmd(pdev, cmd_id, cmd_data, cmd_resp);
+}
+EXPORT_SYMBOL_GPL(processor_thermal_send_mbox_cmd);
+
 /* List of workload types */
 static const char * const workload_types[] = {
        "none",
@@ -147,7 +153,7 @@ static ssize_t workload_type_show(struct device *dev,
                                   char *buf)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       u8 cmd_resp;
+       u32 cmd_resp;
        int ret;
 
        ret = send_mbox_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, 0, &cmd_resp);
@@ -181,7 +187,7 @@ static bool workload_req_created;
 
 int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
 {
-       u8 cmd_resp;
+       u32 cmd_resp;
        int ret;
 
        /* Check if there is a mailbox support, if fails return success */
index aef993a..2b8a323 100644 (file)
@@ -190,6 +190,59 @@ static DEVICE_ATTR_RO(ddr_data_rate_point_2);
 static DEVICE_ATTR_RO(ddr_data_rate_point_3);
 static DEVICE_ATTR_RW(rfi_disable);
 
+static ssize_t rfi_restriction_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       u16 cmd_id = 0x0008;
+       u32 cmd_resp;
+       u32 input;
+       int ret;
+
+       ret = kstrtou32(buf, 10, &input);
+       if (ret)
+               return ret;
+
+       ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, input, &cmd_resp);
+       if (ret)
+               return ret;
+
+       return count;
+}
+
+static ssize_t rfi_restriction_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       u16 cmd_id = 0x0007;
+       u32 cmd_resp;
+       int ret;
+
+       ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "%u\n", cmd_resp);
+}
+
+static ssize_t ddr_data_rate_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
+{
+       u16 cmd_id = 0x0107;
+       u32 cmd_resp;
+       int ret;
+
+       ret = processor_thermal_send_mbox_cmd(to_pci_dev(dev), cmd_id, 0, &cmd_resp);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "%u\n", cmd_resp);
+}
+
+static DEVICE_ATTR_RW(rfi_restriction);
+static DEVICE_ATTR_RO(ddr_data_rate);
+
 static struct attribute *dvfs_attrs[] = {
        &dev_attr_rfi_restriction_run_busy.attr,
        &dev_attr_rfi_restriction_err_code.attr,
@@ -199,6 +252,8 @@ static struct attribute *dvfs_attrs[] = {
        &dev_attr_ddr_data_rate_point_2.attr,
        &dev_attr_ddr_data_rate_point_3.attr,
        &dev_attr_rfi_disable.attr,
+       &dev_attr_ddr_data_rate.attr,
+       &dev_attr_rfi_restriction.attr,
        NULL
 };
 
index 4f1a2f7..342b0bb 100644 (file)
@@ -350,13 +350,14 @@ int intel_soc_dts_iosf_add_read_only_critical_trip(
        int i, j;
 
        for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
-               for (j = 0; j < sensors->soc_dts[i].trip_count; ++j) {
-                       if (!(sensors->soc_dts[i].trip_mask & BIT(j))) {
-                               return update_trip_temp(&sensors->soc_dts[i], j,
-                                       sensors->tj_max - critical_offset,
-                                       THERMAL_TRIP_CRITICAL);
-                       }
-               }
+               struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i];
+               int temp = sensors->tj_max - critical_offset;
+               unsigned long count = entry->trip_count;
+               unsigned long mask = entry->trip_mask;
+
+               j = find_first_zero_bit(&mask, count);
+               if (j < count)
+                       return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL);
        }
 
        return -EINVAL;
index 97e8678..ede94ea 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/reset.h>
 #include <linux/types.h>
 
+#include "thermal_hwmon.h"
+
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V      0x008
 #define AUXADC_CON1_CLR_V      0x00c
@@ -1087,6 +1089,10 @@ static int mtk_thermal_probe(struct platform_device *pdev)
                goto err_disable_clk_peri_therm;
        }
 
+       ret = devm_thermal_add_hwmon_sysfs(tzdev);
+       if (ret)
+               dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+
        return 0;
 
 err_disable_clk_peri_therm:
index e1e4123..fdf16aa 100644 (file)
@@ -143,7 +143,7 @@ static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc,
         * Division is not scaled in BSP and if scaled it might overflow
         * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
         */
-       tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * 157)
+       tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * (ths_tj_1 - TJ_3))
                     / (ptat[0] - ptat[2])) + FIXPT_INT(TJ_3);
 
        tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
@@ -307,7 +307,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
 {
        struct rcar_gen3_thermal_priv *priv;
        struct device *dev = &pdev->dev;
-       const int *rcar_gen3_ths_tj_1 = of_device_get_match_data(dev);
+       const int *ths_tj_1 = of_device_get_match_data(dev);
        struct resource *res;
        struct thermal_zone_device *zone;
        int ret, i;
@@ -352,8 +352,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                priv->tscs[i] = tsc;
 
                priv->thermal_init(tsc);
-               rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i],
-                                            *rcar_gen3_ths_tj_1);
+               rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *ths_tj_1);
 
                zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
                                                            &rcar_gen3_tz_of_ops);
index aa9e0e3..657d84b 100644 (file)
@@ -211,7 +211,11 @@ struct rockchip_thermal_data {
 #define TSADCV3_AUTO_PERIOD_TIME               1875 /* 2.5ms */
 #define TSADCV3_AUTO_PERIOD_HT_TIME            1875 /* 2.5ms */
 
+#define TSADCV5_AUTO_PERIOD_TIME               1622 /* 2.5ms */
+#define TSADCV5_AUTO_PERIOD_HT_TIME            1622 /* 2.5ms */
+
 #define TSADCV2_USER_INTER_PD_SOC              0x340 /* 13 clocks */
+#define TSADCV5_USER_INTER_PD_SOC              0xfc0 /* 97us, at least 90us */
 
 #define GRF_SARADC_TESTBIT                     0x0e644
 #define GRF_TSADC_TESTBIT_L                    0x0e648
@@ -219,6 +223,12 @@ struct rockchip_thermal_data {
 
 #define PX30_GRF_SOC_CON2                      0x0408
 
+#define RK3568_GRF_TSADC_CON                   0x0600
+#define RK3568_GRF_TSADC_ANA_REG0              (0x10001 << 0)
+#define RK3568_GRF_TSADC_ANA_REG1              (0x10001 << 1)
+#define RK3568_GRF_TSADC_ANA_REG2              (0x10001 << 2)
+#define RK3568_GRF_TSADC_TSEN                  (0x10001 << 8)
+
 #define GRF_SARADC_TESTBIT_ON                  (0x10001 << 2)
 #define GRF_TSADC_TESTBIT_H_ON                 (0x10001 << 2)
 #define GRF_TSADC_VCM_EN_L                     (0x10001 << 7)
@@ -474,6 +484,45 @@ static const struct tsadc_table rk3399_code_table[] = {
        {TSADCV3_DATA_MASK, 125000},
 };
 
+static const struct tsadc_table rk3568_code_table[] = {
+       {0, -40000},
+       {1584, -40000},
+       {1620, -35000},
+       {1652, -30000},
+       {1688, -25000},
+       {1720, -20000},
+       {1756, -15000},
+       {1788, -10000},
+       {1824, -5000},
+       {1856, 0},
+       {1892, 5000},
+       {1924, 10000},
+       {1956, 15000},
+       {1992, 20000},
+       {2024, 25000},
+       {2060, 30000},
+       {2092, 35000},
+       {2128, 40000},
+       {2160, 45000},
+       {2196, 50000},
+       {2228, 55000},
+       {2264, 60000},
+       {2300, 65000},
+       {2332, 70000},
+       {2368, 75000},
+       {2400, 80000},
+       {2436, 85000},
+       {2468, 90000},
+       {2500, 95000},
+       {2536, 100000},
+       {2572, 105000},
+       {2604, 110000},
+       {2636, 115000},
+       {2672, 120000},
+       {2704, 125000},
+       {TSADCV2_DATA_MASK, 125000},
+};
+
 static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
                                   int temp)
 {
@@ -701,6 +750,49 @@ static void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs,
        regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
 }
 
+static void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs,
+                                 enum tshut_polarity tshut_polarity)
+{
+       writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON);
+       writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
+       writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
+                      regs + TSADCV2_HIGHT_INT_DEBOUNCE);
+       writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME,
+                      regs + TSADCV2_AUTO_PERIOD_HT);
+       writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
+                      regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
+
+       if (tshut_polarity == TSHUT_HIGH_ACTIVE)
+               writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
+                              regs + TSADCV2_AUTO_CON);
+       else
+               writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH,
+                              regs + TSADCV2_AUTO_CON);
+
+       /*
+        * The general register file will is optional
+        * and might not be available.
+        */
+       if (!IS_ERR(grf)) {
+               regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN);
+               /*
+                * RK3568 TRM, section 18.5. requires a delay no less
+                * than 10us between the rising edge of tsadc_tsen_en
+                * and the rising edge of tsadc_ana_reg_0/1/2.
+                */
+               udelay(15);
+               regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0);
+               regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1);
+               regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2);
+
+               /*
+                * RK3568 TRM, section 18.5. requires a delay no less
+                * than 90us after the rising edge of tsadc_ana_reg_0/1/2.
+                */
+               usleep_range(100, 200);
+       }
+}
+
 static void rk_tsadcv2_irq_ack(void __iomem *regs)
 {
        u32 val;
@@ -1027,6 +1119,31 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
        },
 };
 
+static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
+       .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
+       .chn_id[SENSOR_GPU] = 1, /* gpu sensor is channel 1 */
+       .chn_num = 2, /* two channels for tsadc */
+
+       .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
+       .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
+       .tshut_temp = 95000,
+
+       .initialize = rk_tsadcv7_initialize,
+       .irq_ack = rk_tsadcv3_irq_ack,
+       .control = rk_tsadcv3_control,
+       .get_temp = rk_tsadcv2_get_temp,
+       .set_alarm_temp = rk_tsadcv2_alarm_temp,
+       .set_tshut_temp = rk_tsadcv2_tshut_temp,
+       .set_tshut_mode = rk_tsadcv2_tshut_mode,
+
+       .table = {
+               .id = rk3568_code_table,
+               .length = ARRAY_SIZE(rk3568_code_table),
+               .data_mask = TSADCV2_DATA_MASK,
+               .mode = ADC_INCREMENT,
+       },
+};
+
 static const struct of_device_id of_rockchip_thermal_match[] = {
        {       .compatible = "rockchip,px30-tsadc",
                .data = (void *)&px30_tsadc_data,
@@ -1059,6 +1176,10 @@ static const struct of_device_id of_rockchip_thermal_match[] = {
                .compatible = "rockchip,rk3399-tsadc",
                .data = (void *)&rk3399_tsadc_data,
        },
+       {
+               .compatible = "rockchip,rk3568-tsadc",
+               .data = (void *)&rk3568_tsadc_data,
+       },
        { /* end */ },
 };
 MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
index 3682edb..fff80fc 100644 (file)
@@ -388,7 +388,7 @@ static int sprd_thm_probe(struct platform_device *pdev)
                sen = devm_kzalloc(&pdev->dev, sizeof(*sen), GFP_KERNEL);
                if (!sen) {
                        ret = -ENOMEM;
-                       goto disable_clk;
+                       goto of_put;
                }
 
                sen->data = thm;
@@ -397,13 +397,13 @@ static int sprd_thm_probe(struct platform_device *pdev)
                ret = of_property_read_u32(sen_child, "reg", &sen->id);
                if (ret) {
                        dev_err(&pdev->dev, "get sensor reg failed");
-                       goto disable_clk;
+                       goto of_put;
                }
 
                ret = sprd_thm_sensor_calibration(sen_child, thm, sen);
                if (ret) {
                        dev_err(&pdev->dev, "efuse cal analysis failed");
-                       goto disable_clk;
+                       goto of_put;
                }
 
                sprd_thm_sensor_init(thm, sen);
@@ -416,19 +416,20 @@ static int sprd_thm_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "register thermal zone failed %d\n",
                                sen->id);
                        ret = PTR_ERR(sen->tzd);
-                       goto disable_clk;
+                       goto of_put;
                }
 
                thm->sensor[sen->id] = sen;
        }
+       /* sen_child set to NULL at this point */
 
        ret = sprd_thm_set_ready(thm);
        if (ret)
-               goto disable_clk;
+               goto of_put;
 
        ret = sprd_thm_wait_temp_ready(thm);
        if (ret)
-               goto disable_clk;
+               goto of_put;
 
        for (i = 0; i < thm->nr_sensors; i++)
                sprd_thm_toggle_sensor(thm->sensor[i], true);
@@ -436,6 +437,8 @@ static int sprd_thm_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, thm);
        return 0;
 
+of_put:
+       of_node_put(sen_child);
 disable_clk:
        clk_disable_unprepare(thm->clk);
        return ret;
@@ -532,6 +535,7 @@ static const struct of_device_id sprd_thermal_of_match[] = {
        { .compatible = "sprd,ums512-thermal", .data = &ums512_data },
        { },
 };
+MODULE_DEVICE_TABLE(of, sprd_thermal_of_match);
 
 static const struct dev_pm_ops sprd_thermal_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume)
index a011445..d68596c 100644 (file)
@@ -119,19 +119,10 @@ static int st_mmap_regmap_init(struct st_thermal_sensor *sensor)
 {
        struct device *dev = sensor->dev;
        struct platform_device *pdev = to_platform_device(dev);
-       struct resource *res;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "no memory resources defined\n");
-               return -ENODEV;
-       }
-
-       sensor->mmio_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(sensor->mmio_base)) {
-               dev_err(dev, "failed to remap IO\n");
+       sensor->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+       if (IS_ERR(sensor->mmio_base))
                return PTR_ERR(sensor->mmio_base);
-       }
 
        sensor->regmap = devm_regmap_init_mmio(dev, sensor->mmio_base,
                                &st_416mpe_regmap_config);
index 10a2d8e..97ef9b0 100644 (file)
@@ -1315,7 +1315,7 @@ free_tz:
 EXPORT_SYMBOL_GPL(thermal_zone_device_register);
 
 /**
- * thermal_device_unregister - removes the registered thermal zone device
+ * thermal_zone_device_unregister - removes the registered thermal zone device
  * @tz: the thermal zone device to remove
  */
 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
index 5b76f9a..6379f26 100644 (file)
@@ -559,6 +559,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
        if (!tz)
                return;
 
+       /* stop temperature polling */
+       thermal_zone_device_disable(tzd);
+
        mutex_lock(&tzd->lock);
        tzd->ops->get_temp = NULL;
        tzd->ops->get_trend = NULL;