123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- From 110c18bfed41421edd677935dd33be5e6507ba92 Mon Sep 17 00:00:00 2001
- From: Daniel Golle <[email protected]>
- Date: Mon, 3 Apr 2023 02:19:40 +0100
- Subject: [PATCH 16/16] net: dsa: mt7530: introduce driver for MT7988 built-in
- switch
- Add driver for the built-in Gigabit Ethernet switch which can be found
- in the MediaTek MT7988 SoC.
- The switch shares most of its design with MT7530 and MT7531, but has
- it's registers mapped into the SoCs register space rather than being
- connected externally or internally via MDIO.
- Introduce a new platform driver to support that.
- Signed-off-by: Daniel Golle <[email protected]>
- Reviewed-by: Andrew Lunn <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- MAINTAINERS | 2 +
- drivers/net/dsa/Kconfig | 12 +++
- drivers/net/dsa/Makefile | 1 +
- drivers/net/dsa/mt7530-mmio.c | 101 +++++++++++++++++++++++++
- drivers/net/dsa/mt7530.c | 137 +++++++++++++++++++++++++++++++++-
- drivers/net/dsa/mt7530.h | 12 +--
- 6 files changed, 255 insertions(+), 10 deletions(-)
- create mode 100644 drivers/net/dsa/mt7530-mmio.c
- --- a/MAINTAINERS
- +++ b/MAINTAINERS
- @@ -11899,9 +11899,11 @@ MEDIATEK SWITCH DRIVER
- M: Sean Wang <[email protected]>
- M: Landen Chao <[email protected]>
- M: DENG Qingfang <[email protected]>
- +M: Daniel Golle <[email protected]>
- L: [email protected]
- S: Maintained
- F: drivers/net/dsa/mt7530-mdio.c
- +F: drivers/net/dsa/mt7530-mmio.c
- F: drivers/net/dsa/mt7530.*
- F: net/dsa/tag_mtk.c
-
- --- a/drivers/net/dsa/Kconfig
- +++ b/drivers/net/dsa/Kconfig
- @@ -38,6 +38,7 @@ config NET_DSA_MT7530
- select NET_DSA_TAG_MTK
- select MEDIATEK_GE_PHY
- imply NET_DSA_MT7530_MDIO
- + imply NET_DSA_MT7530_MMIO
- help
- This enables support for the MediaTek MT7530 and MT7531 Ethernet
- switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
- @@ -54,6 +55,17 @@ config NET_DSA_MT7530_MDIO
- module MT7530 which can be found in the MT7621AT, MT7621DAT,
- MT7621ST and MT7623AI SoCs.
-
- +config NET_DSA_MT7530_MMIO
- + tristate "MediaTek MT7530 MMIO interface driver"
- + depends on NET_DSA_MT7530
- + depends on HAS_IOMEM
- + help
- + This enables support for the built-in Ethernet switch found
- + in the MediaTek MT7988 SoC.
- + The switch is a similar design as MT7531, but the switch registers
- + are directly mapped into the SoCs register space rather than being
- + accessible via MDIO.
- +
- config NET_DSA_MV88E6060
- tristate "Marvell 88E6060 ethernet switch chip support"
- select NET_DSA_TAG_TRAILER
- --- a/drivers/net/dsa/Makefile
- +++ b/drivers/net/dsa/Makefile
- @@ -8,6 +8,7 @@ endif
- obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
- obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
- obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
- +obj-$(CONFIG_NET_DSA_MT7530_MMIO) += mt7530-mmio.o
- obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
- obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
- realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
- --- /dev/null
- +++ b/drivers/net/dsa/mt7530-mmio.c
- @@ -0,0 +1,101 @@
- +// SPDX-License-Identifier: GPL-2.0-only
- +
- +#include <linux/module.h>
- +#include <linux/of_platform.h>
- +#include <linux/regmap.h>
- +#include <linux/regulator/consumer.h>
- +#include <linux/reset.h>
- +#include <net/dsa.h>
- +
- +#include "mt7530.h"
- +
- +static const struct of_device_id mt7988_of_match[] = {
- + { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
- + { /* sentinel */ },
- +};
- +MODULE_DEVICE_TABLE(of, mt7988_of_match);
- +
- +static int
- +mt7988_probe(struct platform_device *pdev)
- +{
- + static struct regmap_config *sw_regmap_config;
- + struct mt7530_priv *priv;
- + void __iomem *base_addr;
- + int ret;
- +
- + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- + if (!priv)
- + return -ENOMEM;
- +
- + priv->bus = NULL;
- + priv->dev = &pdev->dev;
- +
- + ret = mt7530_probe_common(priv);
- + if (ret)
- + return ret;
- +
- + priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
- + if (IS_ERR(priv->rstc)) {
- + dev_err(&pdev->dev, "Couldn't get our reset line\n");
- + return PTR_ERR(priv->rstc);
- + }
- +
- + base_addr = devm_platform_ioremap_resource(pdev, 0);
- + if (IS_ERR(base_addr)) {
- + dev_err(&pdev->dev, "cannot request I/O memory space\n");
- + return -ENXIO;
- + }
- +
- + sw_regmap_config = devm_kzalloc(&pdev->dev, sizeof(*sw_regmap_config), GFP_KERNEL);
- + if (!sw_regmap_config)
- + return -ENOMEM;
- +
- + sw_regmap_config->name = "switch";
- + sw_regmap_config->reg_bits = 16;
- + sw_regmap_config->val_bits = 32;
- + sw_regmap_config->reg_stride = 4;
- + sw_regmap_config->max_register = MT7530_CREV;
- + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base_addr, sw_regmap_config);
- + if (IS_ERR(priv->regmap))
- + return PTR_ERR(priv->regmap);
- +
- + return dsa_register_switch(priv->ds);
- +}
- +
- +static int
- +mt7988_remove(struct platform_device *pdev)
- +{
- + struct mt7530_priv *priv = platform_get_drvdata(pdev);
- +
- + if (priv)
- + mt7530_remove_common(priv);
- +
- + return 0;
- +}
- +
- +static void mt7988_shutdown(struct platform_device *pdev)
- +{
- + struct mt7530_priv *priv = platform_get_drvdata(pdev);
- +
- + if (!priv)
- + return;
- +
- + dsa_switch_shutdown(priv->ds);
- +
- + dev_set_drvdata(&pdev->dev, NULL);
- +}
- +
- +static struct platform_driver mt7988_platform_driver = {
- + .probe = mt7988_probe,
- + .remove = mt7988_remove,
- + .shutdown = mt7988_shutdown,
- + .driver = {
- + .name = "mt7530-mmio",
- + .of_match_table = mt7988_of_match,
- + },
- +};
- +module_platform_driver(mt7988_platform_driver);
- +
- +MODULE_AUTHOR("Daniel Golle <[email protected]>");
- +MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MMIO)");
- +MODULE_LICENSE("GPL");
- --- a/drivers/net/dsa/mt7530.c
- +++ b/drivers/net/dsa/mt7530.c
- @@ -1984,6 +1984,47 @@ static const struct irq_domain_ops mt753
- };
-
- static void
- +mt7988_irq_mask(struct irq_data *d)
- +{
- + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
- +
- + priv->irq_enable &= ~BIT(d->hwirq);
- + mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
- +}
- +
- +static void
- +mt7988_irq_unmask(struct irq_data *d)
- +{
- + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
- +
- + priv->irq_enable |= BIT(d->hwirq);
- + mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
- +}
- +
- +static struct irq_chip mt7988_irq_chip = {
- + .name = KBUILD_MODNAME,
- + .irq_mask = mt7988_irq_mask,
- + .irq_unmask = mt7988_irq_unmask,
- +};
- +
- +static int
- +mt7988_irq_map(struct irq_domain *domain, unsigned int irq,
- + irq_hw_number_t hwirq)
- +{
- + irq_set_chip_data(irq, domain->host_data);
- + irq_set_chip_and_handler(irq, &mt7988_irq_chip, handle_simple_irq);
- + irq_set_nested_thread(irq, true);
- + irq_set_noprobe(irq);
- +
- + return 0;
- +}
- +
- +static const struct irq_domain_ops mt7988_irq_domain_ops = {
- + .map = mt7988_irq_map,
- + .xlate = irq_domain_xlate_onecell,
- +};
- +
- +static void
- mt7530_setup_mdio_irq(struct mt7530_priv *priv)
- {
- struct dsa_switch *ds = priv->ds;
- @@ -2017,8 +2058,15 @@ mt7530_setup_irq(struct mt7530_priv *pri
- return priv->irq ? : -EINVAL;
- }
-
- - priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
- - &mt7530_irq_domain_ops, priv);
- + if (priv->id == ID_MT7988)
- + priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
- + &mt7988_irq_domain_ops,
- + priv);
- + else
- + priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
- + &mt7530_irq_domain_ops,
- + priv);
- +
- if (!priv->irq_domain) {
- dev_err(dev, "failed to create IRQ domain\n");
- return -ENOMEM;
- @@ -2511,6 +2559,25 @@ static void mt7531_mac_port_get_caps(str
- }
- }
-
- +static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port,
- + struct phylink_config *config)
- +{
- + phy_interface_zero(config->supported_interfaces);
- +
- + switch (port) {
- + case 0 ... 4: /* Internal phy */
- + __set_bit(PHY_INTERFACE_MODE_INTERNAL,
- + config->supported_interfaces);
- + break;
- +
- + case 6:
- + __set_bit(PHY_INTERFACE_MODE_INTERNAL,
- + config->supported_interfaces);
- + config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
- + MAC_10000FD;
- + }
- +}
- +
- static int
- mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
- {
- @@ -2587,6 +2654,17 @@ static bool mt753x_is_mac_port(u32 port)
- }
-
- static int
- +mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
- + phy_interface_t interface)
- +{
- + if (dsa_is_cpu_port(ds, port) &&
- + interface == PHY_INTERFACE_MODE_INTERNAL)
- + return 0;
- +
- + return -EINVAL;
- +}
- +
- +static int
- mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
- phy_interface_t interface)
- {
- @@ -2656,7 +2734,8 @@ mt753x_phylink_mac_config(struct dsa_swi
-
- switch (port) {
- case 0 ... 4: /* Internal phy */
- - if (state->interface != PHY_INTERFACE_MODE_GMII)
- + if (state->interface != PHY_INTERFACE_MODE_GMII &&
- + state->interface != PHY_INTERFACE_MODE_INTERNAL)
- goto unsupported;
- break;
- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
- @@ -2734,7 +2813,8 @@ static void mt753x_phylink_mac_link_up(s
- /* MT753x MAC works in 1G full duplex mode for all up-clocked
- * variants.
- */
- - if (interface == PHY_INTERFACE_MODE_TRGMII ||
- + if (interface == PHY_INTERFACE_MODE_INTERNAL ||
- + interface == PHY_INTERFACE_MODE_TRGMII ||
- (phy_interface_mode_is_8023z(interface))) {
- speed = SPEED_1000;
- duplex = DUPLEX_FULL;
- @@ -2814,6 +2894,21 @@ mt7531_cpu_port_config(struct dsa_switch
- return 0;
- }
-
- +static int
- +mt7988_cpu_port_config(struct dsa_switch *ds, int port)
- +{
- + struct mt7530_priv *priv = ds->priv;
- +
- + mt7530_write(priv, MT7530_PMCR_P(port),
- + PMCR_CPU_PORT_SETTING(priv->id));
- +
- + mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED,
- + PHY_INTERFACE_MODE_INTERNAL, NULL,
- + SPEED_10000, DUPLEX_FULL, true, true);
- +
- + return 0;
- +}
- +
- static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
- struct phylink_config *config)
- {
- @@ -2959,6 +3054,27 @@ static int mt753x_set_mac_eee(struct dsa
- return 0;
- }
-
- +static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
- +{
- + return 0;
- +}
- +
- +static int mt7988_setup(struct dsa_switch *ds)
- +{
- + struct mt7530_priv *priv = ds->priv;
- +
- + /* Reset the switch */
- + reset_control_assert(priv->rstc);
- + usleep_range(20, 50);
- + reset_control_deassert(priv->rstc);
- + usleep_range(20, 50);
- +
- + /* Reset the switch PHYs */
- + mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST);
- +
- + return mt7531_setup_common(ds);
- +}
- +
- const struct dsa_switch_ops mt7530_switch_ops = {
- .get_tag_protocol = mtk_get_tag_protocol,
- .setup = mt753x_setup,
- @@ -3027,6 +3143,17 @@ const struct mt753x_info mt753x_table[]
- .mac_port_get_caps = mt7531_mac_port_get_caps,
- .mac_port_config = mt7531_mac_config,
- },
- + [ID_MT7988] = {
- + .id = ID_MT7988,
- + .pcs_ops = &mt7530_pcs_ops,
- + .sw_setup = mt7988_setup,
- + .phy_read = mt7531_ind_phy_read,
- + .phy_write = mt7531_ind_phy_write,
- + .pad_setup = mt7988_pad_setup,
- + .cpu_port_config = mt7988_cpu_port_config,
- + .mac_port_get_caps = mt7988_mac_port_get_caps,
- + .mac_port_config = mt7988_mac_config,
- + },
- };
- EXPORT_SYMBOL_GPL(mt753x_table);
-
- --- a/drivers/net/dsa/mt7530.h
- +++ b/drivers/net/dsa/mt7530.h
- @@ -18,6 +18,7 @@ enum mt753x_id {
- ID_MT7530 = 0,
- ID_MT7621 = 1,
- ID_MT7531 = 2,
- + ID_MT7988 = 3,
- };
-
- #define NUM_TRGMII_CTRL 5
- @@ -54,11 +55,11 @@ enum mt753x_id {
- #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
- #define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
-
- -#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \
- +#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
- MT7531_CFC : MT7530_MFC)
- -#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \
- +#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
- MT7531_MIRROR_EN : MIRROR_EN)
- -#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \
- +#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
- MT7531_MIRROR_MASK : MIRROR_MASK)
-
- /* Registers for BPDU and PAE frame control*/
- @@ -295,9 +296,8 @@ enum mt7530_vlan_port_acc_frm {
- MT7531_FORCE_DPX | \
- MT7531_FORCE_RX_FC | \
- MT7531_FORCE_TX_FC)
- -#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \
- - MT7531_FORCE_MODE : \
- - PMCR_FORCE_MODE)
- +#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
- + MT7531_FORCE_MODE : PMCR_FORCE_MODE)
- #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
- PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \
- PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
|