@@ -587,6 +587,28 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
return 0;
}
+static void
+qca8k_setup_port_pad_ctrl_reg(struct qca8k_priv *priv)
+{
+ u32 val = qca8k_read(priv, QCA8K_REG_PORT0_PAD_CTRL);
+
+ /* Swap MAC0-MAC6 */
+ if (of_property_read_bool(priv->dev->of_node,
+ "qca,exchange-mac0-mac6"))
+ val |= QCA8K_PORT0_PAD_CTRL_MAC06_EXCHG;
+
+ /* SGMII Clock phase configuration */
+ if (of_property_read_bool(priv->dev->of_node,
+ "qca,sgmii-rxclk-falling-edge"))
+ val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE;
+
+ if (of_property_read_bool(priv->dev->of_node,
+ "qca,sgmii-txclk-falling-edge"))
+ val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE;
+
+ qca8k_write(priv, QCA8K_REG_PORT0_PAD_CTRL, val);
+}
+
static int
qca8k_setup(struct dsa_switch *ds)
{
@@ -611,6 +633,9 @@ qca8k_setup(struct dsa_switch *ds)
if (ret)
return ret;
+ /* Configure additional port pad properties */
+ qca8k_setup_port_pad_ctrl_reg(priv);
+
/* Enable CPU Port */
qca8k_reg_set(priv, QCA8K_REG_GLOBAL_FW_CTRL0,
QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
@@ -722,27 +747,32 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
return;
}
+ /* Read port pad ctrl reg */
+ val = qca8k_read(priv, reg);
+
switch (state->interface) {
case PHY_INTERFACE_MODE_RGMII:
/* RGMII mode means no delay so don't enable the delay */
- qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
+ val |= QCA8K_PORT_PAD_RGMII_EN;
+ qca8k_write(priv, reg, val);
break;
case PHY_INTERFACE_MODE_RGMII_ID:
/* RGMII_ID needs internal delay. This is enabled through
* PORT5_PAD_CTRL for all ports, rather than individual port
* registers
*/
- qca8k_write(priv, reg,
- QCA8K_PORT_PAD_RGMII_EN |
- QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
- QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY));
+ val |= QCA8K_PORT_PAD_RGMII_EN |
+ QCA8K_PORT_PAD_RGMII_TX_DELAY(QCA8K_MAX_DELAY) |
+ QCA8K_PORT_PAD_RGMII_RX_DELAY(QCA8K_MAX_DELAY);
+ qca8k_write(priv, reg, val);
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
break;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
/* Enable SGMII on the port */
- qca8k_write(priv, reg, QCA8K_PORT_PAD_SGMII_EN);
+ val |= QCA8K_PORT_PAD_SGMII_EN;
+ qca8k_write(priv, reg, val);
/* Enable/disable SerDes auto-negotiation as necessary */
val = qca8k_read(priv, QCA8K_REG_PWS);
@@ -26,6 +26,9 @@
#define QCA8K_MASK_CTRL_ID_M 0xff
#define QCA8K_MASK_CTRL_ID_S 8
#define QCA8K_REG_PORT0_PAD_CTRL 0x004
+#define QCA8K_PORT0_PAD_CTRL_MAC06_EXCHG BIT(31)
+#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19)
+#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18)
#define QCA8K_REG_PORT5_PAD_CTRL 0x008
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
#define QCA8K_PORT_PAD_RGMII_EN BIT(26)
A number of devices require additional PORT0_PAD configuration that cannot otherwise be inferred. This patch is based on John Crispin's "net: dsa: qca8k: allow swapping of mac0 and mac6", adding the ability to swap mac0 and mac6, as well as to set the transmit and receive clock phase to falling edge. To keep things tidy, a function has been added to handle these device tree properties. However this handling could be moved to the qca8k_phylink_mac_config function if preferred. Signed-off-by: Matthew Hagan <mnhagan88@gmail.com> --- drivers/net/dsa/qca8k.c | 42 +++++++++++++++++++++++++++++++++++------ drivers/net/dsa/qca8k.h | 3 +++ 2 files changed, 39 insertions(+), 6 deletions(-)