mediatek: backport a hell of thermal commits
authorDaniel Golle <daniel@makrotopia.org>
Sun, 28 Jan 2024 03:46:58 +0000 (03:46 +0000)
committerDaniel Golle <daniel@makrotopia.org>
Thu, 15 Feb 2024 19:06:36 +0000 (19:06 +0000)
Backport almost 50 commits from upstream Linux to improve thermal
drivers for MediaTek SoCs and add new LVTS driver for MT7988.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
54 files changed:
target/linux/mediatek/files-6.1/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
target/linux/mediatek/filogic/config-6.1
target/linux/mediatek/mt7622/config-6.1
target/linux/mediatek/mt7623/config-6.1
target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch [deleted file]
target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch [deleted file]
target/linux/mediatek/patches-6.1/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.4-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch [new file with mode: 0644]
target/linux/mediatek/patches-6.1/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch [new file with mode: 0644]

index 81410c017bd8e4ed2ddd20dc7d8d0ddaa26b9f60..77c262b8ca79c6482c768e6f5a654c5522921a56 100644 (file)
                clock-output-names = "clkxtal";
        };
 
+       fan: pwm-fan {
+               compatible = "pwm-fan";
+               /* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */
+               cooling-levels = <0 128 255>;
+               #cooling-cells = <2>;
+               #thermal-sensor-cells = <1>;
+               status = "disabled";
+       };
+
        pmu {
                compatible = "arm,cortex-a73-pmu";
                interrupt-parent = <&gic>;
                        status = "disabled";
                };
 
-               fan: pwm-fan {
-                       compatible = "pwm-fan";
-                       /* cooling level (0, 1, 2) : (0% duty, 50% duty, 100% duty) */
-                       cooling-levels = <0 128 255>;
-                       #cooling-cells = <2>;
-                       #thermal-sensor-cells = <1>;
-                       status = "disabled";
-               };
-
                lvts: lvts@1100a000 {
-                       compatible = "mediatek,mt7988-lvts";
+                       compatible = "mediatek,mt7988-lvts-ap";
                        reg = <0 0x1100a000 0 0x1000>;
                        clocks = <&infracfg CLK_INFRA_26M_THERM_SYSTEM>;
                        clock-names = "lvts_clk";
+                       interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+                       resets = <&infracfg MT7988_INFRA_RST1_THERM_CTRL_SWRST>;
                        nvmem-cells = <&lvts_calibration>;
-                       nvmem-cell-names = "e_data1";
+                       nvmem-cell-names = "lvts-calib-data-1";
                        #thermal-sensor-cells = <1>;
                };
 
index 1687aadbc13f03ca04253cdbe90e91d2e1988795..fd55e1a80b500bfbb67ff9f1204d788dd1cad5c2 100644 (file)
@@ -264,6 +264,9 @@ CONFIG_MTK_SCPSYS=y
 CONFIG_MTK_SCPSYS_PM_DOMAINS=y
 # CONFIG_MTK_SVS is not set
 CONFIG_MTK_THERMAL=y
+CONFIG_MTK_SOC_THERMAL=y
+CONFIG_MTK_LVTS_THERMAL=y
+CONFIG_MTK_LVTS_THERMAL_DEBUGFS=y
 CONFIG_MTK_TIMER=y
 # CONFIG_MTK_UART_APDMA is not set
 CONFIG_MUTEX_SPIN_ON_OWNER=y
index 89260f78eedf71250a7e9c64edb9686efa9e7557..0a876bce74e49f082387009667515d466793dc61 100644 (file)
@@ -267,6 +267,8 @@ CONFIG_MTK_SCPSYS=y
 CONFIG_MTK_SCPSYS_PM_DOMAINS=y
 # CONFIG_MTK_SVS is not set
 CONFIG_MTK_THERMAL=y
+CONFIG_MTK_SOC_THERMAL=y
+# CONFIG_MTK_LVTS_THERMAL is not set
 CONFIG_MTK_TIMER=y
 # CONFIG_MTK_UART_APDMA is not set
 CONFIG_MUTEX_SPIN_ON_OWNER=y
index 218016b200c3dfdc7ee4b5c0a2f1f661e71e09f5..765f14fe902ada915e3e084949da8436bf96c0d3 100644 (file)
@@ -385,6 +385,8 @@ CONFIG_MTK_SCPSYS_PM_DOMAINS=y
 CONFIG_MTK_SMI=y
 # CONFIG_MTK_SVS is not set
 CONFIG_MTK_THERMAL=y
+CONFIG_MTK_SOC_THERMAL=y
+# CONFIG_MTK_LVTS_THERMAL is not set
 CONFIG_MTK_TIMER=y
 # CONFIG_MTK_UART_APDMA is not set
 # CONFIG_MUSB_PIO_ONLY is not set
diff --git a/target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-6.1/805-v6.2-thermal-drivers-mtk-use-function-pointer-for-raw_to_.patch
deleted file mode 100644 (file)
index c58ae96..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 69c17529e8418da3eec703dde31e1b01e5b0f7e8 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Wed, 18 Jan 2023 02:48:41 +0000
-Subject: [PATCH 1/2] thermal/drivers/mtk: use function pointer for
- raw_to_mcelsius
-
-Instead of having if-else logic selecting either raw_to_mcelsius_v1 or
-raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function
-pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the
-probe function.
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/thermal/mtk_thermal.c | 17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
---- a/drivers/thermal/mtk_thermal.c
-+++ b/drivers/thermal/mtk_thermal.c
-@@ -292,6 +292,8 @@ struct mtk_thermal {
-       const struct mtk_thermal_data *conf;
-       struct mtk_thermal_bank banks[MAX_NUM_ZONES];
-+
-+      int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
- };
- /* MT8183 thermal sensor data */
-@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature(
-       for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
-               raw = readl(mt->thermal_base + conf->msr[i]);
--              if (mt->conf->version == MTK_THERMAL_V1) {
--                      temp = raw_to_mcelsius_v1(
--                              mt, conf->bank_data[bank->id].sensors[i], raw);
--              } else {
--                      temp = raw_to_mcelsius_v2(
--                              mt, conf->bank_data[bank->id].sensors[i], raw);
--              }
-+              temp = mt->raw_to_mcelsius(
-+                      mt, conf->bank_data[bank->id].sensors[i], raw);
-+
-               /*
-                * The first read of a sensor often contains very high bogus
-@@ -1075,6 +1073,11 @@ static int mtk_thermal_probe(struct plat
-               mtk_thermal_release_periodic_ts(mt, auxadc_base);
-       }
-+      if (mt->conf->version == MTK_THERMAL_V1)
-+              mt->raw_to_mcelsius = raw_to_mcelsius_v1;
-+      else
-+              mt->raw_to_mcelsius = raw_to_mcelsius_v2;
-+
-       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
-               for (i = 0; i < mt->conf->num_banks; i++)
-                       mtk_thermal_init_bank(mt, i, apmixed_phys_base,
diff --git a/target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch b/target/linux/mediatek/patches-6.1/806-v6.2-thermal-mediatek-add-support-for-MT7986-and-MT7981.patch
deleted file mode 100644 (file)
index 65311d5..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-From aa957c759b1182aee00cc35178667f849f941b42 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Wed, 30 Nov 2022 13:19:39 +0000
-Subject: [PATCH 2/2] thermal: mediatek: add support for MT7986 and MT7981
-
-Add support for V3 generation thermal found in MT7986 and MT7981 SoCs.
-Brings code to assign values from efuse as well as new function to
-convert raw temperature to millidegree celsius, as found in MediaTek's
-SDK sources (but cleaned up and de-duplicated)
-
-[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/thermal/mtk_thermal.c | 137 ++++++++++++++++++++++++++++++++--
- 1 file changed, 132 insertions(+), 5 deletions(-)
-
---- a/drivers/thermal/mtk_thermal.c
-+++ b/drivers/thermal/mtk_thermal.c
-@@ -150,6 +150,20 @@
- #define CALIB_BUF1_VALID_V2(x)                (((x) >> 4) & 0x1)
- #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
-+/*
-+ * Layout of the fuses providing the calibration data
-+ * These macros can be used for MT7981 and MT7986.
-+ */
-+#define CALIB_BUF0_ADC_GE_V3(x)               (((x) >> 0) & 0x3ff)
-+#define CALIB_BUF0_DEGC_CALI_V3(x)    (((x) >> 20) & 0x3f)
-+#define CALIB_BUF0_O_SLOPE_V3(x)      (((x) >> 26) & 0x3f)
-+#define CALIB_BUF1_VTS_TS1_V3(x)      (((x) >> 0) & 0x1ff)
-+#define CALIB_BUF1_VTS_TS2_V3(x)      (((x) >> 21) & 0x1ff)
-+#define CALIB_BUF1_VTS_TSABB_V3(x)    (((x) >> 9) & 0x1ff)
-+#define CALIB_BUF1_VALID_V3(x)                (((x) >> 18) & 0x1)
-+#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1)
-+#define CALIB_BUF1_ID_V3(x)           (((x) >> 20) & 0x1)
-+
- enum {
-       VTS1,
-       VTS2,
-@@ -163,6 +177,7 @@ enum {
- enum mtk_thermal_version {
-       MTK_THERMAL_V1 = 1,
-       MTK_THERMAL_V2,
-+      MTK_THERMAL_V3,
- };
- /* MT2701 thermal sensors */
-@@ -245,6 +260,27 @@ enum mtk_thermal_version {
- /* The calibration coefficient of sensor  */
- #define MT8183_CALIBRATION    153
-+/* AUXADC channel 11 is used for the temperature sensors */
-+#define MT7986_TEMP_AUXADC_CHANNEL    11
-+
-+/* The total number of temperature sensors in the MT7986 */
-+#define MT7986_NUM_SENSORS            1
-+
-+/* The number of banks in the MT7986 */
-+#define MT7986_NUM_ZONES              1
-+
-+/* The number of sensing points per bank */
-+#define MT7986_NUM_SENSORS_PER_ZONE   1
-+
-+/* MT7986 thermal sensors */
-+#define MT7986_TS1                    0
-+
-+/* The number of controller in the MT7986 */
-+#define MT7986_NUM_CONTROLLER         1
-+
-+/* The calibration coefficient of sensor  */
-+#define MT7986_CALIBRATION            165
-+
- struct mtk_thermal;
- struct thermal_bank_cfg {
-@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762
- static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
- static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
-+/* MT7986 thermal sensor data */
-+static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, };
-+static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
-+static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
-+static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, };
-+static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
-+static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
-+
- /*
-  * The MT8173 thermal controller has four banks. Each bank can read up to
-  * four temperature sensors simultaneously. The MT8173 has a total of 5
-@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8
-       .version = MTK_THERMAL_V1,
- };
-+/*
-+ * MT7986 uses AUXADC Channel 11 for raw data access.
-+ */
-+static const struct mtk_thermal_data mt7986_thermal_data = {
-+      .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL,
-+      .num_banks = MT7986_NUM_ZONES,
-+      .num_sensors = MT7986_NUM_SENSORS,
-+      .vts_index = mt7986_vts_index,
-+      .cali_val = MT7986_CALIBRATION,
-+      .num_controller = MT7986_NUM_CONTROLLER,
-+      .controller_offset = mt7986_tc_offset,
-+      .need_switch_bank = true,
-+      .bank_data = {
-+              {
-+                      .num_sensors = 1,
-+                      .sensors = mt7986_bank_data,
-+              },
-+      },
-+      .msr = mt7986_msr,
-+      .adcpnp = mt7986_adcpnp,
-+      .sensor_mux_values = mt7986_mux_values,
-+      .version = MTK_THERMAL_V3,
-+};
-+
- /**
-  * raw_to_mcelsius - convert a raw ADC value to mcelsius
-  * @mt:       The thermal controller
-@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk
-       return (format_2 - tmp) * 100;
- }
-+static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw)
-+{
-+      s32 tmp;
-+
-+      if (raw == 0)
-+              return 0;
-+
-+      raw &= 0xfff;
-+      tmp = 100000 * 15 / 16 * 10000;
-+      tmp /= 4096 - 512 + mt->adc_ge;
-+      tmp /= 1490;
-+      tmp *= raw - mt->vts[sensno] - 2900;
-+
-+      return mt->degc_cali * 500 - tmp;
-+}
-+
- /**
-  * mtk_thermal_get_bank - get bank
-  * @bank:     The bank
-@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2(
-       return 0;
- }
-+static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf)
-+{
-+      if (!CALIB_BUF1_VALID_V3(buf[1]))
-+              return -EINVAL;
-+
-+      mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]);
-+      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]);
-+      mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]);
-+      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]);
-+      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]);
-+      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]);
-+      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]);
-+
-+      if (CALIB_BUF1_ID_V3(buf[1]) == 0)
-+              mt->o_slope = 0;
-+
-+      return 0;
-+}
-+
- static int mtk_thermal_get_calibration_data(struct device *dev,
-                                           struct mtk_thermal *mt)
- {
-@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d
-       /* Start with default values */
-       mt->adc_ge = 512;
-+      mt->adc_oe = 512;
-       for (i = 0; i < mt->conf->num_sensors; i++)
-               mt->vts[i] = 260;
-       mt->degc_cali = 40;
-@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d
-               goto out;
-       }
--      if (mt->conf->version == MTK_THERMAL_V1)
-+      switch (mt->conf->version) {
-+      case MTK_THERMAL_V1:
-               ret = mtk_thermal_extract_efuse_v1(mt, buf);
--      else
-+              break;
-+      case MTK_THERMAL_V2:
-               ret = mtk_thermal_extract_efuse_v2(mt, buf);
-+              break;
-+      case MTK_THERMAL_V3:
-+              ret = mtk_thermal_extract_efuse_v3(mt, buf);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-       if (ret) {
-               dev_info(dev, "Device not calibrated, using default calibration values\n");
-@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the
-               .data = (void *)&mt7622_thermal_data,
-       },
-       {
-+              .compatible = "mediatek,mt7986-thermal",
-+              .data = (void *)&mt7986_thermal_data,
-+      },
-+      {
-               .compatible = "mediatek,mt8183-thermal",
-               .data = (void *)&mt8183_thermal_data,
-       }, {
-@@ -1068,15 +1186,24 @@ static int mtk_thermal_probe(struct plat
-               goto err_disable_clk_auxadc;
-       }
--      if (mt->conf->version == MTK_THERMAL_V2) {
-+      if (mt->conf->version != MTK_THERMAL_V1) {
-               mtk_thermal_turn_on_buffer(apmixed_base);
-               mtk_thermal_release_periodic_ts(mt, auxadc_base);
-       }
--      if (mt->conf->version == MTK_THERMAL_V1)
-+      switch (mt->conf->version) {
-+      case MTK_THERMAL_V1:
-               mt->raw_to_mcelsius = raw_to_mcelsius_v1;
--      else
-+              break;
-+      case MTK_THERMAL_V2:
-               mt->raw_to_mcelsius = raw_to_mcelsius_v2;
-+              break;
-+      case MTK_THERMAL_V3:
-+              mt->raw_to_mcelsius = raw_to_mcelsius_v3;
-+              break;
-+      default:
-+              break;
-+      }
-       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
-               for (i = 0; i < mt->conf->num_banks; i++)
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch b/target/linux/mediatek/patches-6.1/830-v6.3-01-thermal-drivers-mtk_thermal-Fix-kernel-doc-function-.patch
new file mode 100644 (file)
index 0000000..694b73a
--- /dev/null
@@ -0,0 +1,37 @@
+From f167da186acf90847e1a6d3716e253825a6218ec Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Thu, 12 Jan 2023 22:44:49 -0800
+Subject: [PATCH 01/42] thermal/drivers/mtk_thermal: Fix kernel-doc function
+ name
+
+Use the correct function name in a kernel-doc comment to prevent
+a warning:
+
+drivers/thermal/mtk_thermal.c:562: warning: expecting prototype for raw_to_mcelsius(). Prototype was for raw_to_mcelsius_v1() instead
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: "Rafael J. Wysocki" <rafael@kernel.org>
+Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
+Cc: Amit Kucheria <amitk@kernel.org>
+Cc: Zhang Rui <rui.zhang@intel.com>
+Cc: Matthias Brugger <matthias.bgg@gmail.com>
+Cc: linux-pm@vger.kernel.org
+Cc: linux-arm-kernel@lists.infradead.org
+Cc: linux-mediatek@lists.infradead.org
+Link: https://lore.kernel.org/r/20230113064449.15061-1-rdunlap@infradead.org
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mtk_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -550,7 +550,7 @@ static const struct mtk_thermal_data mt8
+ };
+ /**
+- * raw_to_mcelsius - convert a raw ADC value to mcelsius
++ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
+  * @mt:       The thermal controller
+  * @sensno:   sensor number
+  * @raw:      raw ADC value
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch b/target/linux/mediatek/patches-6.1/830-v6.3-02-thermal-drivers-mtk_thermal-Use-devm_platform_get_an.patch
new file mode 100644 (file)
index 0000000..aaed9d7
--- /dev/null
@@ -0,0 +1,37 @@
+From 255509232417ee71fd606cb957d44cf6544f0c43 Mon Sep 17 00:00:00 2001
+From: ye xingchen <ye.xingchen@zte.com.cn>
+Date: Wed, 18 Jan 2023 16:37:47 +0800
+Subject: [PATCH 02/42] thermal/drivers/mtk_thermal: Use
+ devm_platform_get_and_ioremap_resource()
+
+Convert platform_get_resource(), devm_ioremap_resource() to a single
+call to devm_platform_get_and_ioremap_resource(), as this is exactly
+what this function does.
+
+Signed-off-by: ye xingchen <ye.xingchen@zte.com.cn>
+Link: https://lore.kernel.org/r/202301181637472073620@zte.com.cn
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mtk_thermal.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -990,7 +990,6 @@ static int mtk_thermal_probe(struct plat
+       int ret, i, ctrl_id;
+       struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
+       struct mtk_thermal *mt;
+-      struct resource *res;
+       u64 auxadc_phys_base, apmixed_phys_base;
+       struct thermal_zone_device *tzdev;
+       void __iomem *apmixed_base, *auxadc_base;
+@@ -1009,8 +1008,7 @@ static int mtk_thermal_probe(struct plat
+       if (IS_ERR(mt->clk_auxadc))
+               return PTR_ERR(mt->clk_auxadc);
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      mt->thermal_base = devm_ioremap_resource(&pdev->dev, res);
++      mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+       if (IS_ERR(mt->thermal_base))
+               return PTR_ERR(mt->thermal_base);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch b/target/linux/mediatek/patches-6.1/830-v6.3-03-thermal-drivers-mtk-Use-function-pointer-for-raw_to_.patch
new file mode 100644 (file)
index 0000000..215b0fd
--- /dev/null
@@ -0,0 +1,60 @@
+From ca86dbd309ba03bef38ae91f037e2030bb671ab7 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 18 Jan 2023 15:40:39 +0000
+Subject: [PATCH 03/42] thermal/drivers/mtk: Use function pointer for
+ raw_to_mcelsius
+
+Instead of having if-else logic selecting either raw_to_mcelsius_v1 or
+raw_to_mcelsius_v2 in mtk_thermal_bank_temperature introduce a function
+pointer raw_to_mcelsius to struct mtk_thermal which is initialized in the
+probe function.
+
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Link: https://lore.kernel.org/r/69c17529e8418da3eec703dde31e1b01e5b0f7e8.1674055882.git.daniel@makrotopia.org
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mtk_thermal.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -292,6 +292,8 @@ struct mtk_thermal {
+       const struct mtk_thermal_data *conf;
+       struct mtk_thermal_bank banks[MAX_NUM_ZONES];
++
++      int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
+ };
+ /* MT8183 thermal sensor data */
+@@ -656,13 +658,9 @@ static int mtk_thermal_bank_temperature(
+       for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
+               raw = readl(mt->thermal_base + conf->msr[i]);
+-              if (mt->conf->version == MTK_THERMAL_V1) {
+-                      temp = raw_to_mcelsius_v1(
+-                              mt, conf->bank_data[bank->id].sensors[i], raw);
+-              } else {
+-                      temp = raw_to_mcelsius_v2(
+-                              mt, conf->bank_data[bank->id].sensors[i], raw);
+-              }
++              temp = mt->raw_to_mcelsius(
++                      mt, conf->bank_data[bank->id].sensors[i], raw);
++
+               /*
+                * The first read of a sensor often contains very high bogus
+@@ -1073,6 +1071,11 @@ static int mtk_thermal_probe(struct plat
+               mtk_thermal_release_periodic_ts(mt, auxadc_base);
+       }
++      if (mt->conf->version == MTK_THERMAL_V1)
++              mt->raw_to_mcelsius = raw_to_mcelsius_v1;
++      else
++              mt->raw_to_mcelsius = raw_to_mcelsius_v2;
++
+       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+               for (i = 0; i < mt->conf->num_banks; i++)
+                       mtk_thermal_init_bank(mt, i, apmixed_phys_base,
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch b/target/linux/mediatek/patches-6.1/830-v6.3-04-thermal-drivers-mtk-Add-support-for-MT7986-and-MT798.patch
new file mode 100644 (file)
index 0000000..ef20067
--- /dev/null
@@ -0,0 +1,236 @@
+From aec1d89dccc7cba04fdb3e52dfda328f3302ba17 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 18 Jan 2023 15:40:58 +0000
+Subject: [PATCH 04/42] thermal/drivers/mtk: Add support for MT7986 and MT7981
+
+Add support for V3 generation thermal found in MT7986 and MT7981 SoCs.
+Brings code to assign values from efuse as well as new function to
+convert raw temperature to millidegree celsius, as found in MediaTek's
+SDK sources (but cleaned up and de-duplicated)
+
+[1]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/baf36c7eef477aae1f8f2653b6c29e2caf48475b
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/2d341fc45266217249586eb4bd3be3ac4ca83a12.1674055882.git.daniel@makrotopia.org
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mtk_thermal.c | 128 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 124 insertions(+), 4 deletions(-)
+
+--- a/drivers/thermal/mtk_thermal.c
++++ b/drivers/thermal/mtk_thermal.c
+@@ -150,6 +150,20 @@
+ #define CALIB_BUF1_VALID_V2(x)                (((x) >> 4) & 0x1)
+ #define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
++/*
++ * Layout of the fuses providing the calibration data
++ * These macros can be used for MT7981 and MT7986.
++ */
++#define CALIB_BUF0_ADC_GE_V3(x)               (((x) >> 0) & 0x3ff)
++#define CALIB_BUF0_DEGC_CALI_V3(x)    (((x) >> 20) & 0x3f)
++#define CALIB_BUF0_O_SLOPE_V3(x)      (((x) >> 26) & 0x3f)
++#define CALIB_BUF1_VTS_TS1_V3(x)      (((x) >> 0) & 0x1ff)
++#define CALIB_BUF1_VTS_TS2_V3(x)      (((x) >> 21) & 0x1ff)
++#define CALIB_BUF1_VTS_TSABB_V3(x)    (((x) >> 9) & 0x1ff)
++#define CALIB_BUF1_VALID_V3(x)                (((x) >> 18) & 0x1)
++#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1)
++#define CALIB_BUF1_ID_V3(x)           (((x) >> 20) & 0x1)
++
+ enum {
+       VTS1,
+       VTS2,
+@@ -163,6 +177,7 @@ enum {
+ enum mtk_thermal_version {
+       MTK_THERMAL_V1 = 1,
+       MTK_THERMAL_V2,
++      MTK_THERMAL_V3,
+ };
+ /* MT2701 thermal sensors */
+@@ -245,6 +260,27 @@ enum mtk_thermal_version {
+ /* The calibration coefficient of sensor  */
+ #define MT8183_CALIBRATION    153
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT7986_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT7986 */
++#define MT7986_NUM_SENSORS            1
++
++/* The number of banks in the MT7986 */
++#define MT7986_NUM_ZONES              1
++
++/* The number of sensing points per bank */
++#define MT7986_NUM_SENSORS_PER_ZONE   1
++
++/* MT7986 thermal sensors */
++#define MT7986_TS1                    0
++
++/* The number of controller in the MT7986 */
++#define MT7986_NUM_CONTROLLER         1
++
++/* The calibration coefficient of sensor  */
++#define MT7986_CALIBRATION            165
++
+ struct mtk_thermal;
+ struct thermal_bank_cfg {
+@@ -388,6 +424,14 @@ static const int mt7622_mux_values[MT762
+ static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
+ static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
++/* MT7986 thermal sensor data */
++static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, };
++static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
++static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
++static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, };
++static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
++static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
++
+ /*
+  * The MT8173 thermal controller has four banks. Each bank can read up to
+  * four temperature sensors simultaneously. The MT8173 has a total of 5
+@@ -551,6 +595,30 @@ static const struct mtk_thermal_data mt8
+       .version = MTK_THERMAL_V1,
+ };
++/*
++ * MT7986 uses AUXADC Channel 11 for raw data access.
++ */
++static const struct mtk_thermal_data mt7986_thermal_data = {
++      .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT7986_NUM_ZONES,
++      .num_sensors = MT7986_NUM_SENSORS,
++      .vts_index = mt7986_vts_index,
++      .cali_val = MT7986_CALIBRATION,
++      .num_controller = MT7986_NUM_CONTROLLER,
++      .controller_offset = mt7986_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 1,
++                      .sensors = mt7986_bank_data,
++              },
++      },
++      .msr = mt7986_msr,
++      .adcpnp = mt7986_adcpnp,
++      .sensor_mux_values = mt7986_mux_values,
++      .version = MTK_THERMAL_V3,
++};
++
+ /**
+  * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
+  * @mt:       The thermal controller
+@@ -605,6 +673,22 @@ static int raw_to_mcelsius_v2(struct mtk
+       return (format_2 - tmp) * 100;
+ }
++static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw)
++{
++      s32 tmp;
++
++      if (raw == 0)
++              return 0;
++
++      raw &= 0xfff;
++      tmp = 100000 * 15 / 16 * 10000;
++      tmp /= 4096 - 512 + mt->adc_ge;
++      tmp /= 1490;
++      tmp *= raw - mt->vts[sensno] - 2900;
++
++      return mt->degc_cali * 500 - tmp;
++}
++
+ /**
+  * mtk_thermal_get_bank - get bank
+  * @bank:     The bank
+@@ -885,6 +969,25 @@ static int mtk_thermal_extract_efuse_v2(
+       return 0;
+ }
++static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf)
++{
++      if (!CALIB_BUF1_VALID_V3(buf[1]))
++              return -EINVAL;
++
++      mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]);
++      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]);
++      mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]);
++      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]);
++      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]);
++      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]);
++      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]);
++
++      if (CALIB_BUF1_ID_V3(buf[1]) == 0)
++              mt->o_slope = 0;
++
++      return 0;
++}
++
+ static int mtk_thermal_get_calibration_data(struct device *dev,
+                                           struct mtk_thermal *mt)
+ {
+@@ -895,6 +998,7 @@ static int mtk_thermal_get_calibration_d
+       /* Start with default values */
+       mt->adc_ge = 512;
++      mt->adc_oe = 512;
+       for (i = 0; i < mt->conf->num_sensors; i++)
+               mt->vts[i] = 260;
+       mt->degc_cali = 40;
+@@ -920,10 +1024,20 @@ static int mtk_thermal_get_calibration_d
+               goto out;
+       }
+-      if (mt->conf->version == MTK_THERMAL_V1)
++      switch (mt->conf->version) {
++      case MTK_THERMAL_V1:
+               ret = mtk_thermal_extract_efuse_v1(mt, buf);
+-      else
++              break;
++      case MTK_THERMAL_V2:
+               ret = mtk_thermal_extract_efuse_v2(mt, buf);
++              break;
++      case MTK_THERMAL_V3:
++              ret = mtk_thermal_extract_efuse_v3(mt, buf);
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
+       if (ret) {
+               dev_info(dev, "Device not calibrated, using default calibration values\n");
+@@ -954,6 +1068,10 @@ static const struct of_device_id mtk_the
+               .data = (void *)&mt7622_thermal_data,
+       },
+       {
++              .compatible = "mediatek,mt7986-thermal",
++              .data = (void *)&mt7986_thermal_data,
++      },
++      {
+               .compatible = "mediatek,mt8183-thermal",
+               .data = (void *)&mt8183_thermal_data,
+       }, {
+@@ -1066,15 +1184,17 @@ static int mtk_thermal_probe(struct plat
+               goto err_disable_clk_auxadc;
+       }
+-      if (mt->conf->version == MTK_THERMAL_V2) {
++      if (mt->conf->version != MTK_THERMAL_V1) {
+               mtk_thermal_turn_on_buffer(apmixed_base);
+               mtk_thermal_release_periodic_ts(mt, auxadc_base);
+       }
+       if (mt->conf->version == MTK_THERMAL_V1)
+               mt->raw_to_mcelsius = raw_to_mcelsius_v1;
+-      else
++      else if (mt->conf->version == MTK_THERMAL_V2)
+               mt->raw_to_mcelsius = raw_to_mcelsius_v2;
++      else
++              mt->raw_to_mcelsius = raw_to_mcelsius_v3;
+       for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+               for (i = 0; i < mt->conf->num_banks; i++)
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch b/target/linux/mediatek/patches-6.1/830-v6.3-05-thermal-drivers-mediatek-Relocate-driver-to-mediatek.patch
new file mode 100644 (file)
index 0000000..e102a33
--- /dev/null
@@ -0,0 +1,2602 @@
+From 5e3aac197a74914ccec2732a89c29d960730d28f Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Thu, 9 Feb 2023 11:56:23 +0100
+Subject: [PATCH 05/42] thermal/drivers/mediatek: Relocate driver to mediatek
+ folder
+
+Add MediaTek proprietary folder to upstream more thermal zone and cooler
+drivers, relocate the original thermal controller driver to it, and rename it
+as "auxadc_thermal.c" to show its purpose more clearly.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230209105628.50294-2-bchihi@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/Kconfig                       | 14 ++++---------
+ drivers/thermal/Makefile                      |  2 +-
+ drivers/thermal/mediatek/Kconfig              | 21 +++++++++++++++++++
+ drivers/thermal/mediatek/Makefile             |  1 +
+ .../auxadc_thermal.c}                         |  2 +-
+ 5 files changed, 28 insertions(+), 12 deletions(-)
+ create mode 100644 drivers/thermal/mediatek/Kconfig
+ create mode 100644 drivers/thermal/mediatek/Makefile
+ rename drivers/thermal/{mtk_thermal.c => mediatek/auxadc_thermal.c} (99%)
+
+--- 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"
+--- a/drivers/thermal/Makefile
++++ b/drivers/thermal/Makefile
+@@ -55,7 +55,7 @@ obj-y                                += st/
+ obj-y                         += qcom/
+ obj-y                         += tegra/
+ obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
+-obj-$(CONFIG_MTK_THERMAL)     += mtk_thermal.o
++obj-y                         += mediatek/
+ obj-$(CONFIG_GENERIC_ADC_THERMAL)     += thermal-generic-adc.o
+ obj-$(CONFIG_UNIPHIER_THERMAL)        += uniphier_thermal.o
+ obj-$(CONFIG_AMLOGIC_THERMAL)     += amlogic_thermal.o
+--- /dev/null
++++ b/drivers/thermal/mediatek/Kconfig
+@@ -0,0 +1,21 @@
++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 "AUXADC temperature sensor driver for MediaTek SoCs"
++      depends on HAS_IOMEM
++      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
+--- /dev/null
++++ b/drivers/thermal/mediatek/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o
+--- a/drivers/thermal/mtk_thermal.c
++++ /dev/null
+@@ -1,1254 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- * Copyright (c) 2015 MediaTek Inc.
+- * Author: Hanyi Wu <hanyi.wu@mediatek.com>
+- *         Sascha Hauer <s.hauer@pengutronix.de>
+- *         Dawei Chien <dawei.chien@mediatek.com>
+- *         Louis Yu <louis.yu@mediatek.com>
+- */
+-
+-#include <linux/clk.h>
+-#include <linux/delay.h>
+-#include <linux/interrupt.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/platform_device.h>
+-#include <linux/slab.h>
+-#include <linux/io.h>
+-#include <linux/thermal.h>
+-#include <linux/reset.h>
+-#include <linux/types.h>
+-
+-#include "thermal_hwmon.h"
+-
+-/* AUXADC Registers */
+-#define AUXADC_CON1_SET_V     0x008
+-#define AUXADC_CON1_CLR_V     0x00c
+-#define AUXADC_CON2_V         0x010
+-#define AUXADC_DATA(channel)  (0x14 + (channel) * 4)
+-
+-#define APMIXED_SYS_TS_CON1   0x604
+-
+-/* Thermal Controller Registers */
+-#define TEMP_MONCTL0          0x000
+-#define TEMP_MONCTL1          0x004
+-#define TEMP_MONCTL2          0x008
+-#define TEMP_MONIDET0         0x014
+-#define TEMP_MONIDET1         0x018
+-#define TEMP_MSRCTL0          0x038
+-#define TEMP_MSRCTL1          0x03c
+-#define TEMP_AHBPOLL          0x040
+-#define TEMP_AHBTO            0x044
+-#define TEMP_ADCPNP0          0x048
+-#define TEMP_ADCPNP1          0x04c
+-#define TEMP_ADCPNP2          0x050
+-#define TEMP_ADCPNP3          0x0b4
+-
+-#define TEMP_ADCMUX           0x054
+-#define TEMP_ADCEN            0x060
+-#define TEMP_PNPMUXADDR               0x064
+-#define TEMP_ADCMUXADDR               0x068
+-#define TEMP_ADCENADDR                0x074
+-#define TEMP_ADCVALIDADDR     0x078
+-#define TEMP_ADCVOLTADDR      0x07c
+-#define TEMP_RDCTRL           0x080
+-#define TEMP_ADCVALIDMASK     0x084
+-#define TEMP_ADCVOLTAGESHIFT  0x088
+-#define TEMP_ADCWRITECTRL     0x08c
+-#define TEMP_MSR0             0x090
+-#define TEMP_MSR1             0x094
+-#define TEMP_MSR2             0x098
+-#define TEMP_MSR3             0x0B8
+-
+-#define TEMP_SPARE0           0x0f0
+-
+-#define TEMP_ADCPNP0_1          0x148
+-#define TEMP_ADCPNP1_1          0x14c
+-#define TEMP_ADCPNP2_1          0x150
+-#define TEMP_MSR0_1             0x190
+-#define TEMP_MSR1_1             0x194
+-#define TEMP_MSR2_1             0x198
+-#define TEMP_ADCPNP3_1          0x1b4
+-#define TEMP_MSR3_1             0x1B8
+-
+-#define PTPCORESEL            0x400
+-
+-#define TEMP_MONCTL1_PERIOD_UNIT(x)   ((x) & 0x3ff)
+-
+-#define TEMP_MONCTL2_FILTER_INTERVAL(x)       (((x) & 0x3ff) << 16)
+-#define TEMP_MONCTL2_SENSOR_INTERVAL(x)       ((x) & 0x3ff)
+-
+-#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x)     (x)
+-
+-#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE               BIT(0)
+-#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE               BIT(1)
+-
+-#define TEMP_ADCVALIDMASK_VALID_HIGH          BIT(5)
+-#define TEMP_ADCVALIDMASK_VALID_POS(bit)      (bit)
+-
+-/* MT8173 thermal sensors */
+-#define MT8173_TS1    0
+-#define MT8173_TS2    1
+-#define MT8173_TS3    2
+-#define MT8173_TS4    3
+-#define MT8173_TSABB  4
+-
+-/* AUXADC channel 11 is used for the temperature sensors */
+-#define MT8173_TEMP_AUXADC_CHANNEL    11
+-
+-/* The total number of temperature sensors in the MT8173 */
+-#define MT8173_NUM_SENSORS            5
+-
+-/* The number of banks in the MT8173 */
+-#define MT8173_NUM_ZONES              4
+-
+-/* The number of sensing points per bank */
+-#define MT8173_NUM_SENSORS_PER_ZONE   4
+-
+-/* The number of controller in the MT8173 */
+-#define MT8173_NUM_CONTROLLER         1
+-
+-/* The calibration coefficient of sensor  */
+-#define MT8173_CALIBRATION    165
+-
+-/*
+- * Layout of the fuses providing the calibration data
+- * These macros could be used for MT8183, MT8173, MT2701, and MT2712.
+- * MT8183 has 6 sensors and needs 6 VTS calibration data.
+- * MT8173 has 5 sensors and needs 5 VTS calibration data.
+- * MT2701 has 3 sensors and needs 3 VTS calibration data.
+- * MT2712 has 4 sensors and needs 4 VTS calibration data.
+- */
+-#define CALIB_BUF0_VALID_V1           BIT(0)
+-#define CALIB_BUF1_ADC_GE_V1(x)               (((x) >> 22) & 0x3ff)
+-#define CALIB_BUF0_VTS_TS1_V1(x)      (((x) >> 17) & 0x1ff)
+-#define CALIB_BUF0_VTS_TS2_V1(x)      (((x) >> 8) & 0x1ff)
+-#define CALIB_BUF1_VTS_TS3_V1(x)      (((x) >> 0) & 0x1ff)
+-#define CALIB_BUF2_VTS_TS4_V1(x)      (((x) >> 23) & 0x1ff)
+-#define CALIB_BUF2_VTS_TS5_V1(x)      (((x) >> 5) & 0x1ff)
+-#define CALIB_BUF2_VTS_TSABB_V1(x)    (((x) >> 14) & 0x1ff)
+-#define CALIB_BUF0_DEGC_CALI_V1(x)    (((x) >> 1) & 0x3f)
+-#define CALIB_BUF0_O_SLOPE_V1(x)      (((x) >> 26) & 0x3f)
+-#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1)
+-#define CALIB_BUF1_ID_V1(x)           (((x) >> 9) & 0x1)
+-
+-/*
+- * Layout of the fuses providing the calibration data
+- * These macros could be used for MT7622.
+- */
+-#define CALIB_BUF0_ADC_OE_V2(x)               (((x) >> 22) & 0x3ff)
+-#define CALIB_BUF0_ADC_GE_V2(x)               (((x) >> 12) & 0x3ff)
+-#define CALIB_BUF0_DEGC_CALI_V2(x)    (((x) >> 6) & 0x3f)
+-#define CALIB_BUF0_O_SLOPE_V2(x)      (((x) >> 0) & 0x3f)
+-#define CALIB_BUF1_VTS_TS1_V2(x)      (((x) >> 23) & 0x1ff)
+-#define CALIB_BUF1_VTS_TS2_V2(x)      (((x) >> 14) & 0x1ff)
+-#define CALIB_BUF1_VTS_TSABB_V2(x)    (((x) >> 5) & 0x1ff)
+-#define CALIB_BUF1_VALID_V2(x)                (((x) >> 4) & 0x1)
+-#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
+-
+-/*
+- * Layout of the fuses providing the calibration data
+- * These macros can be used for MT7981 and MT7986.
+- */
+-#define CALIB_BUF0_ADC_GE_V3(x)               (((x) >> 0) & 0x3ff)
+-#define CALIB_BUF0_DEGC_CALI_V3(x)    (((x) >> 20) & 0x3f)
+-#define CALIB_BUF0_O_SLOPE_V3(x)      (((x) >> 26) & 0x3f)
+-#define CALIB_BUF1_VTS_TS1_V3(x)      (((x) >> 0) & 0x1ff)
+-#define CALIB_BUF1_VTS_TS2_V3(x)      (((x) >> 21) & 0x1ff)
+-#define CALIB_BUF1_VTS_TSABB_V3(x)    (((x) >> 9) & 0x1ff)
+-#define CALIB_BUF1_VALID_V3(x)                (((x) >> 18) & 0x1)
+-#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1)
+-#define CALIB_BUF1_ID_V3(x)           (((x) >> 20) & 0x1)
+-
+-enum {
+-      VTS1,
+-      VTS2,
+-      VTS3,
+-      VTS4,
+-      VTS5,
+-      VTSABB,
+-      MAX_NUM_VTS,
+-};
+-
+-enum mtk_thermal_version {
+-      MTK_THERMAL_V1 = 1,
+-      MTK_THERMAL_V2,
+-      MTK_THERMAL_V3,
+-};
+-
+-/* MT2701 thermal sensors */
+-#define MT2701_TS1    0
+-#define MT2701_TS2    1
+-#define MT2701_TSABB  2
+-
+-/* AUXADC channel 11 is used for the temperature sensors */
+-#define MT2701_TEMP_AUXADC_CHANNEL    11
+-
+-/* The total number of temperature sensors in the MT2701 */
+-#define MT2701_NUM_SENSORS    3
+-
+-/* The number of sensing points per bank */
+-#define MT2701_NUM_SENSORS_PER_ZONE   3
+-
+-/* The number of controller in the MT2701 */
+-#define MT2701_NUM_CONTROLLER         1
+-
+-/* The calibration coefficient of sensor  */
+-#define MT2701_CALIBRATION    165
+-
+-/* MT2712 thermal sensors */
+-#define MT2712_TS1    0
+-#define MT2712_TS2    1
+-#define MT2712_TS3    2
+-#define MT2712_TS4    3
+-
+-/* AUXADC channel 11 is used for the temperature sensors */
+-#define MT2712_TEMP_AUXADC_CHANNEL    11
+-
+-/* The total number of temperature sensors in the MT2712 */
+-#define MT2712_NUM_SENSORS    4
+-
+-/* The number of sensing points per bank */
+-#define MT2712_NUM_SENSORS_PER_ZONE   4
+-
+-/* The number of controller in the MT2712 */
+-#define MT2712_NUM_CONTROLLER         1
+-
+-/* The calibration coefficient of sensor  */
+-#define MT2712_CALIBRATION    165
+-
+-#define MT7622_TEMP_AUXADC_CHANNEL    11
+-#define MT7622_NUM_SENSORS            1
+-#define MT7622_NUM_ZONES              1
+-#define MT7622_NUM_SENSORS_PER_ZONE   1
+-#define MT7622_TS1    0
+-#define MT7622_NUM_CONTROLLER         1
+-
+-/* The maximum number of banks */
+-#define MAX_NUM_ZONES         8
+-
+-/* The calibration coefficient of sensor  */
+-#define MT7622_CALIBRATION    165
+-
+-/* MT8183 thermal sensors */
+-#define MT8183_TS1    0
+-#define MT8183_TS2    1
+-#define MT8183_TS3    2
+-#define MT8183_TS4    3
+-#define MT8183_TS5    4
+-#define MT8183_TSABB  5
+-
+-/* AUXADC channel  is used for the temperature sensors */
+-#define MT8183_TEMP_AUXADC_CHANNEL    11
+-
+-/* The total number of temperature sensors in the MT8183 */
+-#define MT8183_NUM_SENSORS    6
+-
+-/* The number of banks in the MT8183 */
+-#define MT8183_NUM_ZONES               1
+-
+-/* The number of sensing points per bank */
+-#define MT8183_NUM_SENSORS_PER_ZONE    6
+-
+-/* The number of controller in the MT8183 */
+-#define MT8183_NUM_CONTROLLER         2
+-
+-/* The calibration coefficient of sensor  */
+-#define MT8183_CALIBRATION    153
+-
+-/* AUXADC channel 11 is used for the temperature sensors */
+-#define MT7986_TEMP_AUXADC_CHANNEL    11
+-
+-/* The total number of temperature sensors in the MT7986 */
+-#define MT7986_NUM_SENSORS            1
+-
+-/* The number of banks in the MT7986 */
+-#define MT7986_NUM_ZONES              1
+-
+-/* The number of sensing points per bank */
+-#define MT7986_NUM_SENSORS_PER_ZONE   1
+-
+-/* MT7986 thermal sensors */
+-#define MT7986_TS1                    0
+-
+-/* The number of controller in the MT7986 */
+-#define MT7986_NUM_CONTROLLER         1
+-
+-/* The calibration coefficient of sensor  */
+-#define MT7986_CALIBRATION            165
+-
+-struct mtk_thermal;
+-
+-struct thermal_bank_cfg {
+-      unsigned int num_sensors;
+-      const int *sensors;
+-};
+-
+-struct mtk_thermal_bank {
+-      struct mtk_thermal *mt;
+-      int id;
+-};
+-
+-struct mtk_thermal_data {
+-      s32 num_banks;
+-      s32 num_sensors;
+-      s32 auxadc_channel;
+-      const int *vts_index;
+-      const int *sensor_mux_values;
+-      const int *msr;
+-      const int *adcpnp;
+-      const int cali_val;
+-      const int num_controller;
+-      const int *controller_offset;
+-      bool need_switch_bank;
+-      struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
+-      enum mtk_thermal_version version;
+-};
+-
+-struct mtk_thermal {
+-      struct device *dev;
+-      void __iomem *thermal_base;
+-
+-      struct clk *clk_peri_therm;
+-      struct clk *clk_auxadc;
+-      /* lock: for getting and putting banks */
+-      struct mutex lock;
+-
+-      /* Calibration values */
+-      s32 adc_ge;
+-      s32 adc_oe;
+-      s32 degc_cali;
+-      s32 o_slope;
+-      s32 o_slope_sign;
+-      s32 vts[MAX_NUM_VTS];
+-
+-      const struct mtk_thermal_data *conf;
+-      struct mtk_thermal_bank banks[MAX_NUM_ZONES];
+-
+-      int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
+-};
+-
+-/* MT8183 thermal sensor data */
+-static const int mt8183_bank_data[MT8183_NUM_SENSORS] = {
+-      MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB
+-};
+-
+-static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1
+-};
+-
+-static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1,
+-      TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1
+-};
+-
+-static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 };
+-static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100};
+-
+-static const int mt8183_vts_index[MT8183_NUM_SENSORS] = {
+-      VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB
+-};
+-
+-/* MT8173 thermal sensor data */
+-static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
+-      { MT8173_TS2, MT8173_TS3 },
+-      { MT8173_TS2, MT8173_TS4 },
+-      { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
+-      { MT8173_TS2 },
+-};
+-
+-static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
+-};
+-
+-static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
+-};
+-
+-static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
+-static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, };
+-
+-static const int mt8173_vts_index[MT8173_NUM_SENSORS] = {
+-      VTS1, VTS2, VTS3, VTS4, VTSABB
+-};
+-
+-/* MT2701 thermal sensor data */
+-static const int mt2701_bank_data[MT2701_NUM_SENSORS] = {
+-      MT2701_TS1, MT2701_TS2, MT2701_TSABB
+-};
+-
+-static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
+-};
+-
+-static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
+-};
+-
+-static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 };
+-static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, };
+-
+-static const int mt2701_vts_index[MT2701_NUM_SENSORS] = {
+-      VTS1, VTS2, VTS3
+-};
+-
+-/* MT2712 thermal sensor data */
+-static const int mt2712_bank_data[MT2712_NUM_SENSORS] = {
+-      MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4
+-};
+-
+-static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
+-};
+-
+-static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = {
+-      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
+-};
+-
+-static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 };
+-static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, };
+-
+-static const int mt2712_vts_index[MT2712_NUM_SENSORS] = {
+-      VTS1, VTS2, VTS3, VTS4
+-};
+-
+-/* MT7622 thermal sensor data */
+-static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, };
+-static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
+-static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
+-static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
+-static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
+-static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
+-
+-/* MT7986 thermal sensor data */
+-static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, };
+-static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
+-static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
+-static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, };
+-static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
+-static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
+-
+-/*
+- * The MT8173 thermal controller has four banks. Each bank can read up to
+- * four temperature sensors simultaneously. The MT8173 has a total of 5
+- * temperature sensors. We use each bank to measure a certain area of the
+- * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple
+- * areas, hence is used in different banks.
+- *
+- * The thermal core only gets the maximum temperature of all banks, so
+- * the bank concept wouldn't be necessary here. However, the SVS (Smart
+- * Voltage Scaling) unit makes its decisions based on the same bank
+- * data, and this indeed needs the temperatures of the individual banks
+- * for making better decisions.
+- */
+-static const struct mtk_thermal_data mt8173_thermal_data = {
+-      .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL,
+-      .num_banks = MT8173_NUM_ZONES,
+-      .num_sensors = MT8173_NUM_SENSORS,
+-      .vts_index = mt8173_vts_index,
+-      .cali_val = MT8173_CALIBRATION,
+-      .num_controller = MT8173_NUM_CONTROLLER,
+-      .controller_offset = mt8173_tc_offset,
+-      .need_switch_bank = true,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 2,
+-                      .sensors = mt8173_bank_data[0],
+-              }, {
+-                      .num_sensors = 2,
+-                      .sensors = mt8173_bank_data[1],
+-              }, {
+-                      .num_sensors = 3,
+-                      .sensors = mt8173_bank_data[2],
+-              }, {
+-                      .num_sensors = 1,
+-                      .sensors = mt8173_bank_data[3],
+-              },
+-      },
+-      .msr = mt8173_msr,
+-      .adcpnp = mt8173_adcpnp,
+-      .sensor_mux_values = mt8173_mux_values,
+-      .version = MTK_THERMAL_V1,
+-};
+-
+-/*
+- * The MT2701 thermal controller has one bank, which can read up to
+- * three temperature sensors simultaneously. The MT2701 has a total of 3
+- * temperature sensors.
+- *
+- * The thermal core only gets the maximum temperature of this one bank,
+- * so the bank concept wouldn't be necessary here. However, the SVS (Smart
+- * Voltage Scaling) unit makes its decisions based on the same bank
+- * data.
+- */
+-static const struct mtk_thermal_data mt2701_thermal_data = {
+-      .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL,
+-      .num_banks = 1,
+-      .num_sensors = MT2701_NUM_SENSORS,
+-      .vts_index = mt2701_vts_index,
+-      .cali_val = MT2701_CALIBRATION,
+-      .num_controller = MT2701_NUM_CONTROLLER,
+-      .controller_offset = mt2701_tc_offset,
+-      .need_switch_bank = true,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 3,
+-                      .sensors = mt2701_bank_data,
+-              },
+-      },
+-      .msr = mt2701_msr,
+-      .adcpnp = mt2701_adcpnp,
+-      .sensor_mux_values = mt2701_mux_values,
+-      .version = MTK_THERMAL_V1,
+-};
+-
+-/*
+- * The MT2712 thermal controller has one bank, which can read up to
+- * four temperature sensors simultaneously. The MT2712 has a total of 4
+- * temperature sensors.
+- *
+- * The thermal core only gets the maximum temperature of this one bank,
+- * so the bank concept wouldn't be necessary here. However, the SVS (Smart
+- * Voltage Scaling) unit makes its decisions based on the same bank
+- * data.
+- */
+-static const struct mtk_thermal_data mt2712_thermal_data = {
+-      .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL,
+-      .num_banks = 1,
+-      .num_sensors = MT2712_NUM_SENSORS,
+-      .vts_index = mt2712_vts_index,
+-      .cali_val = MT2712_CALIBRATION,
+-      .num_controller = MT2712_NUM_CONTROLLER,
+-      .controller_offset = mt2712_tc_offset,
+-      .need_switch_bank = true,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 4,
+-                      .sensors = mt2712_bank_data,
+-              },
+-      },
+-      .msr = mt2712_msr,
+-      .adcpnp = mt2712_adcpnp,
+-      .sensor_mux_values = mt2712_mux_values,
+-      .version = MTK_THERMAL_V1,
+-};
+-
+-/*
+- * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data
+- * access.
+- */
+-static const struct mtk_thermal_data mt7622_thermal_data = {
+-      .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL,
+-      .num_banks = MT7622_NUM_ZONES,
+-      .num_sensors = MT7622_NUM_SENSORS,
+-      .vts_index = mt7622_vts_index,
+-      .cali_val = MT7622_CALIBRATION,
+-      .num_controller = MT7622_NUM_CONTROLLER,
+-      .controller_offset = mt7622_tc_offset,
+-      .need_switch_bank = true,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 1,
+-                      .sensors = mt7622_bank_data,
+-              },
+-      },
+-      .msr = mt7622_msr,
+-      .adcpnp = mt7622_adcpnp,
+-      .sensor_mux_values = mt7622_mux_values,
+-      .version = MTK_THERMAL_V2,
+-};
+-
+-/*
+- * The MT8183 thermal controller has one bank for the current SW framework.
+- * The MT8183 has a total of 6 temperature sensors.
+- * There are two thermal controller to control the six sensor.
+- * The first one bind 2 sensor, and the other bind 4 sensors.
+- * The thermal core only gets the maximum temperature of all sensor, so
+- * the bank concept wouldn't be necessary here. However, the SVS (Smart
+- * Voltage Scaling) unit makes its decisions based on the same bank
+- * data, and this indeed needs the temperatures of the individual banks
+- * for making better decisions.
+- */
+-static const struct mtk_thermal_data mt8183_thermal_data = {
+-      .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL,
+-      .num_banks = MT8183_NUM_ZONES,
+-      .num_sensors = MT8183_NUM_SENSORS,
+-      .vts_index = mt8183_vts_index,
+-      .cali_val = MT8183_CALIBRATION,
+-      .num_controller = MT8183_NUM_CONTROLLER,
+-      .controller_offset = mt8183_tc_offset,
+-      .need_switch_bank = false,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 6,
+-                      .sensors = mt8183_bank_data,
+-              },
+-      },
+-
+-      .msr = mt8183_msr,
+-      .adcpnp = mt8183_adcpnp,
+-      .sensor_mux_values = mt8183_mux_values,
+-      .version = MTK_THERMAL_V1,
+-};
+-
+-/*
+- * MT7986 uses AUXADC Channel 11 for raw data access.
+- */
+-static const struct mtk_thermal_data mt7986_thermal_data = {
+-      .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL,
+-      .num_banks = MT7986_NUM_ZONES,
+-      .num_sensors = MT7986_NUM_SENSORS,
+-      .vts_index = mt7986_vts_index,
+-      .cali_val = MT7986_CALIBRATION,
+-      .num_controller = MT7986_NUM_CONTROLLER,
+-      .controller_offset = mt7986_tc_offset,
+-      .need_switch_bank = true,
+-      .bank_data = {
+-              {
+-                      .num_sensors = 1,
+-                      .sensors = mt7986_bank_data,
+-              },
+-      },
+-      .msr = mt7986_msr,
+-      .adcpnp = mt7986_adcpnp,
+-      .sensor_mux_values = mt7986_mux_values,
+-      .version = MTK_THERMAL_V3,
+-};
+-
+-/**
+- * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
+- * @mt:       The thermal controller
+- * @sensno:   sensor number
+- * @raw:      raw ADC value
+- *
+- * This converts the raw ADC value to mcelsius using the SoC specific
+- * calibration constants
+- */
+-static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw)
+-{
+-      s32 tmp;
+-
+-      raw &= 0xfff;
+-
+-      tmp = 203450520 << 3;
+-      tmp /= mt->conf->cali_val + mt->o_slope;
+-      tmp /= 10000 + mt->adc_ge;
+-      tmp *= raw - mt->vts[sensno] - 3350;
+-      tmp >>= 3;
+-
+-      return mt->degc_cali * 500 - tmp;
+-}
+-
+-static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw)
+-{
+-      s32 format_1;
+-      s32 format_2;
+-      s32 g_oe;
+-      s32 g_gain;
+-      s32 g_x_roomt;
+-      s32 tmp;
+-
+-      if (raw == 0)
+-              return 0;
+-
+-      raw &= 0xfff;
+-      g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12);
+-      g_oe = mt->adc_oe - 512;
+-      format_1 = mt->vts[VTS2] + 3105 - g_oe;
+-      format_2 = (mt->degc_cali * 10) >> 1;
+-      g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain;
+-
+-      tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt;
+-      tmp = tmp * 10 * 100 / 11;
+-
+-      if (mt->o_slope_sign == 0)
+-              tmp = tmp / (165 - mt->o_slope);
+-      else
+-              tmp = tmp / (165 + mt->o_slope);
+-
+-      return (format_2 - tmp) * 100;
+-}
+-
+-static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw)
+-{
+-      s32 tmp;
+-
+-      if (raw == 0)
+-              return 0;
+-
+-      raw &= 0xfff;
+-      tmp = 100000 * 15 / 16 * 10000;
+-      tmp /= 4096 - 512 + mt->adc_ge;
+-      tmp /= 1490;
+-      tmp *= raw - mt->vts[sensno] - 2900;
+-
+-      return mt->degc_cali * 500 - tmp;
+-}
+-
+-/**
+- * mtk_thermal_get_bank - get bank
+- * @bank:     The bank
+- *
+- * The bank registers are banked, we have to select a bank in the
+- * PTPCORESEL register to access it.
+- */
+-static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
+-{
+-      struct mtk_thermal *mt = bank->mt;
+-      u32 val;
+-
+-      if (mt->conf->need_switch_bank) {
+-              mutex_lock(&mt->lock);
+-
+-              val = readl(mt->thermal_base + PTPCORESEL);
+-              val &= ~0xf;
+-              val |= bank->id;
+-              writel(val, mt->thermal_base + PTPCORESEL);
+-      }
+-}
+-
+-/**
+- * mtk_thermal_put_bank - release bank
+- * @bank:     The bank
+- *
+- * release a bank previously taken with mtk_thermal_get_bank,
+- */
+-static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
+-{
+-      struct mtk_thermal *mt = bank->mt;
+-
+-      if (mt->conf->need_switch_bank)
+-              mutex_unlock(&mt->lock);
+-}
+-
+-/**
+- * mtk_thermal_bank_temperature - get the temperature of a bank
+- * @bank:     The bank
+- *
+- * The temperature of a bank is considered the maximum temperature of
+- * the sensors associated to the bank.
+- */
+-static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
+-{
+-      struct mtk_thermal *mt = bank->mt;
+-      const struct mtk_thermal_data *conf = mt->conf;
+-      int i, temp = INT_MIN, max = INT_MIN;
+-      u32 raw;
+-
+-      for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
+-              raw = readl(mt->thermal_base + conf->msr[i]);
+-
+-              temp = mt->raw_to_mcelsius(
+-                      mt, conf->bank_data[bank->id].sensors[i], raw);
+-
+-
+-              /*
+-               * The first read of a sensor often contains very high bogus
+-               * temperature value. Filter these out so that the system does
+-               * not immediately shut down.
+-               */
+-              if (temp > 200000)
+-                      temp = 0;
+-
+-              if (temp > max)
+-                      max = temp;
+-      }
+-
+-      return max;
+-}
+-
+-static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
+-{
+-      struct mtk_thermal *mt = tz->devdata;
+-      int i;
+-      int tempmax = INT_MIN;
+-
+-      for (i = 0; i < mt->conf->num_banks; i++) {
+-              struct mtk_thermal_bank *bank = &mt->banks[i];
+-
+-              mtk_thermal_get_bank(bank);
+-
+-              tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
+-
+-              mtk_thermal_put_bank(bank);
+-      }
+-
+-      *temperature = tempmax;
+-
+-      return 0;
+-}
+-
+-static const struct thermal_zone_device_ops mtk_thermal_ops = {
+-      .get_temp = mtk_read_temp,
+-};
+-
+-static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
+-                                u32 apmixed_phys_base, u32 auxadc_phys_base,
+-                                int ctrl_id)
+-{
+-      struct mtk_thermal_bank *bank = &mt->banks[num];
+-      const struct mtk_thermal_data *conf = mt->conf;
+-      int i;
+-
+-      int offset = mt->conf->controller_offset[ctrl_id];
+-      void __iomem *controller_base = mt->thermal_base + offset;
+-
+-      bank->id = num;
+-      bank->mt = mt;
+-
+-      mtk_thermal_get_bank(bank);
+-
+-      /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
+-      writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1);
+-
+-      /*
+-       * filt interval is 1 * 46.540us = 46.54us,
+-       * sen interval is 429 * 46.540us = 19.96ms
+-       */
+-      writel(TEMP_MONCTL2_FILTER_INTERVAL(1) |
+-                      TEMP_MONCTL2_SENSOR_INTERVAL(429),
+-                      controller_base + TEMP_MONCTL2);
+-
+-      /* poll is set to 10u */
+-      writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768),
+-             controller_base + TEMP_AHBPOLL);
+-
+-      /* temperature sampling control, 1 sample */
+-      writel(0x0, controller_base + TEMP_MSRCTL0);
+-
+-      /* exceed this polling time, IRQ would be inserted */
+-      writel(0xffffffff, controller_base + TEMP_AHBTO);
+-
+-      /* number of interrupts per event, 1 is enough */
+-      writel(0x0, controller_base + TEMP_MONIDET0);
+-      writel(0x0, controller_base + TEMP_MONIDET1);
+-
+-      /*
+-       * The MT8173 thermal controller does not have its own ADC. Instead it
+-       * uses AHB bus accesses to control the AUXADC. To do this the thermal
+-       * controller has to be programmed with the physical addresses of the
+-       * AUXADC registers and with the various bit positions in the AUXADC.
+-       * Also the thermal controller controls a mux in the APMIXEDSYS register
+-       * space.
+-       */
+-
+-      /*
+-       * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0)
+-       * automatically by hw
+-       */
+-      writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX);
+-
+-      /* AHB address for auxadc mux selection */
+-      writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
+-             controller_base + TEMP_ADCMUXADDR);
+-
+-      if (mt->conf->version == MTK_THERMAL_V1) {
+-              /* AHB address for pnp sensor mux selection */
+-              writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
+-                     controller_base + TEMP_PNPMUXADDR);
+-      }
+-
+-      /* AHB value for auxadc enable */
+-      writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN);
+-
+-      /* AHB address for auxadc enable (channel 0 immediate mode selected) */
+-      writel(auxadc_phys_base + AUXADC_CON1_SET_V,
+-             controller_base + TEMP_ADCENADDR);
+-
+-      /* AHB address for auxadc valid bit */
+-      writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
+-             controller_base + TEMP_ADCVALIDADDR);
+-
+-      /* AHB address for auxadc voltage output */
+-      writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
+-             controller_base + TEMP_ADCVOLTADDR);
+-
+-      /* read valid & voltage are at the same register */
+-      writel(0x0, controller_base + TEMP_RDCTRL);
+-
+-      /* indicate where the valid bit is */
+-      writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12),
+-             controller_base + TEMP_ADCVALIDMASK);
+-
+-      /* no shift */
+-      writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT);
+-
+-      /* enable auxadc mux write transaction */
+-      writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
+-              controller_base + TEMP_ADCWRITECTRL);
+-
+-      for (i = 0; i < conf->bank_data[num].num_sensors; i++)
+-              writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]],
+-                     mt->thermal_base + conf->adcpnp[i]);
+-
+-      writel((1 << conf->bank_data[num].num_sensors) - 1,
+-             controller_base + TEMP_MONCTL0);
+-
+-      writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE |
+-             TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
+-             controller_base + TEMP_ADCWRITECTRL);
+-
+-      mtk_thermal_put_bank(bank);
+-}
+-
+-static u64 of_get_phys_base(struct device_node *np)
+-{
+-      u64 size64;
+-      const __be32 *regaddr_p;
+-
+-      regaddr_p = of_get_address(np, 0, &size64, NULL);
+-      if (!regaddr_p)
+-              return OF_BAD_ADDR;
+-
+-      return of_translate_address(np, regaddr_p);
+-}
+-
+-static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf)
+-{
+-      int i;
+-
+-      if (!(buf[0] & CALIB_BUF0_VALID_V1))
+-              return -EINVAL;
+-
+-      mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]);
+-
+-      for (i = 0; i < mt->conf->num_sensors; i++) {
+-              switch (mt->conf->vts_index[i]) {
+-              case VTS1:
+-                      mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]);
+-                      break;
+-              case VTS2:
+-                      mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]);
+-                      break;
+-              case VTS3:
+-                      mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]);
+-                      break;
+-              case VTS4:
+-                      mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]);
+-                      break;
+-              case VTS5:
+-                      mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]);
+-                      break;
+-              case VTSABB:
+-                      mt->vts[VTSABB] =
+-                              CALIB_BUF2_VTS_TSABB_V1(buf[2]);
+-                      break;
+-              default:
+-                      break;
+-              }
+-      }
+-
+-      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]);
+-      if (CALIB_BUF1_ID_V1(buf[1]) &
+-          CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0]))
+-              mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]);
+-      else
+-              mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]);
+-
+-      return 0;
+-}
+-
+-static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf)
+-{
+-      if (!CALIB_BUF1_VALID_V2(buf[1]))
+-              return -EINVAL;
+-
+-      mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]);
+-      mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]);
+-      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]);
+-      mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]);
+-      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]);
+-      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]);
+-      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]);
+-      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]);
+-
+-      return 0;
+-}
+-
+-static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf)
+-{
+-      if (!CALIB_BUF1_VALID_V3(buf[1]))
+-              return -EINVAL;
+-
+-      mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]);
+-      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]);
+-      mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]);
+-      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]);
+-      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]);
+-      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]);
+-      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]);
+-
+-      if (CALIB_BUF1_ID_V3(buf[1]) == 0)
+-              mt->o_slope = 0;
+-
+-      return 0;
+-}
+-
+-static int mtk_thermal_get_calibration_data(struct device *dev,
+-                                          struct mtk_thermal *mt)
+-{
+-      struct nvmem_cell *cell;
+-      u32 *buf;
+-      size_t len;
+-      int i, ret = 0;
+-
+-      /* Start with default values */
+-      mt->adc_ge = 512;
+-      mt->adc_oe = 512;
+-      for (i = 0; i < mt->conf->num_sensors; i++)
+-              mt->vts[i] = 260;
+-      mt->degc_cali = 40;
+-      mt->o_slope = 0;
+-
+-      cell = nvmem_cell_get(dev, "calibration-data");
+-      if (IS_ERR(cell)) {
+-              if (PTR_ERR(cell) == -EPROBE_DEFER)
+-                      return PTR_ERR(cell);
+-              return 0;
+-      }
+-
+-      buf = (u32 *)nvmem_cell_read(cell, &len);
+-
+-      nvmem_cell_put(cell);
+-
+-      if (IS_ERR(buf))
+-              return PTR_ERR(buf);
+-
+-      if (len < 3 * sizeof(u32)) {
+-              dev_warn(dev, "invalid calibration data\n");
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      switch (mt->conf->version) {
+-      case MTK_THERMAL_V1:
+-              ret = mtk_thermal_extract_efuse_v1(mt, buf);
+-              break;
+-      case MTK_THERMAL_V2:
+-              ret = mtk_thermal_extract_efuse_v2(mt, buf);
+-              break;
+-      case MTK_THERMAL_V3:
+-              ret = mtk_thermal_extract_efuse_v3(mt, buf);
+-              break;
+-      default:
+-              ret = -EINVAL;
+-              break;
+-      }
+-
+-      if (ret) {
+-              dev_info(dev, "Device not calibrated, using default calibration values\n");
+-              ret = 0;
+-      }
+-
+-out:
+-      kfree(buf);
+-
+-      return ret;
+-}
+-
+-static const struct of_device_id mtk_thermal_of_match[] = {
+-      {
+-              .compatible = "mediatek,mt8173-thermal",
+-              .data = (void *)&mt8173_thermal_data,
+-      },
+-      {
+-              .compatible = "mediatek,mt2701-thermal",
+-              .data = (void *)&mt2701_thermal_data,
+-      },
+-      {
+-              .compatible = "mediatek,mt2712-thermal",
+-              .data = (void *)&mt2712_thermal_data,
+-      },
+-      {
+-              .compatible = "mediatek,mt7622-thermal",
+-              .data = (void *)&mt7622_thermal_data,
+-      },
+-      {
+-              .compatible = "mediatek,mt7986-thermal",
+-              .data = (void *)&mt7986_thermal_data,
+-      },
+-      {
+-              .compatible = "mediatek,mt8183-thermal",
+-              .data = (void *)&mt8183_thermal_data,
+-      }, {
+-      },
+-};
+-MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
+-
+-static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
+-{
+-      int tmp;
+-
+-      tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
+-      tmp &= ~(0x37);
+-      tmp |= 0x1;
+-      writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
+-      udelay(200);
+-}
+-
+-static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt,
+-                                          void __iomem *auxadc_base)
+-{
+-      int tmp;
+-
+-      writel(0x800, auxadc_base + AUXADC_CON1_SET_V);
+-      writel(0x1, mt->thermal_base + TEMP_MONCTL0);
+-      tmp = readl(mt->thermal_base + TEMP_MSRCTL1);
+-      writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1);
+-}
+-
+-static int mtk_thermal_probe(struct platform_device *pdev)
+-{
+-      int ret, i, ctrl_id;
+-      struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
+-      struct mtk_thermal *mt;
+-      u64 auxadc_phys_base, apmixed_phys_base;
+-      struct thermal_zone_device *tzdev;
+-      void __iomem *apmixed_base, *auxadc_base;
+-
+-      mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
+-      if (!mt)
+-              return -ENOMEM;
+-
+-      mt->conf = of_device_get_match_data(&pdev->dev);
+-
+-      mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
+-      if (IS_ERR(mt->clk_peri_therm))
+-              return PTR_ERR(mt->clk_peri_therm);
+-
+-      mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
+-      if (IS_ERR(mt->clk_auxadc))
+-              return PTR_ERR(mt->clk_auxadc);
+-
+-      mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+-      if (IS_ERR(mt->thermal_base))
+-              return PTR_ERR(mt->thermal_base);
+-
+-      ret = mtk_thermal_get_calibration_data(&pdev->dev, mt);
+-      if (ret)
+-              return ret;
+-
+-      mutex_init(&mt->lock);
+-
+-      mt->dev = &pdev->dev;
+-
+-      auxadc = of_parse_phandle(np, "mediatek,auxadc", 0);
+-      if (!auxadc) {
+-              dev_err(&pdev->dev, "missing auxadc node\n");
+-              return -ENODEV;
+-      }
+-
+-      auxadc_base = of_iomap(auxadc, 0);
+-      auxadc_phys_base = of_get_phys_base(auxadc);
+-
+-      of_node_put(auxadc);
+-
+-      if (auxadc_phys_base == OF_BAD_ADDR) {
+-              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
+-              return -EINVAL;
+-      }
+-
+-      apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0);
+-      if (!apmixedsys) {
+-              dev_err(&pdev->dev, "missing apmixedsys node\n");
+-              return -ENODEV;
+-      }
+-
+-      apmixed_base = of_iomap(apmixedsys, 0);
+-      apmixed_phys_base = of_get_phys_base(apmixedsys);
+-
+-      of_node_put(apmixedsys);
+-
+-      if (apmixed_phys_base == OF_BAD_ADDR) {
+-              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
+-              return -EINVAL;
+-      }
+-
+-      ret = device_reset_optional(&pdev->dev);
+-      if (ret)
+-              return ret;
+-
+-      ret = clk_prepare_enable(mt->clk_auxadc);
+-      if (ret) {
+-              dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+-              return ret;
+-      }
+-
+-      ret = clk_prepare_enable(mt->clk_peri_therm);
+-      if (ret) {
+-              dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+-              goto err_disable_clk_auxadc;
+-      }
+-
+-      if (mt->conf->version != MTK_THERMAL_V1) {
+-              mtk_thermal_turn_on_buffer(apmixed_base);
+-              mtk_thermal_release_periodic_ts(mt, auxadc_base);
+-      }
+-
+-      if (mt->conf->version == MTK_THERMAL_V1)
+-              mt->raw_to_mcelsius = raw_to_mcelsius_v1;
+-      else if (mt->conf->version == MTK_THERMAL_V2)
+-              mt->raw_to_mcelsius = raw_to_mcelsius_v2;
+-      else
+-              mt->raw_to_mcelsius = raw_to_mcelsius_v3;
+-
+-      for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
+-              for (i = 0; i < mt->conf->num_banks; i++)
+-                      mtk_thermal_init_bank(mt, i, apmixed_phys_base,
+-                                            auxadc_phys_base, ctrl_id);
+-
+-      platform_set_drvdata(pdev, mt);
+-
+-      tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+-                                            &mtk_thermal_ops);
+-      if (IS_ERR(tzdev)) {
+-              ret = PTR_ERR(tzdev);
+-              goto err_disable_clk_peri_therm;
+-      }
+-
+-      ret = devm_thermal_add_hwmon_sysfs(tzdev);
+-      if (ret)
+-              dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+-
+-      return 0;
+-
+-err_disable_clk_peri_therm:
+-      clk_disable_unprepare(mt->clk_peri_therm);
+-err_disable_clk_auxadc:
+-      clk_disable_unprepare(mt->clk_auxadc);
+-
+-      return ret;
+-}
+-
+-static int mtk_thermal_remove(struct platform_device *pdev)
+-{
+-      struct mtk_thermal *mt = platform_get_drvdata(pdev);
+-
+-      clk_disable_unprepare(mt->clk_peri_therm);
+-      clk_disable_unprepare(mt->clk_auxadc);
+-
+-      return 0;
+-}
+-
+-static struct platform_driver mtk_thermal_driver = {
+-      .probe = mtk_thermal_probe,
+-      .remove = mtk_thermal_remove,
+-      .driver = {
+-              .name = "mtk-thermal",
+-              .of_match_table = mtk_thermal_of_match,
+-      },
+-};
+-
+-module_platform_driver(mtk_thermal_driver);
+-
+-MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
+-MODULE_AUTHOR("Louis Yu <louis.yu@mediatek.com>");
+-MODULE_AUTHOR("Dawei Chien <dawei.chien@mediatek.com>");
+-MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+-MODULE_AUTHOR("Hanyi Wu <hanyi.wu@mediatek.com>");
+-MODULE_DESCRIPTION("Mediatek thermal driver");
+-MODULE_LICENSE("GPL v2");
+--- /dev/null
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -0,0 +1,1254 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (c) 2015 MediaTek Inc.
++ * Author: Hanyi Wu <hanyi.wu@mediatek.com>
++ *         Sascha Hauer <s.hauer@pengutronix.de>
++ *         Dawei Chien <dawei.chien@mediatek.com>
++ *         Louis Yu <louis.yu@mediatek.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/interrupt.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/platform_device.h>
++#include <linux/slab.h>
++#include <linux/io.h>
++#include <linux/thermal.h>
++#include <linux/reset.h>
++#include <linux/types.h>
++
++#include "../thermal_hwmon.h"
++
++/* AUXADC Registers */
++#define AUXADC_CON1_SET_V     0x008
++#define AUXADC_CON1_CLR_V     0x00c
++#define AUXADC_CON2_V         0x010
++#define AUXADC_DATA(channel)  (0x14 + (channel) * 4)
++
++#define APMIXED_SYS_TS_CON1   0x604
++
++/* Thermal Controller Registers */
++#define TEMP_MONCTL0          0x000
++#define TEMP_MONCTL1          0x004
++#define TEMP_MONCTL2          0x008
++#define TEMP_MONIDET0         0x014
++#define TEMP_MONIDET1         0x018
++#define TEMP_MSRCTL0          0x038
++#define TEMP_MSRCTL1          0x03c
++#define TEMP_AHBPOLL          0x040
++#define TEMP_AHBTO            0x044
++#define TEMP_ADCPNP0          0x048
++#define TEMP_ADCPNP1          0x04c
++#define TEMP_ADCPNP2          0x050
++#define TEMP_ADCPNP3          0x0b4
++
++#define TEMP_ADCMUX           0x054
++#define TEMP_ADCEN            0x060
++#define TEMP_PNPMUXADDR               0x064
++#define TEMP_ADCMUXADDR               0x068
++#define TEMP_ADCENADDR                0x074
++#define TEMP_ADCVALIDADDR     0x078
++#define TEMP_ADCVOLTADDR      0x07c
++#define TEMP_RDCTRL           0x080
++#define TEMP_ADCVALIDMASK     0x084
++#define TEMP_ADCVOLTAGESHIFT  0x088
++#define TEMP_ADCWRITECTRL     0x08c
++#define TEMP_MSR0             0x090
++#define TEMP_MSR1             0x094
++#define TEMP_MSR2             0x098
++#define TEMP_MSR3             0x0B8
++
++#define TEMP_SPARE0           0x0f0
++
++#define TEMP_ADCPNP0_1          0x148
++#define TEMP_ADCPNP1_1          0x14c
++#define TEMP_ADCPNP2_1          0x150
++#define TEMP_MSR0_1             0x190
++#define TEMP_MSR1_1             0x194
++#define TEMP_MSR2_1             0x198
++#define TEMP_ADCPNP3_1          0x1b4
++#define TEMP_MSR3_1             0x1B8
++
++#define PTPCORESEL            0x400
++
++#define TEMP_MONCTL1_PERIOD_UNIT(x)   ((x) & 0x3ff)
++
++#define TEMP_MONCTL2_FILTER_INTERVAL(x)       (((x) & 0x3ff) << 16)
++#define TEMP_MONCTL2_SENSOR_INTERVAL(x)       ((x) & 0x3ff)
++
++#define TEMP_AHBPOLL_ADC_POLL_INTERVAL(x)     (x)
++
++#define TEMP_ADCWRITECTRL_ADC_PNP_WRITE               BIT(0)
++#define TEMP_ADCWRITECTRL_ADC_MUX_WRITE               BIT(1)
++
++#define TEMP_ADCVALIDMASK_VALID_HIGH          BIT(5)
++#define TEMP_ADCVALIDMASK_VALID_POS(bit)      (bit)
++
++/* MT8173 thermal sensors */
++#define MT8173_TS1    0
++#define MT8173_TS2    1
++#define MT8173_TS3    2
++#define MT8173_TS4    3
++#define MT8173_TSABB  4
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT8173_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT8173 */
++#define MT8173_NUM_SENSORS            5
++
++/* The number of banks in the MT8173 */
++#define MT8173_NUM_ZONES              4
++
++/* The number of sensing points per bank */
++#define MT8173_NUM_SENSORS_PER_ZONE   4
++
++/* The number of controller in the MT8173 */
++#define MT8173_NUM_CONTROLLER         1
++
++/* The calibration coefficient of sensor  */
++#define MT8173_CALIBRATION    165
++
++/*
++ * Layout of the fuses providing the calibration data
++ * These macros could be used for MT8183, MT8173, MT2701, and MT2712.
++ * MT8183 has 6 sensors and needs 6 VTS calibration data.
++ * MT8173 has 5 sensors and needs 5 VTS calibration data.
++ * MT2701 has 3 sensors and needs 3 VTS calibration data.
++ * MT2712 has 4 sensors and needs 4 VTS calibration data.
++ */
++#define CALIB_BUF0_VALID_V1           BIT(0)
++#define CALIB_BUF1_ADC_GE_V1(x)               (((x) >> 22) & 0x3ff)
++#define CALIB_BUF0_VTS_TS1_V1(x)      (((x) >> 17) & 0x1ff)
++#define CALIB_BUF0_VTS_TS2_V1(x)      (((x) >> 8) & 0x1ff)
++#define CALIB_BUF1_VTS_TS3_V1(x)      (((x) >> 0) & 0x1ff)
++#define CALIB_BUF2_VTS_TS4_V1(x)      (((x) >> 23) & 0x1ff)
++#define CALIB_BUF2_VTS_TS5_V1(x)      (((x) >> 5) & 0x1ff)
++#define CALIB_BUF2_VTS_TSABB_V1(x)    (((x) >> 14) & 0x1ff)
++#define CALIB_BUF0_DEGC_CALI_V1(x)    (((x) >> 1) & 0x3f)
++#define CALIB_BUF0_O_SLOPE_V1(x)      (((x) >> 26) & 0x3f)
++#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1)
++#define CALIB_BUF1_ID_V1(x)           (((x) >> 9) & 0x1)
++
++/*
++ * Layout of the fuses providing the calibration data
++ * These macros could be used for MT7622.
++ */
++#define CALIB_BUF0_ADC_OE_V2(x)               (((x) >> 22) & 0x3ff)
++#define CALIB_BUF0_ADC_GE_V2(x)               (((x) >> 12) & 0x3ff)
++#define CALIB_BUF0_DEGC_CALI_V2(x)    (((x) >> 6) & 0x3f)
++#define CALIB_BUF0_O_SLOPE_V2(x)      (((x) >> 0) & 0x3f)
++#define CALIB_BUF1_VTS_TS1_V2(x)      (((x) >> 23) & 0x1ff)
++#define CALIB_BUF1_VTS_TS2_V2(x)      (((x) >> 14) & 0x1ff)
++#define CALIB_BUF1_VTS_TSABB_V2(x)    (((x) >> 5) & 0x1ff)
++#define CALIB_BUF1_VALID_V2(x)                (((x) >> 4) & 0x1)
++#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1)
++
++/*
++ * Layout of the fuses providing the calibration data
++ * These macros can be used for MT7981 and MT7986.
++ */
++#define CALIB_BUF0_ADC_GE_V3(x)               (((x) >> 0) & 0x3ff)
++#define CALIB_BUF0_DEGC_CALI_V3(x)    (((x) >> 20) & 0x3f)
++#define CALIB_BUF0_O_SLOPE_V3(x)      (((x) >> 26) & 0x3f)
++#define CALIB_BUF1_VTS_TS1_V3(x)      (((x) >> 0) & 0x1ff)
++#define CALIB_BUF1_VTS_TS2_V3(x)      (((x) >> 21) & 0x1ff)
++#define CALIB_BUF1_VTS_TSABB_V3(x)    (((x) >> 9) & 0x1ff)
++#define CALIB_BUF1_VALID_V3(x)                (((x) >> 18) & 0x1)
++#define CALIB_BUF1_O_SLOPE_SIGN_V3(x) (((x) >> 19) & 0x1)
++#define CALIB_BUF1_ID_V3(x)           (((x) >> 20) & 0x1)
++
++enum {
++      VTS1,
++      VTS2,
++      VTS3,
++      VTS4,
++      VTS5,
++      VTSABB,
++      MAX_NUM_VTS,
++};
++
++enum mtk_thermal_version {
++      MTK_THERMAL_V1 = 1,
++      MTK_THERMAL_V2,
++      MTK_THERMAL_V3,
++};
++
++/* MT2701 thermal sensors */
++#define MT2701_TS1    0
++#define MT2701_TS2    1
++#define MT2701_TSABB  2
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT2701_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT2701 */
++#define MT2701_NUM_SENSORS    3
++
++/* The number of sensing points per bank */
++#define MT2701_NUM_SENSORS_PER_ZONE   3
++
++/* The number of controller in the MT2701 */
++#define MT2701_NUM_CONTROLLER         1
++
++/* The calibration coefficient of sensor  */
++#define MT2701_CALIBRATION    165
++
++/* MT2712 thermal sensors */
++#define MT2712_TS1    0
++#define MT2712_TS2    1
++#define MT2712_TS3    2
++#define MT2712_TS4    3
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT2712_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT2712 */
++#define MT2712_NUM_SENSORS    4
++
++/* The number of sensing points per bank */
++#define MT2712_NUM_SENSORS_PER_ZONE   4
++
++/* The number of controller in the MT2712 */
++#define MT2712_NUM_CONTROLLER         1
++
++/* The calibration coefficient of sensor  */
++#define MT2712_CALIBRATION    165
++
++#define MT7622_TEMP_AUXADC_CHANNEL    11
++#define MT7622_NUM_SENSORS            1
++#define MT7622_NUM_ZONES              1
++#define MT7622_NUM_SENSORS_PER_ZONE   1
++#define MT7622_TS1    0
++#define MT7622_NUM_CONTROLLER         1
++
++/* The maximum number of banks */
++#define MAX_NUM_ZONES         8
++
++/* The calibration coefficient of sensor  */
++#define MT7622_CALIBRATION    165
++
++/* MT8183 thermal sensors */
++#define MT8183_TS1    0
++#define MT8183_TS2    1
++#define MT8183_TS3    2
++#define MT8183_TS4    3
++#define MT8183_TS5    4
++#define MT8183_TSABB  5
++
++/* AUXADC channel  is used for the temperature sensors */
++#define MT8183_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT8183 */
++#define MT8183_NUM_SENSORS    6
++
++/* The number of banks in the MT8183 */
++#define MT8183_NUM_ZONES               1
++
++/* The number of sensing points per bank */
++#define MT8183_NUM_SENSORS_PER_ZONE    6
++
++/* The number of controller in the MT8183 */
++#define MT8183_NUM_CONTROLLER         2
++
++/* The calibration coefficient of sensor  */
++#define MT8183_CALIBRATION    153
++
++/* AUXADC channel 11 is used for the temperature sensors */
++#define MT7986_TEMP_AUXADC_CHANNEL    11
++
++/* The total number of temperature sensors in the MT7986 */
++#define MT7986_NUM_SENSORS            1
++
++/* The number of banks in the MT7986 */
++#define MT7986_NUM_ZONES              1
++
++/* The number of sensing points per bank */
++#define MT7986_NUM_SENSORS_PER_ZONE   1
++
++/* MT7986 thermal sensors */
++#define MT7986_TS1                    0
++
++/* The number of controller in the MT7986 */
++#define MT7986_NUM_CONTROLLER         1
++
++/* The calibration coefficient of sensor  */
++#define MT7986_CALIBRATION            165
++
++struct mtk_thermal;
++
++struct thermal_bank_cfg {
++      unsigned int num_sensors;
++      const int *sensors;
++};
++
++struct mtk_thermal_bank {
++      struct mtk_thermal *mt;
++      int id;
++};
++
++struct mtk_thermal_data {
++      s32 num_banks;
++      s32 num_sensors;
++      s32 auxadc_channel;
++      const int *vts_index;
++      const int *sensor_mux_values;
++      const int *msr;
++      const int *adcpnp;
++      const int cali_val;
++      const int num_controller;
++      const int *controller_offset;
++      bool need_switch_bank;
++      struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
++      enum mtk_thermal_version version;
++};
++
++struct mtk_thermal {
++      struct device *dev;
++      void __iomem *thermal_base;
++
++      struct clk *clk_peri_therm;
++      struct clk *clk_auxadc;
++      /* lock: for getting and putting banks */
++      struct mutex lock;
++
++      /* Calibration values */
++      s32 adc_ge;
++      s32 adc_oe;
++      s32 degc_cali;
++      s32 o_slope;
++      s32 o_slope_sign;
++      s32 vts[MAX_NUM_VTS];
++
++      const struct mtk_thermal_data *conf;
++      struct mtk_thermal_bank banks[MAX_NUM_ZONES];
++
++      int (*raw_to_mcelsius)(struct mtk_thermal *mt, int sensno, s32 raw);
++};
++
++/* MT8183 thermal sensor data */
++static const int mt8183_bank_data[MT8183_NUM_SENSORS] = {
++      MT8183_TS1, MT8183_TS2, MT8183_TS3, MT8183_TS4, MT8183_TS5, MT8183_TSABB
++};
++
++static const int mt8183_msr[MT8183_NUM_SENSORS_PER_ZONE] = {
++      TEMP_MSR0_1, TEMP_MSR1_1, TEMP_MSR2_1, TEMP_MSR1, TEMP_MSR0, TEMP_MSR3_1
++};
++
++static const int mt8183_adcpnp[MT8183_NUM_SENSORS_PER_ZONE] = {
++      TEMP_ADCPNP0_1, TEMP_ADCPNP1_1, TEMP_ADCPNP2_1,
++      TEMP_ADCPNP1, TEMP_ADCPNP0, TEMP_ADCPNP3_1
++};
++
++static const int mt8183_mux_values[MT8183_NUM_SENSORS] = { 0, 1, 2, 3, 4, 0 };
++static const int mt8183_tc_offset[MT8183_NUM_CONTROLLER] = {0x0, 0x100};
++
++static const int mt8183_vts_index[MT8183_NUM_SENSORS] = {
++      VTS1, VTS2, VTS3, VTS4, VTS5, VTSABB
++};
++
++/* MT8173 thermal sensor data */
++static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
++      { MT8173_TS2, MT8173_TS3 },
++      { MT8173_TS2, MT8173_TS4 },
++      { MT8173_TS1, MT8173_TS2, MT8173_TSABB },
++      { MT8173_TS2 },
++};
++
++static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
++      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
++};
++
++static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
++      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
++};
++
++static const int mt8173_mux_values[MT8173_NUM_SENSORS] = { 0, 1, 2, 3, 16 };
++static const int mt8173_tc_offset[MT8173_NUM_CONTROLLER] = { 0x0, };
++
++static const int mt8173_vts_index[MT8173_NUM_SENSORS] = {
++      VTS1, VTS2, VTS3, VTS4, VTSABB
++};
++
++/* MT2701 thermal sensor data */
++static const int mt2701_bank_data[MT2701_NUM_SENSORS] = {
++      MT2701_TS1, MT2701_TS2, MT2701_TSABB
++};
++
++static const int mt2701_msr[MT2701_NUM_SENSORS_PER_ZONE] = {
++      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
++};
++
++static const int mt2701_adcpnp[MT2701_NUM_SENSORS_PER_ZONE] = {
++      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
++};
++
++static const int mt2701_mux_values[MT2701_NUM_SENSORS] = { 0, 1, 16 };
++static const int mt2701_tc_offset[MT2701_NUM_CONTROLLER] = { 0x0, };
++
++static const int mt2701_vts_index[MT2701_NUM_SENSORS] = {
++      VTS1, VTS2, VTS3
++};
++
++/* MT2712 thermal sensor data */
++static const int mt2712_bank_data[MT2712_NUM_SENSORS] = {
++      MT2712_TS1, MT2712_TS2, MT2712_TS3, MT2712_TS4
++};
++
++static const int mt2712_msr[MT2712_NUM_SENSORS_PER_ZONE] = {
++      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
++};
++
++static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = {
++      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2, TEMP_ADCPNP3
++};
++
++static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 };
++static const int mt2712_tc_offset[MT2712_NUM_CONTROLLER] = { 0x0, };
++
++static const int mt2712_vts_index[MT2712_NUM_SENSORS] = {
++      VTS1, VTS2, VTS3, VTS4
++};
++
++/* MT7622 thermal sensor data */
++static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, };
++static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
++static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
++static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
++static const int mt7622_vts_index[MT7622_NUM_SENSORS] = { VTS1 };
++static const int mt7622_tc_offset[MT7622_NUM_CONTROLLER] = { 0x0, };
++
++/* MT7986 thermal sensor data */
++static const int mt7986_bank_data[MT7986_NUM_SENSORS] = { MT7986_TS1, };
++static const int mt7986_msr[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
++static const int mt7986_adcpnp[MT7986_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
++static const int mt7986_mux_values[MT7986_NUM_SENSORS] = { 0, };
++static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
++static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
++
++/*
++ * The MT8173 thermal controller has four banks. Each bank can read up to
++ * four temperature sensors simultaneously. The MT8173 has a total of 5
++ * temperature sensors. We use each bank to measure a certain area of the
++ * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple
++ * areas, hence is used in different banks.
++ *
++ * The thermal core only gets the maximum temperature of all banks, so
++ * the bank concept wouldn't be necessary here. However, the SVS (Smart
++ * Voltage Scaling) unit makes its decisions based on the same bank
++ * data, and this indeed needs the temperatures of the individual banks
++ * for making better decisions.
++ */
++static const struct mtk_thermal_data mt8173_thermal_data = {
++      .auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT8173_NUM_ZONES,
++      .num_sensors = MT8173_NUM_SENSORS,
++      .vts_index = mt8173_vts_index,
++      .cali_val = MT8173_CALIBRATION,
++      .num_controller = MT8173_NUM_CONTROLLER,
++      .controller_offset = mt8173_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 2,
++                      .sensors = mt8173_bank_data[0],
++              }, {
++                      .num_sensors = 2,
++                      .sensors = mt8173_bank_data[1],
++              }, {
++                      .num_sensors = 3,
++                      .sensors = mt8173_bank_data[2],
++              }, {
++                      .num_sensors = 1,
++                      .sensors = mt8173_bank_data[3],
++              },
++      },
++      .msr = mt8173_msr,
++      .adcpnp = mt8173_adcpnp,
++      .sensor_mux_values = mt8173_mux_values,
++      .version = MTK_THERMAL_V1,
++};
++
++/*
++ * The MT2701 thermal controller has one bank, which can read up to
++ * three temperature sensors simultaneously. The MT2701 has a total of 3
++ * temperature sensors.
++ *
++ * The thermal core only gets the maximum temperature of this one bank,
++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart
++ * Voltage Scaling) unit makes its decisions based on the same bank
++ * data.
++ */
++static const struct mtk_thermal_data mt2701_thermal_data = {
++      .auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL,
++      .num_banks = 1,
++      .num_sensors = MT2701_NUM_SENSORS,
++      .vts_index = mt2701_vts_index,
++      .cali_val = MT2701_CALIBRATION,
++      .num_controller = MT2701_NUM_CONTROLLER,
++      .controller_offset = mt2701_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 3,
++                      .sensors = mt2701_bank_data,
++              },
++      },
++      .msr = mt2701_msr,
++      .adcpnp = mt2701_adcpnp,
++      .sensor_mux_values = mt2701_mux_values,
++      .version = MTK_THERMAL_V1,
++};
++
++/*
++ * The MT2712 thermal controller has one bank, which can read up to
++ * four temperature sensors simultaneously. The MT2712 has a total of 4
++ * temperature sensors.
++ *
++ * The thermal core only gets the maximum temperature of this one bank,
++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart
++ * Voltage Scaling) unit makes its decisions based on the same bank
++ * data.
++ */
++static const struct mtk_thermal_data mt2712_thermal_data = {
++      .auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL,
++      .num_banks = 1,
++      .num_sensors = MT2712_NUM_SENSORS,
++      .vts_index = mt2712_vts_index,
++      .cali_val = MT2712_CALIBRATION,
++      .num_controller = MT2712_NUM_CONTROLLER,
++      .controller_offset = mt2712_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 4,
++                      .sensors = mt2712_bank_data,
++              },
++      },
++      .msr = mt2712_msr,
++      .adcpnp = mt2712_adcpnp,
++      .sensor_mux_values = mt2712_mux_values,
++      .version = MTK_THERMAL_V1,
++};
++
++/*
++ * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data
++ * access.
++ */
++static const struct mtk_thermal_data mt7622_thermal_data = {
++      .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT7622_NUM_ZONES,
++      .num_sensors = MT7622_NUM_SENSORS,
++      .vts_index = mt7622_vts_index,
++      .cali_val = MT7622_CALIBRATION,
++      .num_controller = MT7622_NUM_CONTROLLER,
++      .controller_offset = mt7622_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 1,
++                      .sensors = mt7622_bank_data,
++              },
++      },
++      .msr = mt7622_msr,
++      .adcpnp = mt7622_adcpnp,
++      .sensor_mux_values = mt7622_mux_values,
++      .version = MTK_THERMAL_V2,
++};
++
++/*
++ * The MT8183 thermal controller has one bank for the current SW framework.
++ * The MT8183 has a total of 6 temperature sensors.
++ * There are two thermal controller to control the six sensor.
++ * The first one bind 2 sensor, and the other bind 4 sensors.
++ * The thermal core only gets the maximum temperature of all sensor, so
++ * the bank concept wouldn't be necessary here. However, the SVS (Smart
++ * Voltage Scaling) unit makes its decisions based on the same bank
++ * data, and this indeed needs the temperatures of the individual banks
++ * for making better decisions.
++ */
++static const struct mtk_thermal_data mt8183_thermal_data = {
++      .auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT8183_NUM_ZONES,
++      .num_sensors = MT8183_NUM_SENSORS,
++      .vts_index = mt8183_vts_index,
++      .cali_val = MT8183_CALIBRATION,
++      .num_controller = MT8183_NUM_CONTROLLER,
++      .controller_offset = mt8183_tc_offset,
++      .need_switch_bank = false,
++      .bank_data = {
++              {
++                      .num_sensors = 6,
++                      .sensors = mt8183_bank_data,
++              },
++      },
++
++      .msr = mt8183_msr,
++      .adcpnp = mt8183_adcpnp,
++      .sensor_mux_values = mt8183_mux_values,
++      .version = MTK_THERMAL_V1,
++};
++
++/*
++ * MT7986 uses AUXADC Channel 11 for raw data access.
++ */
++static const struct mtk_thermal_data mt7986_thermal_data = {
++      .auxadc_channel = MT7986_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT7986_NUM_ZONES,
++      .num_sensors = MT7986_NUM_SENSORS,
++      .vts_index = mt7986_vts_index,
++      .cali_val = MT7986_CALIBRATION,
++      .num_controller = MT7986_NUM_CONTROLLER,
++      .controller_offset = mt7986_tc_offset,
++      .need_switch_bank = true,
++      .bank_data = {
++              {
++                      .num_sensors = 1,
++                      .sensors = mt7986_bank_data,
++              },
++      },
++      .msr = mt7986_msr,
++      .adcpnp = mt7986_adcpnp,
++      .sensor_mux_values = mt7986_mux_values,
++      .version = MTK_THERMAL_V3,
++};
++
++/**
++ * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
++ * @mt:       The thermal controller
++ * @sensno:   sensor number
++ * @raw:      raw ADC value
++ *
++ * This converts the raw ADC value to mcelsius using the SoC specific
++ * calibration constants
++ */
++static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw)
++{
++      s32 tmp;
++
++      raw &= 0xfff;
++
++      tmp = 203450520 << 3;
++      tmp /= mt->conf->cali_val + mt->o_slope;
++      tmp /= 10000 + mt->adc_ge;
++      tmp *= raw - mt->vts[sensno] - 3350;
++      tmp >>= 3;
++
++      return mt->degc_cali * 500 - tmp;
++}
++
++static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw)
++{
++      s32 format_1;
++      s32 format_2;
++      s32 g_oe;
++      s32 g_gain;
++      s32 g_x_roomt;
++      s32 tmp;
++
++      if (raw == 0)
++              return 0;
++
++      raw &= 0xfff;
++      g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12);
++      g_oe = mt->adc_oe - 512;
++      format_1 = mt->vts[VTS2] + 3105 - g_oe;
++      format_2 = (mt->degc_cali * 10) >> 1;
++      g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain;
++
++      tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt;
++      tmp = tmp * 10 * 100 / 11;
++
++      if (mt->o_slope_sign == 0)
++              tmp = tmp / (165 - mt->o_slope);
++      else
++              tmp = tmp / (165 + mt->o_slope);
++
++      return (format_2 - tmp) * 100;
++}
++
++static int raw_to_mcelsius_v3(struct mtk_thermal *mt, int sensno, s32 raw)
++{
++      s32 tmp;
++
++      if (raw == 0)
++              return 0;
++
++      raw &= 0xfff;
++      tmp = 100000 * 15 / 16 * 10000;
++      tmp /= 4096 - 512 + mt->adc_ge;
++      tmp /= 1490;
++      tmp *= raw - mt->vts[sensno] - 2900;
++
++      return mt->degc_cali * 500 - tmp;
++}
++
++/**
++ * mtk_thermal_get_bank - get bank
++ * @bank:     The bank
++ *
++ * The bank registers are banked, we have to select a bank in the
++ * PTPCORESEL register to access it.
++ */
++static void mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      u32 val;
++
++      if (mt->conf->need_switch_bank) {
++              mutex_lock(&mt->lock);
++
++              val = readl(mt->thermal_base + PTPCORESEL);
++              val &= ~0xf;
++              val |= bank->id;
++              writel(val, mt->thermal_base + PTPCORESEL);
++      }
++}
++
++/**
++ * mtk_thermal_put_bank - release bank
++ * @bank:     The bank
++ *
++ * release a bank previously taken with mtk_thermal_get_bank,
++ */
++static void mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++
++      if (mt->conf->need_switch_bank)
++              mutex_unlock(&mt->lock);
++}
++
++/**
++ * mtk_thermal_bank_temperature - get the temperature of a bank
++ * @bank:     The bank
++ *
++ * The temperature of a bank is considered the maximum temperature of
++ * the sensors associated to the bank.
++ */
++static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
++{
++      struct mtk_thermal *mt = bank->mt;
++      const struct mtk_thermal_data *conf = mt->conf;
++      int i, temp = INT_MIN, max = INT_MIN;
++      u32 raw;
++
++      for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
++              raw = readl(mt->thermal_base + conf->msr[i]);
++
++              temp = mt->raw_to_mcelsius(
++                      mt, conf->bank_data[bank->id].sensors[i], raw);
++
++
++              /*
++               * The first read of a sensor often contains very high bogus
++               * temperature value. Filter these out so that the system does
++               * not immediately shut down.
++               */
++              if (temp > 200000)
++                      temp = 0;
++
++              if (temp > max)
++                      max = temp;
++      }
++
++      return max;
++}
++
++static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
++{
++      struct mtk_thermal *mt = tz->devdata;
++      int i;
++      int tempmax = INT_MIN;
++
++      for (i = 0; i < mt->conf->num_banks; i++) {
++              struct mtk_thermal_bank *bank = &mt->banks[i];
++
++              mtk_thermal_get_bank(bank);
++
++              tempmax = max(tempmax, mtk_thermal_bank_temperature(bank));
++
++              mtk_thermal_put_bank(bank);
++      }
++
++      *temperature = tempmax;
++
++      return 0;
++}
++
++static const struct thermal_zone_device_ops mtk_thermal_ops = {
++      .get_temp = mtk_read_temp,
++};
++
++static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num,
++                                u32 apmixed_phys_base, u32 auxadc_phys_base,
++                                int ctrl_id)
++{
++      struct mtk_thermal_bank *bank = &mt->banks[num];
++      const struct mtk_thermal_data *conf = mt->conf;
++      int i;
++
++      int offset = mt->conf->controller_offset[ctrl_id];
++      void __iomem *controller_base = mt->thermal_base + offset;
++
++      bank->id = num;
++      bank->mt = mt;
++
++      mtk_thermal_get_bank(bank);
++
++      /* bus clock 66M counting unit is 12 * 15.15ns * 256 = 46.540us */
++      writel(TEMP_MONCTL1_PERIOD_UNIT(12), controller_base + TEMP_MONCTL1);
++
++      /*
++       * filt interval is 1 * 46.540us = 46.54us,
++       * sen interval is 429 * 46.540us = 19.96ms
++       */
++      writel(TEMP_MONCTL2_FILTER_INTERVAL(1) |
++                      TEMP_MONCTL2_SENSOR_INTERVAL(429),
++                      controller_base + TEMP_MONCTL2);
++
++      /* poll is set to 10u */
++      writel(TEMP_AHBPOLL_ADC_POLL_INTERVAL(768),
++             controller_base + TEMP_AHBPOLL);
++
++      /* temperature sampling control, 1 sample */
++      writel(0x0, controller_base + TEMP_MSRCTL0);
++
++      /* exceed this polling time, IRQ would be inserted */
++      writel(0xffffffff, controller_base + TEMP_AHBTO);
++
++      /* number of interrupts per event, 1 is enough */
++      writel(0x0, controller_base + TEMP_MONIDET0);
++      writel(0x0, controller_base + TEMP_MONIDET1);
++
++      /*
++       * The MT8173 thermal controller does not have its own ADC. Instead it
++       * uses AHB bus accesses to control the AUXADC. To do this the thermal
++       * controller has to be programmed with the physical addresses of the
++       * AUXADC registers and with the various bit positions in the AUXADC.
++       * Also the thermal controller controls a mux in the APMIXEDSYS register
++       * space.
++       */
++
++      /*
++       * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0)
++       * automatically by hw
++       */
++      writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX);
++
++      /* AHB address for auxadc mux selection */
++      writel(auxadc_phys_base + AUXADC_CON1_CLR_V,
++             controller_base + TEMP_ADCMUXADDR);
++
++      if (mt->conf->version == MTK_THERMAL_V1) {
++              /* AHB address for pnp sensor mux selection */
++              writel(apmixed_phys_base + APMIXED_SYS_TS_CON1,
++                     controller_base + TEMP_PNPMUXADDR);
++      }
++
++      /* AHB value for auxadc enable */
++      writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN);
++
++      /* AHB address for auxadc enable (channel 0 immediate mode selected) */
++      writel(auxadc_phys_base + AUXADC_CON1_SET_V,
++             controller_base + TEMP_ADCENADDR);
++
++      /* AHB address for auxadc valid bit */
++      writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
++             controller_base + TEMP_ADCVALIDADDR);
++
++      /* AHB address for auxadc voltage output */
++      writel(auxadc_phys_base + AUXADC_DATA(conf->auxadc_channel),
++             controller_base + TEMP_ADCVOLTADDR);
++
++      /* read valid & voltage are at the same register */
++      writel(0x0, controller_base + TEMP_RDCTRL);
++
++      /* indicate where the valid bit is */
++      writel(TEMP_ADCVALIDMASK_VALID_HIGH | TEMP_ADCVALIDMASK_VALID_POS(12),
++             controller_base + TEMP_ADCVALIDMASK);
++
++      /* no shift */
++      writel(0x0, controller_base + TEMP_ADCVOLTAGESHIFT);
++
++      /* enable auxadc mux write transaction */
++      writel(TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
++              controller_base + TEMP_ADCWRITECTRL);
++
++      for (i = 0; i < conf->bank_data[num].num_sensors; i++)
++              writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]],
++                     mt->thermal_base + conf->adcpnp[i]);
++
++      writel((1 << conf->bank_data[num].num_sensors) - 1,
++             controller_base + TEMP_MONCTL0);
++
++      writel(TEMP_ADCWRITECTRL_ADC_PNP_WRITE |
++             TEMP_ADCWRITECTRL_ADC_MUX_WRITE,
++             controller_base + TEMP_ADCWRITECTRL);
++
++      mtk_thermal_put_bank(bank);
++}
++
++static u64 of_get_phys_base(struct device_node *np)
++{
++      u64 size64;
++      const __be32 *regaddr_p;
++
++      regaddr_p = of_get_address(np, 0, &size64, NULL);
++      if (!regaddr_p)
++              return OF_BAD_ADDR;
++
++      return of_translate_address(np, regaddr_p);
++}
++
++static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf)
++{
++      int i;
++
++      if (!(buf[0] & CALIB_BUF0_VALID_V1))
++              return -EINVAL;
++
++      mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]);
++
++      for (i = 0; i < mt->conf->num_sensors; i++) {
++              switch (mt->conf->vts_index[i]) {
++              case VTS1:
++                      mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]);
++                      break;
++              case VTS2:
++                      mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]);
++                      break;
++              case VTS3:
++                      mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]);
++                      break;
++              case VTS4:
++                      mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]);
++                      break;
++              case VTS5:
++                      mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]);
++                      break;
++              case VTSABB:
++                      mt->vts[VTSABB] =
++                              CALIB_BUF2_VTS_TSABB_V1(buf[2]);
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]);
++      if (CALIB_BUF1_ID_V1(buf[1]) &
++          CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0]))
++              mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]);
++      else
++              mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]);
++
++      return 0;
++}
++
++static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf)
++{
++      if (!CALIB_BUF1_VALID_V2(buf[1]))
++              return -EINVAL;
++
++      mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]);
++      mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]);
++      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]);
++      mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]);
++      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]);
++      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]);
++      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]);
++      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]);
++
++      return 0;
++}
++
++static int mtk_thermal_extract_efuse_v3(struct mtk_thermal *mt, u32 *buf)
++{
++      if (!CALIB_BUF1_VALID_V3(buf[1]))
++              return -EINVAL;
++
++      mt->adc_ge = CALIB_BUF0_ADC_GE_V3(buf[0]);
++      mt->degc_cali = CALIB_BUF0_DEGC_CALI_V3(buf[0]);
++      mt->o_slope = CALIB_BUF0_O_SLOPE_V3(buf[0]);
++      mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V3(buf[1]);
++      mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V3(buf[1]);
++      mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V3(buf[1]);
++      mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V3(buf[1]);
++
++      if (CALIB_BUF1_ID_V3(buf[1]) == 0)
++              mt->o_slope = 0;
++
++      return 0;
++}
++
++static int mtk_thermal_get_calibration_data(struct device *dev,
++                                          struct mtk_thermal *mt)
++{
++      struct nvmem_cell *cell;
++      u32 *buf;
++      size_t len;
++      int i, ret = 0;
++
++      /* Start with default values */
++      mt->adc_ge = 512;
++      mt->adc_oe = 512;
++      for (i = 0; i < mt->conf->num_sensors; i++)
++              mt->vts[i] = 260;
++      mt->degc_cali = 40;
++      mt->o_slope = 0;
++
++      cell = nvmem_cell_get(dev, "calibration-data");
++      if (IS_ERR(cell)) {
++              if (PTR_ERR(cell) == -EPROBE_DEFER)
++                      return PTR_ERR(cell);
++              return 0;
++      }
++
++      buf = (u32 *)nvmem_cell_read(cell, &len);
++
++      nvmem_cell_put(cell);
++
++      if (IS_ERR(buf))
++              return PTR_ERR(buf);
++
++      if (len < 3 * sizeof(u32)) {
++              dev_warn(dev, "invalid calibration data\n");
++              ret = -EINVAL;
++              goto out;
++      }
++
++      switch (mt->conf->version) {
++      case MTK_THERMAL_V1:
++              ret = mtk_thermal_extract_efuse_v1(mt, buf);
++              break;
++      case MTK_THERMAL_V2:
++              ret = mtk_thermal_extract_efuse_v2(mt, buf);
++              break;
++      case MTK_THERMAL_V3:
++              ret = mtk_thermal_extract_efuse_v3(mt, buf);
++              break;
++      default:
++              ret = -EINVAL;
++              break;
++      }
++
++      if (ret) {
++              dev_info(dev, "Device not calibrated, using default calibration values\n");
++              ret = 0;
++      }
++
++out:
++      kfree(buf);
++
++      return ret;
++}
++
++static const struct of_device_id mtk_thermal_of_match[] = {
++      {
++              .compatible = "mediatek,mt8173-thermal",
++              .data = (void *)&mt8173_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt2701-thermal",
++              .data = (void *)&mt2701_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt2712-thermal",
++              .data = (void *)&mt2712_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt7622-thermal",
++              .data = (void *)&mt7622_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt7986-thermal",
++              .data = (void *)&mt7986_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt8183-thermal",
++              .data = (void *)&mt8183_thermal_data,
++      }, {
++      },
++};
++MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
++
++static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
++{
++      int tmp;
++
++      tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
++      tmp &= ~(0x37);
++      tmp |= 0x1;
++      writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
++      udelay(200);
++}
++
++static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt,
++                                          void __iomem *auxadc_base)
++{
++      int tmp;
++
++      writel(0x800, auxadc_base + AUXADC_CON1_SET_V);
++      writel(0x1, mt->thermal_base + TEMP_MONCTL0);
++      tmp = readl(mt->thermal_base + TEMP_MSRCTL1);
++      writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1);
++}
++
++static int mtk_thermal_probe(struct platform_device *pdev)
++{
++      int ret, i, ctrl_id;
++      struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
++      struct mtk_thermal *mt;
++      u64 auxadc_phys_base, apmixed_phys_base;
++      struct thermal_zone_device *tzdev;
++      void __iomem *apmixed_base, *auxadc_base;
++
++      mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL);
++      if (!mt)
++              return -ENOMEM;
++
++      mt->conf = of_device_get_match_data(&pdev->dev);
++
++      mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
++      if (IS_ERR(mt->clk_peri_therm))
++              return PTR_ERR(mt->clk_peri_therm);
++
++      mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
++      if (IS_ERR(mt->clk_auxadc))
++              return PTR_ERR(mt->clk_auxadc);
++
++      mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
++      if (IS_ERR(mt->thermal_base))
++              return PTR_ERR(mt->thermal_base);
++
++      ret = mtk_thermal_get_calibration_data(&pdev->dev, mt);
++      if (ret)
++              return ret;
++
++      mutex_init(&mt->lock);
++
++      mt->dev = &pdev->dev;
++
++      auxadc = of_parse_phandle(np, "mediatek,auxadc", 0);
++      if (!auxadc) {
++              dev_err(&pdev->dev, "missing auxadc node\n");
++              return -ENODEV;
++      }
++
++      auxadc_base = of_iomap(auxadc, 0);
++      auxadc_phys_base = of_get_phys_base(auxadc);
++
++      of_node_put(auxadc);
++
++      if (auxadc_phys_base == OF_BAD_ADDR) {
++              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++              return -EINVAL;
++      }
++
++      apmixedsys = of_parse_phandle(np, "mediatek,apmixedsys", 0);
++      if (!apmixedsys) {
++              dev_err(&pdev->dev, "missing apmixedsys node\n");
++              return -ENODEV;
++      }
++
++      apmixed_base = of_iomap(apmixedsys, 0);
++      apmixed_phys_base = of_get_phys_base(apmixedsys);
++
++      of_node_put(apmixedsys);
++
++      if (apmixed_phys_base == OF_BAD_ADDR) {
++              dev_err(&pdev->dev, "Can't get auxadc phys address\n");
++              return -EINVAL;
++      }
++
++      ret = device_reset_optional(&pdev->dev);
++      if (ret)
++              return ret;
++
++      ret = clk_prepare_enable(mt->clk_auxadc);
++      if (ret) {
++              dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
++              return ret;
++      }
++
++      ret = clk_prepare_enable(mt->clk_peri_therm);
++      if (ret) {
++              dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
++              goto err_disable_clk_auxadc;
++      }
++
++      if (mt->conf->version != MTK_THERMAL_V1) {
++              mtk_thermal_turn_on_buffer(apmixed_base);
++              mtk_thermal_release_periodic_ts(mt, auxadc_base);
++      }
++
++      if (mt->conf->version == MTK_THERMAL_V1)
++              mt->raw_to_mcelsius = raw_to_mcelsius_v1;
++      else if (mt->conf->version == MTK_THERMAL_V2)
++              mt->raw_to_mcelsius = raw_to_mcelsius_v2;
++      else
++              mt->raw_to_mcelsius = raw_to_mcelsius_v3;
++
++      for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++)
++              for (i = 0; i < mt->conf->num_banks; i++)
++                      mtk_thermal_init_bank(mt, i, apmixed_phys_base,
++                                            auxadc_phys_base, ctrl_id);
++
++      platform_set_drvdata(pdev, mt);
++
++      tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
++                                            &mtk_thermal_ops);
++      if (IS_ERR(tzdev)) {
++              ret = PTR_ERR(tzdev);
++              goto err_disable_clk_peri_therm;
++      }
++
++      ret = devm_thermal_add_hwmon_sysfs(tzdev);
++      if (ret)
++              dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
++
++      return 0;
++
++err_disable_clk_peri_therm:
++      clk_disable_unprepare(mt->clk_peri_therm);
++err_disable_clk_auxadc:
++      clk_disable_unprepare(mt->clk_auxadc);
++
++      return ret;
++}
++
++static int mtk_thermal_remove(struct platform_device *pdev)
++{
++      struct mtk_thermal *mt = platform_get_drvdata(pdev);
++
++      clk_disable_unprepare(mt->clk_peri_therm);
++      clk_disable_unprepare(mt->clk_auxadc);
++
++      return 0;
++}
++
++static struct platform_driver mtk_thermal_driver = {
++      .probe = mtk_thermal_probe,
++      .remove = mtk_thermal_remove,
++      .driver = {
++              .name = "mtk-thermal",
++              .of_match_table = mtk_thermal_of_match,
++      },
++};
++
++module_platform_driver(mtk_thermal_driver);
++
++MODULE_AUTHOR("Michael Kao <michael.kao@mediatek.com>");
++MODULE_AUTHOR("Louis Yu <louis.yu@mediatek.com>");
++MODULE_AUTHOR("Dawei Chien <dawei.chien@mediatek.com>");
++MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
++MODULE_AUTHOR("Hanyi Wu <hanyi.wu@mediatek.com>");
++MODULE_DESCRIPTION("Mediatek thermal driver");
++MODULE_LICENSE("GPL v2");
diff --git a/target/linux/mediatek/patches-6.1/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch b/target/linux/mediatek/patches-6.1/830-v6.3-06-thermal-drivers-mediatek-Add-the-Low-Voltage-Thermal.patch
new file mode 100644 (file)
index 0000000..2ae3734
--- /dev/null
@@ -0,0 +1,1298 @@
+From 325fadf27b21f7d79843c3cc282b7f3e6620ad3d Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Thu, 9 Feb 2023 11:56:26 +0100
+Subject: [PATCH 06/42] thermal/drivers/mediatek: Add the Low Voltage Thermal
+ Sensor driver
+
+The Low Voltage Thermal Sensor (LVTS) is a multiple sensors, multi
+controllers contained in a thermal domain.
+
+A thermal domains can be the MCU or the AP.
+
+Each thermal domains contain up to seven controllers, each thermal
+controller handle up to four thermal sensors.
+
+The LVTS has two Finite State Machines (FSM), one to handle the
+functionin temperatures range like hot or cold temperature and another
+one to handle monitoring trip point. The FSM notifies via interrupts
+when a trip point is crossed.
+
+The interrupt is managed at the thermal controller level, so when an
+interrupt occurs, the driver has to find out which sensor triggered
+such an interrupt.
+
+The sampling of the thermal can be filtered or immediate. For the
+former, the LVTS measures several points and applies a low pass
+filter.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+
+On MT8195 Tomato Chromebook:
+
+Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20230209105628.50294-5-bchihi@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/mediatek/Kconfig        |   16 +
+ drivers/thermal/mediatek/Makefile       |    1 +
+ drivers/thermal/mediatek/lvts_thermal.c | 1224 +++++++++++++++++++++++
+ 3 files changed, 1241 insertions(+)
+ create mode 100644 drivers/thermal/mediatek/lvts_thermal.c
+
+--- a/drivers/thermal/mediatek/Kconfig
++++ b/drivers/thermal/mediatek/Kconfig
+@@ -18,4 +18,20 @@ config MTK_SOC_THERMAL
+         This driver configures thermal controllers to collect
+         temperature via AUXADC interface.
++config MTK_LVTS_THERMAL
++        tristate "LVTS Thermal Driver for MediaTek SoCs"
++        depends on HAS_IOMEM
++        help
++          Enable this option if you want to get SoC temperature
++          information for supported MediaTek platforms.
++          This driver configures LVTS (Low Voltage Thermal Sensor)
++          thermal controllers to collect temperatures via ASIF
++          (Analog Serial Interface).
++
++config MTK_LVTS_THERMAL_DEBUGFS
++       bool "LVTS thermal debugfs"
++       depends on MTK_LVTS_THERMAL && DEBUG_FS
++       help
++         Enable this option to debug the internals of the device driver.
++
+ endif
+--- a/drivers/thermal/mediatek/Makefile
++++ b/drivers/thermal/mediatek/Makefile
+@@ -1 +1,2 @@
+ obj-$(CONFIG_MTK_SOC_THERMAL) += auxadc_thermal.o
++obj-$(CONFIG_MTK_LVTS_THERMAL)        += lvts_thermal.o
+--- /dev/null
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -0,0 +1,1224 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (c) 2023 MediaTek Inc.
++ * Author: Balsam CHIHI <bchihi@baylibre.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/delay.h>
++#include <linux/debugfs.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/iopoll.h>
++#include <linux/kernel.h>
++#include <linux/nvmem-consumer.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/thermal.h>
++#include <dt-bindings/thermal/mediatek,lvts-thermal.h>
++
++#define LVTS_MONCTL0(__base)  (__base + 0x0000)
++#define LVTS_MONCTL1(__base)  (__base + 0x0004)
++#define LVTS_MONCTL2(__base)  (__base + 0x0008)
++#define LVTS_MONINT(__base)           (__base + 0x000C)
++#define LVTS_MONINTSTS(__base)        (__base + 0x0010)
++#define LVTS_MONIDET0(__base) (__base + 0x0014)
++#define LVTS_MONIDET1(__base) (__base + 0x0018)
++#define LVTS_MONIDET2(__base) (__base + 0x001C)
++#define LVTS_MONIDET3(__base) (__base + 0x0020)
++#define LVTS_H2NTHRE(__base)  (__base + 0x0024)
++#define LVTS_HTHRE(__base)            (__base + 0x0028)
++#define LVTS_OFFSETH(__base)  (__base + 0x0030)
++#define LVTS_OFFSETL(__base)  (__base + 0x0034)
++#define LVTS_MSRCTL0(__base)  (__base + 0x0038)
++#define LVTS_MSRCTL1(__base)  (__base + 0x003C)
++#define LVTS_TSSEL(__base)            (__base + 0x0040)
++#define LVTS_CALSCALE(__base) (__base + 0x0048)
++#define LVTS_ID(__base)                       (__base + 0x004C)
++#define LVTS_CONFIG(__base)           (__base + 0x0050)
++#define LVTS_EDATA00(__base)  (__base + 0x0054)
++#define LVTS_EDATA01(__base)  (__base + 0x0058)
++#define LVTS_EDATA02(__base)  (__base + 0x005C)
++#define LVTS_EDATA03(__base)  (__base + 0x0060)
++#define LVTS_MSR0(__base)             (__base + 0x0090)
++#define LVTS_MSR1(__base)             (__base + 0x0094)
++#define LVTS_MSR2(__base)             (__base + 0x0098)
++#define LVTS_MSR3(__base)             (__base + 0x009C)
++#define LVTS_IMMD0(__base)            (__base + 0x00A0)
++#define LVTS_IMMD1(__base)            (__base + 0x00A4)
++#define LVTS_IMMD2(__base)            (__base + 0x00A8)
++#define LVTS_IMMD3(__base)            (__base + 0x00AC)
++#define LVTS_PROTCTL(__base)  (__base + 0x00C0)
++#define LVTS_PROTTA(__base)           (__base + 0x00C4)
++#define LVTS_PROTTB(__base)           (__base + 0x00C8)
++#define LVTS_PROTTC(__base)           (__base + 0x00CC)
++#define LVTS_CLKEN(__base)            (__base + 0x00E4)
++
++#define LVTS_PERIOD_UNIT                      ((118 * 1000) / (256 * 38))
++#define LVTS_GROUP_INTERVAL                   1
++#define LVTS_FILTER_INTERVAL          1
++#define LVTS_SENSOR_INTERVAL          1
++#define LVTS_HW_FILTER                                0x2
++#define LVTS_TSSEL_CONF                               0x13121110
++#define LVTS_CALSCALE_CONF                    0x300
++#define LVTS_MONINT_CONF                      0x9FBF7BDE
++
++#define LVTS_INT_SENSOR0                      0x0009001F
++#define LVTS_INT_SENSOR1                      0X000881F0
++#define LVTS_INT_SENSOR2                      0x00247C00
++#define LVTS_INT_SENSOR3                      0x1FC00000
++
++#define LVTS_SENSOR_MAX                               4
++#define LVTS_GOLDEN_TEMP_MAX          62
++#define LVTS_GOLDEN_TEMP_DEFAULT      50
++#define LVTS_COEFF_A                          -250460
++#define LVTS_COEFF_B                          250460
++
++#define LVTS_MSR_IMMEDIATE_MODE               0
++#define LVTS_MSR_FILTERED_MODE                1
++
++#define LVTS_HW_SHUTDOWN_MT8195               105000
++
++static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
++static int coeff_b = LVTS_COEFF_B;
++
++struct lvts_sensor_data {
++      int dt_id;
++};
++
++struct lvts_ctrl_data {
++      struct lvts_sensor_data lvts_sensor[LVTS_SENSOR_MAX];
++      int cal_offset[LVTS_SENSOR_MAX];
++      int hw_tshut_temp;
++      int num_lvts_sensor;
++      int offset;
++      int mode;
++};
++
++struct lvts_data {
++      const struct lvts_ctrl_data *lvts_ctrl;
++      int num_lvts_ctrl;
++};
++
++struct lvts_sensor {
++      struct thermal_zone_device *tz;
++      void __iomem *msr;
++      void __iomem *base;
++      int id;
++      int dt_id;
++};
++
++struct lvts_ctrl {
++      struct lvts_sensor sensors[LVTS_SENSOR_MAX];
++      u32 calibration[LVTS_SENSOR_MAX];
++      u32 hw_tshut_raw_temp;
++      int num_lvts_sensor;
++      int mode;
++      void __iomem *base;
++};
++
++struct lvts_domain {
++      struct lvts_ctrl *lvts_ctrl;
++      struct reset_control *reset;
++      struct clk *clk;
++      int num_lvts_ctrl;
++      void __iomem *base;
++      size_t calib_len;
++      u8 *calib;
++#ifdef CONFIG_DEBUG_FS
++      struct dentry *dom_dentry;
++#endif
++};
++
++#ifdef CONFIG_MTK_LVTS_THERMAL_DEBUGFS
++
++#define LVTS_DEBUG_FS_REGS(__reg)             \
++{                                             \
++      .name = __stringify(__reg),             \
++      .offset = __reg(0),                     \
++}
++
++static const struct debugfs_reg32 lvts_regs[] = {
++      LVTS_DEBUG_FS_REGS(LVTS_MONCTL0),
++      LVTS_DEBUG_FS_REGS(LVTS_MONCTL1),
++      LVTS_DEBUG_FS_REGS(LVTS_MONCTL2),
++      LVTS_DEBUG_FS_REGS(LVTS_MONINT),
++      LVTS_DEBUG_FS_REGS(LVTS_MONINTSTS),
++      LVTS_DEBUG_FS_REGS(LVTS_MONIDET0),
++      LVTS_DEBUG_FS_REGS(LVTS_MONIDET1),
++      LVTS_DEBUG_FS_REGS(LVTS_MONIDET2),
++      LVTS_DEBUG_FS_REGS(LVTS_MONIDET3),
++      LVTS_DEBUG_FS_REGS(LVTS_H2NTHRE),
++      LVTS_DEBUG_FS_REGS(LVTS_HTHRE),
++      LVTS_DEBUG_FS_REGS(LVTS_OFFSETH),
++      LVTS_DEBUG_FS_REGS(LVTS_OFFSETL),
++      LVTS_DEBUG_FS_REGS(LVTS_MSRCTL0),
++      LVTS_DEBUG_FS_REGS(LVTS_MSRCTL1),
++      LVTS_DEBUG_FS_REGS(LVTS_TSSEL),
++      LVTS_DEBUG_FS_REGS(LVTS_CALSCALE),
++      LVTS_DEBUG_FS_REGS(LVTS_ID),
++      LVTS_DEBUG_FS_REGS(LVTS_CONFIG),
++      LVTS_DEBUG_FS_REGS(LVTS_EDATA00),
++      LVTS_DEBUG_FS_REGS(LVTS_EDATA01),
++      LVTS_DEBUG_FS_REGS(LVTS_EDATA02),
++      LVTS_DEBUG_FS_REGS(LVTS_EDATA03),
++      LVTS_DEBUG_FS_REGS(LVTS_MSR0),
++      LVTS_DEBUG_FS_REGS(LVTS_MSR1),
++      LVTS_DEBUG_FS_REGS(LVTS_MSR2),
++      LVTS_DEBUG_FS_REGS(LVTS_MSR3),
++      LVTS_DEBUG_FS_REGS(LVTS_IMMD0),
++      LVTS_DEBUG_FS_REGS(LVTS_IMMD1),
++      LVTS_DEBUG_FS_REGS(LVTS_IMMD2),
++      LVTS_DEBUG_FS_REGS(LVTS_IMMD3),
++      LVTS_DEBUG_FS_REGS(LVTS_PROTCTL),
++      LVTS_DEBUG_FS_REGS(LVTS_PROTTA),
++      LVTS_DEBUG_FS_REGS(LVTS_PROTTB),
++      LVTS_DEBUG_FS_REGS(LVTS_PROTTC),
++      LVTS_DEBUG_FS_REGS(LVTS_CLKEN),
++};
++
++static int lvts_debugfs_init(struct device *dev, struct lvts_domain *lvts_td)
++{
++      struct debugfs_regset32 *regset;
++      struct lvts_ctrl *lvts_ctrl;
++      struct dentry *dentry;
++      char name[64];
++      int i;
++
++      lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL);
++      if (!lvts_td->dom_dentry)
++              return 0;
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
++
++              lvts_ctrl = &lvts_td->lvts_ctrl[i];
++
++              sprintf(name, "controller%d", i);
++              dentry = debugfs_create_dir(name, lvts_td->dom_dentry);
++              if (!dentry)
++                      continue;
++
++              regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
++              if (!regset)
++                      continue;
++
++              regset->base = lvts_ctrl->base;
++              regset->regs = lvts_regs;
++              regset->nregs = ARRAY_SIZE(lvts_regs);
++
++              debugfs_create_regset32("registers", 0400, dentry, regset);
++      }
++
++      return 0;
++}
++
++static void lvts_debugfs_exit(struct lvts_domain *lvts_td)
++{
++      debugfs_remove_recursive(lvts_td->dom_dentry);
++}
++
++#else
++
++static inline int lvts_debugfs_init(struct device *dev,
++                                  struct lvts_domain *lvts_td)
++{
++      return 0;
++}
++
++static void lvts_debugfs_exit(struct lvts_domain *lvts_td) { }
++
++#endif
++
++static int lvts_raw_to_temp(u32 raw_temp)
++{
++      int temperature;
++
++      temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14;
++      temperature += coeff_b;
++
++      return temperature;
++}
++
++static u32 lvts_temp_to_raw(int temperature)
++{
++      u32 raw_temp = ((s64)(coeff_b - temperature)) << 14;
++
++      raw_temp = div_s64(raw_temp, -LVTS_COEFF_A);
++
++      return raw_temp;
++}
++
++static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
++{
++      struct lvts_sensor *lvts_sensor = tz->devdata;
++      void __iomem *msr = lvts_sensor->msr;
++      u32 value;
++
++      /*
++       * Measurement registers:
++       *
++       * LVTS_MSR[0-3] / LVTS_IMMD[0-3]
++       *
++       * Bits:
++       *
++       * 32-17: Unused
++       * 16   : Valid temperature
++       * 15-0 : Raw temperature
++       */
++      value = readl(msr);
++
++      /*
++       * As the thermal zone temperature will read before the
++       * hardware sensor is fully initialized, we have to check the
++       * validity of the temperature returned when reading the
++       * measurement register. The thermal controller will set the
++       * valid bit temperature only when it is totally initialized.
++       *
++       * Otherwise, we may end up with garbage values out of the
++       * functionning temperature and directly jump to a system
++       * shutdown.
++       */
++      if (!(value & BIT(16)))
++              return -EAGAIN;
++
++      *temp = lvts_raw_to_temp(value & 0xFFFF);
++
++      return 0;
++}
++
++static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
++{
++      struct lvts_sensor *lvts_sensor = tz->devdata;
++      void __iomem *base = lvts_sensor->base;
++      u32 raw_low = lvts_temp_to_raw(low);
++      u32 raw_high = lvts_temp_to_raw(high);
++
++      /*
++       * Hot to normal temperature threshold
++       *
++       * LVTS_H2NTHRE
++       *
++       * Bits:
++       *
++       * 14-0 : Raw temperature for threshold
++       */
++      if (low != -INT_MAX) {
++              dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low);
++              writel(raw_low, LVTS_H2NTHRE(base));
++      }
++
++      /*
++       * Hot temperature threshold
++       *
++       * LVTS_HTHRE
++       *
++       * Bits:
++       *
++       * 14-0 : Raw temperature for threshold
++       */
++      dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high);
++      writel(raw_high, LVTS_HTHRE(base));
++
++      return 0;
++}
++
++static irqreturn_t lvts_ctrl_irq_handler(struct lvts_ctrl *lvts_ctrl)
++{
++      irqreturn_t iret = IRQ_NONE;
++      u32 value;
++      u32 masks[] = {
++              LVTS_INT_SENSOR0,
++              LVTS_INT_SENSOR1,
++              LVTS_INT_SENSOR2,
++              LVTS_INT_SENSOR3
++      };
++      int i;
++
++      /*
++       * Interrupt monitoring status
++       *
++       * LVTS_MONINTST
++       *
++       * Bits:
++       *
++       * 31 : Interrupt for stage 3
++       * 30 : Interrupt for stage 2
++       * 29 : Interrupt for state 1
++       * 28 : Interrupt using filter on sensor 3
++       *
++       * 27 : Interrupt using immediate on sensor 3
++       * 26 : Interrupt normal to hot on sensor 3
++       * 25 : Interrupt high offset on sensor 3
++       * 24 : Interrupt low offset on sensor 3
++       *
++       * 23 : Interrupt hot threshold on sensor 3
++       * 22 : Interrupt cold threshold on sensor 3
++       * 21 : Interrupt using filter on sensor 2
++       * 20 : Interrupt using filter on sensor 1
++       *
++       * 19 : Interrupt using filter on sensor 0
++       * 18 : Interrupt using immediate on sensor 2
++       * 17 : Interrupt using immediate on sensor 1
++       * 16 : Interrupt using immediate on sensor 0
++       *
++       * 15 : Interrupt device access timeout interrupt
++       * 14 : Interrupt normal to hot on sensor 2
++       * 13 : Interrupt high offset interrupt on sensor 2
++       * 12 : Interrupt low offset interrupt on sensor 2
++       *
++       * 11 : Interrupt hot threshold on sensor 2
++       * 10 : Interrupt cold threshold on sensor 2
++       *  9 : Interrupt normal to hot on sensor 1
++       *  8 : Interrupt high offset interrupt on sensor 1
++       *
++       *  7 : Interrupt low offset interrupt on sensor 1
++       *  6 : Interrupt hot threshold on sensor 1
++       *  5 : Interrupt cold threshold on sensor 1
++       *  4 : Interrupt normal to hot on sensor 0
++       *
++       *  3 : Interrupt high offset interrupt on sensor 0
++       *  2 : Interrupt low offset interrupt on sensor 0
++       *  1 : Interrupt hot threshold on sensor 0
++       *  0 : Interrupt cold threshold on sensor 0
++       *
++       * We are interested in the sensor(s) responsible of the
++       * interrupt event. We update the thermal framework with the
++       * thermal zone associated with the sensor. The framework will
++       * take care of the rest whatever the kind of interrupt, we
++       * are only interested in which sensor raised the interrupt.
++       *
++       * sensor 3 interrupt: 0001 1111 1100 0000 0000 0000 0000 0000
++       *                  => 0x1FC00000
++       * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000
++       *                  => 0x00247C00
++       * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000
++       *                  => 0X000881F0
++       * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111
++       *                  => 0x0009001F
++       */
++      value = readl(LVTS_MONINTSTS(lvts_ctrl->base));
++
++      /*
++       * Let's figure out which sensors raised the interrupt
++       *
++       * NOTE: the masks array must be ordered with the index
++       * corresponding to the sensor id eg. index=0, mask for
++       * sensor0.
++       */
++      for (i = 0; i < ARRAY_SIZE(masks); i++) {
++
++              if (!(value & masks[i]))
++                      continue;
++
++              thermal_zone_device_update(lvts_ctrl->sensors[i].tz,
++                                         THERMAL_TRIP_VIOLATED);
++              iret = IRQ_HANDLED;
++      }
++
++      /*
++       * Write back to clear the interrupt status (W1C)
++       */
++      writel(value, LVTS_MONINTSTS(lvts_ctrl->base));
++
++      return iret;
++}
++
++/*
++ * Temperature interrupt handler. Even if the driver supports more
++ * interrupt modes, we use the interrupt when the temperature crosses
++ * the hot threshold the way up and the way down (modulo the
++ * hysteresis).
++ *
++ * Each thermal domain has a couple of interrupts, one for hardware
++ * reset and another one for all the thermal events happening on the
++ * different sensors.
++ *
++ * The interrupt is configured for thermal events when crossing the
++ * hot temperature limit. At each interrupt, we check in every
++ * controller if there is an interrupt pending.
++ */
++static irqreturn_t lvts_irq_handler(int irq, void *data)
++{
++      struct lvts_domain *lvts_td = data;
++      irqreturn_t aux, iret = IRQ_NONE;
++      int i;
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
++
++              aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl);
++              if (aux != IRQ_HANDLED)
++                      continue;
++
++              iret = IRQ_HANDLED;
++      }
++
++      return iret;
++}
++
++static struct thermal_zone_device_ops lvts_ops = {
++      .get_temp = lvts_get_temp,
++      .set_trips = lvts_set_trips,
++};
++
++static int lvts_sensor_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
++                                      const struct lvts_ctrl_data *lvts_ctrl_data)
++{
++      struct lvts_sensor *lvts_sensor = lvts_ctrl->sensors;
++      void __iomem *msr_regs[] = {
++              LVTS_MSR0(lvts_ctrl->base),
++              LVTS_MSR1(lvts_ctrl->base),
++              LVTS_MSR2(lvts_ctrl->base),
++              LVTS_MSR3(lvts_ctrl->base)
++      };
++
++      void __iomem *imm_regs[] = {
++              LVTS_IMMD0(lvts_ctrl->base),
++              LVTS_IMMD1(lvts_ctrl->base),
++              LVTS_IMMD2(lvts_ctrl->base),
++              LVTS_IMMD3(lvts_ctrl->base)
++      };
++
++      int i;
++
++      for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++) {
++
++              int dt_id = lvts_ctrl_data->lvts_sensor[i].dt_id;
++
++              /*
++               * At this point, we don't know which id matches which
++               * sensor. Let's set arbitrally the id from the index.
++               */
++              lvts_sensor[i].id = i;
++
++              /*
++               * The thermal zone registration will set the trip
++               * point interrupt in the thermal controller
++               * register. But this one will be reset in the
++               * initialization after. So we need to post pone the
++               * thermal zone creation after the controller is
++               * setup. For this reason, we store the device tree
++               * node id from the data in the sensor structure
++               */
++              lvts_sensor[i].dt_id = dt_id;
++
++              /*
++               * We assign the base address of the thermal
++               * controller as a back pointer. So it will be
++               * accessible from the different thermal framework ops
++               * as we pass the lvts_sensor pointer as thermal zone
++               * private data.
++               */
++              lvts_sensor[i].base = lvts_ctrl->base;
++
++              /*
++               * Each sensor has its own register address to read from.
++               */
++              lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
++                      imm_regs[i] : msr_regs[i];
++      };
++
++      lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
++
++      return 0;
++}
++
++/*
++ * The efuse blob values follows the sensor enumeration per thermal
++ * controller. The decoding of the stream is as follow:
++ *
++ *                        <--?-> <----big0 ???---> <-sensor0-> <-0->
++ *                        ------------------------------------------
++ * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 |
++ *                        ------------------------------------------
++ *
++ *                        <--sensor1--><-0-> <----big1 ???---> <-sen
++ *                        ------------------------------------------
++ *                        | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD |
++ *                        ------------------------------------------
++ *
++ *                        sor0-> <-0-> <-sensor1-> <-0-> ..........
++ *                        ------------------------------------------
++ *                        | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD |
++ *                        ------------------------------------------
++ *
++ * And so on ...
++ *
++ * The data description gives the offset of the calibration data in
++ * this bytes stream for each sensor.
++ *
++ * Each thermal controller can handle up to 4 sensors max, we don't
++ * care if there are less as the array of calibration is sized to 4
++ * anyway. The unused sensor slot will be zeroed.
++ */
++static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
++                                      const struct lvts_ctrl_data *lvts_ctrl_data,
++                                      u8 *efuse_calibration)
++{
++      int i;
++
++      for (i = 0; i < lvts_ctrl_data->num_lvts_sensor; i++)
++              memcpy(&lvts_ctrl->calibration[i],
++                     efuse_calibration + lvts_ctrl_data->cal_offset[i], 2);
++
++      return 0;
++}
++
++/*
++ * The efuse bytes stream can be split into different chunk of
++ * nvmems. This function reads and concatenate those into a single
++ * buffer so it can be read sequentially when initializing the
++ * calibration data.
++ */
++static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td,
++                                      const struct lvts_data *lvts_data)
++{
++      struct device_node *np = dev_of_node(dev);
++      struct nvmem_cell *cell;
++      struct property *prop;
++      const char *cell_name;
++
++      of_property_for_each_string(np, "nvmem-cell-names", prop, cell_name) {
++              size_t len;
++              u8 *efuse;
++
++              cell = of_nvmem_cell_get(np, cell_name);
++              if (IS_ERR(cell)) {
++                      dev_err(dev, "Failed to get cell '%s'\n", cell_name);
++                      return PTR_ERR(cell);
++              }
++
++              efuse = nvmem_cell_read(cell, &len);
++
++              nvmem_cell_put(cell);
++
++              if (IS_ERR(efuse)) {
++                      dev_err(dev, "Failed to read cell '%s'\n", cell_name);
++                      return PTR_ERR(efuse);
++              }
++
++              lvts_td->calib = devm_krealloc(dev, lvts_td->calib,
++                                             lvts_td->calib_len + len, GFP_KERNEL);
++              if (!lvts_td->calib)
++                      return -ENOMEM;
++
++              memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len);
++
++              lvts_td->calib_len += len;
++
++              kfree(efuse);
++      }
++
++      return 0;
++}
++
++static int lvts_golden_temp_init(struct device *dev, u32 *value)
++{
++      u32 gt;
++
++      gt = (*value) >> 24;
++
++      if (gt && gt < LVTS_GOLDEN_TEMP_MAX)
++              golden_temp = gt;
++
++      coeff_b = golden_temp * 500 + LVTS_COEFF_B;
++
++      return 0;
++}
++
++static int lvts_ctrl_init(struct device *dev, struct lvts_domain *lvts_td,
++                                      const struct lvts_data *lvts_data)
++{
++      size_t size = sizeof(*lvts_td->lvts_ctrl) * lvts_data->num_lvts_ctrl;
++      struct lvts_ctrl *lvts_ctrl;
++      int i, ret;
++
++      /*
++       * Create the calibration bytes stream from efuse data
++       */
++      ret = lvts_calibration_read(dev, lvts_td, lvts_data);
++      if (ret)
++              return ret;
++
++      /*
++       * The golden temp information is contained in the first chunk
++       * of efuse data.
++       */
++      ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib);
++      if (ret)
++              return ret;
++
++      lvts_ctrl = devm_kzalloc(dev, size, GFP_KERNEL);
++      if (!lvts_ctrl)
++              return -ENOMEM;
++
++      for (i = 0; i < lvts_data->num_lvts_ctrl; i++) {
++
++              lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset;
++
++              ret = lvts_sensor_init(dev, &lvts_ctrl[i],
++                                     &lvts_data->lvts_ctrl[i]);
++              if (ret)
++                      return ret;
++
++              ret = lvts_calibration_init(dev, &lvts_ctrl[i],
++                                          &lvts_data->lvts_ctrl[i],
++                                          lvts_td->calib);
++              if (ret)
++                      return ret;
++
++              /*
++               * The mode the ctrl will use to read the temperature
++               * (filtered or immediate)
++               */
++              lvts_ctrl[i].mode = lvts_data->lvts_ctrl[i].mode;
++
++              /*
++               * The temperature to raw temperature must be done
++               * after initializing the calibration.
++               */
++              lvts_ctrl[i].hw_tshut_raw_temp =
++                      lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
++      }
++
++      /*
++       * We no longer need the efuse bytes stream, let's free it
++       */
++      devm_kfree(dev, lvts_td->calib);
++
++      lvts_td->lvts_ctrl = lvts_ctrl;
++      lvts_td->num_lvts_ctrl = lvts_data->num_lvts_ctrl;
++
++      return 0;
++}
++
++/*
++ * At this point the configuration register is the only place in the
++ * driver where we write multiple values. Per hardware constraint,
++ * each write in the configuration register must be separated by a
++ * delay of 2 us.
++ */
++static void lvts_write_config(struct lvts_ctrl *lvts_ctrl, u32 *cmds, int nr_cmds)
++{
++      int i;
++
++      /*
++       * Configuration register
++       */
++      for (i = 0; i < nr_cmds; i++) {
++              writel(cmds[i], LVTS_CONFIG(lvts_ctrl->base));
++              usleep_range(2, 4);
++      }
++}
++
++static int lvts_irq_init(struct lvts_ctrl *lvts_ctrl)
++{
++      /*
++       * LVTS_PROTCTL : Thermal Protection Sensor Selection
++       *
++       * Bits:
++       *
++       * 19-18 : Sensor to base the protection on
++       * 17-16 : Strategy:
++       *         00 : Average of 4 sensors
++       *         01 : Max of 4 sensors
++       *         10 : Selected sensor with bits 19-18
++       *         11 : Reserved
++       */
++      writel(BIT(16), LVTS_PROTCTL(lvts_ctrl->base));
++
++      /*
++       * LVTS_PROTTA : Stage 1 temperature threshold
++       * LVTS_PROTTB : Stage 2 temperature threshold
++       * LVTS_PROTTC : Stage 3 temperature threshold
++       *
++       * Bits:
++       *
++       * 14-0: Raw temperature threshold
++       *
++       * writel(0x0, LVTS_PROTTA(lvts_ctrl->base));
++       * writel(0x0, LVTS_PROTTB(lvts_ctrl->base));
++       */
++      writel(lvts_ctrl->hw_tshut_raw_temp, LVTS_PROTTC(lvts_ctrl->base));
++
++      /*
++       * LVTS_MONINT : Interrupt configuration register
++       *
++       * The LVTS_MONINT register layout is the same as the LVTS_MONINTSTS
++       * register, except we set the bits to enable the interrupt.
++       */
++      writel(LVTS_MONINT_CONF, LVTS_MONINT(lvts_ctrl->base));
++
++      return 0;
++}
++
++static int lvts_domain_reset(struct device *dev, struct reset_control *reset)
++{
++      int ret;
++
++      ret = reset_control_assert(reset);
++      if (ret)
++              return ret;
++
++      return reset_control_deassert(reset);
++}
++
++/*
++ * Enable or disable the clocks of a specified thermal controller
++ */
++static int lvts_ctrl_set_enable(struct lvts_ctrl *lvts_ctrl, int enable)
++{
++      /*
++       * LVTS_CLKEN : Internal LVTS clock
++       *
++       * Bits:
++       *
++       * 0 : enable / disable clock
++       */
++      writel(enable, LVTS_CLKEN(lvts_ctrl->base));
++
++      return 0;
++}
++
++static int lvts_ctrl_connect(struct device *dev, struct lvts_ctrl *lvts_ctrl)
++{
++      u32 id, cmds[] = { 0xC103FFFF, 0xC502FF55 };
++
++      lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds));
++
++      /*
++       * LVTS_ID : Get ID and status of the thermal controller
++       *
++       * Bits:
++       *
++       * 0-5  : thermal controller id
++       *   7  : thermal controller connection is valid
++       */
++      id = readl(LVTS_ID(lvts_ctrl->base));
++      if (!(id & BIT(7)))
++              return -EIO;
++
++      return 0;
++}
++
++static int lvts_ctrl_initialize(struct device *dev, struct lvts_ctrl *lvts_ctrl)
++{
++      /*
++       * Write device mask: 0xC1030000
++       */
++      u32 cmds[] = {
++              0xC1030E01, 0xC1030CFC, 0xC1030A8C, 0xC103098D, 0xC10308F1,
++              0xC10307A6, 0xC10306B8, 0xC1030500, 0xC1030420, 0xC1030300,
++              0xC1030030, 0xC10300F6, 0xC1030050, 0xC1030060, 0xC10300AC,
++              0xC10300FC, 0xC103009D, 0xC10300F1, 0xC10300E1
++      };
++
++      lvts_write_config(lvts_ctrl, cmds, ARRAY_SIZE(cmds));
++
++      return 0;
++}
++
++static int lvts_ctrl_calibrate(struct device *dev, struct lvts_ctrl *lvts_ctrl)
++{
++      int i;
++      void __iomem *lvts_edata[] = {
++              LVTS_EDATA00(lvts_ctrl->base),
++              LVTS_EDATA01(lvts_ctrl->base),
++              LVTS_EDATA02(lvts_ctrl->base),
++              LVTS_EDATA03(lvts_ctrl->base)
++      };
++
++      /*
++       * LVTS_EDATA0X : Efuse calibration reference value for sensor X
++       *
++       * Bits:
++       *
++       * 20-0 : Efuse value for normalization data
++       */
++      for (i = 0; i < LVTS_SENSOR_MAX; i++)
++              writel(lvts_ctrl->calibration[i], lvts_edata[i]);
++
++      return 0;
++}
++
++static int lvts_ctrl_configure(struct device *dev, struct lvts_ctrl *lvts_ctrl)
++{
++      u32 value;
++
++      /*
++       * LVTS_TSSEL : Sensing point index numbering
++       *
++       * Bits:
++       *
++       * 31-24: ADC Sense 3
++       * 23-16: ADC Sense 2
++       * 15-8 : ADC Sense 1
++       * 7-0  : ADC Sense 0
++       */
++      value = LVTS_TSSEL_CONF;
++      writel(value, LVTS_TSSEL(lvts_ctrl->base));
++
++      /*
++       * LVTS_CALSCALE : ADC voltage round
++       */
++      value = 0x300;
++      value = LVTS_CALSCALE_CONF;
++
++      /*
++       * LVTS_MSRCTL0 : Sensor filtering strategy
++       *
++       * Filters:
++       *
++       * 000 : One sample
++       * 001 : Avg 2 samples
++       * 010 : 4 samples, drop min and max, avg 2 samples
++       * 011 : 6 samples, drop min and max, avg 4 samples
++       * 100 : 10 samples, drop min and max, avg 8 samples
++       * 101 : 18 samples, drop min and max, avg 16 samples
++       *
++       * Bits:
++       *
++       * 0-2  : Sensor0 filter
++       * 3-5  : Sensor1 filter
++       * 6-8  : Sensor2 filter
++       * 9-11 : Sensor3 filter
++       */
++      value = LVTS_HW_FILTER << 9 |  LVTS_HW_FILTER << 6 |
++                      LVTS_HW_FILTER << 3 | LVTS_HW_FILTER;
++      writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
++
++      /*
++       * LVTS_MSRCTL1 : Measurement control
++       *
++       * Bits:
++       *
++       * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
++       * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
++       * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
++       * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
++       *
++       * That configuration will ignore the filtering and the delays
++       * introduced below in MONCTL1 and MONCTL2
++       */
++      if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
++              value = BIT(9) | BIT(6) | BIT(5) | BIT(4);
++              writel(value, LVTS_MSRCTL1(lvts_ctrl->base));
++      }
++
++      /*
++       * LVTS_MONCTL1 : Period unit and group interval configuration
++       *
++       * The clock source of LVTS thermal controller is 26MHz.
++       *
++       * The period unit is a time base for all the interval delays
++       * specified in the registers. By default we use 12. The time
++       * conversion is done by multiplying by 256 and 1/26.10^6
++       *
++       * An interval delay multiplied by the period unit gives the
++       * duration in seconds.
++       *
++       * - Filter interval delay is a delay between two samples of
++       * the same sensor.
++       *
++       * - Sensor interval delay is a delay between two samples of
++       * different 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 time = 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
++       * Bits:
++       *      29 - 20 : Group interval
++       *      16 - 13 : Send a single interrupt when crossing the hot threshold (1)
++       *                or an interrupt everytime the hot threshold is crossed (0)
++       *       9 - 0  : Period unit
++       *
++       */
++      value = LVTS_GROUP_INTERVAL << 20 | LVTS_PERIOD_UNIT;
++      writel(value, LVTS_MONCTL1(lvts_ctrl->base));
++
++      /*
++       * LVTS_MONCTL2 : Filtering and sensor interval
++       *
++       * Bits:
++       *
++       *      25-16 : Interval unit in PERIOD_UNIT between sample on
++       *              the same sensor, filter interval
++       *       9-0  : Interval unit in PERIOD_UNIT between each sensor
++       *
++       */
++      value = LVTS_FILTER_INTERVAL << 16 | LVTS_SENSOR_INTERVAL;
++      writel(value, LVTS_MONCTL2(lvts_ctrl->base));
++
++      return lvts_irq_init(lvts_ctrl);
++}
++
++static int lvts_ctrl_start(struct device *dev, struct lvts_ctrl *lvts_ctrl)
++{
++      struct lvts_sensor *lvts_sensors = lvts_ctrl->sensors;
++      struct thermal_zone_device *tz;
++      u32 sensor_map = 0;
++      int i;
++
++      for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
++
++              int dt_id = lvts_sensors[i].dt_id;
++
++              tz = devm_thermal_of_zone_register(dev, dt_id, &lvts_sensors[i],
++                                                 &lvts_ops);
++              if (IS_ERR(tz)) {
++                      /*
++                       * This thermal zone is not described in the
++                       * device tree. It is not an error from the
++                       * thermal OF code POV, we just continue.
++                       */
++                      if (PTR_ERR(tz) == -ENODEV)
++                              continue;
++
++                      return PTR_ERR(tz);
++              }
++
++              /*
++               * The thermal zone pointer will be needed in the
++               * interrupt handler, we store it in the sensor
++               * structure. The thermal domain structure will be
++               * passed to the interrupt handler private data as the
++               * interrupt is shared for all the controller
++               * belonging to the thermal domain.
++               */
++              lvts_sensors[i].tz = tz;
++
++              /*
++               * This sensor was correctly associated with a thermal
++               * zone, let's set the corresponding bit in the sensor
++               * map, so we can enable the temperature monitoring in
++               * the hardware thermal controller.
++               */
++              sensor_map |= BIT(i);
++      }
++
++      /*
++       * Bits:
++       *      9: Single point access flow
++       *    0-3: Enable sensing point 0-3
++       *
++       * The initialization of the thermal zones give us
++       * which sensor point to enable. If any thermal zone
++       * was not described in the device tree, it won't be
++       * enabled here in the sensor map.
++       */
++      writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
++
++      return 0;
++}
++
++static int lvts_domain_init(struct device *dev, struct lvts_domain *lvts_td,
++                                      const struct lvts_data *lvts_data)
++{
++      struct lvts_ctrl *lvts_ctrl;
++      int i, ret;
++
++      ret = lvts_ctrl_init(dev, lvts_td, lvts_data);
++      if (ret)
++              return ret;
++
++      ret = lvts_domain_reset(dev, lvts_td->reset);
++      if (ret) {
++              dev_dbg(dev, "Failed to reset domain");
++              return ret;
++      }
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
++
++              lvts_ctrl = &lvts_td->lvts_ctrl[i];
++
++              /*
++               * Initialization steps:
++               *
++               * - Enable the clock
++               * - Connect to the LVTS
++               * - Initialize the LVTS
++               * - Prepare the calibration data
++               * - Select monitored sensors
++               * [ Configure sampling ]
++               * [ Configure the interrupt ]
++               * - Start measurement
++               */
++              ret = lvts_ctrl_set_enable(lvts_ctrl, true);
++              if (ret) {
++                      dev_dbg(dev, "Failed to enable LVTS clock");
++                      return ret;
++              }
++
++              ret = lvts_ctrl_connect(dev, lvts_ctrl);
++              if (ret) {
++                      dev_dbg(dev, "Failed to connect to LVTS controller");
++                      return ret;
++              }
++
++              ret = lvts_ctrl_initialize(dev, lvts_ctrl);
++              if (ret) {
++                      dev_dbg(dev, "Failed to initialize controller");
++                      return ret;
++              }
++
++              ret = lvts_ctrl_calibrate(dev, lvts_ctrl);
++              if (ret) {
++                      dev_dbg(dev, "Failed to calibrate controller");
++                      return ret;
++              }
++
++              ret = lvts_ctrl_configure(dev, lvts_ctrl);
++              if (ret) {
++                      dev_dbg(dev, "Failed to configure controller");
++                      return ret;
++              }
++
++              ret = lvts_ctrl_start(dev, lvts_ctrl);
++              if (ret) {
++                      dev_dbg(dev, "Failed to start controller");
++                      return ret;
++              }
++      }
++
++      return lvts_debugfs_init(dev, lvts_td);
++}
++
++static int lvts_probe(struct platform_device *pdev)
++{
++      const struct lvts_data *lvts_data;
++      struct lvts_domain *lvts_td;
++      struct device *dev = &pdev->dev;
++      struct resource *res;
++      int irq, ret;
++
++      lvts_td = devm_kzalloc(dev, sizeof(*lvts_td), GFP_KERNEL);
++      if (!lvts_td)
++              return -ENOMEM;
++
++      lvts_data = of_device_get_match_data(dev);
++
++      lvts_td->clk = devm_clk_get_enabled(dev, NULL);
++      if (IS_ERR(lvts_td->clk))
++              return dev_err_probe(dev, PTR_ERR(lvts_td->clk), "Failed to retrieve clock\n");
++
++      res = platform_get_mem_or_io(pdev, 0);
++      if (!res)
++              return dev_err_probe(dev, (-ENXIO), "No IO resource\n");
++
++      lvts_td->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
++      if (IS_ERR(lvts_td->base))
++              return dev_err_probe(dev, PTR_ERR(lvts_td->base), "Failed to map io resource\n");
++
++      lvts_td->reset = devm_reset_control_get_by_index(dev, 0);
++      if (IS_ERR(lvts_td->reset))
++              return dev_err_probe(dev, PTR_ERR(lvts_td->reset), "Failed to get reset control\n");
++
++      irq = platform_get_irq(pdev, 0);
++      if (irq < 0)
++              return dev_err_probe(dev, irq, "No irq resource\n");
++
++      ret = lvts_domain_init(dev, lvts_td, lvts_data);
++      if (ret)
++              return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n");
++
++      /*
++       * At this point the LVTS is initialized and enabled. We can
++       * safely enable the interrupt.
++       */
++      ret = devm_request_threaded_irq(dev, irq, NULL, lvts_irq_handler,
++                                      IRQF_ONESHOT, dev_name(dev), lvts_td);
++      if (ret)
++              return dev_err_probe(dev, ret, "Failed to request interrupt\n");
++
++      platform_set_drvdata(pdev, lvts_td);
++
++      return 0;
++}
++
++static int lvts_remove(struct platform_device *pdev)
++{
++      struct lvts_domain *lvts_td;
++      int i;
++
++      lvts_td = platform_get_drvdata(pdev);
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++)
++              lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false);
++
++      lvts_debugfs_exit(lvts_td);
++
++      return 0;
++}
++
++static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = {
++      {
++              .cal_offset = { 0x04, 0x07 },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_MCU_BIG_CPU0 },
++                      { .dt_id = MT8195_MCU_BIG_CPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x0,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      },
++      {
++              .cal_offset = { 0x0d, 0x10 },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_MCU_BIG_CPU2 },
++                      { .dt_id = MT8195_MCU_BIG_CPU3 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x100,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      },
++      {
++              .cal_offset = { 0x16, 0x19, 0x1c, 0x1f },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_MCU_LITTLE_CPU0 },
++                      { .dt_id = MT8195_MCU_LITTLE_CPU1 },
++                      { .dt_id = MT8195_MCU_LITTLE_CPU2 },
++                      { .dt_id = MT8195_MCU_LITTLE_CPU3 }
++              },
++              .num_lvts_sensor = 4,
++              .offset = 0x200,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      }
++};
++
++static const struct lvts_data mt8195_lvts_mcu_data = {
++      .lvts_ctrl      = mt8195_lvts_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_data_ctrl),
++};
++
++static const struct of_device_id lvts_of_match[] = {
++      { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data },
++      {},
++};
++MODULE_DEVICE_TABLE(of, lvts_of_match);
++
++static struct platform_driver lvts_driver = {
++      .probe = lvts_probe,
++      .remove = lvts_remove,
++      .driver = {
++              .name = "mtk-lvts-thermal",
++              .of_match_table = lvts_of_match,
++      },
++};
++module_platform_driver(lvts_driver);
++
++MODULE_AUTHOR("Balsam CHIHI <bchihi@baylibre.com>");
++MODULE_DESCRIPTION("MediaTek LVTS Thermal Driver");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch b/target/linux/mediatek/patches-6.1/830-v6.4-07-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch
new file mode 100644 (file)
index 0000000..b6a5f64
--- /dev/null
@@ -0,0 +1,186 @@
+From 498e2f7a6e69dcbca24715de2b4b97569fdfeff4 Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Thu, 9 Feb 2023 11:56:24 +0100
+Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal controllers
+
+Add LVTS thermal controllers dt-binding definition for mt8192 and mt8195.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20230209105628.50294-3-bchihi@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ .../thermal/mediatek,lvts-thermal.yaml        | 142 ++++++++++++++++++
+ .../thermal/mediatek,lvts-thermal.h           |  19 +++
+ 2 files changed, 161 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
+ create mode 100644 include/dt-bindings/thermal/mediatek,lvts-thermal.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
+@@ -0,0 +1,142 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/thermal/mediatek,lvts-thermal.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: MediaTek SoC Low Voltage Thermal Sensor (LVTS)
++
++maintainers:
++  - Balsam CHIHI <bchihi@baylibre.com>
++
++description: |
++  LVTS is a thermal management architecture composed of three subsystems,
++  a Sensing device - Thermal Sensing Micro Circuit Unit (TSMCU),
++  a Converter - Low Voltage Thermal Sensor converter (LVTS), and
++  a Digital controller (LVTS_CTRL).
++
++properties:
++  compatible:
++    enum:
++      - mediatek,mt8192-lvts-ap
++      - mediatek,mt8192-lvts-mcu
++      - mediatek,mt8195-lvts-ap
++      - mediatek,mt8195-lvts-mcu
++
++  reg:
++    maxItems: 1
++
++  interrupts:
++    maxItems: 1
++
++  clocks:
++    maxItems: 1
++
++  resets:
++    maxItems: 1
++    description: LVTS reset for clearing temporary data on AP/MCU.
++
++  nvmem-cells:
++    minItems: 1
++    items:
++      - description: Calibration eFuse data 1 for LVTS
++      - description: Calibration eFuse data 2 for LVTS
++
++  nvmem-cell-names:
++    minItems: 1
++    items:
++      - const: lvts-calib-data-1
++      - const: lvts-calib-data-2
++
++  "#thermal-sensor-cells":
++    const: 1
++
++allOf:
++  - $ref: thermal-sensor.yaml#
++
++  - if:
++      properties:
++        compatible:
++          contains:
++            enum:
++              - mediatek,mt8192-lvts-ap
++              - mediatek,mt8192-lvts-mcu
++    then:
++      properties:
++        nvmem-cells:
++          maxItems: 1
++
++        nvmem-cell-names:
++          maxItems: 1
++
++  - if:
++      properties:
++        compatible:
++          contains:
++            enum:
++              - mediatek,mt8195-lvts-ap
++              - mediatek,mt8195-lvts-mcu
++    then:
++      properties:
++        nvmem-cells:
++          minItems: 2
++
++        nvmem-cell-names:
++          minItems: 2
++
++required:
++  - compatible
++  - reg
++  - interrupts
++  - clocks
++  - resets
++  - nvmem-cells
++  - nvmem-cell-names
++  - "#thermal-sensor-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/interrupt-controller/arm-gic.h>
++    #include <dt-bindings/clock/mt8195-clk.h>
++    #include <dt-bindings/reset/mt8195-resets.h>
++    #include <dt-bindings/thermal/mediatek,lvts-thermal.h>
++
++    soc {
++      #address-cells = <2>;
++      #size-cells = <2>;
++
++      lvts_mcu: thermal-sensor@11278000 {
++        compatible = "mediatek,mt8195-lvts-mcu";
++        reg = <0 0x11278000 0 0x1000>;
++        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-data-1", "lvts-calib-data-2";
++        #thermal-sensor-cells = <1>;
++      };
++    };
++
++    thermal_zones: thermal-zones {
++      cpu0-thermal {
++        polling-delay = <1000>;
++        polling-delay-passive = <250>;
++        thermal-sensors = <&lvts_mcu MT8195_MCU_LITTLE_CPU0>;
++
++        trips {
++          cpu0_alert: trip-alert {
++            temperature = <85000>;
++            hysteresis = <2000>;
++            type = "passive";
++          };
++
++          cpu0_crit: trip-crit {
++            temperature = <100000>;
++            hysteresis = <2000>;
++            type = "critical";
++          };
++        };
++      };
++    };
+--- /dev/null
++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ * Copyright (c) 2023 MediaTek Inc.
++ * Author: Balsam CHIHI <bchihi@baylibre.com>
++ */
++
++#ifndef __MEDIATEK_LVTS_DT_H
++#define __MEDIATEK_LVTS_DT_H
++
++#define MT8195_MCU_BIG_CPU0     0
++#define MT8195_MCU_BIG_CPU1     1
++#define MT8195_MCU_BIG_CPU2     2
++#define MT8195_MCU_BIG_CPU3     3
++#define MT8195_MCU_LITTLE_CPU0  4
++#define MT8195_MCU_LITTLE_CPU1  5
++#define MT8195_MCU_LITTLE_CPU2  6
++#define MT8195_MCU_LITTLE_CPU3  7
++
++#endif /* __MEDIATEK_LVTS_DT_H */
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch b/target/linux/mediatek/patches-6.1/830-v6.4-08-dt-bindings-thermal-mediatek-Add-AP-domain-to-LVTS-t.patch
new file mode 100644 (file)
index 0000000..efb0d8b
--- /dev/null
@@ -0,0 +1,35 @@
+From 05aaa7fdb0736262e224369b9b9f1410320fc71b Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 7 Mar 2023 16:45:21 +0100
+Subject: [PATCH] dt-bindings: thermal: mediatek: Add AP domain to LVTS thermal
+ controllers for mt8195
+
+Add AP Domain to LVTS thermal controllers dt-binding definition for mt8195.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Acked-by: Rob Herring <robh@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230307154524.118541-2-bchihi@baylibre.com
+---
+ include/dt-bindings/thermal/mediatek,lvts-thermal.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h
++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h
+@@ -16,4 +16,14 @@
+ #define MT8195_MCU_LITTLE_CPU2  6
+ #define MT8195_MCU_LITTLE_CPU3  7
++#define MT8195_AP_VPU0  8
++#define MT8195_AP_VPU1  9
++#define MT8195_AP_GPU0  10
++#define MT8195_AP_GPU1  11
++#define MT8195_AP_VDEC  12
++#define MT8195_AP_IMG   13
++#define MT8195_AP_INFRA 14
++#define MT8195_AP_CAM0  15
++#define MT8195_AP_CAM1  16
++
+ #endif /* __MEDIATEK_LVTS_DT_H */
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch b/target/linux/mediatek/patches-6.1/830-v6.4-09-thermal-core-Add-a-thermal-zone-devdata-accessor.patch
new file mode 100644 (file)
index 0000000..c689693
--- /dev/null
@@ -0,0 +1,65 @@
+From a6ff3c0021468721b96e84892a8cae24bde8d65f Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:29 +0100
+Subject: [PATCH] thermal/core: Add a thermal zone 'devdata' accessor
+
+The thermal zone device structure is exposed to the different drivers
+and obviously they access the internals while that should be
+restricted to the core thermal code.
+
+In order to self-encapsulate the thermal core code, we need to prevent
+the drivers accessing directly the thermal zone structure and provide
+accessor functions to deal with.
+
+Provide an accessor to the 'devdata' structure and make use of it in
+the different drivers.
+
+No functional changes intended.
+
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/thermal_core.c | 6 ++++++
+ include/linux/thermal.h        | 7 +++++++
+ 2 files changed, 13 insertions(+)
+
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1346,6 +1346,12 @@ struct thermal_zone_device *thermal_zone
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_device_register);
++void *thermal_zone_device_priv(struct thermal_zone_device *tzd)
++{
++      return tzd->devdata;
++}
++EXPORT_SYMBOL_GPL(thermal_zone_device_priv);
++
+ /**
+  * thermal_zone_device_unregister - removes the registered thermal zone device
+  * @tz: the thermal zone device to remove
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -346,6 +346,8 @@ thermal_zone_device_register_with_trips(
+                                       void *, struct thermal_zone_device_ops *,
+                                       struct thermal_zone_params *, int, int);
++void *thermal_zone_device_priv(struct thermal_zone_device *tzd);
++
+ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
+                                    struct thermal_cooling_device *,
+                                    unsigned long, unsigned long,
+@@ -417,6 +419,11 @@ static inline int thermal_zone_get_offse
+               struct thermal_zone_device *tz)
+ { return -ENODEV; }
++static inline void *thermal_zone_device_priv(struct thermal_zone_device *tz)
++{
++      return NULL;
++}
++
+ static inline int thermal_zone_device_enable(struct thermal_zone_device *tz)
+ { return -ENODEV; }
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-10-thermal-core-Add-thermal_zone_device-structure-type-.patch
new file mode 100644 (file)
index 0000000..66d3c9e
--- /dev/null
@@ -0,0 +1,55 @@
+From 072e35c98806100182c0a7263cf4cba09ce43463 Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:38 +0100
+Subject: [PATCH] thermal/core: Add thermal_zone_device structure 'type'
+ accessor
+
+The thermal zone device structure is exposed via the exported
+thermal.h header. This structure should stay private the thermal core
+code. In order to encapsulate the structure, let's add an accessor to
+get the 'type' of the thermal zone.
+
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/thermal_core.c | 6 ++++++
+ include/linux/thermal.h        | 6 ++++++
+ 2 files changed, 12 insertions(+)
+
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -1352,6 +1352,12 @@ void *thermal_zone_device_priv(struct th
+ }
+ EXPORT_SYMBOL_GPL(thermal_zone_device_priv);
++const char *thermal_zone_device_type(struct thermal_zone_device *tzd)
++{
++      return tzd->type;
++}
++EXPORT_SYMBOL_GPL(thermal_zone_device_type);
++
+ /**
+  * thermal_zone_device_unregister - removes the registered thermal zone device
+  * @tz: the thermal zone device to remove
+--- a/include/linux/thermal.h
++++ b/include/linux/thermal.h
+@@ -347,6 +347,7 @@ thermal_zone_device_register_with_trips(
+                                       struct thermal_zone_params *, int, int);
+ void *thermal_zone_device_priv(struct thermal_zone_device *tzd);
++const char *thermal_zone_device_type(struct thermal_zone_device *tzd);
+ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
+                                    struct thermal_cooling_device *,
+@@ -423,6 +424,11 @@ static inline void *thermal_zone_device_
+ {
+       return NULL;
+ }
++
++static inline const char *thermal_zone_device_type(struct thermal_zone_device *tzd)
++{
++      return NULL;
++}
+ static inline int thermal_zone_device_enable(struct thermal_zone_device *tz)
+ { return -ENODEV; }
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch b/target/linux/mediatek/patches-6.1/830-v6.4-11-thermal-core-Use-the-thermal-zone-devdata-accessor-i.patch
new file mode 100644 (file)
index 0000000..57bc910
--- /dev/null
@@ -0,0 +1,74 @@
+From 7d78bab533eb9aa0e5240e25a204e8f416723ed6 Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:30 +0100
+Subject: [PATCH 07/42] thermal/core: Use the thermal zone 'devdata' accessor
+ in thermal located drivers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The thermal zone device structure is exposed to the different drivers
+and obviously they access the internals while that should be
+restricted to the core thermal code.
+
+In order to self-encapsulate the thermal core code, we need to prevent
+the drivers accessing directly the thermal zone structure and provide
+accessor functions to deal with.
+
+Use the devdata accessor introduced in the previous patch.
+
+No functional changes intended.
+
+[skipped drivers not relevant for mediatek target]
+
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> #R-Car
+Acked-by: Mark Brown <broonie@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> #MediaTek auxadc and lvts
+Reviewed-by: Balsam CHIHI <bchihi@baylibre.com> #Mediatek lvts
+Reviewed-by: Adam Ward <DLG-Adam.Ward.opensource@dm.renesas.com> #da9062
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>  #spread
+Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> #sun8i_thermal
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com> #Broadcom
+Reviewed-by: Dhruva Gole <d-gole@ti.com> # K3 bandgap
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Heiko Stuebner <heiko@sntech.de> #rockchip
+Reviewed-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com> #uniphier
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/mediatek/auxadc_thermal.c           |  2 +-
+ drivers/thermal/mediatek/lvts_thermal.c             |  4 ++--
+ 43 files changed, 71 insertions(+), 73 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -763,7 +763,7 @@ static int mtk_thermal_bank_temperature(
+ static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
+ {
+-      struct mtk_thermal *mt = tz->devdata;
++      struct mtk_thermal *mt = thermal_zone_device_priv(tz);
+       int i;
+       int tempmax = INT_MIN;
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -252,7 +252,7 @@ static u32 lvts_temp_to_raw(int temperat
+ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+-      struct lvts_sensor *lvts_sensor = tz->devdata;
++      struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+       void __iomem *msr = lvts_sensor->msr;
+       u32 value;
+@@ -290,7 +290,7 @@ static int lvts_get_temp(struct thermal_
+ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
+ {
+-      struct lvts_sensor *lvts_sensor = tz->devdata;
++      struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+       void __iomem *base = lvts_sensor->base;
+       u32 raw_low = lvts_temp_to_raw(low);
+       u32 raw_high = lvts_temp_to_raw(high);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch b/target/linux/mediatek/patches-6.1/830-v6.4-12-thermal-hwmon-Use-the-right-device-for-devm_thermal_.patch
new file mode 100644 (file)
index 0000000..647b3b0
--- /dev/null
@@ -0,0 +1,201 @@
+From cc9c60e9cfeeac45d63361fa8c085c43c4bdfe3a Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:36 +0100
+Subject: [PATCH 08/42] thermal/hwmon: Use the right device for
+ devm_thermal_add_hwmon_sysfs()
+
+The devres variant of thermal_add_hwmon_sysfs() only takes the thermal
+zone structure pointer as parameter.
+
+Actually, it uses the tz->device to add it in the devres list.
+
+It is preferable to use the device registering the thermal zone
+instead of the thermal zone device itself. That prevents the driver
+accessing the thermal zone structure internals and it is from my POV
+more correct regarding how devm_ is used.
+
+[skipped imx thermal which did not apply cleanly and irrelevant on
+mediatek target]
+
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> #amlogic_thermal
+Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> #sun8i_thermal
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> #MediaTek auxadc
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/amlogic_thermal.c                  | 2 +-
+ drivers/thermal/imx_sc_thermal.c                   | 2 +-
+ drivers/thermal/k3_bandgap.c                       | 2 +-
+ drivers/thermal/mediatek/auxadc_thermal.c          | 2 +-
+ drivers/thermal/qcom/qcom-spmi-adc-tm5.c           | 2 +-
+ drivers/thermal/qcom/qcom-spmi-temp-alarm.c        | 2 +-
+ drivers/thermal/qcom/tsens.c                       | 2 +-
+ drivers/thermal/qoriq_thermal.c                    | 2 +-
+ drivers/thermal/sun8i_thermal.c                    | 2 +-
+ drivers/thermal/tegra/tegra30-tsensor.c            | 2 +-
+ drivers/thermal/thermal_hwmon.c                    | 4 ++--
+ drivers/thermal/thermal_hwmon.h                    | 4 ++--
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +-
+ 13 files changed, 15 insertions(+), 15 deletions(-)
+
+--- a/drivers/thermal/amlogic_thermal.c
++++ b/drivers/thermal/amlogic_thermal.c
+@@ -286,7 +286,7 @@ static int amlogic_thermal_probe(struct
+               return ret;
+       }
+-      if (devm_thermal_add_hwmon_sysfs(pdata->tzd))
++      if (devm_thermal_add_hwmon_sysfs(&pdev->dev, pdata->tzd))
+               dev_warn(&pdev->dev, "Failed to add hwmon sysfs attributes\n");
+       ret = amlogic_thermal_initialize(pdata);
+--- a/drivers/thermal/imx_sc_thermal.c
++++ b/drivers/thermal/imx_sc_thermal.c
+@@ -120,7 +120,7 @@ static int imx_sc_thermal_probe(struct p
+                       return ret;
+               }
+-              if (devm_thermal_add_hwmon_sysfs(sensor->tzd))
++              if (devm_thermal_add_hwmon_sysfs(&pdev->dev, sensor->tzd))
+                       dev_warn(&pdev->dev, "failed to add hwmon sysfs attributes\n");
+       }
+--- a/drivers/thermal/k3_bandgap.c
++++ b/drivers/thermal/k3_bandgap.c
+@@ -222,7 +222,7 @@ static int k3_bandgap_probe(struct platf
+                       goto err_alloc;
+               }
+-              if (devm_thermal_add_hwmon_sysfs(data[id].tzd))
++              if (devm_thermal_add_hwmon_sysfs(dev, data[id].tzd))
+                       dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
+       }
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1210,7 +1210,7 @@ static int mtk_thermal_probe(struct plat
+               goto err_disable_clk_peri_therm;
+       }
+-      ret = devm_thermal_add_hwmon_sysfs(tzdev);
++      ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev);
+       if (ret)
+               dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
++++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
+@@ -688,7 +688,7 @@ static int adc_tm5_register_tzd(struct a
+                       return PTR_ERR(tzd);
+               }
+               adc_tm->channels[i].tzd = tzd;
+-              if (devm_thermal_add_hwmon_sysfs(tzd))
++              if (devm_thermal_add_hwmon_sysfs(adc_tm->dev, tzd))
+                       dev_warn(adc_tm->dev,
+                                "Failed to add hwmon sysfs attributes\n");
+       }
+--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
++++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+@@ -460,7 +460,7 @@ static int qpnp_tm_probe(struct platform
+               return ret;
+       }
+-      if (devm_thermal_add_hwmon_sysfs(chip->tz_dev))
++      if (devm_thermal_add_hwmon_sysfs(&pdev->dev, chip->tz_dev))
+               dev_warn(&pdev->dev,
+                        "Failed to add hwmon sysfs attributes\n");
+--- a/drivers/thermal/qcom/tsens.c
++++ b/drivers/thermal/qcom/tsens.c
+@@ -1056,7 +1056,7 @@ static int tsens_register(struct tsens_p
+               if (priv->ops->enable)
+                       priv->ops->enable(priv, i);
+-              if (devm_thermal_add_hwmon_sysfs(tzd))
++              if (devm_thermal_add_hwmon_sysfs(priv->dev, tzd))
+                       dev_warn(priv->dev,
+                                "Failed to add hwmon sysfs attributes\n");
+       }
+--- a/drivers/thermal/qoriq_thermal.c
++++ b/drivers/thermal/qoriq_thermal.c
+@@ -158,7 +158,7 @@ static int qoriq_tmu_register_tmu_zone(s
+                       return ret;
+               }
+-              if (devm_thermal_add_hwmon_sysfs(tzd))
++              if (devm_thermal_add_hwmon_sysfs(dev, tzd))
+                       dev_warn(dev,
+                                "Failed to add hwmon sysfs attributes\n");
+--- a/drivers/thermal/sun8i_thermal.c
++++ b/drivers/thermal/sun8i_thermal.c
+@@ -468,7 +468,7 @@ static int sun8i_ths_register(struct ths
+               if (IS_ERR(tmdev->sensor[i].tzd))
+                       return PTR_ERR(tmdev->sensor[i].tzd);
+-              if (devm_thermal_add_hwmon_sysfs(tmdev->sensor[i].tzd))
++              if (devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd))
+                       dev_warn(tmdev->dev,
+                                "Failed to add hwmon sysfs attributes\n");
+       }
+--- a/drivers/thermal/tegra/tegra30-tsensor.c
++++ b/drivers/thermal/tegra/tegra30-tsensor.c
+@@ -530,7 +530,7 @@ static int tegra_tsensor_register_channe
+               return 0;
+       }
+-      if (devm_thermal_add_hwmon_sysfs(tsc->tzd))
++      if (devm_thermal_add_hwmon_sysfs(ts->dev, tsc->tzd))
+               dev_warn(ts->dev, "failed to add hwmon sysfs attributes\n");
+       return 0;
+--- a/drivers/thermal/thermal_hwmon.c
++++ b/drivers/thermal/thermal_hwmon.c
+@@ -255,7 +255,7 @@ static void devm_thermal_hwmon_release(s
+       thermal_remove_hwmon_sysfs(*(struct thermal_zone_device **)res);
+ }
+-int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
++int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz)
+ {
+       struct thermal_zone_device **ptr;
+       int ret;
+@@ -272,7 +272,7 @@ int devm_thermal_add_hwmon_sysfs(struct
+       }
+       *ptr = tz;
+-      devres_add(&tz->device, ptr);
++      devres_add(dev, ptr);
+       return ret;
+ }
+--- a/drivers/thermal/thermal_hwmon.h
++++ b/drivers/thermal/thermal_hwmon.h
+@@ -17,7 +17,7 @@
+ #ifdef CONFIG_THERMAL_HWMON
+ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
+-int devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz);
++int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz);
+ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz);
+ #else
+ static inline int
+@@ -27,7 +27,7 @@ thermal_add_hwmon_sysfs(struct thermal_z
+ }
+ static inline int
+-devm_thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
++devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device *tz)
+ {
+       return 0;
+ }
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -182,7 +182,7 @@ int ti_thermal_expose_sensor(struct ti_b
+       ti_bandgap_set_sensor_data(bgp, id, data);
+       ti_bandgap_write_update_interval(bgp, data->sensor_id, interval);
+-      if (devm_thermal_add_hwmon_sysfs(data->ti_thermal))
++      if (devm_thermal_add_hwmon_sysfs(bgp->dev, data->ti_thermal))
+               dev_warn(bgp->dev, "failed to add hwmon sysfs attributes\n");
+       return 0;
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch b/target/linux/mediatek/patches-6.1/830-v6.4-13-thermal-Don-t-use-device-internal-thermal-zone-struc.patch
new file mode 100644 (file)
index 0000000..9dedc2c
--- /dev/null
@@ -0,0 +1,79 @@
+From 5a72b8e4bac753e4dc74dc0a1335d120f63df97a Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:37 +0100
+Subject: [PATCH 09/42] thermal: Don't use 'device' internal thermal zone
+ structure field
+
+Some drivers are directly using the thermal zone's 'device' structure
+field.
+
+Use the driver device pointer instead of the thermal zone device when
+it is available.
+
+Remove the traces when they are duplicate with the traces in the core
+code.
+
+[again skipped imx_thermal.c]
+
+Cc: Jean Delvare <jdelvare@suse.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Balsam CHIHI <bchihi@baylibre.com> #Mediatek LVTS
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> #MediaTek LVTS
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/mediatek/lvts_thermal.c            | 4 ++--
+ drivers/thermal/thermal_hwmon.c                    | 4 ++--
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -305,7 +305,7 @@ static int lvts_set_trips(struct thermal
+        * 14-0 : Raw temperature for threshold
+        */
+       if (low != -INT_MAX) {
+-              dev_dbg(&tz->device, "Setting low limit temperature interrupt: %d\n", low);
++              pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low);
+               writel(raw_low, LVTS_H2NTHRE(base));
+       }
+@@ -318,7 +318,7 @@ static int lvts_set_trips(struct thermal
+        *
+        * 14-0 : Raw temperature for threshold
+        */
+-      dev_dbg(&tz->device, "Setting high limit temperature interrupt: %d\n", high);
++      pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high);
+       writel(raw_high, LVTS_HTHRE(base));
+       return 0;
+--- a/drivers/thermal/thermal_hwmon.c
++++ b/drivers/thermal/thermal_hwmon.c
+@@ -220,14 +220,14 @@ void thermal_remove_hwmon_sysfs(struct t
+       hwmon = thermal_hwmon_lookup_by_type(tz);
+       if (unlikely(!hwmon)) {
+               /* Should never happen... */
+-              dev_dbg(&tz->device, "hwmon device lookup failed!\n");
++              dev_dbg(hwmon->device, "hwmon device lookup failed!\n");
+               return;
+       }
+       temp = thermal_hwmon_lookup_temp(hwmon, tz);
+       if (unlikely(!temp)) {
+               /* Should never happen... */
+-              dev_dbg(&tz->device, "temperature input lookup failed!\n");
++              dev_dbg(hwmon->device, "temperature input lookup failed!\n");
+               return;
+       }
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -43,7 +43,7 @@ static void ti_thermal_work(struct work_
+       thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
+-      dev_dbg(&data->ti_thermal->device, "updated thermal zone %s\n",
++      dev_dbg(data->bgp->dev, "updated thermal zone %s\n",
+               data->ti_thermal->type);
+ }
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch b/target/linux/mediatek/patches-6.1/830-v6.4-14-thermal-Use-thermal_zone_device_type-accessor.patch
new file mode 100644 (file)
index 0000000..8cec9ab
--- /dev/null
@@ -0,0 +1,62 @@
+From 66b3a292d3fc749e8ec7ac5278a17e8a5757ecbc Mon Sep 17 00:00:00 2001
+From: Daniel Lezcano <daniel.lezcano@linaro.org>
+Date: Wed, 1 Mar 2023 21:14:41 +0100
+Subject: [PATCH 10/42] thermal: Use thermal_zone_device_type() accessor
+
+Replace the accesses to 'tz->type' by its accessor version in order to
+self-encapsulate the thermal_zone_device structure.
+
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com> #mlxsw
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> #MediaTek LVTS
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 2 +-
+ drivers/thermal/mediatek/lvts_thermal.c            | 6 ++++--
+ drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +-
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+@@ -168,7 +168,7 @@ mlxsw_thermal_module_trips_update(struct
+       if (crit_temp > emerg_temp) {
+               dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
+-                       tz->tzdev->type, crit_temp, emerg_temp);
++                       thermal_zone_device_type(tz->tzdev), crit_temp, emerg_temp);
+               return 0;
+       }
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -305,7 +305,8 @@ static int lvts_set_trips(struct thermal
+        * 14-0 : Raw temperature for threshold
+        */
+       if (low != -INT_MAX) {
+-              pr_debug("%s: Setting low limit temperature interrupt: %d\n", tz->type, low);
++              pr_debug("%s: Setting low limit temperature interrupt: %d\n",
++                       thermal_zone_device_type(tz), low);
+               writel(raw_low, LVTS_H2NTHRE(base));
+       }
+@@ -318,7 +319,8 @@ static int lvts_set_trips(struct thermal
+        *
+        * 14-0 : Raw temperature for threshold
+        */
+-      pr_debug("%s: Setting high limit temperature interrupt: %d\n", tz->type, high);
++      pr_debug("%s: Setting high limit temperature interrupt: %d\n",
++               thermal_zone_device_type(tz), high);
+       writel(raw_high, LVTS_HTHRE(base));
+       return 0;
+--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
++++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+@@ -44,7 +44,7 @@ static void ti_thermal_work(struct work_
+       thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
+       dev_dbg(data->bgp->dev, "updated thermal zone %s\n",
+-              data->ti_thermal->type);
++              thermal_zone_device_type(data->ti_thermal));
+ }
+ /**
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch b/target/linux/mediatek/patches-6.1/830-v6.4-15-thermal-drivers-mediatek-Control-buffer-enablement-t.patch
new file mode 100644 (file)
index 0000000..68f41fd
--- /dev/null
@@ -0,0 +1,81 @@
+From f6658c1c4ae98477d6be00495226c0617354fe76 Mon Sep 17 00:00:00 2001
+From: Markus Schneider-Pargmann <msp@baylibre.com>
+Date: Fri, 27 Jan 2023 16:44:43 +0100
+Subject: [PATCH 11/42] thermal/drivers/mediatek: Control buffer enablement
+ tweaks
+
+Add logic in order to be able to turn on the control buffer on MT8365.
+This change now allows to have control buffer support for MTK_THERMAL_V1,
+and it allows to define the register offset, and mask used to enable it.
+
+Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
+Signed-off-by: Fabien Parent <fparent@baylibre.com>
+Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-2-55a1ae14af74@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 28 +++++++++++++++--------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -307,6 +307,9 @@ struct mtk_thermal_data {
+       bool need_switch_bank;
+       struct thermal_bank_cfg bank_data[MAX_NUM_ZONES];
+       enum mtk_thermal_version version;
++      u32 apmixed_buffer_ctl_reg;
++      u32 apmixed_buffer_ctl_mask;
++      u32 apmixed_buffer_ctl_set;
+ };
+ struct mtk_thermal {
+@@ -560,6 +563,9 @@ static const struct mtk_thermal_data mt7
+       .adcpnp = mt7622_adcpnp,
+       .sensor_mux_values = mt7622_mux_values,
+       .version = MTK_THERMAL_V2,
++      .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1,
++      .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3),
++      .apmixed_buffer_ctl_set = BIT(0),
+ };
+ /*
+@@ -1079,14 +1085,18 @@ static const struct of_device_id mtk_the
+ };
+ MODULE_DEVICE_TABLE(of, mtk_thermal_of_match);
+-static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base)
++static void mtk_thermal_turn_on_buffer(struct mtk_thermal *mt,
++                                     void __iomem *apmixed_base)
+ {
+-      int tmp;
++      u32 tmp;
++
++      if (!mt->conf->apmixed_buffer_ctl_reg)
++              return;
+-      tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1);
+-      tmp &= ~(0x37);
+-      tmp |= 0x1;
+-      writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1);
++      tmp = readl(apmixed_base + mt->conf->apmixed_buffer_ctl_reg);
++      tmp &= mt->conf->apmixed_buffer_ctl_mask;
++      tmp |= mt->conf->apmixed_buffer_ctl_set;
++      writel(tmp, apmixed_base + mt->conf->apmixed_buffer_ctl_reg);
+       udelay(200);
+ }
+@@ -1184,10 +1194,10 @@ static int mtk_thermal_probe(struct plat
+               goto err_disable_clk_auxadc;
+       }
+-      if (mt->conf->version != MTK_THERMAL_V1) {
+-              mtk_thermal_turn_on_buffer(apmixed_base);
++      mtk_thermal_turn_on_buffer(mt, apmixed_base);
++
++      if (mt->conf->version != MTK_THERMAL_V2)
+               mtk_thermal_release_periodic_ts(mt, auxadc_base);
+-      }
+       if (mt->conf->version == MTK_THERMAL_V1)
+               mt->raw_to_mcelsius = raw_to_mcelsius_v1;
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch b/target/linux/mediatek/patches-6.1/830-v6.4-16-thermal-drivers-mediatek-Add-support-for-MT8365-SoC.patch
new file mode 100644 (file)
index 0000000..285c6f6
--- /dev/null
@@ -0,0 +1,123 @@
+From c4eff784465f88218dc5eb51320320464db83d3f Mon Sep 17 00:00:00 2001
+From: Fabien Parent <fparent@baylibre.com>
+Date: Fri, 27 Jan 2023 16:44:44 +0100
+Subject: [PATCH 12/42] thermal/drivers/mediatek: Add support for MT8365 SoC
+
+MT8365 is similar to the other SoCs supported by the driver. It has only
+one bank and 3 actual sensors that can be multiplexed. There is another
+one sensor that does not have usable data.
+
+Signed-off-by: Fabien Parent <fparent@baylibre.com>
+Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-3-55a1ae14af74@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 68 +++++++++++++++++++++++
+ 1 file changed, 68 insertions(+)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -31,6 +31,7 @@
+ #define AUXADC_CON2_V         0x010
+ #define AUXADC_DATA(channel)  (0x14 + (channel) * 4)
++#define APMIXED_SYS_TS_CON0   0x600
+ #define APMIXED_SYS_TS_CON1   0x604
+ /* Thermal Controller Registers */
+@@ -281,6 +282,17 @@ enum mtk_thermal_version {
+ /* The calibration coefficient of sensor  */
+ #define MT7986_CALIBRATION            165
++/* MT8365 */
++#define MT8365_TEMP_AUXADC_CHANNEL 11
++#define MT8365_CALIBRATION 164
++#define MT8365_NUM_CONTROLLER 1
++#define MT8365_NUM_BANKS 1
++#define MT8365_NUM_SENSORS 3
++#define MT8365_NUM_SENSORS_PER_ZONE 3
++#define MT8365_TS1 0
++#define MT8365_TS2 1
++#define MT8365_TS3 2
++
+ struct mtk_thermal;
+ struct thermal_bank_cfg {
+@@ -435,6 +447,24 @@ static const int mt7986_mux_values[MT798
+ static const int mt7986_vts_index[MT7986_NUM_SENSORS] = { VTS1 };
+ static const int mt7986_tc_offset[MT7986_NUM_CONTROLLER] = { 0x0, };
++/* MT8365 thermal sensor data */
++static const int mt8365_bank_data[MT8365_NUM_SENSORS] = {
++      MT8365_TS1, MT8365_TS2, MT8365_TS3
++};
++
++static const int mt8365_msr[MT8365_NUM_SENSORS_PER_ZONE] = {
++      TEMP_MSR0, TEMP_MSR1, TEMP_MSR2
++};
++
++static const int mt8365_adcpnp[MT8365_NUM_SENSORS_PER_ZONE] = {
++      TEMP_ADCPNP0, TEMP_ADCPNP1, TEMP_ADCPNP2
++};
++
++static const int mt8365_mux_values[MT8365_NUM_SENSORS] = { 0, 1, 2 };
++static const int mt8365_tc_offset[MT8365_NUM_CONTROLLER] = { 0 };
++
++static const int mt8365_vts_index[MT8365_NUM_SENSORS] = { VTS1, VTS2, VTS3 };
++
+ /*
+  * The MT8173 thermal controller has four banks. Each bank can read up to
+  * four temperature sensors simultaneously. The MT8173 has a total of 5
+@@ -510,6 +540,40 @@ static const struct mtk_thermal_data mt2
+ };
+ /*
++ * The MT8365 thermal controller has one bank, which can read up to
++ * four temperature sensors simultaneously. The MT8365 has a total of 3
++ * temperature sensors.
++ *
++ * The thermal core only gets the maximum temperature of this one bank,
++ * so the bank concept wouldn't be necessary here. However, the SVS (Smart
++ * Voltage Scaling) unit makes its decisions based on the same bank
++ * data.
++ */
++static const struct mtk_thermal_data mt8365_thermal_data = {
++      .auxadc_channel = MT8365_TEMP_AUXADC_CHANNEL,
++      .num_banks = MT8365_NUM_BANKS,
++      .num_sensors = MT8365_NUM_SENSORS,
++      .vts_index = mt8365_vts_index,
++      .cali_val = MT8365_CALIBRATION,
++      .num_controller = MT8365_NUM_CONTROLLER,
++      .controller_offset = mt8365_tc_offset,
++      .need_switch_bank = false,
++      .bank_data = {
++              {
++                      .num_sensors = MT8365_NUM_SENSORS,
++                      .sensors = mt8365_bank_data
++              },
++      },
++      .msr = mt8365_msr,
++      .adcpnp = mt8365_adcpnp,
++      .sensor_mux_values = mt8365_mux_values,
++      .version = MTK_THERMAL_V1,
++      .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON0,
++      .apmixed_buffer_ctl_mask = (u32) ~GENMASK(29, 28),
++      .apmixed_buffer_ctl_set = 0,
++};
++
++/*
+  * The MT2712 thermal controller has one bank, which can read up to
+  * four temperature sensors simultaneously. The MT2712 has a total of 4
+  * temperature sensors.
+@@ -1080,6 +1144,10 @@ static const struct of_device_id mtk_the
+       {
+               .compatible = "mediatek,mt8183-thermal",
+               .data = (void *)&mt8183_thermal_data,
++      },
++      {
++              .compatible = "mediatek,mt8365-thermal",
++              .data = (void *)&mt8365_thermal_data,
+       }, {
+       },
+ };
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch b/target/linux/mediatek/patches-6.1/830-v6.4-17-thermal-drivers-mediatek-Add-delay-after-thermal-ban.patch
new file mode 100644 (file)
index 0000000..5c99aa8
--- /dev/null
@@ -0,0 +1,50 @@
+From 4eead70db74922bc61e9d0b4591524369a335751 Mon Sep 17 00:00:00 2001
+From: Amjad Ouled-Ameur <aouledameur@baylibre.com>
+Date: Fri, 27 Jan 2023 16:44:46 +0100
+Subject: [PATCH 13/42] thermal/drivers/mediatek: Add delay after thermal banks
+ initialization
+
+Thermal sensor reads performed immediately after thermal bank
+initialization returns bogus values. This is currently tackled by returning
+0 if the temperature is bogus (exceeding 200000).
+
+Instead, add a delay between the bank init and the thermal zone device
+register to properly fix this.
+
+Signed-off-by: Michael Kao <michael.kao@mediatek.com>
+Signed-off-by: Hsin-Yi Wang <hsinyi@chromium.org>
+Signed-off-by: Amjad Ouled-Ameur <aouledameur@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20221018-up-i350-thermal-bringup-v9-5-55a1ae14af74@baylibre.com
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -816,14 +816,6 @@ static int mtk_thermal_bank_temperature(
+                       mt, conf->bank_data[bank->id].sensors[i], raw);
+-              /*
+-               * The first read of a sensor often contains very high bogus
+-               * temperature value. Filter these out so that the system does
+-               * not immediately shut down.
+-               */
+-              if (temp > 200000)
+-                      temp = 0;
+-
+               if (temp > max)
+                       max = temp;
+       }
+@@ -1281,6 +1273,9 @@ static int mtk_thermal_probe(struct plat
+       platform_set_drvdata(pdev, mt);
++      /* Delay for thermal banks to be ready */
++      msleep(30);
++
+       tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+                                             &mtk_thermal_ops);
+       if (IS_ERR(tzdev)) {
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch b/target/linux/mediatek/patches-6.1/830-v6.4-18-thermal-drivers-mediatek-lvts_thermal-Fix-sensor-1-i.patch
new file mode 100644 (file)
index 0000000..734f5c1
--- /dev/null
@@ -0,0 +1,46 @@
+From ad9dc9e92367803a4f9576aea0dab110d03fc510 Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wenst@chromium.org>
+Date: Tue, 28 Mar 2023 11:10:17 +0800
+Subject: [PATCH 14/42] thermal/drivers/mediatek/lvts_thermal: Fix sensor 1
+ interrupt status bitmask
+
+The binary representation for sensor 1 interrupt status was incorrectly
+assembled, when compared to the full table given in the same comment
+section. The conversion into hex was also incorrect, leading to
+incorrect interrupt status bitmask for sensor 1. This would cause the
+driver to incorrectly identify changes for sensor 1, when in fact it
+was sensor 0, or a sensor access time out.
+
+Fix the binary and hex representations in the comments, and the actual
+bitmask macro.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230328031017.1360976-1-wenst@chromium.org
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -66,7 +66,7 @@
+ #define LVTS_MONINT_CONF                      0x9FBF7BDE
+ #define LVTS_INT_SENSOR0                      0x0009001F
+-#define LVTS_INT_SENSOR1                      0X000881F0
++#define LVTS_INT_SENSOR1                      0x001203E0
+ #define LVTS_INT_SENSOR2                      0x00247C00
+ #define LVTS_INT_SENSOR3                      0x1FC00000
+@@ -395,8 +395,8 @@ static irqreturn_t lvts_ctrl_irq_handler
+        *                  => 0x1FC00000
+        * sensor 2 interrupt: 0000 0000 0010 0100 0111 1100 0000 0000
+        *                  => 0x00247C00
+-       * sensor 1 interrupt: 0000 0000 0001 0001 0000 0011 1110 0000
+-       *                  => 0X000881F0
++       * sensor 1 interrupt: 0000 0000 0001 0010 0000 0011 1110 0000
++       *                  => 0X001203E0
+        * sensor 0 interrupt: 0000 0000 0000 1001 0000 0000 0001 1111
+        *                  => 0x0009001F
+        */
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-19-thermal-drivers-mediatek-lvts_thermal-Add-AP-domain-.patch
new file mode 100644 (file)
index 0000000..d09c205
--- /dev/null
@@ -0,0 +1,149 @@
+From 9aad43ad3285fc21158fb416830a6156a9a31fa5 Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 7 Mar 2023 16:45:22 +0100
+Subject: [PATCH 15/42] thermal/drivers/mediatek/lvts_thermal: Add AP domain
+ for mt8195
+
+Add MT8195 AP Domain support to LVTS Driver.
+
+Take the opportunity to update the comments to show calibration data
+information related to the new domain.
+
+[dlezcano]: Massaged a bit the changelog
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230307154524.118541-3-bchihi@baylibre.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 94 +++++++++++++++++++------
+ 1 file changed, 74 insertions(+), 20 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -530,29 +530,33 @@ static int lvts_sensor_init(struct devic
+  * The efuse blob values follows the sensor enumeration per thermal
+  * controller. The decoding of the stream is as follow:
+  *
+- *                        <--?-> <----big0 ???---> <-sensor0-> <-0->
+- *                        ------------------------------------------
+- * index in the stream: : | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 |
+- *                        ------------------------------------------
++ * stream index map for MCU Domain :
+  *
+- *                        <--sensor1--><-0-> <----big1 ???---> <-sen
+- *                        ------------------------------------------
+- *                        | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD |
+- *                        ------------------------------------------
++ * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1----->
++ *  0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09
+  *
+- *                        sor0-> <-0-> <-sensor1-> <-0-> ..........
+- *                        ------------------------------------------
+- *                        | 0x7 | 0x8 | 0x9 | 0xA | 0xB | OxC | OxD |
+- *                        ------------------------------------------
++ * <-----mcu-tc#1-----> <-----sensor#2-----> <-----sensor#3----->
++ *  0x0A | 0x0B | 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12
+  *
+- * And so on ...
++ * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7----->
++ *  0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21
++ *
++ * stream index map for AP Domain :
++ *
++ * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1----->
++ *  0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A
++ *
++ * <-----ap--tc#1-----> <-----sensor#2-----> <-----sensor#3----->
++ *  0x2B | 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33
++ *
++ * <-----ap--tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6----->
++ *  0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F
++ *
++ * <-----ap--tc#3-----> <-----sensor#7-----> <-----sensor#8----->
++ *  0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48
+  *
+  * The data description gives the offset of the calibration data in
+  * this bytes stream for each sensor.
+- *
+- * Each thermal controller can handle up to 4 sensors max, we don't
+- * care if there are less as the array of calibration is sized to 4
+- * anyway. The unused sensor slot will be zeroed.
+  */
+ static int lvts_calibration_init(struct device *dev, struct lvts_ctrl *lvts_ctrl,
+                                       const struct lvts_ctrl_data *lvts_ctrl_data,
+@@ -1165,7 +1169,7 @@ static int lvts_remove(struct platform_d
+       return 0;
+ }
+-static const struct lvts_ctrl_data mt8195_lvts_data_ctrl[] = {
++static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = {
+       {
+               .cal_offset = { 0x04, 0x07 },
+               .lvts_sensor = {
+@@ -1200,13 +1204,63 @@ static const struct lvts_ctrl_data mt819
+       }
+ };
++static const struct lvts_ctrl_data mt8195_lvts_ap_data_ctrl[] = {
++              {
++              .cal_offset = { 0x25, 0x28 },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_AP_VPU0 },
++                      { .dt_id = MT8195_AP_VPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x0,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      },
++      {
++              .cal_offset = { 0x2e, 0x31 },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_AP_GPU0 },
++                      { .dt_id = MT8195_AP_GPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x100,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      },
++      {
++              .cal_offset = { 0x37, 0x3a, 0x3d },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_AP_VDEC },
++                      { .dt_id = MT8195_AP_IMG },
++                      { .dt_id = MT8195_AP_INFRA },
++              },
++              .num_lvts_sensor = 3,
++              .offset = 0x200,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      },
++      {
++              .cal_offset = { 0x43, 0x46 },
++              .lvts_sensor = {
++                      { .dt_id = MT8195_AP_CAM0 },
++                      { .dt_id = MT8195_AP_CAM1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x300,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8195,
++      }
++};
++
+ static const struct lvts_data mt8195_lvts_mcu_data = {
+-      .lvts_ctrl      = mt8195_lvts_data_ctrl,
+-      .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_data_ctrl),
++      .lvts_ctrl      = mt8195_lvts_mcu_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl),
++};
++
++static const struct lvts_data mt8195_lvts_ap_data = {
++      .lvts_ctrl      = mt8195_lvts_ap_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl),
+ };
+ 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);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch b/target/linux/mediatek/patches-6.1/830-v6.4-20-Revert-thermal-drivers-mediatek-Add-delay-after-ther.patch
new file mode 100644 (file)
index 0000000..a48ea37
--- /dev/null
@@ -0,0 +1,53 @@
+From 7105a86760bd9e4d107075cefc75016b693a5542 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 19 Apr 2023 08:11:45 +0200
+Subject: [PATCH 16/42] Revert "thermal/drivers/mediatek: Add delay after
+ thermal banks initialization"
+
+Some more testing revealed that this commit introduces a regression on some
+MT8173 Chromebooks and at least on one MT6795 Sony Xperia M5 smartphone due
+to the delay being apparently variable and machine specific.
+
+Another solution would be to delay for a bit more (~70ms) but this is not
+feasible for two reasons: first of all, we're adding an even bigger delay
+in a probe function; second, some machines need less, some may need even
+more, making the msleep at probe solution highly suboptimal.
+
+This reverts commit 10debf8c2da8011c8009dd4b3f6d0ab85891c81b.
+
+Fixes: 10debf8c2da8 ("thermal/drivers/mediatek: Add delay after thermal banks initialization")
+Reported-by: "kernelci.org bot" <bot@kernelci.org>
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230419061146.22246-2-angelogioacchino.delregno@collabora.com
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -816,6 +816,14 @@ static int mtk_thermal_bank_temperature(
+                       mt, conf->bank_data[bank->id].sensors[i], raw);
++              /*
++               * The first read of a sensor often contains very high bogus
++               * temperature value. Filter these out so that the system does
++               * not immediately shut down.
++               */
++              if (temp > 200000)
++                      temp = 0;
++
+               if (temp > max)
+                       max = temp;
+       }
+@@ -1273,9 +1281,6 @@ static int mtk_thermal_probe(struct plat
+       platform_set_drvdata(pdev, mt);
+-      /* Delay for thermal banks to be ready */
+-      msleep(30);
+-
+       tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+                                             &mtk_thermal_ops);
+       if (IS_ERR(tzdev)) {
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch b/target/linux/mediatek/patches-6.1/830-v6.4-21-thermal-drivers-mediatek-Add-temperature-constraints.patch
new file mode 100644 (file)
index 0000000..aae87af
--- /dev/null
@@ -0,0 +1,78 @@
+From 681b652c9dfc4037d4a55b2733e091a4e1a5de18 Mon Sep 17 00:00:00 2001
+From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Date: Wed, 19 Apr 2023 08:11:46 +0200
+Subject: [PATCH 17/42] thermal/drivers/mediatek: Add temperature constraints
+ to validate read
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The AUXADC thermal v1 allows reading temperature range between -20°C to
+150°C and any value out of this range is invalid.
+
+Add new definitions for MT8173_TEMP_{MIN_MAX} and a new small helper
+mtk_thermal_temp_is_valid() to check if new readings are in range: if
+not, we tell to the API that the reading is invalid by returning
+THERMAL_TEMP_INVALID.
+
+It was chosen to introduce the helper function because, even though this
+temperature range is realistically ok for all, it comes from a downstream
+kernel driver for version 1, but here we also support v2 and v3 which may
+may have wider constraints.
+
+Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230419061146.22246-3-angelogioacchino.delregno@collabora.com
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 24 +++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -116,6 +116,10 @@
+ /* The calibration coefficient of sensor  */
+ #define MT8173_CALIBRATION    165
++/* Valid temperatures range */
++#define MT8173_TEMP_MIN               -20000
++#define MT8173_TEMP_MAX               150000
++
+ /*
+  * Layout of the fuses providing the calibration data
+  * These macros could be used for MT8183, MT8173, MT2701, and MT2712.
+@@ -689,6 +693,11 @@ static const struct mtk_thermal_data mt7
+       .version = MTK_THERMAL_V3,
+ };
++static bool mtk_thermal_temp_is_valid(int temp)
++{
++      return (temp >= MT8173_TEMP_MIN) && (temp <= MT8173_TEMP_MAX);
++}
++
+ /**
+  * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius
+  * @mt:       The thermal controller
+@@ -815,14 +824,17 @@ static int mtk_thermal_bank_temperature(
+               temp = mt->raw_to_mcelsius(
+                       mt, conf->bank_data[bank->id].sensors[i], raw);
+-
+               /*
+-               * The first read of a sensor often contains very high bogus
+-               * temperature value. Filter these out so that the system does
+-               * not immediately shut down.
++               * Depending on the filt/sen intervals and ADC polling time,
++               * we may need up to 60 milliseconds after initialization: this
++               * will result in the first reading containing an out of range
++               * temperature value.
++               * Validate the reading to both address the aforementioned issue
++               * and to eventually avoid bogus readings during runtime in the
++               * event that the AUXADC gets unstable due to high EMI, etc.
+                */
+-              if (temp > 200000)
+-                      temp = 0;
++              if (!mtk_thermal_temp_is_valid(temp))
++                      temp = THERMAL_TEMP_INVALID;
+               if (temp > max)
+                       max = temp;
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-22-thermal-drivers-mediatek-Use-devm_of_iomap-to-avoid-.patch
new file mode 100644 (file)
index 0000000..782684a
--- /dev/null
@@ -0,0 +1,53 @@
+From 458fa1d508de3f17e49d974a0158d9aeff273a58 Mon Sep 17 00:00:00 2001
+From: Kang Chen <void0red@hust.edu.cn>
+Date: Wed, 19 Apr 2023 10:07:48 +0800
+Subject: [PATCH 18/42] thermal/drivers/mediatek: Use devm_of_iomap to avoid
+ resource leak in mtk_thermal_probe
+
+Smatch reports:
+1. mtk_thermal_probe() warn: 'apmixed_base' from of_iomap() not released.
+2. mtk_thermal_probe() warn: 'auxadc_base' from of_iomap() not released.
+
+The original code forgets to release iomap resource when handling errors,
+fix it by switch to devm_of_iomap.
+
+Fixes: 89945047b166 ("thermal: mediatek: Add tsensor support for V2 thermal system")
+Signed-off-by: Kang Chen <void0red@hust.edu.cn>
+Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230419020749.621257-1-void0red@hust.edu.cn
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1232,7 +1232,12 @@ static int mtk_thermal_probe(struct plat
+               return -ENODEV;
+       }
+-      auxadc_base = of_iomap(auxadc, 0);
++      auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL);
++      if (IS_ERR(auxadc_base)) {
++              of_node_put(auxadc);
++              return PTR_ERR(auxadc_base);
++      }
++
+       auxadc_phys_base = of_get_phys_base(auxadc);
+       of_node_put(auxadc);
+@@ -1248,7 +1253,12 @@ static int mtk_thermal_probe(struct plat
+               return -ENODEV;
+       }
+-      apmixed_base = of_iomap(apmixedsys, 0);
++      apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL);
++      if (IS_ERR(apmixed_base)) {
++              of_node_put(apmixedsys);
++              return PTR_ERR(apmixed_base);
++      }
++
+       apmixed_phys_base = of_get_phys_base(apmixedsys);
+       of_node_put(apmixedsys);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch b/target/linux/mediatek/patches-6.1/830-v6.4-23-thermal-drivers-mediatek-Change-clk_prepare_enable-t.patch
new file mode 100644 (file)
index 0000000..d7896db
--- /dev/null
@@ -0,0 +1,100 @@
+From 227d1856924ec00a4f5bdf5afcf77bc7f3f04e86 Mon Sep 17 00:00:00 2001
+From: Kang Chen <void0red@hust.edu.cn>
+Date: Wed, 19 Apr 2023 10:07:49 +0800
+Subject: [PATCH 19/42] thermal/drivers/mediatek: Change clk_prepare_enable to
+ devm_clk_get_enabled in mtk_thermal_probe
+
+Use devm_clk_get_enabled to do automatic resource management.
+Meanwhile, remove error handling labels in the probe function and
+the whole remove function.
+
+Signed-off-by: Kang Chen <void0red@hust.edu.cn>
+Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230419020749.621257-2-void0red@hust.edu.cn
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 44 +++++------------------
+ 1 file changed, 9 insertions(+), 35 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1206,14 +1206,6 @@ static int mtk_thermal_probe(struct plat
+       mt->conf = of_device_get_match_data(&pdev->dev);
+-      mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
+-      if (IS_ERR(mt->clk_peri_therm))
+-              return PTR_ERR(mt->clk_peri_therm);
+-
+-      mt->clk_auxadc = devm_clk_get(&pdev->dev, "auxadc");
+-      if (IS_ERR(mt->clk_auxadc))
+-              return PTR_ERR(mt->clk_auxadc);
+-
+       mt->thermal_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+       if (IS_ERR(mt->thermal_base))
+               return PTR_ERR(mt->thermal_base);
+@@ -1272,16 +1264,18 @@ static int mtk_thermal_probe(struct plat
+       if (ret)
+               return ret;
+-      ret = clk_prepare_enable(mt->clk_auxadc);
+-      if (ret) {
++      mt->clk_auxadc = devm_clk_get_enabled(&pdev->dev, "auxadc");
++      if (IS_ERR(mt->clk_auxadc)) {
++              ret = PTR_ERR(mt->clk_auxadc);
+               dev_err(&pdev->dev, "Can't enable auxadc clk: %d\n", ret);
+               return ret;
+       }
+-      ret = clk_prepare_enable(mt->clk_peri_therm);
+-      if (ret) {
++      mt->clk_peri_therm = devm_clk_get_enabled(&pdev->dev, "therm");
++      if (IS_ERR(mt->clk_peri_therm)) {
++              ret = PTR_ERR(mt->clk_peri_therm);
+               dev_err(&pdev->dev, "Can't enable peri clk: %d\n", ret);
+-              goto err_disable_clk_auxadc;
++              return ret;
+       }
+       mtk_thermal_turn_on_buffer(mt, apmixed_base);
+@@ -1305,38 +1299,18 @@ static int mtk_thermal_probe(struct plat
+       tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+                                             &mtk_thermal_ops);
+-      if (IS_ERR(tzdev)) {
+-              ret = PTR_ERR(tzdev);
+-              goto err_disable_clk_peri_therm;
+-      }
++      if (IS_ERR(tzdev))
++              return PTR_ERR(tzdev);
+       ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev);
+       if (ret)
+               dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
+       return 0;
+-
+-err_disable_clk_peri_therm:
+-      clk_disable_unprepare(mt->clk_peri_therm);
+-err_disable_clk_auxadc:
+-      clk_disable_unprepare(mt->clk_auxadc);
+-
+-      return ret;
+-}
+-
+-static int mtk_thermal_remove(struct platform_device *pdev)
+-{
+-      struct mtk_thermal *mt = platform_get_drvdata(pdev);
+-
+-      clk_disable_unprepare(mt->clk_peri_therm);
+-      clk_disable_unprepare(mt->clk_auxadc);
+-
+-      return 0;
+ }
+ static struct platform_driver mtk_thermal_driver = {
+       .probe = mtk_thermal_probe,
+-      .remove = mtk_thermal_remove,
+       .driver = {
+               .name = "mtk-thermal",
+               .of_match_table = mtk_thermal_of_match,
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch b/target/linux/mediatek/patches-6.1/830-v6.4-24-thermal-drivers-mediatek-Use-of_address_to_resource.patch
new file mode 100644 (file)
index 0000000..fd18a53
--- /dev/null
@@ -0,0 +1,36 @@
+From 655fe2533ac05323a07c19ba079bf2064e7741af Mon Sep 17 00:00:00 2001
+From: Rob Herring <robh@kernel.org>
+Date: Sun, 19 Mar 2023 11:32:31 -0500
+Subject: [PATCH 20/42] thermal/drivers/mediatek: Use of_address_to_resource()
+
+Replace of_get_address() and of_translate_address() calls with single
+call to of_address_to_resource().
+
+Signed-off-by: Rob Herring <robh@kernel.org>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230319163231.226738-1-robh@kernel.org
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -979,14 +979,12 @@ static void mtk_thermal_init_bank(struct
+ static u64 of_get_phys_base(struct device_node *np)
+ {
+-      u64 size64;
+-      const __be32 *regaddr_p;
++      struct resource res;
+-      regaddr_p = of_get_address(np, 0, &size64, NULL);
+-      if (!regaddr_p)
++      if (of_address_to_resource(np, 0, &res))
+               return OF_BAD_ADDR;
+-      return of_translate_address(np, regaddr_p);
++      return res.start;
+ }
+ static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf)
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch b/target/linux/mediatek/patches-6.1/830-v6.4-25-Revert-thermal-drivers-mediatek-Use-devm_of_iomap-to.patch
new file mode 100644 (file)
index 0000000..c3ff17d
--- /dev/null
@@ -0,0 +1,57 @@
+From 2c380d07215e6fce3ac66cc5af059bc2c2a69f7a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo?= <ricardo.canuelo@collabora.com>
+Date: Thu, 25 May 2023 14:18:11 +0200
+Subject: [PATCH 21/42] Revert "thermal/drivers/mediatek: Use devm_of_iomap to
+ avoid resource leak in mtk_thermal_probe"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit f05c7b7d9ea9477fcc388476c6f4ade8c66d2d26.
+
+That change was causing a regression in the generic-adc-thermal-probed
+bootrr test as reported in the kernelci-results list [1].
+A proper rework will take longer, so revert it for now.
+
+[1] https://groups.io/g/kernelci-results/message/42660
+
+Fixes: f05c7b7d9ea9 ("thermal/drivers/mediatek: Use devm_of_iomap to avoid resource leak in mtk_thermal_probe")
+Signed-off-by: Ricardo Cañuelo <ricardo.canuelo@collabora.com>
+Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230525121811.3360268-1-ricardo.canuelo@collabora.com
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 14 ++------------
+ 1 file changed, 2 insertions(+), 12 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1222,12 +1222,7 @@ static int mtk_thermal_probe(struct plat
+               return -ENODEV;
+       }
+-      auxadc_base = devm_of_iomap(&pdev->dev, auxadc, 0, NULL);
+-      if (IS_ERR(auxadc_base)) {
+-              of_node_put(auxadc);
+-              return PTR_ERR(auxadc_base);
+-      }
+-
++      auxadc_base = of_iomap(auxadc, 0);
+       auxadc_phys_base = of_get_phys_base(auxadc);
+       of_node_put(auxadc);
+@@ -1243,12 +1238,7 @@ static int mtk_thermal_probe(struct plat
+               return -ENODEV;
+       }
+-      apmixed_base = devm_of_iomap(&pdev->dev, apmixedsys, 0, NULL);
+-      if (IS_ERR(apmixed_base)) {
+-              of_node_put(apmixedsys);
+-              return PTR_ERR(apmixed_base);
+-      }
+-
++      apmixed_base = of_iomap(apmixedsys, 0);
+       apmixed_phys_base = of_get_phys_base(apmixedsys);
+       of_node_put(apmixedsys);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch b/target/linux/mediatek/patches-6.1/830-v6.4-26-thermal-drivers-mediatek-lvts_thermal-Register-therm.patch
new file mode 100644 (file)
index 0000000..c445652
--- /dev/null
@@ -0,0 +1,37 @@
+From 496f4b08981d8a788ad5a2073fa1c65a2af1862b Mon Sep 17 00:00:00 2001
+From: Chen-Yu Tsai <wenst@chromium.org>
+Date: Tue, 13 Jun 2023 17:13:16 +0800
+Subject: [PATCH 22/42] thermal/drivers/mediatek/lvts_thermal: Register thermal
+ zones as hwmon sensors
+
+Register thermal zones as hwmon sensors to let userspace read
+temperatures using standard hwmon interface.
+
+Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230613091317.1691247-1-wenst@chromium.org
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -19,6 +19,8 @@
+ #include <linux/thermal.h>
+ #include <dt-bindings/thermal/mediatek,lvts-thermal.h>
++#include "../thermal_hwmon.h"
++
+ #define LVTS_MONCTL0(__base)  (__base + 0x0000)
+ #define LVTS_MONCTL1(__base)  (__base + 0x0004)
+ #define LVTS_MONCTL2(__base)  (__base + 0x0008)
+@@ -996,6 +998,9 @@ static int lvts_ctrl_start(struct device
+                       return PTR_ERR(tz);
+               }
++              if (devm_thermal_add_hwmon_sysfs(dev, tz))
++                      dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id);
++
+               /*
+                * The thermal zone pointer will be needed in the
+                * interrupt handler, we store it in the sensor
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch b/target/linux/mediatek/patches-6.1/830-v6.4-27-thermal-drivers-mediatek-lvts_thermal-Remove-redunda.patch
new file mode 100644 (file)
index 0000000..22e7a95
--- /dev/null
@@ -0,0 +1,28 @@
+From 885b9768ce2a66ed5d250822aed53d5114c895da Mon Sep 17 00:00:00 2001
+From: Yangtao Li <frank.li@vivo.com>
+Date: Tue, 20 Jun 2023 17:07:31 +0800
+Subject: [PATCH 23/42] thermal/drivers/mediatek/lvts_thermal: Remove redundant
+ msg in lvts_ctrl_start()
+
+The upper-layer devm_thermal_add_hwmon_sysfs() function can directly
+print error information.
+
+Signed-off-by: Yangtao Li <frank.li@vivo.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230620090732.50025-10-frank.li@vivo.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -998,8 +998,7 @@ static int lvts_ctrl_start(struct device
+                       return PTR_ERR(tz);
+               }
+-              if (devm_thermal_add_hwmon_sysfs(dev, tz))
+-                      dev_warn(dev, "zone %d: Failed to add hwmon sysfs attributes\n", dt_id);
++              devm_thermal_add_hwmon_sysfs(dev, tz);
+               /*
+                * The thermal zone pointer will be needed in the
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-29-thermal-drivers-mediatek-lvts_thermal-Handle-IRQ-on-.patch
new file mode 100644 (file)
index 0000000..bc67727
--- /dev/null
@@ -0,0 +1,40 @@
+From 27b389d9f62c2174f95fe4002b11e77d4cb3ce80 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:32 -0400
+Subject: [PATCH 25/42] thermal/drivers/mediatek/lvts_thermal: Handle IRQ on
+ all controllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There is a single IRQ handler for each LVTS thermal domain, and it is
+supposed to check each of its underlying controllers for the origin of
+the interrupt and clear its status. However due to a typo, only the
+first controller was ever being handled, which resulted in the interrupt
+never being cleared when it happened on the other controllers. Add the
+missing index so interrupts are handled for all controllers.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-2-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -451,7 +451,7 @@ static irqreturn_t lvts_irq_handler(int
+       for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
+-              aux = lvts_ctrl_irq_handler(lvts_td->lvts_ctrl);
++              aux = lvts_ctrl_irq_handler(&lvts_td->lvts_ctrl[i]);
+               if (aux != IRQ_HANDLED)
+                       continue;
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-30-thermal-drivers-mediatek-lvts_thermal-Honor-sensors-.patch
new file mode 100644 (file)
index 0000000..51d119c
--- /dev/null
@@ -0,0 +1,120 @@
+From 6d827142643ee10c13ff9a1d90f38fb399aa9fff Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:33 -0400
+Subject: [PATCH 26/42] thermal/drivers/mediatek/lvts_thermal: Honor sensors in
+ immediate mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Each controller can be configured to operate on immediate or filtered
+mode. On filtered mode, the sensors are enabled by setting the
+corresponding bits in MONCTL0, while on immediate mode, by setting
+MSRCTL1.
+
+Previously, the code would set MSRCTL1 for all four sensors when
+configured to immediate mode, but given that the controller might not
+have all four sensors connected, this would cause interrupts to trigger
+for non-existent sensors. Fix this by handling the MSRCTL1 register
+analogously to the MONCTL0: only enable the sensors that were declared.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-3-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 57 ++++++++++++++-----------
+ 1 file changed, 33 insertions(+), 24 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -897,24 +897,6 @@ static int lvts_ctrl_configure(struct de
+       writel(value, LVTS_MSRCTL0(lvts_ctrl->base));
+       /*
+-       * LVTS_MSRCTL1 : Measurement control
+-       *
+-       * Bits:
+-       *
+-       * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
+-       * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
+-       * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
+-       * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
+-       *
+-       * That configuration will ignore the filtering and the delays
+-       * introduced below in MONCTL1 and MONCTL2
+-       */
+-      if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
+-              value = BIT(9) | BIT(6) | BIT(5) | BIT(4);
+-              writel(value, LVTS_MSRCTL1(lvts_ctrl->base));
+-      }
+-
+-      /*
+        * LVTS_MONCTL1 : Period unit and group interval configuration
+        *
+        * The clock source of LVTS thermal controller is 26MHz.
+@@ -979,6 +961,15 @@ static int lvts_ctrl_start(struct device
+       struct thermal_zone_device *tz;
+       u32 sensor_map = 0;
+       int i;
++      /*
++       * Bitmaps to enable each sensor on immediate and filtered modes, as
++       * described in MSRCTL1 and MONCTL0 registers below, respectively.
++       */
++      u32 sensor_imm_bitmap[] = { BIT(4), BIT(5), BIT(6), BIT(9) };
++      u32 sensor_filt_bitmap[] = { BIT(0), BIT(1), BIT(2), BIT(3) };
++
++      u32 *sensor_bitmap = lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE ?
++                           sensor_imm_bitmap : sensor_filt_bitmap;
+       for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++) {
+@@ -1016,20 +1007,38 @@ static int lvts_ctrl_start(struct device
+                * map, so we can enable the temperature monitoring in
+                * the hardware thermal controller.
+                */
+-              sensor_map |= BIT(i);
++              sensor_map |= sensor_bitmap[i];
+       }
+       /*
+-       * Bits:
+-       *      9: Single point access flow
+-       *    0-3: Enable sensing point 0-3
+-       *
+        * The initialization of the thermal zones give us
+        * which sensor point to enable. If any thermal zone
+        * was not described in the device tree, it won't be
+        * enabled here in the sensor map.
+        */
+-      writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
++      if (lvts_ctrl->mode == LVTS_MSR_IMMEDIATE_MODE) {
++              /*
++               * LVTS_MSRCTL1 : Measurement control
++               *
++               * Bits:
++               *
++               * 9: Ignore MSRCTL0 config and do immediate measurement on sensor3
++               * 6: Ignore MSRCTL0 config and do immediate measurement on sensor2
++               * 5: Ignore MSRCTL0 config and do immediate measurement on sensor1
++               * 4: Ignore MSRCTL0 config and do immediate measurement on sensor0
++               *
++               * That configuration will ignore the filtering and the delays
++               * introduced in MONCTL1 and MONCTL2
++               */
++              writel(sensor_map, LVTS_MSRCTL1(lvts_ctrl->base));
++      } else {
++              /*
++               * Bits:
++               *      9: Single point access flow
++               *    0-3: Enable sensing point 0-3
++               */
++              writel(sensor_map | BIT(9), LVTS_MONCTL0(lvts_ctrl->base));
++      }
+       return 0;
+ }
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch b/target/linux/mediatek/patches-6.1/830-v6.4-31-thermal-drivers-mediatek-lvts_thermal-Use-offset-thr.patch
new file mode 100644 (file)
index 0000000..bfbadee
--- /dev/null
@@ -0,0 +1,77 @@
+From 93bb11dd19bdcc1fc97c7ceababd0db9fde128ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:34 -0400
+Subject: [PATCH 27/42] thermal/drivers/mediatek/lvts_thermal: Use offset
+ threshold for IRQ
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There are two kinds of temperature monitoring interrupts available:
+* High Offset, Low Offset
+* Hot, Hot to normal, Cold
+
+The code currently uses the hot/h2n/cold interrupts, however in a way
+that doesn't work: the cold threshold is left uninitialized, which
+prevents the other thresholds from ever triggering, and the h2n
+interrupt is used as the lower threshold, which prevents the hot
+interrupt from triggering again after the thresholds are updated by the
+thermal framework, since a hot interrupt can only trigger again after
+the hot to normal interrupt has been triggered.
+
+But better yet than addressing those issues, is to use the high/low
+offset interrupts instead. This way only two thresholds need to be
+managed, which have a simpler state machine, making them a better match
+to the thermal framework's high and low thresholds.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-4-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -298,9 +298,9 @@ static int lvts_set_trips(struct thermal
+       u32 raw_high = lvts_temp_to_raw(high);
+       /*
+-       * Hot to normal temperature threshold
++       * Low offset temperature threshold
+        *
+-       * LVTS_H2NTHRE
++       * LVTS_OFFSETL
+        *
+        * Bits:
+        *
+@@ -309,13 +309,13 @@ static int lvts_set_trips(struct thermal
+       if (low != -INT_MAX) {
+               pr_debug("%s: Setting low limit temperature interrupt: %d\n",
+                        thermal_zone_device_type(tz), low);
+-              writel(raw_low, LVTS_H2NTHRE(base));
++              writel(raw_low, LVTS_OFFSETL(base));
+       }
+       /*
+-       * Hot temperature threshold
++       * High offset temperature threshold
+        *
+-       * LVTS_HTHRE
++       * LVTS_OFFSETH
+        *
+        * Bits:
+        *
+@@ -323,7 +323,7 @@ static int lvts_set_trips(struct thermal
+        */
+       pr_debug("%s: Setting high limit temperature interrupt: %d\n",
+                thermal_zone_device_type(tz), high);
+-      writel(raw_high, LVTS_HTHRE(base));
++      writel(raw_high, LVTS_OFFSETH(base));
+       return 0;
+ }
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch b/target/linux/mediatek/patches-6.1/830-v6.4-32-thermal-drivers-mediatek-lvts_thermal-Disable-undesi.patch
new file mode 100644 (file)
index 0000000..1c35d0a
--- /dev/null
@@ -0,0 +1,51 @@
+From 8f8cab9d3e90acf1db278ef44ad05f10aefb973f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:35 -0400
+Subject: [PATCH 28/42] thermal/drivers/mediatek/lvts_thermal: Disable
+ undesired interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Out of the many interrupts supported by the hardware, the only ones of
+interest to the driver currently are:
+* The temperature went over the high offset threshold, for any of the
+  sensors
+* The temperature went below the low offset threshold, for any of the
+  sensors
+* The temperature went over the stage3 threshold
+
+These are the only thresholds configured by the driver through the
+OFFSETH, OFFSETL, and PROTTC registers, respectively.
+
+The current interrupt mask in LVTS_MONINT_CONF, enables many more
+interrupts, including data ready on sensors for both filtered and
+immediate mode. These are not only not handled by the driver, but they
+are also triggered too often, causing unneeded overhead. Disable these
+unnecessary interrupts.
+
+The meaning of each bit can be seen in the comment describing
+LVTS_MONINTST in the IRQ handler.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-5-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -65,7 +65,7 @@
+ #define LVTS_HW_FILTER                                0x2
+ #define LVTS_TSSEL_CONF                               0x13121110
+ #define LVTS_CALSCALE_CONF                    0x300
+-#define LVTS_MONINT_CONF                      0x9FBF7BDE
++#define LVTS_MONINT_CONF                      0x8300318C
+ #define LVTS_INT_SENSOR0                      0x0009001F
+ #define LVTS_INT_SENSOR1                      0x001203E0
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch b/target/linux/mediatek/patches-6.1/830-v6.4-33-thermal-drivers-mediatek-lvts_thermal-Don-t-leave-th.patch
new file mode 100644 (file)
index 0000000..60942fd
--- /dev/null
@@ -0,0 +1,70 @@
+From bd1ccf9408e6155564530af5e09b53ae497fe332 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:36 -0400
+Subject: [PATCH 29/42] thermal/drivers/mediatek/lvts_thermal: Don't leave
+ threshold zeroed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The thermal framework might leave the low threshold unset if there
+aren't any lower trip points. This leaves the register zeroed, which
+translates to a very high temperature for the low threshold. The
+interrupt for this threshold is then immediately triggered, and the
+state machine gets stuck, preventing any other temperature monitoring
+interrupts to ever trigger.
+
+(The same happens by not setting the Cold or Hot to Normal thresholds
+when using those)
+
+Set the unused threshold to a valid low value. This value was chosen so
+that for any valid golden temperature read from the efuse, when the
+value is converted to raw and back again to milliCelsius, the result
+doesn't underflow.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-6-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -83,6 +83,8 @@
+ #define LVTS_HW_SHUTDOWN_MT8195               105000
++#define LVTS_MINIMUM_THRESHOLD                20000
++
+ static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
+ static int coeff_b = LVTS_COEFF_B;
+@@ -294,7 +296,7 @@ static int lvts_set_trips(struct thermal
+ {
+       struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+       void __iomem *base = lvts_sensor->base;
+-      u32 raw_low = lvts_temp_to_raw(low);
++      u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
+       u32 raw_high = lvts_temp_to_raw(high);
+       /*
+@@ -306,11 +308,9 @@ static int lvts_set_trips(struct thermal
+        *
+        * 14-0 : Raw temperature for threshold
+        */
+-      if (low != -INT_MAX) {
+-              pr_debug("%s: Setting low limit temperature interrupt: %d\n",
+-                       thermal_zone_device_type(tz), low);
+-              writel(raw_low, LVTS_OFFSETL(base));
+-      }
++      pr_debug("%s: Setting low limit temperature interrupt: %d\n",
++               thermal_zone_device_type(tz), low);
++      writel(raw_low, LVTS_OFFSETL(base));
+       /*
+        * High offset temperature threshold
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch b/target/linux/mediatek/patches-6.1/830-v6.4-34-thermal-drivers-mediatek-lvts_thermal-Manage-thresho.patch
new file mode 100644 (file)
index 0000000..e99aa0c
--- /dev/null
@@ -0,0 +1,156 @@
+From d4dd09968cab3249e6148e1c3fccb51824edb411 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 6 Jul 2023 11:37:37 -0400
+Subject: [PATCH 30/42] thermal/drivers/mediatek/lvts_thermal: Manage threshold
+ between sensors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Each LVTS thermal controller can have up to four sensors, each capable
+of triggering its own interrupt when its measured temperature crosses
+the configured threshold. The threshold for each sensor is handled
+separately by the thermal framework, since each one is registered with
+its own thermal zone and trips. However, the temperature thresholds are
+configured on the controller, and therefore are shared between all
+sensors on that controller.
+
+When the temperature measured by the sensors is different enough to
+cause the thermal framework to configure different thresholds for each
+one, interrupts start triggering on sensors outside the last threshold
+configured.
+
+To address the issue, track the thresholds required by each sensor and
+only actually set the highest one in the hardware, and disable
+interrupts for all sensors outside the current configured range.
+
+Fixes: f5f633b18234 ("thermal/drivers/mediatek: Add the Low Voltage Thermal Sensor driver")
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230706153823.201943-7-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 69 +++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -67,6 +67,11 @@
+ #define LVTS_CALSCALE_CONF                    0x300
+ #define LVTS_MONINT_CONF                      0x8300318C
++#define LVTS_MONINT_OFFSET_SENSOR0            0xC
++#define LVTS_MONINT_OFFSET_SENSOR1            0x180
++#define LVTS_MONINT_OFFSET_SENSOR2            0x3000
++#define LVTS_MONINT_OFFSET_SENSOR3            0x3000000
++
+ #define LVTS_INT_SENSOR0                      0x0009001F
+ #define LVTS_INT_SENSOR1                      0x001203E0
+ #define LVTS_INT_SENSOR2                      0x00247C00
+@@ -112,6 +117,8 @@ struct lvts_sensor {
+       void __iomem *base;
+       int id;
+       int dt_id;
++      int low_thresh;
++      int high_thresh;
+ };
+ struct lvts_ctrl {
+@@ -121,6 +128,8 @@ struct lvts_ctrl {
+       int num_lvts_sensor;
+       int mode;
+       void __iomem *base;
++      int low_thresh;
++      int high_thresh;
+ };
+ struct lvts_domain {
+@@ -292,12 +301,66 @@ static int lvts_get_temp(struct thermal_
+       return 0;
+ }
++static void lvts_update_irq_mask(struct lvts_ctrl *lvts_ctrl)
++{
++      u32 masks[] = {
++              LVTS_MONINT_OFFSET_SENSOR0,
++              LVTS_MONINT_OFFSET_SENSOR1,
++              LVTS_MONINT_OFFSET_SENSOR2,
++              LVTS_MONINT_OFFSET_SENSOR3,
++      };
++      u32 value = 0;
++      int i;
++
++      value = readl(LVTS_MONINT(lvts_ctrl->base));
++
++      for (i = 0; i < ARRAY_SIZE(masks); i++) {
++              if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
++                  && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
++                      value |= masks[i];
++              else
++                      value &= ~masks[i];
++      }
++
++      writel(value, LVTS_MONINT(lvts_ctrl->base));
++}
++
++static bool lvts_should_update_thresh(struct lvts_ctrl *lvts_ctrl, int high)
++{
++      int i;
++
++      if (high > lvts_ctrl->high_thresh)
++              return true;
++
++      for (i = 0; i < lvts_ctrl->num_lvts_sensor; i++)
++              if (lvts_ctrl->sensors[i].high_thresh == lvts_ctrl->high_thresh
++                  && lvts_ctrl->sensors[i].low_thresh == lvts_ctrl->low_thresh)
++                      return false;
++
++      return true;
++}
++
+ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
+ {
+       struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
++      struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
+       void __iomem *base = lvts_sensor->base;
+       u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
+       u32 raw_high = lvts_temp_to_raw(high);
++      bool should_update_thresh;
++
++      lvts_sensor->low_thresh = low;
++      lvts_sensor->high_thresh = high;
++
++      should_update_thresh = lvts_should_update_thresh(lvts_ctrl, high);
++      if (should_update_thresh) {
++              lvts_ctrl->high_thresh = high;
++              lvts_ctrl->low_thresh = low;
++      }
++      lvts_update_irq_mask(lvts_ctrl);
++
++      if (!should_update_thresh)
++              return 0;
+       /*
+        * Low offset temperature threshold
+@@ -521,6 +584,9 @@ static int lvts_sensor_init(struct devic
+                */
+               lvts_sensor[i].msr = lvts_ctrl_data->mode == LVTS_MSR_IMMEDIATE_MODE ?
+                       imm_regs[i] : msr_regs[i];
++
++              lvts_sensor[i].low_thresh = INT_MIN;
++              lvts_sensor[i].high_thresh = INT_MIN;
+       };
+       lvts_ctrl->num_lvts_sensor = lvts_ctrl_data->num_lvts_sensor;
+@@ -688,6 +754,9 @@ static int lvts_ctrl_init(struct device
+                */
+               lvts_ctrl[i].hw_tshut_raw_temp =
+                       lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
++
++              lvts_ctrl[i].low_thresh = INT_MIN;
++              lvts_ctrl[i].high_thresh = INT_MIN;
+       }
+       /*
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch b/target/linux/mediatek/patches-6.1/830-v6.4-35-thermal-drivers-mediatek-lvts-Fix-parameter-check-in.patch
new file mode 100644 (file)
index 0000000..9ce3eeb
--- /dev/null
@@ -0,0 +1,29 @@
+From 5af4904adc8b840987000724977c13c706d3b7d8 Mon Sep 17 00:00:00 2001
+From: Minjie Du <duminjie@vivo.com>
+Date: Thu, 13 Jul 2023 12:24:12 +0800
+Subject: [PATCH 31/42] thermal/drivers/mediatek/lvts: Fix parameter check in
+ lvts_debugfs_init()
+
+The documentation says "If an error occurs, ERR_PTR(-ERROR) will be
+returned" but the current code checks against a NULL pointer returned.
+
+Fix this by checking if IS_ERR().
+
+Signed-off-by: Minjie Du <duminjie@vivo.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230713042413.2519-1-duminjie@vivo.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -201,7 +201,7 @@ static int lvts_debugfs_init(struct devi
+       int i;
+       lvts_td->dom_dentry = debugfs_create_dir(dev_name(dev), NULL);
+-      if (!lvts_td->dom_dentry)
++      if (IS_ERR(lvts_td->dom_dentry))
+               return 0;
+       for (i = 0; i < lvts_td->num_lvts_ctrl; i++) {
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch b/target/linux/mediatek/patches-6.1/830-v6.4-36-thermal-drivers-mediatek-Clean-up-redundant-dev_err_.patch
new file mode 100644 (file)
index 0000000..4841054
--- /dev/null
@@ -0,0 +1,33 @@
+From 6186be80317d1dbda34d35c06c084a083938f2d3 Mon Sep 17 00:00:00 2001
+From: Chen Jiahao <chenjiahao16@huawei.com>
+Date: Wed, 2 Aug 2023 17:45:27 +0800
+Subject: [PATCH 32/42] thermal/drivers/mediatek: Clean up redundant
+ dev_err_probe()
+
+Referring to platform_get_irq()'s definition, the return value has
+already been checked if ret < 0, and printed via dev_err_probe().
+Calling dev_err_probe() one more time outside platform_get_irq()
+is obviously redundant.
+
+Removing dev_err_probe() outside platform_get_irq() to clean up
+above problem.
+
+Signed-off-by: Chen Jiahao <chenjiahao16@huawei.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230802094527.988842-1-chenjiahao16@huawei.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -1216,7 +1216,7 @@ static int lvts_probe(struct platform_de
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+-              return dev_err_probe(dev, irq, "No irq resource\n");
++              return irq;
+       ret = lvts_domain_init(dev, lvts_td, lvts_data);
+       if (ret)
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch b/target/linux/mediatek/patches-6.1/830-v6.4-37-thermal-drivers-mediatek-lvts_thermal-Make-readings-.patch
new file mode 100644 (file)
index 0000000..c88bf98
--- /dev/null
@@ -0,0 +1,95 @@
+From c2ab54ab0425388e65901a7af2fbf69ead968708 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?=
+ <nfraprado@collabora.com>
+Date: Thu, 13 Jul 2023 11:42:37 -0400
+Subject: [PATCH 33/42] thermal/drivers/mediatek/lvts_thermal: Make readings
+ valid in filtered mode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently, when a controller is configured to use filtered mode, thermal
+readings are valid only about 30% of the time.
+
+Upon testing, it was noticed that lowering any of the interval settings
+resulted in an improved rate of valid data. The same was observed when
+decreasing the number of samples for each sensor (which also results in
+quicker measurements).
+
+Retrying the read with a timeout longer than the time it takes to
+resample (about 344us with these settings and 4 sensors) also improves
+the rate.
+
+Lower all timing settings to the minimum, configure the filtering to
+single sample, and poll the measurement register for at least one period
+to improve the data validity on filtered mode.  With these changes in
+place, out of 100000 reads, a single one failed, ie 99.999% of the data
+was valid.
+
+Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230713154743.611870-1-nfraprado@collabora.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -58,11 +58,11 @@
+ #define LVTS_PROTTC(__base)           (__base + 0x00CC)
+ #define LVTS_CLKEN(__base)            (__base + 0x00E4)
+-#define LVTS_PERIOD_UNIT                      ((118 * 1000) / (256 * 38))
+-#define LVTS_GROUP_INTERVAL                   1
+-#define LVTS_FILTER_INTERVAL          1
+-#define LVTS_SENSOR_INTERVAL          1
+-#define LVTS_HW_FILTER                                0x2
++#define LVTS_PERIOD_UNIT                      0
++#define LVTS_GROUP_INTERVAL                   0
++#define LVTS_FILTER_INTERVAL          0
++#define LVTS_SENSOR_INTERVAL          0
++#define LVTS_HW_FILTER                                0x0
+ #define LVTS_TSSEL_CONF                               0x13121110
+ #define LVTS_CALSCALE_CONF                    0x300
+ #define LVTS_MONINT_CONF                      0x8300318C
+@@ -86,6 +86,9 @@
+ #define LVTS_MSR_IMMEDIATE_MODE               0
+ #define LVTS_MSR_FILTERED_MODE                1
++#define LVTS_MSR_READ_TIMEOUT_US      400
++#define LVTS_MSR_READ_WAIT_US         (LVTS_MSR_READ_TIMEOUT_US / 2)
++
+ #define LVTS_HW_SHUTDOWN_MT8195               105000
+ #define LVTS_MINIMUM_THRESHOLD                20000
+@@ -268,6 +271,7 @@ static int lvts_get_temp(struct thermal_
+       struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+       void __iomem *msr = lvts_sensor->msr;
+       u32 value;
++      int rc;
+       /*
+        * Measurement registers:
+@@ -280,7 +284,8 @@ static int lvts_get_temp(struct thermal_
+        * 16   : Valid temperature
+        * 15-0 : Raw temperature
+        */
+-      value = readl(msr);
++      rc = readl_poll_timeout(msr, value, value & BIT(16),
++                              LVTS_MSR_READ_WAIT_US, LVTS_MSR_READ_TIMEOUT_US);
+       /*
+        * As the thermal zone temperature will read before the
+@@ -293,7 +298,7 @@ static int lvts_get_temp(struct thermal_
+        * functionning temperature and directly jump to a system
+        * shutdown.
+        */
+-      if (!(value & BIT(16)))
++      if (rc)
+               return -EAGAIN;
+       *temp = lvts_raw_to_temp(value & 0xFFFF);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch b/target/linux/mediatek/patches-6.1/830-v6.4-38-thermal-drivers-mediatek-auxadc_thermal-Removed-call.patch
new file mode 100644 (file)
index 0000000..994461c
--- /dev/null
@@ -0,0 +1,30 @@
+From c864ff9de3b225b43bb8e08dedb223632323e059 Mon Sep 17 00:00:00 2001
+From: Andrei Coardos <aboutphysycs@gmail.com>
+Date: Fri, 11 Aug 2023 22:28:47 +0300
+Subject: [PATCH 34/42] thermal/drivers/mediatek/auxadc_thermal: Removed call
+ to platform_set_drvdata()
+
+This function call was found to be unnecessary as there is no equivalent
+platform_get_drvdata() call to access the private data of the driver. Also,
+the private data is defined in this driver, so there is no risk of it being
+accessed outside of this driver file.
+
+Signed-off-by: Andrei Coardos <aboutphysycs@gmail.com>
+Reviewed-by: Alexandru Ardelean <alex@shruggie.ro>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230811192847.3838-1-aboutphysycs@gmail.com
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1283,8 +1283,6 @@ static int mtk_thermal_probe(struct plat
+                       mtk_thermal_init_bank(mt, i, apmixed_phys_base,
+                                             auxadc_phys_base, ctrl_id);
+-      platform_set_drvdata(pdev, mt);
+-
+       tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
+                                             &mtk_thermal_ops);
+       if (IS_ERR(tzdev))
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch b/target/linux/mediatek/patches-6.1/830-v6.4-39-thermal-lvts-Convert-to-platform-remove-callback-ret.patch
new file mode 100644 (file)
index 0000000..b3bfa37
--- /dev/null
@@ -0,0 +1,58 @@
+From 6cf96078969ec00b873db99bae4e47001290685e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Wed, 27 Sep 2023 21:37:23 +0200
+Subject: [PATCH 35/42] thermal: lvts: Convert to platform remove callback
+ returning void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new(), which already returns void. Eventually after all drivers
+are converted, .remove_new() will be renamed to .remove().
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -1241,7 +1241,7 @@ static int lvts_probe(struct platform_de
+       return 0;
+ }
+-static int lvts_remove(struct platform_device *pdev)
++static void lvts_remove(struct platform_device *pdev)
+ {
+       struct lvts_domain *lvts_td;
+       int i;
+@@ -1252,8 +1252,6 @@ static int lvts_remove(struct platform_d
+               lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false);
+       lvts_debugfs_exit(lvts_td);
+-
+-      return 0;
+ }
+ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = {
+@@ -1354,7 +1352,7 @@ MODULE_DEVICE_TABLE(of, lvts_of_match);
+ static struct platform_driver lvts_driver = {
+       .probe = lvts_probe,
+-      .remove = lvts_remove,
++      .remove_new = lvts_remove,
+       .driver = {
+               .name = "mtk-lvts-thermal",
+               .of_match_table = lvts_of_match,
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch b/target/linux/mediatek/patches-6.1/830-v6.4-40-thermal-drivers-mediatek-lvts_thermal-Make-coeff-con.patch
new file mode 100644 (file)
index 0000000..16a32f5
--- /dev/null
@@ -0,0 +1,198 @@
+From 26cc18a3d6d9eac21c4f4b4bb96147b2c6617c86 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Fri, 22 Sep 2023 07:50:19 +0200
+Subject: [PATCH 36/42] thermal/drivers/mediatek/lvts_thermal: Make coeff
+ configurable
+
+The upcoming mt7988 has different temperature coefficients so we
+cannot use constants in the functions lvts_golden_temp_init,
+lvts_golden_temp_init and lvts_raw_to_temp anymore.
+
+Add a field in the lvts_ctrl pointing to the lvts_data which now
+contains the soc-specific temperature coefficents.
+
+To make the code better readable, rename static int coeff_b to
+golden_temp_offset, COEFF_A to temp_factor and COEFF_B to temp_offset.
+
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230922055020.6436-4-linux@fw-web.de
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 51 ++++++++++++++++---------
+ 1 file changed, 34 insertions(+), 17 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -80,8 +80,8 @@
+ #define LVTS_SENSOR_MAX                               4
+ #define LVTS_GOLDEN_TEMP_MAX          62
+ #define LVTS_GOLDEN_TEMP_DEFAULT      50
+-#define LVTS_COEFF_A                          -250460
+-#define LVTS_COEFF_B                          250460
++#define LVTS_COEFF_A_MT8195                   -250460
++#define LVTS_COEFF_B_MT8195                   250460
+ #define LVTS_MSR_IMMEDIATE_MODE               0
+ #define LVTS_MSR_FILTERED_MODE                1
+@@ -94,7 +94,7 @@
+ #define LVTS_MINIMUM_THRESHOLD                20000
+ static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT;
+-static int coeff_b = LVTS_COEFF_B;
++static int golden_temp_offset;
+ struct lvts_sensor_data {
+       int dt_id;
+@@ -112,6 +112,8 @@ struct lvts_ctrl_data {
+ struct lvts_data {
+       const struct lvts_ctrl_data *lvts_ctrl;
+       int num_lvts_ctrl;
++      int temp_factor;
++      int temp_offset;
+ };
+ struct lvts_sensor {
+@@ -126,6 +128,7 @@ struct lvts_sensor {
+ struct lvts_ctrl {
+       struct lvts_sensor sensors[LVTS_SENSOR_MAX];
++      const struct lvts_data *lvts_data;
+       u32 calibration[LVTS_SENSOR_MAX];
+       u32 hw_tshut_raw_temp;
+       int num_lvts_sensor;
+@@ -247,21 +250,21 @@ static void lvts_debugfs_exit(struct lvt
+ #endif
+-static int lvts_raw_to_temp(u32 raw_temp)
++static int lvts_raw_to_temp(u32 raw_temp, int temp_factor)
+ {
+       int temperature;
+-      temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14;
+-      temperature += coeff_b;
++      temperature = ((s64)(raw_temp & 0xFFFF) * temp_factor) >> 14;
++      temperature += golden_temp_offset;
+       return temperature;
+ }
+-static u32 lvts_temp_to_raw(int temperature)
++static u32 lvts_temp_to_raw(int temperature, int temp_factor)
+ {
+-      u32 raw_temp = ((s64)(coeff_b - temperature)) << 14;
++      u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14;
+-      raw_temp = div_s64(raw_temp, -LVTS_COEFF_A);
++      raw_temp = div_s64(raw_temp, -temp_factor);
+       return raw_temp;
+ }
+@@ -269,6 +272,9 @@ static u32 lvts_temp_to_raw(int temperat
+ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
++      struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl,
++                                                 sensors[lvts_sensor->id]);
++      const struct lvts_data *lvts_data = lvts_ctrl->lvts_data;
+       void __iomem *msr = lvts_sensor->msr;
+       u32 value;
+       int rc;
+@@ -301,7 +307,7 @@ static int lvts_get_temp(struct thermal_
+       if (rc)
+               return -EAGAIN;
+-      *temp = lvts_raw_to_temp(value & 0xFFFF);
++      *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor);
+       return 0;
+ }
+@@ -348,10 +354,13 @@ static bool lvts_should_update_thresh(st
+ static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
+ {
+       struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz);
+-      struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]);
++      struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl,
++                                                 sensors[lvts_sensor->id]);
++      const struct lvts_data *lvts_data = lvts_ctrl->lvts_data;
+       void __iomem *base = lvts_sensor->base;
+-      u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD);
+-      u32 raw_high = lvts_temp_to_raw(high);
++      u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD,
++                                     lvts_data->temp_factor);
++      u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor);
+       bool should_update_thresh;
+       lvts_sensor->low_thresh = low;
+@@ -692,7 +701,7 @@ static int lvts_calibration_read(struct
+       return 0;
+ }
+-static int lvts_golden_temp_init(struct device *dev, u32 *value)
++static int lvts_golden_temp_init(struct device *dev, u32 *value, int temp_offset)
+ {
+       u32 gt;
+@@ -701,7 +710,7 @@ static int lvts_golden_temp_init(struct
+       if (gt && gt < LVTS_GOLDEN_TEMP_MAX)
+               golden_temp = gt;
+-      coeff_b = golden_temp * 500 + LVTS_COEFF_B;
++      golden_temp_offset = golden_temp * 500 + temp_offset;
+       return 0;
+ }
+@@ -724,7 +733,7 @@ static int lvts_ctrl_init(struct device
+        * The golden temp information is contained in the first chunk
+        * of efuse data.
+        */
+-      ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib);
++      ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib, lvts_data->temp_offset);
+       if (ret)
+               return ret;
+@@ -735,6 +744,7 @@ static int lvts_ctrl_init(struct device
+       for (i = 0; i < lvts_data->num_lvts_ctrl; i++) {
+               lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset;
++              lvts_ctrl[i].lvts_data = lvts_data;
+               ret = lvts_sensor_init(dev, &lvts_ctrl[i],
+                                      &lvts_data->lvts_ctrl[i]);
+@@ -758,7 +768,8 @@ static int lvts_ctrl_init(struct device
+                * after initializing the calibration.
+                */
+               lvts_ctrl[i].hw_tshut_raw_temp =
+-                      lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp);
++                      lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp,
++                                       lvts_data->temp_factor);
+               lvts_ctrl[i].low_thresh = INT_MIN;
+               lvts_ctrl[i].high_thresh = INT_MIN;
+@@ -1223,6 +1234,8 @@ static int lvts_probe(struct platform_de
+       if (irq < 0)
+               return irq;
++      golden_temp_offset = lvts_data->temp_offset;
++
+       ret = lvts_domain_init(dev, lvts_td, lvts_data);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n");
+@@ -1336,11 +1349,15 @@ static const struct lvts_ctrl_data mt819
+ static const struct lvts_data mt8195_lvts_mcu_data = {
+       .lvts_ctrl      = mt8195_lvts_mcu_data_ctrl,
+       .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl),
++      .temp_factor    = LVTS_COEFF_A_MT8195,
++      .temp_offset    = LVTS_COEFF_B_MT8195,
+ };
+ static const struct lvts_data mt8195_lvts_ap_data = {
+       .lvts_ctrl      = mt8195_lvts_ap_data_ctrl,
+       .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl),
++      .temp_factor    = LVTS_COEFF_A_MT8195,
++      .temp_offset    = LVTS_COEFF_B_MT8195,
+ };
+ static const struct of_device_id lvts_of_match[] = {
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch b/target/linux/mediatek/patches-6.1/830-v6.4-41-dt-bindings-thermal-mediatek-Add-LVTS-thermal-sensor.patch
new file mode 100644 (file)
index 0000000..1c2146f
--- /dev/null
@@ -0,0 +1,35 @@
+From be2cc09bd5b46f13629d4fcdeac7ad1b18bb1a0b Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Fri, 22 Sep 2023 07:50:18 +0200
+Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal sensors for
+ mt7988
+
+Add sensor constants for MT7988.
+
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230922055020.6436-3-linux@fw-web.de
+---
+ include/dt-bindings/thermal/mediatek,lvts-thermal.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h
++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h
+@@ -7,6 +7,15 @@
+ #ifndef __MEDIATEK_LVTS_DT_H
+ #define __MEDIATEK_LVTS_DT_H
++#define MT7988_CPU_0          0
++#define MT7988_CPU_1          1
++#define MT7988_ETH2P5G_0      2
++#define MT7988_ETH2P5G_1      3
++#define MT7988_TOPS_0         4
++#define MT7988_TOPS_1         5
++#define MT7988_ETHWARP_0      6
++#define MT7988_ETHWARP_1      7
++
+ #define MT8195_MCU_BIG_CPU0     0
+ #define MT8195_MCU_BIG_CPU1     1
+ #define MT8195_MCU_BIG_CPU2     2
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch b/target/linux/mediatek/patches-6.1/830-v6.4-42-thermal-drivers-mediatek-lvts_thermal-Add-mt7988-sup.patch
new file mode 100644 (file)
index 0000000..97c803a
--- /dev/null
@@ -0,0 +1,91 @@
+From 9924e9b91b43aaa1610a1d59c4caa43785948cf6 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w@public-files.de>
+Date: Fri, 22 Sep 2023 07:50:20 +0200
+Subject: [PATCH 37/42] thermal/drivers/mediatek/lvts_thermal: Add mt7988
+ support
+
+Add Support for Mediatek Filogic 880/MT7988 LVTS.
+
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230922055020.6436-5-linux@fw-web.de
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 38 +++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -82,6 +82,8 @@
+ #define LVTS_GOLDEN_TEMP_DEFAULT      50
+ #define LVTS_COEFF_A_MT8195                   -250460
+ #define LVTS_COEFF_B_MT8195                   250460
++#define LVTS_COEFF_A_MT7988                   -204650
++#define LVTS_COEFF_B_MT7988                   204650
+ #define LVTS_MSR_IMMEDIATE_MODE               0
+ #define LVTS_MSR_FILTERED_MODE                1
+@@ -89,6 +91,7 @@
+ #define LVTS_MSR_READ_TIMEOUT_US      400
+ #define LVTS_MSR_READ_WAIT_US         (LVTS_MSR_READ_TIMEOUT_US / 2)
++#define LVTS_HW_SHUTDOWN_MT7988               105000
+ #define LVTS_HW_SHUTDOWN_MT8195               105000
+ #define LVTS_MINIMUM_THRESHOLD                20000
+@@ -1267,6 +1270,33 @@ static void lvts_remove(struct platform_
+       lvts_debugfs_exit(lvts_td);
+ }
++static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = {
++      {
++              .cal_offset = { 0x00, 0x04, 0x08, 0x0c },
++              .lvts_sensor = {
++                      { .dt_id = MT7988_CPU_0 },
++                      { .dt_id = MT7988_CPU_1 },
++                      { .dt_id = MT7988_ETH2P5G_0 },
++                      { .dt_id = MT7988_ETH2P5G_1 }
++              },
++              .num_lvts_sensor = 4,
++              .offset = 0x0,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988,
++      },
++      {
++              .cal_offset = { 0x14, 0x18, 0x1c, 0x20 },
++              .lvts_sensor = {
++                      { .dt_id = MT7988_TOPS_0},
++                      { .dt_id = MT7988_TOPS_1},
++                      { .dt_id = MT7988_ETHWARP_0},
++                      { .dt_id = MT7988_ETHWARP_1}
++              },
++              .num_lvts_sensor = 4,
++              .offset = 0x100,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988,
++      }
++};
++
+ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = {
+       {
+               .cal_offset = { 0x04, 0x07 },
+@@ -1346,6 +1376,13 @@ static const struct lvts_ctrl_data mt819
+       }
+ };
++static const struct lvts_data mt7988_lvts_ap_data = {
++      .lvts_ctrl      = mt7988_lvts_ap_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt7988_lvts_ap_data_ctrl),
++      .temp_factor    = LVTS_COEFF_A_MT7988,
++      .temp_offset    = LVTS_COEFF_B_MT7988,
++};
++
+ static const struct lvts_data mt8195_lvts_mcu_data = {
+       .lvts_ctrl      = mt8195_lvts_mcu_data_ctrl,
+       .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl),
+@@ -1361,6 +1398,7 @@ static const struct lvts_data mt8195_lvt
+ };
+ static const struct of_device_id lvts_of_match[] = {
++      { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data },
+       { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data },
+       { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data },
+       {},
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch b/target/linux/mediatek/patches-6.1/830-v6.4-43-thermal-drivers-mediatek-lvts_thermal-Fix-error-chec.patch
new file mode 100644 (file)
index 0000000..5b212a2
--- /dev/null
@@ -0,0 +1,30 @@
+From fb1bbb5b63e4e3c788a978724749ced57d208054 Mon Sep 17 00:00:00 2001
+From: Minjie Du <duminjie@vivo.com>
+Date: Thu, 21 Sep 2023 17:10:50 +0800
+Subject: [PATCH 38/42] thermal/drivers/mediatek/lvts_thermal: Fix error check
+ in lvts_debugfs_init()
+
+debugfs_create_dir() function returns an error value embedded in
+the pointer (PTR_ERR). Evaluate the return value using IS_ERR
+rather than checking for NULL.
+
+Signed-off-by: Minjie Du <duminjie@vivo.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230921091057.3812-1-duminjie@vivo.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -219,7 +219,7 @@ static int lvts_debugfs_init(struct devi
+               sprintf(name, "controller%d", i);
+               dentry = debugfs_create_dir(name, lvts_td->dom_dentry);
+-              if (!dentry)
++              if (IS_ERR(dentry))
+                       continue;
+               regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch b/target/linux/mediatek/patches-6.1/830-v6.4-44-thermal-drivers-mediatek-Fix-probe-for-THERMAL_V2.patch
new file mode 100644 (file)
index 0000000..88f383c
--- /dev/null
@@ -0,0 +1,33 @@
+From e6f43063f2fe9f08b34797bc6d223f7d63b01910 Mon Sep 17 00:00:00 2001
+From: Markus Schneider-Pargmann <msp@baylibre.com>
+Date: Mon, 18 Sep 2023 12:07:06 +0200
+Subject: [PATCH 39/42] thermal/drivers/mediatek: Fix probe for THERMAL_V2
+
+Fix the probe function to call mtk_thermal_release_periodic_ts for
+everything != MTK_THERMAL_V1. This was accidentally changed from V1
+to V2 in the original patch.
+
+Reported-by: Frank Wunderlich <frank-w@public-files.de>
+Closes: https://lore.kernel.org/lkml/B0B3775B-B8D1-4284-814F-4F41EC22F532@public-files.de/
+Reported-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Closes: https://lore.kernel.org/lkml/07a569b9-e691-64ea-dd65-3b49842af33d@linaro.org/
+Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks")
+Signed-off-by: Markus Schneider-Pargmann <msp@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20230918100706.1229239-1-msp@baylibre.com
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -1268,7 +1268,7 @@ static int mtk_thermal_probe(struct plat
+       mtk_thermal_turn_on_buffer(mt, apmixed_base);
+-      if (mt->conf->version != MTK_THERMAL_V2)
++      if (mt->conf->version != MTK_THERMAL_V1)
+               mtk_thermal_release_periodic_ts(mt, auxadc_base);
+       if (mt->conf->version == MTK_THERMAL_V1)
diff --git a/target/linux/mediatek/patches-6.1/830-v6.4-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch b/target/linux/mediatek/patches-6.1/830-v6.4-45-thermal-drivers-mediatek-lvts_thermal-Add-suspend-an.patch
new file mode 100644 (file)
index 0000000..7b4b124
--- /dev/null
@@ -0,0 +1,83 @@
+From a1d874ef3376295ee8ed89b3b5315f4c840ff00b Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 17 Oct 2023 21:05:42 +0200
+Subject: [PATCH 40/42] thermal/drivers/mediatek/lvts_thermal: Add suspend and
+ resume
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add suspend and resume support to LVTS driver.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+[bero@baylibre.com: suspend/resume in noirq phase]
+Co-developed-by: Bernhard Rosenkränzer <bero@baylibre.com>
+Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20231017190545.157282-3-bero@baylibre.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 37 +++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -1297,6 +1297,38 @@ static const struct lvts_ctrl_data mt798
+       }
+ };
++static int lvts_suspend(struct device *dev)
++{
++      struct lvts_domain *lvts_td;
++      int i;
++
++      lvts_td = dev_get_drvdata(dev);
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++)
++              lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false);
++
++      clk_disable_unprepare(lvts_td->clk);
++
++      return 0;
++}
++
++static int lvts_resume(struct device *dev)
++{
++      struct lvts_domain *lvts_td;
++      int i, ret;
++
++      lvts_td = dev_get_drvdata(dev);
++
++      ret = clk_prepare_enable(lvts_td->clk);
++      if (ret)
++              return ret;
++
++      for (i = 0; i < lvts_td->num_lvts_ctrl; i++)
++              lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true);
++
++      return 0;
++}
++
+ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = {
+       {
+               .cal_offset = { 0x04, 0x07 },
+@@ -1405,12 +1437,17 @@ static const struct of_device_id lvts_of
+ };
+ MODULE_DEVICE_TABLE(of, lvts_of_match);
++static const struct dev_pm_ops lvts_pm_ops = {
++      NOIRQ_SYSTEM_SLEEP_PM_OPS(lvts_suspend, lvts_resume)
++};
++
+ static struct platform_driver lvts_driver = {
+       .probe = lvts_probe,
+       .remove_new = lvts_remove,
+       .driver = {
+               .name = "mtk-lvts-thermal",
+               .of_match_table = lvts_of_match,
++              .pm = &lvts_pm_ops,
+       },
+ };
+ module_platform_driver(lvts_driver);
diff --git a/target/linux/mediatek/patches-6.1/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch b/target/linux/mediatek/patches-6.1/830-v6.7-46-dt-bindings-thermal-mediatek-Add-LVTS-thermal-contro.patch
new file mode 100644 (file)
index 0000000..c278168
--- /dev/null
@@ -0,0 +1,49 @@
+From 0bb4937b58ab712f158588376dbac97f8e9df68e Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 17 Oct 2023 21:05:41 +0200
+Subject: [PATCH] dt-bindings: thermal: mediatek: Add LVTS thermal controller
+ definition for mt8192
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add LVTS thermal controller definition for MT8192.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20231017190545.157282-2-bero@baylibre.com
+---
+ .../thermal/mediatek,lvts-thermal.h           | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+--- a/include/dt-bindings/thermal/mediatek,lvts-thermal.h
++++ b/include/dt-bindings/thermal/mediatek,lvts-thermal.h
+@@ -35,4 +35,23 @@
+ #define MT8195_AP_CAM0  15
+ #define MT8195_AP_CAM1  16
++#define MT8192_MCU_BIG_CPU0     0
++#define MT8192_MCU_BIG_CPU1     1
++#define MT8192_MCU_BIG_CPU2     2
++#define MT8192_MCU_BIG_CPU3     3
++#define MT8192_MCU_LITTLE_CPU0  4
++#define MT8192_MCU_LITTLE_CPU1  5
++#define MT8192_MCU_LITTLE_CPU2  6
++#define MT8192_MCU_LITTLE_CPU3  7
++
++#define MT8192_AP_VPU0  8
++#define MT8192_AP_VPU1  9
++#define MT8192_AP_GPU0  10
++#define MT8192_AP_GPU1  11
++#define MT8192_AP_INFRA 12
++#define MT8192_AP_CAM   13
++#define MT8192_AP_MD0   14
++#define MT8192_AP_MD1   15
++#define MT8192_AP_MD2   16
++
+ #endif /* __MEDIATEK_LVTS_DT_H */
diff --git a/target/linux/mediatek/patches-6.1/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch b/target/linux/mediatek/patches-6.1/830-v6.7-47-thermal-drivers-mediatek-lvts_thermal-Add-mt8192-sup.patch
new file mode 100644 (file)
index 0000000..6d68a6c
--- /dev/null
@@ -0,0 +1,151 @@
+From 7d8b3864b38d881cf105328ff8569f47446811ad Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 17 Oct 2023 21:05:43 +0200
+Subject: [PATCH 41/42] thermal/drivers/mediatek/lvts_thermal: Add mt8192
+ support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add LVTS Driver support for MT8192.
+
+Co-developed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+[bero@baylibre.com: cosmetic changes, rebase]
+Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
+Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20231017190545.157282-4-bero@baylibre.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 95 +++++++++++++++++++++++++
+ 1 file changed, 95 insertions(+)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -92,6 +92,7 @@
+ #define LVTS_MSR_READ_WAIT_US         (LVTS_MSR_READ_TIMEOUT_US / 2)
+ #define LVTS_HW_SHUTDOWN_MT7988               105000
++#define LVTS_HW_SHUTDOWN_MT8192               105000
+ #define LVTS_HW_SHUTDOWN_MT8195               105000
+ #define LVTS_MINIMUM_THRESHOLD                20000
+@@ -1329,6 +1330,88 @@ static int lvts_resume(struct device *de
+       return 0;
+ }
++static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = {
++      {
++              .cal_offset = { 0x04, 0x08 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_MCU_BIG_CPU0 },
++                      { .dt_id = MT8192_MCU_BIG_CPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x0,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++              .mode = LVTS_MSR_FILTERED_MODE,
++      },
++      {
++              .cal_offset = { 0x0c, 0x10 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_MCU_BIG_CPU2 },
++                      { .dt_id = MT8192_MCU_BIG_CPU3 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x100,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++              .mode = LVTS_MSR_FILTERED_MODE,
++      },
++      {
++              .cal_offset = { 0x14, 0x18, 0x1c, 0x20 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_MCU_LITTLE_CPU0 },
++                      { .dt_id = MT8192_MCU_LITTLE_CPU1 },
++                      { .dt_id = MT8192_MCU_LITTLE_CPU2 },
++                      { .dt_id = MT8192_MCU_LITTLE_CPU3 }
++              },
++              .num_lvts_sensor = 4,
++              .offset = 0x200,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++              .mode = LVTS_MSR_FILTERED_MODE,
++      }
++};
++
++static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = {
++              {
++              .cal_offset = { 0x24, 0x28 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_AP_VPU0 },
++                      { .dt_id = MT8192_AP_VPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x0,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++      },
++      {
++              .cal_offset = { 0x2c, 0x30 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_AP_GPU0 },
++                      { .dt_id = MT8192_AP_GPU1 }
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x100,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++      },
++      {
++              .cal_offset = { 0x34, 0x38 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_AP_INFRA },
++                      { .dt_id = MT8192_AP_CAM },
++              },
++              .num_lvts_sensor = 2,
++              .offset = 0x200,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++      },
++      {
++              .cal_offset = { 0x3c, 0x40, 0x44 },
++              .lvts_sensor = {
++                      { .dt_id = MT8192_AP_MD0 },
++                      { .dt_id = MT8192_AP_MD1 },
++                      { .dt_id = MT8192_AP_MD2 }
++              },
++              .num_lvts_sensor = 3,
++              .offset = 0x300,
++              .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192,
++      }
++};
++
+ static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = {
+       {
+               .cal_offset = { 0x04, 0x07 },
+@@ -1415,6 +1498,16 @@ static const struct lvts_data mt7988_lvt
+       .temp_offset    = LVTS_COEFF_B_MT7988,
+ };
++static const struct lvts_data mt8192_lvts_mcu_data = {
++      .lvts_ctrl      = mt8192_lvts_mcu_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl),
++};
++
++static const struct lvts_data mt8192_lvts_ap_data = {
++      .lvts_ctrl      = mt8192_lvts_ap_data_ctrl,
++      .num_lvts_ctrl  = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl),
++};
++
+ static const struct lvts_data mt8195_lvts_mcu_data = {
+       .lvts_ctrl      = mt8195_lvts_mcu_data_ctrl,
+       .num_lvts_ctrl  = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl),
+@@ -1431,6 +1524,8 @@ static const struct lvts_data mt8195_lvt
+ static const struct of_device_id lvts_of_match[] = {
+       { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data },
++      { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data },
++      { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data },
+       { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data },
+       { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data },
+       {},
diff --git a/target/linux/mediatek/patches-6.1/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch b/target/linux/mediatek/patches-6.1/830-v6.7-48-thermal-drivers-mediatek-lvts_thermal-Update-calibra.patch
new file mode 100644 (file)
index 0000000..c20c0b5
--- /dev/null
@@ -0,0 +1,70 @@
+From 5d126a3c87cf7964b28bacf3826eea4266265bce Mon Sep 17 00:00:00 2001
+From: Balsam CHIHI <bchihi@baylibre.com>
+Date: Tue, 17 Oct 2023 21:05:45 +0200
+Subject: [PATCH 42/42] thermal/drivers/mediatek/lvts_thermal: Update
+ calibration data documentation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Update LVTS calibration data documentation for mt8192 and mt8195.
+
+Signed-off-by: Balsam CHIHI <bchihi@baylibre.com>
+Reviewed-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
+[bero@baylibre.com: Fix issues pointed out by Nícolas F. R. A. Prado <nfraprado@collabora.com>]
+Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Link: https://lore.kernel.org/r/20231017190545.157282-6-bero@baylibre.com
+---
+ drivers/thermal/mediatek/lvts_thermal.c | 31 +++++++++++++++++++++++--
+ 1 file changed, 29 insertions(+), 2 deletions(-)
+
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -616,7 +616,34 @@ static int lvts_sensor_init(struct devic
+  * The efuse blob values follows the sensor enumeration per thermal
+  * controller. The decoding of the stream is as follow:
+  *
+- * stream index map for MCU Domain :
++ * MT8192 :
++ * Stream index map for MCU Domain mt8192 :
++ *
++ * <-----mcu-tc#0-----> <-----sensor#0----->        <-----sensor#1----->
++ *  0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B
++ *
++ * <-----sensor#2----->        <-----sensor#3----->
++ *  0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13
++ *
++ * <-----sensor#4----->        <-----sensor#5----->        <-----sensor#6----->        <-----sensor#7----->
++ *  0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23
++ *
++ * Stream index map for AP Domain mt8192 :
++ *
++ * <-----sensor#0----->        <-----sensor#1----->
++ *  0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B
++ *
++ * <-----sensor#2----->        <-----sensor#3----->
++ *  0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33
++ *
++ * <-----sensor#4----->        <-----sensor#5----->
++ *  0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B
++ *
++ * <-----sensor#6----->        <-----sensor#7----->        <-----sensor#8----->
++ *  0x3C | 0x3D | 0x3E | 0x3F | 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47
++ *
++ * MT8195 :
++ * Stream index map for MCU Domain mt8195 :
+  *
+  * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1----->
+  *  0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09
+@@ -627,7 +654,7 @@ static int lvts_sensor_init(struct devic
+  * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7----->
+  *  0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21
+  *
+- * stream index map for AP Domain :
++ * Stream index map for AP Domain mt8195 :
+  *
+  * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1----->
+  *  0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A
diff --git a/target/linux/mediatek/patches-6.1/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch b/target/linux/mediatek/patches-6.1/831-thermal-drivers-mediatek-Fix-control-buffer-enablement-on-MT7896.patch
new file mode 100644 (file)
index 0000000..fc17364
--- /dev/null
@@ -0,0 +1,59 @@
+From patchwork Thu Sep  7 11:20:18 2023
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Frank Wunderlich <linux@fw-web.de>
+X-Patchwork-Id: 13376356
+From: Frank Wunderlich <linux@fw-web.de>
+To: linux-mediatek@lists.infradead.org
+Subject: [PATCH] thermal/drivers/mediatek: Fix control buffer enablement on
+ MT7896
+Date: Thu,  7 Sep 2023 13:20:18 +0200
+Message-Id: <20230907112018.52811-1-linux@fw-web.de>
+X-Mailer: git-send-email 2.34.1
+MIME-Version: 1.0
+X-Mail-ID: e7eeb8e1-00de-41f6-a5df-ce2e9164136e
+X-BeenThere: linux-mediatek@lists.infradead.org
+X-Mailman-Version: 2.1.34
+Precedence: list
+List-Id: <linux-mediatek.lists.infradead.org>
+Cc: Daniel Lezcano <daniel.lezcano@linaro.org>,
+ "Rafael J. Wysocki" <rafael@kernel.org>, linux-pm@vger.kernel.org,
+ Amit Kucheria <amitk@kernel.org>, Daniel Golle <daniel@makrotopia.org>,
+ stable@vger.kernel.org, linux-kernel@vger.kernel.org,
+ Matthias Brugger <matthias.bgg@gmail.com>, Zhang Rui <rui.zhang@intel.com>,
+ linux-arm-kernel@lists.infradead.org,
+ AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Sender: "Linux-mediatek" <linux-mediatek-bounces@lists.infradead.org>
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+Reading thermal sensor on mt7986 devices returns invalid temperature:
+
+bpi-r3 ~ # cat /sys/class/thermal/thermal_zone0/temp
+ -274000
+
+Fix this by adding missing members in mtk_thermal_data struct which were
+used in mtk_thermal_turn_on_buffer after commit 33140e668b10.
+
+Cc: stable@vger.kernel.org
+Fixes: 33140e668b10 ("thermal/drivers/mediatek: Control buffer enablement tweaks")
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Markus Schneider-Pargmann <msp@baylibre.com>
+---
+ drivers/thermal/mediatek/auxadc_thermal.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -691,6 +691,9 @@ static const struct mtk_thermal_data mt7
+       .adcpnp = mt7986_adcpnp,
+       .sensor_mux_values = mt7986_mux_values,
+       .version = MTK_THERMAL_V3,
++      .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1,
++      .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3),
++      .apmixed_buffer_ctl_set = BIT(0),
+ };
+ static bool mtk_thermal_temp_is_valid(int temp)