stat3);
}
+static int ksz87xx_apply_low_loss_preset(struct ksz_device *dev, bool enable)
+{
+ /* Apply the Microchip erratum short-cable preset (LPF 62 MHz, EQ init 0)
+ * providing a conservative configuration for short or low-loss cables.
+ */
+ u8 lpf_bw, eq_init;
+ int ret;
+
+ lpf_bw = KSZ87XX_PHY_LPF_62MHZ;
+ eq_init = KSZ87XX_DSP_EQ_INIT_LOW_LOSS;
+
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+
+ if (!enable) {
+ /* Restore default values (LPF 90 MHz, EQ init 15). */
+ lpf_bw = KSZ87XX_PHY_LPF_90MHZ;
+ eq_init = KSZ87XX_DSP_EQ_INIT_FACTORY;
+ }
+
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF, lpf_bw);
+ if (ret)
+ return ret;
+
+ dev->lpf_bw = lpf_bw;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_DSP_EQ, eq_init);
+ if (ret)
+ return ret;
+
+ dev->eq_init = eq_init;
+
+ return ret;
+}
+
/**
* ksz8_r_phy_ctrl - Translates and reads from the SMI interface to a MIIM PHY
* Control register (Reg. 31).
if (ret)
return ret;
+ break;
+ case PHY_REG_KSZ87XX_SHORT_CABLE:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = !!(dev->lpf_bw == KSZ87XX_PHY_LPF_62MHZ &&
+ dev->eq_init == KSZ87XX_DSP_EQ_INIT_LOW_LOSS);
+ break;
+ case PHY_REG_KSZ87XX_LPF_BW:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = dev->lpf_bw;
+ break;
+ case PHY_REG_KSZ87XX_EQ_INIT:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ data = dev->eq_init;
break;
default:
processed = false;
if (ret)
return ret;
break;
+ case PHY_REG_KSZ87XX_SHORT_CABLE:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ dev_info_once(dev->dev,
+ "KSZ87xx low-loss tuning is global, applied switch-wide\n");
+ ret = ksz87xx_apply_low_loss_preset(dev, !!val);
+ if (ret)
+ return ret;
+ break;
+ case PHY_REG_KSZ87XX_LPF_BW:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ dev_info_once(dev->dev,
+ "KSZ87xx low-loss tuning is global, applied switch-wide\n");
+ /* Only accept LPF bandwidth bits [7:6] */
+ if (val & ~KSZ87XX_PHY_LPF_MASK)
+ return -EINVAL;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_PHY_LPF, (u8)val);
+ if (ret)
+ return ret;
+ dev->lpf_bw = val;
+ break;
+ case PHY_REG_KSZ87XX_EQ_INIT:
+ if (!ksz_is_ksz87xx(dev))
+ return -EOPNOTSUPP;
+ dev_info_once(dev->dev,
+ "KSZ87xx low-loss tuning is global, applied switch-wide\n");
+ /* Only accept DSP EQ initial value bits [5:0] */
+ if (val & ~KSZ87XX_DSP_EQ_VALID_MASK)
+ return -EINVAL;
+ ret = ksz8_ind_write8(dev, TABLE_LINK_MD, KSZ87XX_REG_DSP_EQ, (u8)val);
+ if (ret)
+ return ret;
+ dev->eq_init = val;
+ break;
default:
break;
}
return ret;
}
+ /* Initialize KSZ87xx short-cable preset control */
+ dev->eq_init = KSZ87XX_DSP_EQ_INIT_FACTORY;
+ dev->lpf_bw = KSZ87XX_PHY_LPF_90MHZ;
+
ret = ksz8_handle_global_errata(ds);
if (ret)
return ret;
#define REG_PORT_3_STATUS_0 0x38
#define REG_PORT_4_STATUS_0 0x48
+/* KSZ87xx LinkMD registers (TABLE_LINK_MD_V) */
+#define KSZ87XX_REG_DSP_EQ 0x08 /* DSP EQ initial value */
+#define KSZ87XX_REG_PHY_LPF 0x4C /* RX LPF bandwidth */
+
/* For KSZ8765. */
#define PORT_REMOTE_ASYM_PAUSE BIT(5)
#define PORT_REMOTE_SYM_PAUSE BIT(4)
#define TABLE_EEE (TABLE_EEE_V << TABLE_EXT_SELECT_S)
#define TABLE_ACL (TABLE_ACL_V << TABLE_EXT_SELECT_S)
#define TABLE_PME (TABLE_PME_V << TABLE_EXT_SELECT_S)
-#define TABLE_LINK_MD (TABLE_LINK_MD << TABLE_EXT_SELECT_S)
+#define TABLE_LINK_MD (TABLE_LINK_MD_V << TABLE_EXT_SELECT_S)
#define TABLE_READ BIT(4)
#define TABLE_SELECT_S 2
#define TABLE_STATIC_MAC_V 0
#define PHY_POWER_SAVING_ENABLE BIT(2)
#define PHY_REMOTE_LOOPBACK BIT(1)
+/* Vendor-specific Clause 22 PHY registers (virtualized) */
+#define PHY_REG_KSZ87XX_SHORT_CABLE 0x1A
+#define PHY_REG_KSZ87XX_LPF_BW 0x1B
+#define PHY_REG_KSZ87XX_EQ_INIT 0x1C
+
+/* LPF bandwidth bits [7:6]: 00 = 90MHz (default), 01 = 62MHz, 10 = 55MHz, 11 = 44MHz */
+#define KSZ87XX_PHY_LPF_MASK GENMASK(7, 6)
+#define KSZ87XX_PHY_LPF_90MHZ FIELD_PREP(KSZ87XX_PHY_LPF_MASK, 0)
+#define KSZ87XX_PHY_LPF_62MHZ FIELD_PREP(KSZ87XX_PHY_LPF_MASK, 1)
+#define KSZ87XX_PHY_LPF_55MHZ FIELD_PREP(KSZ87XX_PHY_LPF_MASK, 2)
+#define KSZ87XX_PHY_LPF_44MHZ FIELD_PREP(KSZ87XX_PHY_LPF_MASK, 3)
+
+/* Low-loss workaround DSP EQ INIT VALUE */
+#define KSZ87XX_DSP_EQ_VALID_MASK GENMASK(5, 0)
+#define KSZ87XX_DSP_EQ_INIT_LOW_LOSS 0x00
+#define KSZ87XX_DSP_EQ_INIT_FACTORY 0x0F
+
/* KSZ8463 specific registers. */
#define P1MBCR 0x4C
#define P1MBSR 0x4E