123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477 |
- From 05dc5ea089f947a69a5db092ef4cad6a0f3c96ce Mon Sep 17 00:00:00 2001
- From: Daniel Golle <[email protected]>
- Date: Sun, 19 Mar 2023 12:58:43 +0000
- Subject: [PATCH 02/48] net: dsa: mt7530: use external PCS driver
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Implement regmap access wrappers, for now only to be used by the
- pcs-mtk-lynxi driver.
- Make use of this external PCS driver and drop the now reduntant
- implementation in mt7530.c.
- As a nice side effect the SGMII registers can now also more easily be
- inspected for debugging via /sys/kernel/debug/regmap.
- Tested-by: Bjørn Mork <[email protected]>
- Signed-off-by: Daniel Golle <[email protected]>
- Tested-by: Frank Wunderlich <[email protected]>
- Reviewed-by: Russell King (Oracle) <[email protected]>
- Signed-off-by: Jakub Kicinski <[email protected]>
- ---
- drivers/net/dsa/Kconfig | 1 +
- drivers/net/dsa/mt7530.c | 277 ++++++++++-----------------------------
- drivers/net/dsa/mt7530.h | 47 +------
- 3 files changed, 71 insertions(+), 254 deletions(-)
- --- a/drivers/net/dsa/Kconfig
- +++ b/drivers/net/dsa/Kconfig
- @@ -37,6 +37,7 @@ config NET_DSA_MT7530
- tristate "MediaTek MT753x and MT7621 Ethernet switch support"
- select NET_DSA_TAG_MTK
- select MEDIATEK_GE_PHY
- + select PCS_MTK_LYNXI
- help
- This enables support for the MediaTek MT7530, MT7531, and MT7621
- Ethernet switch chips.
- --- a/drivers/net/dsa/mt7530.c
- +++ b/drivers/net/dsa/mt7530.c
- @@ -14,6 +14,7 @@
- #include <linux/of_mdio.h>
- #include <linux/of_net.h>
- #include <linux/of_platform.h>
- +#include <linux/pcs/pcs-mtk-lynxi.h>
- #include <linux/phylink.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- @@ -2651,128 +2652,11 @@ static int mt7531_rgmii_setup(struct mt7
- return 0;
- }
-
- -static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
- - phy_interface_t interface, int speed, int duplex)
- -{
- - struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- - int port = pcs_to_mt753x_pcs(pcs)->port;
- - unsigned int val;
- -
- - /* For adjusting speed and duplex of SGMII force mode. */
- - if (interface != PHY_INTERFACE_MODE_SGMII ||
- - phylink_autoneg_inband(mode))
- - return;
- -
- - /* SGMII force mode setting */
- - val = mt7530_read(priv, MT7531_SGMII_MODE(port));
- - val &= ~MT7531_SGMII_IF_MODE_MASK;
- -
- - switch (speed) {
- - case SPEED_10:
- - val |= MT7531_SGMII_FORCE_SPEED_10;
- - break;
- - case SPEED_100:
- - val |= MT7531_SGMII_FORCE_SPEED_100;
- - break;
- - case SPEED_1000:
- - val |= MT7531_SGMII_FORCE_SPEED_1000;
- - break;
- - }
- -
- - /* MT7531 SGMII 1G force mode can only work in full duplex mode,
- - * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
- - *
- - * The speed check is unnecessary as the MAC capabilities apply
- - * this restriction. --rmk
- - */
- - if ((speed == SPEED_10 || speed == SPEED_100) &&
- - duplex != DUPLEX_FULL)
- - val |= MT7531_SGMII_FORCE_HALF_DUPLEX;
- -
- - mt7530_write(priv, MT7531_SGMII_MODE(port), val);
- -}
- -
- static bool mt753x_is_mac_port(u32 port)
- {
- return (port == 5 || port == 6);
- }
-
- -static int mt7531_sgmii_setup_mode_force(struct mt7530_priv *priv, u32 port,
- - phy_interface_t interface)
- -{
- - u32 val;
- -
- - if (!mt753x_is_mac_port(port))
- - return -EINVAL;
- -
- - mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
- - MT7531_SGMII_PHYA_PWD);
- -
- - val = mt7530_read(priv, MT7531_PHYA_CTRL_SIGNAL3(port));
- - val &= ~MT7531_RG_TPHY_SPEED_MASK;
- - /* Setup 2.5 times faster clock for 2.5Gbps data speeds with 10B/8B
- - * encoding.
- - */
- - val |= (interface == PHY_INTERFACE_MODE_2500BASEX) ?
- - MT7531_RG_TPHY_SPEED_3_125G : MT7531_RG_TPHY_SPEED_1_25G;
- - mt7530_write(priv, MT7531_PHYA_CTRL_SIGNAL3(port), val);
- -
- - mt7530_clear(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
- -
- - /* MT7531 SGMII 1G and 2.5G force mode can only work in full duplex
- - * mode, no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
- - */
- - mt7530_rmw(priv, MT7531_SGMII_MODE(port),
- - MT7531_SGMII_IF_MODE_MASK | MT7531_SGMII_REMOTE_FAULT_DIS,
- - MT7531_SGMII_FORCE_SPEED_1000);
- -
- - mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
- -
- - return 0;
- -}
- -
- -static int mt7531_sgmii_setup_mode_an(struct mt7530_priv *priv, int port,
- - phy_interface_t interface)
- -{
- - if (!mt753x_is_mac_port(port))
- - return -EINVAL;
- -
- - mt7530_set(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
- - MT7531_SGMII_PHYA_PWD);
- -
- - mt7530_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port),
- - MT7531_RG_TPHY_SPEED_MASK, MT7531_RG_TPHY_SPEED_1_25G);
- -
- - mt7530_set(priv, MT7531_SGMII_MODE(port),
- - MT7531_SGMII_REMOTE_FAULT_DIS |
- - MT7531_SGMII_SPEED_DUPLEX_AN);
- -
- - mt7530_rmw(priv, MT7531_PCS_SPEED_ABILITY(port),
- - MT7531_SGMII_TX_CONFIG_MASK, 1);
- -
- - mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_ENABLE);
- -
- - mt7530_set(priv, MT7531_PCS_CONTROL_1(port), MT7531_SGMII_AN_RESTART);
- -
- - mt7530_write(priv, MT7531_QPHY_PWR_STATE_CTRL(port), 0);
- -
- - return 0;
- -}
- -
- -static void mt7531_pcs_an_restart(struct phylink_pcs *pcs)
- -{
- - struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- - int port = pcs_to_mt753x_pcs(pcs)->port;
- - u32 val;
- -
- - /* Only restart AN when AN is enabled */
- - val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- - if (val & MT7531_SGMII_AN_ENABLE) {
- - val |= MT7531_SGMII_AN_RESTART;
- - mt7530_write(priv, MT7531_PCS_CONTROL_1(port), val);
- - }
- -}
- -
- static int
- mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
- phy_interface_t interface)
- @@ -2795,11 +2679,11 @@ mt7531_mac_config(struct dsa_switch *ds,
- phydev = dp->slave->phydev;
- return mt7531_rgmii_setup(priv, port, interface, phydev);
- case PHY_INTERFACE_MODE_SGMII:
- - return mt7531_sgmii_setup_mode_an(priv, port, interface);
- case PHY_INTERFACE_MODE_NA:
- case PHY_INTERFACE_MODE_1000BASEX:
- case PHY_INTERFACE_MODE_2500BASEX:
- - return mt7531_sgmii_setup_mode_force(priv, port, interface);
- + /* handled in SGMII PCS driver */
- + return 0;
- default:
- return -EINVAL;
- }
- @@ -2824,11 +2708,11 @@ mt753x_phylink_mac_select_pcs(struct dsa
-
- switch (interface) {
- case PHY_INTERFACE_MODE_TRGMII:
- + return &priv->pcs[port].pcs;
- case PHY_INTERFACE_MODE_SGMII:
- case PHY_INTERFACE_MODE_1000BASEX:
- case PHY_INTERFACE_MODE_2500BASEX:
- - return &priv->pcs[port].pcs;
- -
- + return priv->ports[port].sgmii_pcs;
- default:
- return NULL;
- }
- @@ -3066,86 +2950,6 @@ static void mt7530_pcs_get_state(struct
- state->pause |= MLO_PAUSE_TX;
- }
-
- -static int
- -mt7531_sgmii_pcs_get_state_an(struct mt7530_priv *priv, int port,
- - struct phylink_link_state *state)
- -{
- - u32 status, val;
- - u16 config_reg;
- -
- - status = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- - state->link = !!(status & MT7531_SGMII_LINK_STATUS);
- - state->an_complete = !!(status & MT7531_SGMII_AN_COMPLETE);
- - if (state->interface == PHY_INTERFACE_MODE_SGMII &&
- - (status & MT7531_SGMII_AN_ENABLE)) {
- - val = mt7530_read(priv, MT7531_PCS_SPEED_ABILITY(port));
- - config_reg = val >> 16;
- -
- - switch (config_reg & LPA_SGMII_SPD_MASK) {
- - case LPA_SGMII_1000:
- - state->speed = SPEED_1000;
- - break;
- - case LPA_SGMII_100:
- - state->speed = SPEED_100;
- - break;
- - case LPA_SGMII_10:
- - state->speed = SPEED_10;
- - break;
- - default:
- - dev_err(priv->dev, "invalid sgmii PHY speed\n");
- - state->link = false;
- - return -EINVAL;
- - }
- -
- - if (config_reg & LPA_SGMII_FULL_DUPLEX)
- - state->duplex = DUPLEX_FULL;
- - else
- - state->duplex = DUPLEX_HALF;
- - }
- -
- - return 0;
- -}
- -
- -static void
- -mt7531_sgmii_pcs_get_state_inband(struct mt7530_priv *priv, int port,
- - struct phylink_link_state *state)
- -{
- - unsigned int val;
- -
- - val = mt7530_read(priv, MT7531_PCS_CONTROL_1(port));
- - state->link = !!(val & MT7531_SGMII_LINK_STATUS);
- - if (!state->link)
- - return;
- -
- - state->an_complete = state->link;
- -
- - if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
- - state->speed = SPEED_2500;
- - else
- - state->speed = SPEED_1000;
- -
- - state->duplex = DUPLEX_FULL;
- - state->pause = MLO_PAUSE_NONE;
- -}
- -
- -static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
- - struct phylink_link_state *state)
- -{
- - struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
- - int port = pcs_to_mt753x_pcs(pcs)->port;
- -
- - if (state->interface == PHY_INTERFACE_MODE_SGMII) {
- - mt7531_sgmii_pcs_get_state_an(priv, port, state);
- - return;
- - } else if ((state->interface == PHY_INTERFACE_MODE_1000BASEX) ||
- - (state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
- - mt7531_sgmii_pcs_get_state_inband(priv, port, state);
- - return;
- - }
- -
- - state->link = false;
- -}
- -
- static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
- phy_interface_t interface,
- const unsigned long *advertising,
- @@ -3165,18 +2969,57 @@ static const struct phylink_pcs_ops mt75
- .pcs_an_restart = mt7530_pcs_an_restart,
- };
-
- -static const struct phylink_pcs_ops mt7531_pcs_ops = {
- - .pcs_validate = mt753x_pcs_validate,
- - .pcs_get_state = mt7531_pcs_get_state,
- - .pcs_config = mt753x_pcs_config,
- - .pcs_an_restart = mt7531_pcs_an_restart,
- - .pcs_link_up = mt7531_pcs_link_up,
- +static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
- +{
- + struct mt7530_priv *priv = context;
- +
- + *val = mt7530_read(priv, reg);
- + return 0;
- +};
- +
- +static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
- +{
- + struct mt7530_priv *priv = context;
- +
- + mt7530_write(priv, reg, val);
- + return 0;
- +};
- +
- +static int mt7530_regmap_update_bits(void *context, unsigned int reg,
- + unsigned int mask, unsigned int val)
- +{
- + struct mt7530_priv *priv = context;
- +
- + mt7530_rmw(priv, reg, mask, val);
- + return 0;
- +};
- +
- +static const struct regmap_bus mt7531_regmap_bus = {
- + .reg_write = mt7530_regmap_write,
- + .reg_read = mt7530_regmap_read,
- + .reg_update_bits = mt7530_regmap_update_bits,
- +};
- +
- +#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \
- + { \
- + .name = _name, \
- + .reg_bits = 16, \
- + .val_bits = 32, \
- + .reg_stride = 4, \
- + .reg_base = _reg_base, \
- + .max_register = 0x17c, \
- + }
- +
- +static const struct regmap_config mt7531_pcs_config[] = {
- + MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)),
- + MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)),
- };
-
- static int
- mt753x_setup(struct dsa_switch *ds)
- {
- struct mt7530_priv *priv = ds->priv;
- + struct regmap *regmap;
- int i, ret;
-
- /* Initialise the PCS devices */
- @@ -3184,8 +3027,6 @@ mt753x_setup(struct dsa_switch *ds)
- priv->pcs[i].pcs.ops = priv->info->pcs_ops;
- priv->pcs[i].priv = priv;
- priv->pcs[i].port = i;
- - if (mt753x_is_mac_port(i))
- - priv->pcs[i].pcs.poll = 1;
- }
-
- ret = priv->info->sw_setup(ds);
- @@ -3200,6 +3041,16 @@ mt753x_setup(struct dsa_switch *ds)
- if (ret && priv->irq)
- mt7530_free_irq_common(priv);
-
- + if (priv->id == ID_MT7531)
- + for (i = 0; i < 2; i++) {
- + regmap = devm_regmap_init(ds->dev,
- + &mt7531_regmap_bus, priv,
- + &mt7531_pcs_config[i]);
- + priv->ports[5 + i].sgmii_pcs =
- + mtk_pcs_lynxi_create(ds->dev, regmap,
- + MT7531_PHYA_CTRL_SIGNAL3, 0);
- + }
- +
- return ret;
- }
-
- @@ -3291,7 +3142,7 @@ static const struct mt753x_info mt753x_t
- },
- [ID_MT7531] = {
- .id = ID_MT7531,
- - .pcs_ops = &mt7531_pcs_ops,
- + .pcs_ops = &mt7530_pcs_ops,
- .sw_setup = mt7531_setup,
- .phy_read = mt7531_ind_phy_read,
- .phy_write = mt7531_ind_phy_write,
- @@ -3399,7 +3250,7 @@ static void
- mt7530_remove(struct mdio_device *mdiodev)
- {
- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
- - int ret = 0;
- + int ret = 0, i;
-
- if (!priv)
- return;
- @@ -3418,6 +3269,10 @@ mt7530_remove(struct mdio_device *mdiode
- mt7530_free_irq(priv);
-
- dsa_unregister_switch(priv->ds);
- +
- + for (i = 0; i < 2; ++i)
- + mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
- +
- mutex_destroy(&priv->reg_mutex);
- }
-
- --- a/drivers/net/dsa/mt7530.h
- +++ b/drivers/net/dsa/mt7530.h
- @@ -391,47 +391,8 @@ enum mt7530_vlan_port_acc_frm {
- CCR_TX_OCT_CNT_BAD)
-
- /* MT7531 SGMII register group */
- -#define MT7531_SGMII_REG_BASE 0x5000
- -#define MT7531_SGMII_REG(p, r) (MT7531_SGMII_REG_BASE + \
- - ((p) - 5) * 0x1000 + (r))
- -
- -/* Register forSGMII PCS_CONTROL_1 */
- -#define MT7531_PCS_CONTROL_1(p) MT7531_SGMII_REG(p, 0x00)
- -#define MT7531_SGMII_LINK_STATUS BIT(18)
- -#define MT7531_SGMII_AN_ENABLE BIT(12)
- -#define MT7531_SGMII_AN_RESTART BIT(9)
- -#define MT7531_SGMII_AN_COMPLETE BIT(21)
- -
- -/* Register for SGMII PCS_SPPED_ABILITY */
- -#define MT7531_PCS_SPEED_ABILITY(p) MT7531_SGMII_REG(p, 0x08)
- -#define MT7531_SGMII_TX_CONFIG_MASK GENMASK(15, 0)
- -#define MT7531_SGMII_TX_CONFIG BIT(0)
- -
- -/* Register for SGMII_MODE */
- -#define MT7531_SGMII_MODE(p) MT7531_SGMII_REG(p, 0x20)
- -#define MT7531_SGMII_REMOTE_FAULT_DIS BIT(8)
- -#define MT7531_SGMII_IF_MODE_MASK GENMASK(5, 1)
- -#define MT7531_SGMII_FORCE_DUPLEX BIT(4)
- -#define MT7531_SGMII_FORCE_SPEED_MASK GENMASK(3, 2)
- -#define MT7531_SGMII_FORCE_SPEED_1000 BIT(3)
- -#define MT7531_SGMII_FORCE_SPEED_100 BIT(2)
- -#define MT7531_SGMII_FORCE_SPEED_10 0
- -#define MT7531_SGMII_SPEED_DUPLEX_AN BIT(1)
- -
- -enum mt7531_sgmii_force_duplex {
- - MT7531_SGMII_FORCE_FULL_DUPLEX = 0,
- - MT7531_SGMII_FORCE_HALF_DUPLEX = 0x10,
- -};
- -
- -/* Fields of QPHY_PWR_STATE_CTRL */
- -#define MT7531_QPHY_PWR_STATE_CTRL(p) MT7531_SGMII_REG(p, 0xe8)
- -#define MT7531_SGMII_PHYA_PWD BIT(4)
- -
- -/* Values of SGMII SPEED */
- -#define MT7531_PHYA_CTRL_SIGNAL3(p) MT7531_SGMII_REG(p, 0x128)
- -#define MT7531_RG_TPHY_SPEED_MASK (BIT(2) | BIT(3))
- -#define MT7531_RG_TPHY_SPEED_1_25G 0x0
- -#define MT7531_RG_TPHY_SPEED_3_125G BIT(2)
- +#define MT7531_SGMII_REG_BASE(p) (0x5000 + ((p) - 5) * 0x1000)
- +#define MT7531_PHYA_CTRL_SIGNAL3 0x128
-
- /* Register for system reset */
- #define MT7530_SYS_CTRL 0x7000
- @@ -730,13 +691,13 @@ struct mt7530_fdb {
- * @pm: The matrix used to show all connections with the port.
- * @pvid: The VLAN specified is to be considered a PVID at ingress. Any
- * untagged frames will be assigned to the related VLAN.
- - * @vlan_filtering: The flags indicating whether the port that can recognize
- - * VLAN-tagged frames.
- + * @sgmii_pcs: Pointer to PCS instance for SerDes ports
- */
- struct mt7530_port {
- bool enable;
- u32 pm;
- u16 pvid;
- + struct phylink_pcs *sgmii_pcs;
- };
-
- /* Port 5 interface select definitions */
|