Commit fe109f6b authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'move-ksz9477-errata-handling-to-phy-driver'

Robert Hancock says:

====================
Move KSZ9477 errata handling to PHY driver

Patches to move handling for KSZ9477 PHY errata register fixes from
the DSA switch driver into the corresponding PHY driver, for more
proper layering and ordering.
====================

Link: https://lore.kernel.org/r/20230605153943.1060444-1-robert.hancock@calian.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 2dc47640 6068e6d7
...@@ -889,62 +889,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) ...@@ -889,62 +889,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
return interface; return interface;
} }
static void ksz9477_port_mmd_write(struct ksz_device *dev, int port,
u8 dev_addr, u16 reg_addr, u16 val)
{
ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr));
ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr);
ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP,
MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr));
ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
}
static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
{
/* Apply PHY settings to address errata listed in
* KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
* Silicon Errata and Data Sheet Clarification documents:
*
* Register settings are needed to improve PHY receive performance
*/
ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
/* Transmit waveform amplitude can be improved
* (1000BASE-T, 100BASE-TX, 10BASE-Te)
*/
ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
/* Energy Efficient Ethernet (EEE) feature select must
* be manually disabled (except on KSZ8565 which is 100Mbit)
*/
if (dev->info->gbit_capable[port])
ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
/* Register settings are required to meet data sheet
* supply current specifications
*/
ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
}
void ksz9477_get_caps(struct ksz_device *dev, int port, void ksz9477_get_caps(struct ksz_device *dev, int port,
struct phylink_config *config) struct phylink_config *config)
{ {
...@@ -1029,20 +973,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ...@@ -1029,20 +973,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
/* enable 802.1p priority */ /* enable 802.1p priority */
ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true);
if (dev->info->internal_phy[port]) { /* force flow control for non-PHY ports only */
/* do not force flow control */
ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
false);
if (dev->info->phy_errata_9477)
ksz9477_phy_errata_setup(dev, port);
} else {
/* force flow control */
ksz_port_cfg(dev, port, REG_PORT_CTRL_0, ksz_port_cfg(dev, port, REG_PORT_CTRL_0,
PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
true); !dev->info->internal_phy[port]);
}
if (cpu_port) if (cpu_port)
member = dsa_user_ports(ds); member = dsa_user_ports(ds);
......
...@@ -1270,7 +1270,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1270,7 +1270,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true, .tc_cbs_supported = true,
.tc_ets_supported = true, .tc_ets_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM, .reg_mib_cnt = MIB_COUNTER_NUM,
...@@ -1303,7 +1302,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1303,7 +1302,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2, .port_nirqs = 2,
.num_tx_queues = 4, .num_tx_queues = 4,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM, .reg_mib_cnt = MIB_COUNTER_NUM,
...@@ -1336,7 +1334,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1336,7 +1334,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.port_nirqs = 2, .port_nirqs = 2,
.num_tx_queues = 4, .num_tx_queues = 4,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM, .reg_mib_cnt = MIB_COUNTER_NUM,
...@@ -1423,7 +1420,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { ...@@ -1423,7 +1420,6 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.tc_cbs_supported = true, .tc_cbs_supported = true,
.tc_ets_supported = true, .tc_ets_supported = true,
.ops = &ksz9477_dev_ops, .ops = &ksz9477_dev_ops,
.phy_errata_9477 = true,
.mib_names = ksz9477_mib_names, .mib_names = ksz9477_mib_names,
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
.reg_mib_cnt = MIB_COUNTER_NUM, .reg_mib_cnt = MIB_COUNTER_NUM,
......
...@@ -60,7 +60,6 @@ struct ksz_chip_data { ...@@ -60,7 +60,6 @@ struct ksz_chip_data {
bool tc_cbs_supported; bool tc_cbs_supported;
bool tc_ets_supported; bool tc_ets_supported;
const struct ksz_dev_ops *ops; const struct ksz_dev_ops *ops;
bool phy_errata_9477;
bool ksz87xx_eee_link_erratum; bool ksz87xx_eee_link_erratum;
const struct ksz_mib_names *mib_names; const struct ksz_mib_names *mib_names;
int mib_cnt; int mib_cnt;
......
...@@ -1774,6 +1774,79 @@ static int ksz886x_read_status(struct phy_device *phydev) ...@@ -1774,6 +1774,79 @@ static int ksz886x_read_status(struct phy_device *phydev)
return genphy_read_status(phydev); return genphy_read_status(phydev);
} }
struct ksz9477_errata_write {
u8 dev_addr;
u8 reg_addr;
u16 val;
};
static const struct ksz9477_errata_write ksz9477_errata_writes[] = {
/* Register settings are needed to improve PHY receive performance */
{0x01, 0x6f, 0xdd0b},
{0x01, 0x8f, 0x6032},
{0x01, 0x9d, 0x248c},
{0x01, 0x75, 0x0060},
{0x01, 0xd3, 0x7777},
{0x1c, 0x06, 0x3008},
{0x1c, 0x08, 0x2000},
/* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
{0x1c, 0x04, 0x00d0},
/* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
{0x07, 0x3c, 0x0000},
/* Register settings are required to meet data sheet supply current specifications */
{0x1c, 0x13, 0x6eff},
{0x1c, 0x14, 0xe6ff},
{0x1c, 0x15, 0x6eff},
{0x1c, 0x16, 0xe6ff},
{0x1c, 0x17, 0x00ff},
{0x1c, 0x18, 0x43ff},
{0x1c, 0x19, 0xc3ff},
{0x1c, 0x1a, 0x6fff},
{0x1c, 0x1b, 0x07ff},
{0x1c, 0x1c, 0x0fff},
{0x1c, 0x1d, 0xe7ff},
{0x1c, 0x1e, 0xefff},
{0x1c, 0x20, 0xeeee},
};
static int ksz9477_config_init(struct phy_device *phydev)
{
int err;
int i;
/* Apply PHY settings to address errata listed in
* KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565
* Silicon Errata and Data Sheet Clarification documents.
*
* Document notes: Before configuring the PHY MMD registers, it is
* necessary to set the PHY to 100 Mbps speed with auto-negotiation
* disabled by writing to register 0xN100-0xN101. After writing the
* MMD registers, and after all errata workarounds that involve PHY
* register settings, write register 0xN100-0xN101 again to enable
* and restart auto-negotiation.
*/
err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX);
if (err)
return err;
for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) {
const struct ksz9477_errata_write *errata = &ksz9477_errata_writes[i];
err = phy_write_mmd(phydev, errata->dev_addr, errata->reg_addr, errata->val);
if (err)
return err;
}
err = genphy_restart_aneg(phydev);
if (err)
return err;
return kszphy_config_init(phydev);
}
static int kszphy_get_sset_count(struct phy_device *phydev) static int kszphy_get_sset_count(struct phy_device *phydev)
{ {
return ARRAY_SIZE(kszphy_hw_stats); return ARRAY_SIZE(kszphy_hw_stats);
...@@ -4735,7 +4808,7 @@ static struct phy_driver ksphy_driver[] = { ...@@ -4735,7 +4808,7 @@ static struct phy_driver ksphy_driver[] = {
.phy_id_mask = MICREL_PHY_ID_MASK, .phy_id_mask = MICREL_PHY_ID_MASK,
.name = "Microchip KSZ9477", .name = "Microchip KSZ9477",
/* PHY_GBIT_FEATURES */ /* PHY_GBIT_FEATURES */
.config_init = kszphy_config_init, .config_init = ksz9477_config_init,
.config_intr = kszphy_config_intr, .config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt, .handle_interrupt = kszphy_handle_interrupt,
.suspend = genphy_suspend, .suspend = genphy_suspend,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment