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>
This commit is contained in:
Jakub Kicinski 2026-05-08 19:10:13 -07:00
commit 8b2feced65
11 changed files with 1108 additions and 754 deletions

View File

@ -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");

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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++) {

File diff suppressed because it is too large Load Diff

View File

@ -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)
{

View File

@ -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)

View File

@ -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

View File

@ -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");