Merge branch 'net-dsa-microchip-common-spi-probe-for-the-ksz-series-switches-part-1'
Arun Ramadoss says: ==================== net: dsa: microchip: common spi probe for the ksz series switches - part 1 This patch series aims to refactor the ksz_switch_register routine to have the common flow for the ksz series switch. At present ksz8795.c & ksz9477.c have its own dsa_switch_ops and switch detect functionality. In ksz_switch_register, ksz_dev_ops is assigned based on the function parameter passed by the individual ksz8/ksz9477 switch register function. And then switch detect is performed based on the ksz_dev_ops.detect hook. This patch modifies the ksz_switch_register such a way that switch detect is performed first, based on the chip ksz_dev_ops is assigned to ksz_device structure. It ensures the common flow for the existing as well as LAN937x switches. In the next series of patch, it will move ksz_dsa_ops and dsa_switch_ops from ksz8795.c and ksz9477.c to ksz_common.c and have the common spi probe all the ksz based switches. Changes in v1 - Splitted the patch series into two. - Replaced all occurrence of REG_PORT_STATUS_0 and PORT_FIBER_MODE to KSZ8_PORT_STATUS_0 and KSZ8_PORT_FIBER_MODE. - Separated the tag protocol and phy read/write patch into two. - Assigned the DSA_TAG_PROTO_NONE as the default value for get_tag_protocol hook. - Reduced the indentation level by using the if(!dev->dev_ops->mirror_add). - Added the stp_ctrl_reg as a member in ksz_chip_data and removed the member in ksz_dev_ops. - Removed the r_dyn_mac_table, r_sta_mac_table and w_sta_mac_table from the ksz_dev_ops since it is used only in the ksz8795.c. Changes in RFC v2 - Fixed the compilation issue. - Reduced the patch set to 15. ==================== Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Link: https://lore.kernel.org/r/20220617084255.19376-1-arun.ramadoss@microchip.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
8720bd951b
@ -898,29 +898,6 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
|
||||
}
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol ksz8_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port,
|
||||
enum dsa_tag_protocol mp)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
/* ksz88x3 uses the same tag schema as KSZ9893 */
|
||||
return ksz_is_ksz88x3(dev) ?
|
||||
DSA_TAG_PROTO_KSZ9893 : DSA_TAG_PROTO_KSZ8795;
|
||||
}
|
||||
|
||||
static u32 ksz8_sw_get_phy_flags(struct dsa_switch *ds, int port)
|
||||
{
|
||||
/* Silicon Errata Sheet (DS80000830A):
|
||||
* Port 1 does not work with LinkMD Cable-Testing.
|
||||
* Port 1 does not respond to received PAUSE control frames.
|
||||
*/
|
||||
if (!port)
|
||||
return MICREL_KSZ8_P1_ERRATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
|
||||
{
|
||||
u8 data;
|
||||
@ -931,11 +908,6 @@ static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
|
||||
ksz_pwrite8(dev, port, P_MIRROR_CTRL, data);
|
||||
}
|
||||
|
||||
static void ksz8_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
{
|
||||
ksz_port_stp_state_set(ds, port, state, P_STP_CTRL);
|
||||
}
|
||||
|
||||
static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
{
|
||||
u8 learn[DSA_MAX_PORTS];
|
||||
@ -969,11 +941,111 @@ static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
}
|
||||
}
|
||||
|
||||
static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
|
||||
static int ksz8_fdb_dump(struct ksz_device *dev, int port,
|
||||
dsa_fdb_dump_cb_t *cb, void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 i = 0;
|
||||
u16 entries = 0;
|
||||
u8 timestamp = 0;
|
||||
u8 fid;
|
||||
u8 member;
|
||||
struct alu_struct alu;
|
||||
|
||||
do {
|
||||
alu.is_static = false;
|
||||
ret = ksz8_r_dyn_mac_table(dev, i, alu.mac, &fid, &member,
|
||||
×tamp, &entries);
|
||||
if (!ret && (member & BIT(port))) {
|
||||
ret = cb(alu.mac, alu.fid, alu.is_static, data);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while (i < entries);
|
||||
if (i >= entries)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ksz8_mdb_add(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct alu_struct alu;
|
||||
int index;
|
||||
int empty = 0;
|
||||
|
||||
alu.port_forward = 0;
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!ksz8_r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
alu.fid == mdb->vid)
|
||||
break;
|
||||
/* Remember the first empty entry. */
|
||||
} else if (!empty) {
|
||||
empty = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->info->num_statics && !empty)
|
||||
return -ENOSPC;
|
||||
|
||||
/* add entry */
|
||||
if (index == dev->info->num_statics) {
|
||||
index = empty - 1;
|
||||
memset(&alu, 0, sizeof(alu));
|
||||
memcpy(alu.mac, mdb->addr, ETH_ALEN);
|
||||
alu.is_static = true;
|
||||
}
|
||||
alu.port_forward |= BIT(port);
|
||||
if (mdb->vid) {
|
||||
alu.is_use_fid = true;
|
||||
|
||||
/* Need a way to map VID to FID. */
|
||||
alu.fid = mdb->vid;
|
||||
}
|
||||
ksz8_w_sta_mac_table(dev, index, &alu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_mdb_del(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct alu_struct alu;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!ksz8_r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
alu.fid == mdb->vid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->info->num_statics)
|
||||
goto exit;
|
||||
|
||||
/* clear port */
|
||||
alu.port_forward &= ~BIT(port);
|
||||
if (!alu.port_forward)
|
||||
alu.is_static = false;
|
||||
ksz8_w_sta_mac_table(dev, index, &alu);
|
||||
|
||||
exit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_port_vlan_filtering(struct ksz_device *dev, int port, bool flag,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (ksz_is_ksz88x3(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
@ -998,12 +1070,11 @@ static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
|
||||
}
|
||||
}
|
||||
|
||||
static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
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_device *dev = ds->priv;
|
||||
struct ksz_port *p = &dev->ports[port];
|
||||
u16 data, new_pvid = 0;
|
||||
u8 fid, member, valid;
|
||||
@ -1071,10 +1142,9 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
static int ksz8_port_vlan_del(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u16 data, pvid;
|
||||
u8 fid, member, valid;
|
||||
|
||||
@ -1104,12 +1174,10 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
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)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (ingress) {
|
||||
ksz_port_cfg(dev, port, P_MIRROR_CTRL, PORT_MIRROR_RX, true);
|
||||
dev->mirror_rx |= BIT(port);
|
||||
@ -1128,10 +1196,9 @@ static int ksz8_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ksz8_port_mirror_del(struct dsa_switch *ds, int port,
|
||||
static void ksz8_port_mirror_del(struct ksz_device *dev, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u8 data;
|
||||
|
||||
if (mirror->ingress) {
|
||||
@ -1258,7 +1325,7 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
|
||||
for (i = 0; i < dev->phy_port_cnt; i++) {
|
||||
p = &dev->ports[i];
|
||||
|
||||
ksz8_port_stp_state_set(ds, i, BR_STATE_DISABLED);
|
||||
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
|
||||
|
||||
/* Last port may be disabled. */
|
||||
if (i == dev->phy_port_cnt)
|
||||
@ -1272,7 +1339,7 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds)
|
||||
continue;
|
||||
if (!ksz_is_ksz88x3(dev)) {
|
||||
ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
|
||||
if (remote & PORT_FIBER_MODE)
|
||||
if (remote & KSZ8_PORT_FIBER_MODE)
|
||||
p->fiber = 1;
|
||||
}
|
||||
if (p->fiber)
|
||||
@ -1371,13 +1438,9 @@ static int ksz8_setup(struct dsa_switch *ds)
|
||||
return ksz8_handle_global_errata(ds);
|
||||
}
|
||||
|
||||
static void ksz8_get_caps(struct dsa_switch *ds, int port,
|
||||
static void ksz8_get_caps(struct ksz_device *dev, int port,
|
||||
struct phylink_config *config)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
ksz_phylink_get_caps(ds, port, config);
|
||||
|
||||
config->mac_capabilities = MAC_10 | MAC_100;
|
||||
|
||||
/* Silicon Errata Sheet (DS80000830A):
|
||||
@ -1394,12 +1457,12 @@ static void ksz8_get_caps(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
static const struct dsa_switch_ops ksz8_switch_ops = {
|
||||
.get_tag_protocol = ksz8_get_tag_protocol,
|
||||
.get_phy_flags = ksz8_sw_get_phy_flags,
|
||||
.get_tag_protocol = ksz_get_tag_protocol,
|
||||
.get_phy_flags = ksz_get_phy_flags,
|
||||
.setup = ksz8_setup,
|
||||
.phy_read = ksz_phy_read16,
|
||||
.phy_write = ksz_phy_write16,
|
||||
.phylink_get_caps = ksz8_get_caps,
|
||||
.phylink_get_caps = ksz_phylink_get_caps,
|
||||
.phylink_mac_link_down = ksz_mac_link_down,
|
||||
.port_enable = ksz_enable_port,
|
||||
.get_strings = ksz_get_strings,
|
||||
@ -1407,16 +1470,16 @@ static const struct dsa_switch_ops ksz8_switch_ops = {
|
||||
.get_sset_count = ksz_sset_count,
|
||||
.port_bridge_join = ksz_port_bridge_join,
|
||||
.port_bridge_leave = ksz_port_bridge_leave,
|
||||
.port_stp_state_set = ksz8_port_stp_state_set,
|
||||
.port_stp_state_set = ksz_port_stp_state_set,
|
||||
.port_fast_age = ksz_port_fast_age,
|
||||
.port_vlan_filtering = ksz8_port_vlan_filtering,
|
||||
.port_vlan_add = ksz8_port_vlan_add,
|
||||
.port_vlan_del = ksz8_port_vlan_del,
|
||||
.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_mdb_add = ksz_port_mdb_add,
|
||||
.port_mdb_del = ksz_port_mdb_del,
|
||||
.port_mirror_add = ksz8_port_mirror_add,
|
||||
.port_mirror_del = ksz8_port_mirror_del,
|
||||
.port_mirror_add = ksz_port_mirror_add,
|
||||
.port_mirror_del = ksz_port_mirror_del,
|
||||
};
|
||||
|
||||
static u32 ksz8_get_port_addr(int port, int offset)
|
||||
@ -1424,51 +1487,6 @@ static u32 ksz8_get_port_addr(int port, int offset)
|
||||
return PORT_CTRL_ADDR(port, offset);
|
||||
}
|
||||
|
||||
static int ksz8_switch_detect(struct ksz_device *dev)
|
||||
{
|
||||
u8 id1, id2;
|
||||
u16 id16;
|
||||
int ret;
|
||||
|
||||
/* read chip id */
|
||||
ret = ksz_read16(dev, REG_CHIP_ID0, &id16);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
id1 = id16 >> 8;
|
||||
id2 = id16 & SW_CHIP_ID_M;
|
||||
|
||||
switch (id1) {
|
||||
case KSZ87_FAMILY_ID:
|
||||
if ((id2 != CHIP_ID_94 && id2 != CHIP_ID_95))
|
||||
return -ENODEV;
|
||||
|
||||
if (id2 == CHIP_ID_95) {
|
||||
u8 val;
|
||||
|
||||
id2 = 0x95;
|
||||
ksz_read8(dev, REG_PORT_STATUS_0, &val);
|
||||
if (val & PORT_FIBER_MODE)
|
||||
id2 = 0x65;
|
||||
} else if (id2 == CHIP_ID_94) {
|
||||
id2 = 0x94;
|
||||
}
|
||||
break;
|
||||
case KSZ88_FAMILY_ID:
|
||||
if (id2 != CHIP_ID_63)
|
||||
return -ENODEV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "invalid family id: %d\n", id1);
|
||||
return -ENODEV;
|
||||
}
|
||||
id16 &= ~0xff;
|
||||
id16 |= id2;
|
||||
dev->chip_id = id16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz8_switch_init(struct ksz_device *dev)
|
||||
{
|
||||
struct ksz8 *ksz8 = dev->priv;
|
||||
@ -1514,15 +1532,20 @@ static const struct ksz_dev_ops ksz8_dev_ops = {
|
||||
.port_setup = ksz8_port_setup,
|
||||
.r_phy = ksz8_r_phy,
|
||||
.w_phy = ksz8_w_phy,
|
||||
.r_dyn_mac_table = ksz8_r_dyn_mac_table,
|
||||
.r_sta_mac_table = ksz8_r_sta_mac_table,
|
||||
.w_sta_mac_table = ksz8_w_sta_mac_table,
|
||||
.r_mib_cnt = ksz8_r_mib_cnt,
|
||||
.r_mib_pkt = ksz8_r_mib_pkt,
|
||||
.freeze_mib = ksz8_freeze_mib,
|
||||
.port_init_cnt = ksz8_port_init_cnt,
|
||||
.fdb_dump = ksz8_fdb_dump,
|
||||
.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,
|
||||
.shutdown = ksz8_reset_switch,
|
||||
.detect = ksz8_switch_detect,
|
||||
.init = ksz8_switch_init,
|
||||
.exit = ksz8_switch_exit,
|
||||
};
|
||||
|
@ -14,23 +14,10 @@
|
||||
#define KS_PRIO_M 0x3
|
||||
#define KS_PRIO_S 2
|
||||
|
||||
#define REG_CHIP_ID0 0x00
|
||||
|
||||
#define KSZ87_FAMILY_ID 0x87
|
||||
#define KSZ88_FAMILY_ID 0x88
|
||||
|
||||
#define REG_CHIP_ID1 0x01
|
||||
|
||||
#define SW_CHIP_ID_M 0xF0
|
||||
#define SW_CHIP_ID_S 4
|
||||
#define SW_REVISION_M 0x0E
|
||||
#define SW_REVISION_S 1
|
||||
#define SW_START 0x01
|
||||
|
||||
#define CHIP_ID_94 0x60
|
||||
#define CHIP_ID_95 0x90
|
||||
#define CHIP_ID_63 0x30
|
||||
|
||||
#define KSZ8863_REG_SW_RESET 0x43
|
||||
|
||||
#define KSZ8863_GLOBAL_SOFTWARE_RESET BIT(4)
|
||||
@ -217,8 +204,6 @@
|
||||
#define REG_PORT_4_STATUS_0 0x48
|
||||
|
||||
/* For KSZ8765. */
|
||||
#define PORT_FIBER_MODE BIT(7)
|
||||
|
||||
#define PORT_REMOTE_ASYM_PAUSE BIT(5)
|
||||
#define PORT_REMOTE_SYM_PAUSE BIT(4)
|
||||
#define PORT_REMOTE_100BTX_FD BIT(3)
|
||||
@ -322,7 +307,6 @@
|
||||
|
||||
#define REG_PORT_CTRL_5 0x05
|
||||
|
||||
#define REG_PORT_STATUS_0 0x08
|
||||
#define REG_PORT_STATUS_1 0x09
|
||||
#define REG_PORT_LINK_MD_CTRL 0x0A
|
||||
#define REG_PORT_LINK_MD_RESULT 0x0B
|
||||
|
@ -47,9 +47,8 @@ static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset,
|
||||
bits, set ? bits : 0);
|
||||
}
|
||||
|
||||
static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)
|
||||
static int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u16 frame_size, max_frame = 0;
|
||||
int i;
|
||||
|
||||
@ -65,7 +64,7 @@ static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)
|
||||
REG_SW_MTU_MASK, max_frame);
|
||||
}
|
||||
|
||||
static int ksz9477_max_mtu(struct dsa_switch *ds, int port)
|
||||
static int ksz9477_max_mtu(struct ksz_device *dev, int port)
|
||||
{
|
||||
return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
|
||||
}
|
||||
@ -276,21 +275,8 @@ static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
|
||||
mutex_unlock(&mib->cnt_mutex);
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port,
|
||||
enum dsa_tag_protocol mp)
|
||||
static void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
|
||||
{
|
||||
enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477;
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (dev->features & IS_9893)
|
||||
proto = DSA_TAG_PROTO_KSZ9893;
|
||||
return proto;
|
||||
}
|
||||
|
||||
static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u16 val = 0xffff;
|
||||
|
||||
/* No real PHY after this. Simulate the PHY.
|
||||
@ -335,24 +321,20 @@ static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
|
||||
ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
|
||||
}
|
||||
|
||||
return val;
|
||||
*data = val;
|
||||
}
|
||||
|
||||
static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
|
||||
u16 val)
|
||||
static void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
/* No real PHY after this. */
|
||||
if (addr >= dev->phy_port_cnt)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* No gigabit support. Do not write to this register. */
|
||||
if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
|
||||
return 0;
|
||||
ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
|
||||
return;
|
||||
|
||||
return 0;
|
||||
ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
|
||||
}
|
||||
|
||||
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
|
||||
@ -361,12 +343,6 @@ static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
|
||||
ksz_pwrite32(dev, port, REG_PORT_VLAN_MEMBERSHIP__4, member);
|
||||
}
|
||||
|
||||
static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
|
||||
u8 state)
|
||||
{
|
||||
ksz_port_stp_state_set(ds, port, state, P_STP_CTRL);
|
||||
}
|
||||
|
||||
static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
{
|
||||
u8 data;
|
||||
@ -389,12 +365,10 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
}
|
||||
}
|
||||
|
||||
static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
static int ksz9477_port_vlan_filtering(struct ksz_device *dev, int port,
|
||||
bool flag,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (flag) {
|
||||
ksz_port_cfg(dev, port, REG_PORT_LUE_CTRL,
|
||||
PORT_VLAN_LOOKUP_VID_0, true);
|
||||
@ -408,11 +382,10 @@ static int ksz9477_port_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
static int ksz9477_port_vlan_add(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u32 vlan_table[3];
|
||||
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
|
||||
int err;
|
||||
@ -445,10 +418,9 @@ static int ksz9477_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
static int ksz9477_port_vlan_del(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
|
||||
u32 vlan_table[3];
|
||||
u16 pvid;
|
||||
@ -479,11 +451,10 @@ static int ksz9477_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz9477_port_fdb_add(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
struct dsa_db db)
|
||||
static int ksz9477_fdb_add(struct ksz_device *dev, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u32 alu_table[4];
|
||||
u32 data;
|
||||
int ret = 0;
|
||||
@ -537,11 +508,10 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ksz9477_port_fdb_del(struct dsa_switch *ds, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
struct dsa_db db)
|
||||
static int ksz9477_fdb_del(struct ksz_device *dev, int port,
|
||||
const unsigned char *addr, u16 vid,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u32 alu_table[4];
|
||||
u32 data;
|
||||
int ret = 0;
|
||||
@ -628,10 +598,9 @@ static void ksz9477_convert_alu(struct alu_struct *alu, u32 *alu_table)
|
||||
alu->mac[5] = alu_table[3] & 0xFF;
|
||||
}
|
||||
|
||||
static int ksz9477_port_fdb_dump(struct dsa_switch *ds, int port,
|
||||
dsa_fdb_dump_cb_t *cb, void *data)
|
||||
static int ksz9477_fdb_dump(struct ksz_device *dev, int port,
|
||||
dsa_fdb_dump_cb_t *cb, void *data)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int ret = 0;
|
||||
u32 ksz_data;
|
||||
u32 alu_table[4];
|
||||
@ -680,11 +649,10 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
static int ksz9477_mdb_add(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u32 static_table[4];
|
||||
u32 data;
|
||||
int index;
|
||||
@ -756,11 +724,10 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
static int ksz9477_mdb_del(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u32 static_table[4];
|
||||
u32 data;
|
||||
int index;
|
||||
@ -832,11 +799,10 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
static int ksz9477_port_mirror_add(struct ksz_device *dev, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror,
|
||||
bool ingress, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
u8 data;
|
||||
int p;
|
||||
|
||||
@ -872,10 +838,9 @@ static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
|
||||
static void ksz9477_port_mirror_del(struct ksz_device *dev, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
bool in_use = false;
|
||||
u8 data;
|
||||
int p;
|
||||
@ -1097,11 +1062,9 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
|
||||
ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
|
||||
}
|
||||
|
||||
static void ksz9477_get_caps(struct dsa_switch *ds, int port,
|
||||
static void ksz9477_get_caps(struct ksz_device *dev, int port,
|
||||
struct phylink_config *config)
|
||||
{
|
||||
ksz_phylink_get_caps(ds, port, config);
|
||||
|
||||
config->mac_capabilities = MAC_10 | MAC_100 | MAC_1000FD |
|
||||
MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
|
||||
}
|
||||
@ -1260,7 +1223,7 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
|
||||
continue;
|
||||
p = &dev->ports[i];
|
||||
|
||||
ksz9477_port_stp_state_set(ds, i, BR_STATE_DISABLED);
|
||||
ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
|
||||
p->on = 1;
|
||||
if (i < dev->phy_port_cnt)
|
||||
p->phy = 1;
|
||||
@ -1326,33 +1289,33 @@ static int ksz9477_setup(struct dsa_switch *ds)
|
||||
}
|
||||
|
||||
static const struct dsa_switch_ops ksz9477_switch_ops = {
|
||||
.get_tag_protocol = ksz9477_get_tag_protocol,
|
||||
.get_tag_protocol = ksz_get_tag_protocol,
|
||||
.setup = ksz9477_setup,
|
||||
.phy_read = ksz9477_phy_read16,
|
||||
.phy_write = ksz9477_phy_write16,
|
||||
.phy_read = ksz_phy_read16,
|
||||
.phy_write = ksz_phy_write16,
|
||||
.phylink_mac_link_down = ksz_mac_link_down,
|
||||
.phylink_get_caps = ksz9477_get_caps,
|
||||
.phylink_get_caps = ksz_phylink_get_caps,
|
||||
.port_enable = ksz_enable_port,
|
||||
.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_stp_state_set = ksz9477_port_stp_state_set,
|
||||
.port_stp_state_set = ksz_port_stp_state_set,
|
||||
.port_fast_age = ksz_port_fast_age,
|
||||
.port_vlan_filtering = ksz9477_port_vlan_filtering,
|
||||
.port_vlan_add = ksz9477_port_vlan_add,
|
||||
.port_vlan_del = ksz9477_port_vlan_del,
|
||||
.port_fdb_dump = ksz9477_port_fdb_dump,
|
||||
.port_fdb_add = ksz9477_port_fdb_add,
|
||||
.port_fdb_del = ksz9477_port_fdb_del,
|
||||
.port_mdb_add = ksz9477_port_mdb_add,
|
||||
.port_mdb_del = ksz9477_port_mdb_del,
|
||||
.port_mirror_add = ksz9477_port_mirror_add,
|
||||
.port_mirror_del = ksz9477_port_mirror_del,
|
||||
.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,
|
||||
.port_change_mtu = ksz9477_change_mtu,
|
||||
.port_max_mtu = ksz9477_max_mtu,
|
||||
.port_change_mtu = ksz_change_mtu,
|
||||
.port_max_mtu = ksz_max_mtu,
|
||||
};
|
||||
|
||||
static u32 ksz9477_get_port_addr(int port, int offset)
|
||||
@ -1360,14 +1323,15 @@ static u32 ksz9477_get_port_addr(int port, int offset)
|
||||
return PORT_CTRL_ADDR(port, offset);
|
||||
}
|
||||
|
||||
static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
static int ksz9477_switch_init(struct ksz_device *dev)
|
||||
{
|
||||
u8 data8;
|
||||
u8 id_hi;
|
||||
u8 id_lo;
|
||||
u32 id32;
|
||||
int ret;
|
||||
|
||||
dev->ds->ops = &ksz9477_switch_ops;
|
||||
|
||||
dev->port_mask = (1 << dev->info->port_cnt) - 1;
|
||||
|
||||
/* turn off SPI DO Edge select */
|
||||
ret = ksz_read8(dev, REG_SW_GLOBAL_SERIAL_CTRL_0, &data8);
|
||||
if (ret)
|
||||
@ -1378,10 +1342,6 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read chip id */
|
||||
ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -1392,12 +1352,7 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
/* Default capability is gigabit capable. */
|
||||
dev->features = GBIT_SUPPORT;
|
||||
|
||||
dev_dbg(dev->dev, "Switch detect: ID=%08x%02x\n", id32, data8);
|
||||
id_hi = (u8)(id32 >> 16);
|
||||
id_lo = (u8)(id32 >> 8);
|
||||
if ((id_lo & 0xf) == 3) {
|
||||
/* Chip is from KSZ9893 design. */
|
||||
dev_info(dev->dev, "Found KSZ9893\n");
|
||||
if (dev->chip_id == KSZ9893_CHIP_ID) {
|
||||
dev->features |= IS_9893;
|
||||
|
||||
/* Chip does not support gigabit. */
|
||||
@ -1405,7 +1360,6 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
dev->features &= ~GBIT_SUPPORT;
|
||||
dev->phy_port_cnt = 2;
|
||||
} else {
|
||||
dev_info(dev->dev, "Found KSZ9477 or compatible\n");
|
||||
/* Chip uses new XMII register definitions. */
|
||||
dev->features |= NEW_XMII;
|
||||
|
||||
@ -1413,21 +1367,6 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
if (!(data8 & SW_GIGABIT_ABLE))
|
||||
dev->features &= ~GBIT_SUPPORT;
|
||||
}
|
||||
|
||||
/* Change chip id to known ones so it can be matched against them. */
|
||||
id32 = (id_hi << 16) | (id_lo << 8);
|
||||
|
||||
dev->chip_id = id32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ksz9477_switch_init(struct ksz_device *dev)
|
||||
{
|
||||
dev->ds->ops = &ksz9477_switch_ops;
|
||||
|
||||
dev->port_mask = (1 << dev->info->port_cnt) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1441,13 +1380,27 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
|
||||
.cfg_port_member = ksz9477_cfg_port_member,
|
||||
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
|
||||
.port_setup = ksz9477_port_setup,
|
||||
.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,
|
||||
.max_mtu = ksz9477_max_mtu,
|
||||
.shutdown = ksz9477_reset_switch,
|
||||
.detect = ksz9477_switch_detect,
|
||||
.init = ksz9477_switch_init,
|
||||
.exit = ksz9477_switch_exit,
|
||||
};
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#define REG_CHIP_ID2__1 0x0002
|
||||
|
||||
#define CHIP_ID_63 0x63
|
||||
#define CHIP_ID_66 0x66
|
||||
#define CHIP_ID_67 0x67
|
||||
#define CHIP_ID_77 0x77
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/micrel_phy.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/switchdev.h>
|
||||
|
||||
@ -151,6 +152,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x02,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
@ -183,6 +185,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x02,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
@ -201,6 +204,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x02,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
@ -218,6 +222,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz88xx_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x02,
|
||||
.supports_mii = {false, false, true},
|
||||
.supports_rmii = {false, false, true},
|
||||
.internal_phy = {true, true, false},
|
||||
@ -235,6 +240,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -257,6 +263,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -278,6 +285,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, true},
|
||||
.supports_rmii = {false, false, true},
|
||||
.supports_rgmii = {false, false, true},
|
||||
@ -296,6 +304,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -317,6 +326,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
@ -334,6 +344,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false, true, true},
|
||||
.supports_rmii = {false, false, false, false, true, true},
|
||||
.supports_rgmii = {false, false, false, false, true, true},
|
||||
@ -351,6 +362,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -372,6 +384,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -393,6 +406,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.stp_ctrl_reg = 0x0B04,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
@ -456,6 +470,9 @@ void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
if (dev->info->internal_phy[port])
|
||||
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
config->supported_interfaces);
|
||||
|
||||
if (dev->dev_ops->get_caps)
|
||||
dev->dev_ops->get_caps(dev, port, config);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_phylink_get_caps);
|
||||
|
||||
@ -532,7 +549,7 @@ void ksz_get_strings(struct dsa_switch *ds, int port,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_strings);
|
||||
|
||||
void ksz_update_port_member(struct ksz_device *dev, int port)
|
||||
static void ksz_update_port_member(struct ksz_device *dev, int port)
|
||||
{
|
||||
struct ksz_port *p = &dev->ports[port];
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
@ -589,7 +606,6 @@ void ksz_update_port_member(struct ksz_device *dev, int port)
|
||||
|
||||
dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_update_port_member);
|
||||
|
||||
static void port_r_cnt(struct ksz_device *dev, int port)
|
||||
{
|
||||
@ -690,6 +706,23 @@ int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_phy_write16);
|
||||
|
||||
u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (dev->chip_id == KSZ8830_CHIP_ID) {
|
||||
/* Silicon Errata Sheet (DS80000830A):
|
||||
* Port 1 does not work with LinkMD Cable-Testing.
|
||||
* Port 1 does not respond to received PAUSE control frames.
|
||||
*/
|
||||
if (!port)
|
||||
return MICREL_KSZ8_P1_ERRATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_phy_flags);
|
||||
|
||||
void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@ -763,34 +796,39 @@ void ksz_port_fast_age(struct dsa_switch *ds, int port)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_fast_age);
|
||||
|
||||
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;
|
||||
|
||||
if (!dev->dev_ops->fdb_add)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->fdb_add(dev, port, addr, vid, db);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_fdb_add);
|
||||
|
||||
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;
|
||||
|
||||
if (!dev->dev_ops->fdb_del)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->fdb_del(dev, port, addr, vid, db);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_fdb_del);
|
||||
|
||||
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;
|
||||
int ret = 0;
|
||||
u16 i = 0;
|
||||
u16 entries = 0;
|
||||
u8 timestamp = 0;
|
||||
u8 fid;
|
||||
u8 member;
|
||||
struct alu_struct alu;
|
||||
|
||||
do {
|
||||
alu.is_static = false;
|
||||
ret = dev->dev_ops->r_dyn_mac_table(dev, i, alu.mac, &fid,
|
||||
&member, ×tamp,
|
||||
&entries);
|
||||
if (!ret && (member & BIT(port))) {
|
||||
ret = cb(alu.mac, alu.fid, alu.is_static, data);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
} while (i < entries);
|
||||
if (i >= entries)
|
||||
ret = 0;
|
||||
if (!dev->dev_ops->fdb_dump)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ret;
|
||||
return dev->dev_ops->fdb_dump(dev, port, cb, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_fdb_dump);
|
||||
|
||||
@ -799,44 +837,11 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct alu_struct alu;
|
||||
int index;
|
||||
int empty = 0;
|
||||
|
||||
alu.port_forward = 0;
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
alu.fid == mdb->vid)
|
||||
break;
|
||||
/* Remember the first empty entry. */
|
||||
} else if (!empty) {
|
||||
empty = index + 1;
|
||||
}
|
||||
}
|
||||
if (!dev->dev_ops->mdb_add)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->info->num_statics && !empty)
|
||||
return -ENOSPC;
|
||||
|
||||
/* add entry */
|
||||
if (index == dev->info->num_statics) {
|
||||
index = empty - 1;
|
||||
memset(&alu, 0, sizeof(alu));
|
||||
memcpy(alu.mac, mdb->addr, ETH_ALEN);
|
||||
alu.is_static = true;
|
||||
}
|
||||
alu.port_forward |= BIT(port);
|
||||
if (mdb->vid) {
|
||||
alu.is_use_fid = true;
|
||||
|
||||
/* Need a way to map VID to FID. */
|
||||
alu.fid = mdb->vid;
|
||||
}
|
||||
dev->dev_ops->w_sta_mac_table(dev, index, &alu);
|
||||
|
||||
return 0;
|
||||
return dev->dev_ops->mdb_add(dev, port, mdb, db);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_mdb_add);
|
||||
|
||||
@ -845,30 +850,11 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
struct dsa_db db)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct alu_struct alu;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
alu.fid == mdb->vid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dev->dev_ops->mdb_del)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->info->num_statics)
|
||||
goto exit;
|
||||
|
||||
/* clear port */
|
||||
alu.port_forward &= ~BIT(port);
|
||||
if (!alu.port_forward)
|
||||
alu.is_static = false;
|
||||
dev->dev_ops->w_sta_mac_table(dev, index, &alu);
|
||||
|
||||
exit:
|
||||
return 0;
|
||||
return dev->dev_ops->mdb_del(dev, port, mdb, db);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_mdb_del);
|
||||
|
||||
@ -890,12 +876,14 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_enable_port);
|
||||
|
||||
void ksz_port_stp_state_set(struct dsa_switch *ds, int port,
|
||||
u8 state, int reg)
|
||||
void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct ksz_port *p;
|
||||
u8 data;
|
||||
int reg;
|
||||
|
||||
reg = dev->info->stp_ctrl_reg;
|
||||
|
||||
ksz_pread8(dev, port, reg, &data);
|
||||
data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
|
||||
@ -930,6 +918,178 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_stp_state_set);
|
||||
|
||||
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 (dev->chip_id == KSZ8795_CHIP_ID ||
|
||||
dev->chip_id == KSZ8794_CHIP_ID ||
|
||||
dev->chip_id == KSZ8765_CHIP_ID)
|
||||
proto = DSA_TAG_PROTO_KSZ8795;
|
||||
|
||||
if (dev->chip_id == KSZ8830_CHIP_ID ||
|
||||
dev->chip_id == KSZ9893_CHIP_ID)
|
||||
proto = DSA_TAG_PROTO_KSZ9893;
|
||||
|
||||
if (dev->chip_id == KSZ9477_CHIP_ID ||
|
||||
dev->chip_id == KSZ9897_CHIP_ID ||
|
||||
dev->chip_id == KSZ9567_CHIP_ID)
|
||||
proto = DSA_TAG_PROTO_KSZ9477;
|
||||
|
||||
return proto;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_tag_protocol);
|
||||
|
||||
int ksz_port_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
bool flag, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (!dev->dev_ops->vlan_filtering)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->vlan_filtering(dev, port, flag, extack);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_vlan_filtering);
|
||||
|
||||
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;
|
||||
|
||||
if (!dev->dev_ops->vlan_add)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->vlan_add(dev, port, vlan, extack);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_vlan_add);
|
||||
|
||||
int ksz_port_vlan_del(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (!dev->dev_ops->vlan_del)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->vlan_del(dev, port, vlan);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_vlan_del);
|
||||
|
||||
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;
|
||||
|
||||
if (!dev->dev_ops->mirror_add)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_mirror_add);
|
||||
|
||||
void ksz_port_mirror_del(struct dsa_switch *ds, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (dev->dev_ops->mirror_del)
|
||||
dev->dev_ops->mirror_del(dev, port, mirror);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_port_mirror_del);
|
||||
|
||||
int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (!dev->dev_ops->change_mtu)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->change_mtu(dev, port, mtu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_change_mtu);
|
||||
|
||||
int ksz_max_mtu(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (!dev->dev_ops->max_mtu)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return dev->dev_ops->max_mtu(dev, port);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_max_mtu);
|
||||
|
||||
static int ksz_switch_detect(struct ksz_device *dev)
|
||||
{
|
||||
u8 id1, id2;
|
||||
u16 id16;
|
||||
u32 id32;
|
||||
int ret;
|
||||
|
||||
/* read chip id */
|
||||
ret = ksz_read16(dev, REG_CHIP_ID0, &id16);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
id1 = FIELD_GET(SW_FAMILY_ID_M, id16);
|
||||
id2 = FIELD_GET(SW_CHIP_ID_M, id16);
|
||||
|
||||
switch (id1) {
|
||||
case KSZ87_FAMILY_ID:
|
||||
if (id2 == KSZ87_CHIP_ID_95) {
|
||||
u8 val;
|
||||
|
||||
dev->chip_id = KSZ8795_CHIP_ID;
|
||||
|
||||
ksz_read8(dev, KSZ8_PORT_STATUS_0, &val);
|
||||
if (val & KSZ8_PORT_FIBER_MODE)
|
||||
dev->chip_id = KSZ8765_CHIP_ID;
|
||||
} else if (id2 == KSZ87_CHIP_ID_94) {
|
||||
dev->chip_id = KSZ8794_CHIP_ID;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
break;
|
||||
case KSZ88_FAMILY_ID:
|
||||
if (id2 == KSZ88_CHIP_ID_63)
|
||||
dev->chip_id = KSZ8830_CHIP_ID;
|
||||
else
|
||||
return -ENODEV;
|
||||
break;
|
||||
default:
|
||||
ret = ksz_read32(dev, REG_CHIP_ID0, &id32);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32);
|
||||
id32 &= ~0xFF;
|
||||
|
||||
switch (id32) {
|
||||
case KSZ9477_CHIP_ID:
|
||||
case KSZ9897_CHIP_ID:
|
||||
case KSZ9893_CHIP_ID:
|
||||
case KSZ9567_CHIP_ID:
|
||||
case LAN9370_CHIP_ID:
|
||||
case LAN9371_CHIP_ID:
|
||||
case LAN9372_CHIP_ID:
|
||||
case LAN9373_CHIP_ID:
|
||||
case LAN9374_CHIP_ID:
|
||||
dev->chip_id = id32;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev,
|
||||
"unsupported switch detected %x)\n", id32);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
|
||||
{
|
||||
struct dsa_switch *ds;
|
||||
@ -986,10 +1146,9 @@ int ksz_switch_register(struct ksz_device *dev,
|
||||
mutex_init(&dev->alu_mutex);
|
||||
mutex_init(&dev->vlan_mutex);
|
||||
|
||||
dev->dev_ops = ops;
|
||||
|
||||
if (dev->dev_ops->detect(dev))
|
||||
return -EINVAL;
|
||||
ret = ksz_switch_detect(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
info = ksz_lookup_info(dev->chip_id);
|
||||
if (!info)
|
||||
@ -998,10 +1157,15 @@ int ksz_switch_register(struct ksz_device *dev,
|
||||
/* Update the compatible info with the probed one */
|
||||
dev->info = info;
|
||||
|
||||
dev_info(dev->dev, "found switch: %s, rev %i\n",
|
||||
dev->info->dev_name, dev->chip_rev);
|
||||
|
||||
ret = ksz_check_device_id(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->dev_ops = ops;
|
||||
|
||||
ret = dev->dev_ops->init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -46,6 +46,7 @@ struct ksz_chip_data {
|
||||
const struct ksz_mib_names *mib_names;
|
||||
int mib_cnt;
|
||||
u8 reg_mib_cnt;
|
||||
int stp_ctrl_reg;
|
||||
bool supports_mii[KSZ_MAX_NUM_PORTS];
|
||||
bool supports_rmii[KSZ_MAX_NUM_PORTS];
|
||||
bool supports_rgmii[KSZ_MAX_NUM_PORTS];
|
||||
@ -90,6 +91,7 @@ struct ksz_device {
|
||||
|
||||
/* chip specific data */
|
||||
u32 chip_id;
|
||||
u8 chip_rev;
|
||||
int cpu_port; /* port connected to CPU */
|
||||
int phy_port_cnt;
|
||||
phy_interface_t compat_interface;
|
||||
@ -167,22 +169,42 @@ struct ksz_dev_ops {
|
||||
void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
|
||||
void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
|
||||
void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
|
||||
int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr,
|
||||
u8 *fid, u8 *src_port, u8 *timestamp,
|
||||
u16 *entries);
|
||||
int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr,
|
||||
struct alu_struct *alu);
|
||||
void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr,
|
||||
struct alu_struct *alu);
|
||||
void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
|
||||
u64 *cnt);
|
||||
void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
|
||||
u64 *dropped, u64 *cnt);
|
||||
void (*r_mib_stat64)(struct ksz_device *dev, int port);
|
||||
int (*vlan_filtering)(struct ksz_device *dev, int port,
|
||||
bool flag, struct netlink_ext_ack *extack);
|
||||
int (*vlan_add)(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan,
|
||||
struct netlink_ext_ack *extack);
|
||||
int (*vlan_del)(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_vlan *vlan);
|
||||
int (*mirror_add)(struct ksz_device *dev, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror,
|
||||
bool ingress, struct netlink_ext_ack *extack);
|
||||
void (*mirror_del)(struct ksz_device *dev, int port,
|
||||
struct dsa_mall_mirror_tc_entry *mirror);
|
||||
int (*fdb_add)(struct ksz_device *dev, int port,
|
||||
const unsigned char *addr, u16 vid, struct dsa_db db);
|
||||
int (*fdb_del)(struct ksz_device *dev, int port,
|
||||
const unsigned char *addr, u16 vid, struct dsa_db db);
|
||||
int (*fdb_dump)(struct ksz_device *dev, int port,
|
||||
dsa_fdb_dump_cb_t *cb, void *data);
|
||||
int (*mdb_add)(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db);
|
||||
int (*mdb_del)(struct ksz_device *dev, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db);
|
||||
void (*get_caps)(struct ksz_device *dev, int port,
|
||||
struct phylink_config *config);
|
||||
int (*change_mtu)(struct ksz_device *dev, int port, int mtu);
|
||||
int (*max_mtu)(struct ksz_device *dev, int port);
|
||||
void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
|
||||
void (*port_init_cnt)(struct ksz_device *dev, int port);
|
||||
int (*shutdown)(struct ksz_device *dev);
|
||||
int (*detect)(struct ksz_device *dev);
|
||||
int (*init)(struct ksz_device *dev);
|
||||
void (*exit)(struct ksz_device *dev);
|
||||
};
|
||||
@ -195,7 +217,6 @@ void ksz_switch_remove(struct ksz_device *dev);
|
||||
int ksz8_switch_register(struct ksz_device *dev);
|
||||
int ksz9477_switch_register(struct ksz_device *dev);
|
||||
|
||||
void ksz_update_port_member(struct ksz_device *dev, int port);
|
||||
void ksz_init_mib_timer(struct ksz_device *dev);
|
||||
void ksz_r_mib_stats64(struct ksz_device *dev, int port);
|
||||
void ksz_get_stats64(struct dsa_switch *ds, int port,
|
||||
@ -208,6 +229,7 @@ extern const struct ksz_chip_data ksz_switch_chips[];
|
||||
|
||||
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);
|
||||
void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface);
|
||||
int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
|
||||
@ -217,9 +239,12 @@ int ksz_port_bridge_join(struct dsa_switch *ds, int port,
|
||||
struct netlink_ext_ack *extack);
|
||||
void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
|
||||
struct dsa_bridge bridge);
|
||||
void ksz_port_stp_state_set(struct dsa_switch *ds, int port,
|
||||
u8 state, int reg);
|
||||
void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
|
||||
void ksz_port_fast_age(struct dsa_switch *ds, int port);
|
||||
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,
|
||||
@ -231,6 +256,22 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
|
||||
void ksz_get_strings(struct dsa_switch *ds, int port,
|
||||
u32 stringset, uint8_t *buf);
|
||||
enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
|
||||
int port, enum dsa_tag_protocol mp);
|
||||
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);
|
||||
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);
|
||||
|
||||
/* Common register access functions */
|
||||
|
||||
@ -353,6 +394,23 @@ static inline void ksz_regmap_unlock(void *__mtx)
|
||||
#define PORT_RX_ENABLE BIT(1)
|
||||
#define PORT_LEARN_DISABLE BIT(0)
|
||||
|
||||
/* Switch ID Defines */
|
||||
#define REG_CHIP_ID0 0x00
|
||||
|
||||
#define SW_FAMILY_ID_M GENMASK(15, 8)
|
||||
#define KSZ87_FAMILY_ID 0x87
|
||||
#define KSZ88_FAMILY_ID 0x88
|
||||
|
||||
#define KSZ8_PORT_STATUS_0 0x08
|
||||
#define KSZ8_PORT_FIBER_MODE BIT(7)
|
||||
|
||||
#define SW_CHIP_ID_M GENMASK(7, 4)
|
||||
#define KSZ87_CHIP_ID_94 0x6
|
||||
#define KSZ87_CHIP_ID_95 0x9
|
||||
#define KSZ88_CHIP_ID_63 0x3
|
||||
|
||||
#define SW_REV_ID_M GENMASK(7, 4)
|
||||
|
||||
/* Regmap tables generation */
|
||||
#define KSZ_SPI_OP_RD 3
|
||||
#define KSZ_SPI_OP_WR 2
|
||||
|
Loading…
Reference in New Issue
Block a user