]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dpll: zl3073x: add die temperature reporting for supported chips
authorIvan Vecera <ivecera@redhat.com>
Fri, 27 Feb 2026 10:53:00 +0000 (11:53 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 3 Mar 2026 11:15:30 +0000 (12:15 +0100)
Some zl3073x chip variants (0x1Exx, 0x2Exx and 0x3FC4) provide a die
temperature status register with 0.1 C resolution.

Add a ZL3073X_FLAG_DIE_TEMP chip flag to identify these variants and
implement zl3073x_dpll_temp_get() as the dpll_device_ops.temp_get
callback. The register value is converted from 0.1 C units to
millidegrees as expected by the DPLL subsystem.

To support per-instance ops selection, copy the base dpll_device_ops
into struct zl3073x_dpll and conditionally set .temp_get during device
registration based on the chip flag.

Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260227105300.710272-3-ivecera@redhat.com
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/dpll/zl3073x/core.c
drivers/dpll/zl3073x/core.h
drivers/dpll/zl3073x/dpll.c
drivers/dpll/zl3073x/dpll.h
drivers/dpll/zl3073x/regs.h

index c8af343010450583ec9d4077dbe173220fd0d4d6..10e036ccf08f05ad611f0a6cdf1702e2ab1d8951 100644 (file)
@@ -30,18 +30,18 @@ static const struct zl3073x_chip_info zl3073x_chip_ids[] = {
        ZL_CHIP_INFO(0x0E95, 3, ZL3073X_FLAG_REF_PHASE_COMP_32),
        ZL_CHIP_INFO(0x0E96, 4, ZL3073X_FLAG_REF_PHASE_COMP_32),
        ZL_CHIP_INFO(0x0E97, 5, ZL3073X_FLAG_REF_PHASE_COMP_32),
-       ZL_CHIP_INFO(0x1E93, 1, 0),
-       ZL_CHIP_INFO(0x1E94, 2, 0),
-       ZL_CHIP_INFO(0x1E95, 3, 0),
-       ZL_CHIP_INFO(0x1E96, 4, 0),
-       ZL_CHIP_INFO(0x1E97, 5, 0),
+       ZL_CHIP_INFO(0x1E93, 1, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x1E94, 2, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x1E95, 3, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x1E96, 4, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x1E97, 5, ZL3073X_FLAG_DIE_TEMP),
        ZL_CHIP_INFO(0x1F60, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
-       ZL_CHIP_INFO(0x2E93, 1, 0),
-       ZL_CHIP_INFO(0x2E94, 2, 0),
-       ZL_CHIP_INFO(0x2E95, 3, 0),
-       ZL_CHIP_INFO(0x2E96, 4, 0),
-       ZL_CHIP_INFO(0x2E97, 5, 0),
-       ZL_CHIP_INFO(0x3FC4, 2, 0),
+       ZL_CHIP_INFO(0x2E93, 1, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x2E94, 2, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x2E95, 3, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x2E96, 4, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x2E97, 5, ZL3073X_FLAG_DIE_TEMP),
+       ZL_CHIP_INFO(0x3FC4, 2, ZL3073X_FLAG_DIE_TEMP),
 };
 
 #define ZL_RANGE_OFFSET                0x80
index fde5c8371fbd28f81a03286f3b156e0e3d81dd36..b6f22ee1c0bd1be485c5a97be049b9f338c598fd 100644 (file)
@@ -32,11 +32,13 @@ struct zl3073x_dpll;
 
 enum zl3073x_flags {
        ZL3073X_FLAG_REF_PHASE_COMP_32_BIT,
+       ZL3073X_FLAG_DIE_TEMP_BIT,
        ZL3073X_FLAGS_NBITS /* must be last */
 };
 
 #define __ZL3073X_FLAG(name)   BIT(ZL3073X_FLAG_ ## name ## _BIT)
 #define ZL3073X_FLAG_REF_PHASE_COMP_32 __ZL3073X_FLAG(REF_PHASE_COMP_32)
+#define ZL3073X_FLAG_DIE_TEMP          __ZL3073X_FLAG(DIE_TEMP)
 
 /**
  * struct zl3073x_chip_info - chip variant identification
index aaa14ea5e670fd9b0f0340295c4625afe8f3b48a..c201c974a7f9a4455f3e7d619508d0aa64e5354f 100644 (file)
@@ -1065,6 +1065,25 @@ zl3073x_dpll_output_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin,
        return 0;
 }
 
+static int
+zl3073x_dpll_temp_get(const struct dpll_device *dpll, void *dpll_priv,
+                     s32 *temp, struct netlink_ext_ack *extack)
+{
+       struct zl3073x_dpll *zldpll = dpll_priv;
+       struct zl3073x_dev *zldev = zldpll->dev;
+       u16 val;
+       int rc;
+
+       rc = zl3073x_read_u16(zldev, ZL_REG_DIE_TEMP_STATUS, &val);
+       if (rc)
+               return rc;
+
+       /* Register value is in units of 0.1 C, convert to millidegrees */
+       *temp = (s16)val * 100;
+
+       return 0;
+}
+
 static int
 zl3073x_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv,
                             enum dpll_lock_status *status,
@@ -1671,6 +1690,10 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
        zldpll->forced_ref = FIELD_GET(ZL_DPLL_MODE_REFSEL_REF,
                                       dpll_mode_refsel);
 
+       zldpll->ops = zl3073x_dpll_device_ops;
+       if (zldev->info->flags & ZL3073X_FLAG_DIE_TEMP)
+               zldpll->ops.temp_get = zl3073x_dpll_temp_get;
+
        zldpll->dpll_dev = dpll_device_get(zldev->clock_id, zldpll->id,
                                           THIS_MODULE, &zldpll->tracker);
        if (IS_ERR(zldpll->dpll_dev)) {
@@ -1682,7 +1705,7 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
 
        rc = dpll_device_register(zldpll->dpll_dev,
                                  zl3073x_prop_dpll_type_get(zldev, zldpll->id),
-                                 &zl3073x_dpll_device_ops, zldpll);
+                                 &zldpll->ops, zldpll);
        if (rc) {
                dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
                zldpll->dpll_dev = NULL;
@@ -1705,8 +1728,7 @@ zl3073x_dpll_device_unregister(struct zl3073x_dpll *zldpll)
 
        cancel_work_sync(&zldpll->change_work);
 
-       dpll_device_unregister(zldpll->dpll_dev, &zl3073x_dpll_device_ops,
-                              zldpll);
+       dpll_device_unregister(zldpll->dpll_dev, &zldpll->ops, zldpll);
        dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
        zldpll->dpll_dev = NULL;
 }
index c65c798c37927f4016da1b2c81eecdfe8db01fc6..278a24f357c9bd22ed2d0518225006cda988f45f 100644 (file)
@@ -17,6 +17,7 @@
  * @forced_ref: selected reference in forced reference lock mode
  * @check_count: periodic check counter
  * @phase_monitor: is phase offset monitor enabled
+ * @ops: DPLL device operations for this instance
  * @dpll_dev: pointer to registered DPLL device
  * @tracker: tracking object for the acquired reference
  * @lock_status: last saved DPLL lock status
@@ -31,6 +32,7 @@ struct zl3073x_dpll {
        u8                              forced_ref;
        u8                              check_count;
        bool                            phase_monitor;
+       struct dpll_device_ops          ops;
        struct dpll_device              *dpll_dev;
        dpll_tracker                    tracker;
        enum dpll_lock_status           lock_status;
index 5573d7188406bb7cf8f041aabb4f309bd96111c4..19c598daa784cad10c432ef68fcdb326d52a7754 100644 (file)
@@ -78,6 +78,8 @@
 #define ZL_REG_RESET_STATUS                    ZL_REG(0, 0x18, 1)
 #define ZL_REG_RESET_STATUS_RESET              BIT(0)
 
+#define ZL_REG_DIE_TEMP_STATUS                 ZL_REG(0, 0x44, 2)
+
 /*************************
  * Register Page 2, Status
  *************************/