Merge tag 'thermal-v6.9-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git...
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 13 Mar 2024 19:35:48 +0000 (20:35 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 13 Mar 2024 19:35:48 +0000 (20:35 +0100)
Merge additional thermal control changes for 6.9-rc1 from Daniel Lezcano:

"- Fix memory leak in the error path at probe time in the Mediatek LVTS
   driver (Christophe Jaillet)

 - Fix control buffer enablement regression on Meditek MT7896 (Frank
   Wunderlich)

 - Drop spaces before TABs in different places: thermal-of, ST drivers
   and Makefile (Geert Uytterhoeven)

 - Adjust DT binding for NXP as fsl,tmu-range min/maxItems can vary
   among several SoC versions (Fabio Estevam)

 - Add support for H616 THS controller for the Sun8i platforms. Note
   that this change relies on another change in the SoC specific code
   which is included in this branch (Martin Botka)

 - Don't fail probe due to zone registration failure because there is
   no trip points defined in the DT (Mark Brown)

 - Support variable TMU array size for new platforms (Peng Fan)

 - Adjust the DT binding for thermal-of and make the polling time not
   required and assume it is zero when not found in the DT (Konrad
   Dybcio)

 - Add r8a779h0 support in both the DT and the driver (Geert Uytterhoeven)"

* tag 'thermal-v6.9-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/thermal/linux:
  thermal/drivers/rcar_gen3: Add support for R-Car V4M
  dt-bindings: thermal: rcar-gen3-thermal: Add r8a779h0 support
  thermal/of: Assume polling-delay(-passive) 0 when absent
  dt-bindings: thermal-zones: Don't require polling-delay(-passive)
  thermal/drivers/qoriq: Fix getting tmu range
  thermal/drivers/sun8i: Don't fail probe due to zone registration failure
  thermal/drivers/sun8i: Add support for H616 THS controller
  thermal/drivers/sun8i: Add SRAM register access code
  thermal/drivers/sun8i: Extend H6 calibration to support 4 sensors
  thermal/drivers/sun8i: Explain unknown H6 register value
  dt-bindings: thermal: sun8i: Add H616 THS controller
  soc: sunxi: sram: export register 0 for THS on H616
  dt-bindings: thermal: qoriq-thermal: Adjust fsl,tmu-range min/maxItems
  thermal: Drop spaces before TABs
  thermal/drivers/mediatek: Fix control buffer enablement on MT7896
  thermal/drivers/mediatek/lvts_thermal: Fix a memory leak in an error handling path

14 files changed:
Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml
Documentation/devicetree/bindings/thermal/qoriq-thermal.yaml
Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.yaml
Documentation/devicetree/bindings/thermal/thermal-zones.yaml
drivers/soc/sunxi/sunxi_sram.c
drivers/thermal/Makefile
drivers/thermal/mediatek/auxadc_thermal.c
drivers/thermal/mediatek/lvts_thermal.c
drivers/thermal/qoriq_thermal.c
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/st/st_thermal.h
drivers/thermal/st/st_thermal_memmap.c
drivers/thermal/sun8i_thermal.c
drivers/thermal/thermal_of.c

index 9b2272a9ec15d89122c3540b7088c91198a81e5d..6b3aea6d73b077ba537eeaf456840f61fb1cca6a 100644 (file)
@@ -21,6 +21,7 @@ properties:
       - allwinner,sun50i-a100-ths
       - allwinner,sun50i-h5-ths
       - allwinner,sun50i-h6-ths
+      - allwinner,sun50i-h616-ths
 
   clocks:
     minItems: 1
@@ -50,6 +51,10 @@ properties:
   nvmem-cell-names:
     const: calibration
 
+  allwinner,sram:
+    maxItems: 1
+    description: phandle to device controlling temperate offset SYS_CFG register
+
   # See Documentation/devicetree/bindings/thermal/thermal-sensor.yaml for details
   "#thermal-sensor-cells":
     enum:
@@ -65,6 +70,7 @@ allOf:
               - allwinner,sun20i-d1-ths
               - allwinner,sun50i-a100-ths
               - allwinner,sun50i-h6-ths
+              - allwinner,sun50i-h616-ths
 
     then:
       properties:
@@ -82,6 +88,17 @@ allOf:
         clock-names:
           minItems: 2
 
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              const: allwinner,sun50i-h616-ths
+
+    then:
+      properties:
+        allwinner,sram: false
+
   - if:
       properties:
         compatible:
@@ -101,17 +118,12 @@ allOf:
           const: 1
 
   - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - allwinner,sun8i-h3-ths
-              - allwinner,sun8i-r40-ths
-              - allwinner,sun20i-d1-ths
-              - allwinner,sun50i-a64-ths
-              - allwinner,sun50i-a100-ths
-              - allwinner,sun50i-h5-ths
-              - allwinner,sun50i-h6-ths
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - allwinner,sun8i-a83t-ths
 
     then:
       required:
index 145744027234bf82a46aabfb46ff74cc605288f5..d155d6799da6fcf1744d3fbeb635f6f4d1542b25 100644 (file)
@@ -33,7 +33,8 @@ properties:
     description: |
       The values to be programmed into TTRnCR, as specified by the SoC
       reference manual. The first cell is TTR0CR, the second is TTR1CR, etc.
-    maxItems: 4
+    minItems: 2
+    maxItems: 7
 
   fsl,tmu-calibration:
     $ref: /schemas/types.yaml#/definitions/uint32-matrix
index ecf276fd155cfb2730ac5d9a91e9feecb72fd46b..6a81cb6e11bc1e149af6152977239ac9c6a5b883 100644 (file)
@@ -29,6 +29,7 @@ properties:
       - renesas,r8a779a0-thermal # R-Car V3U
       - renesas,r8a779f0-thermal # R-Car S4-8
       - renesas,r8a779g0-thermal # R-Car V4H
+      - renesas,r8a779h0-thermal # R-Car V4M
 
   reg: true
 
@@ -90,6 +91,7 @@ else:
             enum:
               - renesas,r8a779f0-thermal
               - renesas,r8a779g0-thermal
+              - renesas,r8a779h0-thermal
   then:
     required:
       - interrupts
index dbd52620d293060f59432ac5e3df2b6d8d23a542..68398e7e8655657f77eb7b186137af522d675fd6 100644 (file)
@@ -228,8 +228,6 @@ patternProperties:
             additionalProperties: false
 
     required:
-      - polling-delay
-      - polling-delay-passive
       - thermal-sensors
       - trips
 
index 4458b2e0562b09bda26f063e11e09daa5e67d04f..6eb6cf06278e6684507249d1bf8b586e71055671 100644 (file)
@@ -287,6 +287,7 @@ EXPORT_SYMBOL(sunxi_sram_release);
 struct sunxi_sramc_variant {
        int num_emac_clocks;
        bool has_ldo_ctrl;
+       bool has_ths_offset;
 };
 
 static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
@@ -308,8 +309,10 @@ static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
 
 static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
        .num_emac_clocks = 2,
+       .has_ths_offset = true,
 };
 
+#define SUNXI_SRAM_THS_OFFSET_REG      0x0
 #define SUNXI_SRAM_EMAC_CLOCK_REG      0x30
 #define SUNXI_SYS_LDO_CTRL_REG         0x150
 
@@ -318,6 +321,8 @@ static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
 {
        const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev);
 
+       if (reg == SUNXI_SRAM_THS_OFFSET_REG && variant->has_ths_offset)
+               return true;
        if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG &&
            reg <  SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
                return true;
@@ -327,6 +332,20 @@ static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
        return false;
 }
 
+static void sunxi_sram_lock(void *_lock)
+{
+       spinlock_t *lock = _lock;
+
+       spin_lock(lock);
+}
+
+static void sunxi_sram_unlock(void *_lock)
+{
+       spinlock_t *lock = _lock;
+
+       spin_unlock(lock);
+}
+
 static struct regmap_config sunxi_sram_regmap_config = {
        .reg_bits       = 32,
        .val_bits       = 32,
@@ -336,6 +355,9 @@ static struct regmap_config sunxi_sram_regmap_config = {
        /* other devices have no business accessing other registers */
        .readable_reg   = sunxi_sram_regmap_accessible_reg,
        .writeable_reg  = sunxi_sram_regmap_accessible_reg,
+       .lock           = sunxi_sram_lock,
+       .unlock         = sunxi_sram_unlock,
+       .lock_arg       = &sram_lock,
 };
 
 static int __init sunxi_sram_probe(struct platform_device *pdev)
index d77d7fe99a84aa3fb1f8059cd8c58f643741b1db..5cdf7d68687f43b3a0f62c15bcb78235e16de679 100644 (file)
@@ -43,7 +43,7 @@ obj-$(CONFIG_RCAR_GEN3_THERMAL)       += rcar_gen3_thermal.o
 obj-$(CONFIG_RZG2L_THERMAL)    += rzg2l_thermal.o
 obj-$(CONFIG_KIRKWOOD_THERMAL)  += kirkwood_thermal.o
 obj-y                          += samsung/
-obj-$(CONFIG_DOVE_THERMAL)     += dove_thermal.o
+obj-$(CONFIG_DOVE_THERMAL)     += dove_thermal.o
 obj-$(CONFIG_DB8500_THERMAL)   += db8500_thermal.o
 obj-$(CONFIG_ARMADA_THERMAL)   += armada_thermal.o
 obj-$(CONFIG_IMX_THERMAL)      += imx_thermal.o
index 8b0edb2048443d9e7f05dd09977e447b4b594a20..9ee2e7283435acfcbb1a956303b6122a08affecc 100644 (file)
@@ -690,6 +690,9 @@ static const struct mtk_thermal_data mt7986_thermal_data = {
        .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)
index 98d9c80bd4c6279385efa97fea52b0a2651348ea..fd4bd650c77a6ae8a0deebb7d8cfb13415d9214e 100644 (file)
@@ -719,8 +719,10 @@ static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td
 
                lvts_td->calib = devm_krealloc(dev, lvts_td->calib,
                                               lvts_td->calib_len + len, GFP_KERNEL);
-               if (!lvts_td->calib)
+               if (!lvts_td->calib) {
+                       kfree(efuse);
                        return -ENOMEM;
+               }
 
                memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len);
 
index ccc2eea7f9f548a184646cb38a39068238b978b3..404f01cca4dab581aa3dff8799d37b38f03ebc1d 100644 (file)
@@ -57,6 +57,9 @@
 #define REGS_TTRnCR(n) (0xf10 + 4 * (n)) /* Temperature Range n
                                           * Control Register
                                           */
+#define NUM_TTRCR_V1   4
+#define NUM_TTRCR_MAX  16
+
 #define REGS_IPBRR(n)          (0xbf8 + 4 * (n)) /* IP Block Revision
                                                   * Register n
                                                   */
@@ -71,6 +74,7 @@ struct qoriq_sensor {
 
 struct qoriq_tmu_data {
        int ver;
+       u32 ttrcr[NUM_TTRCR_MAX];
        struct regmap *regmap;
        struct clk *clk;
        struct qoriq_sensor     sensor[SITES_MAX];
@@ -182,17 +186,17 @@ static int qoriq_tmu_calibration(struct device *dev,
                                 struct qoriq_tmu_data *data)
 {
        int i, val, len;
-       u32 range[4];
        const u32 *calibration;
        struct device_node *np = dev->of_node;
 
        len = of_property_count_u32_elems(np, "fsl,tmu-range");
-       if (len < 0 || len > 4) {
+       if (len < 0 || (data->ver == TMU_VER1 && len > NUM_TTRCR_V1) ||
+           (data->ver > TMU_VER1 && len > NUM_TTRCR_MAX)) {
                dev_err(dev, "invalid range data.\n");
                return len;
        }
 
-       val = of_property_read_u32_array(np, "fsl,tmu-range", range, len);
+       val = of_property_read_u32_array(np, "fsl,tmu-range", data->ttrcr, len);
        if (val != 0) {
                dev_err(dev, "failed to read range data.\n");
                return val;
@@ -200,7 +204,7 @@ static int qoriq_tmu_calibration(struct device *dev,
 
        /* Init temperature range registers */
        for (i = 0; i < len; i++)
-               regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
+               regmap_write(data->regmap, REGS_TTRnCR(i), data->ttrcr[i]);
 
        calibration = of_get_property(np, "fsl,tmu-calibration", &len);
        if (calibration == NULL || len % 8) {
index cafcb6d6e235be442375ac3180429a5daaeef707..a764cb1115a575620dbceb897ee04cc176c4082f 100644 (file)
@@ -428,6 +428,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
                .compatible = "renesas,r8a779g0-thermal",
                .data = &rcar_gen4_thermal_info,
        },
+       {
+               .compatible = "renesas,r8a779h0-thermal",
+               .data = &rcar_gen4_thermal_info,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
index 75a84e6ec6a729bfce9027b467526f90713c33ee..8639d9165c9b9d56a184db198bb24b692a2d8472 100644 (file)
@@ -38,10 +38,10 @@ struct st_thermal_sensor;
  *
  * @power_ctrl:                Function for powering on/off a sensor. Clock to the
  *                     sensor is also controlled from this function.
- * @alloc_regfields:   Allocate regmap register fields, specific to a sensor.
- * @do_memmap_regmap:  Memory map the thermal register space and init regmap
+ * @alloc_regfields:   Allocate regmap register fields, specific to a sensor.
+ * @do_memmap_regmap:  Memory map the thermal register space and init regmap
  *                     instance or find regmap instance.
- * @register_irq:      Register an interrupt handler for a sensor.
+ * @register_irq:      Register an interrupt handler for a sensor.
  */
 struct st_thermal_sensor_ops {
        int (*power_ctrl)(struct st_thermal_sensor *, enum st_thermal_power_state);
@@ -56,15 +56,15 @@ struct st_thermal_sensor_ops {
  *
  * @reg_fields:                Pointer to the regfields array for a sensor.
  * @sys_compat:                Pointer to the syscon node compatible string.
- * @ops:               Pointer to private thermal ops for a sensor.
- * @calibration_val:   Default calibration value to be written to the DCORRECT
+ * @ops:               Pointer to private thermal ops for a sensor.
+ * @calibration_val:   Default calibration value to be written to the DCORRECT
  *                     register field for a sensor.
- * @temp_adjust_val:   Value to be added/subtracted from the data read from
+ * @temp_adjust_val:   Value to be added/subtracted from the data read from
  *                     the sensor. If value needs to be added please provide a
  *                     positive value and if it is to be subtracted please
- *                     provide a negative value.
- * @crit_temp:                 The temperature beyond which the SoC should be shutdown
- *                     to prevent damage.
+ *                     provide a negative value.
+ * @crit_temp:         The temperature beyond which the SoC should be shutdown
+ *                     to prevent damage.
  */
 struct st_thermal_compat_data {
        char *sys_compat;
index e8cfa83b724a774b53e0be33d1e462601b070f07..29c2269b0fb35ced3d9a9b623494fd6f0ca76e78 100644 (file)
@@ -27,7 +27,7 @@ static const struct reg_field st_mmap_thermal_regfields[MAX_REGFIELDS] = {
         * written simultaneously for powering on and off the temperature
         * sensor. regmap_update_bits() will be used to update the register.
         */
-       [INT_THRESH_HI] = REG_FIELD(STIH416_MPE_INT_THRESH,     0,  7),
+       [INT_THRESH_HI] = REG_FIELD(STIH416_MPE_INT_THRESH,     0,  7),
        [DCORRECT]      = REG_FIELD(STIH416_MPE_CONF,           5,  9),
        [OVERFLOW]      = REG_FIELD(STIH416_MPE_STATUS,         9,  9),
        [DATA]          = REG_FIELD(STIH416_MPE_STATUS,         11, 18),
index 6a8e386dbc8dc2972461c59295d3d3661f1d6248..3203d8bd13a8fc2a9e5a59b3547cefc2440542c6 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
@@ -50,7 +51,8 @@
 #define SUN8I_THS_CTRL2_T_ACQ1(x)              ((GENMASK(15, 0) & (x)) << 16)
 #define SUN8I_THS_DATA_IRQ_STS(x)              BIT(x + 8)
 
-#define SUN50I_THS_CTRL0_T_ACQ(x)              ((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_CTRL0_T_ACQ(x)              (GENMASK(15, 0) & ((x) - 1))
+#define SUN50I_THS_CTRL0_T_SAMPLE_PER(x)       ((GENMASK(15, 0) & ((x) - 1)) << 16)
 #define SUN50I_THS_FILTER_EN                   BIT(2)
 #define SUN50I_THS_FILTER_TYPE(x)              (GENMASK(1, 0) & (x))
 #define SUN50I_H6_THS_PC_TEMP_PERIOD(x)                ((GENMASK(19, 0) & (x)) << 12)
@@ -65,6 +67,7 @@ struct tsensor {
 struct ths_thermal_chip {
        bool            has_mod_clk;
        bool            has_bus_clk_reset;
+       bool            needs_sram;
        int             sensor_num;
        int             offset;
        int             scale;
@@ -82,12 +85,16 @@ struct ths_device {
        const struct ths_thermal_chip           *chip;
        struct device                           *dev;
        struct regmap                           *regmap;
+       struct regmap_field                     *sram_regmap_field;
        struct reset_control                    *reset;
        struct clk                              *bus_clk;
        struct clk                              *mod_clk;
        struct tsensor                          sensor[MAX_SENSOR_NUM];
 };
 
+/* The H616 needs to have a bit 16 in the SRAM control register cleared. */
+static const struct reg_field sun8i_ths_sram_reg_field = REG_FIELD(0x0, 16, 16);
+
 /* Temp Unit: millidegree Celsius */
 static int sun8i_ths_calc_temp(struct ths_device *tmdev,
                               int id, int reg)
@@ -188,6 +195,9 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
        int i;
 
        for_each_set_bit(i, &irq_bitmap, tmdev->chip->sensor_num) {
+               /* We allow some zones to not register. */
+               if (IS_ERR(tmdev->sensor[i].tzd))
+                       continue;
                thermal_zone_device_update(tmdev->sensor[i].tzd,
                                           THERMAL_EVENT_UNSPECIFIED);
        }
@@ -221,16 +231,21 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
        struct device *dev = tmdev->dev;
        int i, ft_temp;
 
-       if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num)
+       if (!caldata[0])
                return -EINVAL;
 
        /*
         * efuse layout:
         *
-        *      0   11  16       32
-        *      +-------+-------+-------+
-        *      |temp|  |sensor0|sensor1|
-        *      +-------+-------+-------+
+        * 0      11  16     27   32     43   48    57
+        * +----------+-----------+-----------+-----------+
+        * |  temp |  |sensor0|   |sensor1|   |sensor2|   |
+        * +----------+-----------+-----------+-----------+
+        *                      ^           ^           ^
+        *                      |           |           |
+        *                      |           |           sensor3[11:8]
+        *                      |           sensor3[7:4]
+        *                      sensor3[3:0]
         *
         * The calibration data on the H6 is the ambient temperature and
         * sensor values that are filled during the factory test stage.
@@ -243,9 +258,16 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
        ft_temp = (caldata[0] & FT_TEMP_MASK) * 100;
 
        for (i = 0; i < tmdev->chip->sensor_num; i++) {
-               int sensor_reg = caldata[i + 1] & TEMP_CALIB_MASK;
-               int cdata, offset;
-               int sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg);
+               int sensor_reg, sensor_temp, cdata, offset;
+
+               if (i == 3)
+                       sensor_reg = (caldata[1] >> 12)
+                                    | ((caldata[2] >> 12) << 4)
+                                    | ((caldata[3] >> 12) << 8);
+               else
+                       sensor_reg = caldata[i + 1] & TEMP_CALIB_MASK;
+
+               sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg);
 
                /*
                 * Calibration data is CALIBRATE_DEFAULT - (calculated
@@ -324,6 +346,34 @@ static void sun8i_ths_reset_control_assert(void *data)
        reset_control_assert(data);
 }
 
+static struct regmap *sun8i_ths_get_sram_regmap(struct device_node *node)
+{
+       struct device_node *sram_node;
+       struct platform_device *sram_pdev;
+       struct regmap *regmap = NULL;
+
+       sram_node = of_parse_phandle(node, "allwinner,sram", 0);
+       if (!sram_node)
+               return ERR_PTR(-ENODEV);
+
+       sram_pdev = of_find_device_by_node(sram_node);
+       if (!sram_pdev) {
+               /* platform device might not be probed yet */
+               regmap = ERR_PTR(-EPROBE_DEFER);
+               goto out_put_node;
+       }
+
+       /* If no regmap is found then the other device driver is at fault */
+       regmap = dev_get_regmap(&sram_pdev->dev, NULL);
+       if (!regmap)
+               regmap = ERR_PTR(-EINVAL);
+
+       platform_device_put(sram_pdev);
+out_put_node:
+       of_node_put(sram_node);
+       return regmap;
+}
+
 static int sun8i_ths_resource_init(struct ths_device *tmdev)
 {
        struct device *dev = tmdev->dev;
@@ -368,6 +418,19 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
        if (ret)
                return ret;
 
+       if (tmdev->chip->needs_sram) {
+               struct regmap *regmap;
+
+               regmap = sun8i_ths_get_sram_regmap(dev->of_node);
+               if (IS_ERR(regmap))
+                       return PTR_ERR(regmap);
+               tmdev->sram_regmap_field = devm_regmap_field_alloc(dev,
+                                                     regmap,
+                                                     sun8i_ths_sram_reg_field);
+               if (IS_ERR(tmdev->sram_regmap_field))
+                       return PTR_ERR(tmdev->sram_regmap_field);
+       }
+
        ret = sun8i_ths_calibrate(tmdev);
        if (ret)
                return ret;
@@ -410,25 +473,31 @@ static int sun8i_h3_thermal_init(struct ths_device *tmdev)
        return 0;
 }
 
-/*
- * Without this undocumented value, the returned temperatures would
- * be higher than real ones by about 20C.
- */
-#define SUN50I_H6_CTRL0_UNK 0x0000002f
-
 static int sun50i_h6_thermal_init(struct ths_device *tmdev)
 {
        int val;
 
+       /* The H616 needs to have a bit in the SRAM control register cleared. */
+       if (tmdev->sram_regmap_field)
+               regmap_field_write(tmdev->sram_regmap_field, 0);
+
        /*
-        * T_acq = 20us
-        * clkin = 24MHz
-        *
-        * x = T_acq * clkin - 1
-        *   = 479
+        * The manual recommends an overall sample frequency of 50 KHz (20us,
+        * 480 cycles at 24 MHz), which provides plenty of time for both the
+        * acquisition time (>24 cycles) and the actual conversion time
+        * (>14 cycles).
+        * The lower half of the CTRL register holds the "acquire time", in
+        * clock cycles, which the manual recommends to be 2us:
+        * 24MHz * 2us = 48 cycles.
+        * The high half of THS_CTRL encodes the sample frequency, in clock
+        * cycles: 24MHz * 20us = 480 cycles.
+        * This is explained in the H616 manual, but apparently wrongly
+        * described in the H6 manual, although the BSP code does the same
+        * for both SoCs.
         */
        regmap_write(tmdev->regmap, SUN50I_THS_CTRL0,
-                    SUN50I_H6_CTRL0_UNK | SUN50I_THS_CTRL0_T_ACQ(479));
+                    SUN50I_THS_CTRL0_T_ACQ(48) |
+                    SUN50I_THS_CTRL0_T_SAMPLE_PER(480));
        /* average over 4 samples */
        regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC,
                     SUN50I_THS_FILTER_EN |
@@ -465,8 +534,17 @@ static int sun8i_ths_register(struct ths_device *tmdev)
                                                      i,
                                                      &tmdev->sensor[i],
                                                      &ths_ops);
-               if (IS_ERR(tmdev->sensor[i].tzd))
-                       return PTR_ERR(tmdev->sensor[i].tzd);
+
+               /*
+                * If an individual zone fails to register for reasons
+                * other than probe deferral (eg, a bad DT) then carry
+                * on, other zones might register successfully.
+                */
+               if (IS_ERR(tmdev->sensor[i].tzd)) {
+                       if (PTR_ERR(tmdev->sensor[i].tzd) == -EPROBE_DEFER)
+                               return PTR_ERR(tmdev->sensor[i].tzd);
+                       continue;
+               }
 
                devm_thermal_add_hwmon_sysfs(tmdev->dev, tmdev->sensor[i].tzd);
        }
@@ -618,6 +696,20 @@ static const struct ths_thermal_chip sun20i_d1_ths = {
        .calc_temp = sun8i_ths_calc_temp,
 };
 
+static const struct ths_thermal_chip sun50i_h616_ths = {
+       .sensor_num = 4,
+       .has_bus_clk_reset = true,
+       .needs_sram = true,
+       .ft_deviation = 8000,
+       .offset = 263655,
+       .scale = 810,
+       .temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+       .calibrate = sun50i_h6_ths_calibrate,
+       .init = sun50i_h6_thermal_init,
+       .irq_ack = sun50i_h6_irq_ack,
+       .calc_temp = sun8i_ths_calc_temp,
+};
+
 static const struct of_device_id of_ths_match[] = {
        { .compatible = "allwinner,sun8i-a83t-ths", .data = &sun8i_a83t_ths },
        { .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
@@ -627,6 +719,7 @@ static const struct of_device_id of_ths_match[] = {
        { .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths },
        { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
        { .compatible = "allwinner,sun20i-d1-ths", .data = &sun20i_d1_ths },
+       { .compatible = "allwinner,sun50i-h616-ths", .data = &sun50i_h616_ths },
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, of_ths_match);
index f1cbf9aa62cfedc2f621d6d619f3226f4a46f2e9..aa34b6e82e268bce2cb964ad5fcea02122f046c1 100644 (file)
@@ -227,14 +227,18 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
        int ret;
 
        ret = of_property_read_u32(np, "polling-delay-passive", pdelay);
-       if (ret < 0) {
-               pr_err("%pOFn: missing polling-delay-passive property\n", np);
+       if (ret == -EINVAL) {
+               *pdelay = 0;
+       } else if (ret < 0) {
+               pr_err("%pOFn: Couldn't get polling-delay-passive: %d\n", np, ret);
                return ret;
        }
 
        ret = of_property_read_u32(np, "polling-delay", delay);
-       if (ret < 0) {
-               pr_err("%pOFn: missing polling-delay property\n", np);
+       if (ret == -EINVAL) {
+               *delay = 0;
+       } else if (ret < 0) {
+               pr_err("%pOFn: Couldn't get polling-delay: %d\n", np, ret);
                return ret;
        }
 
@@ -460,7 +464,7 @@ static void thermal_of_zone_unregister(struct thermal_zone_device *tz)
  * @ops: A set of thermal sensor ops
  *
  * Return: a valid thermal zone structure pointer on success.
- *     - EINVAL: if the device tree thermal description is malformed
+ *     - EINVAL: if the device tree thermal description is malformed
  *     - ENOMEM: if one structure can not be allocated
  *     - Other negative errors are returned by the underlying called functions
  */