mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 05:31:37 -04:00
dpll: zl3073x: add die temperature reporting for supported chips
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>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*************************/
|
||||
|
||||
Reference in New Issue
Block a user