diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-05-09 05:10:13 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-05-09 05:10:13 +0300 |
| commit | 8b2feced65cd3aa0597d596ed5733a1abd4c4d78 (patch) | |
| tree | 80edb590541abf4b985ce1e997fcfb02603a056b | |
| parent | 50223dfd66526052aad4eef3465de2d9094b9f72 (diff) | |
| parent | 1df461e527477068e5f3773e645d555120704be6 (diff) | |
| download | linux-8b2feced65cd3aa0597d596ed5733a1abd4c4d78.tar.xz | |
Merge branch 'net-dsa-microchip-remove-one-indirection-layer'
Bastien Curutchet says:
====================
net: dsa: microchip: Remove one indirection layer
This series follows the discussions we had on a previous series that
aimed to add PTP support for the KSZ8463 (cf [1]).
The KSZ driver got way too convoluted over time because it uses a common
framework to handle more than 20 switches split in 5 families (see below
table)
+----------+---------+---------+---------+---------+---------+
| Family | KSZ8463 | KSZ87xx | KSZ88xx | KSZ9477 | LAN937X |
+----------+---------+---------+---------+---------+---------+
| Switches | KSZ8463 | KSZ8795 | KSZ88X3 | KSZ8563 | LAN9370 |
| | | KSZ8794 | KSZ8864 | KSZ9477 | LAN9371 |
| | | KSZ8765 | KSZ8895 | KSZ9896 | LAN9372 |
| | | | | KSZ9897 | LAN9373 |
| | | | | KSZ9893 | LAN9374 |
| | | | | KSZ9563 | |
| | | | | KSZ8567 | |
| | | | | KSZ9567 | |
| | | | | LAN9646 | |
+----------+---------+---------+---------+---------+---------+
A unique struct dsa_switch_ops is used by all the switches. Next to it,
each switch family has its own struct ksz_dev_ops with family-specific
callbacks. So the dsa_switch_ops operations handle the specificities of
each family through these ksz_dev_ops callbacks and/or conditional
branches based on the chip ID.
Vladimir initiated a rework of the driver ([2]) which I carried on. On
top of the rework I added PTP and periodic output support for the
KSZ8463 (which was my first goal). There are more than 60 patches for
all this so this series will be followed by several others and if you
want to see the full picture we can check my github ([3]).
This first series aims to split the unique struct dsa_switch_ops into
5 so each switch family will be able to implement its own set of DSA
operations.
I haven't finished yet to group all the patches into meaningful series
but here is more or less what I plan to do next:
- A series will remove from the struct ksz_dev_ops the callbacks
that have an equivalent in dsa_switch_ops to remove one level of
indirection.
- A series will split again some operations to get rid of the
if (is_kszXYZ) branches.
- Maybe a fourth one will be needed to completely move out of
ksz_common.c everything that isn't truly common to all the switches
- A series will add PTP support for the KSZ8463
- A final series will add periodic output support for the KSZ8463
[1]: https://lore.kernel.org/r/20260304-ksz8463-ptp-v6-0-3f4c47954c71@bootlin.com)
[2]: https://github.com/vladimiroltean/linux/tree/ksz_separate_dsa_switch_ops
[3]: https://github.com/bastien-curutchet/linux/tree/ksz_rework
====================
Link: https://patch.msgid.link/20260505-clean-ksz-driver-v1-0-05d70fa42461@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/dsa/microchip/ksz8.c | 506 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz8.h | 62 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz8863_smi.c | 8 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz9477.c | 283 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz9477.h | 24 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz9477_i2c.c | 8 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz_common.c | 672 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz_common.h | 106 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/ksz_spi.c | 8 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/lan937x.h | 21 | ||||
| -rw-r--r-- | drivers/net/dsa/microchip/lan937x_main.c | 164 |
11 files changed, 1108 insertions, 754 deletions
diff --git a/drivers/net/dsa/microchip/ksz8.c b/drivers/net/dsa/microchip/ksz8.c index c354abdafc1b..abee0dc5ec04 100644 --- a/drivers/net/dsa/microchip/ksz8.c +++ b/drivers/net/dsa/microchip/ksz8.c @@ -16,6 +16,7 @@ #include <linux/bitfield.h> #include <linux/delay.h> +#include <linux/dsa/ksz_common.h> #include <linux/export.h> #include <linux/gpio.h> #include <linux/if_vlan.h> @@ -31,6 +32,7 @@ #include <linux/phylink.h> #include "ksz_common.h" +#include "ksz_dcb.h" #include "ksz8_reg.h" #include "ksz8.h" @@ -114,26 +116,26 @@ static int ksz8_ind_read8(struct ksz_device *dev, u8 table, u16 addr, u8 *val) return ret; } -int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value) +static int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value) { return ksz8_ind_write8(dev, (u8)(reg >> 8), (u8)(reg), value); } -int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data) +static int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data) { u8 table = (u8)(offset >> 8 | (port + 1)); return ksz8_ind_read8(dev, table, (u8)(offset), data); } -int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data) +static int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data) { u8 table = (u8)(offset >> 8 | (port + 1)); return ksz8_ind_write8(dev, table, (u8)(offset), data); } -int ksz8_reset_switch(struct ksz_device *dev) +static int ksz8_reset_switch(struct ksz_device *dev) { if (ksz_is_ksz88x3(dev)) { /* reset switch */ @@ -186,7 +188,7 @@ static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size) return ksz_rmw8(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, ctrl2); } -int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) +static int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu) { u16 frame_size; @@ -267,22 +269,7 @@ static int ksz8_port_queue_split(struct ksz_device *dev, int port, int queues) return ksz_prmw8(dev, port, reg_2q, mask_2q, data_2q); } -int ksz8_all_queues_split(struct ksz_device *dev, int queues) -{ - struct dsa_switch *ds = dev->ds; - const struct dsa_port *dp; - - dsa_switch_for_each_port(dp, ds) { - int ret = ksz8_port_queue_split(dev, dp->index, queues); - - if (ret) - return ret; - } - - return 0; -} - -void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) +static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) { const u32 *masks; const u16 *regs; @@ -405,8 +392,8 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, } } -void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, - u64 *dropped, u64 *cnt) +static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) { if (is_ksz88xx(dev)) ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt); @@ -414,7 +401,7 @@ void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt); } -void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) +static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) { if (is_ksz88xx(dev)) return; @@ -429,7 +416,7 @@ void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); } -void ksz8_port_init_cnt(struct ksz_device *dev, int port) +static void ksz8_port_init_cnt(struct ksz_device *dev, int port) { struct ksz_port_mib *mib = &dev->ports[port].mib; u64 *dropped; @@ -954,7 +941,7 @@ static int ksz8_r_phy_bmcr(struct ksz_device *dev, u16 port, u16 *val) return 0; } -int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) +static int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) { u8 ctrl, link, val1, val2; int processed = true; @@ -1218,7 +1205,7 @@ static int ksz8_w_phy_bmcr(struct ksz_device *dev, u16 port, u16 val) restart); } -int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) +static int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) { const u16 *regs; u8 ctrl, data; @@ -1278,7 +1265,7 @@ int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) return 0; } -void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) +static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) { int offset = P_MIRROR_CTRL; u8 data; @@ -1291,7 +1278,7 @@ void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member) ksz_pwrite8(dev, port, offset, data); } -void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) +static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) { u8 learn[DSA_MAX_PORTS]; int first, index, cnt; @@ -1326,8 +1313,8 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) } } -int ksz8_fdb_dump(struct ksz_device *dev, int port, - dsa_fdb_dump_cb_t *cb, void *data) +static int ksz8_fdb_dump(struct ksz_device *dev, int port, + dsa_fdb_dump_cb_t *cb, void *data) { u8 mac[ETH_ALEN]; u8 src_port, fid; @@ -1431,32 +1418,34 @@ static int ksz8_del_sta_mac(struct ksz_device *dev, int port, return ksz8_w_sta_mac_table(dev, index, &alu); } -int ksz8_mdb_add(struct ksz_device *dev, int port, - const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) +static int ksz8_mdb_add(struct ksz_device *dev, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) { return ksz8_add_sta_mac(dev, port, mdb->addr, mdb->vid); } -int ksz8_mdb_del(struct ksz_device *dev, int port, - const struct switchdev_obj_port_mdb *mdb, struct dsa_db db) +static int ksz8_mdb_del(struct ksz_device *dev, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) { return ksz8_del_sta_mac(dev, port, mdb->addr, mdb->vid); } -int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr, - u16 vid, struct dsa_db db) +static int ksz8_fdb_add(struct ksz_device *dev, int port, + const unsigned char *addr, u16 vid, struct dsa_db db) { return ksz8_add_sta_mac(dev, port, addr, vid); } -int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr, - u16 vid, struct dsa_db db) +static int ksz8_fdb_del(struct ksz_device *dev, int port, + const unsigned char *addr, u16 vid, struct dsa_db db) { return ksz8_del_sta_mac(dev, port, addr, vid); } -int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, - struct netlink_ext_ack *extack) +static int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, + struct netlink_ext_ack *extack) { if (ksz_is_ksz88x3(dev) || ksz_is_ksz8463(dev)) return -ENOTSUPP; @@ -1485,9 +1474,9 @@ static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state) } } -int ksz8_port_vlan_add(struct ksz_device *dev, int port, - const struct switchdev_obj_port_vlan *vlan, - struct netlink_ext_ack *extack) +static int ksz8_port_vlan_add(struct ksz_device *dev, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_port *p = &dev->ports[port]; @@ -1557,8 +1546,8 @@ int ksz8_port_vlan_add(struct ksz_device *dev, int port, return 0; } -int ksz8_port_vlan_del(struct ksz_device *dev, int port, - const struct switchdev_obj_port_vlan *vlan) +static int ksz8_port_vlan_del(struct ksz_device *dev, int port, + const struct switchdev_obj_port_vlan *vlan) { u16 data, pvid; u8 fid, member, valid; @@ -1589,9 +1578,9 @@ int ksz8_port_vlan_del(struct ksz_device *dev, int port, return 0; } -int ksz8_port_mirror_add(struct ksz_device *dev, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress, struct netlink_ext_ack *extack) +static int ksz8_port_mirror_add(struct ksz_device *dev, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack) { int offset = P_MIRROR_CTRL; @@ -1615,8 +1604,8 @@ int ksz8_port_mirror_add(struct ksz_device *dev, int port, return 0; } -void ksz8_port_mirror_del(struct ksz_device *dev, int port, - struct dsa_mall_mirror_tc_entry *mirror) +static void ksz8_port_mirror_del(struct ksz_device *dev, int port, + struct dsa_mall_mirror_tc_entry *mirror) { int offset = P_MIRROR_CTRL; u8 data; @@ -1654,7 +1643,7 @@ static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port) } } -void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) +static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) { const u16 *regs = dev->info->regs; struct dsa_switch *ds = dev->ds; @@ -1709,7 +1698,7 @@ static void ksz88x3_config_rmii_clk(struct ksz_device *dev) KSZ88X3_PORT3_RMII_CLK_INTERNAL, rmii_clk_internal); } -void ksz8_config_cpu_port(struct dsa_switch *ds) +static void ksz8_config_cpu_port(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; struct ksz_port *p; @@ -1883,10 +1872,12 @@ static void ksz8_cpu_port_link_up(struct ksz_device *dev, int speed, int duplex, SW_10_MBIT, ctrl); } -void ksz8_phylink_mac_link_up(struct phylink_config *config, - struct phy_device *phydev, unsigned int mode, - phy_interface_t interface, int speed, int duplex, - bool tx_pause, bool rx_pause) +static void ksz8_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) { struct dsa_port *dp = dsa_phylink_to_port(config); struct ksz_device *dev = dp->ds->priv; @@ -1918,7 +1909,7 @@ static int ksz8_handle_global_errata(struct dsa_switch *ds) return ret; } -int ksz8_enable_stp_addr(struct ksz_device *dev) +static int ksz8_enable_stp_addr(struct ksz_device *dev) { struct alu_struct alu; @@ -1932,7 +1923,7 @@ int ksz8_enable_stp_addr(struct ksz_device *dev) return ksz8_w_sta_mac_table(dev, 0, &alu); } -int ksz8_setup(struct dsa_switch *ds) +static int ksz8_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; const u16 *regs = dev->info->regs; @@ -1995,8 +1986,8 @@ int ksz8_setup(struct dsa_switch *ds) return ret; } -void ksz8_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config) +static void ksz8_get_caps(struct ksz_device *dev, int port, + struct phylink_config *config) { config->mac_capabilities = MAC_10 | MAC_100; @@ -2013,12 +2004,12 @@ void ksz8_get_caps(struct ksz_device *dev, int port, config->mac_capabilities |= MAC_ASYM_PAUSE; } -u32 ksz8_get_port_addr(int port, int offset) +static u32 ksz8_get_port_addr(int port, int offset) { return PORT_CTRL_ADDR(port, offset); } -u32 ksz8463_get_port_addr(int port, int offset) +static u32 ksz8463_get_port_addr(int port, int offset) { return offset + 0x18 * port; } @@ -2028,7 +2019,7 @@ static u16 ksz8463_get_phy_addr(u16 phy, u16 reg, u16 offset) return offset + reg * 2 + phy * (P2MBCR - P1MBCR); } -int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) +static int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) { u16 sw_reg = 0; u16 data = 0; @@ -2068,7 +2059,7 @@ int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) return 0; } -int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) +static int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) { u16 sw_reg = 0; int ret; @@ -2096,7 +2087,7 @@ int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) return 0; } -int ksz8_switch_init(struct ksz_device *dev) +static int ksz8_switch_init(struct ksz_device *dev) { dev->cpu_port = fls(dev->info->cpu_ports) - 1; dev->phy_port_cnt = dev->info->port_cnt - 1; @@ -2105,11 +2096,392 @@ int ksz8_switch_init(struct ksz_device *dev) return 0; } -void ksz8_switch_exit(struct ksz_device *dev) +static void ksz8_switch_exit(struct ksz_device *dev) { ksz8_reset_switch(dev); } +static enum dsa_tag_protocol ksz8463_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) +{ + return DSA_TAG_PROTO_KSZ9893; +} + +static int ksz8463_connect_tag_protocol(struct dsa_switch *ds, + enum dsa_tag_protocol proto) +{ + struct ksz_tagger_data *tagger_data; + + if (proto != DSA_TAG_PROTO_KSZ9893) + return -EPROTONOSUPPORT; + + tagger_data = ksz_tagger_data(ds); + tagger_data->xmit_work_fn = ksz_port_deferred_xmit; + + return 0; +} + +static enum dsa_tag_protocol ksz87xx_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) +{ + return DSA_TAG_PROTO_KSZ8795; +} + +static int ksz87xx_connect_tag_protocol(struct dsa_switch *ds, + enum dsa_tag_protocol proto) +{ + if (proto != DSA_TAG_PROTO_KSZ8795) + return -EPROTONOSUPPORT; + + return 0; +} + +static enum dsa_tag_protocol ksz88xx_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) +{ + struct ksz_device *dev = ds->priv; + + if (ksz_is_8895_family(dev)) /* KSZ8864, KSZ8895 */ + return DSA_TAG_PROTO_KSZ8795; + + return DSA_TAG_PROTO_KSZ9893; +} + +static int ksz88xx_connect_tag_protocol(struct dsa_switch *ds, + enum dsa_tag_protocol proto) +{ + struct ksz_tagger_data *tagger_data; + + if (ksz_is_8895_family(ds->priv)) { /* KSZ8864, KSZ8895 */ + if (proto != DSA_TAG_PROTO_KSZ8795) + return -EPROTONOSUPPORT; + + return 0; + } + + if (proto != DSA_TAG_PROTO_KSZ9893) + return -EPROTONOSUPPORT; + + tagger_data = ksz_tagger_data(ds); + tagger_data->xmit_work_fn = ksz_port_deferred_xmit; + + return 0; +} + +static void ksz88x3_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct ksz_device *dev = dp->ds->priv; + + dev->ports[dp->index].manual_flow = !(state->pause & MLO_PAUSE_AN); +} + +const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { + .mac_config = ksz88x3_phylink_mac_config, + .mac_link_down = ksz_phylink_mac_link_down, + .mac_link_up = ksz8_phylink_mac_link_up, + .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, + .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, +}; + +const struct phylink_mac_ops ksz8_phylink_mac_ops = { + .mac_config = ksz_phylink_mac_config, + .mac_link_down = ksz_phylink_mac_link_down, + .mac_link_up = ksz8_phylink_mac_link_up, + .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, + .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, +}; + +const struct ksz_dev_ops ksz8463_dev_ops = { + .setup = ksz8_setup, + .get_port_addr = ksz8463_get_port_addr, + .cfg_port_member = ksz8_cfg_port_member, + .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, + .port_setup = ksz8_port_setup, + .r_phy = ksz8463_r_phy, + .w_phy = ksz8463_w_phy, + .r_mib_cnt = ksz8_r_mib_cnt, + .r_mib_pkt = ksz8_r_mib_pkt, + .r_mib_stat64 = ksz88xx_r_mib_stats64, + .freeze_mib = ksz8_freeze_mib, + .port_init_cnt = ksz8_port_init_cnt, + .fdb_dump = ksz8_fdb_dump, + .fdb_add = ksz8_fdb_add, + .fdb_del = ksz8_fdb_del, + .mdb_add = ksz8_mdb_add, + .mdb_del = ksz8_mdb_del, + .vlan_filtering = ksz8_port_vlan_filtering, + .vlan_add = ksz8_port_vlan_add, + .vlan_del = ksz8_port_vlan_del, + .mirror_add = ksz8_port_mirror_add, + .mirror_del = ksz8_port_mirror_del, + .get_caps = ksz8_get_caps, + .config_cpu_port = ksz8_config_cpu_port, + .enable_stp_addr = ksz8_enable_stp_addr, + .reset = ksz8_reset_switch, + .init = ksz8_switch_init, + .exit = ksz8_switch_exit, + .change_mtu = ksz8_change_mtu, +}; + +const struct ksz_dev_ops ksz87xx_dev_ops = { + .setup = ksz8_setup, + .get_port_addr = ksz8_get_port_addr, + .cfg_port_member = ksz8_cfg_port_member, + .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, + .port_setup = ksz8_port_setup, + .r_phy = ksz8_r_phy, + .w_phy = ksz8_w_phy, + .r_mib_cnt = ksz8_r_mib_cnt, + .r_mib_pkt = ksz8_r_mib_pkt, + .r_mib_stat64 = ksz_r_mib_stats64, + .freeze_mib = ksz8_freeze_mib, + .port_init_cnt = ksz8_port_init_cnt, + .fdb_dump = ksz8_fdb_dump, + .fdb_add = ksz8_fdb_add, + .fdb_del = ksz8_fdb_del, + .mdb_add = ksz8_mdb_add, + .mdb_del = ksz8_mdb_del, + .vlan_filtering = ksz8_port_vlan_filtering, + .vlan_add = ksz8_port_vlan_add, + .vlan_del = ksz8_port_vlan_del, + .mirror_add = ksz8_port_mirror_add, + .mirror_del = ksz8_port_mirror_del, + .get_caps = ksz8_get_caps, + .config_cpu_port = ksz8_config_cpu_port, + .enable_stp_addr = ksz8_enable_stp_addr, + .reset = ksz8_reset_switch, + .init = ksz8_switch_init, + .exit = ksz8_switch_exit, + .change_mtu = ksz8_change_mtu, + .pme_write8 = ksz8_pme_write8, + .pme_pread8 = ksz8_pme_pread8, + .pme_pwrite8 = ksz8_pme_pwrite8, +}; + +const struct ksz_dev_ops ksz88xx_dev_ops = { + .setup = ksz8_setup, + .get_port_addr = ksz8_get_port_addr, + .cfg_port_member = ksz8_cfg_port_member, + .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, + .port_setup = ksz8_port_setup, + .r_phy = ksz8_r_phy, + .w_phy = ksz8_w_phy, + .r_mib_cnt = ksz8_r_mib_cnt, + .r_mib_pkt = ksz8_r_mib_pkt, + .r_mib_stat64 = ksz88xx_r_mib_stats64, + .freeze_mib = ksz8_freeze_mib, + .port_init_cnt = ksz8_port_init_cnt, + .fdb_dump = ksz8_fdb_dump, + .fdb_add = ksz8_fdb_add, + .fdb_del = ksz8_fdb_del, + .mdb_add = ksz8_mdb_add, + .mdb_del = ksz8_mdb_del, + .vlan_filtering = ksz8_port_vlan_filtering, + .vlan_add = ksz8_port_vlan_add, + .vlan_del = ksz8_port_vlan_del, + .mirror_add = ksz8_port_mirror_add, + .mirror_del = ksz8_port_mirror_del, + .get_caps = ksz8_get_caps, + .config_cpu_port = ksz8_config_cpu_port, + .enable_stp_addr = ksz8_enable_stp_addr, + .reset = ksz8_reset_switch, + .init = ksz8_switch_init, + .exit = ksz8_switch_exit, + .change_mtu = ksz8_change_mtu, + .pme_write8 = ksz8_pme_write8, + .pme_pread8 = ksz8_pme_pread8, + .pme_pwrite8 = ksz8_pme_pwrite8, +}; + +const struct dsa_switch_ops ksz8463_switch_ops = { + .get_tag_protocol = ksz8463_get_tag_protocol, + .connect_tag_protocol = ksz8463_connect_tag_protocol, + .get_phy_flags = ksz_get_phy_flags, + .setup = ksz_setup, + .teardown = ksz_teardown, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .phylink_get_caps = ksz_phylink_get_caps, + .port_setup = ksz_port_setup, + .set_ageing_time = ksz_set_ageing_time, + .get_strings = ksz_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_hsr_join = ksz_hsr_join, + .port_hsr_leave = ksz_hsr_leave, + .port_set_mac_address = ksz_port_set_mac_address, + .port_stp_state_set = ksz_port_stp_state_set, + .port_teardown = ksz_port_teardown, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz_port_vlan_filtering, + .port_vlan_add = ksz_port_vlan_add, + .port_vlan_del = ksz_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_fdb_add = ksz_port_fdb_add, + .port_fdb_del = ksz_port_fdb_del, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz_port_mirror_add, + .port_mirror_del = ksz_port_mirror_del, + .get_stats64 = ksz_get_stats64, + .get_pause_stats = ksz_get_pause_stats, + .port_change_mtu = ksz_change_mtu, + .port_max_mtu = ksz_max_mtu, + .get_wol = ksz_get_wol, + .set_wol = ksz_set_wol, + .suspend = ksz_suspend, + .resume = ksz_resume, + .get_ts_info = ksz_get_ts_info, + .port_hwtstamp_get = ksz_hwtstamp_get, + .port_hwtstamp_set = ksz_hwtstamp_set, + .port_txtstamp = ksz_port_txtstamp, + .port_rxtstamp = ksz_port_rxtstamp, + .cls_flower_add = ksz_cls_flower_add, + .cls_flower_del = ksz_cls_flower_del, + .port_setup_tc = ksz_setup_tc, + .support_eee = ksz_support_eee, + .set_mac_eee = ksz_set_mac_eee, + .port_get_default_prio = ksz_port_get_default_prio, + .port_set_default_prio = ksz_port_set_default_prio, + .port_get_dscp_prio = ksz_port_get_dscp_prio, + .port_add_dscp_prio = ksz_port_add_dscp_prio, + .port_del_dscp_prio = ksz_port_del_dscp_prio, + .port_get_apptrust = ksz_port_get_apptrust, + .port_set_apptrust = ksz_port_set_apptrust, +}; + +const struct dsa_switch_ops ksz87xx_switch_ops = { + .get_tag_protocol = ksz87xx_get_tag_protocol, + .connect_tag_protocol = ksz87xx_connect_tag_protocol, + .get_phy_flags = ksz_get_phy_flags, + .setup = ksz_setup, + .teardown = ksz_teardown, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .phylink_get_caps = ksz_phylink_get_caps, + .port_setup = ksz_port_setup, + .set_ageing_time = ksz_set_ageing_time, + .get_strings = ksz_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_hsr_join = ksz_hsr_join, + .port_hsr_leave = ksz_hsr_leave, + .port_set_mac_address = ksz_port_set_mac_address, + .port_stp_state_set = ksz_port_stp_state_set, + .port_teardown = ksz_port_teardown, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz_port_vlan_filtering, + .port_vlan_add = ksz_port_vlan_add, + .port_vlan_del = ksz_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_fdb_add = ksz_port_fdb_add, + .port_fdb_del = ksz_port_fdb_del, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz_port_mirror_add, + .port_mirror_del = ksz_port_mirror_del, + .get_stats64 = ksz_get_stats64, + .get_pause_stats = ksz_get_pause_stats, + .port_change_mtu = ksz_change_mtu, + .port_max_mtu = ksz_max_mtu, + .get_wol = ksz_get_wol, + .set_wol = ksz_set_wol, + .suspend = ksz_suspend, + .resume = ksz_resume, + .get_ts_info = ksz_get_ts_info, + .port_hwtstamp_get = ksz_hwtstamp_get, + .port_hwtstamp_set = ksz_hwtstamp_set, + .port_txtstamp = ksz_port_txtstamp, + .port_rxtstamp = ksz_port_rxtstamp, + .cls_flower_add = ksz_cls_flower_add, + .cls_flower_del = ksz_cls_flower_del, + .port_setup_tc = ksz_setup_tc, + .support_eee = ksz_support_eee, + .set_mac_eee = ksz_set_mac_eee, + .port_get_default_prio = ksz_port_get_default_prio, + .port_set_default_prio = ksz_port_set_default_prio, + .port_get_dscp_prio = ksz_port_get_dscp_prio, + .port_add_dscp_prio = ksz_port_add_dscp_prio, + .port_del_dscp_prio = ksz_port_del_dscp_prio, + .port_get_apptrust = ksz_port_get_apptrust, + .port_set_apptrust = ksz_port_set_apptrust, +}; + +const struct dsa_switch_ops ksz88xx_switch_ops = { + .get_tag_protocol = ksz88xx_get_tag_protocol, + .connect_tag_protocol = ksz88xx_connect_tag_protocol, + .get_phy_flags = ksz_get_phy_flags, + .setup = ksz_setup, + .teardown = ksz_teardown, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .phylink_get_caps = ksz_phylink_get_caps, + .port_setup = ksz_port_setup, + .set_ageing_time = ksz_set_ageing_time, + .get_strings = ksz_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_hsr_join = ksz_hsr_join, + .port_hsr_leave = ksz_hsr_leave, + .port_set_mac_address = ksz_port_set_mac_address, + .port_stp_state_set = ksz_port_stp_state_set, + .port_teardown = ksz_port_teardown, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz_port_vlan_filtering, + .port_vlan_add = ksz_port_vlan_add, + .port_vlan_del = ksz_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_fdb_add = ksz_port_fdb_add, + .port_fdb_del = ksz_port_fdb_del, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz_port_mirror_add, + .port_mirror_del = ksz_port_mirror_del, + .get_stats64 = ksz_get_stats64, + .get_pause_stats = ksz_get_pause_stats, + .port_change_mtu = ksz_change_mtu, + .port_max_mtu = ksz_max_mtu, + .get_wol = ksz_get_wol, + .set_wol = ksz_set_wol, + .suspend = ksz_suspend, + .resume = ksz_resume, + .get_ts_info = ksz_get_ts_info, + .port_hwtstamp_get = ksz_hwtstamp_get, + .port_hwtstamp_set = ksz_hwtstamp_set, + .port_txtstamp = ksz_port_txtstamp, + .port_rxtstamp = ksz_port_rxtstamp, + .cls_flower_add = ksz_cls_flower_add, + .cls_flower_del = ksz_cls_flower_del, + .port_setup_tc = ksz_setup_tc, + .support_eee = ksz_support_eee, + .set_mac_eee = ksz_set_mac_eee, + .port_get_default_prio = ksz_port_get_default_prio, + .port_set_default_prio = ksz_port_set_default_prio, + .port_get_dscp_prio = ksz_port_get_dscp_prio, + .port_add_dscp_prio = ksz_port_add_dscp_prio, + .port_del_dscp_prio = ksz_port_del_dscp_prio, + .port_get_apptrust = ksz_port_get_apptrust, + .port_set_apptrust = ksz_port_set_apptrust, +}; + MODULE_AUTHOR("Tristram Ha <Tristram.Ha@microchip.com>"); MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h index 0f2cd1474b44..bc371cc26c6f 100644 --- a/drivers/net/dsa/microchip/ksz8.h +++ b/drivers/net/dsa/microchip/ksz8.h @@ -12,59 +12,13 @@ #include <net/dsa.h> #include "ksz_common.h" -int ksz8_setup(struct dsa_switch *ds); -u32 ksz8_get_port_addr(int port, int offset); -void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member); -void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port); -void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port); -int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); -int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val); -void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt); -void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, - u64 *dropped, u64 *cnt); -void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze); -void ksz8_port_init_cnt(struct ksz_device *dev, int port); -int ksz8_fdb_dump(struct ksz_device *dev, int port, - dsa_fdb_dump_cb_t *cb, void *data); -int ksz8_fdb_add(struct ksz_device *dev, int port, const unsigned char *addr, - u16 vid, struct dsa_db db); -int ksz8_fdb_del(struct ksz_device *dev, int port, const unsigned char *addr, - u16 vid, struct dsa_db db); -int ksz8_mdb_add(struct ksz_device *dev, int port, - const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); -int ksz8_mdb_del(struct ksz_device *dev, int port, - const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); -int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag, - struct netlink_ext_ack *extack); -int ksz8_port_vlan_add(struct ksz_device *dev, int port, - const struct switchdev_obj_port_vlan *vlan, - struct netlink_ext_ack *extack); -int ksz8_port_vlan_del(struct ksz_device *dev, int port, - const struct switchdev_obj_port_vlan *vlan); -int ksz8_port_mirror_add(struct ksz_device *dev, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress, struct netlink_ext_ack *extack); -void ksz8_port_mirror_del(struct ksz_device *dev, int port, - struct dsa_mall_mirror_tc_entry *mirror); -void ksz8_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config); -void ksz8_config_cpu_port(struct dsa_switch *ds); -int ksz8_enable_stp_addr(struct ksz_device *dev); -int ksz8_reset_switch(struct ksz_device *dev); -int ksz8_switch_init(struct ksz_device *dev); -void ksz8_switch_exit(struct ksz_device *dev); -int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu); -int ksz8_pme_write8(struct ksz_device *dev, u32 reg, u8 value); -int ksz8_pme_pread8(struct ksz_device *dev, int port, int offset, u8 *data); -int ksz8_pme_pwrite8(struct ksz_device *dev, int port, int offset, u8 data); -void ksz8_phylink_mac_link_up(struct phylink_config *config, - struct phy_device *phydev, unsigned int mode, - phy_interface_t interface, int speed, int duplex, - bool tx_pause, bool rx_pause); -int ksz8_all_queues_split(struct ksz_device *dev, int queues); - -u32 ksz8463_get_port_addr(int port, int offset); -int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); -int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val); +extern const struct ksz_dev_ops ksz8463_dev_ops; +extern const struct ksz_dev_ops ksz87xx_dev_ops; +extern const struct ksz_dev_ops ksz88xx_dev_ops; +extern const struct phylink_mac_ops ksz88x3_phylink_mac_ops; +extern const struct phylink_mac_ops ksz8_phylink_mac_ops; +extern const struct dsa_switch_ops ksz8463_switch_ops; +extern const struct dsa_switch_ops ksz87xx_switch_ops; +extern const struct dsa_switch_ops ksz88xx_switch_ops; #endif diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index a8bfcd917bf7..ba08d2cf8e99 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -140,14 +140,14 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev) int ret; int i; - dev = ksz_switch_alloc(&mdiodev->dev, mdiodev); - if (!dev) - return -ENOMEM; - chip = device_get_match_data(ddev); if (!chip) return -EINVAL; + dev = ksz_switch_alloc(&mdiodev->dev, chip, mdiodev); + if (!dev) + return -ENOMEM; + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz8863_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index d3c23dcaea8c..ac2c63fe0588 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -5,6 +5,7 @@ * Copyright (C) 2017-2025 Microchip Technology Inc. */ +#include <linux/dsa/ksz_common.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/iopoll.h> @@ -17,6 +18,7 @@ #include "ksz9477_reg.h" #include "ksz_common.h" +#include "ksz_dcb.h" #include "ksz9477.h" static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) @@ -43,7 +45,7 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset, bits, set ? bits : 0); } -int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) +static int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) { u16 frame_size; @@ -308,7 +310,7 @@ static int ksz9477_pcs_write(struct mii_bus *bus, int phy, int mmd, int reg, return 0; } -int ksz9477_pcs_create(struct ksz_device *dev) +static int ksz9477_pcs_create(struct ksz_device *dev) { int port = ksz_get_sgmii_port(dev); struct ksz_port *p = &dev->ports[port]; @@ -341,7 +343,7 @@ int ksz9477_pcs_create(struct ksz_device *dev) return 0; } -int ksz9477_reset_switch(struct ksz_device *dev) +static int ksz9477_reset_switch(struct ksz_device *dev) { u8 data8; u32 data32; @@ -516,7 +518,7 @@ static void ksz9477_r_phy_quirks(struct ksz_device *dev, u16 addr, u16 reg, *data &= ~(BMSR_ESTATEN | BMSR_ERCAP); } -int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) +static int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) { u16 val = 0xffff; int ret; @@ -572,7 +574,7 @@ int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) return 0; } -int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) +static int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) { u32 mask, val32; @@ -1150,8 +1152,8 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) return interface; } -void ksz9477_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config) +static void ksz9477_get_caps(struct ksz_device *dev, int port, + struct phylink_config *config) { config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | MAC_SYM_PAUSE; @@ -1168,7 +1170,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port, } } -int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs) +static int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs) { u32 secs = msecs / 1000; u8 data, mult, value; @@ -1234,7 +1236,7 @@ void ksz9477_port_queue_split(struct ksz_device *dev, int port) ksz_prmw8(dev, port, REG_PORT_CTRL_0, PORT_QUEUE_SPLIT_MASK, data); } -void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) +static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) { const u16 *regs = dev->info->regs; struct dsa_switch *ds = dev->ds; @@ -1289,7 +1291,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) ksz_pwrite8(dev, port, regs[REG_PORT_PME_CTRL], 0); } -void ksz9477_config_cpu_port(struct dsa_switch *ds) +static void ksz9477_config_cpu_port(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; struct ksz_port *p; @@ -1454,7 +1456,7 @@ int ksz9477_enable_stp_addr(struct ksz_device *dev) return 0; } -int ksz9477_setup(struct dsa_switch *ds) +static int ksz9477_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; const u16 *regs = dev->info->regs; @@ -1500,7 +1502,7 @@ u32 ksz9477_get_port_addr(int port, int offset) return PORT_CTRL_ADDR(port, offset); } -int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val) +static int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val) { val = val >> 8; @@ -1584,7 +1586,7 @@ void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr) ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL, PORT_SRC_ADDR_FILTER, false); } -int ksz9477_switch_init(struct ksz_device *dev) +static int ksz9477_switch_init(struct ksz_device *dev) { u8 data8; int ret; @@ -1604,11 +1606,264 @@ int ksz9477_switch_init(struct ksz_device *dev) return 0; } -void ksz9477_switch_exit(struct ksz_device *dev) +static void ksz9477_switch_exit(struct ksz_device *dev) { ksz9477_reset_switch(dev); } +static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) +{ + struct ksz_device *dev = ds->priv; + + if (dev->chip_id == KSZ8563_CHIP_ID || + dev->chip_id == KSZ9893_CHIP_ID || + dev->chip_id == KSZ9563_CHIP_ID) + return DSA_TAG_PROTO_KSZ9893; + + return DSA_TAG_PROTO_KSZ9477; +} + +static int ksz9477_connect_tag_protocol(struct dsa_switch *ds, + enum dsa_tag_protocol proto) +{ + struct ksz_tagger_data *tagger_data; + + if (proto != DSA_TAG_PROTO_KSZ9893 && proto != DSA_TAG_PROTO_KSZ9477) + return -EPROTONOSUPPORT; + + tagger_data = ksz_tagger_data(ds); + tagger_data->xmit_work_fn = ksz_port_deferred_xmit; + + return 0; +} + +static void ksz9477_set_gbit(struct ksz_device *dev, int port, bool gbit) +{ + const u8 *bitval = dev->info->xmii_ctrl1; + const u16 *regs = dev->info->regs; + u8 data8; + + ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); + + data8 &= ~P_GMII_1GBIT_M; + + if (gbit) + data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); + else + data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); + + /* Write the updated value */ + ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); +} + +static void ksz9477_set_100_10mbit(struct ksz_device *dev, int port, int speed) +{ + const u8 *bitval = dev->info->xmii_ctrl0; + const u16 *regs = dev->info->regs; + u8 data8; + + ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); + + data8 &= ~P_MII_100MBIT_M; + + if (speed == SPEED_100) + data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); + else + data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); + + /* Write the updated value */ + ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); +} + +static void ksz9477_port_set_xmii_speed(struct ksz_device *dev, int port, + int speed) +{ + if (speed == SPEED_1000) + ksz9477_set_gbit(dev, port, true); + else + ksz9477_set_gbit(dev, port, false); + + if (speed == SPEED_100 || speed == SPEED_10) + ksz9477_set_100_10mbit(dev, port, speed); +} + +static void ksz9477_duplex_flowctrl(struct ksz_device *dev, int port, int duplex, + bool tx_pause, bool rx_pause) +{ + const u8 *bitval = dev->info->xmii_ctrl0; + const u32 *masks = dev->info->masks; + const u16 *regs = dev->info->regs; + u8 mask; + u8 val; + + mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] | + masks[P_MII_RX_FLOW_CTRL]; + + if (duplex == DUPLEX_FULL) + val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]); + else + val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]); + + if (tx_pause) + val |= masks[P_MII_TX_FLOW_CTRL]; + + if (rx_pause) + val |= masks[P_MII_RX_FLOW_CTRL]; + + ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val); +} + +void ksz9477_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, + int speed, int duplex, bool tx_pause, + bool rx_pause) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct ksz_device *dev = dp->ds->priv; + int port = dp->index; + struct ksz_port *p; + + p = &dev->ports[port]; + + /* Internal PHYs */ + if (dev->info->internal_phy[port]) + return; + + p->speed = speed; + + ksz9477_port_set_xmii_speed(dev, port, speed); + + ksz9477_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause); +} + +static struct phylink_pcs * +ksz9477_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct ksz_device *dev = dp->ds->priv; + struct ksz_port *p = &dev->ports[dp->index]; + + if (ksz_is_sgmii_port(dev, dp->index) && + (interface == PHY_INTERFACE_MODE_SGMII || + interface == PHY_INTERFACE_MODE_1000BASEX)) + return p->pcs; + + return NULL; +} + +const struct phylink_mac_ops ksz9477_phylink_mac_ops = { + .mac_config = ksz_phylink_mac_config, + .mac_link_down = ksz_phylink_mac_link_down, + .mac_link_up = ksz9477_phylink_mac_link_up, + .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, + .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, + .mac_select_pcs = ksz9477_phylink_mac_select_pcs, +}; + +const struct ksz_dev_ops ksz9477_dev_ops = { + .setup = ksz9477_setup, + .get_port_addr = ksz9477_get_port_addr, + .cfg_port_member = ksz9477_cfg_port_member, + .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, + .port_setup = ksz9477_port_setup, + .set_ageing_time = ksz9477_set_ageing_time, + .r_phy = ksz9477_r_phy, + .w_phy = ksz9477_w_phy, + .r_mib_cnt = ksz9477_r_mib_cnt, + .r_mib_pkt = ksz9477_r_mib_pkt, + .r_mib_stat64 = ksz_r_mib_stats64, + .freeze_mib = ksz9477_freeze_mib, + .port_init_cnt = ksz9477_port_init_cnt, + .vlan_filtering = ksz9477_port_vlan_filtering, + .vlan_add = ksz9477_port_vlan_add, + .vlan_del = ksz9477_port_vlan_del, + .mirror_add = ksz9477_port_mirror_add, + .mirror_del = ksz9477_port_mirror_del, + .get_caps = ksz9477_get_caps, + .fdb_dump = ksz9477_fdb_dump, + .fdb_add = ksz9477_fdb_add, + .fdb_del = ksz9477_fdb_del, + .mdb_add = ksz9477_mdb_add, + .mdb_del = ksz9477_mdb_del, + .change_mtu = ksz9477_change_mtu, + .pme_write8 = ksz_write8, + .pme_pread8 = ksz_pread8, + .pme_pwrite8 = ksz_pwrite8, + .config_cpu_port = ksz9477_config_cpu_port, + .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc, + .enable_stp_addr = ksz9477_enable_stp_addr, + .reset = ksz9477_reset_switch, + .init = ksz9477_switch_init, + .exit = ksz9477_switch_exit, + .pcs_create = ksz9477_pcs_create, +}; + +const struct dsa_switch_ops ksz9477_switch_ops = { + .get_tag_protocol = ksz9477_get_tag_protocol, + .connect_tag_protocol = ksz9477_connect_tag_protocol, + .get_phy_flags = ksz_get_phy_flags, + .setup = ksz_setup, + .teardown = ksz_teardown, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .phylink_get_caps = ksz_phylink_get_caps, + .port_setup = ksz_port_setup, + .set_ageing_time = ksz_set_ageing_time, + .get_strings = ksz_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_hsr_join = ksz_hsr_join, + .port_hsr_leave = ksz_hsr_leave, + .port_set_mac_address = ksz_port_set_mac_address, + .port_stp_state_set = ksz_port_stp_state_set, + .port_teardown = ksz_port_teardown, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz_port_vlan_filtering, + .port_vlan_add = ksz_port_vlan_add, + .port_vlan_del = ksz_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_fdb_add = ksz_port_fdb_add, + .port_fdb_del = ksz_port_fdb_del, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz_port_mirror_add, + .port_mirror_del = ksz_port_mirror_del, + .get_stats64 = ksz_get_stats64, + .get_pause_stats = ksz_get_pause_stats, + .port_change_mtu = ksz_change_mtu, + .port_max_mtu = ksz_max_mtu, + .get_wol = ksz_get_wol, + .set_wol = ksz_set_wol, + .suspend = ksz_suspend, + .resume = ksz_resume, + .get_ts_info = ksz_get_ts_info, + .port_hwtstamp_get = ksz_hwtstamp_get, + .port_hwtstamp_set = ksz_hwtstamp_set, + .port_txtstamp = ksz_port_txtstamp, + .port_rxtstamp = ksz_port_rxtstamp, + .cls_flower_add = ksz_cls_flower_add, + .cls_flower_del = ksz_cls_flower_del, + .port_setup_tc = ksz_setup_tc, + .support_eee = ksz_support_eee, + .set_mac_eee = ksz_set_mac_eee, + .port_get_default_prio = ksz_port_get_default_prio, + .port_set_default_prio = ksz_port_set_default_prio, + .port_get_dscp_prio = ksz_port_get_dscp_prio, + .port_add_dscp_prio = ksz_port_add_dscp_prio, + .port_del_dscp_prio = ksz_port_del_dscp_prio, + .port_get_apptrust = ksz_port_get_apptrust, + .port_set_apptrust = ksz_port_set_apptrust, +}; + MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch DSA Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/microchip/ksz9477.h b/drivers/net/dsa/microchip/ksz9477.h index 0d1a6dfda23e..bacadcbc478c 100644 --- a/drivers/net/dsa/microchip/ksz9477.h +++ b/drivers/net/dsa/microchip/ksz9477.h @@ -11,14 +11,9 @@ #include <net/dsa.h> #include "ksz_common.h" -int ksz9477_setup(struct dsa_switch *ds); u32 ksz9477_get_port_addr(int port, int offset); void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member); void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port); -void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port); -int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs); -int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data); -int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val); void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt); void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, u64 *dropped, u64 *cnt); @@ -38,8 +33,6 @@ void ksz9477_port_mirror_del(struct ksz_device *dev, int port, struct dsa_mall_mirror_tc_entry *mirror); int ksz9477_errata_monitor(struct ksz_device *dev, int port, u64 tx_late_col); -void ksz9477_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config); int ksz9477_fdb_dump(struct ksz_device *dev, int port, dsa_fdb_dump_cb_t *cb, void *data); int ksz9477_fdb_add(struct ksz_device *dev, int port, @@ -50,13 +43,7 @@ int ksz9477_mdb_add(struct ksz_device *dev, int port, const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); int ksz9477_mdb_del(struct ksz_device *dev, int port, const struct switchdev_obj_port_mdb *mdb, struct dsa_db db); -int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu); -void ksz9477_config_cpu_port(struct dsa_switch *ds); -int ksz9477_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val); int ksz9477_enable_stp_addr(struct ksz_device *dev); -int ksz9477_reset_switch(struct ksz_device *dev); -int ksz9477_switch_init(struct ksz_device *dev); -void ksz9477_switch_exit(struct ksz_device *dev); void ksz9477_port_queue_split(struct ksz_device *dev, int port); void ksz9477_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr); void ksz9477_hsr_leave(struct dsa_switch *ds, int port, struct net_device *hsr); @@ -97,6 +84,15 @@ void ksz9477_acl_match_process_l2(struct ksz_device *dev, int port, u16 ethtype, u8 *src_mac, u8 *dst_mac, unsigned long cookie, u32 prio); -int ksz9477_pcs_create(struct ksz_device *dev); +void ksz9477_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, + int speed, int duplex, bool tx_pause, + bool rx_pause); + +extern const struct ksz_dev_ops ksz9477_dev_ops; +extern const struct phylink_mac_ops ksz9477_phylink_mac_ops; +extern const struct dsa_switch_ops ksz9477_switch_ops; #endif diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index a2beb27459f1..8e9d08f2e1d6 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -22,14 +22,14 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c) struct ksz_device *dev; int i, ret; - dev = ksz_switch_alloc(&i2c->dev, i2c); - if (!dev) - return -ENOMEM; - chip = device_get_match_data(ddev); if (!chip) return -EINVAL; + dev = ksz_switch_alloc(&i2c->dev, chip, i2c); + if (!dev) + return -ENOMEM; + /* Save chip id to do special initialization when probing. */ dev->chip_id = chip->chip_id; for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 144373e13bea..426414a21845 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -256,16 +256,6 @@ static const struct ksz_drive_strength ksz88x3_drive_strengths[] = { { KSZ8873_DRIVE_STRENGTH_16MA, 16000 }, }; -static void ksz88x3_phylink_mac_config(struct phylink_config *config, - unsigned int mode, - const struct phylink_link_state *state); -static void ksz_phylink_mac_config(struct phylink_config *config, - unsigned int mode, - const struct phylink_link_state *state); -static void ksz_phylink_mac_link_down(struct phylink_config *config, - unsigned int mode, - phy_interface_t interface); - /** * ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy) * @config: phylink config structure @@ -273,7 +263,7 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config, * This function is a dummy handler. See ksz_phylink_mac_enable_tx_lpi() for * a detailed explanation of EEE/LPI handling in KSZ switches. */ -static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config) +void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config) { } @@ -310,246 +300,12 @@ static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config) * * Returns: 0 (Always success) */ -static int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config, - u32 timer, bool tx_clock_stop) +int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config, + u32 timer, bool tx_clock_stop) { return 0; } -static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = { - .mac_config = ksz88x3_phylink_mac_config, - .mac_link_down = ksz_phylink_mac_link_down, - .mac_link_up = ksz8_phylink_mac_link_up, - .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, - .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, -}; - -static const struct phylink_mac_ops ksz8_phylink_mac_ops = { - .mac_config = ksz_phylink_mac_config, - .mac_link_down = ksz_phylink_mac_link_down, - .mac_link_up = ksz8_phylink_mac_link_up, - .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, - .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, -}; - -static const struct ksz_dev_ops ksz8463_dev_ops = { - .setup = ksz8_setup, - .get_port_addr = ksz8463_get_port_addr, - .cfg_port_member = ksz8_cfg_port_member, - .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, - .port_setup = ksz8_port_setup, - .r_phy = ksz8463_r_phy, - .w_phy = ksz8463_w_phy, - .r_mib_cnt = ksz8_r_mib_cnt, - .r_mib_pkt = ksz8_r_mib_pkt, - .r_mib_stat64 = ksz88xx_r_mib_stats64, - .freeze_mib = ksz8_freeze_mib, - .port_init_cnt = ksz8_port_init_cnt, - .fdb_dump = ksz8_fdb_dump, - .fdb_add = ksz8_fdb_add, - .fdb_del = ksz8_fdb_del, - .mdb_add = ksz8_mdb_add, - .mdb_del = ksz8_mdb_del, - .vlan_filtering = ksz8_port_vlan_filtering, - .vlan_add = ksz8_port_vlan_add, - .vlan_del = ksz8_port_vlan_del, - .mirror_add = ksz8_port_mirror_add, - .mirror_del = ksz8_port_mirror_del, - .get_caps = ksz8_get_caps, - .config_cpu_port = ksz8_config_cpu_port, - .enable_stp_addr = ksz8_enable_stp_addr, - .reset = ksz8_reset_switch, - .init = ksz8_switch_init, - .exit = ksz8_switch_exit, - .change_mtu = ksz8_change_mtu, -}; - -static const struct ksz_dev_ops ksz88xx_dev_ops = { - .setup = ksz8_setup, - .get_port_addr = ksz8_get_port_addr, - .cfg_port_member = ksz8_cfg_port_member, - .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, - .port_setup = ksz8_port_setup, - .r_phy = ksz8_r_phy, - .w_phy = ksz8_w_phy, - .r_mib_cnt = ksz8_r_mib_cnt, - .r_mib_pkt = ksz8_r_mib_pkt, - .r_mib_stat64 = ksz88xx_r_mib_stats64, - .freeze_mib = ksz8_freeze_mib, - .port_init_cnt = ksz8_port_init_cnt, - .fdb_dump = ksz8_fdb_dump, - .fdb_add = ksz8_fdb_add, - .fdb_del = ksz8_fdb_del, - .mdb_add = ksz8_mdb_add, - .mdb_del = ksz8_mdb_del, - .vlan_filtering = ksz8_port_vlan_filtering, - .vlan_add = ksz8_port_vlan_add, - .vlan_del = ksz8_port_vlan_del, - .mirror_add = ksz8_port_mirror_add, - .mirror_del = ksz8_port_mirror_del, - .get_caps = ksz8_get_caps, - .config_cpu_port = ksz8_config_cpu_port, - .enable_stp_addr = ksz8_enable_stp_addr, - .reset = ksz8_reset_switch, - .init = ksz8_switch_init, - .exit = ksz8_switch_exit, - .change_mtu = ksz8_change_mtu, - .pme_write8 = ksz8_pme_write8, - .pme_pread8 = ksz8_pme_pread8, - .pme_pwrite8 = ksz8_pme_pwrite8, -}; - -static const struct ksz_dev_ops ksz87xx_dev_ops = { - .setup = ksz8_setup, - .get_port_addr = ksz8_get_port_addr, - .cfg_port_member = ksz8_cfg_port_member, - .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, - .port_setup = ksz8_port_setup, - .r_phy = ksz8_r_phy, - .w_phy = ksz8_w_phy, - .r_mib_cnt = ksz8_r_mib_cnt, - .r_mib_pkt = ksz8_r_mib_pkt, - .r_mib_stat64 = ksz_r_mib_stats64, - .freeze_mib = ksz8_freeze_mib, - .port_init_cnt = ksz8_port_init_cnt, - .fdb_dump = ksz8_fdb_dump, - .fdb_add = ksz8_fdb_add, - .fdb_del = ksz8_fdb_del, - .mdb_add = ksz8_mdb_add, - .mdb_del = ksz8_mdb_del, - .vlan_filtering = ksz8_port_vlan_filtering, - .vlan_add = ksz8_port_vlan_add, - .vlan_del = ksz8_port_vlan_del, - .mirror_add = ksz8_port_mirror_add, - .mirror_del = ksz8_port_mirror_del, - .get_caps = ksz8_get_caps, - .config_cpu_port = ksz8_config_cpu_port, - .enable_stp_addr = ksz8_enable_stp_addr, - .reset = ksz8_reset_switch, - .init = ksz8_switch_init, - .exit = ksz8_switch_exit, - .change_mtu = ksz8_change_mtu, - .pme_write8 = ksz8_pme_write8, - .pme_pread8 = ksz8_pme_pread8, - .pme_pwrite8 = ksz8_pme_pwrite8, -}; - -static void ksz9477_phylink_mac_link_up(struct phylink_config *config, - struct phy_device *phydev, - unsigned int mode, - phy_interface_t interface, - int speed, int duplex, bool tx_pause, - bool rx_pause); - -static struct phylink_pcs * -ksz_phylink_mac_select_pcs(struct phylink_config *config, - phy_interface_t interface) -{ - struct dsa_port *dp = dsa_phylink_to_port(config); - struct ksz_device *dev = dp->ds->priv; - struct ksz_port *p = &dev->ports[dp->index]; - - if (ksz_is_sgmii_port(dev, dp->index) && - (interface == PHY_INTERFACE_MODE_SGMII || - interface == PHY_INTERFACE_MODE_1000BASEX)) - return p->pcs; - - return NULL; -} - -static const struct phylink_mac_ops ksz9477_phylink_mac_ops = { - .mac_config = ksz_phylink_mac_config, - .mac_link_down = ksz_phylink_mac_link_down, - .mac_link_up = ksz9477_phylink_mac_link_up, - .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, - .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, - .mac_select_pcs = ksz_phylink_mac_select_pcs, -}; - -static const struct ksz_dev_ops ksz9477_dev_ops = { - .setup = ksz9477_setup, - .get_port_addr = ksz9477_get_port_addr, - .cfg_port_member = ksz9477_cfg_port_member, - .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, - .port_setup = ksz9477_port_setup, - .set_ageing_time = ksz9477_set_ageing_time, - .r_phy = ksz9477_r_phy, - .w_phy = ksz9477_w_phy, - .r_mib_cnt = ksz9477_r_mib_cnt, - .r_mib_pkt = ksz9477_r_mib_pkt, - .r_mib_stat64 = ksz_r_mib_stats64, - .freeze_mib = ksz9477_freeze_mib, - .port_init_cnt = ksz9477_port_init_cnt, - .vlan_filtering = ksz9477_port_vlan_filtering, - .vlan_add = ksz9477_port_vlan_add, - .vlan_del = ksz9477_port_vlan_del, - .mirror_add = ksz9477_port_mirror_add, - .mirror_del = ksz9477_port_mirror_del, - .get_caps = ksz9477_get_caps, - .fdb_dump = ksz9477_fdb_dump, - .fdb_add = ksz9477_fdb_add, - .fdb_del = ksz9477_fdb_del, - .mdb_add = ksz9477_mdb_add, - .mdb_del = ksz9477_mdb_del, - .change_mtu = ksz9477_change_mtu, - .pme_write8 = ksz_write8, - .pme_pread8 = ksz_pread8, - .pme_pwrite8 = ksz_pwrite8, - .config_cpu_port = ksz9477_config_cpu_port, - .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc, - .enable_stp_addr = ksz9477_enable_stp_addr, - .reset = ksz9477_reset_switch, - .init = ksz9477_switch_init, - .exit = ksz9477_switch_exit, - .pcs_create = ksz9477_pcs_create, -}; - -static const struct phylink_mac_ops lan937x_phylink_mac_ops = { - .mac_config = ksz_phylink_mac_config, - .mac_link_down = ksz_phylink_mac_link_down, - .mac_link_up = ksz9477_phylink_mac_link_up, - .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, - .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, -}; - -static const struct ksz_dev_ops lan937x_dev_ops = { - .setup = lan937x_setup, - .teardown = lan937x_teardown, - .get_port_addr = ksz9477_get_port_addr, - .cfg_port_member = ksz9477_cfg_port_member, - .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, - .port_setup = lan937x_port_setup, - .set_ageing_time = lan937x_set_ageing_time, - .mdio_bus_preinit = lan937x_mdio_bus_preinit, - .create_phy_addr_map = lan937x_create_phy_addr_map, - .r_phy = lan937x_r_phy, - .w_phy = lan937x_w_phy, - .r_mib_cnt = ksz9477_r_mib_cnt, - .r_mib_pkt = ksz9477_r_mib_pkt, - .r_mib_stat64 = ksz_r_mib_stats64, - .freeze_mib = ksz9477_freeze_mib, - .port_init_cnt = ksz9477_port_init_cnt, - .vlan_filtering = ksz9477_port_vlan_filtering, - .vlan_add = ksz9477_port_vlan_add, - .vlan_del = ksz9477_port_vlan_del, - .mirror_add = ksz9477_port_mirror_add, - .mirror_del = ksz9477_port_mirror_del, - .get_caps = lan937x_phylink_get_caps, - .setup_rgmii_delay = lan937x_setup_rgmii_delay, - .fdb_dump = ksz9477_fdb_dump, - .fdb_add = ksz9477_fdb_add, - .fdb_del = ksz9477_fdb_del, - .mdb_add = ksz9477_mdb_add, - .mdb_del = ksz9477_mdb_del, - .change_mtu = lan937x_change_mtu, - .config_cpu_port = lan937x_config_cpu_port, - .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc, - .enable_stp_addr = ksz9477_enable_stp_addr, - .reset = lan937x_reset_switch, - .init = lan937x_switch_init, - .exit = lan937x_switch_exit, -}; - static const u16 ksz8463_regs[] = { [REG_SW_MAC_ADDR] = 0x10, [REG_IND_CTRL_0] = 0x30, @@ -1502,6 +1258,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz8463_dev_ops, + .switch_ops = &ksz8463_switch_ops, .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), @@ -1527,6 +1284,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_ipms = 8, .tc_cbs_supported = true, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -1557,6 +1315,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz87xx_dev_ops, + .switch_ops = &ksz87xx_switch_ops, .phylink_mac_ops = &ksz8_phylink_mac_ops, .ksz87xx_eee_link_erratum = true, .mib_names = ksz9477_mib_names, @@ -1598,6 +1357,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz87xx_dev_ops, + .switch_ops = &ksz87xx_switch_ops, .phylink_mac_ops = &ksz8_phylink_mac_ops, .ksz87xx_eee_link_erratum = true, .mib_names = ksz9477_mib_names, @@ -1625,6 +1385,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz87xx_dev_ops, + .switch_ops = &ksz87xx_switch_ops, .phylink_mac_ops = &ksz8_phylink_mac_ops, .ksz87xx_eee_link_erratum = true, .mib_names = ksz9477_mib_names, @@ -1652,6 +1413,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, + .switch_ops = &ksz88xx_switch_ops, .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), @@ -1686,6 +1448,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, + .switch_ops = &ksz88xx_switch_ops, .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), @@ -1709,6 +1472,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 4, .ops = &ksz88xx_dev_ops, + .switch_ops = &ksz88xx_switch_ops, .phylink_mac_ops = &ksz88x3_phylink_mac_ops, .mib_names = ksz88xx_mib_names, .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), @@ -1734,6 +1498,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_ipms = 8, .tc_cbs_supported = true, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, @@ -1771,6 +1536,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 8, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, @@ -1806,6 +1572,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 8, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, @@ -1839,6 +1606,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 8, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -1868,6 +1636,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_ipms = 8, .tc_cbs_supported = true, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -1898,6 +1667,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_ipms = 8, .tc_cbs_supported = true, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, @@ -1934,6 +1704,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_ipms = 8, .tc_cbs_supported = true, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1968,6 +1739,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .phy_side_mdio_supported = true, .ops = &lan937x_dev_ops, + .switch_ops = &lan937x_switch_ops, .phylink_mac_ops = &lan937x_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -1998,6 +1770,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .phy_side_mdio_supported = true, .ops = &lan937x_dev_ops, + .switch_ops = &lan937x_switch_ops, .phylink_mac_ops = &lan937x_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -2028,6 +1801,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .phy_side_mdio_supported = true, .ops = &lan937x_dev_ops, + .switch_ops = &lan937x_switch_ops, .phylink_mac_ops = &lan937x_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -2062,6 +1836,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .phy_side_mdio_supported = true, .ops = &lan937x_dev_ops, + .switch_ops = &lan937x_switch_ops, .phylink_mac_ops = &lan937x_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -2096,6 +1871,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .phy_side_mdio_supported = true, .ops = &lan937x_dev_ops, + .switch_ops = &lan937x_switch_ops, .phylink_mac_ops = &lan937x_phylink_mac_ops, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), @@ -2128,6 +1904,7 @@ const struct ksz_chip_data ksz_switch_chips[] = { .num_tx_queues = 4, .num_ipms = 8, .ops = &ksz9477_dev_ops, + .switch_ops = &ksz9477_switch_ops, .phylink_mac_ops = &ksz9477_phylink_mac_ops, .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, @@ -2193,8 +1970,8 @@ static int ksz_check_device_id(struct ksz_device *dev) return 0; } -static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, - struct phylink_config *config) +void ksz_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) { struct ksz_device *dev = ds->priv; @@ -2339,8 +2116,8 @@ void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port) spin_unlock(&mib->stats64_lock); } -static void ksz_get_stats64(struct dsa_switch *ds, int port, - struct rtnl_link_stats64 *s) +void ksz_get_stats64(struct dsa_switch *ds, int port, + struct rtnl_link_stats64 *s) { struct ksz_device *dev = ds->priv; struct ksz_port_mib *mib; @@ -2352,8 +2129,8 @@ static void ksz_get_stats64(struct dsa_switch *ds, int port, spin_unlock(&mib->stats64_lock); } -static void ksz_get_pause_stats(struct dsa_switch *ds, int port, - struct ethtool_pause_stats *pause_stats) +void ksz_get_pause_stats(struct dsa_switch *ds, int port, + struct ethtool_pause_stats *pause_stats) { struct ksz_device *dev = ds->priv; struct ksz_port_mib *mib; @@ -2365,8 +2142,8 @@ static void ksz_get_pause_stats(struct dsa_switch *ds, int port, spin_unlock(&mib->stats64_lock); } -static void ksz_get_strings(struct dsa_switch *ds, int port, - u32 stringset, uint8_t *buf) +void ksz_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *buf) { struct ksz_device *dev = ds->priv; int i; @@ -2973,7 +2750,7 @@ static int ksz_pirq_setup(struct ksz_device *dev, u8 p) static int ksz_parse_drive_strength(struct ksz_device *dev); -static int ksz_setup(struct dsa_switch *ds) +int ksz_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; u16 storm_mask, storm_rate; @@ -3103,7 +2880,7 @@ pirq_release: return ret; } -static void ksz_teardown(struct dsa_switch *ds) +void ksz_teardown(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; struct dsa_port *dp; @@ -3203,7 +2980,7 @@ void ksz_init_mib_timer(struct ksz_device *dev) } } -static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) +int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) { struct ksz_device *dev = ds->priv; u16 val = 0xffff; @@ -3216,7 +2993,7 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) return val; } -static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) +int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) { struct ksz_device *dev = ds->priv; int ret; @@ -3228,7 +3005,7 @@ static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) return 0; } -static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) +u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; @@ -3246,9 +3023,9 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) return 0; } -static void ksz_phylink_mac_link_down(struct phylink_config *config, - unsigned int mode, - phy_interface_t interface) +void ksz_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) { struct dsa_port *dp = dsa_phylink_to_port(config); struct ksz_device *dev = dp->ds->priv; @@ -3260,7 +3037,7 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config, schedule_delayed_work(&dev->mib_read, 0); } -static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) +int ksz_sset_count(struct dsa_switch *ds, int port, int sset) { struct ksz_device *dev = ds->priv; @@ -3270,8 +3047,8 @@ static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) return dev->info->mib_cnt; } -static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, - uint64_t *buf) +void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *buf) { const struct dsa_port *dp = dsa_to_port(ds, port); struct ksz_device *dev = ds->priv; @@ -3288,10 +3065,10 @@ static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, mutex_unlock(&mib->cnt_mutex); } -static int ksz_port_bridge_join(struct dsa_switch *ds, int port, - struct dsa_bridge bridge, - bool *tx_fwd_offload, - struct netlink_ext_ack *extack) +int ksz_port_bridge_join(struct dsa_switch *ds, int port, + struct dsa_bridge bridge, + bool *tx_fwd_offload, + struct netlink_ext_ack *extack) { /* port_stp_state_set() will be called after to put the port in * appropriate state so there is no need to do anything. @@ -3300,22 +3077,22 @@ static int ksz_port_bridge_join(struct dsa_switch *ds, int port, return 0; } -static void ksz_port_bridge_leave(struct dsa_switch *ds, int port, - struct dsa_bridge bridge) +void ksz_port_bridge_leave(struct dsa_switch *ds, int port, + struct dsa_bridge bridge) { /* port_stp_state_set() will be called after to put the port in * forwarding state so there is no need to do anything. */ } -static void ksz_port_fast_age(struct dsa_switch *ds, int port) +void ksz_port_fast_age(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; dev->dev_ops->flush_dyn_mac_table(dev, port); } -static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) +int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) { struct ksz_device *dev = ds->priv; @@ -3325,9 +3102,9 @@ static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) return dev->dev_ops->set_ageing_time(dev, msecs); } -static int ksz_port_fdb_add(struct dsa_switch *ds, int port, - const unsigned char *addr, u16 vid, - struct dsa_db db) +int ksz_port_fdb_add(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid, + struct dsa_db db) { struct ksz_device *dev = ds->priv; @@ -3337,9 +3114,9 @@ static int ksz_port_fdb_add(struct dsa_switch *ds, int port, return dev->dev_ops->fdb_add(dev, port, addr, vid, db); } -static int ksz_port_fdb_del(struct dsa_switch *ds, int port, - const unsigned char *addr, - u16 vid, struct dsa_db db) +int ksz_port_fdb_del(struct dsa_switch *ds, int port, + const unsigned char *addr, + u16 vid, struct dsa_db db) { struct ksz_device *dev = ds->priv; @@ -3349,8 +3126,8 @@ static int ksz_port_fdb_del(struct dsa_switch *ds, int port, return dev->dev_ops->fdb_del(dev, port, addr, vid, db); } -static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, - dsa_fdb_dump_cb_t *cb, void *data) +int ksz_port_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data) { struct ksz_device *dev = ds->priv; @@ -3360,9 +3137,9 @@ static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, return dev->dev_ops->fdb_dump(dev, port, cb, data); } -static int ksz_port_mdb_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb, - struct dsa_db db) +int ksz_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) { struct ksz_device *dev = ds->priv; @@ -3372,9 +3149,9 @@ static int ksz_port_mdb_add(struct dsa_switch *ds, int port, return dev->dev_ops->mdb_add(dev, port, mdb, db); } -static int ksz_port_mdb_del(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_mdb *mdb, - struct dsa_db db) +int ksz_port_mdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) { struct ksz_device *dev = ds->priv; @@ -3407,7 +3184,7 @@ static int ksz9477_set_default_prio_queue_mapping(struct ksz_device *dev, return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map); } -static int ksz_port_setup(struct dsa_switch *ds, int port) +int ksz_port_setup(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; int ret; @@ -3477,7 +3254,7 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) ksz_update_port_member(dev, port); } -static void ksz_port_teardown(struct dsa_switch *ds, int port) +void ksz_port_teardown(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; @@ -3496,9 +3273,9 @@ static void ksz_port_teardown(struct dsa_switch *ds, int port) } } -static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, - struct switchdev_brport_flags flags, - struct netlink_ext_ack *extack) +int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) { if (flags.mask & ~(BR_LEARNING | BR_ISOLATED)) return -EINVAL; @@ -3506,9 +3283,9 @@ static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, return 0; } -static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, - struct switchdev_brport_flags flags, - struct netlink_ext_ack *extack) +int ksz_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; struct ksz_port *p = &dev->ports[port]; @@ -3527,58 +3304,8 @@ static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, return 0; } -static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, - int port, - enum dsa_tag_protocol mp) -{ - struct ksz_device *dev = ds->priv; - enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; - - if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) - proto = DSA_TAG_PROTO_KSZ8795; - - if (dev->chip_id == KSZ88X3_CHIP_ID || - dev->chip_id == KSZ8463_CHIP_ID || - dev->chip_id == KSZ8563_CHIP_ID || - dev->chip_id == KSZ9893_CHIP_ID || - dev->chip_id == KSZ9563_CHIP_ID) - proto = DSA_TAG_PROTO_KSZ9893; - - if (dev->chip_id == KSZ8567_CHIP_ID || - dev->chip_id == KSZ9477_CHIP_ID || - dev->chip_id == KSZ9896_CHIP_ID || - dev->chip_id == KSZ9897_CHIP_ID || - dev->chip_id == KSZ9567_CHIP_ID || - dev->chip_id == LAN9646_CHIP_ID) - proto = DSA_TAG_PROTO_KSZ9477; - - if (is_lan937x(dev)) - proto = DSA_TAG_PROTO_LAN937X; - - return proto; -} - -static int ksz_connect_tag_protocol(struct dsa_switch *ds, - enum dsa_tag_protocol proto) -{ - struct ksz_tagger_data *tagger_data; - - switch (proto) { - case DSA_TAG_PROTO_KSZ8795: - return 0; - case DSA_TAG_PROTO_KSZ9893: - case DSA_TAG_PROTO_KSZ9477: - case DSA_TAG_PROTO_LAN937X: - tagger_data = ksz_tagger_data(ds); - tagger_data->xmit_work_fn = ksz_port_deferred_xmit; - return 0; - default: - return -EPROTONOSUPPORT; - } -} - -static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, - bool flag, struct netlink_ext_ack *extack) +int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, + bool flag, struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; @@ -3588,9 +3315,9 @@ static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, return dev->dev_ops->vlan_filtering(dev, port, flag, extack); } -static int ksz_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan, - struct netlink_ext_ack *extack) +int ksz_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; @@ -3600,8 +3327,8 @@ static int ksz_port_vlan_add(struct dsa_switch *ds, int port, return dev->dev_ops->vlan_add(dev, port, vlan, extack); } -static int ksz_port_vlan_del(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +int ksz_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) { struct ksz_device *dev = ds->priv; @@ -3611,9 +3338,9 @@ static int ksz_port_vlan_del(struct dsa_switch *ds, int port, return dev->dev_ops->vlan_del(dev, port, vlan); } -static int ksz_port_mirror_add(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress, struct netlink_ext_ack *extack) +int ksz_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; @@ -3623,8 +3350,8 @@ static int ksz_port_mirror_add(struct dsa_switch *ds, int port, return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack); } -static void ksz_port_mirror_del(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror) +void ksz_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) { struct ksz_device *dev = ds->priv; @@ -3632,7 +3359,7 @@ static void ksz_port_mirror_del(struct dsa_switch *ds, int port, dev->dev_ops->mirror_del(dev, port, mirror); } -static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) +int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) { struct ksz_device *dev = ds->priv; @@ -3642,7 +3369,7 @@ static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) return dev->dev_ops->change_mtu(dev, port, mtu); } -static int ksz_max_mtu(struct dsa_switch *ds, int port) +int ksz_max_mtu(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; @@ -3690,7 +3417,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port) * Returns: true if the internal PHY on the given port supports fully * operational EEE, false otherwise. */ -static bool ksz_support_eee(struct dsa_switch *ds, int port) +bool ksz_support_eee(struct dsa_switch *ds, int port) { struct ksz_device *dev = ds->priv; @@ -3733,8 +3460,8 @@ static bool ksz_support_eee(struct dsa_switch *ds, int port) return false; } -static int ksz_set_mac_eee(struct dsa_switch *ds, int port, - struct ethtool_keee *e) +int ksz_set_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_keee *e) { struct ksz_device *dev = ds->priv; @@ -3835,19 +3562,9 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) return interface; } -static void ksz88x3_phylink_mac_config(struct phylink_config *config, - unsigned int mode, - const struct phylink_link_state *state) -{ - struct dsa_port *dp = dsa_phylink_to_port(config); - struct ksz_device *dev = dp->ds->priv; - - dev->ports[dp->index].manual_flow = !(state->pause & MLO_PAUSE_AN); -} - -static void ksz_phylink_mac_config(struct phylink_config *config, - unsigned int mode, - const struct phylink_link_state *state) +void ksz_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) { struct dsa_port *dp = dsa_phylink_to_port(config); struct ksz_device *dev = dp->ds->priv; @@ -3890,106 +3607,6 @@ bool ksz_get_gbit(struct ksz_device *dev, int port) return gbit; } -static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit) -{ - const u8 *bitval = dev->info->xmii_ctrl1; - const u16 *regs = dev->info->regs; - u8 data8; - - ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); - - data8 &= ~P_GMII_1GBIT_M; - - if (gbit) - data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); - else - data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); - - /* Write the updated value */ - ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); -} - -static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed) -{ - const u8 *bitval = dev->info->xmii_ctrl0; - const u16 *regs = dev->info->regs; - u8 data8; - - ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); - - data8 &= ~P_MII_100MBIT_M; - - if (speed == SPEED_100) - data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); - else - data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); - - /* Write the updated value */ - ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); -} - -static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed) -{ - if (speed == SPEED_1000) - ksz_set_gbit(dev, port, true); - else - ksz_set_gbit(dev, port, false); - - if (speed == SPEED_100 || speed == SPEED_10) - ksz_set_100_10mbit(dev, port, speed); -} - -static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex, - bool tx_pause, bool rx_pause) -{ - const u8 *bitval = dev->info->xmii_ctrl0; - const u32 *masks = dev->info->masks; - const u16 *regs = dev->info->regs; - u8 mask; - u8 val; - - mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] | - masks[P_MII_RX_FLOW_CTRL]; - - if (duplex == DUPLEX_FULL) - val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]); - else - val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]); - - if (tx_pause) - val |= masks[P_MII_TX_FLOW_CTRL]; - - if (rx_pause) - val |= masks[P_MII_RX_FLOW_CTRL]; - - ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val); -} - -static void ksz9477_phylink_mac_link_up(struct phylink_config *config, - struct phy_device *phydev, - unsigned int mode, - phy_interface_t interface, - int speed, int duplex, bool tx_pause, - bool rx_pause) -{ - struct dsa_port *dp = dsa_phylink_to_port(config); - struct ksz_device *dev = dp->ds->priv; - int port = dp->index; - struct ksz_port *p; - - p = &dev->ports[port]; - - /* Internal PHYs */ - if (dev->info->internal_phy[port]) - return; - - p->speed = speed; - - ksz_port_set_xmii_speed(dev, port, speed); - - ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause); -} - static int ksz_switch_detect(struct ksz_device *dev) { u8 id1, id2, id4; @@ -4089,8 +3706,8 @@ static int ksz_switch_detect(struct ksz_device *dev) return 0; } -static int ksz_cls_flower_add(struct dsa_switch *ds, int port, - struct flow_cls_offload *cls, bool ingress) +int ksz_cls_flower_add(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) { struct ksz_device *dev = ds->priv; @@ -4110,8 +3727,8 @@ static int ksz_cls_flower_add(struct dsa_switch *ds, int port, return -EOPNOTSUPP; } -static int ksz_cls_flower_del(struct dsa_switch *ds, int port, - struct flow_cls_offload *cls, bool ingress) +int ksz_cls_flower_del(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) { struct ksz_device *dev = ds->priv; @@ -4514,8 +4131,8 @@ static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port, return -EOPNOTSUPP; } -static int ksz_setup_tc(struct dsa_switch *ds, int port, - enum tc_setup_type type, void *type_data) +int ksz_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data) { switch (type) { case TC_SETUP_QDISC_CBS: @@ -4574,8 +4191,8 @@ int ksz_handle_wake_reason(struct ksz_device *dev, int port) * If enabled and supported, it sets the supported and active WoL * flags. */ -static void ksz_get_wol(struct dsa_switch *ds, int port, - struct ethtool_wolinfo *wol) +void ksz_get_wol(struct dsa_switch *ds, int port, + struct ethtool_wolinfo *wol) { struct ksz_device *dev = ds->priv; const u16 *regs = dev->info->regs; @@ -4622,8 +4239,8 @@ static void ksz_get_wol(struct dsa_switch *ds, int port, * * Return: 0 on success, or other error codes on failure. */ -static int ksz_set_wol(struct dsa_switch *ds, int port, - struct ethtool_wolinfo *wol) +int ksz_set_wol(struct dsa_switch *ds, int port, + struct ethtool_wolinfo *wol) { u8 pme_ctrl = 0, pme_ctrl_old = 0; struct ksz_device *dev = ds->priv; @@ -4737,8 +4354,8 @@ static void ksz_wol_pre_shutdown(struct ksz_device *dev, bool *wol_enabled) } } -static int ksz_port_set_mac_address(struct dsa_switch *ds, int port, - const unsigned char *addr) +int ksz_port_set_mac_address(struct dsa_switch *ds, int port, + const unsigned char *addr) { struct dsa_port *dp = dsa_to_port(ds, port); struct ethtool_wolinfo wol; @@ -4890,8 +4507,8 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds) kfree(switch_macaddr); } -static int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr, - struct netlink_ext_ack *extack) +int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr, + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; enum hsr_version ver; @@ -4939,8 +4556,8 @@ static int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr, return 0; } -static int ksz_hsr_leave(struct dsa_switch *ds, int port, - struct net_device *hsr) +int ksz_hsr_leave(struct dsa_switch *ds, int port, + struct net_device *hsr) { struct ksz_device *dev = ds->priv; @@ -4956,7 +4573,7 @@ static int ksz_hsr_leave(struct dsa_switch *ds, int port, return 0; } -static int ksz_suspend(struct dsa_switch *ds) +int ksz_suspend(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; @@ -4964,7 +4581,7 @@ static int ksz_suspend(struct dsa_switch *ds) return 0; } -static int ksz_resume(struct dsa_switch *ds) +int ksz_resume(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; @@ -4973,68 +4590,9 @@ static int ksz_resume(struct dsa_switch *ds) return 0; } -static const struct dsa_switch_ops ksz_switch_ops = { - .get_tag_protocol = ksz_get_tag_protocol, - .connect_tag_protocol = ksz_connect_tag_protocol, - .get_phy_flags = ksz_get_phy_flags, - .setup = ksz_setup, - .teardown = ksz_teardown, - .phy_read = ksz_phy_read16, - .phy_write = ksz_phy_write16, - .phylink_get_caps = ksz_phylink_get_caps, - .port_setup = ksz_port_setup, - .set_ageing_time = ksz_set_ageing_time, - .get_strings = ksz_get_strings, - .get_ethtool_stats = ksz_get_ethtool_stats, - .get_sset_count = ksz_sset_count, - .port_bridge_join = ksz_port_bridge_join, - .port_bridge_leave = ksz_port_bridge_leave, - .port_hsr_join = ksz_hsr_join, - .port_hsr_leave = ksz_hsr_leave, - .port_set_mac_address = ksz_port_set_mac_address, - .port_stp_state_set = ksz_port_stp_state_set, - .port_teardown = ksz_port_teardown, - .port_pre_bridge_flags = ksz_port_pre_bridge_flags, - .port_bridge_flags = ksz_port_bridge_flags, - .port_fast_age = ksz_port_fast_age, - .port_vlan_filtering = ksz_port_vlan_filtering, - .port_vlan_add = ksz_port_vlan_add, - .port_vlan_del = ksz_port_vlan_del, - .port_fdb_dump = ksz_port_fdb_dump, - .port_fdb_add = ksz_port_fdb_add, - .port_fdb_del = ksz_port_fdb_del, - .port_mdb_add = ksz_port_mdb_add, - .port_mdb_del = ksz_port_mdb_del, - .port_mirror_add = ksz_port_mirror_add, - .port_mirror_del = ksz_port_mirror_del, - .get_stats64 = ksz_get_stats64, - .get_pause_stats = ksz_get_pause_stats, - .port_change_mtu = ksz_change_mtu, - .port_max_mtu = ksz_max_mtu, - .get_wol = ksz_get_wol, - .set_wol = ksz_set_wol, - .suspend = ksz_suspend, - .resume = ksz_resume, - .get_ts_info = ksz_get_ts_info, - .port_hwtstamp_get = ksz_hwtstamp_get, - .port_hwtstamp_set = ksz_hwtstamp_set, - .port_txtstamp = ksz_port_txtstamp, - .port_rxtstamp = ksz_port_rxtstamp, - .cls_flower_add = ksz_cls_flower_add, - .cls_flower_del = ksz_cls_flower_del, - .port_setup_tc = ksz_setup_tc, - .support_eee = ksz_support_eee, - .set_mac_eee = ksz_set_mac_eee, - .port_get_default_prio = ksz_port_get_default_prio, - .port_set_default_prio = ksz_port_set_default_prio, - .port_get_dscp_prio = ksz_port_get_dscp_prio, - .port_add_dscp_prio = ksz_port_add_dscp_prio, - .port_del_dscp_prio = ksz_port_del_dscp_prio, - .port_get_apptrust = ksz_port_get_apptrust, - .port_set_apptrust = ksz_port_set_apptrust, -}; - -struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) +struct ksz_device *ksz_switch_alloc(struct device *base, + const struct ksz_chip_data *chip, + void *priv) { struct dsa_switch *ds; struct ksz_device *swdev; @@ -5045,7 +4603,7 @@ struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) ds->dev = base; ds->num_ports = DSA_MAX_PORTS; - ds->ops = &ksz_switch_ops; + ds->ops = chip->switch_ops; swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); if (!swdev) diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 18f13ee9c7b6..3dde7e771727 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -73,6 +73,7 @@ struct ksz_chip_data { */ bool phy_side_mdio_supported; const struct ksz_dev_ops *ops; + const struct dsa_switch_ops *switch_ops; const struct phylink_mac_ops *phylink_mac_ops; bool phy_errata_9477; bool ksz87xx_eee_link_erratum; @@ -363,7 +364,6 @@ struct ksz_dev_ops { u32 (*get_port_addr)(int port, int offset); void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); - void (*port_cleanup)(struct ksz_device *dev, int port); void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); int (*set_ageing_time)(struct ksz_device *dev, unsigned int msecs); @@ -460,12 +460,19 @@ struct ksz_dev_ops { int (*pcs_create)(struct ksz_device *dev); }; -struct ksz_device *ksz_switch_alloc(struct device *base, void *priv); +struct ksz_device *ksz_switch_alloc(struct device *base, + const struct ksz_chip_data *chip, + void *priv); int ksz_switch_register(struct ksz_device *dev); void ksz_switch_remove(struct ksz_device *dev); int ksz_switch_suspend(struct device *dev); int ksz_switch_resume(struct device *dev); +int ksz_setup(struct dsa_switch *ds); +void ksz_teardown(struct dsa_switch *ds); +int ksz_port_setup(struct dsa_switch *ds, int port); +void ksz_port_teardown(struct dsa_switch *ds, int port); + void ksz_init_mib_timer(struct ksz_device *dev); bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port); void ksz_r_mib_stats64(struct ksz_device *dev, int port); @@ -480,6 +487,101 @@ void ksz_switch_macaddr_put(struct dsa_switch *ds); void ksz_switch_shutdown(struct ksz_device *dev); int ksz_handle_wake_reason(struct ksz_device *dev, int port); +int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg); +int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val); +u32 ksz_get_phy_flags(struct dsa_switch *ds, int port); + +int ksz_sset_count(struct dsa_switch *ds, int port, int sset); +void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, + uint64_t *buf); +void ksz_get_stats64(struct dsa_switch *ds, int port, + struct rtnl_link_stats64 *s); +void ksz_get_pause_stats(struct dsa_switch *ds, int port, + struct ethtool_pause_stats *pause_stats); +void ksz_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *buf); + +int ksz_port_bridge_join(struct dsa_switch *ds, int port, + struct dsa_bridge bridge, + bool *tx_fwd_offload, + struct netlink_ext_ack *extack); +void ksz_port_bridge_leave(struct dsa_switch *ds, int port, + struct dsa_bridge bridge); +int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack); +int ksz_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack); +int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, + bool flag, struct netlink_ext_ack *extack); +int ksz_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack); +int ksz_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan); +void ksz_port_fast_age(struct dsa_switch *ds, int port); +int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs); +int ksz_port_fdb_add(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid, + struct dsa_db db); +int ksz_port_fdb_del(struct dsa_switch *ds, int port, + const unsigned char *addr, + u16 vid, struct dsa_db db); +int ksz_port_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data); +int ksz_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db); +int ksz_port_mdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db); + +void ksz_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config); +void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config); +int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config, + u32 timer, bool tx_clock_stop); +void ksz_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state); +void ksz_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface); + +int ksz_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, struct netlink_ext_ack *extack); +void ksz_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror); +int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu); +int ksz_max_mtu(struct dsa_switch *ds, int port); + +bool ksz_support_eee(struct dsa_switch *ds, int port); +int ksz_set_mac_eee(struct dsa_switch *ds, int port, + struct ethtool_keee *e); + +int ksz_cls_flower_add(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress); +int ksz_cls_flower_del(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress); +int ksz_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data); + +void ksz_get_wol(struct dsa_switch *ds, int port, + struct ethtool_wolinfo *wol); +int ksz_set_wol(struct dsa_switch *ds, int port, + struct ethtool_wolinfo *wol); +int ksz_port_set_mac_address(struct dsa_switch *ds, int port, + const unsigned char *addr); +int ksz_hsr_join(struct dsa_switch *ds, int port, struct net_device *hsr, + struct netlink_ext_ack *extack); +int ksz_hsr_leave(struct dsa_switch *ds, int port, + struct net_device *hsr); + +int ksz_suspend(struct dsa_switch *ds); +int ksz_resume(struct dsa_switch *ds); + /* Common register access functions */ static inline struct regmap *ksz_regmap_8(struct ksz_device *dev) { diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index d8001734b057..373e9054947c 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -143,14 +143,14 @@ static int ksz_spi_probe(struct spi_device *spi) struct ksz_device *dev; int i, ret = 0; - dev = ksz_switch_alloc(&spi->dev, spi); - if (!dev) - return -ENOMEM; - chip = device_get_match_data(ddev); if (!chip) return -EINVAL; + dev = ksz_switch_alloc(&spi->dev, chip, spi); + if (!dev) + return -ENOMEM; + /* Save chip id to do special initialization when probing. */ dev->chip_id = chip->chip_id; if (chip->chip_id == KSZ88X3_CHIP_ID) diff --git a/drivers/net/dsa/microchip/lan937x.h b/drivers/net/dsa/microchip/lan937x.h index df13ebbd356f..d12483f9081d 100644 --- a/drivers/net/dsa/microchip/lan937x.h +++ b/drivers/net/dsa/microchip/lan937x.h @@ -6,21 +6,8 @@ #ifndef __LAN937X_CFG_H #define __LAN937X_CFG_H -int lan937x_reset_switch(struct ksz_device *dev); -int lan937x_setup(struct dsa_switch *ds); -void lan937x_teardown(struct dsa_switch *ds); -void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port); -void lan937x_config_cpu_port(struct dsa_switch *ds); -int lan937x_switch_init(struct ksz_device *dev); -void lan937x_switch_exit(struct ksz_device *dev); -int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio); -int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio); -int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data); -int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val); -int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu); -void lan937x_phylink_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config); -void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port); -int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs); -int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val); +extern const struct ksz_dev_ops lan937x_dev_ops; +extern const struct phylink_mac_ops lan937x_phylink_mac_ops; +extern const struct dsa_switch_ops lan937x_switch_ops; + #endif diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c index 5a1496fff445..e522990cce22 100644 --- a/drivers/net/dsa/microchip/lan937x_main.c +++ b/drivers/net/dsa/microchip/lan937x_main.c @@ -2,6 +2,7 @@ /* Microchip LAN937X switch driver main logic * Copyright (C) 2019-2024 Microchip Technology Inc. */ +#include <linux/dsa/ksz_common.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/iopoll.h> @@ -15,6 +16,7 @@ #include "lan937x_reg.h" #include "ksz_common.h" +#include "ksz_dcb.h" #include "ksz9477.h" #include "lan937x.h" @@ -137,7 +139,7 @@ static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset, * * Return: 0 on success, error code on failure. */ -int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio) +static int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio) { static const u8 *phy_addr_map; u32 strap_val; @@ -221,7 +223,7 @@ int lan937x_create_phy_addr_map(struct ksz_device *dev, bool side_mdio) * * Return: 0 on success, error code on failure. */ -int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio) +static int lan937x_mdio_bus_preinit(struct ksz_device *dev, bool side_mdio) { u16 data16; int ret; @@ -332,17 +334,17 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg, return ksz_read16(dev, REG_VPHY_IND_DATA__2, val); } -int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) +static int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data) { return lan937x_internal_phy_read(dev, addr, reg, data); } -int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) +static int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val) { return lan937x_internal_phy_write(dev, addr, reg, val); } -int lan937x_reset_switch(struct ksz_device *dev) +static int lan937x_reset_switch(struct ksz_device *dev) { u32 data32; int ret; @@ -373,7 +375,7 @@ int lan937x_reset_switch(struct ksz_device *dev) return ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32); } -void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port) +static void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port) { const u32 *masks = dev->info->masks; const u16 *regs = dev->info->regs; @@ -409,7 +411,7 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port) dev->dev_ops->cfg_port_member(dev, port, member); } -void lan937x_config_cpu_port(struct dsa_switch *ds) +static void lan937x_config_cpu_port(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; struct dsa_port *dp; @@ -428,7 +430,7 @@ void lan937x_config_cpu_port(struct dsa_switch *ds) } } -int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu) +static int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu) { struct dsa_switch *ds = dev->ds; int ret; @@ -459,7 +461,7 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu) return 0; } -int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs) +static int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs) { u8 data, mult, value8; bool in_msec = false; @@ -572,8 +574,8 @@ static void lan937x_set_rgmii_rx_delay(struct ksz_device *dev, int port) lan937x_set_tune_adj(dev, port, REG_PORT_XMII_CTRL_4, val); } -void lan937x_phylink_get_caps(struct ksz_device *dev, int port, - struct phylink_config *config) +static void lan937x_phylink_get_caps(struct ksz_device *dev, int port, + struct phylink_config *config) { config->mac_capabilities = MAC_100FD; @@ -587,7 +589,7 @@ void lan937x_phylink_get_caps(struct ksz_device *dev, int port, } } -void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port) +static void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port) { struct ksz_port *p = &dev->ports[port]; @@ -604,19 +606,19 @@ void lan937x_setup_rgmii_delay(struct ksz_device *dev, int port) } } -int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val) +static int lan937x_tc_cbs_set_cinc(struct ksz_device *dev, int port, u32 val) { return ksz_pwrite32(dev, port, REG_PORT_MTI_CREDIT_INCREMENT, val); } -int lan937x_switch_init(struct ksz_device *dev) +static int lan937x_switch_init(struct ksz_device *dev) { dev->port_mask = (1 << dev->info->port_cnt) - 1; return 0; } -int lan937x_setup(struct dsa_switch *ds) +static int lan937x_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; int ret; @@ -656,16 +658,144 @@ int lan937x_setup(struct dsa_switch *ds) SW_VPHY_DISABLE); } -void lan937x_teardown(struct dsa_switch *ds) +static void lan937x_teardown(struct dsa_switch *ds) { } -void lan937x_switch_exit(struct ksz_device *dev) +static void lan937x_switch_exit(struct ksz_device *dev) { lan937x_reset_switch(dev); } +static enum dsa_tag_protocol lan937x_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) +{ + return DSA_TAG_PROTO_LAN937X; +} + +static int lan937x_connect_tag_protocol(struct dsa_switch *ds, + enum dsa_tag_protocol proto) +{ + struct ksz_tagger_data *tagger_data; + + if (proto != DSA_TAG_PROTO_LAN937X) + return -EPROTONOSUPPORT; + + tagger_data = ksz_tagger_data(ds); + tagger_data->xmit_work_fn = ksz_port_deferred_xmit; + + return 0; +} + +const struct phylink_mac_ops lan937x_phylink_mac_ops = { + .mac_config = ksz_phylink_mac_config, + .mac_link_down = ksz_phylink_mac_link_down, + .mac_link_up = ksz9477_phylink_mac_link_up, + .mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi, + .mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi, +}; + +const struct ksz_dev_ops lan937x_dev_ops = { + .setup = lan937x_setup, + .teardown = lan937x_teardown, + .get_port_addr = ksz9477_get_port_addr, + .cfg_port_member = ksz9477_cfg_port_member, + .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, + .port_setup = lan937x_port_setup, + .set_ageing_time = lan937x_set_ageing_time, + .mdio_bus_preinit = lan937x_mdio_bus_preinit, + .create_phy_addr_map = lan937x_create_phy_addr_map, + .r_phy = lan937x_r_phy, + .w_phy = lan937x_w_phy, + .r_mib_cnt = ksz9477_r_mib_cnt, + .r_mib_pkt = ksz9477_r_mib_pkt, + .r_mib_stat64 = ksz_r_mib_stats64, + .freeze_mib = ksz9477_freeze_mib, + .port_init_cnt = ksz9477_port_init_cnt, + .vlan_filtering = ksz9477_port_vlan_filtering, + .vlan_add = ksz9477_port_vlan_add, + .vlan_del = ksz9477_port_vlan_del, + .mirror_add = ksz9477_port_mirror_add, + .mirror_del = ksz9477_port_mirror_del, + .get_caps = lan937x_phylink_get_caps, + .setup_rgmii_delay = lan937x_setup_rgmii_delay, + .fdb_dump = ksz9477_fdb_dump, + .fdb_add = ksz9477_fdb_add, + .fdb_del = ksz9477_fdb_del, + .mdb_add = ksz9477_mdb_add, + .mdb_del = ksz9477_mdb_del, + .change_mtu = lan937x_change_mtu, + .config_cpu_port = lan937x_config_cpu_port, + .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc, + .enable_stp_addr = ksz9477_enable_stp_addr, + .reset = lan937x_reset_switch, + .init = lan937x_switch_init, + .exit = lan937x_switch_exit, +}; + +const struct dsa_switch_ops lan937x_switch_ops = { + .get_tag_protocol = lan937x_get_tag_protocol, + .connect_tag_protocol = lan937x_connect_tag_protocol, + .get_phy_flags = ksz_get_phy_flags, + .setup = ksz_setup, + .teardown = ksz_teardown, + .phy_read = ksz_phy_read16, + .phy_write = ksz_phy_write16, + .phylink_get_caps = ksz_phylink_get_caps, + .port_setup = ksz_port_setup, + .set_ageing_time = ksz_set_ageing_time, + .get_strings = ksz_get_strings, + .get_ethtool_stats = ksz_get_ethtool_stats, + .get_sset_count = ksz_sset_count, + .port_bridge_join = ksz_port_bridge_join, + .port_bridge_leave = ksz_port_bridge_leave, + .port_hsr_join = ksz_hsr_join, + .port_hsr_leave = ksz_hsr_leave, + .port_set_mac_address = ksz_port_set_mac_address, + .port_stp_state_set = ksz_port_stp_state_set, + .port_teardown = ksz_port_teardown, + .port_pre_bridge_flags = ksz_port_pre_bridge_flags, + .port_bridge_flags = ksz_port_bridge_flags, + .port_fast_age = ksz_port_fast_age, + .port_vlan_filtering = ksz_port_vlan_filtering, + .port_vlan_add = ksz_port_vlan_add, + .port_vlan_del = ksz_port_vlan_del, + .port_fdb_dump = ksz_port_fdb_dump, + .port_fdb_add = ksz_port_fdb_add, + .port_fdb_del = ksz_port_fdb_del, + .port_mdb_add = ksz_port_mdb_add, + .port_mdb_del = ksz_port_mdb_del, + .port_mirror_add = ksz_port_mirror_add, + .port_mirror_del = ksz_port_mirror_del, + .get_stats64 = ksz_get_stats64, + .get_pause_stats = ksz_get_pause_stats, + .port_change_mtu = ksz_change_mtu, + .port_max_mtu = ksz_max_mtu, + .get_wol = ksz_get_wol, + .set_wol = ksz_set_wol, + .suspend = ksz_suspend, + .resume = ksz_resume, + .get_ts_info = ksz_get_ts_info, + .port_hwtstamp_get = ksz_hwtstamp_get, + .port_hwtstamp_set = ksz_hwtstamp_set, + .port_txtstamp = ksz_port_txtstamp, + .port_rxtstamp = ksz_port_rxtstamp, + .cls_flower_add = ksz_cls_flower_add, + .cls_flower_del = ksz_cls_flower_del, + .port_setup_tc = ksz_setup_tc, + .support_eee = ksz_support_eee, + .set_mac_eee = ksz_set_mac_eee, + .port_get_default_prio = ksz_port_get_default_prio, + .port_set_default_prio = ksz_port_set_default_prio, + .port_get_dscp_prio = ksz_port_get_dscp_prio, + .port_add_dscp_prio = ksz_port_add_dscp_prio, + .port_del_dscp_prio = ksz_port_del_dscp_prio, + .port_get_apptrust = ksz_port_get_apptrust, + .port_set_apptrust = ksz_port_set_apptrust, +}; + MODULE_AUTHOR("Arun Ramadoss <arun.ramadoss@microchip.com>"); MODULE_DESCRIPTION("Microchip LAN937x Series Switch DSA Driver"); MODULE_LICENSE("GPL"); |
