All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 0/6] Add LVTS architecture thermal
@ 2022-07-26 13:55 ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This series moves thermal files related to MediaTek to the mediatek folder.
And introduce the new architecture LVTS (low voltage thermal sensor) driver to report
the highest temperature in the SoC and record the highest temperature sensor,
each sensor as a hot zone.
The LVTS body is divided into two parts, the LVTS controller and the LVTS device.
The LVTS controller can connect up to 4 LVTS devices, and each LVTS device
can connect up to 7 TSMCUs.

The architecture will be the first to be used on mt8192 and mt8195.

Changelog:
Changes in v8:
        - Fix Coding style issues
        - Rebase to kernel-5.18.rc8
        - Rebase on top of these series :
          - [RESEND v8 00/19] Cleanup MediaTek clk reset drivers and support SoCs :
                https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
          - [PATCH v6 00/12] thermal OF rework :
                https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
        - Add multi-instance support and SRC Modularization :
          - Rewrite DTS and DT bindings
            - Add DT bindings for MT8195
            - One LVTS node for each HW Domain (AP and MCU)
          - One SW Instance for each HW Domain, for each SoC
          - Add an SRC file for each SoC (MT8192 and MT8195)
          - Add a Kconfig sub-menu entry for each SoC
        - Shrink LVTS instance iospace length from 0x1000 to 0x400
        - Replace platform_get_resource by platform_get_mem_or_io to get Base Address
        - Replace platform_get_resource by platform_get_irq to get Interrupt Number
        - Add "lvts_" prefix to functions and structs

Changes in v7:
        - Fix coding style issues
        - Rewrite dt bindings
          - was not accurate
          - Use mt8195 for example (instead of mt8192)
          - Rename mt6873 to mt8192
          - Remove clock name
        - Rebased on top of to series:
          - https://patchwork.kernel.org/project/linux-mediatek/list/?series=637849
          - https://patchwork.kernel.org/project/linux-pm/list/?series=639386

Changes in v6:
        - Remove temperature aggregation (it will be added in another series)
        - Update the way to read the temperature (read one sensor instead of all)
        - Add support of mt8195

Changes in v5:
        - Use 'git mv' for the relocated file.

Changes in v4:
        - Rebase to kernel-v5.13-rc1
        - Resend

Changes in v3:
        - change the expression in the lvts_temp_to_raw to dev_s64.

Changes in v2:
        - Rebase to kernel-5.11-rc1.
        - sort headers
        - remove initial value 0 of msr_raw in the lvts_temp_to_raw.
        - disconstruct the api of lvts_read_tc_msr_raw.
        - add the initial value max_temp = 0 and compare e.q.
          in the lvts_read_all_tc_temperature.
        - add the return with an invalid number in the lvts_init.

This series depends on [1] and [2].

[1]https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
[2]https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/

Alexandre Bailon (2):
  dt-bindings: thermal: Add binding document for LVTS thermal
    controllers
  arm64: dts: mt8195: Add efuse node to mt8195

Michael Kao (3):
  thermal: mediatek: Relocate driver to mediatek folder
  thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  thermal: mediatek: Add thermal zone settings for mt8195

Tinghan Shen (1):
  arm64: dts: mt8195: Add thermal zone

 .../thermal/mediatek,mt8192-lvts.yaml         |  73 ++
 .../thermal/mediatek,mt8195-lvts.yaml         |  75 ++
 arch/arm64/boot/dts/mediatek/mt8195.dtsi      | 131 ++-
 drivers/thermal/Kconfig                       |  14 +-
 drivers/thermal/Makefile                      |   2 +-
 drivers/thermal/mediatek/Kconfig              |  62 ++
 drivers/thermal/mediatek/Makefile             |   4 +
 drivers/thermal/mediatek/lvts_mt8192.c        | 241 +++++
 drivers/thermal/mediatek/lvts_mt8195.c        | 253 +++++
 .../{mtk_thermal.c => mediatek/soc_temp.c}    |   2 +-
 drivers/thermal/mediatek/soc_temp_lvts.c      | 928 ++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h      | 366 +++++++
 12 files changed, 2138 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
 create mode 100644 drivers/thermal/mediatek/Kconfig
 create mode 100644 drivers/thermal/mediatek/Makefile
 create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
 create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c
 rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (99%)
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v8 0/6] Add LVTS architecture thermal
@ 2022-07-26 13:55 ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This series moves thermal files related to MediaTek to the mediatek folder.
And introduce the new architecture LVTS (low voltage thermal sensor) driver to report
the highest temperature in the SoC and record the highest temperature sensor,
each sensor as a hot zone.
The LVTS body is divided into two parts, the LVTS controller and the LVTS device.
The LVTS controller can connect up to 4 LVTS devices, and each LVTS device
can connect up to 7 TSMCUs.

The architecture will be the first to be used on mt8192 and mt8195.

Changelog:
Changes in v8:
        - Fix Coding style issues
        - Rebase to kernel-5.18.rc8
        - Rebase on top of these series :
          - [RESEND v8 00/19] Cleanup MediaTek clk reset drivers and support SoCs :
                https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
          - [PATCH v6 00/12] thermal OF rework :
                https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
        - Add multi-instance support and SRC Modularization :
          - Rewrite DTS and DT bindings
            - Add DT bindings for MT8195
            - One LVTS node for each HW Domain (AP and MCU)
          - One SW Instance for each HW Domain, for each SoC
          - Add an SRC file for each SoC (MT8192 and MT8195)
          - Add a Kconfig sub-menu entry for each SoC
        - Shrink LVTS instance iospace length from 0x1000 to 0x400
        - Replace platform_get_resource by platform_get_mem_or_io to get Base Address
        - Replace platform_get_resource by platform_get_irq to get Interrupt Number
        - Add "lvts_" prefix to functions and structs

Changes in v7:
        - Fix coding style issues
        - Rewrite dt bindings
          - was not accurate
          - Use mt8195 for example (instead of mt8192)
          - Rename mt6873 to mt8192
          - Remove clock name
        - Rebased on top of to series:
          - https://patchwork.kernel.org/project/linux-mediatek/list/?series=637849
          - https://patchwork.kernel.org/project/linux-pm/list/?series=639386

Changes in v6:
        - Remove temperature aggregation (it will be added in another series)
        - Update the way to read the temperature (read one sensor instead of all)
        - Add support of mt8195

Changes in v5:
        - Use 'git mv' for the relocated file.

Changes in v4:
        - Rebase to kernel-v5.13-rc1
        - Resend

Changes in v3:
        - change the expression in the lvts_temp_to_raw to dev_s64.

Changes in v2:
        - Rebase to kernel-5.11-rc1.
        - sort headers
        - remove initial value 0 of msr_raw in the lvts_temp_to_raw.
        - disconstruct the api of lvts_read_tc_msr_raw.
        - add the initial value max_temp = 0 and compare e.q.
          in the lvts_read_all_tc_temperature.
        - add the return with an invalid number in the lvts_init.

This series depends on [1] and [2].

[1]https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
[2]https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/

Alexandre Bailon (2):
  dt-bindings: thermal: Add binding document for LVTS thermal
    controllers
  arm64: dts: mt8195: Add efuse node to mt8195

Michael Kao (3):
  thermal: mediatek: Relocate driver to mediatek folder
  thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  thermal: mediatek: Add thermal zone settings for mt8195

Tinghan Shen (1):
  arm64: dts: mt8195: Add thermal zone

 .../thermal/mediatek,mt8192-lvts.yaml         |  73 ++
 .../thermal/mediatek,mt8195-lvts.yaml         |  75 ++
 arch/arm64/boot/dts/mediatek/mt8195.dtsi      | 131 ++-
 drivers/thermal/Kconfig                       |  14 +-
 drivers/thermal/Makefile                      |   2 +-
 drivers/thermal/mediatek/Kconfig              |  62 ++
 drivers/thermal/mediatek/Makefile             |   4 +
 drivers/thermal/mediatek/lvts_mt8192.c        | 241 +++++
 drivers/thermal/mediatek/lvts_mt8195.c        | 253 +++++
 .../{mtk_thermal.c => mediatek/soc_temp.c}    |   2 +-
 drivers/thermal/mediatek/soc_temp_lvts.c      | 928 ++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h      | 366 +++++++
 12 files changed, 2138 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
 create mode 100644 drivers/thermal/mediatek/Kconfig
 create mode 100644 drivers/thermal/mediatek/Makefile
 create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
 create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c
 rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (99%)
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add Mediatek proprietary folder to upstream more thermal zone and cooler
drivers. Relocate the original thermal controller driver to it and rename
as soc_temp.c to show its purpose more clearly.

Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/Kconfig                       | 14 ++++-------
 drivers/thermal/Makefile                      |  2 +-
 drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
 drivers/thermal/mediatek/Makefile             |  1 +
 .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
 5 files changed, 29 insertions(+), 11 deletions(-)
 create mode 100644 drivers/thermal/mediatek/Kconfig
 create mode 100644 drivers/thermal/mediatek/Makefile
 rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 0e5cc948373c..ecba8d6e313b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -412,16 +412,10 @@ config DA9062_THERMAL
 	  zone.
 	  Compatible with the DA9062 and DA9061 PMICs.
 
-config MTK_THERMAL
-	tristate "Temperature sensor driver for mediatek SoCs"
-	depends on ARCH_MEDIATEK || COMPILE_TEST
-	depends on HAS_IOMEM
-	depends on NVMEM || NVMEM=n
-	depends on RESET_CONTROLLER
-	default y
-	help
-	  Enable this option if you want to have support for thermal management
-	  controller present in Mediatek SoCs
+menu "Mediatek thermal drivers"
+depends on ARCH_MEDIATEK || COMPILE_TEST
+source "drivers/thermal/mediatek/Kconfig"
+endmenu
 
 config AMLOGIC_THERMAL
 	tristate "Amlogic Thermal Support"
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index def8e1a0399c..3c00e864ad55 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -55,7 +55,7 @@ obj-y				+= st/
 obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-y				+= tegra/
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
-obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
+obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
 obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
 obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
 obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
new file mode 100644
index 000000000000..9c41e9079fc3
--- /dev/null
+++ b/drivers/thermal/mediatek/Kconfig
@@ -0,0 +1,23 @@
+config MTK_THERMAL
+	tristate "MediaTek thermal drivers"
+	depends on THERMAL_OF
+	help
+		This is the option for MediaTek thermal software
+		solutions. Please enable corresponding options to
+		get temperature information from thermal sensors or
+		turn on throttle mechaisms for thermal mitigation.
+
+if MTK_THERMAL
+
+config MTK_SOC_THERMAL
+	tristate "Temperature sensor driver for MediaTek SoCs"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_CONTROLLER
+	help
+		Enable this option if you want to get SoC temperature
+		information for MediaTek platforms. This driver
+		configures thermal controllers to collect temperature
+		via AUXADC interface.
+
+endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
new file mode 100644
index 000000000000..4b4cb04a358f
--- /dev/null
+++ b/drivers/thermal/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mediatek/soc_temp.c
similarity index 100%
rename from drivers/thermal/mtk_thermal.c
rename to drivers/thermal/mediatek/soc_temp.c
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add Mediatek proprietary folder to upstream more thermal zone and cooler
drivers. Relocate the original thermal controller driver to it and rename
as soc_temp.c to show its purpose more clearly.

Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/Kconfig                       | 14 ++++-------
 drivers/thermal/Makefile                      |  2 +-
 drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
 drivers/thermal/mediatek/Makefile             |  1 +
 .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
 5 files changed, 29 insertions(+), 11 deletions(-)
 create mode 100644 drivers/thermal/mediatek/Kconfig
 create mode 100644 drivers/thermal/mediatek/Makefile
 rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)

diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 0e5cc948373c..ecba8d6e313b 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -412,16 +412,10 @@ config DA9062_THERMAL
 	  zone.
 	  Compatible with the DA9062 and DA9061 PMICs.
 
-config MTK_THERMAL
-	tristate "Temperature sensor driver for mediatek SoCs"
-	depends on ARCH_MEDIATEK || COMPILE_TEST
-	depends on HAS_IOMEM
-	depends on NVMEM || NVMEM=n
-	depends on RESET_CONTROLLER
-	default y
-	help
-	  Enable this option if you want to have support for thermal management
-	  controller present in Mediatek SoCs
+menu "Mediatek thermal drivers"
+depends on ARCH_MEDIATEK || COMPILE_TEST
+source "drivers/thermal/mediatek/Kconfig"
+endmenu
 
 config AMLOGIC_THERMAL
 	tristate "Amlogic Thermal Support"
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index def8e1a0399c..3c00e864ad55 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -55,7 +55,7 @@ obj-y				+= st/
 obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-y				+= tegra/
 obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
-obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
+obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
 obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
 obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
 obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
new file mode 100644
index 000000000000..9c41e9079fc3
--- /dev/null
+++ b/drivers/thermal/mediatek/Kconfig
@@ -0,0 +1,23 @@
+config MTK_THERMAL
+	tristate "MediaTek thermal drivers"
+	depends on THERMAL_OF
+	help
+		This is the option for MediaTek thermal software
+		solutions. Please enable corresponding options to
+		get temperature information from thermal sensors or
+		turn on throttle mechaisms for thermal mitigation.
+
+if MTK_THERMAL
+
+config MTK_SOC_THERMAL
+	tristate "Temperature sensor driver for MediaTek SoCs"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_CONTROLLER
+	help
+		Enable this option if you want to get SoC temperature
+		information for MediaTek platforms. This driver
+		configures thermal controllers to collect temperature
+		via AUXADC interface.
+
+endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
new file mode 100644
index 000000000000..4b4cb04a358f
--- /dev/null
+++ b/drivers/thermal/mediatek/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mediatek/soc_temp.c
similarity index 100%
rename from drivers/thermal/mtk_thermal.c
rename to drivers/thermal/mediatek/soc_temp.c
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
 .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
 2 files changed, 148 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml

diff --git a/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml b/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
new file mode 100644
index 000000000000..8c5a02eb97c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/mediatek,mt8192-lvts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SoC LVTS thermal controller
+
+maintainers:
+  - Yu-Chia Chang <ethan.chang@mediatek.com>
+  - Ben Tseng <ben.tseng@mediatek.com>
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8192-lvts-ap
+      - mediatek,mt8192-lvts-mcu
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: SW reset HW AP/MCU domain for clean temporary data when HW initialization and resume.
+
+  nvmem-cells:
+    items:
+      - description: LVTS calibration data for thermal sensors
+
+  nvmem-cell-names:
+    items:
+      - const: lvts_calib_data
+
+required:
+  - compatible
+  - '#thermal-sensor-cells'
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - nvmem-cells
+  - nvmem-cell-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/thermal/thermal.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/mt8192-clk.h>
+    #include <dt-bindings/reset/mt8192-resets.h>
+
+      lvtsmcu: thermal-sensor@11278000 {
+        compatible = "mediatek,mt8192-lvts-mcu";
+        #thermal-sensor-cells = <1>;
+        reg = <0 0x11278000 0 0x400>;
+        interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+        clocks = <&infracfg_ao CLK_INFRA_THERM>;
+        resets = <&infracfg_ao MT8192_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+        nvmem-cells = <&lvts_efuse_data>;
+        nvmem-cell-names = "lvts_calib_data";
+      };
+
+...
diff --git a/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml b/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
new file mode 100644
index 000000000000..6b0b53a33272
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/mediatek,mt8195-lvts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SoC LVTS thermal controller
+
+maintainers:
+  - Yu-Chia Chang <ethan.chang@mediatek.com>
+  - Ben Tseng <ben.tseng@mediatek.com>
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8195-lvts-ap
+      - mediatek,mt8195-lvts-mcu
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: SW reset HW AP/MCU domain for clean temporary data when HW initialization and resume.
+
+  nvmem-cells:
+    items:
+      - description: LVTS calibration data 1 for thermal sensors
+      - description: LVTS calibration data 2 for thermal sensors
+
+  nvmem-cell-names:
+    items:
+      - const: lvts_calib_data1
+      - const: lvts_calib_data2
+
+required:
+  - compatible
+  - '#thermal-sensor-cells'
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - nvmem-cells
+  - nvmem-cell-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/thermal/thermal.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/mt8195-clk.h>
+    #include <dt-bindings/reset/mt8195-resets.h>
+
+      lvtsmcu: thermal-sensor@11278000 {
+        compatible = "mediatek,mt8195-lvts-mcu";
+        #thermal-sensor-cells = <1>;
+        reg = <0 0x11278000 0 0x400>;
+        interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+        clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+        resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+        nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+        nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+      };
+
+...
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
 .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
 2 files changed, 148 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
 create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml

diff --git a/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml b/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
new file mode 100644
index 000000000000..8c5a02eb97c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/mediatek,mt8192-lvts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SoC LVTS thermal controller
+
+maintainers:
+  - Yu-Chia Chang <ethan.chang@mediatek.com>
+  - Ben Tseng <ben.tseng@mediatek.com>
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8192-lvts-ap
+      - mediatek,mt8192-lvts-mcu
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: SW reset HW AP/MCU domain for clean temporary data when HW initialization and resume.
+
+  nvmem-cells:
+    items:
+      - description: LVTS calibration data for thermal sensors
+
+  nvmem-cell-names:
+    items:
+      - const: lvts_calib_data
+
+required:
+  - compatible
+  - '#thermal-sensor-cells'
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - nvmem-cells
+  - nvmem-cell-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/thermal/thermal.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/mt8192-clk.h>
+    #include <dt-bindings/reset/mt8192-resets.h>
+
+      lvtsmcu: thermal-sensor@11278000 {
+        compatible = "mediatek,mt8192-lvts-mcu";
+        #thermal-sensor-cells = <1>;
+        reg = <0 0x11278000 0 0x400>;
+        interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+        clocks = <&infracfg_ao CLK_INFRA_THERM>;
+        resets = <&infracfg_ao MT8192_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+        nvmem-cells = <&lvts_efuse_data>;
+        nvmem-cell-names = "lvts_calib_data";
+      };
+
+...
diff --git a/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml b/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
new file mode 100644
index 000000000000..6b0b53a33272
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/mediatek,mt8195-lvts.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek SoC LVTS thermal controller
+
+maintainers:
+  - Yu-Chia Chang <ethan.chang@mediatek.com>
+  - Ben Tseng <ben.tseng@mediatek.com>
+
+properties:
+  compatible:
+    enum:
+      - mediatek,mt8195-lvts-ap
+      - mediatek,mt8195-lvts-mcu
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    items:
+      - description: SW reset HW AP/MCU domain for clean temporary data when HW initialization and resume.
+
+  nvmem-cells:
+    items:
+      - description: LVTS calibration data 1 for thermal sensors
+      - description: LVTS calibration data 2 for thermal sensors
+
+  nvmem-cell-names:
+    items:
+      - const: lvts_calib_data1
+      - const: lvts_calib_data2
+
+required:
+  - compatible
+  - '#thermal-sensor-cells'
+  - reg
+  - interrupts
+  - clocks
+  - resets
+  - nvmem-cells
+  - nvmem-cell-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/thermal/thermal.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/mt8195-clk.h>
+    #include <dt-bindings/reset/mt8195-resets.h>
+
+      lvtsmcu: thermal-sensor@11278000 {
+        compatible = "mediatek,mt8195-lvts-mcu";
+        #thermal-sensor-cells = <1>;
+        reg = <0 0x11278000 0 0x400>;
+        interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+        clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+        resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+        nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+        nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+      };
+
+...
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add a LVTS (Low voltage thermal sensor) driver to report junction
temperatures in Mediatek SoC mt8192 and register the maximum temperature
of sensors and each sensor as a thermal zone.

Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/mediatek/Kconfig         |  27 +
 drivers/thermal/mediatek/Makefile        |   2 +
 drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
 drivers/thermal/mediatek/soc_temp.c      |   2 +-
 drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
 6 files changed, 1564 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
index 9c41e9079fc3..7fc04237dd50 100644
--- a/drivers/thermal/mediatek/Kconfig
+++ b/drivers/thermal/mediatek/Kconfig
@@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
 		configures thermal controllers to collect temperature
 		via AUXADC interface.
 
+config MTK_SOC_THERMAL_LVTS
+	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	help
+		Enable this option if you want to get SoC temperature
+		information for MediaTek platforms. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via Analog Serial Interface(ASIF).
+
+endif
+
+if MTK_SOC_THERMAL_LVTS
+
+config LVTS_MT8192
+	tristate "LVTS driver for MediaTek MT8192 SoC"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	depends on MTK_SOC_THERMAL_LVTS
+	help
+		Enable this option if you want to get SoC temperature
+		information for MT8192. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via ASIF.
+
 endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
index 4b4cb04a358f..5ff1197e80ab 100644
--- a/drivers/thermal/mediatek/Makefile
+++ b/drivers/thermal/mediatek/Makefile
@@ -1 +1,3 @@
 obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
+obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
+obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
new file mode 100644
index 000000000000..19e4e82c410b
--- /dev/null
+++ b/drivers/thermal/mediatek/lvts_mt8192.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include "soc_temp_lvts.h"
+
+enum mt8192_lvts_mcu_sensor_enum {
+	MT8192_TS1_0,
+	MT8192_TS1_1,
+	MT8192_TS2_0,
+	MT8192_TS2_1,
+	MT8192_TS3_0,
+	MT8192_TS3_1,
+	MT8192_TS3_2,
+	MT8192_TS3_3,
+	MT8192_NUM_TS_MCU
+};
+
+enum mt8192_lvts_ap_sensor_enum {
+	MT8192_TS4_0,
+	MT8192_TS4_1,
+	MT8192_TS5_0,
+	MT8192_TS5_1,
+	MT8192_TS6_0,
+	MT8192_TS6_1,
+	MT8192_TS7_0,
+	MT8192_TS7_1,
+	MT8192_TS7_2,
+	MT8192_NUM_TS_AP
+};
+
+static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j;
+	const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	for (i = 0; i < MT8192_NUM_TS_MCU; i++)
+		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
+
+	cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);
+
+	for (i = 0; i < (ARRAY_SIZE(mt8192_TS)); i++) {
+		for (j = 1; j <= 18; j++) {
+			cal_data->count_rc[mt8192_TS[i]] = (GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 16) +
+				(GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 8) +
+					GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24);
+		}
+	}
+}
+
+static void mt8192_ap_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j;
+	const unsigned int mt8192_TS[] = {MT8192_TS4_0, MT8192_TS5_0, MT8192_TS6_0, MT8192_TS7_0};
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	for (i = 0; i < MT8192_NUM_TS_AP; i++)
+		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
+
+	for (i = 0; i < (ARRAY_SIZE(mt8192_TS)); i++) {
+		for (j = 1; j <= 18; j++) {
+			cal_data->count_rc[mt8192_TS[i]] = (GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 16) +
+				(GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 8) +
+					GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24);
+		}
+	}
+}
+
+static struct lvts_speed_settings tc_speed_mt8192 = {
+	.period_unit = PERIOD_UNIT,
+	.group_interval_delay = GROUP_INTERVAL_DELAY,
+	.filter_interval_delay = FILTER_INTERVAL_DELAY,
+	.sensor_interval_delay = SENSOR_INTERVAL_DELAY,
+};
+
+static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
+	[0] = {
+		.dev_id = 0x81,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS1_0, MT8192_TS1_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x82,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS2_0, MT8192_TS2_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x83,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT8192_TS3_0, MT8192_TS3_1, MT8192_TS3_2, MT8192_TS3_3},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	}
+};
+
+static const struct lvts_tc_settings mt8192_tc_ap_settings[] = {
+	[0] = {
+		.dev_id = 0x84,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS4_0, MT8192_TS4_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x85,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS5_0, MT8192_TS5_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x86,
+		.addr_offset = 0x200,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS6_0, MT8192_TS6_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.dev_id = 0x87,
+		.addr_offset = 0x300,
+		.num_sensor = 3,
+		.sensor_map = {MT8192_TS7_0, MT8192_TS7_1, MT8192_TS7_2},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT2,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(6),
+	}
+};
+
+static const struct lvts_data mt8192_lvts_mcu_data = {
+	.num_tc = (ARRAY_SIZE(mt8192_tc_mcu_settings)),
+	.tc = mt8192_tc_mcu_settings,
+	.num_sensor = MT8192_NUM_TS_MCU,
+	.ops = {
+		.efuse_to_cal_data = mt8192_mcu_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct lvts_data mt8192_lvts_ap_data = {
+	.num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
+	.tc = mt8192_tc_ap_settings,
+	.num_sensor = MT8192_NUM_TS_AP,
+	.ops = {
+		.efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct of_device_id lvts_of_match[] = {
+	{ .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
+	{ .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvts_of_match);
+
+static struct platform_driver soc_temp_lvts = {
+	.probe = lvts_probe,
+	.remove = lvts_remove,
+	.suspend = lvts_suspend,
+	.resume = lvts_resume,
+	.driver = {
+		.name = "mtk-soc-temp-lvts-mt8192",
+		.of_match_table = lvts_of_match,
+	},
+};
+module_platform_driver(soc_temp_lvts);
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
index ede94eadddda..60924f8f98e9 100644
--- a/drivers/thermal/mediatek/soc_temp.c
+++ b/drivers/thermal/mediatek/soc_temp.c
@@ -23,7 +23,7 @@
 #include <linux/reset.h>
 #include <linux/types.h>
 
-#include "thermal_hwmon.h"
+#include "../thermal_hwmon.h"
 
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V	0x008
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
new file mode 100644
index 000000000000..ee7efc0de65f
--- /dev/null
+++ b/drivers/thermal/mediatek/soc_temp_lvts.c
@@ -0,0 +1,928 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/thermal.h>
+#include "soc_temp_lvts.h"
+
+static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
+{
+	/* This function returns degree mC */
+
+	int temp;
+
+	temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
+	temp = temp + co->golden_temp * 500 + co->b;
+
+	return temp;
+}
+
+static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
+{
+	unsigned int msr_raw;
+
+	msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
+		(-1 * co->a));
+
+	return msr_raw;
+}
+
+static int soc_temp_lvts_read_temp(void *data, int *temperature)
+{
+	struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
+	struct lvts_data *lvts_data = lvts_tz->lvts_data;
+	unsigned int msr_raw;
+
+	msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
+	if (msr_raw == 0)
+		return -EINVAL;
+
+	*temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
+	.get_temp = soc_temp_lvts_read_temp,
+};
+
+static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
+	int tc_id)
+{
+	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
+
+	usleep_range(5, 15);
+}
+
+static unsigned int lvts_read_device(struct lvts_data *lvts_data,
+	unsigned int reg_idx, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
+	unsigned int data;
+	int ret;
+
+	writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
+
+	usleep_range(5, 15);
+
+	ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
+		!(data & DEVICE_ACCESS_STARTUS), 2, 200);
+	if (ret)
+		dev_err(dev,
+			"Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
+
+	data = readl(LVTSRDATA0_0 + base);
+
+	return data;
+}
+
+static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
+	"Waiting for read after Write", "Disable Continue fetching on Device",
+	"Read transaction", "Set Device special Register for Voltage threshold",
+	"Set TSMCU number for Fetch"};
+
+static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int mask, error_code, is_error;
+	void __iomem *base;
+	int i, cnt, ret;
+
+	mask = BIT(10) | BIT(7) | BIT(0);
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		is_error = 0;
+		for (i = 0; i < lvts_data->num_tc; i++) {
+			base = GET_BASE_ADDR(lvts_data, i);
+			ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
+						 !(error_code & mask), 2, 200);
+
+			error_code = ((error_code & BIT(10)) >> 8) +
+				((error_code & BIT(7)) >> 6) +
+				(error_code & BIT(0));
+
+			if (ret)
+				dev_err(dev, "LVTS %d error: %s\n",
+					i, lvts_error_table[error_code]);
+
+			if (error_code != 0)
+				is_error = 1;
+		}
+
+		if (is_error == 0)
+			break;
+	}
+}
+
+static void lvts_reset(struct lvts_data *lvts_data)
+{
+	if (lvts_data->reset)
+		reset_control_assert(lvts_data->reset);
+	if (lvts_data->reset)
+		reset_control_deassert(lvts_data->reset);
+}
+
+static void device_identification(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i, data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		writel(ENABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+		writel(READ_BACK_DEVICE_ID, LVTS_CONFIG_0 + base);
+
+		usleep_range(5, 15);
+
+		/* Check LVTS device ID */
+		data = (readl(LVTS_ID_0 + base) & DEVICE_REG_DATA);
+		if (data != (lvts_data->tc->dev_id + i))
+			dev_err(dev, "LVTS_TC_%d, Device ID should be 0x%x, but 0x%x\n",
+				i, (lvts_data->tc->dev_id + i), data);
+	}
+}
+
+static void disable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		writel(DISABLE_SENSING_POINT, LVTSMONCTL0_0 + base);
+	}
+}
+
+static void enable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, num;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		num = tc[i].num_sensor;
+
+		if (num > ALL_SENSING_POINTS) {
+			dev_err(dev,
+				"%s, LVTS%d, illegal number of sensors: %d\n",
+				__func__, i, tc[i].num_sensor);
+			continue;
+		}
+
+		writel(ENABLE_SENSING_POINT(num), LVTSMONCTL0_0 + base);
+	}
+}
+
+static void set_polling_speed(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int lvts_mon_ctl_1, lvts_mon_ctl_2;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	lvts_mon_ctl_1 = ((tc[tc_id].tc_speed->group_interval_delay << 20) & GENMASK(29, 20)) |
+		(tc[tc_id].tc_speed->period_unit & GENMASK(9, 0));
+	lvts_mon_ctl_2 = ((tc[tc_id].tc_speed->filter_interval_delay << 16) & GENMASK(25, 16)) |
+		(tc[tc_id].tc_speed->sensor_interval_delay & GENMASK(9, 0));
+	/*
+	 * Clock source of LVTS thermal controller is 26MHz.
+	 * Period unit is a base for all interval delays
+	 * All interval delays must multiply it to convert a setting to time.
+	 * Filter interval delay is a delay between two samples of the same sensor
+	 * Sensor interval delay is a delay between two samples of differnet sensors
+	 * Group interval delay is a delay between different rounds.
+	 * For example:
+	 *     If Period unit = C, filter delay = 1, sensor delay = 2, group delay = 1,
+	 *     and two sensors, TS1 and TS2, are in a LVTS thermal controller
+	 *     and then
+	 *     Period unit = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us
+	 *     Filter interval delay = 1 * Period unit = 118.149us
+	 *     Sensor interval delay = 2 * Period unit = 236.298us
+	 *     Group interval delay = 1 * Period unit = 118.149us
+	 *
+	 *     TS1    TS1 ... TS1    TS2    TS2 ... TS2    TS1...
+	 *        <--> Filter interval delay
+	 *                       <--> Sensor interval delay
+	 *                                             <--> Group interval delay
+	 */
+	writel(lvts_mon_ctl_1, LVTSMONCTL1_0 + base);
+	writel(lvts_mon_ctl_2, LVTSMONCTL2_0 + base);
+
+	dev_dbg(dev, "LVTS_TC_%d, LVTSMONCTL1_0= 0x%x, LVTSMONCTL2_0= 0x%x\n",
+		 tc_id, readl(LVTSMONCTL1_0 + base),
+		 readl(LVTSMONCTL2_0 + base));
+}
+
+static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int option;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+	option = tc[tc_id].hw_filter & 0x7;
+	/*
+	 * hw filter
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+	 */
+	option = (option << 9) | (option << 6) | (option << 3) | option;
+
+	writel(option, LVTSMSRCTL0_0 + base);
+	dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
+		 tc_id, readl(LVTSMSRCTL0_0 + base));
+}
+
+static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	int d_index;
+
+	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
+		d_index = ALL_SENSING_POINTS;
+	} else if (tc[tc_id].dominator_sensing_point <
+		tc[tc_id].num_sensor){
+		d_index = tc[tc_id].dominator_sensing_point;
+	} else {
+		dev_err(dev,
+			"Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",
+			tc_id, tc[tc_id].dominator_sensing_point,
+			tc[tc_id].num_sensor);
+
+		dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
+		d_index = SENSING_POINT0;
+	}
+
+	return d_index;
+}
+
+static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	/*
+	 * LVTS thermal controller has two interrupts for thermal HW reboot
+	 * One is for AP SW and the other is for RGU
+	 * The interrupt of AP SW can turn off by a bit of a register, but
+	 * the other for RGU cannot.
+	 * To prevent rebooting device accidentally, we are going to add
+	 * a huge offset to LVTS and make LVTS always report extremely low
+	 * temperature.
+	 */
+
+	/*
+	 * After adding the huge offset 0x3FFF, LVTS alawys adds the
+	 * offset to MSR_RAW.
+	 * When MSR_RAW is larger, SW will convert lower temperature/
+	 */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
+
+	/* Disable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
+}
+
+static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	/* Enable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
+	/* Clear the offset */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
+}
+
+static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
+	int trip_point, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int msr_raw, temp, config, d_index;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+	d_index = get_dominator_index(lvts_data, tc_id);
+
+	dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);
+
+	disable_hw_reboot_interrupt(lvts_data, tc_id);
+
+	temp = readl(LVTSPROTCTL_0 + base);
+	if (d_index == ALL_SENSING_POINTS) {
+		/* Maximum of 4 sensing points */
+		config = (0x1 << 16);
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	} else {
+		/* Select protection sensor */
+		config = ((d_index << 2) + 0x2) << 16;
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	}
+
+	msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
+	writel(msr_raw, LVTSPROTTC_0 + base);
+
+	enable_hw_reboot_interrupt(lvts_data, tc_id);
+}
+
+static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	int i, trip_point;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		trip_point = tc[i].hw_reboot_trip_point;
+
+		if (tc[i].num_sensor == 0)
+			continue;
+
+		if (trip_point == THERMAL_TEMP_INVALID)
+			continue;
+
+		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
+	}
+}
+
+static int lvts_init(struct lvts_data *lvts_data)
+{
+	struct platform_ops *ops = &lvts_data->ops;
+	struct device *dev = lvts_data->dev;
+	int ret;
+
+	ret = clk_prepare_enable(lvts_data->clk);
+	if (ret) {
+		dev_err(dev,
+			"Error: Failed to enable lvts controller clock: %d\n",
+			ret);
+		return ret;
+	}
+
+	lvts_reset(lvts_data);
+
+	device_identification(lvts_data);
+	if (ops->device_enable_and_init)
+		ops->device_enable_and_init(lvts_data);
+
+	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
+		if (ops->device_enable_auto_rck)
+			ops->device_enable_auto_rck(lvts_data);
+	} else {
+		if (ops->device_read_count_rc_n)
+			ops->device_read_count_rc_n(lvts_data);
+	}
+
+	if (ops->set_cal_data)
+		ops->set_cal_data(lvts_data);
+
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	if (ops->init_controller)
+		ops->init_controller(lvts_data);
+	enable_all_sensing_points(lvts_data);
+
+	set_all_tc_hw_reboot(lvts_data);
+
+	return 0;
+}
+
+static int prepare_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	struct platform_ops *ops = &lvts_data->ops;
+	int i, offset;
+	char buffer[512];
+
+	cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_r), GFP_KERNEL);
+	if (!cal_data->count_r)
+		return -ENOMEM;
+
+	cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_rc), GFP_KERNEL);
+	if (!cal_data->count_rc)
+		return -ENOMEM;
+
+	if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
+		ops->efuse_to_cal_data(lvts_data);
+	if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
+		cal_data->use_fake_efuse = 1;
+
+	if (cal_data->use_fake_efuse) {
+		/* It means all efuse data are equal to 0 */
+		dev_err(dev,
+			"%s: This sample is not calibrated, fake !!\n", __func__);
+
+		cal_data->golden_temp = cal_data->default_golden_temp;
+		for (i = 0; i < lvts_data->num_sensor; i++) {
+			cal_data->count_r[i] = cal_data->default_count_r;
+			cal_data->count_rc[i] = cal_data->default_count_rc;
+		}
+	}
+
+	lvts_data->coeff.golden_temp = cal_data->golden_temp;
+
+	dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
+
+	offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
+			i, cal_data->count_r[i], cal_data->count_rc[i]);
+
+	buffer[offset] = '\0';
+
+	return 0;
+}
+
+static int get_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	char cell_name[32];
+	struct nvmem_cell *cell;
+	u32 *buf;
+	size_t len;
+	int i, j, index = 0, ret;
+
+	lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
+					sizeof(*lvts_data->efuse), GFP_KERNEL);
+	if (!lvts_data->efuse)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_efuse_block; i++) {
+		snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
+		cell = nvmem_cell_get(dev, cell_name);
+		if (IS_ERR(cell)) {
+			dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
+			return PTR_ERR(cell);
+		}
+
+		buf = (u32 *)nvmem_cell_read(cell, &len);
+		nvmem_cell_put(cell);
+
+		if (IS_ERR(buf))
+			return PTR_ERR(buf);
+
+		for (j = 0; j < (len / sizeof(u32)); j++) {
+			if (index >= lvts_data->num_efuse_addr) {
+				dev_err(dev, "Array efuse is going to overflow");
+				kfree(buf);
+				return -EINVAL;
+			}
+
+			lvts_data->efuse[index] = buf[j];
+			index++;
+		}
+
+		kfree(buf);
+	}
+
+	ret = prepare_calibration_data(lvts_data);
+
+	return ret;
+}
+
+static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, j, s_index;
+	void __iomem *base;
+
+	lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*lvts_data->reg), GFP_KERNEL);
+	if (!lvts_data->reg)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+			lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
+		}
+	}
+
+	return 0;
+}
+
+static int of_update_lvts_data(struct lvts_data *lvts_data,
+	struct platform_device *pdev)
+{
+	struct device *dev = lvts_data->dev;
+	struct resource *res;
+	int ret;
+
+	lvts_data->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(lvts_data->clk))
+		return PTR_ERR(lvts_data->clk);
+
+	/* Get base address */
+	res = platform_get_mem_or_io(pdev, 0);
+	if (!res) {
+		dev_err(dev, "No IO resource\n");
+		return -ENXIO;
+	}
+
+	lvts_data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lvts_data->base)) {
+		dev_err(dev, "Failed to remap io\n");
+		return PTR_ERR(lvts_data->base);
+	}
+
+	/* Get interrupt number */
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		dev_err(dev, "No irq resource\n");
+		return -EINVAL;
+	}
+	lvts_data->irq_num = ret;
+
+	/* Get reset control */
+	lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
+	if (IS_ERR(lvts_data->reset)) {
+		dev_err(dev, "Failed to get reset control\n");
+		return PTR_ERR(lvts_data->reset);
+	}
+
+	ret = lvts_init_tc_regs(dev, lvts_data);
+	if (ret)
+		return ret;
+
+	ret = get_calibration_data(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void lvts_device_close(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+		writel(DISABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+	}
+}
+
+static void lvts_close(struct lvts_data *lvts_data)
+{
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	lvts_device_close(lvts_data);
+	clk_disable_unprepare(lvts_data->clk);
+}
+
+static void tc_irq_handler(struct lvts_data *lvts_data, int tc_id)
+{
+	const struct device *dev = lvts_data->dev;
+	unsigned int ret = 0;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	ret = readl(LVTSMONINTSTS_0 + base);
+	/* Write back to clear interrupt status */
+	writel(ret, LVTSMONINTSTS_0 + base);
+
+	dev_dbg(dev, "LVTS thermal controller %d, LVTSMONINTSTS=0x%08x\n", tc_id, ret);
+
+	if (ret & THERMAL_PROTECTION_STAGE_3)
+		dev_dbg(dev, "Thermal protection stage 3 interrupt triggered\n");
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, *irq_bitmap;
+	void __iomem *base;
+
+	irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
+
+	if (!irq_bitmap)
+		return IRQ_NONE;
+
+	base = lvts_data->base;
+	*irq_bitmap = readl(THERMINTST + base);
+	dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		if (tc[i].irq_bit == 0)
+			tc_irq_handler(lvts_data, i);
+	}
+
+	kfree(irq_bitmap);
+
+	return IRQ_HANDLED;
+}
+
+static int lvts_register_irq_handler(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	int ret;
+
+	ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
+		IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);
+
+	if (ret) {
+		dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
+			ret, lvts_data->irq_num);
+		lvts_close(lvts_data);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct thermal_zone_device *tzdev;
+	struct soc_temp_tz *lvts_tz;
+	int i, ret;
+
+	for (i = 0; i < lvts_data->num_sensor; i++) {
+		lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
+		if (!lvts_tz) {
+			lvts_close(lvts_data);
+			return -ENOMEM;
+		}
+
+		lvts_tz->id = i;
+		lvts_tz->lvts_data = lvts_data;
+
+		tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
+			lvts_tz, &soc_temp_lvts_ops);
+
+		if (IS_ERR(tzdev)) {
+			if (lvts_tz->id != 0)
+				return 0;
+
+			ret = PTR_ERR(tzdev);
+			dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",
+				lvts_tz->id, ret);
+			lvts_close(lvts_data);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+void lvts_device_enable_and_init_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		lvts_write_device(lvts_data, STOP_COUNTING_V4, i);
+		lvts_write_device(lvts_data, SET_RG_TSFM_LPDLY_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US1_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US2_V4, i);
+		lvts_write_device(lvts_data, TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4, i);
+		lvts_write_device(lvts_data, TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4, i);
+		lvts_write_device(lvts_data, SET_TS_RSV_V4, i);
+		lvts_write_device(lvts_data, SET_TS_EN_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST1_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST2_V4, i);
+	}
+
+	lvts_data->counting_window_us = 20;
+}
+EXPORT_SYMBOL_GPL(lvts_device_enable_and_init_v4);
+
+void lvts_device_enable_auto_rck_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++)
+		lvts_write_device(lvts_data, SET_LVTS_AUTO_RCK_V4, i);
+}
+EXPORT_SYMBOL_GPL(lvts_device_enable_auto_rck_v4);
+
+int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
+{
+	/* Resistor-Capacitor Calibration */
+	/* count_RC_N: count RC now */
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int offset, size, s_index, data;
+	void __iomem *base;
+	int ret, i, j;
+	char buffer[512];
+
+	cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_rc_now), GFP_KERNEL);
+	if (!cal_data->count_rc_now)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+
+			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
+			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
+			usleep_range(10, 20);
+
+			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
+			usleep_range(30, 40);
+
+			ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
+						 !(data & DEVICE_SENSING_STATUS), 2, 200);
+			if (ret)
+				dev_err(dev,
+					"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
+
+			data = lvts_read_device(lvts_data, 0x00, i);
+
+			cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));
+		}
+
+		/* Recover Setting for Normal Access on
+		 * temperature fetch
+		 */
+		lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
+		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+	}
+
+	size = sizeof(buffer);
+	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, size - offset, "%d:%d ",
+			i, cal_data->count_rc_now[i]);
+
+	buffer[offset] = '\0';
+	dev_dbg(dev, "%s\n", buffer);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
+
+void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j, s_index, lvts_calib_data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+			if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
+				lvts_calib_data = cal_data->count_r[s_index];
+			else
+				lvts_calib_data = (((unsigned long long)
+					cal_data->count_rc_now[s_index]) *
+					cal_data->count_r[s_index]) >> 14;
+
+			writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
+
+void lvts_init_controller_v4(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+
+		writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
+		writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
+
+		set_polling_speed(lvts_data, i);
+		set_hw_filter(lvts_data, i);
+
+		dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
+			i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));
+	}
+}
+EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
+
+int lvts_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lvts_data *lvts_data;
+	int ret;
+
+	lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
+
+	if (!lvts_data)	{
+		dev_err(dev, "Error: Failed to get lvts platform data\n");
+		return -ENODATA;
+	}
+
+	lvts_data->dev = &pdev->dev;
+
+	ret = of_update_lvts_data(lvts_data, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, lvts_data);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	ret = lvts_register_irq_handler(lvts_data);
+	if (ret)
+		return ret;
+
+	ret = lvts_register_thermal_zones(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int lvts_remove(struct platform_device *pdev)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+int lvts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+int lvts_resume(struct platform_device *pdev)
+{
+	int ret;
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.h b/drivers/thermal/mediatek/soc_temp_lvts.h
new file mode 100644
index 000000000000..6f8b6e3af98c
--- /dev/null
+++ b/drivers/thermal/mediatek/soc_temp_lvts.h
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#ifndef __MTK_SOC_TEMP_LVTS_H__
+#define __MTK_SOC_TEMP_LVTS_H__
+
+#define PERIOD_UNIT				12
+#define GROUP_INTERVAL_DELAY	1
+#define FILTER_INTERVAL_DELAY	1
+#define SENSOR_INTERVAL_DELAY	1
+
+#define HW_REBOOT_TRIP_POINT	117000
+
+#define FEATURE_DEVICE_AUTO_RCK	BIT(0)
+#define NUM_EFUSE_ADDR			22
+#define NUM_EFUSE_BLOCK_MT8192	1
+#define DEFAULT_GOLDEN_TEMP		50
+#define DEFAULT_CUONT_R			35000
+#define DEFAULT_CUONT_RC		2750
+#define COEFF_A					-250460
+#define COEFF_B					250460
+
+#define CLOCK_26MHZ_CYCLE_NS	38
+#define BUS_ACCESS_US			2
+#define GOLDEN_TEMP_MAX			62
+
+/* LVTS device register */
+#define RG_TSFM_DATA_0			0x00
+#define RG_TSFM_DATA_1			0x01
+#define RG_TSFM_DATA_2			0x02
+#define RG_TSFM_CTRL_0			0x03
+#define RG_TSFM_CTRL_1			0x04
+#define RG_TSFM_CTRL_2			0x05
+#define RG_TSFM_CTRL_3			0x06
+#define RG_TSFM_CTRL_4			0x07
+#define RG_TSV2F_CTRL_0			0x08
+#define RG_TSV2F_CTRL_1			0x09
+#define RG_TSV2F_CTRL_2			0x0A
+#define RG_TSV2F_CTRL_3			0x0B
+#define RG_TSV2F_CTRL_4			0x0C
+#define RG_TSV2F_CTRL_5			0x0D
+#define RG_TSV2F_CTRL_6			0x0E
+#define RG_TEMP_DATA_0			0x10
+#define RG_TEMP_DATA_1			0x11
+#define RG_TEMP_DATA_2			0x12
+#define RG_TEMP_DATA_3			0x13
+#define RG_RC_DATA_0			0x14
+#define RG_RC_DATA_1			0x15
+#define RG_RC_DATA_2			0x16
+#define RG_RC_DATA_3			0x17
+#define RG_DIV_DATA_0			0x18
+#define RG_DIV_DATA_1			0x19
+#define RG_DIV_DATA_2			0x1A
+#define RG_DIV_DATA_3			0x1B
+#define RG_TST_DATA_0			0x70
+#define RG_TST_DATA_1			0x71
+#define RG_TST_DATA_2			0x72
+#define RG_TST_CTRL				0x73
+#define RG_DBG_FQMTR			0xF0
+#define RG_DBG_LPSEQ			0xF1
+#define RG_DBG_STATE			0xF2
+#define RG_DBG_CHKSUM			0xF3
+#define RG_DID_LVTS				0xFC
+#define RG_DID_REV				0xFD
+#define RG_TSFM_RST				0xFF
+
+/* LVTS controller register */
+#define LVTSMONCTL0_0				0x000
+#define ENABLE_SENSING_POINT(num)	(LVTS_SINGLE_SENSE | GENMASK(((num) - 1), 0))
+#define DISABLE_SENSING_POINT		(LVTS_SINGLE_SENSE | 0x0)
+#define LVTSMONCTL1_0				0x004
+#define LVTSMONCTL2_0				0x008
+#define LVTSMONINT_0				0x00C
+#define STAGE3_INT_EN				BIT(31)
+#define LVTSMONINTSTS_0				0x010
+#define LVTSMONIDET0_0				0x014
+#define LVTSMONIDET1_0				0x018
+#define LVTSMONIDET2_0				0x01C
+#define LVTSMONIDET3_0				0x020
+#define LVTSH2NTHRE_0				0x024
+#define LVTSHTHRE_0					0x028
+#define LVTSCTHRE_0					0x02C
+#define LVTSOFFSETH_0				0x030
+#define LVTSOFFSETL_0				0x034
+#define LVTSMSRCTL0_0				0x038
+#define LVTSMSRCTL1_0				0x03C
+#define LVTSTSSEL_0					0x040
+#define SET_SENSOR_INDEX			0x13121110
+#define LVTSDEVICETO_0				0x044
+#define LVTSCALSCALE_0				0x048
+#define SET_CALC_SCALE_RULES		0x00000300
+#define LVTS_ID_0					0x04C
+#define LVTS_CONFIG_0				0x050
+
+#define SCK_ONLY					BIT(31)
+#define BROADCAST_ID_UPDATE			BIT(26)
+#define DEVICE_SENSING_STATUS		BIT(25)
+#define DEVICE_ACCESS_STARTUS		BIT(24)
+#define READ_32BIT_ACCESS			BIT(17)
+#define WRITE_ACCESS				BIT(16)
+#define LVTS_SINGLE_SENSE			BIT(9)
+#define FEATURE_CK26M_ACTIVE		BIT(1)
+#define DEVICE_REG_DATA				GENMASK(7, 0)
+
+#define LVTSEDATA00_0				0x054
+#define LVTSEDATA01_0				0x058
+#define LVTSEDATA02_0				0x05C
+#define LVTSEDATA03_0				0x060
+#define LVTSMSR0_0					0x090
+#define MRS_RAW_MASK				GENMASK(15, 0)
+#define MRS_RAW_VALID_BIT			BIT(16)
+#define LVTSMSR1_0					0x094
+#define LVTSMSR2_0					0x098
+#define LVTSMSR3_0					0x09C
+#define LVTSIMMD0_0					0x0A0
+#define LVTSIMMD1_0					0x0A4
+#define LVTSIMMD2_0					0x0A8
+#define LVTSIMMD3_0					0x0AC
+#define LVTSRDATA0_0				0x0B0
+#define LVTSRDATA1_0				0x0B4
+#define LVTSRDATA2_0				0x0B8
+#define LVTSRDATA3_0				0x0BC
+#define LVTSPROTCTL_0				0x0C0
+#define PROTOFFSET					GENMASK(15, 0)
+#define LVTSPROTTA_0				0x0C4
+#define LVTSPROTTB_0				0x0C8
+#define LVTSPROTTC_0				0x0CC
+#define LVTSCLKEN_0					0x0E4
+#define ENABLE_LVTS_CTRL_CLK		(1)
+#define DISABLE_LVTS_CTRL_CLK		(0)
+#define LVTSDBGSEL_0				0x0E8
+#define LVTSDBGSIG_0				0x0EC
+#define LVTSSPARE0_0				0x0F0
+#define LVTSSPARE1_0				0x0F4
+#define LVTSSPARE2_0				0x0F8
+#define LVTSSPARE3_0				0x0FC
+#define THERMINTST					0xF04
+
+/* LVTS register mask */
+#define THERMAL_COLD_INTERRUPT_0			BIT(0)
+#define THERMAL_HOT_INTERRUPT_0				BIT(1)
+#define THERMAL_LOW_OFFSET_INTERRUPT_0		BIT(2)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_0		BIT(3)
+#define THERMAL_HOT2NORMAL_INTERRUPT_0		BIT(4)
+#define THERMAL_COLD_INTERRUPT_1			BIT(5)
+#define THERMAL_HOT_INTERRUPT_1				BIT(6)
+#define THERMAL_LOW_OFFSET_INTERRUPT_1		BIT(7)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_1		BIT(8)
+#define THERMAL_HOT2NORMAL_INTERRUPT_1		BIT(9)
+#define THERMAL_COLD_INTERRUPT_2			BIT(10)
+#define THERMAL_HOT_INTERRUPT_2				BIT(11)
+#define THERMAL_LOW_OFFSET_INTERRUPT_2		BIT(12)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_2		BIT(13)
+#define THERMAL_HOT2NORMAL_INTERRUPT_2		BIT(14)
+#define THERMAL_AHB_TIMEOUT_INTERRUPT		BIT(15)
+#define THERMAL_DEVICE_TIMEOUT_INTERRUPT	BIT(15)
+#define THERMAL_IMMEDIATE_INTERRUPT_0		BIT(16)
+#define THERMAL_IMMEDIATE_INTERRUPT_1		BIT(17)
+#define THERMAL_IMMEDIATE_INTERRUPT_2		BIT(18)
+#define THERMAL_FILTER_INTERRUPT_0			BIT(19)
+#define THERMAL_FILTER_INTERRUPT_1			BIT(20)
+#define THERMAL_FILTER_INTERRUPT_2			BIT(21)
+#define THERMAL_COLD_INTERRUPT_3			BIT(22)
+#define THERMAL_HOT_INTERRUPT_3				BIT(23)
+#define THERMAL_LOW_OFFSET_INTERRUPT_3		BIT(24)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_3		BIT(25)
+#define THERMAL_HOT2NORMAL_INTERRUPT_3		BIT(26)
+#define THERMAL_IMMEDIATE_INTERRUPT_3		BIT(27)
+#define THERMAL_FILTER_INTERRUPT_3			BIT(28)
+#define THERMAL_PROTECTION_STAGE_1			BIT(29)
+#define THERMAL_PROTECTION_STAGE_2			BIT(30)
+#define THERMAL_PROTECTION_STAGE_3			BIT(31)
+
+#define CFG_REGISTER(reg, value)	(reg << 8 | value)
+#define STOP_COUNTING_V4					CFG_REGISTER(RG_TSFM_CTRL_0, 0x00)
+#define SET_RG_TSFM_LPDLY_V4				CFG_REGISTER(RG_TSFM_CTRL_4, 0xA6)
+#define SET_COUNTING_WINDOW_20US1_V4		CFG_REGISTER(RG_TSFM_CTRL_2, 0x00)
+#define SET_COUNTING_WINDOW_20US2_V4		CFG_REGISTER(RG_TSFM_CTRL_1, 0x20)
+#define TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4	CFG_REGISTER(RG_TSV2F_CTRL_2, 0x84)
+#define TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4	CFG_REGISTER(RG_TSV2F_CTRL_4, 0x7C)
+#define SET_TS_RSV_V4						CFG_REGISTER(RG_TSV2F_CTRL_1, 0x8D)
+#define SET_TS_EN_V4						CFG_REGISTER(RG_TSV2F_CTRL_0, 0xF4)
+#define TOGGLE_RG_TSV2F_VCO_RST1_V4			CFG_REGISTER(RG_TSV2F_CTRL_0, 0xFC)
+#define TOGGLE_RG_TSV2F_VCO_RST2_V4			CFG_REGISTER(RG_TSV2F_CTRL_0, 0xF4)
+
+#define SET_LVTS_AUTO_RCK_V4				CFG_REGISTER(RG_TSV2F_CTRL_6, 0x01)
+#define SELECT_SENSOR_RCK_V4(id)			CFG_REGISTER(RG_TSV2F_CTRL_5, (id))
+#define SET_DEVICE_SINGLE_MODE_V4			CFG_REGISTER(RG_TSFM_CTRL_3, 0x78)
+#define KICK_OFF_RCK_COUNTING_V4			CFG_REGISTER(RG_TSFM_CTRL_0, 0x02)
+#define SET_SENSOR_NO_RCK_V4				CFG_REGISTER(RG_TSV2F_CTRL_5, 0x10)
+#define SET_DEVICE_LOW_POWER_SINGLE_MODE_V4	CFG_REGISTER(RG_TSFM_CTRL_3, 0xB8)
+
+#define HAS_FEATURE(lvts_data, feature)		(lvts_data->feature_bitmap & (feature))
+#define GET_BASE_ADDR(lvts_data, tc_id)		(lvts_data->base + lvts_data->tc[tc_id].addr_offset)
+#define GET_CAL_DATA_BITMASK(index, lvts_data, h, l)	(((index) < lvts_data->num_efuse_addr) \
+	? ((lvts_data->efuse[(index)] & GENMASK(h, l)) >> l) : 0)
+
+#define GET_TC_SENSOR_NUM(lvts_data, tc_id)		(lvts_data->tc[tc_id].num_sensor)
+#define ONE_SAMPLE		(lvts_data->counting_window_us + 2 * BUS_ACCESS_US)
+#define NUM_OF_SAMPLE(tc_id)	((lvts_data->tc[tc_id].hw_filter < LVTS_FILTER_2) ? 1 :	\
+	((lvts_data->tc[tc_id].hw_filter > LVTS_FILTER_16_OF_18) ? 1 :	\
+	((lvts_data->tc[tc_id].hw_filter == LVTS_FILTER_16_OF_18) ? 18 : \
+	((lvts_data->tc[tc_id].hw_filter == LVTS_FILTER_8_OF_10) ? 10 :	\
+	(lvts_data->tc[tc_id].hw_filter * 2)))))
+
+#define PERIOD_UNIT_US(tc_id)	((lvts_data->tc[tc_id].tc_speed->period_unit * 256 * \
+	CLOCK_26MHZ_CYCLE_NS) / 1000)
+#define FILTER_INT_US(tc_id)	(lvts_data->tc[tc_id].tc_speed->filter_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define SENSOR_INT_US(tc_id)	(lvts_data->tc[tc_id].tc_speed->sensor_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define GROUP_INT_US(tc_id)		(lvts_data->tc[tc_id].tc_speed->group_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define SENSOR_LATENCY_US(tc_id)	((NUM_OF_SAMPLE(tc_id) - 1) * FILTER_INT_US(tc_id) + \
+	NUM_OF_SAMPLE(tc_id) * ONE_SAMPLE)
+#define GROUP_LATENCY_US(tc_id)		(GET_TC_SENSOR_NUM(lvts_data, tc_id) * \
+	SENSOR_LATENCY_US(tc_id) + (GET_TC_SENSOR_NUM(lvts_data, tc_id) - 1) * SENSOR_INT_US(tc_id) + \
+	GROUP_INT_US(tc_id))
+
+#define CK26M_ACTIVE(lvts_data)	(((lvts_data->feature_bitmap & FEATURE_CK26M_ACTIVE) ? 1 : 0) << 30)
+#define DEVICE_ACCESS			(SCK_ONLY | DEVICE_ACCESS_STARTUS | READ_32BIT_ACCESS)
+#define DEVICE_READ				(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS)
+#define DEVICE_WRITE			(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS | WRITE_ACCESS)
+#define READ_BACK_DEVICE_ID		(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS | BROADCAST_ID_UPDATE | \
+	RG_DID_LVTS << 8)
+#define READ_DEVICE_REG(reg_idx)	(DEVICE_READ | (reg_idx) << 8 | 0x00)
+#define RESET_ALL_DEVICES			(DEVICE_WRITE | RG_TSFM_RST << 8 | 0xFF)
+
+/*
+ * LVTS HW filter settings
+ * 000: Get one sample
+ * 001: Get 2 samples and average them
+ * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+ * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+ * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+ * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+ */
+enum lvts_hw_filter {
+	LVTS_FILTER_1,
+	LVTS_FILTER_2,
+	LVTS_FILTER_2_OF_4,
+	LVTS_FILTER_4_OF_6,
+	LVTS_FILTER_8_OF_10,
+	LVTS_FILTER_16_OF_18
+};
+
+enum lvts_sensing_point {
+	SENSING_POINT0,
+	SENSING_POINT1,
+	SENSING_POINT2,
+	SENSING_POINT3,
+	ALL_SENSING_POINTS
+};
+
+struct lvts_data;
+
+/**
+ * struct lvts_speed_settings - A structure to hold the data related to polling rate
+ * @period_unit: Period unit is a base for all interval delays
+ * @group_interval_delay:  Delay between different rounds
+ * @filter_interval_delay: Delay between two samples of the same sensor
+ * @sensor_interval_delay: Delay between two samples of differnet sensors
+ *
+ * Calculation is achieved with the following equations:
+ * For the period unit: (period_us * 1000) / (256 * clock_26mhz_cycle_ns)
+ * For the interval delays: delay / period_us
+ */
+struct lvts_speed_settings {
+	unsigned int period_unit;
+	unsigned int group_interval_delay;
+	unsigned int filter_interval_delay;
+	unsigned int sensor_interval_delay;
+};
+
+struct lvts_tc_settings {
+	unsigned int dev_id;
+	unsigned int addr_offset;
+	unsigned int num_sensor;
+	unsigned int sensor_map[ALL_SENSING_POINTS];	/* In sensor ID */
+	struct lvts_speed_settings *tc_speed;
+	/*
+	 * HW filter setting
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+	 */
+	unsigned int hw_filter;
+	/*
+	 * Dominator_sensing point is used to select a sensing point
+	 * and reference its temperature to trigger Thermal HW Reboot
+	 * When it is ALL_SENSING_POINTS, it will select all sensing points
+	 */
+	int dominator_sensing_point;
+	int hw_reboot_trip_point;		/* -274000: Disable HW reboot */
+	unsigned int irq_bit;
+};
+
+struct lvts_formula_coeff {
+	int a;
+	int b;
+	unsigned int golden_temp;
+};
+
+struct lvts_sensor_cal_data {
+	int use_fake_efuse;				/* 1: Use fake efuse, 0: Use real efuse */
+	unsigned int golden_temp;
+	unsigned int *count_r;
+	unsigned int *count_rc;
+	unsigned int *count_rc_now;
+	unsigned int default_golden_temp;
+	unsigned int default_count_r;
+	unsigned int default_count_rc;
+};
+
+struct platform_ops {
+	void (*efuse_to_cal_data)(struct lvts_data *lvts_data);
+	void (*device_enable_and_init)(struct lvts_data *lvts_data);
+	void (*device_enable_auto_rck)(struct lvts_data *lvts_data);
+	int (*device_read_count_rc_n)(struct lvts_data *lvts_data);
+	void (*set_cal_data)(struct lvts_data *lvts_data);
+	void (*init_controller)(struct lvts_data *lvts_data);
+};
+
+struct lvts_data {
+	struct device *dev;
+	struct clk *clk;
+	void __iomem *base;				/* LVTS base addresses */
+	unsigned int irq_num;			/* LVTS interrupt numbers */
+	struct reset_control *reset;
+	int num_tc;						/* Number of LVTS thermal controllers */
+	const struct lvts_tc_settings *tc;
+	int counting_window_us;			/* LVTS device counting window */
+	int num_sensor;					/* Number of sensors in this platform */
+	void __iomem **reg;
+	struct platform_ops ops;
+	int feature_bitmap;				/* Show what features are enabled */
+	unsigned int num_efuse_addr;
+	unsigned int *efuse;
+	unsigned int num_efuse_block;	/* Number of contiguous efuse indexes */
+	struct lvts_sensor_cal_data cal_data;
+	struct lvts_formula_coeff coeff;
+};
+
+struct soc_temp_tz {
+	unsigned int id;
+	struct lvts_data *lvts_data;
+};
+
+extern void lvts_device_enable_and_init_v4(struct lvts_data *lvts_data);
+extern void lvts_device_enable_auto_rck_v4(struct lvts_data *lvts_data);
+extern int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data);
+extern void lvts_set_calibration_data_v4(struct lvts_data *lvts_data);
+extern void lvts_init_controller_v4(struct lvts_data *lvts_data);
+
+extern int lvts_probe(struct platform_device *pdev);
+extern int lvts_remove(struct platform_device *pdev);
+extern int lvts_suspend(struct platform_device *pdev, pm_message_t state);
+extern int lvts_resume(struct platform_device *pdev);
+
+#endif /* __MTK_SOC_TEMP_LVTS_H__ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add a LVTS (Low voltage thermal sensor) driver to report junction
temperatures in Mediatek SoC mt8192 and register the maximum temperature
of sensors and each sensor as a thermal zone.

Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/mediatek/Kconfig         |  27 +
 drivers/thermal/mediatek/Makefile        |   2 +
 drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
 drivers/thermal/mediatek/soc_temp.c      |   2 +-
 drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
 6 files changed, 1564 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
 create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
index 9c41e9079fc3..7fc04237dd50 100644
--- a/drivers/thermal/mediatek/Kconfig
+++ b/drivers/thermal/mediatek/Kconfig
@@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
 		configures thermal controllers to collect temperature
 		via AUXADC interface.
 
+config MTK_SOC_THERMAL_LVTS
+	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	help
+		Enable this option if you want to get SoC temperature
+		information for MediaTek platforms. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via Analog Serial Interface(ASIF).
+
+endif
+
+if MTK_SOC_THERMAL_LVTS
+
+config LVTS_MT8192
+	tristate "LVTS driver for MediaTek MT8192 SoC"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	depends on MTK_SOC_THERMAL_LVTS
+	help
+		Enable this option if you want to get SoC temperature
+		information for MT8192. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via ASIF.
+
 endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
index 4b4cb04a358f..5ff1197e80ab 100644
--- a/drivers/thermal/mediatek/Makefile
+++ b/drivers/thermal/mediatek/Makefile
@@ -1 +1,3 @@
 obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
+obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
+obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
new file mode 100644
index 000000000000..19e4e82c410b
--- /dev/null
+++ b/drivers/thermal/mediatek/lvts_mt8192.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include "soc_temp_lvts.h"
+
+enum mt8192_lvts_mcu_sensor_enum {
+	MT8192_TS1_0,
+	MT8192_TS1_1,
+	MT8192_TS2_0,
+	MT8192_TS2_1,
+	MT8192_TS3_0,
+	MT8192_TS3_1,
+	MT8192_TS3_2,
+	MT8192_TS3_3,
+	MT8192_NUM_TS_MCU
+};
+
+enum mt8192_lvts_ap_sensor_enum {
+	MT8192_TS4_0,
+	MT8192_TS4_1,
+	MT8192_TS5_0,
+	MT8192_TS5_1,
+	MT8192_TS6_0,
+	MT8192_TS6_1,
+	MT8192_TS7_0,
+	MT8192_TS7_1,
+	MT8192_TS7_2,
+	MT8192_NUM_TS_AP
+};
+
+static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j;
+	const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	for (i = 0; i < MT8192_NUM_TS_MCU; i++)
+		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
+
+	cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);
+
+	for (i = 0; i < (ARRAY_SIZE(mt8192_TS)); i++) {
+		for (j = 1; j <= 18; j++) {
+			cal_data->count_rc[mt8192_TS[i]] = (GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 16) +
+				(GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 8) +
+					GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24);
+		}
+	}
+}
+
+static void mt8192_ap_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j;
+	const unsigned int mt8192_TS[] = {MT8192_TS4_0, MT8192_TS5_0, MT8192_TS6_0, MT8192_TS7_0};
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	for (i = 0; i < MT8192_NUM_TS_AP; i++)
+		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
+
+	for (i = 0; i < (ARRAY_SIZE(mt8192_TS)); i++) {
+		for (j = 1; j <= 18; j++) {
+			cal_data->count_rc[mt8192_TS[i]] = (GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 16) +
+				(GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24) << 8) +
+					GET_CAL_DATA_BITMASK(j, lvts_data, 31, 24);
+		}
+	}
+}
+
+static struct lvts_speed_settings tc_speed_mt8192 = {
+	.period_unit = PERIOD_UNIT,
+	.group_interval_delay = GROUP_INTERVAL_DELAY,
+	.filter_interval_delay = FILTER_INTERVAL_DELAY,
+	.sensor_interval_delay = SENSOR_INTERVAL_DELAY,
+};
+
+static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
+	[0] = {
+		.dev_id = 0x81,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS1_0, MT8192_TS1_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x82,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS2_0, MT8192_TS2_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x83,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT8192_TS3_0, MT8192_TS3_1, MT8192_TS3_2, MT8192_TS3_3},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	}
+};
+
+static const struct lvts_tc_settings mt8192_tc_ap_settings[] = {
+	[0] = {
+		.dev_id = 0x84,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS4_0, MT8192_TS4_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x85,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS5_0, MT8192_TS5_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x86,
+		.addr_offset = 0x200,
+		.num_sensor = 2,
+		.sensor_map = {MT8192_TS6_0, MT8192_TS6_1},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.dev_id = 0x87,
+		.addr_offset = 0x300,
+		.num_sensor = 3,
+		.sensor_map = {MT8192_TS7_0, MT8192_TS7_1, MT8192_TS7_2},
+		.tc_speed = &tc_speed_mt8192,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT2,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(6),
+	}
+};
+
+static const struct lvts_data mt8192_lvts_mcu_data = {
+	.num_tc = (ARRAY_SIZE(mt8192_tc_mcu_settings)),
+	.tc = mt8192_tc_mcu_settings,
+	.num_sensor = MT8192_NUM_TS_MCU,
+	.ops = {
+		.efuse_to_cal_data = mt8192_mcu_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct lvts_data mt8192_lvts_ap_data = {
+	.num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
+	.tc = mt8192_tc_ap_settings,
+	.num_sensor = MT8192_NUM_TS_AP,
+	.ops = {
+		.efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct of_device_id lvts_of_match[] = {
+	{ .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
+	{ .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvts_of_match);
+
+static struct platform_driver soc_temp_lvts = {
+	.probe = lvts_probe,
+	.remove = lvts_remove,
+	.suspend = lvts_suspend,
+	.resume = lvts_resume,
+	.driver = {
+		.name = "mtk-soc-temp-lvts-mt8192",
+		.of_match_table = lvts_of_match,
+	},
+};
+module_platform_driver(soc_temp_lvts);
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
index ede94eadddda..60924f8f98e9 100644
--- a/drivers/thermal/mediatek/soc_temp.c
+++ b/drivers/thermal/mediatek/soc_temp.c
@@ -23,7 +23,7 @@
 #include <linux/reset.h>
 #include <linux/types.h>
 
-#include "thermal_hwmon.h"
+#include "../thermal_hwmon.h"
 
 /* AUXADC Registers */
 #define AUXADC_CON1_SET_V	0x008
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
new file mode 100644
index 000000000000..ee7efc0de65f
--- /dev/null
+++ b/drivers/thermal/mediatek/soc_temp_lvts.c
@@ -0,0 +1,928 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/thermal.h>
+#include "soc_temp_lvts.h"
+
+static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
+{
+	/* This function returns degree mC */
+
+	int temp;
+
+	temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
+	temp = temp + co->golden_temp * 500 + co->b;
+
+	return temp;
+}
+
+static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
+{
+	unsigned int msr_raw;
+
+	msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
+		(-1 * co->a));
+
+	return msr_raw;
+}
+
+static int soc_temp_lvts_read_temp(void *data, int *temperature)
+{
+	struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
+	struct lvts_data *lvts_data = lvts_tz->lvts_data;
+	unsigned int msr_raw;
+
+	msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
+	if (msr_raw == 0)
+		return -EINVAL;
+
+	*temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
+	.get_temp = soc_temp_lvts_read_temp,
+};
+
+static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
+	int tc_id)
+{
+	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
+
+	usleep_range(5, 15);
+}
+
+static unsigned int lvts_read_device(struct lvts_data *lvts_data,
+	unsigned int reg_idx, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
+	unsigned int data;
+	int ret;
+
+	writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
+
+	usleep_range(5, 15);
+
+	ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
+		!(data & DEVICE_ACCESS_STARTUS), 2, 200);
+	if (ret)
+		dev_err(dev,
+			"Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
+
+	data = readl(LVTSRDATA0_0 + base);
+
+	return data;
+}
+
+static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
+	"Waiting for read after Write", "Disable Continue fetching on Device",
+	"Read transaction", "Set Device special Register for Voltage threshold",
+	"Set TSMCU number for Fetch"};
+
+static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int mask, error_code, is_error;
+	void __iomem *base;
+	int i, cnt, ret;
+
+	mask = BIT(10) | BIT(7) | BIT(0);
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		is_error = 0;
+		for (i = 0; i < lvts_data->num_tc; i++) {
+			base = GET_BASE_ADDR(lvts_data, i);
+			ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
+						 !(error_code & mask), 2, 200);
+
+			error_code = ((error_code & BIT(10)) >> 8) +
+				((error_code & BIT(7)) >> 6) +
+				(error_code & BIT(0));
+
+			if (ret)
+				dev_err(dev, "LVTS %d error: %s\n",
+					i, lvts_error_table[error_code]);
+
+			if (error_code != 0)
+				is_error = 1;
+		}
+
+		if (is_error == 0)
+			break;
+	}
+}
+
+static void lvts_reset(struct lvts_data *lvts_data)
+{
+	if (lvts_data->reset)
+		reset_control_assert(lvts_data->reset);
+	if (lvts_data->reset)
+		reset_control_deassert(lvts_data->reset);
+}
+
+static void device_identification(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i, data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		writel(ENABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+		writel(READ_BACK_DEVICE_ID, LVTS_CONFIG_0 + base);
+
+		usleep_range(5, 15);
+
+		/* Check LVTS device ID */
+		data = (readl(LVTS_ID_0 + base) & DEVICE_REG_DATA);
+		if (data != (lvts_data->tc->dev_id + i))
+			dev_err(dev, "LVTS_TC_%d, Device ID should be 0x%x, but 0x%x\n",
+				i, (lvts_data->tc->dev_id + i), data);
+	}
+}
+
+static void disable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		writel(DISABLE_SENSING_POINT, LVTSMONCTL0_0 + base);
+	}
+}
+
+static void enable_all_sensing_points(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, num;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		num = tc[i].num_sensor;
+
+		if (num > ALL_SENSING_POINTS) {
+			dev_err(dev,
+				"%s, LVTS%d, illegal number of sensors: %d\n",
+				__func__, i, tc[i].num_sensor);
+			continue;
+		}
+
+		writel(ENABLE_SENSING_POINT(num), LVTSMONCTL0_0 + base);
+	}
+}
+
+static void set_polling_speed(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int lvts_mon_ctl_1, lvts_mon_ctl_2;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	lvts_mon_ctl_1 = ((tc[tc_id].tc_speed->group_interval_delay << 20) & GENMASK(29, 20)) |
+		(tc[tc_id].tc_speed->period_unit & GENMASK(9, 0));
+	lvts_mon_ctl_2 = ((tc[tc_id].tc_speed->filter_interval_delay << 16) & GENMASK(25, 16)) |
+		(tc[tc_id].tc_speed->sensor_interval_delay & GENMASK(9, 0));
+	/*
+	 * Clock source of LVTS thermal controller is 26MHz.
+	 * Period unit is a base for all interval delays
+	 * All interval delays must multiply it to convert a setting to time.
+	 * Filter interval delay is a delay between two samples of the same sensor
+	 * Sensor interval delay is a delay between two samples of differnet sensors
+	 * Group interval delay is a delay between different rounds.
+	 * For example:
+	 *     If Period unit = C, filter delay = 1, sensor delay = 2, group delay = 1,
+	 *     and two sensors, TS1 and TS2, are in a LVTS thermal controller
+	 *     and then
+	 *     Period unit = C * 1/26M * 256 = 12 * 38.46ns * 256 = 118.149us
+	 *     Filter interval delay = 1 * Period unit = 118.149us
+	 *     Sensor interval delay = 2 * Period unit = 236.298us
+	 *     Group interval delay = 1 * Period unit = 118.149us
+	 *
+	 *     TS1    TS1 ... TS1    TS2    TS2 ... TS2    TS1...
+	 *        <--> Filter interval delay
+	 *                       <--> Sensor interval delay
+	 *                                             <--> Group interval delay
+	 */
+	writel(lvts_mon_ctl_1, LVTSMONCTL1_0 + base);
+	writel(lvts_mon_ctl_2, LVTSMONCTL2_0 + base);
+
+	dev_dbg(dev, "LVTS_TC_%d, LVTSMONCTL1_0= 0x%x, LVTSMONCTL2_0= 0x%x\n",
+		 tc_id, readl(LVTSMONCTL1_0 + base),
+		 readl(LVTSMONCTL2_0 + base));
+}
+
+static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int option;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+	option = tc[tc_id].hw_filter & 0x7;
+	/*
+	 * hw filter
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+	 */
+	option = (option << 9) | (option << 6) | (option << 3) | option;
+
+	writel(option, LVTSMSRCTL0_0 + base);
+	dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
+		 tc_id, readl(LVTSMSRCTL0_0 + base));
+}
+
+static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	int d_index;
+
+	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
+		d_index = ALL_SENSING_POINTS;
+	} else if (tc[tc_id].dominator_sensing_point <
+		tc[tc_id].num_sensor){
+		d_index = tc[tc_id].dominator_sensing_point;
+	} else {
+		dev_err(dev,
+			"Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",
+			tc_id, tc[tc_id].dominator_sensing_point,
+			tc[tc_id].num_sensor);
+
+		dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
+		d_index = SENSING_POINT0;
+	}
+
+	return d_index;
+}
+
+static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	/*
+	 * LVTS thermal controller has two interrupts for thermal HW reboot
+	 * One is for AP SW and the other is for RGU
+	 * The interrupt of AP SW can turn off by a bit of a register, but
+	 * the other for RGU cannot.
+	 * To prevent rebooting device accidentally, we are going to add
+	 * a huge offset to LVTS and make LVTS always report extremely low
+	 * temperature.
+	 */
+
+	/*
+	 * After adding the huge offset 0x3FFF, LVTS alawys adds the
+	 * offset to MSR_RAW.
+	 * When MSR_RAW is larger, SW will convert lower temperature/
+	 */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
+
+	/* Disable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
+}
+
+static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
+{
+	unsigned int temp;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	/* Enable the interrupt of AP SW */
+	temp = readl(LVTSMONINT_0 + base);
+	writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
+	/* Clear the offset */
+	temp = readl(LVTSPROTCTL_0 + base);
+	writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
+}
+
+static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
+	int trip_point, int tc_id)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int msr_raw, temp, config, d_index;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+	d_index = get_dominator_index(lvts_data, tc_id);
+
+	dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);
+
+	disable_hw_reboot_interrupt(lvts_data, tc_id);
+
+	temp = readl(LVTSPROTCTL_0 + base);
+	if (d_index == ALL_SENSING_POINTS) {
+		/* Maximum of 4 sensing points */
+		config = (0x1 << 16);
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	} else {
+		/* Select protection sensor */
+		config = ((d_index << 2) + 0x2) << 16;
+		writel(config | temp, LVTSPROTCTL_0 + base);
+	}
+
+	msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
+	writel(msr_raw, LVTSPROTTC_0 + base);
+
+	enable_hw_reboot_interrupt(lvts_data, tc_id);
+}
+
+static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	int i, trip_point;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		trip_point = tc[i].hw_reboot_trip_point;
+
+		if (tc[i].num_sensor == 0)
+			continue;
+
+		if (trip_point == THERMAL_TEMP_INVALID)
+			continue;
+
+		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
+	}
+}
+
+static int lvts_init(struct lvts_data *lvts_data)
+{
+	struct platform_ops *ops = &lvts_data->ops;
+	struct device *dev = lvts_data->dev;
+	int ret;
+
+	ret = clk_prepare_enable(lvts_data->clk);
+	if (ret) {
+		dev_err(dev,
+			"Error: Failed to enable lvts controller clock: %d\n",
+			ret);
+		return ret;
+	}
+
+	lvts_reset(lvts_data);
+
+	device_identification(lvts_data);
+	if (ops->device_enable_and_init)
+		ops->device_enable_and_init(lvts_data);
+
+	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
+		if (ops->device_enable_auto_rck)
+			ops->device_enable_auto_rck(lvts_data);
+	} else {
+		if (ops->device_read_count_rc_n)
+			ops->device_read_count_rc_n(lvts_data);
+	}
+
+	if (ops->set_cal_data)
+		ops->set_cal_data(lvts_data);
+
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	if (ops->init_controller)
+		ops->init_controller(lvts_data);
+	enable_all_sensing_points(lvts_data);
+
+	set_all_tc_hw_reboot(lvts_data);
+
+	return 0;
+}
+
+static int prepare_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	struct platform_ops *ops = &lvts_data->ops;
+	int i, offset;
+	char buffer[512];
+
+	cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_r), GFP_KERNEL);
+	if (!cal_data->count_r)
+		return -ENOMEM;
+
+	cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_rc), GFP_KERNEL);
+	if (!cal_data->count_rc)
+		return -ENOMEM;
+
+	if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
+		ops->efuse_to_cal_data(lvts_data);
+	if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
+		cal_data->use_fake_efuse = 1;
+
+	if (cal_data->use_fake_efuse) {
+		/* It means all efuse data are equal to 0 */
+		dev_err(dev,
+			"%s: This sample is not calibrated, fake !!\n", __func__);
+
+		cal_data->golden_temp = cal_data->default_golden_temp;
+		for (i = 0; i < lvts_data->num_sensor; i++) {
+			cal_data->count_r[i] = cal_data->default_count_r;
+			cal_data->count_rc[i] = cal_data->default_count_rc;
+		}
+	}
+
+	lvts_data->coeff.golden_temp = cal_data->golden_temp;
+
+	dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
+
+	offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
+			i, cal_data->count_r[i], cal_data->count_rc[i]);
+
+	buffer[offset] = '\0';
+
+	return 0;
+}
+
+static int get_calibration_data(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	char cell_name[32];
+	struct nvmem_cell *cell;
+	u32 *buf;
+	size_t len;
+	int i, j, index = 0, ret;
+
+	lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
+					sizeof(*lvts_data->efuse), GFP_KERNEL);
+	if (!lvts_data->efuse)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_efuse_block; i++) {
+		snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
+		cell = nvmem_cell_get(dev, cell_name);
+		if (IS_ERR(cell)) {
+			dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
+			return PTR_ERR(cell);
+		}
+
+		buf = (u32 *)nvmem_cell_read(cell, &len);
+		nvmem_cell_put(cell);
+
+		if (IS_ERR(buf))
+			return PTR_ERR(buf);
+
+		for (j = 0; j < (len / sizeof(u32)); j++) {
+			if (index >= lvts_data->num_efuse_addr) {
+				dev_err(dev, "Array efuse is going to overflow");
+				kfree(buf);
+				return -EINVAL;
+			}
+
+			lvts_data->efuse[index] = buf[j];
+			index++;
+		}
+
+		kfree(buf);
+	}
+
+	ret = prepare_calibration_data(lvts_data);
+
+	return ret;
+}
+
+static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, j, s_index;
+	void __iomem *base;
+
+	lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*lvts_data->reg), GFP_KERNEL);
+	if (!lvts_data->reg)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+			lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
+		}
+	}
+
+	return 0;
+}
+
+static int of_update_lvts_data(struct lvts_data *lvts_data,
+	struct platform_device *pdev)
+{
+	struct device *dev = lvts_data->dev;
+	struct resource *res;
+	int ret;
+
+	lvts_data->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(lvts_data->clk))
+		return PTR_ERR(lvts_data->clk);
+
+	/* Get base address */
+	res = platform_get_mem_or_io(pdev, 0);
+	if (!res) {
+		dev_err(dev, "No IO resource\n");
+		return -ENXIO;
+	}
+
+	lvts_data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(lvts_data->base)) {
+		dev_err(dev, "Failed to remap io\n");
+		return PTR_ERR(lvts_data->base);
+	}
+
+	/* Get interrupt number */
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		dev_err(dev, "No irq resource\n");
+		return -EINVAL;
+	}
+	lvts_data->irq_num = ret;
+
+	/* Get reset control */
+	lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
+	if (IS_ERR(lvts_data->reset)) {
+		dev_err(dev, "Failed to get reset control\n");
+		return PTR_ERR(lvts_data->reset);
+	}
+
+	ret = lvts_init_tc_regs(dev, lvts_data);
+	if (ret)
+		return ret;
+
+	ret = get_calibration_data(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void lvts_device_close(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		lvts_write_device(lvts_data, RESET_ALL_DEVICES, i);
+		writel(DISABLE_LVTS_CTRL_CLK, LVTSCLKEN_0 + base);
+	}
+}
+
+static void lvts_close(struct lvts_data *lvts_data)
+{
+	disable_all_sensing_points(lvts_data);
+	wait_all_tc_sensing_point_idle(lvts_data);
+	lvts_device_close(lvts_data);
+	clk_disable_unprepare(lvts_data->clk);
+}
+
+static void tc_irq_handler(struct lvts_data *lvts_data, int tc_id)
+{
+	const struct device *dev = lvts_data->dev;
+	unsigned int ret = 0;
+	void __iomem *base;
+
+	base = GET_BASE_ADDR(lvts_data, tc_id);
+
+	ret = readl(LVTSMONINTSTS_0 + base);
+	/* Write back to clear interrupt status */
+	writel(ret, LVTSMONINTSTS_0 + base);
+
+	dev_dbg(dev, "LVTS thermal controller %d, LVTSMONINTSTS=0x%08x\n", tc_id, ret);
+
+	if (ret & THERMAL_PROTECTION_STAGE_3)
+		dev_dbg(dev, "Thermal protection stage 3 interrupt triggered\n");
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	unsigned int i, *irq_bitmap;
+	void __iomem *base;
+
+	irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
+
+	if (!irq_bitmap)
+		return IRQ_NONE;
+
+	base = lvts_data->base;
+	*irq_bitmap = readl(THERMINTST + base);
+	dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		if (tc[i].irq_bit == 0)
+			tc_irq_handler(lvts_data, i);
+	}
+
+	kfree(irq_bitmap);
+
+	return IRQ_HANDLED;
+}
+
+static int lvts_register_irq_handler(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	int ret;
+
+	ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
+		IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);
+
+	if (ret) {
+		dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
+			ret, lvts_data->irq_num);
+		lvts_close(lvts_data);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	struct thermal_zone_device *tzdev;
+	struct soc_temp_tz *lvts_tz;
+	int i, ret;
+
+	for (i = 0; i < lvts_data->num_sensor; i++) {
+		lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
+		if (!lvts_tz) {
+			lvts_close(lvts_data);
+			return -ENOMEM;
+		}
+
+		lvts_tz->id = i;
+		lvts_tz->lvts_data = lvts_data;
+
+		tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
+			lvts_tz, &soc_temp_lvts_ops);
+
+		if (IS_ERR(tzdev)) {
+			if (lvts_tz->id != 0)
+				return 0;
+
+			ret = PTR_ERR(tzdev);
+			dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",
+				lvts_tz->id, ret);
+			lvts_close(lvts_data);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+void lvts_device_enable_and_init_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		lvts_write_device(lvts_data, STOP_COUNTING_V4, i);
+		lvts_write_device(lvts_data, SET_RG_TSFM_LPDLY_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US1_V4, i);
+		lvts_write_device(lvts_data, SET_COUNTING_WINDOW_20US2_V4, i);
+		lvts_write_device(lvts_data, TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4, i);
+		lvts_write_device(lvts_data, TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4, i);
+		lvts_write_device(lvts_data, SET_TS_RSV_V4, i);
+		lvts_write_device(lvts_data, SET_TS_EN_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST1_V4, i);
+		lvts_write_device(lvts_data, TOGGLE_RG_TSV2F_VCO_RST2_V4, i);
+	}
+
+	lvts_data->counting_window_us = 20;
+}
+EXPORT_SYMBOL_GPL(lvts_device_enable_and_init_v4);
+
+void lvts_device_enable_auto_rck_v4(struct lvts_data *lvts_data)
+{
+	unsigned int i;
+
+	for (i = 0; i < lvts_data->num_tc; i++)
+		lvts_write_device(lvts_data, SET_LVTS_AUTO_RCK_V4, i);
+}
+EXPORT_SYMBOL_GPL(lvts_device_enable_auto_rck_v4);
+
+int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
+{
+	/* Resistor-Capacitor Calibration */
+	/* count_RC_N: count RC now */
+	struct device *dev = lvts_data->dev;
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int offset, size, s_index, data;
+	void __iomem *base;
+	int ret, i, j;
+	char buffer[512];
+
+	cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
+		sizeof(*cal_data->count_rc_now), GFP_KERNEL);
+	if (!cal_data->count_rc_now)
+		return -ENOMEM;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+
+			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
+			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
+			usleep_range(10, 20);
+
+			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
+			usleep_range(30, 40);
+
+			ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
+						 !(data & DEVICE_SENSING_STATUS), 2, 200);
+			if (ret)
+				dev_err(dev,
+					"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
+
+			data = lvts_read_device(lvts_data, 0x00, i);
+
+			cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));
+		}
+
+		/* Recover Setting for Normal Access on
+		 * temperature fetch
+		 */
+		lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
+		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+	}
+
+	size = sizeof(buffer);
+	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
+	for (i = 0; i < lvts_data->num_sensor; i++)
+		offset += snprintf(buffer + offset, size - offset, "%d:%d ",
+			i, cal_data->count_rc_now[i]);
+
+	buffer[offset] = '\0';
+	dev_dbg(dev, "%s\n", buffer);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
+
+void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
+{
+	const struct lvts_tc_settings *tc = lvts_data->tc;
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+	unsigned int i, j, s_index, lvts_calib_data;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		for (j = 0; j < tc[i].num_sensor; j++) {
+			s_index = tc[i].sensor_map[j];
+			if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
+				lvts_calib_data = cal_data->count_r[s_index];
+			else
+				lvts_calib_data = (((unsigned long long)
+					cal_data->count_rc_now[s_index]) *
+					cal_data->count_r[s_index]) >> 14;
+
+			writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
+
+void lvts_init_controller_v4(struct lvts_data *lvts_data)
+{
+	struct device *dev = lvts_data->dev;
+	unsigned int i;
+	void __iomem *base;
+
+	for (i = 0; i < lvts_data->num_tc; i++) {
+		base = GET_BASE_ADDR(lvts_data, i);
+
+		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
+
+		writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
+		writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
+
+		set_polling_speed(lvts_data, i);
+		set_hw_filter(lvts_data, i);
+
+		dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
+			i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));
+	}
+}
+EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
+
+int lvts_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct lvts_data *lvts_data;
+	int ret;
+
+	lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
+
+	if (!lvts_data)	{
+		dev_err(dev, "Error: Failed to get lvts platform data\n");
+		return -ENODATA;
+	}
+
+	lvts_data->dev = &pdev->dev;
+
+	ret = of_update_lvts_data(lvts_data, pdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, lvts_data);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	ret = lvts_register_irq_handler(lvts_data);
+	if (ret)
+		return ret;
+
+	ret = lvts_register_thermal_zones(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int lvts_remove(struct platform_device *pdev)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+int lvts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	lvts_close(lvts_data);
+
+	return 0;
+}
+
+int lvts_resume(struct platform_device *pdev)
+{
+	int ret;
+	struct lvts_data *lvts_data;
+
+	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
+
+	ret = lvts_init(lvts_data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.h b/drivers/thermal/mediatek/soc_temp_lvts.h
new file mode 100644
index 000000000000..6f8b6e3af98c
--- /dev/null
+++ b/drivers/thermal/mediatek/soc_temp_lvts.h
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#ifndef __MTK_SOC_TEMP_LVTS_H__
+#define __MTK_SOC_TEMP_LVTS_H__
+
+#define PERIOD_UNIT				12
+#define GROUP_INTERVAL_DELAY	1
+#define FILTER_INTERVAL_DELAY	1
+#define SENSOR_INTERVAL_DELAY	1
+
+#define HW_REBOOT_TRIP_POINT	117000
+
+#define FEATURE_DEVICE_AUTO_RCK	BIT(0)
+#define NUM_EFUSE_ADDR			22
+#define NUM_EFUSE_BLOCK_MT8192	1
+#define DEFAULT_GOLDEN_TEMP		50
+#define DEFAULT_CUONT_R			35000
+#define DEFAULT_CUONT_RC		2750
+#define COEFF_A					-250460
+#define COEFF_B					250460
+
+#define CLOCK_26MHZ_CYCLE_NS	38
+#define BUS_ACCESS_US			2
+#define GOLDEN_TEMP_MAX			62
+
+/* LVTS device register */
+#define RG_TSFM_DATA_0			0x00
+#define RG_TSFM_DATA_1			0x01
+#define RG_TSFM_DATA_2			0x02
+#define RG_TSFM_CTRL_0			0x03
+#define RG_TSFM_CTRL_1			0x04
+#define RG_TSFM_CTRL_2			0x05
+#define RG_TSFM_CTRL_3			0x06
+#define RG_TSFM_CTRL_4			0x07
+#define RG_TSV2F_CTRL_0			0x08
+#define RG_TSV2F_CTRL_1			0x09
+#define RG_TSV2F_CTRL_2			0x0A
+#define RG_TSV2F_CTRL_3			0x0B
+#define RG_TSV2F_CTRL_4			0x0C
+#define RG_TSV2F_CTRL_5			0x0D
+#define RG_TSV2F_CTRL_6			0x0E
+#define RG_TEMP_DATA_0			0x10
+#define RG_TEMP_DATA_1			0x11
+#define RG_TEMP_DATA_2			0x12
+#define RG_TEMP_DATA_3			0x13
+#define RG_RC_DATA_0			0x14
+#define RG_RC_DATA_1			0x15
+#define RG_RC_DATA_2			0x16
+#define RG_RC_DATA_3			0x17
+#define RG_DIV_DATA_0			0x18
+#define RG_DIV_DATA_1			0x19
+#define RG_DIV_DATA_2			0x1A
+#define RG_DIV_DATA_3			0x1B
+#define RG_TST_DATA_0			0x70
+#define RG_TST_DATA_1			0x71
+#define RG_TST_DATA_2			0x72
+#define RG_TST_CTRL				0x73
+#define RG_DBG_FQMTR			0xF0
+#define RG_DBG_LPSEQ			0xF1
+#define RG_DBG_STATE			0xF2
+#define RG_DBG_CHKSUM			0xF3
+#define RG_DID_LVTS				0xFC
+#define RG_DID_REV				0xFD
+#define RG_TSFM_RST				0xFF
+
+/* LVTS controller register */
+#define LVTSMONCTL0_0				0x000
+#define ENABLE_SENSING_POINT(num)	(LVTS_SINGLE_SENSE | GENMASK(((num) - 1), 0))
+#define DISABLE_SENSING_POINT		(LVTS_SINGLE_SENSE | 0x0)
+#define LVTSMONCTL1_0				0x004
+#define LVTSMONCTL2_0				0x008
+#define LVTSMONINT_0				0x00C
+#define STAGE3_INT_EN				BIT(31)
+#define LVTSMONINTSTS_0				0x010
+#define LVTSMONIDET0_0				0x014
+#define LVTSMONIDET1_0				0x018
+#define LVTSMONIDET2_0				0x01C
+#define LVTSMONIDET3_0				0x020
+#define LVTSH2NTHRE_0				0x024
+#define LVTSHTHRE_0					0x028
+#define LVTSCTHRE_0					0x02C
+#define LVTSOFFSETH_0				0x030
+#define LVTSOFFSETL_0				0x034
+#define LVTSMSRCTL0_0				0x038
+#define LVTSMSRCTL1_0				0x03C
+#define LVTSTSSEL_0					0x040
+#define SET_SENSOR_INDEX			0x13121110
+#define LVTSDEVICETO_0				0x044
+#define LVTSCALSCALE_0				0x048
+#define SET_CALC_SCALE_RULES		0x00000300
+#define LVTS_ID_0					0x04C
+#define LVTS_CONFIG_0				0x050
+
+#define SCK_ONLY					BIT(31)
+#define BROADCAST_ID_UPDATE			BIT(26)
+#define DEVICE_SENSING_STATUS		BIT(25)
+#define DEVICE_ACCESS_STARTUS		BIT(24)
+#define READ_32BIT_ACCESS			BIT(17)
+#define WRITE_ACCESS				BIT(16)
+#define LVTS_SINGLE_SENSE			BIT(9)
+#define FEATURE_CK26M_ACTIVE		BIT(1)
+#define DEVICE_REG_DATA				GENMASK(7, 0)
+
+#define LVTSEDATA00_0				0x054
+#define LVTSEDATA01_0				0x058
+#define LVTSEDATA02_0				0x05C
+#define LVTSEDATA03_0				0x060
+#define LVTSMSR0_0					0x090
+#define MRS_RAW_MASK				GENMASK(15, 0)
+#define MRS_RAW_VALID_BIT			BIT(16)
+#define LVTSMSR1_0					0x094
+#define LVTSMSR2_0					0x098
+#define LVTSMSR3_0					0x09C
+#define LVTSIMMD0_0					0x0A0
+#define LVTSIMMD1_0					0x0A4
+#define LVTSIMMD2_0					0x0A8
+#define LVTSIMMD3_0					0x0AC
+#define LVTSRDATA0_0				0x0B0
+#define LVTSRDATA1_0				0x0B4
+#define LVTSRDATA2_0				0x0B8
+#define LVTSRDATA3_0				0x0BC
+#define LVTSPROTCTL_0				0x0C0
+#define PROTOFFSET					GENMASK(15, 0)
+#define LVTSPROTTA_0				0x0C4
+#define LVTSPROTTB_0				0x0C8
+#define LVTSPROTTC_0				0x0CC
+#define LVTSCLKEN_0					0x0E4
+#define ENABLE_LVTS_CTRL_CLK		(1)
+#define DISABLE_LVTS_CTRL_CLK		(0)
+#define LVTSDBGSEL_0				0x0E8
+#define LVTSDBGSIG_0				0x0EC
+#define LVTSSPARE0_0				0x0F0
+#define LVTSSPARE1_0				0x0F4
+#define LVTSSPARE2_0				0x0F8
+#define LVTSSPARE3_0				0x0FC
+#define THERMINTST					0xF04
+
+/* LVTS register mask */
+#define THERMAL_COLD_INTERRUPT_0			BIT(0)
+#define THERMAL_HOT_INTERRUPT_0				BIT(1)
+#define THERMAL_LOW_OFFSET_INTERRUPT_0		BIT(2)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_0		BIT(3)
+#define THERMAL_HOT2NORMAL_INTERRUPT_0		BIT(4)
+#define THERMAL_COLD_INTERRUPT_1			BIT(5)
+#define THERMAL_HOT_INTERRUPT_1				BIT(6)
+#define THERMAL_LOW_OFFSET_INTERRUPT_1		BIT(7)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_1		BIT(8)
+#define THERMAL_HOT2NORMAL_INTERRUPT_1		BIT(9)
+#define THERMAL_COLD_INTERRUPT_2			BIT(10)
+#define THERMAL_HOT_INTERRUPT_2				BIT(11)
+#define THERMAL_LOW_OFFSET_INTERRUPT_2		BIT(12)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_2		BIT(13)
+#define THERMAL_HOT2NORMAL_INTERRUPT_2		BIT(14)
+#define THERMAL_AHB_TIMEOUT_INTERRUPT		BIT(15)
+#define THERMAL_DEVICE_TIMEOUT_INTERRUPT	BIT(15)
+#define THERMAL_IMMEDIATE_INTERRUPT_0		BIT(16)
+#define THERMAL_IMMEDIATE_INTERRUPT_1		BIT(17)
+#define THERMAL_IMMEDIATE_INTERRUPT_2		BIT(18)
+#define THERMAL_FILTER_INTERRUPT_0			BIT(19)
+#define THERMAL_FILTER_INTERRUPT_1			BIT(20)
+#define THERMAL_FILTER_INTERRUPT_2			BIT(21)
+#define THERMAL_COLD_INTERRUPT_3			BIT(22)
+#define THERMAL_HOT_INTERRUPT_3				BIT(23)
+#define THERMAL_LOW_OFFSET_INTERRUPT_3		BIT(24)
+#define THERMAL_HIGH_OFFSET_INTERRUPT_3		BIT(25)
+#define THERMAL_HOT2NORMAL_INTERRUPT_3		BIT(26)
+#define THERMAL_IMMEDIATE_INTERRUPT_3		BIT(27)
+#define THERMAL_FILTER_INTERRUPT_3			BIT(28)
+#define THERMAL_PROTECTION_STAGE_1			BIT(29)
+#define THERMAL_PROTECTION_STAGE_2			BIT(30)
+#define THERMAL_PROTECTION_STAGE_3			BIT(31)
+
+#define CFG_REGISTER(reg, value)	(reg << 8 | value)
+#define STOP_COUNTING_V4					CFG_REGISTER(RG_TSFM_CTRL_0, 0x00)
+#define SET_RG_TSFM_LPDLY_V4				CFG_REGISTER(RG_TSFM_CTRL_4, 0xA6)
+#define SET_COUNTING_WINDOW_20US1_V4		CFG_REGISTER(RG_TSFM_CTRL_2, 0x00)
+#define SET_COUNTING_WINDOW_20US2_V4		CFG_REGISTER(RG_TSFM_CTRL_1, 0x20)
+#define TSV2F_CHOP_CKSEL_AND_TSV2F_EN_V4	CFG_REGISTER(RG_TSV2F_CTRL_2, 0x84)
+#define TSBG_DEM_CKSEL_X_TSBG_CHOP_EN_V4	CFG_REGISTER(RG_TSV2F_CTRL_4, 0x7C)
+#define SET_TS_RSV_V4						CFG_REGISTER(RG_TSV2F_CTRL_1, 0x8D)
+#define SET_TS_EN_V4						CFG_REGISTER(RG_TSV2F_CTRL_0, 0xF4)
+#define TOGGLE_RG_TSV2F_VCO_RST1_V4			CFG_REGISTER(RG_TSV2F_CTRL_0, 0xFC)
+#define TOGGLE_RG_TSV2F_VCO_RST2_V4			CFG_REGISTER(RG_TSV2F_CTRL_0, 0xF4)
+
+#define SET_LVTS_AUTO_RCK_V4				CFG_REGISTER(RG_TSV2F_CTRL_6, 0x01)
+#define SELECT_SENSOR_RCK_V4(id)			CFG_REGISTER(RG_TSV2F_CTRL_5, (id))
+#define SET_DEVICE_SINGLE_MODE_V4			CFG_REGISTER(RG_TSFM_CTRL_3, 0x78)
+#define KICK_OFF_RCK_COUNTING_V4			CFG_REGISTER(RG_TSFM_CTRL_0, 0x02)
+#define SET_SENSOR_NO_RCK_V4				CFG_REGISTER(RG_TSV2F_CTRL_5, 0x10)
+#define SET_DEVICE_LOW_POWER_SINGLE_MODE_V4	CFG_REGISTER(RG_TSFM_CTRL_3, 0xB8)
+
+#define HAS_FEATURE(lvts_data, feature)		(lvts_data->feature_bitmap & (feature))
+#define GET_BASE_ADDR(lvts_data, tc_id)		(lvts_data->base + lvts_data->tc[tc_id].addr_offset)
+#define GET_CAL_DATA_BITMASK(index, lvts_data, h, l)	(((index) < lvts_data->num_efuse_addr) \
+	? ((lvts_data->efuse[(index)] & GENMASK(h, l)) >> l) : 0)
+
+#define GET_TC_SENSOR_NUM(lvts_data, tc_id)		(lvts_data->tc[tc_id].num_sensor)
+#define ONE_SAMPLE		(lvts_data->counting_window_us + 2 * BUS_ACCESS_US)
+#define NUM_OF_SAMPLE(tc_id)	((lvts_data->tc[tc_id].hw_filter < LVTS_FILTER_2) ? 1 :	\
+	((lvts_data->tc[tc_id].hw_filter > LVTS_FILTER_16_OF_18) ? 1 :	\
+	((lvts_data->tc[tc_id].hw_filter == LVTS_FILTER_16_OF_18) ? 18 : \
+	((lvts_data->tc[tc_id].hw_filter == LVTS_FILTER_8_OF_10) ? 10 :	\
+	(lvts_data->tc[tc_id].hw_filter * 2)))))
+
+#define PERIOD_UNIT_US(tc_id)	((lvts_data->tc[tc_id].tc_speed->period_unit * 256 * \
+	CLOCK_26MHZ_CYCLE_NS) / 1000)
+#define FILTER_INT_US(tc_id)	(lvts_data->tc[tc_id].tc_speed->filter_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define SENSOR_INT_US(tc_id)	(lvts_data->tc[tc_id].tc_speed->sensor_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define GROUP_INT_US(tc_id)		(lvts_data->tc[tc_id].tc_speed->group_interval_delay * \
+	PERIOD_UNIT_US(tc_id))
+#define SENSOR_LATENCY_US(tc_id)	((NUM_OF_SAMPLE(tc_id) - 1) * FILTER_INT_US(tc_id) + \
+	NUM_OF_SAMPLE(tc_id) * ONE_SAMPLE)
+#define GROUP_LATENCY_US(tc_id)		(GET_TC_SENSOR_NUM(lvts_data, tc_id) * \
+	SENSOR_LATENCY_US(tc_id) + (GET_TC_SENSOR_NUM(lvts_data, tc_id) - 1) * SENSOR_INT_US(tc_id) + \
+	GROUP_INT_US(tc_id))
+
+#define CK26M_ACTIVE(lvts_data)	(((lvts_data->feature_bitmap & FEATURE_CK26M_ACTIVE) ? 1 : 0) << 30)
+#define DEVICE_ACCESS			(SCK_ONLY | DEVICE_ACCESS_STARTUS | READ_32BIT_ACCESS)
+#define DEVICE_READ				(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS)
+#define DEVICE_WRITE			(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS | WRITE_ACCESS)
+#define READ_BACK_DEVICE_ID		(CK26M_ACTIVE(lvts_data) | DEVICE_ACCESS | BROADCAST_ID_UPDATE | \
+	RG_DID_LVTS << 8)
+#define READ_DEVICE_REG(reg_idx)	(DEVICE_READ | (reg_idx) << 8 | 0x00)
+#define RESET_ALL_DEVICES			(DEVICE_WRITE | RG_TSFM_RST << 8 | 0xFF)
+
+/*
+ * LVTS HW filter settings
+ * 000: Get one sample
+ * 001: Get 2 samples and average them
+ * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+ * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+ * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+ * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+ */
+enum lvts_hw_filter {
+	LVTS_FILTER_1,
+	LVTS_FILTER_2,
+	LVTS_FILTER_2_OF_4,
+	LVTS_FILTER_4_OF_6,
+	LVTS_FILTER_8_OF_10,
+	LVTS_FILTER_16_OF_18
+};
+
+enum lvts_sensing_point {
+	SENSING_POINT0,
+	SENSING_POINT1,
+	SENSING_POINT2,
+	SENSING_POINT3,
+	ALL_SENSING_POINTS
+};
+
+struct lvts_data;
+
+/**
+ * struct lvts_speed_settings - A structure to hold the data related to polling rate
+ * @period_unit: Period unit is a base for all interval delays
+ * @group_interval_delay:  Delay between different rounds
+ * @filter_interval_delay: Delay between two samples of the same sensor
+ * @sensor_interval_delay: Delay between two samples of differnet sensors
+ *
+ * Calculation is achieved with the following equations:
+ * For the period unit: (period_us * 1000) / (256 * clock_26mhz_cycle_ns)
+ * For the interval delays: delay / period_us
+ */
+struct lvts_speed_settings {
+	unsigned int period_unit;
+	unsigned int group_interval_delay;
+	unsigned int filter_interval_delay;
+	unsigned int sensor_interval_delay;
+};
+
+struct lvts_tc_settings {
+	unsigned int dev_id;
+	unsigned int addr_offset;
+	unsigned int num_sensor;
+	unsigned int sensor_map[ALL_SENSING_POINTS];	/* In sensor ID */
+	struct lvts_speed_settings *tc_speed;
+	/*
+	 * HW filter setting
+	 * 000: Get one sample
+	 * 001: Get 2 samples and average them
+	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
+	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
+	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
+	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
+	 */
+	unsigned int hw_filter;
+	/*
+	 * Dominator_sensing point is used to select a sensing point
+	 * and reference its temperature to trigger Thermal HW Reboot
+	 * When it is ALL_SENSING_POINTS, it will select all sensing points
+	 */
+	int dominator_sensing_point;
+	int hw_reboot_trip_point;		/* -274000: Disable HW reboot */
+	unsigned int irq_bit;
+};
+
+struct lvts_formula_coeff {
+	int a;
+	int b;
+	unsigned int golden_temp;
+};
+
+struct lvts_sensor_cal_data {
+	int use_fake_efuse;				/* 1: Use fake efuse, 0: Use real efuse */
+	unsigned int golden_temp;
+	unsigned int *count_r;
+	unsigned int *count_rc;
+	unsigned int *count_rc_now;
+	unsigned int default_golden_temp;
+	unsigned int default_count_r;
+	unsigned int default_count_rc;
+};
+
+struct platform_ops {
+	void (*efuse_to_cal_data)(struct lvts_data *lvts_data);
+	void (*device_enable_and_init)(struct lvts_data *lvts_data);
+	void (*device_enable_auto_rck)(struct lvts_data *lvts_data);
+	int (*device_read_count_rc_n)(struct lvts_data *lvts_data);
+	void (*set_cal_data)(struct lvts_data *lvts_data);
+	void (*init_controller)(struct lvts_data *lvts_data);
+};
+
+struct lvts_data {
+	struct device *dev;
+	struct clk *clk;
+	void __iomem *base;				/* LVTS base addresses */
+	unsigned int irq_num;			/* LVTS interrupt numbers */
+	struct reset_control *reset;
+	int num_tc;						/* Number of LVTS thermal controllers */
+	const struct lvts_tc_settings *tc;
+	int counting_window_us;			/* LVTS device counting window */
+	int num_sensor;					/* Number of sensors in this platform */
+	void __iomem **reg;
+	struct platform_ops ops;
+	int feature_bitmap;				/* Show what features are enabled */
+	unsigned int num_efuse_addr;
+	unsigned int *efuse;
+	unsigned int num_efuse_block;	/* Number of contiguous efuse indexes */
+	struct lvts_sensor_cal_data cal_data;
+	struct lvts_formula_coeff coeff;
+};
+
+struct soc_temp_tz {
+	unsigned int id;
+	struct lvts_data *lvts_data;
+};
+
+extern void lvts_device_enable_and_init_v4(struct lvts_data *lvts_data);
+extern void lvts_device_enable_auto_rck_v4(struct lvts_data *lvts_data);
+extern int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data);
+extern void lvts_set_calibration_data_v4(struct lvts_data *lvts_data);
+extern void lvts_init_controller_v4(struct lvts_data *lvts_data);
+
+extern int lvts_probe(struct platform_device *pdev);
+extern int lvts_remove(struct platform_device *pdev);
+extern int lvts_suspend(struct platform_device *pdev, pm_message_t state);
+extern int lvts_resume(struct platform_device *pdev);
+
+#endif /* __MTK_SOC_TEMP_LVTS_H__ */
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 4/6] thermal: mediatek: Add thermal zone settings for mt8195
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add thermal zone settings for mt8195

Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/mediatek/Kconfig         |  12 ++
 drivers/thermal/mediatek/Makefile        |   1 +
 drivers/thermal/mediatek/lvts_mt8195.c   | 253 +++++++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h |   1 +
 4 files changed, 267 insertions(+)
 create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c

diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
index 7fc04237dd50..df3b4a033fc2 100644
--- a/drivers/thermal/mediatek/Kconfig
+++ b/drivers/thermal/mediatek/Kconfig
@@ -47,4 +47,16 @@ config LVTS_MT8192
 		configures LVTS thermal controllers to collect temperatures
 		via ASIF.
 
+config LVTS_MT8195
+	tristate "LVTS driver for MediaTek MT8195 SoC"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	depends on MTK_SOC_THERMAL_LVTS
+	help
+		Enable this option if you want to get SoC temperature
+		information for MT8195. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via ASIF.
+
 endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
index 5ff1197e80ab..dada1bf13110 100644
--- a/drivers/thermal/mediatek/Makefile
+++ b/drivers/thermal/mediatek/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
 obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
 obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
+obj-$(CONFIG_LVTS_MT8195)			+= lvts_mt8195.o
diff --git a/drivers/thermal/mediatek/lvts_mt8195.c b/drivers/thermal/mediatek/lvts_mt8195.c
new file mode 100644
index 000000000000..df69e2e79115
--- /dev/null
+++ b/drivers/thermal/mediatek/lvts_mt8195.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include "soc_temp_lvts.h"
+
+enum mt8195_lvts_mcu_sensor_enum {
+	MT8195_TS1_0,		// cpu_big1
+	MT8195_TS1_1,		// cpu_big2
+	MT8195_TS2_0,		// cpu_big3
+	MT8195_TS2_1,		// cpu_big4
+	MT8195_TS3_0,		// cpu_little1
+	MT8195_TS3_1,		// cpu_little2
+	MT8195_TS3_2,		// cpu_little3
+	MT8195_TS3_3,		// cpu_little4
+	MT8195_NUM_TS_MCU
+};
+
+enum mt8195_lvts_ap_sensor_enum {
+	MT8195_TS4_0,		// vpu1
+	MT8195_TS4_1,		// vpu2
+	MT8195_TS5_0,		// gpu1
+	MT8195_TS5_1,		// gpu2
+	MT8195_TS6_0,		// vdec
+	MT8195_TS6_1,		// img
+	MT8195_TS6_2,		// infra
+	MT8195_TS7_0,		// cam1
+	MT8195_TS7_1,		// cam2
+	MT8195_NUM_TS_AP
+};
+
+static void mt8195_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	cal_data->count_r[MT8195_TS1_0] = GET_CAL_DATA_BITMASK(1, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS1_1] = (GET_CAL_DATA_BITMASK(2, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(1, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS2_0] = GET_CAL_DATA_BITMASK(3, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS2_1] = GET_CAL_DATA_BITMASK(4, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS3_0] = (GET_CAL_DATA_BITMASK(6, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(5, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS3_1] = GET_CAL_DATA_BITMASK(6, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS3_2] = GET_CAL_DATA_BITMASK(7, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS3_3] = (GET_CAL_DATA_BITMASK(8, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(7, lvts_data, 31, 24);
+
+	cal_data->count_rc[MT8195_TS1_0] = (GET_CAL_DATA_BITMASK(3, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(2, lvts_data, 31, 16);
+	cal_data->count_rc[MT8195_TS2_0] = (GET_CAL_DATA_BITMASK(5, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(4, lvts_data, 31, 24);
+	cal_data->count_rc[MT8195_TS3_0] = (GET_CAL_DATA_BITMASK(9, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(8, lvts_data, 31, 16);
+}
+
+static void mt8195_ap_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	cal_data->count_r[MT8195_TS4_0] = GET_CAL_DATA_BITMASK(9, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS4_1] = GET_CAL_DATA_BITMASK(10, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS5_0] = (GET_CAL_DATA_BITMASK(12, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(11, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS5_1] = GET_CAL_DATA_BITMASK(12, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS6_0] = (GET_CAL_DATA_BITMASK(14, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(13, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS6_1] = (GET_CAL_DATA_BITMASK(15, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(14, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS6_2] = GET_CAL_DATA_BITMASK(15, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS7_0] = (GET_CAL_DATA_BITMASK(17, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(16, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS7_1] = (GET_CAL_DATA_BITMASK(18, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(17, lvts_data, 31, 16);
+
+	cal_data->count_rc[MT8195_TS4_0] = (GET_CAL_DATA_BITMASK(11, lvts_data, 15, 0) << 8) +
+						GET_CAL_DATA_BITMASK(10, lvts_data, 31, 24);
+	cal_data->count_rc[MT8195_TS5_0] = GET_CAL_DATA_BITMASK(13, lvts_data, 23, 0);
+	cal_data->count_rc[MT8195_TS6_0] = GET_CAL_DATA_BITMASK(16, lvts_data, 23, 0);
+	cal_data->count_rc[MT8195_TS7_0] = GET_CAL_DATA_BITMASK(18, lvts_data, 31, 8);
+}
+
+static struct lvts_speed_settings tc_speed_mt8195 = {
+	.period_unit = PERIOD_UNIT,
+	.group_interval_delay = GROUP_INTERVAL_DELAY,
+	.filter_interval_delay = FILTER_INTERVAL_DELAY,
+	.sensor_interval_delay = SENSOR_INTERVAL_DELAY,
+};
+
+static const struct lvts_tc_settings mt8195_tc_mcu_settings[] = {
+	[0] = {
+		.dev_id = 0x81,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS1_0, MT8195_TS1_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x82,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS2_0, MT8195_TS2_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x83,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT8195_TS3_0, MT8195_TS3_1, MT8195_TS3_2, MT8195_TS3_3},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	}
+};
+
+static const struct lvts_tc_settings mt8195_tc_ap_settings[] = {
+	[0] = {
+		.dev_id = 0x84,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS4_0, MT8195_TS4_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x85,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS5_0, MT8195_TS5_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x86,
+		.addr_offset = 0x200,
+		.num_sensor = 3,
+		.sensor_map = {MT8195_TS6_0, MT8195_TS6_1, MT8195_TS6_2},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.dev_id = 0x87,
+		.addr_offset = 0x300,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS7_0, MT8195_TS7_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(6),
+	}
+};
+
+static const struct lvts_data mt8195_lvts_mcu_data = {
+	.num_tc = (ARRAY_SIZE(mt8195_tc_mcu_settings)),
+	.tc = mt8195_tc_mcu_settings,
+	.num_sensor = MT8195_NUM_TS_MCU,
+	.ops = {
+		.efuse_to_cal_data = mt8195_mcu_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8195,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct lvts_data mt8195_lvts_ap_data = {
+	.num_tc = (ARRAY_SIZE(mt8195_tc_ap_settings)),
+	.tc = mt8195_tc_ap_settings,
+	.num_sensor = MT8195_NUM_TS_AP,
+	.ops = {
+		.efuse_to_cal_data = mt8195_ap_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8195,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct of_device_id lvts_of_match[] = {
+	{ .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data, },
+	{ .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvts_of_match);
+
+static struct platform_driver soc_temp_lvts = {
+	.probe = lvts_probe,
+	.remove = lvts_remove,
+	.suspend = lvts_suspend,
+	.resume = lvts_resume,
+	.driver = {
+		.name = "mtk-soc-temp-lvts-mt8195",
+		.of_match_table = lvts_of_match,
+	},
+};
+module_platform_driver(soc_temp_lvts);
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.h b/drivers/thermal/mediatek/soc_temp_lvts.h
index 6f8b6e3af98c..c4acb7e26e5e 100644
--- a/drivers/thermal/mediatek/soc_temp_lvts.h
+++ b/drivers/thermal/mediatek/soc_temp_lvts.h
@@ -16,6 +16,7 @@
 #define FEATURE_DEVICE_AUTO_RCK	BIT(0)
 #define NUM_EFUSE_ADDR			22
 #define NUM_EFUSE_BLOCK_MT8192	1
+#define NUM_EFUSE_BLOCK_MT8195	2
 #define DEFAULT_GOLDEN_TEMP		50
 #define DEFAULT_CUONT_R			35000
 #define DEFAULT_CUONT_RC		2750
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 4/6] thermal: mediatek: Add thermal zone settings for mt8195
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Add thermal zone settings for mt8195

Signed-off-by: Michael Kao <michael.kao@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 drivers/thermal/mediatek/Kconfig         |  12 ++
 drivers/thermal/mediatek/Makefile        |   1 +
 drivers/thermal/mediatek/lvts_mt8195.c   | 253 +++++++++++++++++++++++
 drivers/thermal/mediatek/soc_temp_lvts.h |   1 +
 4 files changed, 267 insertions(+)
 create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c

diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
index 7fc04237dd50..df3b4a033fc2 100644
--- a/drivers/thermal/mediatek/Kconfig
+++ b/drivers/thermal/mediatek/Kconfig
@@ -47,4 +47,16 @@ config LVTS_MT8192
 		configures LVTS thermal controllers to collect temperatures
 		via ASIF.
 
+config LVTS_MT8195
+	tristate "LVTS driver for MediaTek MT8195 SoC"
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on RESET_TI_SYSCON
+	depends on MTK_SOC_THERMAL_LVTS
+	help
+		Enable this option if you want to get SoC temperature
+		information for MT8195. This driver
+		configures LVTS thermal controllers to collect temperatures
+		via ASIF.
+
 endif
diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
index 5ff1197e80ab..dada1bf13110 100644
--- a/drivers/thermal/mediatek/Makefile
+++ b/drivers/thermal/mediatek/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
 obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
 obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
+obj-$(CONFIG_LVTS_MT8195)			+= lvts_mt8195.o
diff --git a/drivers/thermal/mediatek/lvts_mt8195.c b/drivers/thermal/mediatek/lvts_mt8195.c
new file mode 100644
index 000000000000..df69e2e79115
--- /dev/null
+++ b/drivers/thermal/mediatek/lvts_mt8195.c
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include "soc_temp_lvts.h"
+
+enum mt8195_lvts_mcu_sensor_enum {
+	MT8195_TS1_0,		// cpu_big1
+	MT8195_TS1_1,		// cpu_big2
+	MT8195_TS2_0,		// cpu_big3
+	MT8195_TS2_1,		// cpu_big4
+	MT8195_TS3_0,		// cpu_little1
+	MT8195_TS3_1,		// cpu_little2
+	MT8195_TS3_2,		// cpu_little3
+	MT8195_TS3_3,		// cpu_little4
+	MT8195_NUM_TS_MCU
+};
+
+enum mt8195_lvts_ap_sensor_enum {
+	MT8195_TS4_0,		// vpu1
+	MT8195_TS4_1,		// vpu2
+	MT8195_TS5_0,		// gpu1
+	MT8195_TS5_1,		// gpu2
+	MT8195_TS6_0,		// vdec
+	MT8195_TS6_1,		// img
+	MT8195_TS6_2,		// infra
+	MT8195_TS7_0,		// cam1
+	MT8195_TS7_1,		// cam2
+	MT8195_NUM_TS_AP
+};
+
+static void mt8195_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	cal_data->count_r[MT8195_TS1_0] = GET_CAL_DATA_BITMASK(1, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS1_1] = (GET_CAL_DATA_BITMASK(2, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(1, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS2_0] = GET_CAL_DATA_BITMASK(3, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS2_1] = GET_CAL_DATA_BITMASK(4, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS3_0] = (GET_CAL_DATA_BITMASK(6, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(5, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS3_1] = GET_CAL_DATA_BITMASK(6, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS3_2] = GET_CAL_DATA_BITMASK(7, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS3_3] = (GET_CAL_DATA_BITMASK(8, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(7, lvts_data, 31, 24);
+
+	cal_data->count_rc[MT8195_TS1_0] = (GET_CAL_DATA_BITMASK(3, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(2, lvts_data, 31, 16);
+	cal_data->count_rc[MT8195_TS2_0] = (GET_CAL_DATA_BITMASK(5, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(4, lvts_data, 31, 24);
+	cal_data->count_rc[MT8195_TS3_0] = (GET_CAL_DATA_BITMASK(9, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(8, lvts_data, 31, 16);
+}
+
+static void mt8195_ap_efuse_to_cal_data(struct lvts_data *lvts_data)
+{
+	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
+
+	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
+
+	cal_data->count_r[MT8195_TS4_0] = GET_CAL_DATA_BITMASK(9, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS4_1] = GET_CAL_DATA_BITMASK(10, lvts_data, 23, 0);
+	cal_data->count_r[MT8195_TS5_0] = (GET_CAL_DATA_BITMASK(12, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(11, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS5_1] = GET_CAL_DATA_BITMASK(12, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS6_0] = (GET_CAL_DATA_BITMASK(14, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(13, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS6_1] = (GET_CAL_DATA_BITMASK(15, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(14, lvts_data, 31, 16);
+	cal_data->count_r[MT8195_TS6_2] = GET_CAL_DATA_BITMASK(15, lvts_data, 31, 8);
+	cal_data->count_r[MT8195_TS7_0] = (GET_CAL_DATA_BITMASK(17, lvts_data, 15, 0) << 8) +
+		GET_CAL_DATA_BITMASK(16, lvts_data, 31, 24);
+	cal_data->count_r[MT8195_TS7_1] = (GET_CAL_DATA_BITMASK(18, lvts_data, 7, 0) << 16) +
+		GET_CAL_DATA_BITMASK(17, lvts_data, 31, 16);
+
+	cal_data->count_rc[MT8195_TS4_0] = (GET_CAL_DATA_BITMASK(11, lvts_data, 15, 0) << 8) +
+						GET_CAL_DATA_BITMASK(10, lvts_data, 31, 24);
+	cal_data->count_rc[MT8195_TS5_0] = GET_CAL_DATA_BITMASK(13, lvts_data, 23, 0);
+	cal_data->count_rc[MT8195_TS6_0] = GET_CAL_DATA_BITMASK(16, lvts_data, 23, 0);
+	cal_data->count_rc[MT8195_TS7_0] = GET_CAL_DATA_BITMASK(18, lvts_data, 31, 8);
+}
+
+static struct lvts_speed_settings tc_speed_mt8195 = {
+	.period_unit = PERIOD_UNIT,
+	.group_interval_delay = GROUP_INTERVAL_DELAY,
+	.filter_interval_delay = FILTER_INTERVAL_DELAY,
+	.sensor_interval_delay = SENSOR_INTERVAL_DELAY,
+};
+
+static const struct lvts_tc_settings mt8195_tc_mcu_settings[] = {
+	[0] = {
+		.dev_id = 0x81,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS1_0, MT8195_TS1_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x82,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS2_0, MT8195_TS2_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x83,
+		.addr_offset = 0x200,
+		.num_sensor = 4,
+		.sensor_map = {MT8195_TS3_0, MT8195_TS3_1, MT8195_TS3_2, MT8195_TS3_3},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	}
+};
+
+static const struct lvts_tc_settings mt8195_tc_ap_settings[] = {
+	[0] = {
+		.dev_id = 0x84,
+		.addr_offset = 0x0,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS4_0, MT8195_TS4_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(3),
+	},
+	[1] = {
+		.dev_id = 0x85,
+		.addr_offset = 0x100,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS5_0, MT8195_TS5_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(4),
+	},
+	[2] = {
+		.dev_id = 0x86,
+		.addr_offset = 0x200,
+		.num_sensor = 3,
+		.sensor_map = {MT8195_TS6_0, MT8195_TS6_1, MT8195_TS6_2},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT1,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(5),
+	},
+	[3] = {
+		.dev_id = 0x87,
+		.addr_offset = 0x300,
+		.num_sensor = 2,
+		.sensor_map = {MT8195_TS7_0, MT8195_TS7_1},
+		.tc_speed = &tc_speed_mt8195,
+		.hw_filter = LVTS_FILTER_2_OF_4,
+		.dominator_sensing_point = SENSING_POINT0,
+		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
+		.irq_bit = BIT(6),
+	}
+};
+
+static const struct lvts_data mt8195_lvts_mcu_data = {
+	.num_tc = (ARRAY_SIZE(mt8195_tc_mcu_settings)),
+	.tc = mt8195_tc_mcu_settings,
+	.num_sensor = MT8195_NUM_TS_MCU,
+	.ops = {
+		.efuse_to_cal_data = mt8195_mcu_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8195,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct lvts_data mt8195_lvts_ap_data = {
+	.num_tc = (ARRAY_SIZE(mt8195_tc_ap_settings)),
+	.tc = mt8195_tc_ap_settings,
+	.num_sensor = MT8195_NUM_TS_AP,
+	.ops = {
+		.efuse_to_cal_data = mt8195_ap_efuse_to_cal_data,
+		.device_enable_and_init = lvts_device_enable_and_init_v4,
+		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
+		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
+		.set_cal_data = lvts_set_calibration_data_v4,
+		.init_controller = lvts_init_controller_v4,
+	},
+	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
+	.num_efuse_addr = NUM_EFUSE_ADDR,
+	.num_efuse_block = NUM_EFUSE_BLOCK_MT8195,
+	.cal_data = {
+		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
+		.default_count_r = DEFAULT_CUONT_R,
+		.default_count_rc = DEFAULT_CUONT_RC,
+	},
+	.coeff = {
+		.a = COEFF_A,
+		.b = COEFF_B,
+	},
+};
+
+static const struct of_device_id lvts_of_match[] = {
+	{ .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data, },
+	{ .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, lvts_of_match);
+
+static struct platform_driver soc_temp_lvts = {
+	.probe = lvts_probe,
+	.remove = lvts_remove,
+	.suspend = lvts_suspend,
+	.resume = lvts_resume,
+	.driver = {
+		.name = "mtk-soc-temp-lvts-mt8195",
+		.of_match_table = lvts_of_match,
+	},
+};
+module_platform_driver(soc_temp_lvts);
+
+MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
+MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek soc temperature driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/mediatek/soc_temp_lvts.h b/drivers/thermal/mediatek/soc_temp_lvts.h
index 6f8b6e3af98c..c4acb7e26e5e 100644
--- a/drivers/thermal/mediatek/soc_temp_lvts.h
+++ b/drivers/thermal/mediatek/soc_temp_lvts.h
@@ -16,6 +16,7 @@
 #define FEATURE_DEVICE_AUTO_RCK	BIT(0)
 #define NUM_EFUSE_ADDR			22
 #define NUM_EFUSE_BLOCK_MT8192	1
+#define NUM_EFUSE_BLOCK_MT8195	2
 #define DEFAULT_GOLDEN_TEMP		50
 #define DEFAULT_CUONT_R			35000
 #define DEFAULT_CUONT_RC		2750
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This adds the efuse node. This will be required by the thermal driver
to get the calibration data.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 0ff34edcf8c8..4fbf24b5d202 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
 			status = "disabled";
 		};
 
+		efuse: efuse@11c10000 {
+			compatible = "mediatek,efuse";
+			reg = <0 0x11c10000 0 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			lvts_efuse_data1: lvts1-calib@1bc {
+				reg = <0x1bc 0x14>;
+			};
+			lvts_efuse_data2: lvts2-calib@1d0 {
+				reg = <0x1d0 0x38>;
+			};
+			svs_calibration: calib@580 {
+				reg = <0x580 0x64>;
+			};
+		};
+
 		u3phy2: t-phy@11c40000 {
 			compatible = "mediatek,mt8195-tphy", "mediatek,generic-tphy-v3";
 			#address-cells = <1>;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This adds the efuse node. This will be required by the thermal driver
to get the calibration data.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 0ff34edcf8c8..4fbf24b5d202 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
 			status = "disabled";
 		};
 
+		efuse: efuse@11c10000 {
+			compatible = "mediatek,efuse";
+			reg = <0 0x11c10000 0 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			lvts_efuse_data1: lvts1-calib@1bc {
+				reg = <0x1bc 0x14>;
+			};
+			lvts_efuse_data2: lvts2-calib@1d0 {
+				reg = <0x1d0 0x38>;
+			};
+			svs_calibration: calib@580 {
+				reg = <0x580 0x64>;
+			};
+		};
+
 		u3phy2: t-phy@11c40000 {
 			compatible = "mediatek,mt8195-tphy", "mediatek,generic-tphy-v3";
 			#address-cells = <1>;
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 6/6] arm64: dts: mt8195: Add thermal zone
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-26 13:55   ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This adds the thermal zone for the mt8195.

Signed-off-by: Tinghan Shen <tinghan.shen@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 arch/arm64/boot/dts/mediatek/mt8195.dtsi | 115 ++++++++++++++++++++++-
 1 file changed, 114 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 4fbf24b5d202..78017224930c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
- * Copyright (c) 2021 MediaTek Inc.
+ * Copyright (c) 2022 MediaTek Inc.
  * Author: Seiya Wang <seiya.wang@mediatek.com>
  */
 
@@ -11,6 +11,9 @@
 #include <dt-bindings/memory/mt8195-memory-port.h>
 #include <dt-bindings/phy/phy.h>
 #include <dt-bindings/pinctrl/mt8195-pinfunc.h>
+#include <dt-bindings/power/mt8195-power.h>
+#include <dt-bindings/reset/mt8195-resets.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "mediatek,mt8195";
@@ -810,6 +813,28 @@ spi0: spi@1100a000 {
 			status = "disabled";
 		};
 
+		lvtsap: thermal-sensor@1100b000 {
+			compatible = "mediatek,mt8195-lvts-ap";
+			#thermal-sensor-cells = <1>;
+			reg = <0 0x1100b000 0 0x400>;
+			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>;
+			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+			resets = <&infracfg_ao MT8195_INFRA_RST0_THERM_CTRL_SWRST>;
+			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+		};
+
+		lvtsmcu: thermal-sensor@11278000 {
+			compatible = "mediatek,mt8195-lvts-mcu";
+			#thermal-sensor-cells = <1>;
+			reg = <0 0x11278000 0 0x400>;
+			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+			resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+		};
+
 		spi1: spi@11010000 {
 			compatible = "mediatek,mt8195-spi",
 				     "mediatek,mt6765-spi";
@@ -1613,4 +1638,92 @@ vencsys_core1: clock-controller@1b000000 {
 			#clock-cells = <1>;
 		};
 	};
+
+	thermal_zones: thermal-zones {
+		cpu-big1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 0>;
+		};
+		cpu-big2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 1>;
+		};
+		cpu-big3-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 2>;
+		};
+		cpu-big4-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 3>;
+		};
+		cpu-little1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 4>;
+		};
+		cpu-little2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 5>;
+		};
+		cpu-little3-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 6>;
+		};
+		cpu-little4-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 7>;
+		};
+		vpu1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 0>;
+		};
+		vpu2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 1>;
+		};
+		gpu1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 2>;
+		};
+		gpu2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 3>;
+		};
+		vdec-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 4>;
+		};
+		img-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 5>;
+		};
+		infra-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 6>;
+		};
+		cam1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 7>;
+		};
+		cam2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 8>;
+		};
+	};
 };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 60+ messages in thread

* [PATCH v8 6/6] arm64: dts: mt8195: Add thermal zone
@ 2022-07-26 13:55   ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-26 13:55 UTC (permalink / raw)
  To: rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

This adds the thermal zone for the mt8195.

Signed-off-by: Tinghan Shen <tinghan.shen@mediatek.com>
Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
---
 arch/arm64/boot/dts/mediatek/mt8195.dtsi | 115 ++++++++++++++++++++++-
 1 file changed, 114 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 4fbf24b5d202..78017224930c 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
 /*
- * Copyright (c) 2021 MediaTek Inc.
+ * Copyright (c) 2022 MediaTek Inc.
  * Author: Seiya Wang <seiya.wang@mediatek.com>
  */
 
@@ -11,6 +11,9 @@
 #include <dt-bindings/memory/mt8195-memory-port.h>
 #include <dt-bindings/phy/phy.h>
 #include <dt-bindings/pinctrl/mt8195-pinfunc.h>
+#include <dt-bindings/power/mt8195-power.h>
+#include <dt-bindings/reset/mt8195-resets.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "mediatek,mt8195";
@@ -810,6 +813,28 @@ spi0: spi@1100a000 {
 			status = "disabled";
 		};
 
+		lvtsap: thermal-sensor@1100b000 {
+			compatible = "mediatek,mt8195-lvts-ap";
+			#thermal-sensor-cells = <1>;
+			reg = <0 0x1100b000 0 0x400>;
+			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>;
+			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+			resets = <&infracfg_ao MT8195_INFRA_RST0_THERM_CTRL_SWRST>;
+			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+		};
+
+		lvtsmcu: thermal-sensor@11278000 {
+			compatible = "mediatek,mt8195-lvts-mcu";
+			#thermal-sensor-cells = <1>;
+			reg = <0 0x11278000 0 0x400>;
+			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
+			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
+			resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
+			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
+			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
+		};
+
 		spi1: spi@11010000 {
 			compatible = "mediatek,mt8195-spi",
 				     "mediatek,mt6765-spi";
@@ -1613,4 +1638,92 @@ vencsys_core1: clock-controller@1b000000 {
 			#clock-cells = <1>;
 		};
 	};
+
+	thermal_zones: thermal-zones {
+		cpu-big1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 0>;
+		};
+		cpu-big2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 1>;
+		};
+		cpu-big3-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 2>;
+		};
+		cpu-big4-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 3>;
+		};
+		cpu-little1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 4>;
+		};
+		cpu-little2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 5>;
+		};
+		cpu-little3-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 6>;
+		};
+		cpu-little4-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsmcu 7>;
+		};
+		vpu1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 0>;
+		};
+		vpu2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 1>;
+		};
+		gpu1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 2>;
+		};
+		gpu2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 3>;
+		};
+		vdec-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 4>;
+		};
+		img-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 5>;
+		};
+		infra-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 6>;
+		};
+		cam1-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 7>;
+		};
+		cam2-thermal {
+			polling-delay = <0>; /* milliseconds */
+			polling-delay-passive = <0>; /* milliseconds */
+			thermal-sensors = <&lvtsap 8>;
+		};
+	};
 };
-- 
2.34.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-26 20:09     ` Rob Herring
  -1 siblings, 0 replies; 60+ messages in thread
From: Rob Herring @ 2022-07-26 20:09 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
>  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
>  2 files changed, 148 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1404: dt_binding_check] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-26 20:09     ` Rob Herring
  0 siblings, 0 replies; 60+ messages in thread
From: Rob Herring @ 2022-07-26 20:09 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
>  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
>  2 files changed, 148 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
FATAL ERROR: Unable to parse input tree
make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1404: dt_binding_check] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-27  8:17     ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:17 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>   .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
>   .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
>   2 files changed, 148 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> 

Hello Balsam,

I don't think that having two separated files is necessary (and I don't know if
that's correct, even).

You're referring to variants of the same hardware (and using the same driver, but
that's not really relevant here), so my suggestion here is to have only one YAML,
named like "mediatek,lvts-thermal.yaml", where we list all of the compatibles for
both MT8192 and MT8195 (and future SoCs).

Regards,
Angelo

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-27  8:17     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:17 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>   .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
>   .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
>   2 files changed, 148 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> 

Hello Balsam,

I don't think that having two separated files is necessary (and I don't know if
that's correct, even).

You're referring to variants of the same hardware (and using the same driver, but
that's not really relevant here), so my suggestion here is to have only one YAML,
named like "mediatek,lvts-thermal.yaml", where we list all of the compatibles for
both MT8192 and MT8195 (and future SoCs).

Regards,
Angelo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-27  8:17     ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:17 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.
> 
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-27  8:17     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:17 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.
> 
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-27  8:24     ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:24 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.
> 
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>   drivers/thermal/Kconfig                       | 14 ++++-------
>   drivers/thermal/Makefile                      |  2 +-
>   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
>   drivers/thermal/mediatek/Makefile             |  1 +
>   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
>   5 files changed, 29 insertions(+), 11 deletions(-)
>   create mode 100644 drivers/thermal/mediatek/Kconfig
>   create mode 100644 drivers/thermal/mediatek/Makefile
>   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 0e5cc948373c..ecba8d6e313b 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -412,16 +412,10 @@ config DA9062_THERMAL
>   	  zone.
>   	  Compatible with the DA9062 and DA9061 PMICs.
>   
> -config MTK_THERMAL
> -	tristate "Temperature sensor driver for mediatek SoCs"
> -	depends on ARCH_MEDIATEK || COMPILE_TEST
> -	depends on HAS_IOMEM
> -	depends on NVMEM || NVMEM=n
> -	depends on RESET_CONTROLLER
> -	default y
> -	help
> -	  Enable this option if you want to have support for thermal management
> -	  controller present in Mediatek SoCs
> +menu "Mediatek thermal drivers"
> +depends on ARCH_MEDIATEK || COMPILE_TEST
> +source "drivers/thermal/mediatek/Kconfig"
> +endmenu
>   
>   config AMLOGIC_THERMAL
>   	tristate "Amlogic Thermal Support"
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index def8e1a0399c..3c00e864ad55 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,7 +55,7 @@ obj-y				+= st/
>   obj-$(CONFIG_QCOM_TSENS)	+= qcom/
>   obj-y				+= tegra/
>   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> -obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
> +obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
>   obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
>   obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
>   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> new file mode 100644
> index 000000000000..9c41e9079fc3
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -0,0 +1,23 @@
> +config MTK_THERMAL
> +	tristate "MediaTek thermal drivers"
> +	depends on THERMAL_OF
> +	help
> +		This is the option for MediaTek thermal software
> +		solutions. Please enable corresponding options to
> +		get temperature information from thermal sensors or
> +		turn on throttle mechaisms for thermal mitigation.

Sorry, I just noticed that the indentation must be fixed.

	help
	  This is the option .....

Thanks,
Angelo

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-27  8:24     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  8:24 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.
> 
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>   drivers/thermal/Kconfig                       | 14 ++++-------
>   drivers/thermal/Makefile                      |  2 +-
>   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
>   drivers/thermal/mediatek/Makefile             |  1 +
>   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
>   5 files changed, 29 insertions(+), 11 deletions(-)
>   create mode 100644 drivers/thermal/mediatek/Kconfig
>   create mode 100644 drivers/thermal/mediatek/Makefile
>   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 0e5cc948373c..ecba8d6e313b 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -412,16 +412,10 @@ config DA9062_THERMAL
>   	  zone.
>   	  Compatible with the DA9062 and DA9061 PMICs.
>   
> -config MTK_THERMAL
> -	tristate "Temperature sensor driver for mediatek SoCs"
> -	depends on ARCH_MEDIATEK || COMPILE_TEST
> -	depends on HAS_IOMEM
> -	depends on NVMEM || NVMEM=n
> -	depends on RESET_CONTROLLER
> -	default y
> -	help
> -	  Enable this option if you want to have support for thermal management
> -	  controller present in Mediatek SoCs
> +menu "Mediatek thermal drivers"
> +depends on ARCH_MEDIATEK || COMPILE_TEST
> +source "drivers/thermal/mediatek/Kconfig"
> +endmenu
>   
>   config AMLOGIC_THERMAL
>   	tristate "Amlogic Thermal Support"
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index def8e1a0399c..3c00e864ad55 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,7 +55,7 @@ obj-y				+= st/
>   obj-$(CONFIG_QCOM_TSENS)	+= qcom/
>   obj-y				+= tegra/
>   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> -obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
> +obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
>   obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
>   obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
>   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> new file mode 100644
> index 000000000000..9c41e9079fc3
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -0,0 +1,23 @@
> +config MTK_THERMAL
> +	tristate "MediaTek thermal drivers"
> +	depends on THERMAL_OF
> +	help
> +		This is the option for MediaTek thermal software
> +		solutions. Please enable corresponding options to
> +		get temperature information from thermal sensors or
> +		turn on throttle mechaisms for thermal mitigation.

Sorry, I just noticed that the indentation must be fixed.

	help
	  This is the option .....

Thanks,
Angelo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-26 20:09     ` Rob Herring
@ 2022-07-27  9:02       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:02 UTC (permalink / raw)
  To: Rob Herring
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >  2 files changed, 148 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> FATAL ERROR: Unable to parse input tree
> make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1404: dt_binding_check] Error 2
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/patch/
>
> This check can fail if there are any dependencies. The base for a patch
> series is generally the most recent rc1.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit.
>
Hello Rob,

Thank you for the feedback.
I'm updating my dt-bindings check tools, fixing, and I will resend ASPA.

Best regards,
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-27  9:02       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:02 UTC (permalink / raw)
  To: Rob Herring
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >  2 files changed, 148 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> FATAL ERROR: Unable to parse input tree
> make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1404: dt_binding_check] Error 2
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/patch/
>
> This check can fail if there are any dependencies. The base for a patch
> series is generally the most recent rc1.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit.
>
Hello Rob,

Thank you for the feedback.
I'm updating my dt-bindings check tools, fixing, and I will resend ASPA.

Best regards,
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-27  8:17     ` AngeloGioacchino Del Regno
@ 2022-07-27  9:02       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:02 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 10:17 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >   .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >   .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >   2 files changed, 148 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> Hello Balsam,
>
> I don't think that having two separated files is necessary (and I don't know if
> that's correct, even).
>
> You're referring to variants of the same hardware (and using the same driver, but
> that's not really relevant here), so my suggestion here is to have only one YAML,
> named like "mediatek,lvts-thermal.yaml", where we list all of the compatibles for
> both MT8192 and MT8195 (and future SoCs).
>
> Regards,
> Angelo
Hello AngeloGioacchino,

Thank you for the feedback.
Well received. I will resend ASAP.

Best regards,
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-27  9:02       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:02 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 10:17 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >   .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >   .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >   2 files changed, 148 insertions(+)
> >   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >   create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> Hello Balsam,
>
> I don't think that having two separated files is necessary (and I don't know if
> that's correct, even).
>
> You're referring to variants of the same hardware (and using the same driver, but
> that's not really relevant here), so my suggestion here is to have only one YAML,
> named like "mediatek,lvts-thermal.yaml", where we list all of the compatibles for
> both MT8192 and MT8195 (and future SoCs).
>
> Regards,
> Angelo
Hello AngeloGioacchino,

Thank you for the feedback.
Well received. I will resend ASAP.

Best regards,
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-27  8:24     ` AngeloGioacchino Del Regno
@ 2022-07-27  9:03       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:03 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 10:24 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > drivers. Relocate the original thermal controller driver to it and rename
> > as soc_temp.c to show its purpose more clearly.
> >
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >   drivers/thermal/Kconfig                       | 14 ++++-------
> >   drivers/thermal/Makefile                      |  2 +-
> >   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
> >   drivers/thermal/mediatek/Makefile             |  1 +
> >   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
> >   5 files changed, 29 insertions(+), 11 deletions(-)
> >   create mode 100644 drivers/thermal/mediatek/Kconfig
> >   create mode 100644 drivers/thermal/mediatek/Makefile
> >   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> >
> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> > index 0e5cc948373c..ecba8d6e313b 100644
> > --- a/drivers/thermal/Kconfig
> > +++ b/drivers/thermal/Kconfig
> > @@ -412,16 +412,10 @@ config DA9062_THERMAL
> >         zone.
> >         Compatible with the DA9062 and DA9061 PMICs.
> >
> > -config MTK_THERMAL
> > -     tristate "Temperature sensor driver for mediatek SoCs"
> > -     depends on ARCH_MEDIATEK || COMPILE_TEST
> > -     depends on HAS_IOMEM
> > -     depends on NVMEM || NVMEM=n
> > -     depends on RESET_CONTROLLER
> > -     default y
> > -     help
> > -       Enable this option if you want to have support for thermal management
> > -       controller present in Mediatek SoCs
> > +menu "Mediatek thermal drivers"
> > +depends on ARCH_MEDIATEK || COMPILE_TEST
> > +source "drivers/thermal/mediatek/Kconfig"
> > +endmenu
> >
> >   config AMLOGIC_THERMAL
> >       tristate "Amlogic Thermal Support"
> > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> > index def8e1a0399c..3c00e864ad55 100644
> > --- a/drivers/thermal/Makefile
> > +++ b/drivers/thermal/Makefile
> > @@ -55,7 +55,7 @@ obj-y                               += st/
> >   obj-$(CONFIG_QCOM_TSENS)    += qcom/
> >   obj-y                               += tegra/
> >   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> > -obj-$(CONFIG_MTK_THERMAL)    += mtk_thermal.o
> > +obj-$(CONFIG_MTK_THERMAL)    += mediatek/
> >   obj-$(CONFIG_GENERIC_ADC_THERMAL)   += thermal-generic-adc.o
> >   obj-$(CONFIG_UNIPHIER_THERMAL)      += uniphier_thermal.o
> >   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> > diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> > new file mode 100644
> > index 000000000000..9c41e9079fc3
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/Kconfig
> > @@ -0,0 +1,23 @@
> > +config MTK_THERMAL
> > +     tristate "MediaTek thermal drivers"
> > +     depends on THERMAL_OF
> > +     help
> > +             This is the option for MediaTek thermal software
> > +             solutions. Please enable corresponding options to
> > +             get temperature information from thermal sensors or
> > +             turn on throttle mechaisms for thermal mitigation.
>
> Sorry, I just noticed that the indentation must be fixed.
>
>         help
>           This is the option .....
>
> Thanks,
> Angelo
OK, It will be fixed ASAP.

Thanks,
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-27  9:03       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-27  9:03 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 10:24 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > drivers. Relocate the original thermal controller driver to it and rename
> > as soc_temp.c to show its purpose more clearly.
> >
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >   drivers/thermal/Kconfig                       | 14 ++++-------
> >   drivers/thermal/Makefile                      |  2 +-
> >   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
> >   drivers/thermal/mediatek/Makefile             |  1 +
> >   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
> >   5 files changed, 29 insertions(+), 11 deletions(-)
> >   create mode 100644 drivers/thermal/mediatek/Kconfig
> >   create mode 100644 drivers/thermal/mediatek/Makefile
> >   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> >
> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> > index 0e5cc948373c..ecba8d6e313b 100644
> > --- a/drivers/thermal/Kconfig
> > +++ b/drivers/thermal/Kconfig
> > @@ -412,16 +412,10 @@ config DA9062_THERMAL
> >         zone.
> >         Compatible with the DA9062 and DA9061 PMICs.
> >
> > -config MTK_THERMAL
> > -     tristate "Temperature sensor driver for mediatek SoCs"
> > -     depends on ARCH_MEDIATEK || COMPILE_TEST
> > -     depends on HAS_IOMEM
> > -     depends on NVMEM || NVMEM=n
> > -     depends on RESET_CONTROLLER
> > -     default y
> > -     help
> > -       Enable this option if you want to have support for thermal management
> > -       controller present in Mediatek SoCs
> > +menu "Mediatek thermal drivers"
> > +depends on ARCH_MEDIATEK || COMPILE_TEST
> > +source "drivers/thermal/mediatek/Kconfig"
> > +endmenu
> >
> >   config AMLOGIC_THERMAL
> >       tristate "Amlogic Thermal Support"
> > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> > index def8e1a0399c..3c00e864ad55 100644
> > --- a/drivers/thermal/Makefile
> > +++ b/drivers/thermal/Makefile
> > @@ -55,7 +55,7 @@ obj-y                               += st/
> >   obj-$(CONFIG_QCOM_TSENS)    += qcom/
> >   obj-y                               += tegra/
> >   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> > -obj-$(CONFIG_MTK_THERMAL)    += mtk_thermal.o
> > +obj-$(CONFIG_MTK_THERMAL)    += mediatek/
> >   obj-$(CONFIG_GENERIC_ADC_THERMAL)   += thermal-generic-adc.o
> >   obj-$(CONFIG_UNIPHIER_THERMAL)      += uniphier_thermal.o
> >   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> > diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> > new file mode 100644
> > index 000000000000..9c41e9079fc3
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/Kconfig
> > @@ -0,0 +1,23 @@
> > +config MTK_THERMAL
> > +     tristate "MediaTek thermal drivers"
> > +     depends on THERMAL_OF
> > +     help
> > +             This is the option for MediaTek thermal software
> > +             solutions. Please enable corresponding options to
> > +             get temperature information from thermal sensors or
> > +             turn on throttle mechaisms for thermal mitigation.
>
> Sorry, I just noticed that the indentation must be fixed.
>
>         help
>           This is the option .....
>
> Thanks,
> Angelo
OK, It will be fixed ASAP.

Thanks,
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-27  9:23     ` AngeloGioacchino Del Regno
  -1 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  9:23 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add a LVTS (Low voltage thermal sensor) driver to report junction
> temperatures in Mediatek SoC mt8192 and register the maximum temperature
> of sensors and each sensor as a thermal zone.
> 
> Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

Hello Balsam,

there are a few comments on this patch.

First of all, can you please fix the typo that you have in the commit title?
theraml -> thermal

...then, please, the commit description:
Add a LVTS (Low Voltage Thermal Sensor) <- capitalize

and

Mediatek -> MediaTek

> ---
>   drivers/thermal/mediatek/Kconfig         |  27 +
>   drivers/thermal/mediatek/Makefile        |   2 +
>   drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
>   drivers/thermal/mediatek/soc_temp.c      |   2 +-
>   drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
>   drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
>   6 files changed, 1564 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> 
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> index 9c41e9079fc3..7fc04237dd50 100644
> --- a/drivers/thermal/mediatek/Kconfig
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
>   		configures thermal controllers to collect temperature
>   		via AUXADC interface.
>   
> +config MTK_SOC_THERMAL_LVTS
> +	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via Analog Serial Interface(ASIF).

Fix the indentation, please:

	help
	  Enable this option.......
(\t<space><space>)



> +
> +endif
> +
> +if MTK_SOC_THERMAL_LVTS
> +
> +config LVTS_MT8192
> +	tristate "LVTS driver for MediaTek MT8192 SoC"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	depends on MTK_SOC_THERMAL_LVTS
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MT8192. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via ASIF.
> +
>   endif
> diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> index 4b4cb04a358f..5ff1197e80ab 100644
> --- a/drivers/thermal/mediatek/Makefile
> +++ b/drivers/thermal/mediatek/Makefile
> @@ -1 +1,3 @@
>   obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
> +obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
> +obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
> diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
> new file mode 100644
> index 000000000000..19e4e82c410b
> --- /dev/null
> +++ b/drivers/thermal/mediatek/lvts_mt8192.c
> @@ -0,0 +1,241 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + */
> +
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include "soc_temp_lvts.h"
> +
> +enum mt8192_lvts_mcu_sensor_enum {
> +	MT8192_TS1_0,
> +	MT8192_TS1_1,
> +	MT8192_TS2_0,
> +	MT8192_TS2_1,
> +	MT8192_TS3_0,
> +	MT8192_TS3_1,
> +	MT8192_TS3_2,
> +	MT8192_TS3_3,
> +	MT8192_NUM_TS_MCU
> +};
> +
> +enum mt8192_lvts_ap_sensor_enum {
> +	MT8192_TS4_0,
> +	MT8192_TS4_1,
> +	MT8192_TS5_0,
> +	MT8192_TS5_1,
> +	MT8192_TS6_0,
> +	MT8192_TS6_1,
> +	MT8192_TS7_0,
> +	MT8192_TS7_1,
> +	MT8192_TS7_2,
> +	MT8192_NUM_TS_AP
> +};
> +
> +static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
> +{
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int i, j;
> +	const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};


Please fix and reorder (here and for any other instance):

	const unsigned int mt8192_ts[] = { MT8192_TS2_0, MT8192_TS3_0 };
	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
	unsigned int i, j;

> +
> +	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
> +
> +	for (i = 0; i < MT8192_NUM_TS_MCU; i++)
> +		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
> +
> +	cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);

..snip..

> +
> +static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
> +	[0] = {
> +		.dev_id = 0x81,
> +		.addr_offset = 0x0,
> +		.num_sensor = 2,
> +		.sensor_map = {MT8192_TS1_0, MT8192_TS1_1},

Please, leave a space after opening and before closing the braces.

> +		.tc_speed = &tc_speed_mt8192,
> +		.hw_filter = LVTS_FILTER_2_OF_4,
> +		.dominator_sensing_point = SENSING_POINT1,
> +		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
> +		.irq_bit = BIT(3),
> +	},

..snip..

> +
> +static const struct lvts_data mt8192_lvts_ap_data = {
> +	.num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
> +	.tc = mt8192_tc_ap_settings,
> +	.num_sensor = MT8192_NUM_TS_AP,
> +	.ops = {
> +		.efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
> +		.device_enable_and_init = lvts_device_enable_and_init_v4,
> +		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
> +		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
> +		.set_cal_data = lvts_set_calibration_data_v4,
> +		.init_controller = lvts_init_controller_v4,
> +	},
> +	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
> +	.num_efuse_addr = NUM_EFUSE_ADDR,
> +	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
> +	.cal_data = {
> +		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
> +		.default_count_r = DEFAULT_CUONT_R,
> +		.default_count_rc = DEFAULT_CUONT_RC,
> +	},
> +	.coeff = {
> +		.a = COEFF_A,
> +		.b = COEFF_B,
> +	},
> +};
> +
> +static const struct of_device_id lvts_of_match[] = {

I don't like having one driver per SoC, where we have only two specific functions.

I suggest to either:
- Remove the static word from mt8192_lvts_ap_data and put the of_match
   in soc_temp_lvts.c; or
- Separate the SoCs by LVTS version: create a lvts_v4.c where we group all
   of the V4 SoCs (so, currently, MT8192 and MT8195): this will allow us to
   eventually get a lvts_v3, lvts_v2, etc, where we group other SoCs.

I prefer the second way, as MediaTek has a lot of SoCs and I can see this list
growing a lot when these will be (hopefully) upstreamed.



> +	{ .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
> +	{ .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, lvts_of_match);
> +
> +static struct platform_driver soc_temp_lvts = {
> +	.probe = lvts_probe,
> +	.remove = lvts_remove,
> +	.suspend = lvts_suspend,
> +	.resume = lvts_resume,
> +	.driver = {
> +		.name = "mtk-soc-temp-lvts-mt8192",
> +		.of_match_table = lvts_of_match,
> +	},
> +};
> +module_platform_driver(soc_temp_lvts);
> +
> +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> +MODULE_LICENSE("GPL v2");

You should run checkpatch.pl. Please.

> diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
> index ede94eadddda..60924f8f98e9 100644
> --- a/drivers/thermal/mediatek/soc_temp.c
> +++ b/drivers/thermal/mediatek/soc_temp.c
> @@ -23,7 +23,7 @@
>   #include <linux/reset.h>
>   #include <linux/types.h>
>   
> -#include "thermal_hwmon.h"
> +#include "../thermal_hwmon.h"

This change doesn't belong to this commit.

>   
>   /* AUXADC Registers */
>   #define AUXADC_CON1_SET_V	0x008
> diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
> new file mode 100644
> index 000000000000..ee7efc0de65f
> --- /dev/null
> +++ b/drivers/thermal/mediatek/soc_temp_lvts.c
> @@ -0,0 +1,928 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/thermal.h>
> +#include "soc_temp_lvts.h"
> +
> +static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
> +{
> +	/* This function returns degree mC */
> +
> +	int temp;
> +
> +	temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
> +	temp = temp + co->golden_temp * 500 + co->b;
> +
> +	return temp;
> +}
> +
> +static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
> +{
> +	unsigned int msr_raw;
> +
> +	msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
> +		(-1 * co->a));
> +
> +	return msr_raw;
> +}
> +
> +static int soc_temp_lvts_read_temp(void *data, int *temperature)
> +{
> +	struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
> +	struct lvts_data *lvts_data = lvts_tz->lvts_data;
> +	unsigned int msr_raw;
> +
> +	msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
> +	if (msr_raw == 0)
> +		return -EINVAL;
> +
> +	*temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
> +
> +	return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
> +	.get_temp = soc_temp_lvts_read_temp,
> +};
> +
> +static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
> +	int tc_id)
> +{
> +	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
> +
> +	usleep_range(5, 15);
> +}
> +
> +static unsigned int lvts_read_device(struct lvts_data *lvts_data,
> +	unsigned int reg_idx, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> +	unsigned int data;
> +	int ret;
> +
> +	writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
> +
> +	usleep_range(5, 15);
> +
> +	ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> +		!(data & DEVICE_ACCESS_STARTUS), 2, 200);
> +	if (ret)
> +		dev_err(dev,
> +			"Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
> +
> +	data = readl(LVTSRDATA0_0 + base);
> +
> +	return data;
> +}
> +
> +static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
> +	"Waiting for read after Write", "Disable Continue fetching on Device",
> +	"Read transaction", "Set Device special Register for Voltage threshold",
> +	"Set TSMCU number for Fetch"};

In my opinion, that's unreadable.

static const char * const lvts_error_table[] = {

	"Idle",

	"Write transaction",

	"Waiting for read after write",

	"Disable continue fetching on device",

	"Read transaction",

	"Set device special register for voltage threshold",

	"Set TSMCU number for fetch"

};

...but like this, it's way more readable.


> +
> +static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int mask, error_code, is_error;
> +	void __iomem *base;
> +	int i, cnt, ret;
> +
> +	mask = BIT(10) | BIT(7) | BIT(0);

What are these magic bits?
Please add definitions.

> +
> +	for (cnt = 0; cnt < 2; cnt++) {
> +		is_error = 0;
> +		for (i = 0; i < lvts_data->num_tc; i++) {
> +			base = GET_BASE_ADDR(lvts_data, i);
> +			ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
> +						 !(error_code & mask), 2, 200);
> +
> +			error_code = ((error_code & BIT(10)) >> 8) +
> +				((error_code & BIT(7)) >> 6) +
> +				(error_code & BIT(0));
> +
> +			if (ret)
> +				dev_err(dev, "LVTS %d error: %s\n",
> +					i, lvts_error_table[error_code]);
> +
> +			if (error_code != 0)
> +				is_error = 1;
> +		}
> +
> +		if (is_error == 0)
> +			break;
> +	}
> +}
> +

...snip...

> +static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int option;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +	option = tc[tc_id].hw_filter & 0x7;
> +	/*
> +	 * hw filter
> +	 * 000: Get one sample
> +	 * 001: Get 2 samples and average them
> +	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
> +	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
> +	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
> +	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
> +	 */
> +	option = (option << 9) | (option << 6) | (option << 3) | option;
> +
> +	writel(option, LVTSMSRCTL0_0 + base);
> +	dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
> +		 tc_id, readl(LVTSMSRCTL0_0 + base));
> +}
> +
> +static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	int d_index;
> +
> +	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
> +		d_index = ALL_SENSING_POINTS;
> +	} else if (tc[tc_id].dominator_sensing_point <
> +		tc[tc_id].num_sensor){

There's no reason to break this line.

> +		d_index = tc[tc_id].dominator_sensing_point;
> +	} else {
> +		dev_err(dev,
> +			"Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",

"Error:" is unneeded, as this is a dev_err, so it's definitely an error.
Also, s/should/shall be/g

> +			tc_id, tc[tc_id].dominator_sensing_point,
> +			tc[tc_id].num_sensor);
> +
> +		dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
> +		d_index = SENSING_POINT0;
> +	}
> +
> +	return d_index;
> +}
> +
> +static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> +{
> +	unsigned int temp;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	/*
> +	 * LVTS thermal controller has two interrupts for thermal HW reboot
> +	 * One is for AP SW and the other is for RGU
> +	 * The interrupt of AP SW can turn off by a bit of a register, but
> +	 * the other for RGU cannot.
> +	 * To prevent rebooting device accidentally, we are going to add
> +	 * a huge offset to LVTS and make LVTS always report extremely low
> +	 * temperature.
> +	 */
> +
> +	/*
> +	 * After adding the huge offset 0x3FFF, LVTS alawys adds the

s/alawys/always/g

> +	 * offset to MSR_RAW.
> +	 * When MSR_RAW is larger, SW will convert lower temperature/
> +	 */
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
> +
> +	/* Disable the interrupt of AP SW */
> +	temp = readl(LVTSMONINT_0 + base);
> +	writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
> +}
> +
> +static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> +{
> +	unsigned int temp;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	/* Enable the interrupt of AP SW */
> +	temp = readl(LVTSMONINT_0 + base);
> +	writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
> +	/* Clear the offset */
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
> +}
> +
> +static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
> +	int trip_point, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int msr_raw, temp, config, d_index;
> +	void __iomem *base;

	void __iomem *base;
	struct device *dev = lvts_data->dev;
	unsigned int msr_raw, temp, config, d_index;

or

	unsigned int msr_raw, temp, config, d_index;
	struct device *dev = lvts_data->dev;
	void __iomem *base;

Make it pretty - human readabilty is important.
P.S.: I prefer the first option.
P.P.S.: This is not the only instance!

> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +	d_index = get_dominator_index(lvts_data, tc_id);
> +
> +	dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);

dev_dbg().

> +
> +	disable_hw_reboot_interrupt(lvts_data, tc_id);
> +
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	if (d_index == ALL_SENSING_POINTS) {
> +		/* Maximum of 4 sensing points */
> +		config = (0x1 << 16);
> +		writel(config | temp, LVTSPROTCTL_0 + base);
> +	} else {
> +		/* Select protection sensor */
> +		config = ((d_index << 2) + 0x2) << 16;
> +		writel(config | temp, LVTSPROTCTL_0 + base);
> +	}
> +
> +	msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
> +	writel(msr_raw, LVTSPROTTC_0 + base);
> +
> +	enable_hw_reboot_interrupt(lvts_data, tc_id);
> +}
> +
> +static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	int i, trip_point;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		trip_point = tc[i].hw_reboot_trip_point;
> +
> +		if (tc[i].num_sensor == 0)
> +			continue;
> +
> +		if (trip_point == THERMAL_TEMP_INVALID)
> +			continue;
> +
> +		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
> +	}
> +}
> +
> +static int lvts_init(struct lvts_data *lvts_data)
> +{
> +	struct platform_ops *ops = &lvts_data->ops;
> +	struct device *dev = lvts_data->dev;
> +	int ret;
> +
> +	ret = clk_prepare_enable(lvts_data->clk);
> +	if (ret) {
> +		dev_err(dev,
> +			"Error: Failed to enable lvts controller clock: %d\n",
> +			ret);

This should be:
		dev_err(dev, "Failed to enable lvts controller clock: %d\n", ret);

(or return dev_err_probe()).

> +		return ret;
> +	}
> +
> +	lvts_reset(lvts_data);
> +
> +	device_identification(lvts_data);
> +	if (ops->device_enable_and_init)
> +		ops->device_enable_and_init(lvts_data);
> +
> +	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
> +		if (ops->device_enable_auto_rck)
> +			ops->device_enable_auto_rck(lvts_data);
> +	} else {
> +		if (ops->device_read_count_rc_n)
> +			ops->device_read_count_rc_n(lvts_data);
> +	}

	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK) && ops....)
		ops....
	else if (ops.....)
		ops.....

> +
> +	if (ops->set_cal_data)
> +		ops->set_cal_data(lvts_data);
> +
> +	disable_all_sensing_points(lvts_data);
> +	wait_all_tc_sensing_point_idle(lvts_data);
> +	if (ops->init_controller)
> +		ops->init_controller(lvts_data);
> +	enable_all_sensing_points(lvts_data);
> +
> +	set_all_tc_hw_reboot(lvts_data);
> +
> +	return 0;
> +}
> +
> +static int prepare_calibration_data(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	struct platform_ops *ops = &lvts_data->ops;
> +	int i, offset;
> +	char buffer[512];
> +
> +	cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_r), GFP_KERNEL);
> +	if (!cal_data->count_r)
> +		return -ENOMEM;
> +
> +	cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_rc), GFP_KERNEL);
> +	if (!cal_data->count_rc)
> +		return -ENOMEM;
> +
> +	if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
> +		ops->efuse_to_cal_data(lvts_data);
> +	if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
> +		cal_data->use_fake_efuse = 1;
> +
> +	if (cal_data->use_fake_efuse) {
> +		/* It means all efuse data are equal to 0 */
> +		dev_err(dev,
> +			"%s: This sample is not calibrated, fake !!\n", __func__);
> +
> +		cal_data->golden_temp = cal_data->default_golden_temp;
> +		for (i = 0; i < lvts_data->num_sensor; i++) {
> +			cal_data->count_r[i] = cal_data->default_count_r;
> +			cal_data->count_rc[i] = cal_data->default_count_rc;
> +		}
> +	}
> +
> +	lvts_data->coeff.golden_temp = cal_data->golden_temp;
> +
> +	dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
> +
> +	offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
> +	for (i = 0; i < lvts_data->num_sensor; i++)
> +		offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
> +			i, cal_data->count_r[i], cal_data->count_rc[i]);
> +
> +	buffer[offset] = '\0';

What is this string for?
You're formatting it but never using, what's the point?

> +
> +	return 0;
> +}
> +
> +static int get_calibration_data(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	char cell_name[32];
> +	struct nvmem_cell *cell;
> +	u32 *buf;
> +	size_t len;
> +	int i, j, index = 0, ret;
> +
> +	lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
> +					sizeof(*lvts_data->efuse), GFP_KERNEL);
> +	if (!lvts_data->efuse)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_efuse_block; i++) {
> +		snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
> +		cell = nvmem_cell_get(dev, cell_name);
> +		if (IS_ERR(cell)) {
> +			dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
> +			return PTR_ERR(cell);
> +		}
> +
> +		buf = (u32 *)nvmem_cell_read(cell, &len);
> +		nvmem_cell_put(cell);
> +
> +		if (IS_ERR(buf))
> +			return PTR_ERR(buf);
> +
> +		for (j = 0; j < (len / sizeof(u32)); j++) {
> +			if (index >= lvts_data->num_efuse_addr) {
> +				dev_err(dev, "Array efuse is going to overflow");
> +				kfree(buf);
> +				return -EINVAL;

If we get an error here, you should free all of the allocated buffers, which means
that you have to walk back from i to 0 and kfree everything, or this is going to be
a (relatively) big memory leak.

> +			}
> +
> +			lvts_data->efuse[index] = buf[j];
> +			index++;
> +		}
> +
> +		kfree(buf);
> +	}
> +
> +	ret = prepare_calibration_data(lvts_data);
> +
> +	return ret;
> +}
> +
> +static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int i, j, s_index;
> +	void __iomem *base;
> +
> +	lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*lvts_data->reg), GFP_KERNEL);
> +	if (!lvts_data->reg)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +			lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int of_update_lvts_data(struct lvts_data *lvts_data,
> +	struct platform_device *pdev)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct resource *res;
> +	int ret;
> +
> +	lvts_data->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(lvts_data->clk))
> +		return PTR_ERR(lvts_data->clk);
> +
> +	/* Get base address */
> +	res = platform_get_mem_or_io(pdev, 0);
> +	if (!res) {
> +		dev_err(dev, "No IO resource\n");
> +		return -ENXIO;
> +	}
> +
> +	lvts_data->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(lvts_data->base)) {
> +		dev_err(dev, "Failed to remap io\n");
> +		return PTR_ERR(lvts_data->base);
> +	}
> +
> +	/* Get interrupt number */
> +	ret = platform_get_irq(pdev, 0);
> +	if (ret < 0) {
> +		dev_err(dev, "No irq resource\n");
> +		return -EINVAL;

Why are you overriding the return value? return ret here.

> +	}
> +	lvts_data->irq_num = ret;
> +
> +	/* Get reset control */
> +	lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
> +	if (IS_ERR(lvts_data->reset)) {
> +		dev_err(dev, "Failed to get reset control\n");
> +		return PTR_ERR(lvts_data->reset);
> +	}
> +
> +	ret = lvts_init_tc_regs(dev, lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	ret = get_calibration_data(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +

..snip..

> +
> +static irqreturn_t irq_handler(int irq, void *dev_id)
> +{
> +	struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int i, *irq_bitmap;
> +	void __iomem *base;
> +
> +	irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
> +

You're using this for debugging only? Also, why wasn't this stack-allocated?

Just remove it.

> +	if (!irq_bitmap)
> +		return IRQ_NONE;
> +
> +	base = lvts_data->base;
> +	*irq_bitmap = readl(THERMINTST + base);
> +	dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		if (tc[i].irq_bit == 0)
> +			tc_irq_handler(lvts_data, i);
> +	}
> +
> +	kfree(irq_bitmap);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int lvts_register_irq_handler(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	int ret;
> +
> +	ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
> +		IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);

Interrupt flags are specified in devicetree: why are you forcing TRIGGER_HIGH here?

> +
> +	if (ret) {
> +		dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
> +			ret, lvts_data->irq_num);
> +		lvts_close(lvts_data);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct thermal_zone_device *tzdev;
> +	struct soc_temp_tz *lvts_tz;
> +	int i, ret;
> +
> +	for (i = 0; i < lvts_data->num_sensor; i++) {
> +		lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
> +		if (!lvts_tz) {
> +			lvts_close(lvts_data);
> +			return -ENOMEM;
> +		}
> +
> +		lvts_tz->id = i;
> +		lvts_tz->lvts_data = lvts_data;
> +
> +		tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
> +			lvts_tz, &soc_temp_lvts_ops);
> +
> +		if (IS_ERR(tzdev)) {
> +			if (lvts_tz->id != 0)
> +				return 0;
> +
> +			ret = PTR_ERR(tzdev);
> +			dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",

s/Error: //g - here and everywhere else: a dev_err() *is* an error print.

> +				lvts_tz->id, ret);
> +			lvts_close(lvts_data);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +

..snip..

> +
> +int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
> +{
> +	/* Resistor-Capacitor Calibration */
> +	/* count_RC_N: count RC now */
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int offset, size, s_index, data;
> +	void __iomem *base;
> +	int ret, i, j;
> +	char buffer[512];

I don't think that you need this buffer to be that long and I'm sure that its
size can be reduced.
I didn't check how much you need, but I'm guessing that you need less than a
quarter of that size.

> +
> +	cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_rc_now), GFP_KERNEL);
> +	if (!cal_data->count_rc_now)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +
> +			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
> +			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
> +			usleep_range(10, 20);
> +
> +			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
> +			usleep_range(30, 40);
> +
> +			ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> +						 !(data & DEVICE_SENSING_STATUS), 2, 200);
> +			if (ret)
> +				dev_err(dev,
> +					"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
> +
> +			data = lvts_read_device(lvts_data, 0x00, i);
> +
> +			cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));

No magic GENMASK() or BIT() please, add a definition for readability.

> +		}
> +
> +		/* Recover Setting for Normal Access on
> +		 * temperature fetch
> +		 */
> +		lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
> +		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> +	}
> +
> +	size = sizeof(buffer);
> +	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
> +	for (i = 0; i < lvts_data->num_sensor; i++)
> +		offset += snprintf(buffer + offset, size - offset, "%d:%d ",
> +			i, cal_data->count_rc_now[i]);
> +
> +	buffer[offset] = '\0';
> +	dev_dbg(dev, "%s\n", buffer);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
> +
> +void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int i, j, s_index, lvts_calib_data;
> +	void __iomem *base;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +			if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
> +				lvts_calib_data = cal_data->count_r[s_index];
> +			else
> +				lvts_calib_data = (((unsigned long long)

lvts_calib_data is unsigned int. You're assigning unsigned long long here.

Also, since this is register-size bound, use fixed size types.

> +					cal_data->count_rc_now[s_index]) *
> +					cal_data->count_r[s_index]) >> 14;
> +
> +			writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
> +
> +void lvts_init_controller_v4(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int i;
> +	void __iomem *base;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +
> +		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> +
> +		writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
> +		writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
> +
> +		set_polling_speed(lvts_data, i);
> +		set_hw_filter(lvts_data, i);
> +
> +		dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
> +			i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));

dev_dbg().

> +	}
> +}
> +EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
> +
> +int lvts_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct lvts_data *lvts_data;
> +	int ret;
> +
> +	lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
> +
> +	if (!lvts_data)	{
> +		dev_err(dev, "Error: Failed to get lvts platform data\n");
> +		return -ENODATA;
> +	}
> +
> +	lvts_data->dev = &pdev->dev;
> +
> +	ret = of_update_lvts_data(lvts_data, pdev);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, lvts_data);
> +
> +	ret = lvts_init(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	ret = lvts_register_irq_handler(lvts_data);
> +	if (ret)
> +		return ret;

If anything goes wrong here, you're leaving the lvts_data->clk clock enabled.
Please fix.

> +
> +	ret = lvts_register_thermal_zones(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +int lvts_remove(struct platform_device *pdev)
> +{
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	lvts_close(lvts_data);
> +
> +	return 0;
> +}
> +
> +int lvts_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	lvts_close(lvts_data);
> +
> +	return 0;
> +}
> +
> +int lvts_resume(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	ret = lvts_init(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> +MODULE_LICENSE("GPL v2");

Regards,
Angelo

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
@ 2022-07-27  9:23     ` AngeloGioacchino Del Regno
  0 siblings, 0 replies; 60+ messages in thread
From: AngeloGioacchino Del Regno @ 2022-07-27  9:23 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, daniel.lezcano, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon

Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> Add a LVTS (Low voltage thermal sensor) driver to report junction
> temperatures in Mediatek SoC mt8192 and register the maximum temperature
> of sensors and each sensor as a thermal zone.
> 
> Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

Hello Balsam,

there are a few comments on this patch.

First of all, can you please fix the typo that you have in the commit title?
theraml -> thermal

...then, please, the commit description:
Add a LVTS (Low Voltage Thermal Sensor) <- capitalize

and

Mediatek -> MediaTek

> ---
>   drivers/thermal/mediatek/Kconfig         |  27 +
>   drivers/thermal/mediatek/Makefile        |   2 +
>   drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
>   drivers/thermal/mediatek/soc_temp.c      |   2 +-
>   drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
>   drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
>   6 files changed, 1564 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> 
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> index 9c41e9079fc3..7fc04237dd50 100644
> --- a/drivers/thermal/mediatek/Kconfig
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
>   		configures thermal controllers to collect temperature
>   		via AUXADC interface.
>   
> +config MTK_SOC_THERMAL_LVTS
> +	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via Analog Serial Interface(ASIF).

Fix the indentation, please:

	help
	  Enable this option.......
(\t<space><space>)



> +
> +endif
> +
> +if MTK_SOC_THERMAL_LVTS
> +
> +config LVTS_MT8192
> +	tristate "LVTS driver for MediaTek MT8192 SoC"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	depends on MTK_SOC_THERMAL_LVTS
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MT8192. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via ASIF.
> +
>   endif
> diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> index 4b4cb04a358f..5ff1197e80ab 100644
> --- a/drivers/thermal/mediatek/Makefile
> +++ b/drivers/thermal/mediatek/Makefile
> @@ -1 +1,3 @@
>   obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
> +obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)	+= soc_temp_lvts.o
> +obj-$(CONFIG_LVTS_MT8192)			+= lvts_mt8192.o
> diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
> new file mode 100644
> index 000000000000..19e4e82c410b
> --- /dev/null
> +++ b/drivers/thermal/mediatek/lvts_mt8192.c
> @@ -0,0 +1,241 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + */
> +
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include "soc_temp_lvts.h"
> +
> +enum mt8192_lvts_mcu_sensor_enum {
> +	MT8192_TS1_0,
> +	MT8192_TS1_1,
> +	MT8192_TS2_0,
> +	MT8192_TS2_1,
> +	MT8192_TS3_0,
> +	MT8192_TS3_1,
> +	MT8192_TS3_2,
> +	MT8192_TS3_3,
> +	MT8192_NUM_TS_MCU
> +};
> +
> +enum mt8192_lvts_ap_sensor_enum {
> +	MT8192_TS4_0,
> +	MT8192_TS4_1,
> +	MT8192_TS5_0,
> +	MT8192_TS5_1,
> +	MT8192_TS6_0,
> +	MT8192_TS6_1,
> +	MT8192_TS7_0,
> +	MT8192_TS7_1,
> +	MT8192_TS7_2,
> +	MT8192_NUM_TS_AP
> +};
> +
> +static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
> +{
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int i, j;
> +	const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};


Please fix and reorder (here and for any other instance):

	const unsigned int mt8192_ts[] = { MT8192_TS2_0, MT8192_TS3_0 };
	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
	unsigned int i, j;

> +
> +	cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
> +
> +	for (i = 0; i < MT8192_NUM_TS_MCU; i++)
> +		cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
> +
> +	cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);

..snip..

> +
> +static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
> +	[0] = {
> +		.dev_id = 0x81,
> +		.addr_offset = 0x0,
> +		.num_sensor = 2,
> +		.sensor_map = {MT8192_TS1_0, MT8192_TS1_1},

Please, leave a space after opening and before closing the braces.

> +		.tc_speed = &tc_speed_mt8192,
> +		.hw_filter = LVTS_FILTER_2_OF_4,
> +		.dominator_sensing_point = SENSING_POINT1,
> +		.hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
> +		.irq_bit = BIT(3),
> +	},

..snip..

> +
> +static const struct lvts_data mt8192_lvts_ap_data = {
> +	.num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
> +	.tc = mt8192_tc_ap_settings,
> +	.num_sensor = MT8192_NUM_TS_AP,
> +	.ops = {
> +		.efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
> +		.device_enable_and_init = lvts_device_enable_and_init_v4,
> +		.device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
> +		.device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
> +		.set_cal_data = lvts_set_calibration_data_v4,
> +		.init_controller = lvts_init_controller_v4,
> +	},
> +	.feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
> +	.num_efuse_addr = NUM_EFUSE_ADDR,
> +	.num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
> +	.cal_data = {
> +		.default_golden_temp = DEFAULT_GOLDEN_TEMP,
> +		.default_count_r = DEFAULT_CUONT_R,
> +		.default_count_rc = DEFAULT_CUONT_RC,
> +	},
> +	.coeff = {
> +		.a = COEFF_A,
> +		.b = COEFF_B,
> +	},
> +};
> +
> +static const struct of_device_id lvts_of_match[] = {

I don't like having one driver per SoC, where we have only two specific functions.

I suggest to either:
- Remove the static word from mt8192_lvts_ap_data and put the of_match
   in soc_temp_lvts.c; or
- Separate the SoCs by LVTS version: create a lvts_v4.c where we group all
   of the V4 SoCs (so, currently, MT8192 and MT8195): this will allow us to
   eventually get a lvts_v3, lvts_v2, etc, where we group other SoCs.

I prefer the second way, as MediaTek has a lot of SoCs and I can see this list
growing a lot when these will be (hopefully) upstreamed.



> +	{ .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
> +	{ .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, lvts_of_match);
> +
> +static struct platform_driver soc_temp_lvts = {
> +	.probe = lvts_probe,
> +	.remove = lvts_remove,
> +	.suspend = lvts_suspend,
> +	.resume = lvts_resume,
> +	.driver = {
> +		.name = "mtk-soc-temp-lvts-mt8192",
> +		.of_match_table = lvts_of_match,
> +	},
> +};
> +module_platform_driver(soc_temp_lvts);
> +
> +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> +MODULE_LICENSE("GPL v2");

You should run checkpatch.pl. Please.

> diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
> index ede94eadddda..60924f8f98e9 100644
> --- a/drivers/thermal/mediatek/soc_temp.c
> +++ b/drivers/thermal/mediatek/soc_temp.c
> @@ -23,7 +23,7 @@
>   #include <linux/reset.h>
>   #include <linux/types.h>
>   
> -#include "thermal_hwmon.h"
> +#include "../thermal_hwmon.h"

This change doesn't belong to this commit.

>   
>   /* AUXADC Registers */
>   #define AUXADC_CON1_SET_V	0x008
> diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
> new file mode 100644
> index 000000000000..ee7efc0de65f
> --- /dev/null
> +++ b/drivers/thermal/mediatek/soc_temp_lvts.c
> @@ -0,0 +1,928 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2022 MediaTek Inc.
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +#include <linux/string.h>
> +#include <linux/thermal.h>
> +#include "soc_temp_lvts.h"
> +
> +static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
> +{
> +	/* This function returns degree mC */
> +
> +	int temp;
> +
> +	temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
> +	temp = temp + co->golden_temp * 500 + co->b;
> +
> +	return temp;
> +}
> +
> +static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
> +{
> +	unsigned int msr_raw;
> +
> +	msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
> +		(-1 * co->a));
> +
> +	return msr_raw;
> +}
> +
> +static int soc_temp_lvts_read_temp(void *data, int *temperature)
> +{
> +	struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
> +	struct lvts_data *lvts_data = lvts_tz->lvts_data;
> +	unsigned int msr_raw;
> +
> +	msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
> +	if (msr_raw == 0)
> +		return -EINVAL;
> +
> +	*temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
> +
> +	return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
> +	.get_temp = soc_temp_lvts_read_temp,
> +};
> +
> +static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
> +	int tc_id)
> +{
> +	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
> +
> +	usleep_range(5, 15);
> +}
> +
> +static unsigned int lvts_read_device(struct lvts_data *lvts_data,
> +	unsigned int reg_idx, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> +	unsigned int data;
> +	int ret;
> +
> +	writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
> +
> +	usleep_range(5, 15);
> +
> +	ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> +		!(data & DEVICE_ACCESS_STARTUS), 2, 200);
> +	if (ret)
> +		dev_err(dev,
> +			"Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
> +
> +	data = readl(LVTSRDATA0_0 + base);
> +
> +	return data;
> +}
> +
> +static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
> +	"Waiting for read after Write", "Disable Continue fetching on Device",
> +	"Read transaction", "Set Device special Register for Voltage threshold",
> +	"Set TSMCU number for Fetch"};

In my opinion, that's unreadable.

static const char * const lvts_error_table[] = {

	"Idle",

	"Write transaction",

	"Waiting for read after write",

	"Disable continue fetching on device",

	"Read transaction",

	"Set device special register for voltage threshold",

	"Set TSMCU number for fetch"

};

...but like this, it's way more readable.


> +
> +static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int mask, error_code, is_error;
> +	void __iomem *base;
> +	int i, cnt, ret;
> +
> +	mask = BIT(10) | BIT(7) | BIT(0);

What are these magic bits?
Please add definitions.

> +
> +	for (cnt = 0; cnt < 2; cnt++) {
> +		is_error = 0;
> +		for (i = 0; i < lvts_data->num_tc; i++) {
> +			base = GET_BASE_ADDR(lvts_data, i);
> +			ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
> +						 !(error_code & mask), 2, 200);
> +
> +			error_code = ((error_code & BIT(10)) >> 8) +
> +				((error_code & BIT(7)) >> 6) +
> +				(error_code & BIT(0));
> +
> +			if (ret)
> +				dev_err(dev, "LVTS %d error: %s\n",
> +					i, lvts_error_table[error_code]);
> +
> +			if (error_code != 0)
> +				is_error = 1;
> +		}
> +
> +		if (is_error == 0)
> +			break;
> +	}
> +}
> +

...snip...

> +static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int option;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +	option = tc[tc_id].hw_filter & 0x7;
> +	/*
> +	 * hw filter
> +	 * 000: Get one sample
> +	 * 001: Get 2 samples and average them
> +	 * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
> +	 * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
> +	 * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
> +	 * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
> +	 */
> +	option = (option << 9) | (option << 6) | (option << 3) | option;
> +
> +	writel(option, LVTSMSRCTL0_0 + base);
> +	dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
> +		 tc_id, readl(LVTSMSRCTL0_0 + base));
> +}
> +
> +static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	int d_index;
> +
> +	if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
> +		d_index = ALL_SENSING_POINTS;
> +	} else if (tc[tc_id].dominator_sensing_point <
> +		tc[tc_id].num_sensor){

There's no reason to break this line.

> +		d_index = tc[tc_id].dominator_sensing_point;
> +	} else {
> +		dev_err(dev,
> +			"Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",

"Error:" is unneeded, as this is a dev_err, so it's definitely an error.
Also, s/should/shall be/g

> +			tc_id, tc[tc_id].dominator_sensing_point,
> +			tc[tc_id].num_sensor);
> +
> +		dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
> +		d_index = SENSING_POINT0;
> +	}
> +
> +	return d_index;
> +}
> +
> +static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> +{
> +	unsigned int temp;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	/*
> +	 * LVTS thermal controller has two interrupts for thermal HW reboot
> +	 * One is for AP SW and the other is for RGU
> +	 * The interrupt of AP SW can turn off by a bit of a register, but
> +	 * the other for RGU cannot.
> +	 * To prevent rebooting device accidentally, we are going to add
> +	 * a huge offset to LVTS and make LVTS always report extremely low
> +	 * temperature.
> +	 */
> +
> +	/*
> +	 * After adding the huge offset 0x3FFF, LVTS alawys adds the

s/alawys/always/g

> +	 * offset to MSR_RAW.
> +	 * When MSR_RAW is larger, SW will convert lower temperature/
> +	 */
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
> +
> +	/* Disable the interrupt of AP SW */
> +	temp = readl(LVTSMONINT_0 + base);
> +	writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
> +}
> +
> +static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> +{
> +	unsigned int temp;
> +	void __iomem *base;
> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +
> +	/* Enable the interrupt of AP SW */
> +	temp = readl(LVTSMONINT_0 + base);
> +	writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
> +	/* Clear the offset */
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
> +}
> +
> +static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
> +	int trip_point, int tc_id)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int msr_raw, temp, config, d_index;
> +	void __iomem *base;

	void __iomem *base;
	struct device *dev = lvts_data->dev;
	unsigned int msr_raw, temp, config, d_index;

or

	unsigned int msr_raw, temp, config, d_index;
	struct device *dev = lvts_data->dev;
	void __iomem *base;

Make it pretty - human readabilty is important.
P.S.: I prefer the first option.
P.P.S.: This is not the only instance!

> +
> +	base = GET_BASE_ADDR(lvts_data, tc_id);
> +	d_index = get_dominator_index(lvts_data, tc_id);
> +
> +	dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);

dev_dbg().

> +
> +	disable_hw_reboot_interrupt(lvts_data, tc_id);
> +
> +	temp = readl(LVTSPROTCTL_0 + base);
> +	if (d_index == ALL_SENSING_POINTS) {
> +		/* Maximum of 4 sensing points */
> +		config = (0x1 << 16);
> +		writel(config | temp, LVTSPROTCTL_0 + base);
> +	} else {
> +		/* Select protection sensor */
> +		config = ((d_index << 2) + 0x2) << 16;
> +		writel(config | temp, LVTSPROTCTL_0 + base);
> +	}
> +
> +	msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
> +	writel(msr_raw, LVTSPROTTC_0 + base);
> +
> +	enable_hw_reboot_interrupt(lvts_data, tc_id);
> +}
> +
> +static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	int i, trip_point;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		trip_point = tc[i].hw_reboot_trip_point;
> +
> +		if (tc[i].num_sensor == 0)
> +			continue;
> +
> +		if (trip_point == THERMAL_TEMP_INVALID)
> +			continue;
> +
> +		set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
> +	}
> +}
> +
> +static int lvts_init(struct lvts_data *lvts_data)
> +{
> +	struct platform_ops *ops = &lvts_data->ops;
> +	struct device *dev = lvts_data->dev;
> +	int ret;
> +
> +	ret = clk_prepare_enable(lvts_data->clk);
> +	if (ret) {
> +		dev_err(dev,
> +			"Error: Failed to enable lvts controller clock: %d\n",
> +			ret);

This should be:
		dev_err(dev, "Failed to enable lvts controller clock: %d\n", ret);

(or return dev_err_probe()).

> +		return ret;
> +	}
> +
> +	lvts_reset(lvts_data);
> +
> +	device_identification(lvts_data);
> +	if (ops->device_enable_and_init)
> +		ops->device_enable_and_init(lvts_data);
> +
> +	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
> +		if (ops->device_enable_auto_rck)
> +			ops->device_enable_auto_rck(lvts_data);
> +	} else {
> +		if (ops->device_read_count_rc_n)
> +			ops->device_read_count_rc_n(lvts_data);
> +	}

	if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK) && ops....)
		ops....
	else if (ops.....)
		ops.....

> +
> +	if (ops->set_cal_data)
> +		ops->set_cal_data(lvts_data);
> +
> +	disable_all_sensing_points(lvts_data);
> +	wait_all_tc_sensing_point_idle(lvts_data);
> +	if (ops->init_controller)
> +		ops->init_controller(lvts_data);
> +	enable_all_sensing_points(lvts_data);
> +
> +	set_all_tc_hw_reboot(lvts_data);
> +
> +	return 0;
> +}
> +
> +static int prepare_calibration_data(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	struct platform_ops *ops = &lvts_data->ops;
> +	int i, offset;
> +	char buffer[512];
> +
> +	cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_r), GFP_KERNEL);
> +	if (!cal_data->count_r)
> +		return -ENOMEM;
> +
> +	cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_rc), GFP_KERNEL);
> +	if (!cal_data->count_rc)
> +		return -ENOMEM;
> +
> +	if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
> +		ops->efuse_to_cal_data(lvts_data);
> +	if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
> +		cal_data->use_fake_efuse = 1;
> +
> +	if (cal_data->use_fake_efuse) {
> +		/* It means all efuse data are equal to 0 */
> +		dev_err(dev,
> +			"%s: This sample is not calibrated, fake !!\n", __func__);
> +
> +		cal_data->golden_temp = cal_data->default_golden_temp;
> +		for (i = 0; i < lvts_data->num_sensor; i++) {
> +			cal_data->count_r[i] = cal_data->default_count_r;
> +			cal_data->count_rc[i] = cal_data->default_count_rc;
> +		}
> +	}
> +
> +	lvts_data->coeff.golden_temp = cal_data->golden_temp;
> +
> +	dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
> +
> +	offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
> +	for (i = 0; i < lvts_data->num_sensor; i++)
> +		offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
> +			i, cal_data->count_r[i], cal_data->count_rc[i]);
> +
> +	buffer[offset] = '\0';

What is this string for?
You're formatting it but never using, what's the point?

> +
> +	return 0;
> +}
> +
> +static int get_calibration_data(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	char cell_name[32];
> +	struct nvmem_cell *cell;
> +	u32 *buf;
> +	size_t len;
> +	int i, j, index = 0, ret;
> +
> +	lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
> +					sizeof(*lvts_data->efuse), GFP_KERNEL);
> +	if (!lvts_data->efuse)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_efuse_block; i++) {
> +		snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
> +		cell = nvmem_cell_get(dev, cell_name);
> +		if (IS_ERR(cell)) {
> +			dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
> +			return PTR_ERR(cell);
> +		}
> +
> +		buf = (u32 *)nvmem_cell_read(cell, &len);
> +		nvmem_cell_put(cell);
> +
> +		if (IS_ERR(buf))
> +			return PTR_ERR(buf);
> +
> +		for (j = 0; j < (len / sizeof(u32)); j++) {
> +			if (index >= lvts_data->num_efuse_addr) {
> +				dev_err(dev, "Array efuse is going to overflow");
> +				kfree(buf);
> +				return -EINVAL;

If we get an error here, you should free all of the allocated buffers, which means
that you have to walk back from i to 0 and kfree everything, or this is going to be
a (relatively) big memory leak.

> +			}
> +
> +			lvts_data->efuse[index] = buf[j];
> +			index++;
> +		}
> +
> +		kfree(buf);
> +	}
> +
> +	ret = prepare_calibration_data(lvts_data);
> +
> +	return ret;
> +}
> +
> +static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int i, j, s_index;
> +	void __iomem *base;
> +
> +	lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*lvts_data->reg), GFP_KERNEL);
> +	if (!lvts_data->reg)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +			lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int of_update_lvts_data(struct lvts_data *lvts_data,
> +	struct platform_device *pdev)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct resource *res;
> +	int ret;
> +
> +	lvts_data->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(lvts_data->clk))
> +		return PTR_ERR(lvts_data->clk);
> +
> +	/* Get base address */
> +	res = platform_get_mem_or_io(pdev, 0);
> +	if (!res) {
> +		dev_err(dev, "No IO resource\n");
> +		return -ENXIO;
> +	}
> +
> +	lvts_data->base = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(lvts_data->base)) {
> +		dev_err(dev, "Failed to remap io\n");
> +		return PTR_ERR(lvts_data->base);
> +	}
> +
> +	/* Get interrupt number */
> +	ret = platform_get_irq(pdev, 0);
> +	if (ret < 0) {
> +		dev_err(dev, "No irq resource\n");
> +		return -EINVAL;

Why are you overriding the return value? return ret here.

> +	}
> +	lvts_data->irq_num = ret;
> +
> +	/* Get reset control */
> +	lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
> +	if (IS_ERR(lvts_data->reset)) {
> +		dev_err(dev, "Failed to get reset control\n");
> +		return PTR_ERR(lvts_data->reset);
> +	}
> +
> +	ret = lvts_init_tc_regs(dev, lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	ret = get_calibration_data(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +

..snip..

> +
> +static irqreturn_t irq_handler(int irq, void *dev_id)
> +{
> +	struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	unsigned int i, *irq_bitmap;
> +	void __iomem *base;
> +
> +	irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
> +

You're using this for debugging only? Also, why wasn't this stack-allocated?

Just remove it.

> +	if (!irq_bitmap)
> +		return IRQ_NONE;
> +
> +	base = lvts_data->base;
> +	*irq_bitmap = readl(THERMINTST + base);
> +	dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		if (tc[i].irq_bit == 0)
> +			tc_irq_handler(lvts_data, i);
> +	}
> +
> +	kfree(irq_bitmap);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int lvts_register_irq_handler(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	int ret;
> +
> +	ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
> +		IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);

Interrupt flags are specified in devicetree: why are you forcing TRIGGER_HIGH here?

> +
> +	if (ret) {
> +		dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
> +			ret, lvts_data->irq_num);
> +		lvts_close(lvts_data);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	struct thermal_zone_device *tzdev;
> +	struct soc_temp_tz *lvts_tz;
> +	int i, ret;
> +
> +	for (i = 0; i < lvts_data->num_sensor; i++) {
> +		lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
> +		if (!lvts_tz) {
> +			lvts_close(lvts_data);
> +			return -ENOMEM;
> +		}
> +
> +		lvts_tz->id = i;
> +		lvts_tz->lvts_data = lvts_data;
> +
> +		tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
> +			lvts_tz, &soc_temp_lvts_ops);
> +
> +		if (IS_ERR(tzdev)) {
> +			if (lvts_tz->id != 0)
> +				return 0;
> +
> +			ret = PTR_ERR(tzdev);
> +			dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",

s/Error: //g - here and everywhere else: a dev_err() *is* an error print.

> +				lvts_tz->id, ret);
> +			lvts_close(lvts_data);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +

..snip..

> +
> +int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
> +{
> +	/* Resistor-Capacitor Calibration */
> +	/* count_RC_N: count RC now */
> +	struct device *dev = lvts_data->dev;
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int offset, size, s_index, data;
> +	void __iomem *base;
> +	int ret, i, j;
> +	char buffer[512];

I don't think that you need this buffer to be that long and I'm sure that its
size can be reduced.
I didn't check how much you need, but I'm guessing that you need less than a
quarter of that size.

> +
> +	cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
> +		sizeof(*cal_data->count_rc_now), GFP_KERNEL);
> +	if (!cal_data->count_rc_now)
> +		return -ENOMEM;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +
> +			lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
> +			lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
> +			usleep_range(10, 20);
> +
> +			lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
> +			usleep_range(30, 40);
> +
> +			ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> +						 !(data & DEVICE_SENSING_STATUS), 2, 200);
> +			if (ret)
> +				dev_err(dev,
> +					"Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
> +
> +			data = lvts_read_device(lvts_data, 0x00, i);
> +
> +			cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));

No magic GENMASK() or BIT() please, add a definition for readability.

> +		}
> +
> +		/* Recover Setting for Normal Access on
> +		 * temperature fetch
> +		 */
> +		lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
> +		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> +	}
> +
> +	size = sizeof(buffer);
> +	offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
> +	for (i = 0; i < lvts_data->num_sensor; i++)
> +		offset += snprintf(buffer + offset, size - offset, "%d:%d ",
> +			i, cal_data->count_rc_now[i]);
> +
> +	buffer[offset] = '\0';
> +	dev_dbg(dev, "%s\n", buffer);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
> +
> +void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
> +{
> +	const struct lvts_tc_settings *tc = lvts_data->tc;
> +	struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> +	unsigned int i, j, s_index, lvts_calib_data;
> +	void __iomem *base;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +
> +		for (j = 0; j < tc[i].num_sensor; j++) {
> +			s_index = tc[i].sensor_map[j];
> +			if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
> +				lvts_calib_data = cal_data->count_r[s_index];
> +			else
> +				lvts_calib_data = (((unsigned long long)

lvts_calib_data is unsigned int. You're assigning unsigned long long here.

Also, since this is register-size bound, use fixed size types.

> +					cal_data->count_rc_now[s_index]) *
> +					cal_data->count_r[s_index]) >> 14;
> +
> +			writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
> +		}
> +	}
> +}
> +EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
> +
> +void lvts_init_controller_v4(struct lvts_data *lvts_data)
> +{
> +	struct device *dev = lvts_data->dev;
> +	unsigned int i;
> +	void __iomem *base;
> +
> +	for (i = 0; i < lvts_data->num_tc; i++) {
> +		base = GET_BASE_ADDR(lvts_data, i);
> +
> +		lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> +
> +		writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
> +		writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
> +
> +		set_polling_speed(lvts_data, i);
> +		set_hw_filter(lvts_data, i);
> +
> +		dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
> +			i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));

dev_dbg().

> +	}
> +}
> +EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
> +
> +int lvts_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct lvts_data *lvts_data;
> +	int ret;
> +
> +	lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
> +
> +	if (!lvts_data)	{
> +		dev_err(dev, "Error: Failed to get lvts platform data\n");
> +		return -ENODATA;
> +	}
> +
> +	lvts_data->dev = &pdev->dev;
> +
> +	ret = of_update_lvts_data(lvts_data, pdev);
> +	if (ret)
> +		return ret;
> +
> +	platform_set_drvdata(pdev, lvts_data);
> +
> +	ret = lvts_init(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	ret = lvts_register_irq_handler(lvts_data);
> +	if (ret)
> +		return ret;

If anything goes wrong here, you're leaving the lvts_data->clk clock enabled.
Please fix.

> +
> +	ret = lvts_register_thermal_zones(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +int lvts_remove(struct platform_device *pdev)
> +{
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	lvts_close(lvts_data);
> +
> +	return 0;
> +}
> +
> +int lvts_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	lvts_close(lvts_data);
> +
> +	return 0;
> +}
> +
> +int lvts_resume(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct lvts_data *lvts_data;
> +
> +	lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> +
> +	ret = lvts_init(lvts_data);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> +MODULE_LICENSE("GPL v2");

Regards,
Angelo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-28  8:53     ` Daniel Lezcano
  -1 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-07-28  8:53 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon


Hi Balsam,

On 26/07/2022 15:55, Balsam CHIHI wrote:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.

I realize the Kconfig, Makefiles format are not consistent across the 
boards. Before I fix this, you can comply to the format:

drivers/thermal/Kconfig:

menu "Mediatek thermal drivers"
depends on ARCH_MEDIATEK || COMPILE_TEST
source "drivers/thermal/mediatek/Kconfig"
endmenu

drivers/thermal/Makefile:

-obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
+obj-y                          += mediatek

drivers/thermal/mediatek/Kconfig:

config MTK_SOC_THERMAL
	tristate "Temperature sensor driver for MediaTek SoCs"
	depends on HAS_IOMEM
	depends on NVMEM
	depends on RESET_CONTROLLER
	help
		Enable this option if you want to get SoC temperature
		information for MediaTek platforms. This driver
		configures thermal controllers to collect temperature
		via AUXADC interface.

drivers/thermal/mediatek/Makefile:

obj-$(MTK_SOC_THERMAL)	+= soc_temp.o

However, rename 'soc_temp' to something more SoC explicit, eg. 
mtxxx_thermal.c

Thanks

   -- Daniel


> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

> ---
>   drivers/thermal/Kconfig                       | 14 ++++-------
>   drivers/thermal/Makefile                      |  2 +-
>   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
>   drivers/thermal/mediatek/Makefile             |  1 +
>   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
>   5 files changed, 29 insertions(+), 11 deletions(-)
>   create mode 100644 drivers/thermal/mediatek/Kconfig
>   create mode 100644 drivers/thermal/mediatek/Makefile
>   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 0e5cc948373c..ecba8d6e313b 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -412,16 +412,10 @@ config DA9062_THERMAL
>   	  zone.
>   	  Compatible with the DA9062 and DA9061 PMICs.
>   
> -config MTK_THERMAL
> -	tristate "Temperature sensor driver for mediatek SoCs"
> -	depends on ARCH_MEDIATEK || COMPILE_TEST
> -	depends on HAS_IOMEM
> -	depends on NVMEM || NVMEM=n
> -	depends on RESET_CONTROLLER
> -	default y
> -	help
> -	  Enable this option if you want to have support for thermal management
> -	  controller present in Mediatek SoCs
> +menu "Mediatek thermal drivers"
> +depends on ARCH_MEDIATEK || COMPILE_TEST
> +source "drivers/thermal/mediatek/Kconfig"
> +endmenu
>   
>   config AMLOGIC_THERMAL
>   	tristate "Amlogic Thermal Support"
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index def8e1a0399c..3c00e864ad55 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,7 +55,7 @@ obj-y				+= st/
>   obj-$(CONFIG_QCOM_TSENS)	+= qcom/
>   obj-y				+= tegra/
>   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> -obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
> +obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
>   obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
>   obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
>   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> new file mode 100644
> index 000000000000..9c41e9079fc3
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -0,0 +1,23 @@
> +config MTK_THERMAL
> +	tristate "MediaTek thermal drivers"
> +	depends on THERMAL_OF
> +	help
> +		This is the option for MediaTek thermal software
> +		solutions. Please enable corresponding options to
> +		get temperature information from thermal sensors or
> +		turn on throttle mechaisms for thermal mitigation.
> +
> +if MTK_THERMAL
> +
> +config MTK_SOC_THERMAL
> +	tristate "Temperature sensor driver for MediaTek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_CONTROLLER
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures thermal controllers to collect temperature
> +		via AUXADC interface.
> +
> +endif
> diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> new file mode 100644
> index 000000000000..4b4cb04a358f
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mediatek/soc_temp.c
> similarity index 100%
> rename from drivers/thermal/mtk_thermal.c
> rename to drivers/thermal/mediatek/soc_temp.c


-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-28  8:53     ` Daniel Lezcano
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-07-28  8:53 UTC (permalink / raw)
  To: Balsam CHIHI, rafael, rui.zhang, amitk
  Cc: linux-pm, linux-kernel, khilman, mka, robh+dt, krzk+dt,
	matthias.bgg, p.zabel, devicetree, linux-arm-kernel,
	linux-mediatek, james.lo, fan.chen, louis.yu, rex-bc.chen,
	abailon


Hi Balsam,

On 26/07/2022 15:55, Balsam CHIHI wrote:
> Add Mediatek proprietary folder to upstream more thermal zone and cooler
> drivers. Relocate the original thermal controller driver to it and rename
> as soc_temp.c to show its purpose more clearly.

I realize the Kconfig, Makefiles format are not consistent across the 
boards. Before I fix this, you can comply to the format:

drivers/thermal/Kconfig:

menu "Mediatek thermal drivers"
depends on ARCH_MEDIATEK || COMPILE_TEST
source "drivers/thermal/mediatek/Kconfig"
endmenu

drivers/thermal/Makefile:

-obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
+obj-y                          += mediatek

drivers/thermal/mediatek/Kconfig:

config MTK_SOC_THERMAL
	tristate "Temperature sensor driver for MediaTek SoCs"
	depends on HAS_IOMEM
	depends on NVMEM
	depends on RESET_CONTROLLER
	help
		Enable this option if you want to get SoC temperature
		information for MediaTek platforms. This driver
		configures thermal controllers to collect temperature
		via AUXADC interface.

drivers/thermal/mediatek/Makefile:

obj-$(MTK_SOC_THERMAL)	+= soc_temp.o

However, rename 'soc_temp' to something more SoC explicit, eg. 
mtxxx_thermal.c

Thanks

   -- Daniel


> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>

> ---
>   drivers/thermal/Kconfig                       | 14 ++++-------
>   drivers/thermal/Makefile                      |  2 +-
>   drivers/thermal/mediatek/Kconfig              | 23 +++++++++++++++++++
>   drivers/thermal/mediatek/Makefile             |  1 +
>   .../{mtk_thermal.c => mediatek/soc_temp.c}    |  0
>   5 files changed, 29 insertions(+), 11 deletions(-)
>   create mode 100644 drivers/thermal/mediatek/Kconfig
>   create mode 100644 drivers/thermal/mediatek/Makefile
>   rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (100%)
> 
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 0e5cc948373c..ecba8d6e313b 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -412,16 +412,10 @@ config DA9062_THERMAL
>   	  zone.
>   	  Compatible with the DA9062 and DA9061 PMICs.
>   
> -config MTK_THERMAL
> -	tristate "Temperature sensor driver for mediatek SoCs"
> -	depends on ARCH_MEDIATEK || COMPILE_TEST
> -	depends on HAS_IOMEM
> -	depends on NVMEM || NVMEM=n
> -	depends on RESET_CONTROLLER
> -	default y
> -	help
> -	  Enable this option if you want to have support for thermal management
> -	  controller present in Mediatek SoCs
> +menu "Mediatek thermal drivers"
> +depends on ARCH_MEDIATEK || COMPILE_TEST
> +source "drivers/thermal/mediatek/Kconfig"
> +endmenu
>   
>   config AMLOGIC_THERMAL
>   	tristate "Amlogic Thermal Support"
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index def8e1a0399c..3c00e864ad55 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,7 +55,7 @@ obj-y				+= st/
>   obj-$(CONFIG_QCOM_TSENS)	+= qcom/
>   obj-y				+= tegra/
>   obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> -obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
> +obj-$(CONFIG_MTK_THERMAL)	+= mediatek/
>   obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
>   obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
>   obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> new file mode 100644
> index 000000000000..9c41e9079fc3
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -0,0 +1,23 @@
> +config MTK_THERMAL
> +	tristate "MediaTek thermal drivers"
> +	depends on THERMAL_OF
> +	help
> +		This is the option for MediaTek thermal software
> +		solutions. Please enable corresponding options to
> +		get temperature information from thermal sensors or
> +		turn on throttle mechaisms for thermal mitigation.
> +
> +if MTK_THERMAL
> +
> +config MTK_SOC_THERMAL
> +	tristate "Temperature sensor driver for MediaTek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_CONTROLLER
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures thermal controllers to collect temperature
> +		via AUXADC interface.
> +
> +endif
> diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> new file mode 100644
> index 000000000000..4b4cb04a358f
> --- /dev/null
> +++ b/drivers/thermal/mediatek/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_MTK_SOC_THERMAL)		+= soc_temp.o
> diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mediatek/soc_temp.c
> similarity index 100%
> rename from drivers/thermal/mtk_thermal.c
> rename to drivers/thermal/mediatek/soc_temp.c


-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-26 20:09     ` Rob Herring
@ 2022-07-29 15:15       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:15 UTC (permalink / raw)
  To: Rob Herring
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >  2 files changed, 148 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> FATAL ERROR: Unable to parse input tree
> make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1404: dt_binding_check] Error 2
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/patch/
>
> This check can fail if there are any dependencies. The base for a patch
> series is generally the most recent rc1.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit.
>

Hello Rob,

This error only appear when I apply my series directly on top of linux-5.19.rc8.
But, when I apply the other two series that mine depends on,

https://patchwork.kernel.org/project/linux-pm/cover/20220722200007.1839356-1-daniel.lezcano@linexp.org/
https://patchwork.kernel.org/project/linux-mediatek/cover/20220523093346.28493-1-rex-bc.chen@mediatek.com/

and run "dt_binding_check" again against my YAML file, it does not
print the error you found above.
Would you check it, please?
Thank you.

Best regards.
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-07-29 15:15       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:15 UTC (permalink / raw)
  To: Rob Herring
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, robh+dt, p.zabel, matthias.bgg, linux-pm, rafael,
	khilman, fan.chen, linux-arm-kernel, krzk+dt, devicetree,
	linux-mediatek, louis.yu, james.lo

On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
>
> On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> >  2 files changed, 148 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> >
>
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
>
> yamllint warnings/errors:
>
> dtschema/dtc warnings/errors:
> Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> FATAL ERROR: Unable to parse input tree
> make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1404: dt_binding_check] Error 2
>
> doc reference errors (make refcheckdocs):
>
> See https://patchwork.ozlabs.org/patch/
>
> This check can fail if there are any dependencies. The base for a patch
> series is generally the most recent rc1.
>
> If you already ran 'make dt_binding_check' and didn't see the above
> error(s), then make sure 'yamllint' is installed and dt-schema is up to
> date:
>
> pip3 install dtschema --upgrade
>
> Please check and re-submit.
>

Hello Rob,

This error only appear when I apply my series directly on top of linux-5.19.rc8.
But, when I apply the other two series that mine depends on,

https://patchwork.kernel.org/project/linux-pm/cover/20220722200007.1839356-1-daniel.lezcano@linexp.org/
https://patchwork.kernel.org/project/linux-mediatek/cover/20220523093346.28493-1-rex-bc.chen@mediatek.com/

and run "dt_binding_check" again against my YAML file, it does not
print the error you found above.
Would you check it, please?
Thank you.

Best regards.
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-28  8:53     ` Daniel Lezcano
@ 2022-07-29 15:19       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:19 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Thu, Jul 28, 2022 at 10:53 AM Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
>
>
> Hi Balsam,
>
> On 26/07/2022 15:55, Balsam CHIHI wrote:
> > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > drivers. Relocate the original thermal controller driver to it and rename
> > as soc_temp.c to show its purpose more clearly.
>
> I realize the Kconfig, Makefiles format are not consistent across the
> boards. Before I fix this, you can comply to the format:
>
> drivers/thermal/Kconfig:
>
> menu "Mediatek thermal drivers"
> depends on ARCH_MEDIATEK || COMPILE_TEST
> source "drivers/thermal/mediatek/Kconfig"
> endmenu
>
> drivers/thermal/Makefile:
>
> -obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
> +obj-y                          += mediatek
>
> drivers/thermal/mediatek/Kconfig:
>
> config MTK_SOC_THERMAL
>         tristate "Temperature sensor driver for MediaTek SoCs"
>         depends on HAS_IOMEM
>         depends on NVMEM
>         depends on RESET_CONTROLLER
>         help
>                 Enable this option if you want to get SoC temperature
>                 information for MediaTek platforms. This driver
>                 configures thermal controllers to collect temperature
>                 via AUXADC interface.
>
> drivers/thermal/mediatek/Makefile:
>
> obj-$(MTK_SOC_THERMAL)  += soc_temp.o
>
> However, rename 'soc_temp' to something more SoC explicit, eg.
> mtxxx_thermal.c
>
> Thanks
>
>    -- Daniel

Hello Daniel,

Thank you for the feedback.
Changes have been made as you suggested.
Resubmitting seen.

Best regards.
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-29 15:19       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:19 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Thu, Jul 28, 2022 at 10:53 AM Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
>
>
> Hi Balsam,
>
> On 26/07/2022 15:55, Balsam CHIHI wrote:
> > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > drivers. Relocate the original thermal controller driver to it and rename
> > as soc_temp.c to show its purpose more clearly.
>
> I realize the Kconfig, Makefiles format are not consistent across the
> boards. Before I fix this, you can comply to the format:
>
> drivers/thermal/Kconfig:
>
> menu "Mediatek thermal drivers"
> depends on ARCH_MEDIATEK || COMPILE_TEST
> source "drivers/thermal/mediatek/Kconfig"
> endmenu
>
> drivers/thermal/Makefile:
>
> -obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
> +obj-y                          += mediatek
>
> drivers/thermal/mediatek/Kconfig:
>
> config MTK_SOC_THERMAL
>         tristate "Temperature sensor driver for MediaTek SoCs"
>         depends on HAS_IOMEM
>         depends on NVMEM
>         depends on RESET_CONTROLLER
>         help
>                 Enable this option if you want to get SoC temperature
>                 information for MediaTek platforms. This driver
>                 configures thermal controllers to collect temperature
>                 via AUXADC interface.
>
> drivers/thermal/mediatek/Makefile:
>
> obj-$(MTK_SOC_THERMAL)  += soc_temp.o
>
> However, rename 'soc_temp' to something more SoC explicit, eg.
> mtxxx_thermal.c
>
> Thanks
>
>    -- Daniel

Hello Daniel,

Thank you for the feedback.
Changes have been made as you suggested.
Resubmitting seen.

Best regards.
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-29 15:19       ` Balsam CHIHI
@ 2022-07-29 15:21         ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:21 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 5:19 PM Balsam CHIHI <bchihi@baylibre.com> wrote:
>
> On Thu, Jul 28, 2022 at 10:53 AM Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
> >
> >
> > Hi Balsam,
> >
> > On 26/07/2022 15:55, Balsam CHIHI wrote:
> > > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > > drivers. Relocate the original thermal controller driver to it and rename
> > > as soc_temp.c to show its purpose more clearly.
> >
> > I realize the Kconfig, Makefiles format are not consistent across the
> > boards. Before I fix this, you can comply to the format:
> >
> > drivers/thermal/Kconfig:
> >
> > menu "Mediatek thermal drivers"
> > depends on ARCH_MEDIATEK || COMPILE_TEST
> > source "drivers/thermal/mediatek/Kconfig"
> > endmenu
> >
> > drivers/thermal/Makefile:
> >
> > -obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
> > +obj-y                          += mediatek
> >
> > drivers/thermal/mediatek/Kconfig:
> >
> > config MTK_SOC_THERMAL
> >         tristate "Temperature sensor driver for MediaTek SoCs"
> >         depends on HAS_IOMEM
> >         depends on NVMEM
> >         depends on RESET_CONTROLLER
> >         help
> >                 Enable this option if you want to get SoC temperature
> >                 information for MediaTek platforms. This driver
> >                 configures thermal controllers to collect temperature
> >                 via AUXADC interface.
> >
> > drivers/thermal/mediatek/Makefile:
> >
> > obj-$(MTK_SOC_THERMAL)  += soc_temp.o
> >
> > However, rename 'soc_temp' to something more SoC explicit, eg.
> > mtxxx_thermal.c
> >
> > Thanks
> >
> >    -- Daniel
>
> Hello Daniel,
>
> Thank you for the feedback.
> Changes have been made as you suggested.
> Resubmitting seen.
*soon.
>
> Best regards.
> Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-29 15:21         ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:21 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 5:19 PM Balsam CHIHI <bchihi@baylibre.com> wrote:
>
> On Thu, Jul 28, 2022 at 10:53 AM Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
> >
> >
> > Hi Balsam,
> >
> > On 26/07/2022 15:55, Balsam CHIHI wrote:
> > > Add Mediatek proprietary folder to upstream more thermal zone and cooler
> > > drivers. Relocate the original thermal controller driver to it and rename
> > > as soc_temp.c to show its purpose more clearly.
> >
> > I realize the Kconfig, Makefiles format are not consistent across the
> > boards. Before I fix this, you can comply to the format:
> >
> > drivers/thermal/Kconfig:
> >
> > menu "Mediatek thermal drivers"
> > depends on ARCH_MEDIATEK || COMPILE_TEST
> > source "drivers/thermal/mediatek/Kconfig"
> > endmenu
> >
> > drivers/thermal/Makefile:
> >
> > -obj-$(CONFIG_MTK_THERMAL)      += mtk_thermal.o
> > +obj-y                          += mediatek
> >
> > drivers/thermal/mediatek/Kconfig:
> >
> > config MTK_SOC_THERMAL
> >         tristate "Temperature sensor driver for MediaTek SoCs"
> >         depends on HAS_IOMEM
> >         depends on NVMEM
> >         depends on RESET_CONTROLLER
> >         help
> >                 Enable this option if you want to get SoC temperature
> >                 information for MediaTek platforms. This driver
> >                 configures thermal controllers to collect temperature
> >                 via AUXADC interface.
> >
> > drivers/thermal/mediatek/Makefile:
> >
> > obj-$(MTK_SOC_THERMAL)  += soc_temp.o
> >
> > However, rename 'soc_temp' to something more SoC explicit, eg.
> > mtxxx_thermal.c
> >
> > Thanks
> >
> >    -- Daniel
>
> Hello Daniel,
>
> Thank you for the feedback.
> Changes have been made as you suggested.
> Resubmitting seen.
*soon.
>
> Best regards.
> Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-29 15:21         ` Balsam CHIHI
@ 2022-07-29 15:35           ` Daniel Lezcano
  -1 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-07-29 15:35 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

Hi Balsam,

On 29/07/2022 17:21, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 5:19 PM Balsam CHIHI <bchihi@baylibre.com> wrote:

[ ... ]

>>> config MTK_SOC_THERMAL
>>>          tristate "Temperature sensor driver for MediaTek SoCs"
>>>          depends on HAS_IOMEM
>>>          depends on NVMEM
>>>          depends on RESET_CONTROLLER
>>>          help
>>>                  Enable this option if you want to get SoC temperature
>>>                  information for MediaTek platforms. This driver
>>>                  configures thermal controllers to collect temperature
>>>                  via AUXADC interface.
>>>
>>> drivers/thermal/mediatek/Makefile:
>>>
>>> obj-$(MTK_SOC_THERMAL)  += soc_temp.o
>>>
>>> However, rename 'soc_temp' to something more SoC explicit, eg.
>>> mtxxx_thermal.c
>>>
>>> Thanks
>>>
>>>     -- Daniel
>>
>> Hello Daniel,
>>
>> Thank you for the feedback.
>> Changes have been made as you suggested.
>> Resubmitting seen.
> *soon.

You may want to wait next week before sending a new version, I'm still 
reviewing your series (note you can send it anyway if you prefer)

-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-07-29 15:35           ` Daniel Lezcano
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-07-29 15:35 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

Hi Balsam,

On 29/07/2022 17:21, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 5:19 PM Balsam CHIHI <bchihi@baylibre.com> wrote:

[ ... ]

>>> config MTK_SOC_THERMAL
>>>          tristate "Temperature sensor driver for MediaTek SoCs"
>>>          depends on HAS_IOMEM
>>>          depends on NVMEM
>>>          depends on RESET_CONTROLLER
>>>          help
>>>                  Enable this option if you want to get SoC temperature
>>>                  information for MediaTek platforms. This driver
>>>                  configures thermal controllers to collect temperature
>>>                  via AUXADC interface.
>>>
>>> drivers/thermal/mediatek/Makefile:
>>>
>>> obj-$(MTK_SOC_THERMAL)  += soc_temp.o
>>>
>>> However, rename 'soc_temp' to something more SoC explicit, eg.
>>> mtxxx_thermal.c
>>>
>>> Thanks
>>>
>>>     -- Daniel
>>
>> Hello Daniel,
>>
>> Thank you for the feedback.
>> Changes have been made as you suggested.
>> Resubmitting seen.
> *soon.

You may want to wait next week before sending a new version, I'm still 
reviewing your series (note you can send it anyway if you prefer)

-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  2022-07-27  9:23     ` AngeloGioacchino Del Regno
@ 2022-07-29 15:38       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:38 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 11:24 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > Add a LVTS (Low voltage thermal sensor) driver to report junction
> > temperatures in Mediatek SoC mt8192 and register the maximum temperature
> > of sensors and each sensor as a thermal zone.
> >
> > Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
>
> Hello Balsam,
>
> there are a few comments on this patch.
>
> First of all, can you please fix the typo that you have in the commit title?
> theraml -> thermal
>
> ...then, please, the commit description:
> Add a LVTS (Low Voltage Thermal Sensor) <- capitalize
>
> and
>
> Mediatek -> MediaTek
>
> > ---
> >   drivers/thermal/mediatek/Kconfig         |  27 +
> >   drivers/thermal/mediatek/Makefile        |   2 +
> >   drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
> >   drivers/thermal/mediatek/soc_temp.c      |   2 +-
> >   drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
> >   drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
> >   6 files changed, 1564 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
> >   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
> >   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> >
> > diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> > index 9c41e9079fc3..7fc04237dd50 100644
> > --- a/drivers/thermal/mediatek/Kconfig
> > +++ b/drivers/thermal/mediatek/Kconfig
> > @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
> >               configures thermal controllers to collect temperature
> >               via AUXADC interface.
> >
> > +config MTK_SOC_THERMAL_LVTS
> > +     tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> > +     depends on HAS_IOMEM
> > +     depends on NVMEM
> > +     depends on RESET_TI_SYSCON
> > +     help
> > +             Enable this option if you want to get SoC temperature
> > +             information for MediaTek platforms. This driver
> > +             configures LVTS thermal controllers to collect temperatures
> > +             via Analog Serial Interface(ASIF).
>
> Fix the indentation, please:
>
>         help
>           Enable this option.......
> (\t<space><space>)
>
>
>
> > +
> > +endif
> > +
> > +if MTK_SOC_THERMAL_LVTS
> > +
> > +config LVTS_MT8192
> > +     tristate "LVTS driver for MediaTek MT8192 SoC"
> > +     depends on HAS_IOMEM
> > +     depends on NVMEM
> > +     depends on RESET_TI_SYSCON
> > +     depends on MTK_SOC_THERMAL_LVTS
> > +     help
> > +             Enable this option if you want to get SoC temperature
> > +             information for MT8192. This driver
> > +             configures LVTS thermal controllers to collect temperatures
> > +             via ASIF.
> > +
> >   endif
> > diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> > index 4b4cb04a358f..5ff1197e80ab 100644
> > --- a/drivers/thermal/mediatek/Makefile
> > +++ b/drivers/thermal/mediatek/Makefile
> > @@ -1 +1,3 @@
> >   obj-$(CONFIG_MTK_SOC_THERMAL)               += soc_temp.o
> > +obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)   += soc_temp_lvts.o
> > +obj-$(CONFIG_LVTS_MT8192)                    += lvts_mt8192.o
> > diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
> > new file mode 100644
> > index 000000000000..19e4e82c410b
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/lvts_mt8192.c
> > @@ -0,0 +1,241 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2022 MediaTek Inc.
> > + */
> > +
> > +#include <linux/of_irq.h>
> > +#include <linux/platform_device.h>
> > +#include "soc_temp_lvts.h"
> > +
> > +enum mt8192_lvts_mcu_sensor_enum {
> > +     MT8192_TS1_0,
> > +     MT8192_TS1_1,
> > +     MT8192_TS2_0,
> > +     MT8192_TS2_1,
> > +     MT8192_TS3_0,
> > +     MT8192_TS3_1,
> > +     MT8192_TS3_2,
> > +     MT8192_TS3_3,
> > +     MT8192_NUM_TS_MCU
> > +};
> > +
> > +enum mt8192_lvts_ap_sensor_enum {
> > +     MT8192_TS4_0,
> > +     MT8192_TS4_1,
> > +     MT8192_TS5_0,
> > +     MT8192_TS5_1,
> > +     MT8192_TS6_0,
> > +     MT8192_TS6_1,
> > +     MT8192_TS7_0,
> > +     MT8192_TS7_1,
> > +     MT8192_TS7_2,
> > +     MT8192_NUM_TS_AP
> > +};
> > +
> > +static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
> > +{
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int i, j;
> > +     const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};
>
>
> Please fix and reorder (here and for any other instance):
>
>         const unsigned int mt8192_ts[] = { MT8192_TS2_0, MT8192_TS3_0 };
>         struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
>         unsigned int i, j;
>
> > +
> > +     cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
> > +
> > +     for (i = 0; i < MT8192_NUM_TS_MCU; i++)
> > +             cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
> > +
> > +     cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);
>
> ..snip..
>
> > +
> > +static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
> > +     [0] = {
> > +             .dev_id = 0x81,
> > +             .addr_offset = 0x0,
> > +             .num_sensor = 2,
> > +             .sensor_map = {MT8192_TS1_0, MT8192_TS1_1},
>
> Please, leave a space after opening and before closing the braces.
>
> > +             .tc_speed = &tc_speed_mt8192,
> > +             .hw_filter = LVTS_FILTER_2_OF_4,
> > +             .dominator_sensing_point = SENSING_POINT1,
> > +             .hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
> > +             .irq_bit = BIT(3),
> > +     },
>
> ..snip..
>
> > +
> > +static const struct lvts_data mt8192_lvts_ap_data = {
> > +     .num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
> > +     .tc = mt8192_tc_ap_settings,
> > +     .num_sensor = MT8192_NUM_TS_AP,
> > +     .ops = {
> > +             .efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
> > +             .device_enable_and_init = lvts_device_enable_and_init_v4,
> > +             .device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
> > +             .device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
> > +             .set_cal_data = lvts_set_calibration_data_v4,
> > +             .init_controller = lvts_init_controller_v4,
> > +     },
> > +     .feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
> > +     .num_efuse_addr = NUM_EFUSE_ADDR,
> > +     .num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
> > +     .cal_data = {
> > +             .default_golden_temp = DEFAULT_GOLDEN_TEMP,
> > +             .default_count_r = DEFAULT_CUONT_R,
> > +             .default_count_rc = DEFAULT_CUONT_RC,
> > +     },
> > +     .coeff = {
> > +             .a = COEFF_A,
> > +             .b = COEFF_B,
> > +     },
> > +};
> > +
> > +static const struct of_device_id lvts_of_match[] = {
>
> I don't like having one driver per SoC, where we have only two specific functions.
>
> I suggest to either:
> - Remove the static word from mt8192_lvts_ap_data and put the of_match
>    in soc_temp_lvts.c; or
> - Separate the SoCs by LVTS version: create a lvts_v4.c where we group all
>    of the V4 SoCs (so, currently, MT8192 and MT8195): this will allow us to
>    eventually get a lvts_v3, lvts_v2, etc, where we group other SoCs.
>
> I prefer the second way, as MediaTek has a lot of SoCs and I can see this list
> growing a lot when these will be (hopefully) upstreamed.
>
>
>
> > +     { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
> > +     { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
> > +     {},
> > +};
> > +MODULE_DEVICE_TABLE(of, lvts_of_match);
> > +
> > +static struct platform_driver soc_temp_lvts = {
> > +     .probe = lvts_probe,
> > +     .remove = lvts_remove,
> > +     .suspend = lvts_suspend,
> > +     .resume = lvts_resume,
> > +     .driver = {
> > +             .name = "mtk-soc-temp-lvts-mt8192",
> > +             .of_match_table = lvts_of_match,
> > +     },
> > +};
> > +module_platform_driver(soc_temp_lvts);
> > +
> > +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> > +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> > +MODULE_LICENSE("GPL v2");
>
> You should run checkpatch.pl. Please.
>
> > diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
> > index ede94eadddda..60924f8f98e9 100644
> > --- a/drivers/thermal/mediatek/soc_temp.c
> > +++ b/drivers/thermal/mediatek/soc_temp.c
> > @@ -23,7 +23,7 @@
> >   #include <linux/reset.h>
> >   #include <linux/types.h>
> >
> > -#include "thermal_hwmon.h"
> > +#include "../thermal_hwmon.h"
>
> This change doesn't belong to this commit.
>
> >
> >   /* AUXADC Registers */
> >   #define AUXADC_CON1_SET_V   0x008
> > diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
> > new file mode 100644
> > index 000000000000..ee7efc0de65f
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/soc_temp_lvts.c
> > @@ -0,0 +1,928 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2022 MediaTek Inc.
> > + */
> > +
> > +#include <linux/bits.h>
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/nvmem-consumer.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> > +#include <linux/thermal.h>
> > +#include "soc_temp_lvts.h"
> > +
> > +static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
> > +{
> > +     /* This function returns degree mC */
> > +
> > +     int temp;
> > +
> > +     temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
> > +     temp = temp + co->golden_temp * 500 + co->b;
> > +
> > +     return temp;
> > +}
> > +
> > +static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
> > +{
> > +     unsigned int msr_raw;
> > +
> > +     msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
> > +             (-1 * co->a));
> > +
> > +     return msr_raw;
> > +}
> > +
> > +static int soc_temp_lvts_read_temp(void *data, int *temperature)
> > +{
> > +     struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
> > +     struct lvts_data *lvts_data = lvts_tz->lvts_data;
> > +     unsigned int msr_raw;
> > +
> > +     msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
> > +     if (msr_raw == 0)
> > +             return -EINVAL;
> > +
> > +     *temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
> > +     .get_temp = soc_temp_lvts_read_temp,
> > +};
> > +
> > +static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
> > +     int tc_id)
> > +{
> > +     void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
> > +
> > +     usleep_range(5, 15);
> > +}
> > +
> > +static unsigned int lvts_read_device(struct lvts_data *lvts_data,
> > +     unsigned int reg_idx, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     unsigned int data;
> > +     int ret;
> > +
> > +     writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
> > +
> > +     usleep_range(5, 15);
> > +
> > +     ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> > +             !(data & DEVICE_ACCESS_STARTUS), 2, 200);
> > +     if (ret)
> > +             dev_err(dev,
> > +                     "Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
> > +
> > +     data = readl(LVTSRDATA0_0 + base);
> > +
> > +     return data;
> > +}
> > +
> > +static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
> > +     "Waiting for read after Write", "Disable Continue fetching on Device",
> > +     "Read transaction", "Set Device special Register for Voltage threshold",
> > +     "Set TSMCU number for Fetch"};
>
> In my opinion, that's unreadable.
>
> static const char * const lvts_error_table[] = {
>
>         "Idle",
>
>         "Write transaction",
>
>         "Waiting for read after write",
>
>         "Disable continue fetching on device",
>
>         "Read transaction",
>
>         "Set device special register for voltage threshold",
>
>         "Set TSMCU number for fetch"
>
> };
>
> ...but like this, it's way more readable.
>
>
> > +
> > +static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int mask, error_code, is_error;
> > +     void __iomem *base;
> > +     int i, cnt, ret;
> > +
> > +     mask = BIT(10) | BIT(7) | BIT(0);
>
> What are these magic bits?
> Please add definitions.
>
> > +
> > +     for (cnt = 0; cnt < 2; cnt++) {
> > +             is_error = 0;
> > +             for (i = 0; i < lvts_data->num_tc; i++) {
> > +                     base = GET_BASE_ADDR(lvts_data, i);
> > +                     ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
> > +                                              !(error_code & mask), 2, 200);
> > +
> > +                     error_code = ((error_code & BIT(10)) >> 8) +
> > +                             ((error_code & BIT(7)) >> 6) +
> > +                             (error_code & BIT(0));
> > +
> > +                     if (ret)
> > +                             dev_err(dev, "LVTS %d error: %s\n",
> > +                                     i, lvts_error_table[error_code]);
> > +
> > +                     if (error_code != 0)
> > +                             is_error = 1;
> > +             }
> > +
> > +             if (is_error == 0)
> > +                     break;
> > +     }
> > +}
> > +
>
> ...snip...
>
> > +static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int option;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     option = tc[tc_id].hw_filter & 0x7;
> > +     /*
> > +      * hw filter
> > +      * 000: Get one sample
> > +      * 001: Get 2 samples and average them
> > +      * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
> > +      * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
> > +      * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
> > +      * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
> > +      */
> > +     option = (option << 9) | (option << 6) | (option << 3) | option;
> > +
> > +     writel(option, LVTSMSRCTL0_0 + base);
> > +     dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
> > +              tc_id, readl(LVTSMSRCTL0_0 + base));
> > +}
> > +
> > +static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     int d_index;
> > +
> > +     if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
> > +             d_index = ALL_SENSING_POINTS;
> > +     } else if (tc[tc_id].dominator_sensing_point <
> > +             tc[tc_id].num_sensor){
>
> There's no reason to break this line.
>
> > +             d_index = tc[tc_id].dominator_sensing_point;
> > +     } else {
> > +             dev_err(dev,
> > +                     "Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",
>
> "Error:" is unneeded, as this is a dev_err, so it's definitely an error.
> Also, s/should/shall be/g
>
> > +                     tc_id, tc[tc_id].dominator_sensing_point,
> > +                     tc[tc_id].num_sensor);
> > +
> > +             dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
> > +             d_index = SENSING_POINT0;
> > +     }
> > +
> > +     return d_index;
> > +}
> > +
> > +static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     unsigned int temp;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     /*
> > +      * LVTS thermal controller has two interrupts for thermal HW reboot
> > +      * One is for AP SW and the other is for RGU
> > +      * The interrupt of AP SW can turn off by a bit of a register, but
> > +      * the other for RGU cannot.
> > +      * To prevent rebooting device accidentally, we are going to add
> > +      * a huge offset to LVTS and make LVTS always report extremely low
> > +      * temperature.
> > +      */
> > +
> > +     /*
> > +      * After adding the huge offset 0x3FFF, LVTS alawys adds the
>
> s/alawys/always/g
>
> > +      * offset to MSR_RAW.
> > +      * When MSR_RAW is larger, SW will convert lower temperature/
> > +      */
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
> > +
> > +     /* Disable the interrupt of AP SW */
> > +     temp = readl(LVTSMONINT_0 + base);
> > +     writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
> > +}
> > +
> > +static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     unsigned int temp;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     /* Enable the interrupt of AP SW */
> > +     temp = readl(LVTSMONINT_0 + base);
> > +     writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
> > +     /* Clear the offset */
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
> > +}
> > +
> > +static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
> > +     int trip_point, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int msr_raw, temp, config, d_index;
> > +     void __iomem *base;
>
>         void __iomem *base;
>         struct device *dev = lvts_data->dev;
>         unsigned int msr_raw, temp, config, d_index;
>
> or
>
>         unsigned int msr_raw, temp, config, d_index;
>         struct device *dev = lvts_data->dev;
>         void __iomem *base;
>
> Make it pretty - human readabilty is important.
> P.S.: I prefer the first option.
> P.P.S.: This is not the only instance!
>
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     d_index = get_dominator_index(lvts_data, tc_id);
> > +
> > +     dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);
>
> dev_dbg().
>
> > +
> > +     disable_hw_reboot_interrupt(lvts_data, tc_id);
> > +
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     if (d_index == ALL_SENSING_POINTS) {
> > +             /* Maximum of 4 sensing points */
> > +             config = (0x1 << 16);
> > +             writel(config | temp, LVTSPROTCTL_0 + base);
> > +     } else {
> > +             /* Select protection sensor */
> > +             config = ((d_index << 2) + 0x2) << 16;
> > +             writel(config | temp, LVTSPROTCTL_0 + base);
> > +     }
> > +
> > +     msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
> > +     writel(msr_raw, LVTSPROTTC_0 + base);
> > +
> > +     enable_hw_reboot_interrupt(lvts_data, tc_id);
> > +}
> > +
> > +static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     int i, trip_point;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             trip_point = tc[i].hw_reboot_trip_point;
> > +
> > +             if (tc[i].num_sensor == 0)
> > +                     continue;
> > +
> > +             if (trip_point == THERMAL_TEMP_INVALID)
> > +                     continue;
> > +
> > +             set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
> > +     }
> > +}
> > +
> > +static int lvts_init(struct lvts_data *lvts_data)
> > +{
> > +     struct platform_ops *ops = &lvts_data->ops;
> > +     struct device *dev = lvts_data->dev;
> > +     int ret;
> > +
> > +     ret = clk_prepare_enable(lvts_data->clk);
> > +     if (ret) {
> > +             dev_err(dev,
> > +                     "Error: Failed to enable lvts controller clock: %d\n",
> > +                     ret);
>
> This should be:
>                 dev_err(dev, "Failed to enable lvts controller clock: %d\n", ret);
>
> (or return dev_err_probe()).
>
> > +             return ret;
> > +     }
> > +
> > +     lvts_reset(lvts_data);
> > +
> > +     device_identification(lvts_data);
> > +     if (ops->device_enable_and_init)
> > +             ops->device_enable_and_init(lvts_data);
> > +
> > +     if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
> > +             if (ops->device_enable_auto_rck)
> > +                     ops->device_enable_auto_rck(lvts_data);
> > +     } else {
> > +             if (ops->device_read_count_rc_n)
> > +                     ops->device_read_count_rc_n(lvts_data);
> > +     }
>
>         if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK) && ops....)
>                 ops....
>         else if (ops.....)
>                 ops.....
>
> > +
> > +     if (ops->set_cal_data)
> > +             ops->set_cal_data(lvts_data);
> > +
> > +     disable_all_sensing_points(lvts_data);
> > +     wait_all_tc_sensing_point_idle(lvts_data);
> > +     if (ops->init_controller)
> > +             ops->init_controller(lvts_data);
> > +     enable_all_sensing_points(lvts_data);
> > +
> > +     set_all_tc_hw_reboot(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +static int prepare_calibration_data(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     struct platform_ops *ops = &lvts_data->ops;
> > +     int i, offset;
> > +     char buffer[512];
> > +
> > +     cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_r), GFP_KERNEL);
> > +     if (!cal_data->count_r)
> > +             return -ENOMEM;
> > +
> > +     cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_rc), GFP_KERNEL);
> > +     if (!cal_data->count_rc)
> > +             return -ENOMEM;
> > +
> > +     if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
> > +             ops->efuse_to_cal_data(lvts_data);
> > +     if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
> > +             cal_data->use_fake_efuse = 1;
> > +
> > +     if (cal_data->use_fake_efuse) {
> > +             /* It means all efuse data are equal to 0 */
> > +             dev_err(dev,
> > +                     "%s: This sample is not calibrated, fake !!\n", __func__);
> > +
> > +             cal_data->golden_temp = cal_data->default_golden_temp;
> > +             for (i = 0; i < lvts_data->num_sensor; i++) {
> > +                     cal_data->count_r[i] = cal_data->default_count_r;
> > +                     cal_data->count_rc[i] = cal_data->default_count_rc;
> > +             }
> > +     }
> > +
> > +     lvts_data->coeff.golden_temp = cal_data->golden_temp;
> > +
> > +     dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
> > +
> > +     offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
> > +     for (i = 0; i < lvts_data->num_sensor; i++)
> > +             offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
> > +                     i, cal_data->count_r[i], cal_data->count_rc[i]);
> > +
> > +     buffer[offset] = '\0';
>
> What is this string for?
> You're formatting it but never using, what's the point?
>
> > +
> > +     return 0;
> > +}
> > +
> > +static int get_calibration_data(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     char cell_name[32];
> > +     struct nvmem_cell *cell;
> > +     u32 *buf;
> > +     size_t len;
> > +     int i, j, index = 0, ret;
> > +
> > +     lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
> > +                                     sizeof(*lvts_data->efuse), GFP_KERNEL);
> > +     if (!lvts_data->efuse)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_efuse_block; i++) {
> > +             snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
> > +             cell = nvmem_cell_get(dev, cell_name);
> > +             if (IS_ERR(cell)) {
> > +                     dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
> > +                     return PTR_ERR(cell);
> > +             }
> > +
> > +             buf = (u32 *)nvmem_cell_read(cell, &len);
> > +             nvmem_cell_put(cell);
> > +
> > +             if (IS_ERR(buf))
> > +                     return PTR_ERR(buf);
> > +
> > +             for (j = 0; j < (len / sizeof(u32)); j++) {
> > +                     if (index >= lvts_data->num_efuse_addr) {
> > +                             dev_err(dev, "Array efuse is going to overflow");
> > +                             kfree(buf);
> > +                             return -EINVAL;
>
> If we get an error here, you should free all of the allocated buffers, which means
> that you have to walk back from i to 0 and kfree everything, or this is going to be
> a (relatively) big memory leak.
>

I need a better explanation here, please.
I couldn't see how the memory leak will happen.

> > +                     }
> > +
> > +                     lvts_data->efuse[index] = buf[j];
> > +                     index++;
> > +             }
> > +
> > +             kfree(buf);
> > +     }
> > +
> > +     ret = prepare_calibration_data(lvts_data);
> > +
> > +     return ret;
> > +}
> > +
> > +static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int i, j, s_index;
> > +     void __iomem *base;
> > +
> > +     lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*lvts_data->reg), GFP_KERNEL);
> > +     if (!lvts_data->reg)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +                     lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int of_update_lvts_data(struct lvts_data *lvts_data,
> > +     struct platform_device *pdev)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct resource *res;
> > +     int ret;
> > +
> > +     lvts_data->clk = devm_clk_get(dev, NULL);
> > +     if (IS_ERR(lvts_data->clk))
> > +             return PTR_ERR(lvts_data->clk);
> > +
> > +     /* Get base address */
> > +     res = platform_get_mem_or_io(pdev, 0);
> > +     if (!res) {
> > +             dev_err(dev, "No IO resource\n");
> > +             return -ENXIO;
> > +     }
> > +
> > +     lvts_data->base = devm_ioremap_resource(dev, res);
> > +     if (IS_ERR(lvts_data->base)) {
> > +             dev_err(dev, "Failed to remap io\n");
> > +             return PTR_ERR(lvts_data->base);
> > +     }
> > +
> > +     /* Get interrupt number */
> > +     ret = platform_get_irq(pdev, 0);
> > +     if (ret < 0) {
> > +             dev_err(dev, "No irq resource\n");
> > +             return -EINVAL;
>
> Why are you overriding the return value? return ret here.
>
> > +     }
> > +     lvts_data->irq_num = ret;
> > +
> > +     /* Get reset control */
> > +     lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
> > +     if (IS_ERR(lvts_data->reset)) {
> > +             dev_err(dev, "Failed to get reset control\n");
> > +             return PTR_ERR(lvts_data->reset);
> > +     }
> > +
> > +     ret = lvts_init_tc_regs(dev, lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = get_calibration_data(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
>
> ..snip..
>
> > +
> > +static irqreturn_t irq_handler(int irq, void *dev_id)
> > +{
> > +     struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int i, *irq_bitmap;
> > +     void __iomem *base;
> > +
> > +     irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
> > +
>
> You're using this for debugging only? Also, why wasn't this stack-allocated?
>
> Just remove it.
>
> > +     if (!irq_bitmap)
> > +             return IRQ_NONE;
> > +
> > +     base = lvts_data->base;
> > +     *irq_bitmap = readl(THERMINTST + base);
> > +     dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             if (tc[i].irq_bit == 0)
> > +                     tc_irq_handler(lvts_data, i);
> > +     }
> > +
> > +     kfree(irq_bitmap);
> > +
> > +     return IRQ_HANDLED;
> > +}
> > +
> > +static int lvts_register_irq_handler(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     int ret;
> > +
> > +     ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
> > +             IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);
>
> Interrupt flags are specified in devicetree: why are you forcing TRIGGER_HIGH here?
>
> > +
> > +     if (ret) {
> > +             dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
> > +                     ret, lvts_data->irq_num);
> > +             lvts_close(lvts_data);
> > +             return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct thermal_zone_device *tzdev;
> > +     struct soc_temp_tz *lvts_tz;
> > +     int i, ret;
> > +
> > +     for (i = 0; i < lvts_data->num_sensor; i++) {
> > +             lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
> > +             if (!lvts_tz) {
> > +                     lvts_close(lvts_data);
> > +                     return -ENOMEM;
> > +             }
> > +
> > +             lvts_tz->id = i;
> > +             lvts_tz->lvts_data = lvts_data;
> > +
> > +             tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
> > +                     lvts_tz, &soc_temp_lvts_ops);
> > +
> > +             if (IS_ERR(tzdev)) {
> > +                     if (lvts_tz->id != 0)
> > +                             return 0;
> > +
> > +                     ret = PTR_ERR(tzdev);
> > +                     dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",
>
> s/Error: //g - here and everywhere else: a dev_err() *is* an error print.
>
> > +                             lvts_tz->id, ret);
> > +                     lvts_close(lvts_data);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
>
> ..snip..
>
> > +
> > +int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
> > +{
> > +     /* Resistor-Capacitor Calibration */
> > +     /* count_RC_N: count RC now */
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int offset, size, s_index, data;
> > +     void __iomem *base;
> > +     int ret, i, j;
> > +     char buffer[512];
>
> I don't think that you need this buffer to be that long and I'm sure that its
> size can be reduced.
> I didn't check how much you need, but I'm guessing that you need less than a
> quarter of that size.
>
> > +
> > +     cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_rc_now), GFP_KERNEL);
> > +     if (!cal_data->count_rc_now)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +
> > +                     lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
> > +                     lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
> > +                     usleep_range(10, 20);
> > +
> > +                     lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
> > +                     usleep_range(30, 40);
> > +
> > +                     ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> > +                                              !(data & DEVICE_SENSING_STATUS), 2, 200);
> > +                     if (ret)
> > +                             dev_err(dev,
> > +                                     "Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
> > +
> > +                     data = lvts_read_device(lvts_data, 0x00, i);
> > +
> > +                     cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));
>
> No magic GENMASK() or BIT() please, add a definition for readability.
>
> > +             }
> > +
> > +             /* Recover Setting for Normal Access on
> > +              * temperature fetch
> > +              */
> > +             lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
> > +             lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> > +     }
> > +
> > +     size = sizeof(buffer);
> > +     offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
> > +     for (i = 0; i < lvts_data->num_sensor; i++)
> > +             offset += snprintf(buffer + offset, size - offset, "%d:%d ",
> > +                     i, cal_data->count_rc_now[i]);
> > +
> > +     buffer[offset] = '\0';
> > +     dev_dbg(dev, "%s\n", buffer);
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
> > +
> > +void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int i, j, s_index, lvts_calib_data;
> > +     void __iomem *base;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +                     if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
> > +                             lvts_calib_data = cal_data->count_r[s_index];
> > +                     else
> > +                             lvts_calib_data = (((unsigned long long)
>
> lvts_calib_data is unsigned int. You're assigning unsigned long long here.
>
> Also, since this is register-size bound, use fixed size types.
>
> > +                                     cal_data->count_rc_now[s_index]) *
> > +                                     cal_data->count_r[s_index]) >> 14;
> > +
> > +                     writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
> > +             }
> > +     }
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
> > +
> > +void lvts_init_controller_v4(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int i;
> > +     void __iomem *base;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +
> > +             lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> > +
> > +             writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
> > +             writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
> > +
> > +             set_polling_speed(lvts_data, i);
> > +             set_hw_filter(lvts_data, i);
> > +
> > +             dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
> > +                     i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));
>
> dev_dbg().
>
> > +     }
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
> > +
> > +int lvts_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct lvts_data *lvts_data;
> > +     int ret;
> > +
> > +     lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
> > +
> > +     if (!lvts_data) {
> > +             dev_err(dev, "Error: Failed to get lvts platform data\n");
> > +             return -ENODATA;
> > +     }
> > +
> > +     lvts_data->dev = &pdev->dev;
> > +
> > +     ret = of_update_lvts_data(lvts_data, pdev);
> > +     if (ret)
> > +             return ret;
> > +
> > +     platform_set_drvdata(pdev, lvts_data);
> > +
> > +     ret = lvts_init(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = lvts_register_irq_handler(lvts_data);
> > +     if (ret)
> > +             return ret;
>
> If anything goes wrong here, you're leaving the lvts_data->clk clock enabled.
> Please fix.

"lvts_close(lvts_data)" is called just before "return ret" which in
turn calls "clk_disable_unprepare(lvts_data->clk)".
Please let me know if I misunderstood the comment.

>
> > +
> > +     ret = lvts_register_thermal_zones(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_remove(struct platform_device *pdev)
> > +{
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     lvts_close(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     lvts_close(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_resume(struct platform_device *pdev)
> > +{
> > +     int ret;
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     ret = lvts_init(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
> > +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> > +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> > +MODULE_LICENSE("GPL v2");
>
> Regards,
> Angelo

Thank you Angelo for the review.

Most of the changes are done.
Resubmitting very soon.

Best regards.
Balsam.

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
@ 2022-07-29 15:38       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-07-29 15:38 UTC (permalink / raw)
  To: AngeloGioacchino Del Regno
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Wed, Jul 27, 2022 at 11:24 AM AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com> wrote:
>
> Il 26/07/22 15:55, Balsam CHIHI ha scritto:
> > Add a LVTS (Low voltage thermal sensor) driver to report junction
> > temperatures in Mediatek SoC mt8192 and register the maximum temperature
> > of sensors and each sensor as a thermal zone.
> >
> > Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> > Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> > Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
>
> Hello Balsam,
>
> there are a few comments on this patch.
>
> First of all, can you please fix the typo that you have in the commit title?
> theraml -> thermal
>
> ...then, please, the commit description:
> Add a LVTS (Low Voltage Thermal Sensor) <- capitalize
>
> and
>
> Mediatek -> MediaTek
>
> > ---
> >   drivers/thermal/mediatek/Kconfig         |  27 +
> >   drivers/thermal/mediatek/Makefile        |   2 +
> >   drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
> >   drivers/thermal/mediatek/soc_temp.c      |   2 +-
> >   drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
> >   drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
> >   6 files changed, 1564 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
> >   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
> >   create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> >
> > diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> > index 9c41e9079fc3..7fc04237dd50 100644
> > --- a/drivers/thermal/mediatek/Kconfig
> > +++ b/drivers/thermal/mediatek/Kconfig
> > @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
> >               configures thermal controllers to collect temperature
> >               via AUXADC interface.
> >
> > +config MTK_SOC_THERMAL_LVTS
> > +     tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> > +     depends on HAS_IOMEM
> > +     depends on NVMEM
> > +     depends on RESET_TI_SYSCON
> > +     help
> > +             Enable this option if you want to get SoC temperature
> > +             information for MediaTek platforms. This driver
> > +             configures LVTS thermal controllers to collect temperatures
> > +             via Analog Serial Interface(ASIF).
>
> Fix the indentation, please:
>
>         help
>           Enable this option.......
> (\t<space><space>)
>
>
>
> > +
> > +endif
> > +
> > +if MTK_SOC_THERMAL_LVTS
> > +
> > +config LVTS_MT8192
> > +     tristate "LVTS driver for MediaTek MT8192 SoC"
> > +     depends on HAS_IOMEM
> > +     depends on NVMEM
> > +     depends on RESET_TI_SYSCON
> > +     depends on MTK_SOC_THERMAL_LVTS
> > +     help
> > +             Enable this option if you want to get SoC temperature
> > +             information for MT8192. This driver
> > +             configures LVTS thermal controllers to collect temperatures
> > +             via ASIF.
> > +
> >   endif
> > diff --git a/drivers/thermal/mediatek/Makefile b/drivers/thermal/mediatek/Makefile
> > index 4b4cb04a358f..5ff1197e80ab 100644
> > --- a/drivers/thermal/mediatek/Makefile
> > +++ b/drivers/thermal/mediatek/Makefile
> > @@ -1 +1,3 @@
> >   obj-$(CONFIG_MTK_SOC_THERMAL)               += soc_temp.o
> > +obj-$(CONFIG_MTK_SOC_THERMAL_LVTS)   += soc_temp_lvts.o
> > +obj-$(CONFIG_LVTS_MT8192)                    += lvts_mt8192.o
> > diff --git a/drivers/thermal/mediatek/lvts_mt8192.c b/drivers/thermal/mediatek/lvts_mt8192.c
> > new file mode 100644
> > index 000000000000..19e4e82c410b
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/lvts_mt8192.c
> > @@ -0,0 +1,241 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2022 MediaTek Inc.
> > + */
> > +
> > +#include <linux/of_irq.h>
> > +#include <linux/platform_device.h>
> > +#include "soc_temp_lvts.h"
> > +
> > +enum mt8192_lvts_mcu_sensor_enum {
> > +     MT8192_TS1_0,
> > +     MT8192_TS1_1,
> > +     MT8192_TS2_0,
> > +     MT8192_TS2_1,
> > +     MT8192_TS3_0,
> > +     MT8192_TS3_1,
> > +     MT8192_TS3_2,
> > +     MT8192_TS3_3,
> > +     MT8192_NUM_TS_MCU
> > +};
> > +
> > +enum mt8192_lvts_ap_sensor_enum {
> > +     MT8192_TS4_0,
> > +     MT8192_TS4_1,
> > +     MT8192_TS5_0,
> > +     MT8192_TS5_1,
> > +     MT8192_TS6_0,
> > +     MT8192_TS6_1,
> > +     MT8192_TS7_0,
> > +     MT8192_TS7_1,
> > +     MT8192_TS7_2,
> > +     MT8192_NUM_TS_AP
> > +};
> > +
> > +static void mt8192_mcu_efuse_to_cal_data(struct lvts_data *lvts_data)
> > +{
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int i, j;
> > +     const unsigned int mt8192_TS[] = {MT8192_TS2_0, MT8192_TS3_0};
>
>
> Please fix and reorder (here and for any other instance):
>
>         const unsigned int mt8192_ts[] = { MT8192_TS2_0, MT8192_TS3_0 };
>         struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
>         unsigned int i, j;
>
> > +
> > +     cal_data->golden_temp = GET_CAL_DATA_BITMASK(0, lvts_data, 31, 24);
> > +
> > +     for (i = 0; i < MT8192_NUM_TS_MCU; i++)
> > +             cal_data->count_r[i] = GET_CAL_DATA_BITMASK(i + 1, lvts_data, 23, 0);
> > +
> > +     cal_data->count_rc[MT8192_TS1_0] = GET_CAL_DATA_BITMASK(21, lvts_data, 23, 0);
>
> ..snip..
>
> > +
> > +static const struct lvts_tc_settings mt8192_tc_mcu_settings[] = {
> > +     [0] = {
> > +             .dev_id = 0x81,
> > +             .addr_offset = 0x0,
> > +             .num_sensor = 2,
> > +             .sensor_map = {MT8192_TS1_0, MT8192_TS1_1},
>
> Please, leave a space after opening and before closing the braces.
>
> > +             .tc_speed = &tc_speed_mt8192,
> > +             .hw_filter = LVTS_FILTER_2_OF_4,
> > +             .dominator_sensing_point = SENSING_POINT1,
> > +             .hw_reboot_trip_point = HW_REBOOT_TRIP_POINT,
> > +             .irq_bit = BIT(3),
> > +     },
>
> ..snip..
>
> > +
> > +static const struct lvts_data mt8192_lvts_ap_data = {
> > +     .num_tc = (ARRAY_SIZE(mt8192_tc_ap_settings)),
> > +     .tc = mt8192_tc_ap_settings,
> > +     .num_sensor = MT8192_NUM_TS_AP,
> > +     .ops = {
> > +             .efuse_to_cal_data = mt8192_ap_efuse_to_cal_data,
> > +             .device_enable_and_init = lvts_device_enable_and_init_v4,
> > +             .device_enable_auto_rck = lvts_device_enable_auto_rck_v4,
> > +             .device_read_count_rc_n = lvts_device_read_count_rc_n_v4,
> > +             .set_cal_data = lvts_set_calibration_data_v4,
> > +             .init_controller = lvts_init_controller_v4,
> > +     },
> > +     .feature_bitmap = FEATURE_DEVICE_AUTO_RCK,
> > +     .num_efuse_addr = NUM_EFUSE_ADDR,
> > +     .num_efuse_block = NUM_EFUSE_BLOCK_MT8192,
> > +     .cal_data = {
> > +             .default_golden_temp = DEFAULT_GOLDEN_TEMP,
> > +             .default_count_r = DEFAULT_CUONT_R,
> > +             .default_count_rc = DEFAULT_CUONT_RC,
> > +     },
> > +     .coeff = {
> > +             .a = COEFF_A,
> > +             .b = COEFF_B,
> > +     },
> > +};
> > +
> > +static const struct of_device_id lvts_of_match[] = {
>
> I don't like having one driver per SoC, where we have only two specific functions.
>
> I suggest to either:
> - Remove the static word from mt8192_lvts_ap_data and put the of_match
>    in soc_temp_lvts.c; or
> - Separate the SoCs by LVTS version: create a lvts_v4.c where we group all
>    of the V4 SoCs (so, currently, MT8192 and MT8195): this will allow us to
>    eventually get a lvts_v3, lvts_v2, etc, where we group other SoCs.
>
> I prefer the second way, as MediaTek has a lot of SoCs and I can see this list
> growing a lot when these will be (hopefully) upstreamed.
>
>
>
> > +     { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data, },
> > +     { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data, },
> > +     {},
> > +};
> > +MODULE_DEVICE_TABLE(of, lvts_of_match);
> > +
> > +static struct platform_driver soc_temp_lvts = {
> > +     .probe = lvts_probe,
> > +     .remove = lvts_remove,
> > +     .suspend = lvts_suspend,
> > +     .resume = lvts_resume,
> > +     .driver = {
> > +             .name = "mtk-soc-temp-lvts-mt8192",
> > +             .of_match_table = lvts_of_match,
> > +     },
> > +};
> > +module_platform_driver(soc_temp_lvts);
> > +
> > +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> > +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> > +MODULE_LICENSE("GPL v2");
>
> You should run checkpatch.pl. Please.
>
> > diff --git a/drivers/thermal/mediatek/soc_temp.c b/drivers/thermal/mediatek/soc_temp.c
> > index ede94eadddda..60924f8f98e9 100644
> > --- a/drivers/thermal/mediatek/soc_temp.c
> > +++ b/drivers/thermal/mediatek/soc_temp.c
> > @@ -23,7 +23,7 @@
> >   #include <linux/reset.h>
> >   #include <linux/types.h>
> >
> > -#include "thermal_hwmon.h"
> > +#include "../thermal_hwmon.h"
>
> This change doesn't belong to this commit.
>
> >
> >   /* AUXADC Registers */
> >   #define AUXADC_CON1_SET_V   0x008
> > diff --git a/drivers/thermal/mediatek/soc_temp_lvts.c b/drivers/thermal/mediatek/soc_temp_lvts.c
> > new file mode 100644
> > index 000000000000..ee7efc0de65f
> > --- /dev/null
> > +++ b/drivers/thermal/mediatek/soc_temp_lvts.c
> > @@ -0,0 +1,928 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2022 MediaTek Inc.
> > + */
> > +
> > +#include <linux/bits.h>
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/iopoll.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/nvmem-consumer.h>
> > +#include <linux/of.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/slab.h>
> > +#include <linux/string.h>
> > +#include <linux/thermal.h>
> > +#include "soc_temp_lvts.h"
> > +
> > +static int lvts_raw_to_temp(struct lvts_formula_coeff *co, unsigned int msr_raw)
> > +{
> > +     /* This function returns degree mC */
> > +
> > +     int temp;
> > +
> > +     temp = (co->a * ((unsigned long long)msr_raw)) >> 14;
> > +     temp = temp + co->golden_temp * 500 + co->b;
> > +
> > +     return temp;
> > +}
> > +
> > +static unsigned int lvts_temp_to_raw(struct lvts_formula_coeff *co, int temp)
> > +{
> > +     unsigned int msr_raw;
> > +
> > +     msr_raw = div_s64((s64)((co->golden_temp * 500 + co->b - temp)) << 14,
> > +             (-1 * co->a));
> > +
> > +     return msr_raw;
> > +}
> > +
> > +static int soc_temp_lvts_read_temp(void *data, int *temperature)
> > +{
> > +     struct soc_temp_tz *lvts_tz = (struct soc_temp_tz *)data;
> > +     struct lvts_data *lvts_data = lvts_tz->lvts_data;
> > +     unsigned int msr_raw;
> > +
> > +     msr_raw = readl(lvts_data->reg[lvts_tz->id]) & MRS_RAW_MASK;
> > +     if (msr_raw == 0)
> > +             return -EINVAL;
> > +
> > +     *temperature = lvts_raw_to_temp(&lvts_data->coeff, msr_raw);
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct thermal_zone_of_device_ops soc_temp_lvts_ops = {
> > +     .get_temp = soc_temp_lvts_read_temp,
> > +};
> > +
> > +static void lvts_write_device(struct lvts_data *lvts_data, unsigned int data,
> > +     int tc_id)
> > +{
> > +     void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     writel(DEVICE_WRITE | data, LVTS_CONFIG_0 + base);
> > +
> > +     usleep_range(5, 15);
> > +}
> > +
> > +static unsigned int lvts_read_device(struct lvts_data *lvts_data,
> > +     unsigned int reg_idx, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     void __iomem *base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     unsigned int data;
> > +     int ret;
> > +
> > +     writel(READ_DEVICE_REG(reg_idx), LVTS_CONFIG_0 + base);
> > +
> > +     usleep_range(5, 15);
> > +
> > +     ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> > +             !(data & DEVICE_ACCESS_STARTUS), 2, 200);
> > +     if (ret)
> > +             dev_err(dev,
> > +                     "Error: LVTS %d DEVICE_ACCESS_START is not ready\n", tc_id);
> > +
> > +     data = readl(LVTSRDATA0_0 + base);
> > +
> > +     return data;
> > +}
> > +
> > +static const char * const lvts_error_table[] = {"IDLE", "Write transaction",
> > +     "Waiting for read after Write", "Disable Continue fetching on Device",
> > +     "Read transaction", "Set Device special Register for Voltage threshold",
> > +     "Set TSMCU number for Fetch"};
>
> In my opinion, that's unreadable.
>
> static const char * const lvts_error_table[] = {
>
>         "Idle",
>
>         "Write transaction",
>
>         "Waiting for read after write",
>
>         "Disable continue fetching on device",
>
>         "Read transaction",
>
>         "Set device special register for voltage threshold",
>
>         "Set TSMCU number for fetch"
>
> };
>
> ...but like this, it's way more readable.
>
>
> > +
> > +static void wait_all_tc_sensing_point_idle(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int mask, error_code, is_error;
> > +     void __iomem *base;
> > +     int i, cnt, ret;
> > +
> > +     mask = BIT(10) | BIT(7) | BIT(0);
>
> What are these magic bits?
> Please add definitions.
>
> > +
> > +     for (cnt = 0; cnt < 2; cnt++) {
> > +             is_error = 0;
> > +             for (i = 0; i < lvts_data->num_tc; i++) {
> > +                     base = GET_BASE_ADDR(lvts_data, i);
> > +                     ret = readl_poll_timeout(LVTSMSRCTL1_0 + base, error_code,
> > +                                              !(error_code & mask), 2, 200);
> > +
> > +                     error_code = ((error_code & BIT(10)) >> 8) +
> > +                             ((error_code & BIT(7)) >> 6) +
> > +                             (error_code & BIT(0));
> > +
> > +                     if (ret)
> > +                             dev_err(dev, "LVTS %d error: %s\n",
> > +                                     i, lvts_error_table[error_code]);
> > +
> > +                     if (error_code != 0)
> > +                             is_error = 1;
> > +             }
> > +
> > +             if (is_error == 0)
> > +                     break;
> > +     }
> > +}
> > +
>
> ...snip...
>
> > +static void set_hw_filter(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int option;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     option = tc[tc_id].hw_filter & 0x7;
> > +     /*
> > +      * hw filter
> > +      * 000: Get one sample
> > +      * 001: Get 2 samples and average them
> > +      * 010: Get 4 samples, drop max and min, then average the rest of 2 samples
> > +      * 011: Get 6 samples, drop max and min, then average the rest of 4 samples
> > +      * 100: Get 10 samples, drop max and min, then average the rest of 8 samples
> > +      * 101: Get 18 samples, drop max and min, then average the rest of 16 samples
> > +      */
> > +     option = (option << 9) | (option << 6) | (option << 3) | option;
> > +
> > +     writel(option, LVTSMSRCTL0_0 + base);
> > +     dev_dbg(dev, "LVTS_TC_%d, LVTSMSRCTL0_0= 0x%x\n",
> > +              tc_id, readl(LVTSMSRCTL0_0 + base));
> > +}
> > +
> > +static int get_dominator_index(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     int d_index;
> > +
> > +     if (tc[tc_id].dominator_sensing_point == ALL_SENSING_POINTS) {
> > +             d_index = ALL_SENSING_POINTS;
> > +     } else if (tc[tc_id].dominator_sensing_point <
> > +             tc[tc_id].num_sensor){
>
> There's no reason to break this line.
>
> > +             d_index = tc[tc_id].dominator_sensing_point;
> > +     } else {
> > +             dev_err(dev,
> > +                     "Error: LVTS%d, dominator_sensing_point= %d should smaller than num_sensor= %d\n",
>
> "Error:" is unneeded, as this is a dev_err, so it's definitely an error.
> Also, s/should/shall be/g
>
> > +                     tc_id, tc[tc_id].dominator_sensing_point,
> > +                     tc[tc_id].num_sensor);
> > +
> > +             dev_err(dev, "Use the sensing point 0 as the dominated sensor\n");
> > +             d_index = SENSING_POINT0;
> > +     }
> > +
> > +     return d_index;
> > +}
> > +
> > +static void disable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     unsigned int temp;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     /*
> > +      * LVTS thermal controller has two interrupts for thermal HW reboot
> > +      * One is for AP SW and the other is for RGU
> > +      * The interrupt of AP SW can turn off by a bit of a register, but
> > +      * the other for RGU cannot.
> > +      * To prevent rebooting device accidentally, we are going to add
> > +      * a huge offset to LVTS and make LVTS always report extremely low
> > +      * temperature.
> > +      */
> > +
> > +     /*
> > +      * After adding the huge offset 0x3FFF, LVTS alawys adds the
>
> s/alawys/always/g
>
> > +      * offset to MSR_RAW.
> > +      * When MSR_RAW is larger, SW will convert lower temperature/
> > +      */
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     writel(temp | 0x3FFF, LVTSPROTCTL_0 + base);
> > +
> > +     /* Disable the interrupt of AP SW */
> > +     temp = readl(LVTSMONINT_0 + base);
> > +     writel(temp & ~(STAGE3_INT_EN), LVTSMONINT_0 + base);
> > +}
> > +
> > +static void enable_hw_reboot_interrupt(struct lvts_data *lvts_data, int tc_id)
> > +{
> > +     unsigned int temp;
> > +     void __iomem *base;
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +
> > +     /* Enable the interrupt of AP SW */
> > +     temp = readl(LVTSMONINT_0 + base);
> > +     writel(temp | STAGE3_INT_EN, LVTSMONINT_0 + base);
> > +     /* Clear the offset */
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     writel(temp & ~PROTOFFSET, LVTSPROTCTL_0 + base);
> > +}
> > +
> > +static void set_tc_hw_reboot_threshold(struct lvts_data *lvts_data,
> > +     int trip_point, int tc_id)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int msr_raw, temp, config, d_index;
> > +     void __iomem *base;
>
>         void __iomem *base;
>         struct device *dev = lvts_data->dev;
>         unsigned int msr_raw, temp, config, d_index;
>
> or
>
>         unsigned int msr_raw, temp, config, d_index;
>         struct device *dev = lvts_data->dev;
>         void __iomem *base;
>
> Make it pretty - human readabilty is important.
> P.S.: I prefer the first option.
> P.P.S.: This is not the only instance!
>
> > +
> > +     base = GET_BASE_ADDR(lvts_data, tc_id);
> > +     d_index = get_dominator_index(lvts_data, tc_id);
> > +
> > +     dev_info(dev, "lvts_tc_%d: dominator sensing point = %d\n", tc_id, d_index);
>
> dev_dbg().
>
> > +
> > +     disable_hw_reboot_interrupt(lvts_data, tc_id);
> > +
> > +     temp = readl(LVTSPROTCTL_0 + base);
> > +     if (d_index == ALL_SENSING_POINTS) {
> > +             /* Maximum of 4 sensing points */
> > +             config = (0x1 << 16);
> > +             writel(config | temp, LVTSPROTCTL_0 + base);
> > +     } else {
> > +             /* Select protection sensor */
> > +             config = ((d_index << 2) + 0x2) << 16;
> > +             writel(config | temp, LVTSPROTCTL_0 + base);
> > +     }
> > +
> > +     msr_raw = lvts_temp_to_raw(&lvts_data->coeff, trip_point);
> > +     writel(msr_raw, LVTSPROTTC_0 + base);
> > +
> > +     enable_hw_reboot_interrupt(lvts_data, tc_id);
> > +}
> > +
> > +static void set_all_tc_hw_reboot(struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     int i, trip_point;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             trip_point = tc[i].hw_reboot_trip_point;
> > +
> > +             if (tc[i].num_sensor == 0)
> > +                     continue;
> > +
> > +             if (trip_point == THERMAL_TEMP_INVALID)
> > +                     continue;
> > +
> > +             set_tc_hw_reboot_threshold(lvts_data, trip_point, i);
> > +     }
> > +}
> > +
> > +static int lvts_init(struct lvts_data *lvts_data)
> > +{
> > +     struct platform_ops *ops = &lvts_data->ops;
> > +     struct device *dev = lvts_data->dev;
> > +     int ret;
> > +
> > +     ret = clk_prepare_enable(lvts_data->clk);
> > +     if (ret) {
> > +             dev_err(dev,
> > +                     "Error: Failed to enable lvts controller clock: %d\n",
> > +                     ret);
>
> This should be:
>                 dev_err(dev, "Failed to enable lvts controller clock: %d\n", ret);
>
> (or return dev_err_probe()).
>
> > +             return ret;
> > +     }
> > +
> > +     lvts_reset(lvts_data);
> > +
> > +     device_identification(lvts_data);
> > +     if (ops->device_enable_and_init)
> > +             ops->device_enable_and_init(lvts_data);
> > +
> > +     if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK)) {
> > +             if (ops->device_enable_auto_rck)
> > +                     ops->device_enable_auto_rck(lvts_data);
> > +     } else {
> > +             if (ops->device_read_count_rc_n)
> > +                     ops->device_read_count_rc_n(lvts_data);
> > +     }
>
>         if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK) && ops....)
>                 ops....
>         else if (ops.....)
>                 ops.....
>
> > +
> > +     if (ops->set_cal_data)
> > +             ops->set_cal_data(lvts_data);
> > +
> > +     disable_all_sensing_points(lvts_data);
> > +     wait_all_tc_sensing_point_idle(lvts_data);
> > +     if (ops->init_controller)
> > +             ops->init_controller(lvts_data);
> > +     enable_all_sensing_points(lvts_data);
> > +
> > +     set_all_tc_hw_reboot(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +static int prepare_calibration_data(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     struct platform_ops *ops = &lvts_data->ops;
> > +     int i, offset;
> > +     char buffer[512];
> > +
> > +     cal_data->count_r = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_r), GFP_KERNEL);
> > +     if (!cal_data->count_r)
> > +             return -ENOMEM;
> > +
> > +     cal_data->count_rc = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_rc), GFP_KERNEL);
> > +     if (!cal_data->count_rc)
> > +             return -ENOMEM;
> > +
> > +     if (ops->efuse_to_cal_data && !cal_data->use_fake_efuse)
> > +             ops->efuse_to_cal_data(lvts_data);
> > +     if (cal_data->golden_temp == 0 || cal_data->golden_temp > GOLDEN_TEMP_MAX)
> > +             cal_data->use_fake_efuse = 1;
> > +
> > +     if (cal_data->use_fake_efuse) {
> > +             /* It means all efuse data are equal to 0 */
> > +             dev_err(dev,
> > +                     "%s: This sample is not calibrated, fake !!\n", __func__);
> > +
> > +             cal_data->golden_temp = cal_data->default_golden_temp;
> > +             for (i = 0; i < lvts_data->num_sensor; i++) {
> > +                     cal_data->count_r[i] = cal_data->default_count_r;
> > +                     cal_data->count_rc[i] = cal_data->default_count_rc;
> > +             }
> > +     }
> > +
> > +     lvts_data->coeff.golden_temp = cal_data->golden_temp;
> > +
> > +     dev_dbg(dev, "golden_temp = %d\n", cal_data->golden_temp);
> > +
> > +     offset = snprintf(buffer, sizeof(buffer), "[lvts_cal] num:g_count:g_count_rc ");
> > +     for (i = 0; i < lvts_data->num_sensor; i++)
> > +             offset += snprintf(buffer + offset, sizeof(buffer) - offset, "%d:%d:%d ",
> > +                     i, cal_data->count_r[i], cal_data->count_rc[i]);
> > +
> > +     buffer[offset] = '\0';
>
> What is this string for?
> You're formatting it but never using, what's the point?
>
> > +
> > +     return 0;
> > +}
> > +
> > +static int get_calibration_data(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     char cell_name[32];
> > +     struct nvmem_cell *cell;
> > +     u32 *buf;
> > +     size_t len;
> > +     int i, j, index = 0, ret;
> > +
> > +     lvts_data->efuse = devm_kcalloc(dev, lvts_data->num_efuse_addr,
> > +                                     sizeof(*lvts_data->efuse), GFP_KERNEL);
> > +     if (!lvts_data->efuse)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_efuse_block; i++) {
> > +             snprintf(cell_name, sizeof(cell_name), "lvts_calib_data%d", i + 1);
> > +             cell = nvmem_cell_get(dev, cell_name);
> > +             if (IS_ERR(cell)) {
> > +                     dev_err(dev, "Error: Failed to get nvmem cell %s\n", cell_name);
> > +                     return PTR_ERR(cell);
> > +             }
> > +
> > +             buf = (u32 *)nvmem_cell_read(cell, &len);
> > +             nvmem_cell_put(cell);
> > +
> > +             if (IS_ERR(buf))
> > +                     return PTR_ERR(buf);
> > +
> > +             for (j = 0; j < (len / sizeof(u32)); j++) {
> > +                     if (index >= lvts_data->num_efuse_addr) {
> > +                             dev_err(dev, "Array efuse is going to overflow");
> > +                             kfree(buf);
> > +                             return -EINVAL;
>
> If we get an error here, you should free all of the allocated buffers, which means
> that you have to walk back from i to 0 and kfree everything, or this is going to be
> a (relatively) big memory leak.
>

I need a better explanation here, please.
I couldn't see how the memory leak will happen.

> > +                     }
> > +
> > +                     lvts_data->efuse[index] = buf[j];
> > +                     index++;
> > +             }
> > +
> > +             kfree(buf);
> > +     }
> > +
> > +     ret = prepare_calibration_data(lvts_data);
> > +
> > +     return ret;
> > +}
> > +
> > +static int lvts_init_tc_regs(struct device *dev, struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int i, j, s_index;
> > +     void __iomem *base;
> > +
> > +     lvts_data->reg = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*lvts_data->reg), GFP_KERNEL);
> > +     if (!lvts_data->reg)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +                     lvts_data->reg[s_index] = LVTSMSR0_0 + base + 0x4 * j;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int of_update_lvts_data(struct lvts_data *lvts_data,
> > +     struct platform_device *pdev)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct resource *res;
> > +     int ret;
> > +
> > +     lvts_data->clk = devm_clk_get(dev, NULL);
> > +     if (IS_ERR(lvts_data->clk))
> > +             return PTR_ERR(lvts_data->clk);
> > +
> > +     /* Get base address */
> > +     res = platform_get_mem_or_io(pdev, 0);
> > +     if (!res) {
> > +             dev_err(dev, "No IO resource\n");
> > +             return -ENXIO;
> > +     }
> > +
> > +     lvts_data->base = devm_ioremap_resource(dev, res);
> > +     if (IS_ERR(lvts_data->base)) {
> > +             dev_err(dev, "Failed to remap io\n");
> > +             return PTR_ERR(lvts_data->base);
> > +     }
> > +
> > +     /* Get interrupt number */
> > +     ret = platform_get_irq(pdev, 0);
> > +     if (ret < 0) {
> > +             dev_err(dev, "No irq resource\n");
> > +             return -EINVAL;
>
> Why are you overriding the return value? return ret here.
>
> > +     }
> > +     lvts_data->irq_num = ret;
> > +
> > +     /* Get reset control */
> > +     lvts_data->reset = devm_reset_control_get_by_index(dev, 0);
> > +     if (IS_ERR(lvts_data->reset)) {
> > +             dev_err(dev, "Failed to get reset control\n");
> > +             return PTR_ERR(lvts_data->reset);
> > +     }
> > +
> > +     ret = lvts_init_tc_regs(dev, lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = get_calibration_data(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
>
> ..snip..
>
> > +
> > +static irqreturn_t irq_handler(int irq, void *dev_id)
> > +{
> > +     struct lvts_data *lvts_data = (struct lvts_data *)dev_id;
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     unsigned int i, *irq_bitmap;
> > +     void __iomem *base;
> > +
> > +     irq_bitmap = kcalloc(1, sizeof(*irq_bitmap), GFP_ATOMIC);
> > +
>
> You're using this for debugging only? Also, why wasn't this stack-allocated?
>
> Just remove it.
>
> > +     if (!irq_bitmap)
> > +             return IRQ_NONE;
> > +
> > +     base = lvts_data->base;
> > +     *irq_bitmap = readl(THERMINTST + base);
> > +     dev_dbg(dev, "THERMINTST = 0x%x\n", *irq_bitmap);
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             if (tc[i].irq_bit == 0)
> > +                     tc_irq_handler(lvts_data, i);
> > +     }
> > +
> > +     kfree(irq_bitmap);
> > +
> > +     return IRQ_HANDLED;
> > +}
> > +
> > +static int lvts_register_irq_handler(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     int ret;
> > +
> > +     ret = devm_request_irq(dev, lvts_data->irq_num, irq_handler,
> > +             IRQF_TRIGGER_HIGH, "mtk_lvts", lvts_data);
>
> Interrupt flags are specified in devicetree: why are you forcing TRIGGER_HIGH here?
>
> > +
> > +     if (ret) {
> > +             dev_err(dev, "Failed to register LVTS IRQ, ret %d, irq_num %d\n",
> > +                     ret, lvts_data->irq_num);
> > +             lvts_close(lvts_data);
> > +             return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static int lvts_register_thermal_zones(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     struct thermal_zone_device *tzdev;
> > +     struct soc_temp_tz *lvts_tz;
> > +     int i, ret;
> > +
> > +     for (i = 0; i < lvts_data->num_sensor; i++) {
> > +             lvts_tz = devm_kzalloc(dev, sizeof(*lvts_tz), GFP_KERNEL);
> > +             if (!lvts_tz) {
> > +                     lvts_close(lvts_data);
> > +                     return -ENOMEM;
> > +             }
> > +
> > +             lvts_tz->id = i;
> > +             lvts_tz->lvts_data = lvts_data;
> > +
> > +             tzdev = devm_thermal_zone_of_sensor_register(dev, lvts_tz->id,
> > +                     lvts_tz, &soc_temp_lvts_ops);
> > +
> > +             if (IS_ERR(tzdev)) {
> > +                     if (lvts_tz->id != 0)
> > +                             return 0;
> > +
> > +                     ret = PTR_ERR(tzdev);
> > +                     dev_err(dev, "Error: Failed to register lvts tz %d, ret = %d\n",
>
> s/Error: //g - here and everywhere else: a dev_err() *is* an error print.
>
> > +                             lvts_tz->id, ret);
> > +                     lvts_close(lvts_data);
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
>
> ..snip..
>
> > +
> > +int lvts_device_read_count_rc_n_v4(struct lvts_data *lvts_data)
> > +{
> > +     /* Resistor-Capacitor Calibration */
> > +     /* count_RC_N: count RC now */
> > +     struct device *dev = lvts_data->dev;
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int offset, size, s_index, data;
> > +     void __iomem *base;
> > +     int ret, i, j;
> > +     char buffer[512];
>
> I don't think that you need this buffer to be that long and I'm sure that its
> size can be reduced.
> I didn't check how much you need, but I'm guessing that you need less than a
> quarter of that size.
>
> > +
> > +     cal_data->count_rc_now = devm_kcalloc(dev, lvts_data->num_sensor,
> > +             sizeof(*cal_data->count_rc_now), GFP_KERNEL);
> > +     if (!cal_data->count_rc_now)
> > +             return -ENOMEM;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +
> > +                     lvts_write_device(lvts_data, SELECT_SENSOR_RCK_V4(j), i);
> > +                     lvts_write_device(lvts_data, SET_DEVICE_SINGLE_MODE_V4, i);
> > +                     usleep_range(10, 20);
> > +
> > +                     lvts_write_device(lvts_data, KICK_OFF_RCK_COUNTING_V4, i);
> > +                     usleep_range(30, 40);
> > +
> > +                     ret = readl_poll_timeout(LVTS_CONFIG_0 + base, data,
> > +                                              !(data & DEVICE_SENSING_STATUS), 2, 200);
> > +                     if (ret)
> > +                             dev_err(dev,
> > +                                     "Error: LVTS %d DEVICE_SENSING_STATUS didn't ready\n", i);
> > +
> > +                     data = lvts_read_device(lvts_data, 0x00, i);
> > +
> > +                     cal_data->count_rc_now[s_index] = (data & GENMASK(23, 0));
>
> No magic GENMASK() or BIT() please, add a definition for readability.
>
> > +             }
> > +
> > +             /* Recover Setting for Normal Access on
> > +              * temperature fetch
> > +              */
> > +             lvts_write_device(lvts_data, SET_SENSOR_NO_RCK_V4, i);
> > +             lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> > +     }
> > +
> > +     size = sizeof(buffer);
> > +     offset = snprintf(buffer, size, "[COUNT_RC_NOW] ");
> > +     for (i = 0; i < lvts_data->num_sensor; i++)
> > +             offset += snprintf(buffer + offset, size - offset, "%d:%d ",
> > +                     i, cal_data->count_rc_now[i]);
> > +
> > +     buffer[offset] = '\0';
> > +     dev_dbg(dev, "%s\n", buffer);
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_device_read_count_rc_n_v4);
> > +
> > +void lvts_set_calibration_data_v4(struct lvts_data *lvts_data)
> > +{
> > +     const struct lvts_tc_settings *tc = lvts_data->tc;
> > +     struct lvts_sensor_cal_data *cal_data = &lvts_data->cal_data;
> > +     unsigned int i, j, s_index, lvts_calib_data;
> > +     void __iomem *base;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +
> > +             for (j = 0; j < tc[i].num_sensor; j++) {
> > +                     s_index = tc[i].sensor_map[j];
> > +                     if (HAS_FEATURE(lvts_data, FEATURE_DEVICE_AUTO_RCK))
> > +                             lvts_calib_data = cal_data->count_r[s_index];
> > +                     else
> > +                             lvts_calib_data = (((unsigned long long)
>
> lvts_calib_data is unsigned int. You're assigning unsigned long long here.
>
> Also, since this is register-size bound, use fixed size types.
>
> > +                                     cal_data->count_rc_now[s_index]) *
> > +                                     cal_data->count_r[s_index]) >> 14;
> > +
> > +                     writel(lvts_calib_data, LVTSEDATA00_0 + base + 0x4 * j);
> > +             }
> > +     }
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_set_calibration_data_v4);
> > +
> > +void lvts_init_controller_v4(struct lvts_data *lvts_data)
> > +{
> > +     struct device *dev = lvts_data->dev;
> > +     unsigned int i;
> > +     void __iomem *base;
> > +
> > +     for (i = 0; i < lvts_data->num_tc; i++) {
> > +             base = GET_BASE_ADDR(lvts_data, i);
> > +
> > +             lvts_write_device(lvts_data, SET_DEVICE_LOW_POWER_SINGLE_MODE_V4, i);
> > +
> > +             writel(SET_SENSOR_INDEX, LVTSTSSEL_0 + base);
> > +             writel(SET_CALC_SCALE_RULES, LVTSCALSCALE_0 + base);
> > +
> > +             set_polling_speed(lvts_data, i);
> > +             set_hw_filter(lvts_data, i);
> > +
> > +             dev_info(dev, "lvts_tc_%d: read all %d sensors in %d us, one in %d us\n",
> > +                     i, GET_TC_SENSOR_NUM(lvts_data, i), GROUP_LATENCY_US(i), SENSOR_LATENCY_US(i));
>
> dev_dbg().
>
> > +     }
> > +}
> > +EXPORT_SYMBOL_GPL(lvts_init_controller_v4);
> > +
> > +int lvts_probe(struct platform_device *pdev)
> > +{
> > +     struct device *dev = &pdev->dev;
> > +     struct lvts_data *lvts_data;
> > +     int ret;
> > +
> > +     lvts_data = (struct lvts_data *)of_device_get_match_data(dev);
> > +
> > +     if (!lvts_data) {
> > +             dev_err(dev, "Error: Failed to get lvts platform data\n");
> > +             return -ENODATA;
> > +     }
> > +
> > +     lvts_data->dev = &pdev->dev;
> > +
> > +     ret = of_update_lvts_data(lvts_data, pdev);
> > +     if (ret)
> > +             return ret;
> > +
> > +     platform_set_drvdata(pdev, lvts_data);
> > +
> > +     ret = lvts_init(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     ret = lvts_register_irq_handler(lvts_data);
> > +     if (ret)
> > +             return ret;
>
> If anything goes wrong here, you're leaving the lvts_data->clk clock enabled.
> Please fix.

"lvts_close(lvts_data)" is called just before "return ret" which in
turn calls "clk_disable_unprepare(lvts_data->clk)".
Please let me know if I misunderstood the comment.

>
> > +
> > +     ret = lvts_register_thermal_zones(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_remove(struct platform_device *pdev)
> > +{
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     lvts_close(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_suspend(struct platform_device *pdev, pm_message_t state)
> > +{
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     lvts_close(lvts_data);
> > +
> > +     return 0;
> > +}
> > +
> > +int lvts_resume(struct platform_device *pdev)
> > +{
> > +     int ret;
> > +     struct lvts_data *lvts_data;
> > +
> > +     lvts_data = (struct lvts_data *)platform_get_drvdata(pdev);
> > +
> > +     ret = lvts_init(lvts_data);
> > +     if (ret)
> > +             return ret;
> > +
> > +     return 0;
> > +}
> > +
> > +MODULE_AUTHOR("Yu-Chia Chang <ethan.chang@mediatek.com>");
> > +MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
> > +MODULE_DESCRIPTION("MediaTek soc temperature driver");
> > +MODULE_LICENSE("GPL v2");
>
> Regards,
> Angelo

Thank you Angelo for the review.

Most of the changes are done.
Resubmitting very soon.

Best regards.
Balsam.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-29 20:14     ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:14 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> This adds the efuse node. This will be required by the thermal driver
> to get the calibration data.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> index 0ff34edcf8c8..4fbf24b5d202 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
>  			status = "disabled";
>  		};
>  
> +		efuse: efuse@11c10000 {
> +			compatible = "mediatek,efuse";
> +			reg = <0 0x11c10000 0 0x1000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			lvts_efuse_data1: lvts1-calib@1bc {
> +				reg = <0x1bc 0x14>;
> +			};
> +			lvts_efuse_data2: lvts2-calib@1d0 {
> +				reg = <0x1d0 0x38>;
> +			};
> +			svs_calibration: calib@580 {
> +				reg = <0x580 0x64>;
> +			};
> +		};
> +

This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
rebase.

Thanks,
Nícolas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
@ 2022-07-29 20:14     ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:14 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> This adds the efuse node. This will be required by the thermal driver
> to get the calibration data.
> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> index 0ff34edcf8c8..4fbf24b5d202 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
>  			status = "disabled";
>  		};
>  
> +		efuse: efuse@11c10000 {
> +			compatible = "mediatek,efuse";
> +			reg = <0 0x11c10000 0 0x1000>;
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			lvts_efuse_data1: lvts1-calib@1bc {
> +				reg = <0x1bc 0x14>;
> +			};
> +			lvts_efuse_data2: lvts2-calib@1d0 {
> +				reg = <0x1d0 0x38>;
> +			};
> +			svs_calibration: calib@580 {
> +				reg = <0x580 0x64>;
> +			};
> +		};
> +

This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
rebase.

Thanks,
Nícolas

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 6/6] arm64: dts: mt8195: Add thermal zone
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-29 20:22     ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:22 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:06PM +0200, Balsam CHIHI wrote:
> This adds the thermal zone for the mt8195.
> 
> Signed-off-by: Tinghan Shen <tinghan.shen@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 115 ++++++++++++++++++++++-
>  1 file changed, 114 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> index 4fbf24b5d202..78017224930c 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0 OR MIT)
>  /*
> - * Copyright (c) 2021 MediaTek Inc.
> + * Copyright (c) 2022 MediaTek Inc.
>   * Author: Seiya Wang <seiya.wang@mediatek.com>
>   */
>  
> @@ -11,6 +11,9 @@
>  #include <dt-bindings/memory/mt8195-memory-port.h>
>  #include <dt-bindings/phy/phy.h>
>  #include <dt-bindings/pinctrl/mt8195-pinfunc.h>
> +#include <dt-bindings/power/mt8195-power.h>
> +#include <dt-bindings/reset/mt8195-resets.h>
> +#include <dt-bindings/thermal/thermal.h>

You're not actually using the mt8195-power and thermal includes.

>  
>  / {
>  	compatible = "mediatek,mt8195";
> @@ -810,6 +813,28 @@ spi0: spi@1100a000 {
>  			status = "disabled";
>  		};
>  
> +		lvtsap: thermal-sensor@1100b000 {

Can you name this label lvts_ap, and the one below lvts_mcu, please? Makes it
much more readable.

> +			compatible = "mediatek,mt8195-lvts-ap";
> +			#thermal-sensor-cells = <1>;
> +			reg = <0 0x1100b000 0 0x400>;

Don't you need the reg size to be 0x1000 to be able to access THERMINTST in the
soc_temp_lvts.c?

> +			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>;
> +			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
> +			resets = <&infracfg_ao MT8195_INFRA_RST0_THERM_CTRL_SWRST>;
> +			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
> +			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
> +		};
> +
> +		lvtsmcu: thermal-sensor@11278000 {
> +			compatible = "mediatek,mt8195-lvts-mcu";
> +			#thermal-sensor-cells = <1>;
> +			reg = <0 0x11278000 0 0x400>;
> +			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
> +			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
> +			resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
> +			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
> +			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
> +		};
> +
>  		spi1: spi@11010000 {
>  			compatible = "mediatek,mt8195-spi",
>  				     "mediatek,mt6765-spi";
> @@ -1613,4 +1638,92 @@ vencsys_core1: clock-controller@1b000000 {
>  			#clock-cells = <1>;
>  		};
>  	};
> +
> +	thermal_zones: thermal-zones {
> +		cpu-big1-thermal {
> +			polling-delay = <0>; /* milliseconds */
> +			polling-delay-passive = <0>; /* milliseconds */

Please drop all these '/* milliseconds */' comments. The thermal-zones
dt-binding already defines both of these properties as being in milliseconds, so
this is just polluting the DT.

Thanks,
Nícolas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 6/6] arm64: dts: mt8195: Add thermal zone
@ 2022-07-29 20:22     ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:22 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:06PM +0200, Balsam CHIHI wrote:
> This adds the thermal zone for the mt8195.
> 
> Signed-off-by: Tinghan Shen <tinghan.shen@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 115 ++++++++++++++++++++++-
>  1 file changed, 114 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> index 4fbf24b5d202..78017224930c 100644
> --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> @@ -1,6 +1,6 @@
>  // SPDX-License-Identifier: (GPL-2.0 OR MIT)
>  /*
> - * Copyright (c) 2021 MediaTek Inc.
> + * Copyright (c) 2022 MediaTek Inc.
>   * Author: Seiya Wang <seiya.wang@mediatek.com>
>   */
>  
> @@ -11,6 +11,9 @@
>  #include <dt-bindings/memory/mt8195-memory-port.h>
>  #include <dt-bindings/phy/phy.h>
>  #include <dt-bindings/pinctrl/mt8195-pinfunc.h>
> +#include <dt-bindings/power/mt8195-power.h>
> +#include <dt-bindings/reset/mt8195-resets.h>
> +#include <dt-bindings/thermal/thermal.h>

You're not actually using the mt8195-power and thermal includes.

>  
>  / {
>  	compatible = "mediatek,mt8195";
> @@ -810,6 +813,28 @@ spi0: spi@1100a000 {
>  			status = "disabled";
>  		};
>  
> +		lvtsap: thermal-sensor@1100b000 {

Can you name this label lvts_ap, and the one below lvts_mcu, please? Makes it
much more readable.

> +			compatible = "mediatek,mt8195-lvts-ap";
> +			#thermal-sensor-cells = <1>;
> +			reg = <0 0x1100b000 0 0x400>;

Don't you need the reg size to be 0x1000 to be able to access THERMINTST in the
soc_temp_lvts.c?

> +			interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>;
> +			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
> +			resets = <&infracfg_ao MT8195_INFRA_RST0_THERM_CTRL_SWRST>;
> +			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
> +			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
> +		};
> +
> +		lvtsmcu: thermal-sensor@11278000 {
> +			compatible = "mediatek,mt8195-lvts-mcu";
> +			#thermal-sensor-cells = <1>;
> +			reg = <0 0x11278000 0 0x400>;
> +			interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>;
> +			clocks = <&infracfg_ao CLK_INFRA_AO_THERM>;
> +			resets = <&infracfg_ao MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST>;
> +			nvmem-cells = <&lvts_efuse_data1 &lvts_efuse_data2>;
> +			nvmem-cell-names = "lvts_calib_data1", "lvts_calib_data2";
> +		};
> +
>  		spi1: spi@11010000 {
>  			compatible = "mediatek,mt8195-spi",
>  				     "mediatek,mt6765-spi";
> @@ -1613,4 +1638,92 @@ vencsys_core1: clock-controller@1b000000 {
>  			#clock-cells = <1>;
>  		};
>  	};
> +
> +	thermal_zones: thermal-zones {
> +		cpu-big1-thermal {
> +			polling-delay = <0>; /* milliseconds */
> +			polling-delay-passive = <0>; /* milliseconds */

Please drop all these '/* milliseconds */' comments. The thermal-zones
dt-binding already defines both of these properties as being in milliseconds, so
this is just polluting the DT.

Thanks,
Nícolas

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
  2022-07-26 13:55   ` Balsam CHIHI
@ 2022-07-29 20:30     ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:30 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:03PM +0200, Balsam CHIHI wrote:
> Add a LVTS (Low voltage thermal sensor) driver to report junction
> temperatures in Mediatek SoC mt8192 and register the maximum temperature
> of sensors and each sensor as a thermal zone.
> 
> Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  drivers/thermal/mediatek/Kconfig         |  27 +
>  drivers/thermal/mediatek/Makefile        |   2 +
>  drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
>  drivers/thermal/mediatek/soc_temp.c      |   2 +-
>  drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
>  drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
>  6 files changed, 1564 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> 
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> index 9c41e9079fc3..7fc04237dd50 100644
> --- a/drivers/thermal/mediatek/Kconfig
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
>  		configures thermal controllers to collect temperature
>  		via AUXADC interface.
>  
> +config MTK_SOC_THERMAL_LVTS
> +	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON

Both mt8192 and mt8195 use the reset controller provided by infracfg [1], so
there's no need to depend on RESET_TI_SYSCON. (Same thing below)

[1] https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/

Thanks,
Nícolas

> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via Analog Serial Interface(ASIF).
> +
> +endif
> +
> +if MTK_SOC_THERMAL_LVTS
> +
> +config LVTS_MT8192
> +	tristate "LVTS driver for MediaTek MT8192 SoC"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	depends on MTK_SOC_THERMAL_LVTS
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MT8192. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via ASIF.
> +
>  endif
[..]

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
@ 2022-07-29 20:30     ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:30 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:03PM +0200, Balsam CHIHI wrote:
> Add a LVTS (Low voltage thermal sensor) driver to report junction
> temperatures in Mediatek SoC mt8192 and register the maximum temperature
> of sensors and each sensor as a thermal zone.
> 
> Signed-off-by: Yu-Chia Chang <ethan.chang@mediatek.com>
> Signed-off-by: Michael Kao <michael.kao@mediatek.com>
> Signed-off-by: Ben Tseng <ben.tseng@mediatek.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> ---
>  drivers/thermal/mediatek/Kconfig         |  27 +
>  drivers/thermal/mediatek/Makefile        |   2 +
>  drivers/thermal/mediatek/lvts_mt8192.c   | 241 ++++++
>  drivers/thermal/mediatek/soc_temp.c      |   2 +-
>  drivers/thermal/mediatek/soc_temp_lvts.c | 928 +++++++++++++++++++++++
>  drivers/thermal/mediatek/soc_temp_lvts.h | 365 +++++++++
>  6 files changed, 1564 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h
> 
> diff --git a/drivers/thermal/mediatek/Kconfig b/drivers/thermal/mediatek/Kconfig
> index 9c41e9079fc3..7fc04237dd50 100644
> --- a/drivers/thermal/mediatek/Kconfig
> +++ b/drivers/thermal/mediatek/Kconfig
> @@ -20,4 +20,31 @@ config MTK_SOC_THERMAL
>  		configures thermal controllers to collect temperature
>  		via AUXADC interface.
>  
> +config MTK_SOC_THERMAL_LVTS
> +	tristate "LVTS (Low voltage thermal sensor) driver for Mediatek SoCs"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON

Both mt8192 and mt8195 use the reset controller provided by infracfg [1], so
there's no need to depend on RESET_TI_SYSCON. (Same thing below)

[1] https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/

Thanks,
Nícolas

> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MediaTek platforms. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via Analog Serial Interface(ASIF).
> +
> +endif
> +
> +if MTK_SOC_THERMAL_LVTS
> +
> +config LVTS_MT8192
> +	tristate "LVTS driver for MediaTek MT8192 SoC"
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on RESET_TI_SYSCON
> +	depends on MTK_SOC_THERMAL_LVTS
> +	help
> +		Enable this option if you want to get SoC temperature
> +		information for MT8192. This driver
> +		configures LVTS thermal controllers to collect temperatures
> +		via ASIF.
> +
>  endif
[..]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 0/6] Add LVTS architecture thermal
  2022-07-26 13:55 ` Balsam CHIHI
@ 2022-07-29 20:33   ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:33 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:00PM +0200, Balsam CHIHI wrote:
> This series moves thermal files related to MediaTek to the mediatek folder.
> And introduce the new architecture LVTS (low voltage thermal sensor) driver to report
> the highest temperature in the SoC and record the highest temperature sensor,
> each sensor as a hot zone.
> The LVTS body is divided into two parts, the LVTS controller and the LVTS device.
> The LVTS controller can connect up to 4 LVTS devices, and each LVTS device
> can connect up to 7 TSMCUs.
> 
> The architecture will be the first to be used on mt8192 and mt8195.
> 
> Changelog:
> Changes in v8:
>         - Fix Coding style issues
>         - Rebase to kernel-5.18.rc8
>         - Rebase on top of these series :
>           - [RESEND v8 00/19] Cleanup MediaTek clk reset drivers and support SoCs :
>                 https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
>           - [PATCH v6 00/12] thermal OF rework :
>                 https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
>         - Add multi-instance support and SRC Modularization :
>           - Rewrite DTS and DT bindings
>             - Add DT bindings for MT8195
>             - One LVTS node for each HW Domain (AP and MCU)
>           - One SW Instance for each HW Domain, for each SoC
>           - Add an SRC file for each SoC (MT8192 and MT8195)
>           - Add a Kconfig sub-menu entry for each SoC
>         - Shrink LVTS instance iospace length from 0x1000 to 0x400
>         - Replace platform_get_resource by platform_get_mem_or_io to get Base Address
>         - Replace platform_get_resource by platform_get_irq to get Interrupt Number
>         - Add "lvts_" prefix to functions and structs
> 
> Changes in v7:
>         - Fix coding style issues
>         - Rewrite dt bindings
>           - was not accurate
>           - Use mt8195 for example (instead of mt8192)
>           - Rename mt6873 to mt8192
>           - Remove clock name
>         - Rebased on top of to series:
>           - https://patchwork.kernel.org/project/linux-mediatek/list/?series=637849
>           - https://patchwork.kernel.org/project/linux-pm/list/?series=639386
> 
> Changes in v6:
>         - Remove temperature aggregation (it will be added in another series)
>         - Update the way to read the temperature (read one sensor instead of all)
>         - Add support of mt8195
> 
> Changes in v5:
>         - Use 'git mv' for the relocated file.
> 
> Changes in v4:
>         - Rebase to kernel-v5.13-rc1
>         - Resend
> 
> Changes in v3:
>         - change the expression in the lvts_temp_to_raw to dev_s64.
> 
> Changes in v2:
>         - Rebase to kernel-5.11-rc1.
>         - sort headers
>         - remove initial value 0 of msr_raw in the lvts_temp_to_raw.
>         - disconstruct the api of lvts_read_tc_msr_raw.
>         - add the initial value max_temp = 0 and compare e.q.
>           in the lvts_read_all_tc_temperature.
>         - add the return with an invalid number in the lvts_init.
> 
> This series depends on [1] and [2].
> 
> [1]https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
> [2]https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
> 
> Alexandre Bailon (2):
>   dt-bindings: thermal: Add binding document for LVTS thermal
>     controllers
>   arm64: dts: mt8195: Add efuse node to mt8195
> 
> Michael Kao (3):
>   thermal: mediatek: Relocate driver to mediatek folder
>   thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
>   thermal: mediatek: Add thermal zone settings for mt8195
> 
> Tinghan Shen (1):
>   arm64: dts: mt8195: Add thermal zone
> 
>  .../thermal/mediatek,mt8192-lvts.yaml         |  73 ++
>  .../thermal/mediatek,mt8195-lvts.yaml         |  75 ++
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi      | 131 ++-
>  drivers/thermal/Kconfig                       |  14 +-
>  drivers/thermal/Makefile                      |   2 +-
>  drivers/thermal/mediatek/Kconfig              |  62 ++
>  drivers/thermal/mediatek/Makefile             |   4 +
>  drivers/thermal/mediatek/lvts_mt8192.c        | 241 +++++
>  drivers/thermal/mediatek/lvts_mt8195.c        | 253 +++++
>  .../{mtk_thermal.c => mediatek/soc_temp.c}    |   2 +-
>  drivers/thermal/mediatek/soc_temp_lvts.c      | 928 ++++++++++++++++++
>  drivers/thermal/mediatek/soc_temp_lvts.h      | 366 +++++++
>  12 files changed, 2138 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
>  create mode 100644 drivers/thermal/mediatek/Kconfig
>  create mode 100644 drivers/thermal/mediatek/Makefile
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c
>  rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (99%)
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

Given that you're adding a driver that supports both mt8192 and mt8195, and also
the DT thermal nodes for mt8195, maybe you could the DT nodes for mt8192 here as
well?

Thanks,
Nícolas

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 0/6] Add LVTS architecture thermal
@ 2022-07-29 20:33   ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-07-29 20:33 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Tue, Jul 26, 2022 at 03:55:00PM +0200, Balsam CHIHI wrote:
> This series moves thermal files related to MediaTek to the mediatek folder.
> And introduce the new architecture LVTS (low voltage thermal sensor) driver to report
> the highest temperature in the SoC and record the highest temperature sensor,
> each sensor as a hot zone.
> The LVTS body is divided into two parts, the LVTS controller and the LVTS device.
> The LVTS controller can connect up to 4 LVTS devices, and each LVTS device
> can connect up to 7 TSMCUs.
> 
> The architecture will be the first to be used on mt8192 and mt8195.
> 
> Changelog:
> Changes in v8:
>         - Fix Coding style issues
>         - Rebase to kernel-5.18.rc8
>         - Rebase on top of these series :
>           - [RESEND v8 00/19] Cleanup MediaTek clk reset drivers and support SoCs :
>                 https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
>           - [PATCH v6 00/12] thermal OF rework :
>                 https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
>         - Add multi-instance support and SRC Modularization :
>           - Rewrite DTS and DT bindings
>             - Add DT bindings for MT8195
>             - One LVTS node for each HW Domain (AP and MCU)
>           - One SW Instance for each HW Domain, for each SoC
>           - Add an SRC file for each SoC (MT8192 and MT8195)
>           - Add a Kconfig sub-menu entry for each SoC
>         - Shrink LVTS instance iospace length from 0x1000 to 0x400
>         - Replace platform_get_resource by platform_get_mem_or_io to get Base Address
>         - Replace platform_get_resource by platform_get_irq to get Interrupt Number
>         - Add "lvts_" prefix to functions and structs
> 
> Changes in v7:
>         - Fix coding style issues
>         - Rewrite dt bindings
>           - was not accurate
>           - Use mt8195 for example (instead of mt8192)
>           - Rename mt6873 to mt8192
>           - Remove clock name
>         - Rebased on top of to series:
>           - https://patchwork.kernel.org/project/linux-mediatek/list/?series=637849
>           - https://patchwork.kernel.org/project/linux-pm/list/?series=639386
> 
> Changes in v6:
>         - Remove temperature aggregation (it will be added in another series)
>         - Update the way to read the temperature (read one sensor instead of all)
>         - Add support of mt8195
> 
> Changes in v5:
>         - Use 'git mv' for the relocated file.
> 
> Changes in v4:
>         - Rebase to kernel-v5.13-rc1
>         - Resend
> 
> Changes in v3:
>         - change the expression in the lvts_temp_to_raw to dev_s64.
> 
> Changes in v2:
>         - Rebase to kernel-5.11-rc1.
>         - sort headers
>         - remove initial value 0 of msr_raw in the lvts_temp_to_raw.
>         - disconstruct the api of lvts_read_tc_msr_raw.
>         - add the initial value max_temp = 0 and compare e.q.
>           in the lvts_read_all_tc_temperature.
>         - add the return with an invalid number in the lvts_init.
> 
> This series depends on [1] and [2].
> 
> [1]https://lore.kernel.org/all/20220523093346.28493-1-rex-bc.chen@mediatek.com/
> [2]https://lore.kernel.org/all/20220722200007.1839356-1-daniel.lezcano@linexp.org/
> 
> Alexandre Bailon (2):
>   dt-bindings: thermal: Add binding document for LVTS thermal
>     controllers
>   arm64: dts: mt8195: Add efuse node to mt8195
> 
> Michael Kao (3):
>   thermal: mediatek: Relocate driver to mediatek folder
>   thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192
>   thermal: mediatek: Add thermal zone settings for mt8195
> 
> Tinghan Shen (1):
>   arm64: dts: mt8195: Add thermal zone
> 
>  .../thermal/mediatek,mt8192-lvts.yaml         |  73 ++
>  .../thermal/mediatek,mt8195-lvts.yaml         |  75 ++
>  arch/arm64/boot/dts/mediatek/mt8195.dtsi      | 131 ++-
>  drivers/thermal/Kconfig                       |  14 +-
>  drivers/thermal/Makefile                      |   2 +-
>  drivers/thermal/mediatek/Kconfig              |  62 ++
>  drivers/thermal/mediatek/Makefile             |   4 +
>  drivers/thermal/mediatek/lvts_mt8192.c        | 241 +++++
>  drivers/thermal/mediatek/lvts_mt8195.c        | 253 +++++
>  .../{mtk_thermal.c => mediatek/soc_temp.c}    |   2 +-
>  drivers/thermal/mediatek/soc_temp_lvts.c      | 928 ++++++++++++++++++
>  drivers/thermal/mediatek/soc_temp_lvts.h      | 366 +++++++
>  12 files changed, 2138 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
>  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
>  create mode 100644 drivers/thermal/mediatek/Kconfig
>  create mode 100644 drivers/thermal/mediatek/Makefile
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8192.c
>  create mode 100644 drivers/thermal/mediatek/lvts_mt8195.c
>  rename drivers/thermal/{mtk_thermal.c => mediatek/soc_temp.c} (99%)
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.c
>  create mode 100644 drivers/thermal/mediatek/soc_temp_lvts.h

Given that you're adding a driver that supports both mt8192 and mt8195, and also
the DT thermal nodes for mt8195, maybe you could the DT nodes for mt8192 here as
well?

Thanks,
Nícolas

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
  2022-07-29 20:14     ` Nícolas F. R. A. Prado
@ 2022-08-01 12:33       ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-08-01 12:33 UTC (permalink / raw)
  To: Nícolas F. R. A. Prado
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 10:14 PM Nícolas F. R. A. Prado
<nfraprado@collabora.com> wrote:
>
> On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> > This adds the efuse node. This will be required by the thermal driver
> > to get the calibration data.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
> >  1 file changed, 16 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > index 0ff34edcf8c8..4fbf24b5d202 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
> >                       status = "disabled";
> >               };
> >
> > +             efuse: efuse@11c10000 {
> > +                     compatible = "mediatek,efuse";
> > +                     reg = <0 0x11c10000 0 0x1000>;
> > +                     #address-cells = <1>;
> > +                     #size-cells = <1>;
> > +                     lvts_efuse_data1: lvts1-calib@1bc {
> > +                             reg = <0x1bc 0x14>;
> > +                     };
> > +                     lvts_efuse_data2: lvts2-calib@1d0 {
> > +                             reg = <0x1d0 0x38>;
> > +                     };
> > +                     svs_calibration: calib@580 {
> > +                             reg = <0x580 0x64>;
> > +                     };
> > +             };
> > +
>
> This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
> rebase.
>
> Thanks,
> Nícolas

Hello Nícolas,

Thank you so much for the review.
I rebased on top of the latest kernel version "linux-5.19.0" but I
can't find efuse node on mt8195.dtsi.
But, this node is indeed present on mt8192.dtsi.

Best regards,
Balsam

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
@ 2022-08-01 12:33       ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-08-01 12:33 UTC (permalink / raw)
  To: Nícolas F. R. A. Prado
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 10:14 PM Nícolas F. R. A. Prado
<nfraprado@collabora.com> wrote:
>
> On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> > This adds the efuse node. This will be required by the thermal driver
> > to get the calibration data.
> >
> > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > ---
> >  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
> >  1 file changed, 16 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > index 0ff34edcf8c8..4fbf24b5d202 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
> >                       status = "disabled";
> >               };
> >
> > +             efuse: efuse@11c10000 {
> > +                     compatible = "mediatek,efuse";
> > +                     reg = <0 0x11c10000 0 0x1000>;
> > +                     #address-cells = <1>;
> > +                     #size-cells = <1>;
> > +                     lvts_efuse_data1: lvts1-calib@1bc {
> > +                             reg = <0x1bc 0x14>;
> > +                     };
> > +                     lvts_efuse_data2: lvts2-calib@1d0 {
> > +                             reg = <0x1d0 0x38>;
> > +                     };
> > +                     svs_calibration: calib@580 {
> > +                             reg = <0x580 0x64>;
> > +                     };
> > +             };
> > +
>
> This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
> rebase.
>
> Thanks,
> Nícolas

Hello Nícolas,

Thank you so much for the review.
I rebased on top of the latest kernel version "linux-5.19.0" but I
can't find efuse node on mt8195.dtsi.
But, this node is indeed present on mt8192.dtsi.

Best regards,
Balsam

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
  2022-08-01 12:33       ` Balsam CHIHI
@ 2022-08-01 13:57         ` Nícolas F. R. A. Prado
  -1 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-08-01 13:57 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Mon, Aug 01, 2022 at 02:33:31PM +0200, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 10:14 PM Nícolas F. R. A. Prado
> <nfraprado@collabora.com> wrote:
> >
> > On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> > > This adds the efuse node. This will be required by the thermal driver
> > > to get the calibration data.
> > >
> > > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > > ---
> > >  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
> > >  1 file changed, 16 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > index 0ff34edcf8c8..4fbf24b5d202 100644
> > > --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
> > >                       status = "disabled";
> > >               };
> > >
> > > +             efuse: efuse@11c10000 {
> > > +                     compatible = "mediatek,efuse";
> > > +                     reg = <0 0x11c10000 0 0x1000>;
> > > +                     #address-cells = <1>;
> > > +                     #size-cells = <1>;
> > > +                     lvts_efuse_data1: lvts1-calib@1bc {
> > > +                             reg = <0x1bc 0x14>;
> > > +                     };
> > > +                     lvts_efuse_data2: lvts2-calib@1d0 {
> > > +                             reg = <0x1d0 0x38>;
> > > +                     };
> > > +                     svs_calibration: calib@580 {
> > > +                             reg = <0x580 0x64>;
> > > +                     };
> > > +             };
> > > +
> >
> > This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
> > rebase.
> >
> > Thanks,
> > Nícolas
> 
> Hello Nícolas,
> 
> Thank you so much for the review.
> I rebased on top of the latest kernel version "linux-5.19.0" but I
> can't find efuse node on mt8195.dtsi.
> But, this node is indeed present on mt8192.dtsi.

Hi Balsam,

no I'm really talking about mt8195. For the dts patches in the series you should
base on top of Matthias' -next/dts64 branch [1]. And there you can see the efuse
node on mt8195 [2].

Thanks,
Nícolas

[1] https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux.git/log/?h=v5.19-next/dts64
[2] https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux.git/commit/?h=v5.19-next/dts64&id=ab43a84c9863b65dc20373d5aca4e4d012aa852e

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195
@ 2022-08-01 13:57         ` Nícolas F. R. A. Prado
  0 siblings, 0 replies; 60+ messages in thread
From: Nícolas F. R. A. Prado @ 2022-08-01 13:57 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, daniel.lezcano, amitk, linux-pm, linux-kernel,
	khilman, mka, robh+dt, krzk+dt, matthias.bgg, p.zabel,
	devicetree, linux-arm-kernel, linux-mediatek, james.lo, fan.chen,
	louis.yu, rex-bc.chen, abailon

On Mon, Aug 01, 2022 at 02:33:31PM +0200, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 10:14 PM Nícolas F. R. A. Prado
> <nfraprado@collabora.com> wrote:
> >
> > On Tue, Jul 26, 2022 at 03:55:05PM +0200, Balsam CHIHI wrote:
> > > This adds the efuse node. This will be required by the thermal driver
> > > to get the calibration data.
> > >
> > > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > > ---
> > >  arch/arm64/boot/dts/mediatek/mt8195.dtsi | 16 ++++++++++++++++
> > >  1 file changed, 16 insertions(+)
> > >
> > > diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > index 0ff34edcf8c8..4fbf24b5d202 100644
> > > --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
> > > @@ -1236,6 +1236,22 @@ nor_flash: spi@1132c000 {
> > >                       status = "disabled";
> > >               };
> > >
> > > +             efuse: efuse@11c10000 {
> > > +                     compatible = "mediatek,efuse";
> > > +                     reg = <0 0x11c10000 0 0x1000>;
> > > +                     #address-cells = <1>;
> > > +                     #size-cells = <1>;
> > > +                     lvts_efuse_data1: lvts1-calib@1bc {
> > > +                             reg = <0x1bc 0x14>;
> > > +                     };
> > > +                     lvts_efuse_data2: lvts2-calib@1d0 {
> > > +                             reg = <0x1d0 0x38>;
> > > +                     };
> > > +                     svs_calibration: calib@580 {
> > > +                             reg = <0x580 0x64>;
> > > +                     };
> > > +             };
> > > +
> >
> > This commit doesn't apply, there's already an efuse node on mt8195.dtsi. Please
> > rebase.
> >
> > Thanks,
> > Nícolas
> 
> Hello Nícolas,
> 
> Thank you so much for the review.
> I rebased on top of the latest kernel version "linux-5.19.0" but I
> can't find efuse node on mt8195.dtsi.
> But, this node is indeed present on mt8192.dtsi.

Hi Balsam,

no I'm really talking about mt8195. For the dts patches in the series you should
base on top of Matthias' -next/dts64 branch [1]. And there you can see the efuse
node on mt8195 [2].

Thanks,
Nícolas

[1] https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux.git/log/?h=v5.19-next/dts64
[2] https://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux.git/commit/?h=v5.19-next/dts64&id=ab43a84c9863b65dc20373d5aca4e4d012aa852e

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-07-29 15:35           ` Daniel Lezcano
@ 2022-08-03  8:41             ` Balsam CHIHI
  -1 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-08-03  8:41 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 5:35 PM Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
>
> Hi Balsam,
>
> On 29/07/2022 17:21, Balsam CHIHI wrote:
>
> [ ... ]
>
> You may want to wait next week before sending a new version, I'm still
> reviewing your series (note you can send it anyway if you prefer)
>

Hi Daniel,

Thank you for the review.
I have finished implementing the changes requested by the maintainers
and would like to resubmit the series.
Do I still have to wait for your feedback to send it again?

Best regards,
Balsam

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-08-03  8:41             ` Balsam CHIHI
  0 siblings, 0 replies; 60+ messages in thread
From: Balsam CHIHI @ 2022-08-03  8:41 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon

On Fri, Jul 29, 2022 at 5:35 PM Daniel Lezcano
<daniel.lezcano@linaro.org> wrote:
>
> Hi Balsam,
>
> On 29/07/2022 17:21, Balsam CHIHI wrote:
>
> [ ... ]
>
> You may want to wait next week before sending a new version, I'm still
> reviewing your series (note you can send it anyway if you prefer)
>

Hi Daniel,

Thank you for the review.
I have finished implementing the changes requested by the maintainers
and would like to resubmit the series.
Do I still have to wait for your feedback to send it again?

Best regards,
Balsam

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
  2022-08-03  8:41             ` Balsam CHIHI
@ 2022-08-03 10:51               ` Daniel Lezcano
  -1 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-08-03 10:51 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon


Hi Balsam,

On 03/08/2022 10:41, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 5:35 PM Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
>>
>> Hi Balsam,
>>
>> On 29/07/2022 17:21, Balsam CHIHI wrote:
>>
>> [ ... ]
>>
>> You may want to wait next week before sending a new version, I'm still
>> reviewing your series (note you can send it anyway if you prefer)
>>
> 
> Hi Daniel,
> 
> Thank you for the review.
> I have finished implementing the changes requested by the maintainers
> and would like to resubmit the series.
> Do I still have to wait for your feedback to send it again?

At your convenience, I'll review the new version if you send it



-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder
@ 2022-08-03 10:51               ` Daniel Lezcano
  0 siblings, 0 replies; 60+ messages in thread
From: Daniel Lezcano @ 2022-08-03 10:51 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rafael, rui.zhang, amitk, linux-pm, linux-kernel, khilman, mka,
	robh+dt, krzk+dt, matthias.bgg, p.zabel, devicetree,
	linux-arm-kernel, linux-mediatek, james.lo, fan.chen, louis.yu,
	rex-bc.chen, abailon


Hi Balsam,

On 03/08/2022 10:41, Balsam CHIHI wrote:
> On Fri, Jul 29, 2022 at 5:35 PM Daniel Lezcano
> <daniel.lezcano@linaro.org> wrote:
>>
>> Hi Balsam,
>>
>> On 29/07/2022 17:21, Balsam CHIHI wrote:
>>
>> [ ... ]
>>
>> You may want to wait next week before sending a new version, I'm still
>> reviewing your series (note you can send it anyway if you prefer)
>>
> 
> Hi Daniel,
> 
> Thank you for the review.
> I have finished implementing the changes requested by the maintainers
> and would like to resubmit the series.
> Do I still have to wait for your feedback to send it again?

At your convenience, I'll review the new version if you send it



-- 
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
  2022-07-29 15:15       ` Balsam CHIHI
@ 2022-08-10 18:25         ` Rob Herring
  -1 siblings, 0 replies; 60+ messages in thread
From: Rob Herring @ 2022-08-10 18:25 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, p.zabel, matthias.bgg, linux-pm, rafael, khilman,
	fan.chen, linux-arm-kernel, krzk+dt, devicetree, linux-mediatek,
	louis.yu, james.lo

On Fri, Jul 29, 2022 at 05:15:01PM +0200, Balsam CHIHI wrote:
> On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
> >
> > On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> > >
> > > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > > ---
> > >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> > >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> > >  2 files changed, 148 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> > >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> > >
> >
> > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> >
> > yamllint warnings/errors:
> >
> > dtschema/dtc warnings/errors:
> > Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> > FATAL ERROR: Unable to parse input tree
> > make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> > make[1]: *** Waiting for unfinished jobs....
> > make: *** [Makefile:1404: dt_binding_check] Error 2
> >
> > doc reference errors (make refcheckdocs):
> >
> > See https://patchwork.ozlabs.org/patch/
> >
> > This check can fail if there are any dependencies. The base for a patch
> > series is generally the most recent rc1.
> >
> > If you already ran 'make dt_binding_check' and didn't see the above
> > error(s), then make sure 'yamllint' is installed and dt-schema is up to
> > date:
> >
> > pip3 install dtschema --upgrade
> >
> > Please check and re-submit.
> >
> 
> Hello Rob,
> 
> This error only appear when I apply my series directly on top of linux-5.19.rc8.
> But, when I apply the other two series that mine depends on,
> 
> https://patchwork.kernel.org/project/linux-pm/cover/20220722200007.1839356-1-daniel.lezcano@linexp.org/
> https://patchwork.kernel.org/project/linux-mediatek/cover/20220523093346.28493-1-rex-bc.chen@mediatek.com/

How was I supposed to know that if you don't document that in the patch?
 
> and run "dt_binding_check" again against my YAML file, it does not
> print the error you found above.
> Would you check it, please?

No. Resend after rc1 and checks will be based on that.

Rob

^ permalink raw reply	[flat|nested] 60+ messages in thread

* Re: [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers
@ 2022-08-10 18:25         ` Rob Herring
  0 siblings, 0 replies; 60+ messages in thread
From: Rob Herring @ 2022-08-10 18:25 UTC (permalink / raw)
  To: Balsam CHIHI
  Cc: rui.zhang, rex-bc.chen, daniel.lezcano, amitk, mka, linux-kernel,
	abailon, p.zabel, matthias.bgg, linux-pm, rafael, khilman,
	fan.chen, linux-arm-kernel, krzk+dt, devicetree, linux-mediatek,
	louis.yu, james.lo

On Fri, Jul 29, 2022 at 05:15:01PM +0200, Balsam CHIHI wrote:
> On Tue, Jul 26, 2022 at 10:09 PM Rob Herring <robh@kernel.org> wrote:
> >
> > On Tue, 26 Jul 2022 15:55:02 +0200, Balsam CHIHI wrote:
> > > This patch adds dt-binding documents for mt8192 and mt8195 thermal controllers.
> > >
> > > Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> > > Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
> > > ---
> > >  .../thermal/mediatek,mt8192-lvts.yaml         | 73 ++++++++++++++++++
> > >  .../thermal/mediatek,mt8195-lvts.yaml         | 75 +++++++++++++++++++
> > >  2 files changed, 148 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8192-lvts.yaml
> > >  create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.yaml
> > >
> >
> > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> >
> > yamllint warnings/errors:
> >
> > dtschema/dtc warnings/errors:
> > Error: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dts:32.36-37 syntax error
> > FATAL ERROR: Unable to parse input tree
> > make[1]: *** [scripts/Makefile.lib:383: Documentation/devicetree/bindings/thermal/mediatek,mt8195-lvts.example.dtb] Error 1
> > make[1]: *** Waiting for unfinished jobs....
> > make: *** [Makefile:1404: dt_binding_check] Error 2
> >
> > doc reference errors (make refcheckdocs):
> >
> > See https://patchwork.ozlabs.org/patch/
> >
> > This check can fail if there are any dependencies. The base for a patch
> > series is generally the most recent rc1.
> >
> > If you already ran 'make dt_binding_check' and didn't see the above
> > error(s), then make sure 'yamllint' is installed and dt-schema is up to
> > date:
> >
> > pip3 install dtschema --upgrade
> >
> > Please check and re-submit.
> >
> 
> Hello Rob,
> 
> This error only appear when I apply my series directly on top of linux-5.19.rc8.
> But, when I apply the other two series that mine depends on,
> 
> https://patchwork.kernel.org/project/linux-pm/cover/20220722200007.1839356-1-daniel.lezcano@linexp.org/
> https://patchwork.kernel.org/project/linux-mediatek/cover/20220523093346.28493-1-rex-bc.chen@mediatek.com/

How was I supposed to know that if you don't document that in the patch?
 
> and run "dt_binding_check" again against my YAML file, it does not
> print the error you found above.
> Would you check it, please?

No. Resend after rc1 and checks will be based on that.

Rob

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 60+ messages in thread

end of thread, other threads:[~2022-08-10 18:27 UTC | newest]

Thread overview: 60+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-26 13:55 [PATCH v8 0/6] Add LVTS architecture thermal Balsam CHIHI
2022-07-26 13:55 ` Balsam CHIHI
2022-07-26 13:55 ` [PATCH v8 1/6] thermal: mediatek: Relocate driver to mediatek folder Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-27  8:17   ` AngeloGioacchino Del Regno
2022-07-27  8:17     ` AngeloGioacchino Del Regno
2022-07-27  8:24   ` AngeloGioacchino Del Regno
2022-07-27  8:24     ` AngeloGioacchino Del Regno
2022-07-27  9:03     ` Balsam CHIHI
2022-07-27  9:03       ` Balsam CHIHI
2022-07-28  8:53   ` Daniel Lezcano
2022-07-28  8:53     ` Daniel Lezcano
2022-07-29 15:19     ` Balsam CHIHI
2022-07-29 15:19       ` Balsam CHIHI
2022-07-29 15:21       ` Balsam CHIHI
2022-07-29 15:21         ` Balsam CHIHI
2022-07-29 15:35         ` Daniel Lezcano
2022-07-29 15:35           ` Daniel Lezcano
2022-08-03  8:41           ` Balsam CHIHI
2022-08-03  8:41             ` Balsam CHIHI
2022-08-03 10:51             ` Daniel Lezcano
2022-08-03 10:51               ` Daniel Lezcano
2022-07-26 13:55 ` [PATCH v8 2/6] dt-bindings: thermal: Add binding document for LVTS thermal controllers Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-26 20:09   ` Rob Herring
2022-07-26 20:09     ` Rob Herring
2022-07-27  9:02     ` Balsam CHIHI
2022-07-27  9:02       ` Balsam CHIHI
2022-07-29 15:15     ` Balsam CHIHI
2022-07-29 15:15       ` Balsam CHIHI
2022-08-10 18:25       ` Rob Herring
2022-08-10 18:25         ` Rob Herring
2022-07-27  8:17   ` AngeloGioacchino Del Regno
2022-07-27  8:17     ` AngeloGioacchino Del Regno
2022-07-27  9:02     ` Balsam CHIHI
2022-07-27  9:02       ` Balsam CHIHI
2022-07-26 13:55 ` [PATCH v8 3/6] thermal: mediatek: Add LVTS drivers for SoC theraml zones for mt8192 Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-27  9:23   ` AngeloGioacchino Del Regno
2022-07-27  9:23     ` AngeloGioacchino Del Regno
2022-07-29 15:38     ` Balsam CHIHI
2022-07-29 15:38       ` Balsam CHIHI
2022-07-29 20:30   ` Nícolas F. R. A. Prado
2022-07-29 20:30     ` Nícolas F. R. A. Prado
2022-07-26 13:55 ` [PATCH v8 4/6] thermal: mediatek: Add thermal zone settings for mt8195 Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-26 13:55 ` [PATCH v8 5/6] arm64: dts: mt8195: Add efuse node to mt8195 Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-29 20:14   ` Nícolas F. R. A. Prado
2022-07-29 20:14     ` Nícolas F. R. A. Prado
2022-08-01 12:33     ` Balsam CHIHI
2022-08-01 12:33       ` Balsam CHIHI
2022-08-01 13:57       ` Nícolas F. R. A. Prado
2022-08-01 13:57         ` Nícolas F. R. A. Prado
2022-07-26 13:55 ` [PATCH v8 6/6] arm64: dts: mt8195: Add thermal zone Balsam CHIHI
2022-07-26 13:55   ` Balsam CHIHI
2022-07-29 20:22   ` Nícolas F. R. A. Prado
2022-07-29 20:22     ` Nícolas F. R. A. Prado
2022-07-29 20:33 ` [PATCH v8 0/6] Add LVTS architecture thermal Nícolas F. R. A. Prado
2022-07-29 20:33   ` Nícolas F. R. A. Prado

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.