Skip to content

Commit

Permalink
Merge branch 'net-dsa-microchip-common-spi-probe-for-the-ksz-series-s…
Browse files Browse the repository at this point in the history
…witches-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>
  • Loading branch information
Paolo Abeni committed Jun 21, 2022
2 parents 00bb292 + 1fe94f5 commit 8720bd9
Show file tree
Hide file tree
Showing 6 changed files with 517 additions and 336 deletions.
233 changes: 128 additions & 105 deletions drivers/net/dsa/microchip/ksz8795.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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,
struct netlink_ext_ack *extack)
static int ksz8_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;
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,
&timestamp, &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)
{
if (ksz_is_ksz88x3(dev))
return -ENOTSUPP;

Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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):
Expand All @@ -1394,81 +1457,36 @@ 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,
.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 = 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)
{
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;
Expand Down Expand Up @@ -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,
};
Expand Down
16 changes: 0 additions & 16 deletions drivers/net/dsa/microchip/ksz8795_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 8720bd9

Please sign in to comment.