From patchwork Mon Apr 26 13:19:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 427740 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 62487C43461 for ; Mon, 26 Apr 2021 13:19:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2832E6135A for ; Mon, 26 Apr 2021 13:19:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233828AbhDZNUW (ORCPT ); Mon, 26 Apr 2021 09:20:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233628AbhDZNUE (ORCPT ); Mon, 26 Apr 2021 09:20:04 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A6EF2C061761 for ; Mon, 26 Apr 2021 06:19:22 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004UX-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006mG-8Y; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 1/9] net: dsa: microchip: ksz8795: change drivers prefix to be generic Date: Mon, 26 Apr 2021 15:19:03 +0200 Message-Id: <20210426131911.25976-2-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik The driver can be used on other chips of this type. To reflect this we rename the drivers prefix from ksz8795 to ksz8. Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn --- v1 -> v4: - extracted this change from bigger previous patch v4 -> v5: - removed extra unavailable variables in ksz8_r_vlan_entries v5 -> v6: - move vlan variable size changes to other patch --- drivers/net/dsa/microchip/ksz8795.c | 224 ++++++++++++------------ drivers/net/dsa/microchip/ksz8795_spi.c | 2 +- drivers/net/dsa/microchip/ksz_common.h | 2 +- 3 files changed, 111 insertions(+), 117 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index b4b7de63ca79..91297df4371c 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -74,7 +74,7 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bits, set ? bits : 0); } -static int ksz8795_reset_switch(struct ksz_device *dev) +static int ksz8_reset_switch(struct ksz_device *dev) { /* reset switch */ ksz_write8(dev, REG_POWER_MANAGEMENT_1, @@ -117,8 +117,7 @@ static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) true); } -static void ksz8795_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) { u16 ctrl_addr; u32 data; @@ -148,8 +147,8 @@ static void ksz8795_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, mutex_unlock(&dev->alu_mutex); } -static void ksz8795_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) { u16 ctrl_addr; u32 data; @@ -195,7 +194,7 @@ static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, mutex_unlock(&dev->alu_mutex); } -static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze) +static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) { /* enable the port for flush/freeze function */ if (freeze) @@ -207,7 +206,7 @@ static void ksz8795_freeze_mib(struct ksz_device *dev, int port, bool freeze) ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); } -static void ksz8795_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; @@ -235,8 +234,7 @@ static void ksz8795_port_init_cnt(struct ksz_device *dev, int port) memset(mib->counters, 0, dev->mib_cnt * sizeof(u64)); } -static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr, - u64 *data) +static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data) { u16 ctrl_addr; @@ -248,8 +246,7 @@ static void ksz8795_r_table(struct ksz_device *dev, int table, u16 addr, mutex_unlock(&dev->alu_mutex); } -static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr, - u64 data) +static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data) { u16 ctrl_addr; @@ -261,7 +258,7 @@ static void ksz8795_w_table(struct ksz_device *dev, int table, u16 addr, mutex_unlock(&dev->alu_mutex); } -static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data) +static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data) { int timeout = 100; @@ -284,9 +281,9 @@ static int ksz8795_valid_dyn_entry(struct ksz_device *dev, u8 *data) return 0; } -static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, - u8 *mac_addr, u8 *fid, u8 *src_port, - u8 *timestamp, u16 *entries) +static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, + u8 *mac_addr, u8 *fid, u8 *src_port, + u8 *timestamp, u16 *entries) { u32 data_hi, data_lo; u16 ctrl_addr; @@ -298,7 +295,7 @@ static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, mutex_lock(&dev->alu_mutex); ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); - rc = ksz8795_valid_dyn_entry(dev, &data); + rc = ksz8_valid_dyn_entry(dev, &data); if (rc == -EAGAIN) { if (addr == 0) *entries = 0; @@ -341,13 +338,13 @@ static int ksz8795_r_dyn_mac_table(struct ksz_device *dev, u16 addr, return rc; } -static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr, - struct alu_struct *alu) +static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) { u32 data_hi, data_lo; u64 data; - ksz8795_r_table(dev, TABLE_STATIC_MAC, addr, &data); + ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data); data_hi = data >> 32; data_lo = (u32)data; if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) { @@ -370,8 +367,8 @@ static int ksz8795_r_sta_mac_table(struct ksz_device *dev, u16 addr, return -ENXIO; } -static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr, - struct alu_struct *alu) +static void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr, + struct alu_struct *alu) { u32 data_hi, data_lo; u64 data; @@ -394,17 +391,17 @@ static void ksz8795_w_sta_mac_table(struct ksz_device *dev, u16 addr, data_hi &= ~STATIC_MAC_TABLE_OVERRIDE; data = (u64)data_hi << 32 | data_lo; - ksz8795_w_table(dev, TABLE_STATIC_MAC, addr, data); + ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data); } -static void ksz8795_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) +static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) { *fid = vlan & VLAN_TABLE_FID; *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S; *valid = !!(vlan & VLAN_TABLE_VALID); } -static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) +static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) { *vlan = fid; *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S; @@ -412,12 +409,12 @@ static void ksz8795_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) *vlan |= VLAN_TABLE_VALID; } -static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr) +static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr) { u64 data; int i; - ksz8795_r_table(dev, TABLE_VLAN, addr, &data); + ksz8_r_table(dev, TABLE_VLAN, addr, &data); addr *= dev->phy_port_cnt; for (i = 0; i < dev->phy_port_cnt; i++) { dev->vlan_cache[addr + i].table[0] = (u16)data; @@ -425,7 +422,7 @@ static void ksz8795_r_vlan_entries(struct ksz_device *dev, u16 addr) } } -static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) +static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) { int index; u16 *data; @@ -435,11 +432,11 @@ static void ksz8795_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan) data = (u16 *)&buf; addr = vid / dev->phy_port_cnt; index = vid & 3; - ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + ksz8_r_table(dev, TABLE_VLAN, addr, &buf); *vlan = data[index]; } -static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) +static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) { int index; u16 *data; @@ -449,13 +446,13 @@ static void ksz8795_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) data = (u16 *)&buf; addr = vid / dev->phy_port_cnt; index = vid & 3; - ksz8795_r_table(dev, TABLE_VLAN, addr, &buf); + ksz8_r_table(dev, TABLE_VLAN, addr, &buf); data[index] = vlan; dev->vlan_cache[vid].table[0] = vlan; - ksz8795_w_table(dev, TABLE_VLAN, addr, buf); + ksz8_w_table(dev, TABLE_VLAN, addr, buf); } -static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) +static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) { u8 restart, speed, ctrl, link; int processed = true; @@ -546,7 +543,7 @@ static void ksz8795_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) *val = data; } -static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) +static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) { u8 p = phy; u8 restart, speed, ctrl, data; @@ -644,15 +641,15 @@ static void ksz8795_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) } } -static enum dsa_tag_protocol ksz8795_get_tag_protocol(struct dsa_switch *ds, - int port, - enum dsa_tag_protocol mp) +static enum dsa_tag_protocol ksz8_get_tag_protocol(struct dsa_switch *ds, + int port, + enum dsa_tag_protocol mp) { return DSA_TAG_PROTO_KSZ8795; } -static void ksz8795_get_strings(struct dsa_switch *ds, int port, - u32 stringset, uint8_t *buf) +static void ksz8_get_strings(struct dsa_switch *ds, int port, + u32 stringset, uint8_t *buf) { struct ksz_device *dev = ds->priv; int i; @@ -663,8 +660,7 @@ static void ksz8795_get_strings(struct dsa_switch *ds, int port, } } -static void ksz8795_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) { u8 data; @@ -675,8 +671,7 @@ static void ksz8795_cfg_port_member(struct ksz_device *dev, int port, dev->ports[port].member = member; } -static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, - u8 state) +static void ksz8_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { struct ksz_device *dev = ds->priv; int forward = dev->member; @@ -734,7 +729,7 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, p->stp_state = state; /* Port membership may share register with STP state. */ if (member >= 0 && member != p->member) - ksz8795_cfg_port_member(dev, port, (u8)member); + ksz8_cfg_port_member(dev, port, (u8)member); /* Check if forwarding needs to be updated. */ if (state != BR_STATE_FORWARDING) { @@ -749,7 +744,7 @@ static void ksz8795_port_stp_state_set(struct dsa_switch *ds, int port, ksz_update_port_member(dev, port); } -static void ksz8795_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; @@ -782,9 +777,8 @@ static void ksz8795_flush_dyn_mac_table(struct ksz_device *dev, int port) } } -static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, - bool flag, - struct netlink_ext_ack *extack) +static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag, + struct netlink_ext_ack *extack) { struct ksz_device *dev = ds->priv; @@ -793,9 +787,9 @@ static int ksz8795_port_vlan_filtering(struct dsa_switch *ds, int port, return 0; } -static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan, - struct netlink_ext_ack *extack) +static int ksz8_port_vlan_add(struct dsa_switch *ds, 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; @@ -804,8 +798,8 @@ static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port, ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); - ksz8795_r_vlan_table(dev, vlan->vid, &data); - ksz8795_from_vlan(data, &fid, &member, &valid); + ksz8_r_vlan_table(dev, vlan->vid, &data); + ksz8_from_vlan(data, &fid, &member, &valid); /* First time to setup the VLAN entry. */ if (!valid) { @@ -815,8 +809,8 @@ static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port, } member |= BIT(port); - ksz8795_to_vlan(fid, member, valid, &data); - ksz8795_w_vlan_table(dev, vlan->vid, data); + ksz8_to_vlan(fid, member, valid, &data); + ksz8_w_vlan_table(dev, vlan->vid, data); /* change PVID */ if (vlan->flags & BRIDGE_VLAN_INFO_PVID) @@ -834,8 +828,8 @@ static int ksz8795_port_vlan_add(struct dsa_switch *ds, int port, return 0; } -static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, - const struct switchdev_obj_port_vlan *vlan) +static int ksz8_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_device *dev = ds->priv; @@ -847,8 +841,8 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); - ksz8795_r_vlan_table(dev, vlan->vid, &data); - ksz8795_from_vlan(data, &fid, &member, &valid); + ksz8_r_vlan_table(dev, vlan->vid, &data); + ksz8_from_vlan(data, &fid, &member, &valid); member &= ~BIT(port); @@ -861,8 +855,8 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, if (pvid == vlan->vid) new_pvid = 1; - ksz8795_to_vlan(fid, member, valid, &data); - ksz8795_w_vlan_table(dev, vlan->vid, data); + ksz8_to_vlan(fid, member, valid, &data); + ksz8_w_vlan_table(dev, vlan->vid, data); if (new_pvid != pvid) ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid); @@ -870,9 +864,9 @@ static int ksz8795_port_vlan_del(struct dsa_switch *ds, int port, return 0; } -static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror, - bool ingress) +static int ksz8_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress) { struct ksz_device *dev = ds->priv; @@ -894,8 +888,8 @@ static int ksz8795_port_mirror_add(struct dsa_switch *ds, int port, return 0; } -static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port, - struct dsa_mall_mirror_tc_entry *mirror) +static void ksz8_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) { struct ksz_device *dev = ds->priv; u8 data; @@ -915,7 +909,7 @@ static void ksz8795_port_mirror_del(struct dsa_switch *ds, int port, PORT_MIRROR_SNIFFER, false); } -static void ksz8795_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) { struct ksz_port *p = &dev->ports[port]; u8 data8, member; @@ -981,10 +975,10 @@ static void ksz8795_port_setup(struct ksz_device *dev, int port, bool cpu_port) } else { member = dev->host_mask | p->vid_member; } - ksz8795_cfg_port_member(dev, port, member); + ksz8_cfg_port_member(dev, port, member); } -static void ksz8795_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; @@ -999,7 +993,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds) p->vid_member = dev->port_mask; p->on = 1; - ksz8795_port_setup(dev, dev->cpu_port, true); + ksz8_port_setup(dev, dev->cpu_port, true); dev->member = dev->host_mask; for (i = 0; i < dev->phy_port_cnt; i++) { @@ -1010,7 +1004,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds) */ p->vid_member = BIT(i); p->member = dev->port_mask; - ksz8795_port_stp_state_set(ds, i, BR_STATE_DISABLED); + ksz8_port_stp_state_set(ds, i, BR_STATE_DISABLED); /* Last port may be disabled. */ if (i == dev->phy_port_cnt) @@ -1034,7 +1028,7 @@ static void ksz8795_config_cpu_port(struct dsa_switch *ds) } } -static int ksz8795_setup(struct dsa_switch *ds) +static int ksz8_setup(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; struct alu_struct alu; @@ -1045,7 +1039,7 @@ static int ksz8795_setup(struct dsa_switch *ds) if (!dev->vlan_cache) return -ENOMEM; - ret = ksz8795_reset_switch(dev); + ret = ksz8_reset_switch(dev); if (ret) { dev_err(ds->dev, "failed to reset switch\n"); return ret; @@ -1068,7 +1062,7 @@ static int ksz8795_setup(struct dsa_switch *ds) UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); - ksz8795_config_cpu_port(ds); + ksz8_config_cpu_port(ds); ksz_cfg(dev, REG_SW_CTRL_2, MULTICAST_STORM_DISABLE, true); @@ -1083,7 +1077,7 @@ static int ksz8795_setup(struct dsa_switch *ds) BROADCAST_STORM_PROT_RATE) / 100); for (i = 0; i < (dev->num_vlans / 4); i++) - ksz8795_r_vlan_entries(dev, i); + ksz8_r_vlan_entries(dev, i); /* Setup STP address for STP operation. */ memset(&alu, 0, sizeof(alu)); @@ -1092,7 +1086,7 @@ static int ksz8795_setup(struct dsa_switch *ds) alu.is_override = true; alu.port_forward = dev->host_mask; - ksz8795_w_sta_mac_table(dev, 0, &alu); + ksz8_w_sta_mac_table(dev, 0, &alu); ksz_init_mib_timer(dev); @@ -1101,36 +1095,36 @@ static int ksz8795_setup(struct dsa_switch *ds) return 0; } -static const struct dsa_switch_ops ksz8795_switch_ops = { - .get_tag_protocol = ksz8795_get_tag_protocol, - .setup = ksz8795_setup, +static const struct dsa_switch_ops ksz8_switch_ops = { + .get_tag_protocol = ksz8_get_tag_protocol, + .setup = ksz8_setup, .phy_read = ksz_phy_read16, .phy_write = ksz_phy_write16, .phylink_mac_link_down = ksz_mac_link_down, .port_enable = ksz_enable_port, - .get_strings = ksz8795_get_strings, + .get_strings = ksz8_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 = ksz8795_port_stp_state_set, + .port_stp_state_set = ksz8_port_stp_state_set, .port_fast_age = ksz_port_fast_age, - .port_vlan_filtering = ksz8795_port_vlan_filtering, - .port_vlan_add = ksz8795_port_vlan_add, - .port_vlan_del = ksz8795_port_vlan_del, + .port_vlan_filtering = ksz8_port_vlan_filtering, + .port_vlan_add = ksz8_port_vlan_add, + .port_vlan_del = ksz8_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 = ksz8795_port_mirror_add, - .port_mirror_del = ksz8795_port_mirror_del, + .port_mirror_add = ksz8_port_mirror_add, + .port_mirror_del = ksz8_port_mirror_del, }; -static u32 ksz8795_get_port_addr(int port, int offset) +static u32 ksz8_get_port_addr(int port, int offset) { return PORT_CTRL_ADDR(port, offset); } -static int ksz8795_switch_detect(struct ksz_device *dev) +static int ksz8_switch_detect(struct ksz_device *dev) { u8 id1, id2; u16 id16; @@ -1174,7 +1168,7 @@ struct ksz_chip_data { int port_cnt; }; -static const struct ksz_chip_data ksz8795_switch_chips[] = { +static const struct ksz_chip_data ksz8_switch_chips[] = { { .chip_id = 0x8795, .dev_name = "KSZ8795", @@ -1218,14 +1212,14 @@ static const struct ksz_chip_data ksz8795_switch_chips[] = { }, }; -static int ksz8795_switch_init(struct ksz_device *dev) +static int ksz8_switch_init(struct ksz_device *dev) { int i; - dev->ds->ops = &ksz8795_switch_ops; + dev->ds->ops = &ksz8_switch_ops; - for (i = 0; i < ARRAY_SIZE(ksz8795_switch_chips); i++) { - const struct ksz_chip_data *chip = &ksz8795_switch_chips[i]; + for (i = 0; i < ARRAY_SIZE(ksz8_switch_chips); i++) { + const struct ksz_chip_data *chip = &ksz8_switch_chips[i]; if (dev->chip_id == chip->chip_id) { dev->name = chip->dev_name; @@ -1272,36 +1266,36 @@ static int ksz8795_switch_init(struct ksz_device *dev) return 0; } -static void ksz8795_switch_exit(struct ksz_device *dev) +static void ksz8_switch_exit(struct ksz_device *dev) { - ksz8795_reset_switch(dev); + ksz8_reset_switch(dev); } -static const struct ksz_dev_ops ksz8795_dev_ops = { - .get_port_addr = ksz8795_get_port_addr, - .cfg_port_member = ksz8795_cfg_port_member, - .flush_dyn_mac_table = ksz8795_flush_dyn_mac_table, - .port_setup = ksz8795_port_setup, - .r_phy = ksz8795_r_phy, - .w_phy = ksz8795_w_phy, - .r_dyn_mac_table = ksz8795_r_dyn_mac_table, - .r_sta_mac_table = ksz8795_r_sta_mac_table, - .w_sta_mac_table = ksz8795_w_sta_mac_table, - .r_mib_cnt = ksz8795_r_mib_cnt, - .r_mib_pkt = ksz8795_r_mib_pkt, - .freeze_mib = ksz8795_freeze_mib, - .port_init_cnt = ksz8795_port_init_cnt, - .shutdown = ksz8795_reset_switch, - .detect = ksz8795_switch_detect, - .init = ksz8795_switch_init, - .exit = ksz8795_switch_exit, +static const struct ksz_dev_ops ksz8_dev_ops = { + .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_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, + .shutdown = ksz8_reset_switch, + .detect = ksz8_switch_detect, + .init = ksz8_switch_init, + .exit = ksz8_switch_exit, }; -int ksz8795_switch_register(struct ksz_device *dev) +int ksz8_switch_register(struct ksz_device *dev) { - return ksz_switch_register(dev, &ksz8795_dev_ops); + return ksz_switch_register(dev, &ksz8_dev_ops); } -EXPORT_SYMBOL(ksz8795_switch_register); +EXPORT_SYMBOL(ksz8_switch_register); MODULE_AUTHOR("Tristram Ha "); MODULE_DESCRIPTION("Microchip KSZ8795 Series Switch DSA Driver"); diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index f98432a3e2b5..45420c07c99f 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -55,7 +55,7 @@ static int ksz8795_spi_probe(struct spi_device *spi) if (ret) return ret; - ret = ksz8795_switch_register(dev); + ret = ksz8_switch_register(dev); /* Main DSA driver may not be started yet. */ if (ret) diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index f212775372ce..f0681a891cca 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -142,7 +142,7 @@ int ksz_switch_register(struct ksz_device *dev, const struct ksz_dev_ops *ops); void ksz_switch_remove(struct ksz_device *dev); -int ksz8795_switch_register(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); From patchwork Mon Apr 26 13:19:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 428418 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A4B7FC433B4 for ; Mon, 26 Apr 2021 13:19:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 70A306135A for ; Mon, 26 Apr 2021 13:19:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233757AbhDZNUK (ORCPT ); Mon, 26 Apr 2021 09:20:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59396 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233218AbhDZNUD (ORCPT ); Mon, 26 Apr 2021 09:20:03 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F74EC061574 for ; Mon, 26 Apr 2021 06:19:22 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004UY-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006mR-9Z; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 2/9] net: dsa: microchip: ksz8795: move cpu_select_interface to extra function Date: Mon, 26 Apr 2021 15:19:04 +0200 Message-Id: <20210426131911.25976-3-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik This patch moves the cpu interface selection code to a individual function specific for ksz8795. It will make it simpler to customize the code path for different switches supported by this driver. Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn --- v1 -> v5: - extracted this from previous bigger patch --- drivers/net/dsa/microchip/ksz8795.c | 92 ++++++++++++++++------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index 91297df4371c..85fb727c13eb 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -909,10 +909,58 @@ static void ksz8_port_mirror_del(struct dsa_switch *ds, int port, PORT_MIRROR_SNIFFER, false); } +static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port) +{ + struct ksz_port *p = &dev->ports[port]; + u8 data8; + + if (!p->interface && dev->compat_interface) { + dev_warn(dev->dev, + "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. " + "Please update your device tree.\n", + port); + p->interface = dev->compat_interface; + } + + /* Configure MII interface for proper network communication. */ + ksz_read8(dev, REG_PORT_5_CTRL_6, &data8); + data8 &= ~PORT_INTERFACE_TYPE; + data8 &= ~PORT_GMII_1GPS_MODE; + switch (p->interface) { + case PHY_INTERFACE_MODE_MII: + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_RMII: + data8 |= PORT_INTERFACE_RMII; + p->phydev.speed = SPEED_100; + break; + case PHY_INTERFACE_MODE_GMII: + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_GMII; + p->phydev.speed = SPEED_1000; + break; + default: + data8 &= ~PORT_RGMII_ID_IN_ENABLE; + data8 &= ~PORT_RGMII_ID_OUT_ENABLE; + if (p->interface == PHY_INTERFACE_MODE_RGMII_ID || + p->interface == PHY_INTERFACE_MODE_RGMII_RXID) + data8 |= PORT_RGMII_ID_IN_ENABLE; + if (p->interface == PHY_INTERFACE_MODE_RGMII_ID || + p->interface == PHY_INTERFACE_MODE_RGMII_TXID) + data8 |= PORT_RGMII_ID_OUT_ENABLE; + data8 |= PORT_GMII_1GPS_MODE; + data8 |= PORT_INTERFACE_RGMII; + p->phydev.speed = SPEED_1000; + break; + } + ksz_write8(dev, REG_PORT_5_CTRL_6, data8); + p->phydev.duplex = 1; +} + static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) { struct ksz_port *p = &dev->ports[port]; - u8 data8, member; + u8 member; /* enable broadcast storm limit */ ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); @@ -929,47 +977,7 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); if (cpu_port) { - if (!p->interface && dev->compat_interface) { - dev_warn(dev->dev, - "Using legacy switch \"phy-mode\" property, because it is missing on port %d node. " - "Please update your device tree.\n", - port); - p->interface = dev->compat_interface; - } - - /* Configure MII interface for proper network communication. */ - ksz_read8(dev, REG_PORT_5_CTRL_6, &data8); - data8 &= ~PORT_INTERFACE_TYPE; - data8 &= ~PORT_GMII_1GPS_MODE; - switch (p->interface) { - case PHY_INTERFACE_MODE_MII: - p->phydev.speed = SPEED_100; - break; - case PHY_INTERFACE_MODE_RMII: - data8 |= PORT_INTERFACE_RMII; - p->phydev.speed = SPEED_100; - break; - case PHY_INTERFACE_MODE_GMII: - data8 |= PORT_GMII_1GPS_MODE; - data8 |= PORT_INTERFACE_GMII; - p->phydev.speed = SPEED_1000; - break; - default: - data8 &= ~PORT_RGMII_ID_IN_ENABLE; - data8 &= ~PORT_RGMII_ID_OUT_ENABLE; - if (p->interface == PHY_INTERFACE_MODE_RGMII_ID || - p->interface == PHY_INTERFACE_MODE_RGMII_RXID) - data8 |= PORT_RGMII_ID_IN_ENABLE; - if (p->interface == PHY_INTERFACE_MODE_RGMII_ID || - p->interface == PHY_INTERFACE_MODE_RGMII_TXID) - data8 |= PORT_RGMII_ID_OUT_ENABLE; - data8 |= PORT_GMII_1GPS_MODE; - data8 |= PORT_INTERFACE_RGMII; - p->phydev.speed = SPEED_1000; - break; - } - ksz_write8(dev, REG_PORT_5_CTRL_6, data8); - p->phydev.duplex = 1; + ksz8795_cpu_interface_select(dev, port); member = dev->port_mask; } else { From patchwork Mon Apr 26 13:19:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 428417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4D4FEC433ED for ; Mon, 26 Apr 2021 13:19:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 16BC96135A for ; Mon, 26 Apr 2021 13:19:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233638AbhDZNUP (ORCPT ); Mon, 26 Apr 2021 09:20:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233560AbhDZNUE (ORCPT ); Mon, 26 Apr 2021 09:20:04 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80B86C061756 for ; Mon, 26 Apr 2021 06:19:22 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004UZ-CI; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006mb-B3; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 3/9] net: dsa: microchip: ksz8795: move register offsets and shifts to separate struct Date: Mon, 26 Apr 2021 15:19:05 +0200 Message-Id: <20210426131911.25976-4-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik In order to get this driver used with other switches the functions need to use different offsets and register shifts. This patch changes the direct use of the register defines to register description structures, which can be set depending on the chips register layout. Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn --- v1 -> v4: - extracted this change from bigger previous patch v4 -> v5: - added missing variables in ksz8_r_vlan_entries - moved shifts, masks and registers to arrays indexed by enums - using unsigned types where possible v5 -> v6: - changed variable order to revers christmas tree - fixed shift entry VLAN_TABLE_MEMBERSHIP to VLAN_TABLE_MEMBERSHIP_S --- drivers/net/dsa/microchip/ksz8.h | 69 ++++++ drivers/net/dsa/microchip/ksz8795.c | 293 +++++++++++++++++------- drivers/net/dsa/microchip/ksz8795_reg.h | 85 ------- 3 files changed, 285 insertions(+), 162 deletions(-) create mode 100644 drivers/net/dsa/microchip/ksz8.h diff --git a/drivers/net/dsa/microchip/ksz8.h b/drivers/net/dsa/microchip/ksz8.h new file mode 100644 index 000000000000..9d611895d3cf --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Microchip KSZ8XXX series register access + * + * Copyright (C) 2020 Pengutronix, Michael Grzeschik + */ + +#ifndef __KSZ8XXX_H +#define __KSZ8XXX_H +#include + +enum ksz_regs { + REG_IND_CTRL_0, + REG_IND_DATA_8, + REG_IND_DATA_CHECK, + REG_IND_DATA_HI, + REG_IND_DATA_LO, + REG_IND_MIB_CHECK, + P_FORCE_CTRL, + P_LINK_STATUS, + P_LOCAL_CTRL, + P_NEG_RESTART_CTRL, + P_REMOTE_STATUS, + P_SPEED_STATUS, + S_TAIL_TAG_CTRL, +}; + +enum ksz_masks { + PORT_802_1P_REMAPPING, + SW_TAIL_TAG_ENABLE, + MIB_COUNTER_OVERFLOW, + MIB_COUNTER_VALID, + VLAN_TABLE_FID, + VLAN_TABLE_MEMBERSHIP, + VLAN_TABLE_VALID, + STATIC_MAC_TABLE_VALID, + STATIC_MAC_TABLE_USE_FID, + STATIC_MAC_TABLE_FID, + STATIC_MAC_TABLE_OVERRIDE, + STATIC_MAC_TABLE_FWD_PORTS, + DYNAMIC_MAC_TABLE_ENTRIES_H, + DYNAMIC_MAC_TABLE_MAC_EMPTY, + DYNAMIC_MAC_TABLE_NOT_READY, + DYNAMIC_MAC_TABLE_ENTRIES, + DYNAMIC_MAC_TABLE_FID, + DYNAMIC_MAC_TABLE_SRC_PORT, + DYNAMIC_MAC_TABLE_TIMESTAMP, +}; + +enum ksz_shifts { + VLAN_TABLE_MEMBERSHIP_S, + VLAN_TABLE, + STATIC_MAC_FWD_PORTS, + STATIC_MAC_FID, + DYNAMIC_MAC_ENTRIES_H, + DYNAMIC_MAC_ENTRIES, + DYNAMIC_MAC_FID, + DYNAMIC_MAC_TIMESTAMP, + DYNAMIC_MAC_SRC_PORT, +}; + +struct ksz8 { + const u8 *regs; + const u32 *masks; + const u8 *shifts; + void *priv; +}; + +#endif diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index 85fb727c13eb..18534d6f640d 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -20,6 +20,57 @@ #include "ksz_common.h" #include "ksz8795_reg.h" +#include "ksz8.h" + +static const u8 ksz8795_regs[] = { + [REG_IND_CTRL_0] = 0x6E, + [REG_IND_DATA_8] = 0x70, + [REG_IND_DATA_CHECK] = 0x72, + [REG_IND_DATA_HI] = 0x71, + [REG_IND_DATA_LO] = 0x75, + [REG_IND_MIB_CHECK] = 0x74, + [P_FORCE_CTRL] = 0x0C, + [P_LINK_STATUS] = 0x0E, + [P_LOCAL_CTRL] = 0x07, + [P_NEG_RESTART_CTRL] = 0x0D, + [P_REMOTE_STATUS] = 0x08, + [P_SPEED_STATUS] = 0x09, + [S_TAIL_TAG_CTRL] = 0x0C, +}; + +static const u32 ksz8795_masks[] = { + [PORT_802_1P_REMAPPING] = BIT(7), + [SW_TAIL_TAG_ENABLE] = BIT(1), + [MIB_COUNTER_OVERFLOW] = BIT(6), + [MIB_COUNTER_VALID] = BIT(5), + [VLAN_TABLE_FID] = GENMASK(6, 0), + [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), + [VLAN_TABLE_VALID] = BIT(12), + [STATIC_MAC_TABLE_VALID] = BIT(21), + [STATIC_MAC_TABLE_USE_FID] = BIT(23), + [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), + [STATIC_MAC_TABLE_OVERRIDE] = BIT(26), + [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20), + [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), + [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8), + [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), + [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), + [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20), + [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), + [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), +}; + +static const u8 ksz8795_shifts[] = { + [VLAN_TABLE_MEMBERSHIP_S] = 7, + [VLAN_TABLE] = 16, + [STATIC_MAC_FWD_PORTS] = 16, + [STATIC_MAC_FID] = 24, + [DYNAMIC_MAC_ENTRIES_H] = 3, + [DYNAMIC_MAC_ENTRIES] = 29, + [DYNAMIC_MAC_FID] = 16, + [DYNAMIC_MAC_TIMESTAMP] = 27, + [DYNAMIC_MAC_SRC_PORT] = 24, +}; static const struct { char string[ETH_GSTRING_LEN]; @@ -119,26 +170,32 @@ static void ksz8795_set_prio_queue(struct ksz_device *dev, int port, int queue) static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) { + struct ksz8 *ksz8 = dev->priv; + const u32 *masks; + const u8 *regs; u16 ctrl_addr; u32 data; u8 check; int loop; + masks = ksz8->masks; + regs = ksz8->regs; + ctrl_addr = addr + dev->reg_mib_cnt * port; ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); mutex_lock(&dev->alu_mutex); - ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); /* It is almost guaranteed to always read the valid bit because of * slow SPI speed. */ for (loop = 2; loop > 0; loop--) { - ksz_read8(dev, REG_IND_MIB_CHECK, &check); + ksz_read8(dev, regs[REG_IND_MIB_CHECK], &check); - if (check & MIB_COUNTER_VALID) { - ksz_read32(dev, REG_IND_DATA_LO, &data); - if (check & MIB_COUNTER_OVERFLOW) + if (check & masks[MIB_COUNTER_VALID]) { + ksz_read32(dev, regs[REG_IND_DATA_LO], &data); + if (check & masks[MIB_COUNTER_OVERFLOW]) *cnt += MIB_COUNTER_VALUE + 1; *cnt += data & MIB_COUNTER_VALUE; break; @@ -150,27 +207,33 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, u64 *dropped, u64 *cnt) { + struct ksz8 *ksz8 = dev->priv; + const u32 *masks; + const u8 *regs; u16 ctrl_addr; u32 data; u8 check; int loop; + masks = ksz8->masks; + regs = ksz8->regs; + addr -= dev->reg_mib_cnt; ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port; ctrl_addr += addr + KS_MIB_TOTAL_RX_0; ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); mutex_lock(&dev->alu_mutex); - ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); /* It is almost guaranteed to always read the valid bit because of * slow SPI speed. */ for (loop = 2; loop > 0; loop--) { - ksz_read8(dev, REG_IND_MIB_CHECK, &check); + ksz_read8(dev, regs[REG_IND_MIB_CHECK], &check); - if (check & MIB_COUNTER_VALID) { - ksz_read32(dev, REG_IND_DATA_LO, &data); + if (check & masks[MIB_COUNTER_VALID]) { + ksz_read32(dev, regs[REG_IND_DATA_LO], &data); if (addr < 2) { u64 total; @@ -178,13 +241,13 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, total <<= 32; *cnt += total; *cnt += data; - if (check & MIB_COUNTER_OVERFLOW) { + if (check & masks[MIB_COUNTER_OVERFLOW]) { total = MIB_TOTAL_BYTES_H + 1; total <<= 32; *cnt += total; } } else { - if (check & MIB_COUNTER_OVERFLOW) + if (check & masks[MIB_COUNTER_OVERFLOW]) *cnt += MIB_PACKET_DROPPED + 1; *cnt += data & MIB_PACKET_DROPPED; } @@ -236,46 +299,56 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port) static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data) { + struct ksz8 *ksz8 = dev->priv; + const u8 *regs = ksz8->regs; u16 ctrl_addr; ctrl_addr = IND_ACC_TABLE(table | TABLE_READ) | addr; mutex_lock(&dev->alu_mutex); - ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); - ksz_read64(dev, REG_IND_DATA_HI, data); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); + ksz_read64(dev, regs[REG_IND_DATA_HI], data); mutex_unlock(&dev->alu_mutex); } static void ksz8_w_table(struct ksz_device *dev, int table, u16 addr, u64 data) { + struct ksz8 *ksz8 = dev->priv; + const u8 *regs = ksz8->regs; u16 ctrl_addr; ctrl_addr = IND_ACC_TABLE(table) | addr; mutex_lock(&dev->alu_mutex); - ksz_write64(dev, REG_IND_DATA_HI, data); - ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_write64(dev, regs[REG_IND_DATA_HI], data); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); mutex_unlock(&dev->alu_mutex); } static int ksz8_valid_dyn_entry(struct ksz_device *dev, u8 *data) { + struct ksz8 *ksz8 = dev->priv; int timeout = 100; + const u32 *masks; + const u8 *regs; + + masks = ksz8->masks; + regs = ksz8->regs; do { - ksz_read8(dev, REG_IND_DATA_CHECK, data); + ksz_read8(dev, regs[REG_IND_DATA_CHECK], data); timeout--; - } while ((*data & DYNAMIC_MAC_TABLE_NOT_READY) && timeout); + } while ((*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) && timeout); /* Entry is not ready for accessing. */ - if (*data & DYNAMIC_MAC_TABLE_NOT_READY) { + if (*data & masks[DYNAMIC_MAC_TABLE_NOT_READY]) { return -EAGAIN; /* Entry is ready for accessing. */ } else { - ksz_read8(dev, REG_IND_DATA_8, data); + ksz_read8(dev, regs[REG_IND_DATA_8], data); /* There is no valid entry in the table. */ - if (*data & DYNAMIC_MAC_TABLE_MAC_EMPTY) + if (*data & masks[DYNAMIC_MAC_TABLE_MAC_EMPTY]) return -ENXIO; } return 0; @@ -285,15 +358,23 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr, u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries) { + struct ksz8 *ksz8 = dev->priv; u32 data_hi, data_lo; + const u8 *shifts; + const u32 *masks; + const u8 *regs; u16 ctrl_addr; u8 data; int rc; + shifts = ksz8->shifts; + masks = ksz8->masks; + regs = ksz8->regs; + ctrl_addr = IND_ACC_TABLE(TABLE_DYNAMIC_MAC | TABLE_READ) | addr; mutex_lock(&dev->alu_mutex); - ksz_write16(dev, REG_IND_CTRL_0, ctrl_addr); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); rc = ksz8_valid_dyn_entry(dev, &data); if (rc == -EAGAIN) { @@ -306,23 +387,23 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u64 buf = 0; int cnt; - ksz_read64(dev, REG_IND_DATA_HI, &buf); + ksz_read64(dev, regs[REG_IND_DATA_HI], &buf); data_hi = (u32)(buf >> 32); data_lo = (u32)buf; /* Check out how many valid entry in the table. */ - cnt = data & DYNAMIC_MAC_TABLE_ENTRIES_H; - cnt <<= DYNAMIC_MAC_ENTRIES_H_S; - cnt |= (data_hi & DYNAMIC_MAC_TABLE_ENTRIES) >> - DYNAMIC_MAC_ENTRIES_S; + cnt = data & masks[DYNAMIC_MAC_TABLE_ENTRIES_H]; + cnt <<= shifts[DYNAMIC_MAC_ENTRIES_H]; + cnt |= (data_hi & masks[DYNAMIC_MAC_TABLE_ENTRIES]) >> + shifts[DYNAMIC_MAC_ENTRIES]; *entries = cnt + 1; - *fid = (data_hi & DYNAMIC_MAC_TABLE_FID) >> - DYNAMIC_MAC_FID_S; - *src_port = (data_hi & DYNAMIC_MAC_TABLE_SRC_PORT) >> - DYNAMIC_MAC_SRC_PORT_S; - *timestamp = (data_hi & DYNAMIC_MAC_TABLE_TIMESTAMP) >> - DYNAMIC_MAC_TIMESTAMP_S; + *fid = (data_hi & masks[DYNAMIC_MAC_TABLE_FID]) >> + shifts[DYNAMIC_MAC_FID]; + *src_port = (data_hi & masks[DYNAMIC_MAC_TABLE_SRC_PORT]) >> + shifts[DYNAMIC_MAC_SRC_PORT]; + *timestamp = (data_hi & masks[DYNAMIC_MAC_TABLE_TIMESTAMP]) >> + shifts[DYNAMIC_MAC_TIMESTAMP]; mac_addr[5] = (u8)data_lo; mac_addr[4] = (u8)(data_lo >> 8); @@ -341,27 +422,37 @@ static int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, struct alu_struct *alu) { + struct ksz8 *ksz8 = dev->priv; u32 data_hi, data_lo; + const u8 *shifts; + const u32 *masks; u64 data; + shifts = ksz8->shifts; + masks = ksz8->masks; + ksz8_r_table(dev, TABLE_STATIC_MAC, addr, &data); data_hi = data >> 32; data_lo = (u32)data; - if (data_hi & (STATIC_MAC_TABLE_VALID | STATIC_MAC_TABLE_OVERRIDE)) { + if (data_hi & (masks[STATIC_MAC_TABLE_VALID] | + masks[STATIC_MAC_TABLE_OVERRIDE])) { alu->mac[5] = (u8)data_lo; alu->mac[4] = (u8)(data_lo >> 8); alu->mac[3] = (u8)(data_lo >> 16); alu->mac[2] = (u8)(data_lo >> 24); alu->mac[1] = (u8)data_hi; alu->mac[0] = (u8)(data_hi >> 8); - alu->port_forward = (data_hi & STATIC_MAC_TABLE_FWD_PORTS) >> - STATIC_MAC_FWD_PORTS_S; + alu->port_forward = + (data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >> + shifts[STATIC_MAC_FWD_PORTS]; alu->is_override = - (data_hi & STATIC_MAC_TABLE_OVERRIDE) ? 1 : 0; + (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0; data_hi >>= 1; - alu->is_use_fid = (data_hi & STATIC_MAC_TABLE_USE_FID) ? 1 : 0; - alu->fid = (data_hi & STATIC_MAC_TABLE_FID) >> - STATIC_MAC_FID_S; + alu->is_static = true; + alu->is_use_fid = + (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0; + alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >> + shifts[STATIC_MAC_FID]; return 0; } return -ENXIO; @@ -370,55 +461,82 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr, static void ksz8_w_sta_mac_table(struct ksz_device *dev, u16 addr, struct alu_struct *alu) { + struct ksz8 *ksz8 = dev->priv; u32 data_hi, data_lo; + const u8 *shifts; + const u32 *masks; u64 data; + shifts = ksz8->shifts; + masks = ksz8->masks; + data_lo = ((u32)alu->mac[2] << 24) | ((u32)alu->mac[3] << 16) | ((u32)alu->mac[4] << 8) | alu->mac[5]; data_hi = ((u32)alu->mac[0] << 8) | alu->mac[1]; - data_hi |= (u32)alu->port_forward << STATIC_MAC_FWD_PORTS_S; + data_hi |= (u32)alu->port_forward << shifts[STATIC_MAC_FWD_PORTS]; if (alu->is_override) - data_hi |= STATIC_MAC_TABLE_OVERRIDE; + data_hi |= masks[STATIC_MAC_TABLE_OVERRIDE]; if (alu->is_use_fid) { - data_hi |= STATIC_MAC_TABLE_USE_FID; - data_hi |= (u32)alu->fid << STATIC_MAC_FID_S; + data_hi |= masks[STATIC_MAC_TABLE_USE_FID]; + data_hi |= (u32)alu->fid << shifts[STATIC_MAC_FID]; } if (alu->is_static) - data_hi |= STATIC_MAC_TABLE_VALID; + data_hi |= masks[STATIC_MAC_TABLE_VALID]; else - data_hi &= ~STATIC_MAC_TABLE_OVERRIDE; + data_hi &= ~masks[STATIC_MAC_TABLE_OVERRIDE]; data = (u64)data_hi << 32 | data_lo; ksz8_w_table(dev, TABLE_STATIC_MAC, addr, data); } -static void ksz8_from_vlan(u16 vlan, u8 *fid, u8 *member, u8 *valid) +static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid, + u8 *member, u8 *valid) { - *fid = vlan & VLAN_TABLE_FID; - *member = (vlan & VLAN_TABLE_MEMBERSHIP) >> VLAN_TABLE_MEMBERSHIP_S; - *valid = !!(vlan & VLAN_TABLE_VALID); + struct ksz8 *ksz8 = dev->priv; + const u8 *shifts; + const u32 *masks; + + shifts = ksz8->shifts; + masks = ksz8->masks; + + *fid = vlan & masks[VLAN_TABLE_FID]; + *member = (vlan & masks[VLAN_TABLE_MEMBERSHIP]) >> + shifts[VLAN_TABLE_MEMBERSHIP_S]; + *valid = !!(vlan & masks[VLAN_TABLE_VALID]); } -static void ksz8_to_vlan(u8 fid, u8 member, u8 valid, u16 *vlan) +static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8 valid, + u32 *vlan) { + struct ksz8 *ksz8 = dev->priv; + const u8 *shifts; + const u32 *masks; + + shifts = ksz8->shifts; + masks = ksz8->masks; + *vlan = fid; - *vlan |= (u16)member << VLAN_TABLE_MEMBERSHIP_S; + *vlan |= (u16)member << shifts[VLAN_TABLE_MEMBERSHIP_S]; if (valid) - *vlan |= VLAN_TABLE_VALID; + *vlan |= masks[VLAN_TABLE_VALID]; } static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr) { + struct ksz8 *ksz8 = dev->priv; + const u8 *shifts; u64 data; int i; + shifts = ksz8->shifts; + ksz8_r_table(dev, TABLE_VLAN, addr, &data); addr *= dev->phy_port_cnt; for (i = 0; i < dev->phy_port_cnt; i++) { dev->vlan_cache[addr + i].table[0] = (u16)data; - data >>= VLAN_TABLE_S; + data >>= shifts[VLAN_TABLE]; } } @@ -454,16 +572,18 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan) static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) { + struct ksz8 *ksz8 = dev->priv; u8 restart, speed, ctrl, link; + const u8 *regs = ksz8->regs; int processed = true; u16 data = 0; u8 p = phy; switch (reg) { case PHY_REG_CTRL: - ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); - ksz_pread8(dev, p, P_SPEED_STATUS, &speed); - ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart); + ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed); + ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl); if (restart & PORT_PHY_LOOPBACK) data |= PHY_LOOPBACK; if (ctrl & PORT_FORCE_100_MBIT) @@ -488,7 +608,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) data |= PHY_LED_DISABLE; break; case PHY_REG_STATUS: - ksz_pread8(dev, p, P_LINK_STATUS, &link); + ksz_pread8(dev, p, regs[P_LINK_STATUS], &link); data = PHY_100BTX_FD_CAPABLE | PHY_100BTX_CAPABLE | PHY_10BT_FD_CAPABLE | @@ -506,7 +626,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) data = KSZ8795_ID_LO; break; case PHY_REG_AUTO_NEGOTIATION: - ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl); data = PHY_AUTO_NEG_802_3; if (ctrl & PORT_AUTO_NEG_SYM_PAUSE) data |= PHY_AUTO_NEG_SYM_PAUSE; @@ -520,7 +640,7 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) data |= PHY_AUTO_NEG_10BT; break; case PHY_REG_REMOTE_CAPABILITY: - ksz_pread8(dev, p, P_REMOTE_STATUS, &link); + ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link); data = PHY_AUTO_NEG_802_3; if (link & PORT_REMOTE_SYM_PAUSE) data |= PHY_AUTO_NEG_SYM_PAUSE; @@ -545,8 +665,10 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) { - u8 p = phy; + struct ksz8 *ksz8 = dev->priv; u8 restart, speed, ctrl, data; + const u8 *regs = ksz8->regs; + u8 p = phy; switch (reg) { case PHY_REG_CTRL: @@ -554,15 +676,15 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) /* Do not support PHY reset function. */ if (val & PHY_RESET) break; - ksz_pread8(dev, p, P_SPEED_STATUS, &speed); + ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed); data = speed; if (val & PHY_HP_MDIX) data |= PORT_HP_MDIX; else data &= ~PORT_HP_MDIX; if (data != speed) - ksz_pwrite8(dev, p, P_SPEED_STATUS, data); - ksz_pread8(dev, p, P_FORCE_CTRL, &ctrl); + ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data); + ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl); data = ctrl; if (!(val & PHY_AUTO_NEG_ENABLE)) data |= PORT_AUTO_NEG_DISABLE; @@ -581,8 +703,8 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) else data &= ~PORT_FORCE_FULL_DUPLEX; if (data != ctrl) - ksz_pwrite8(dev, p, P_FORCE_CTRL, data); - ksz_pread8(dev, p, P_NEG_RESTART_CTRL, &restart); + ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data); + ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart); data = restart; if (val & PHY_LED_DISABLE) data |= PORT_LED_OFF; @@ -613,10 +735,10 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) else data &= ~PORT_PHY_LOOPBACK; if (data != restart) - ksz_pwrite8(dev, p, P_NEG_RESTART_CTRL, data); + ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL], data); break; case PHY_REG_AUTO_NEGOTIATION: - ksz_pread8(dev, p, P_LOCAL_CTRL, &ctrl); + ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl); data = ctrl; data &= ~(PORT_AUTO_NEG_SYM_PAUSE | PORT_AUTO_NEG_100BTX_FD | @@ -634,7 +756,7 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) if (val & PHY_AUTO_NEG_10BT) data |= PORT_AUTO_NEG_10BT; if (data != ctrl) - ksz_pwrite8(dev, p, P_LOCAL_CTRL, data); + ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data); break; default: break; @@ -793,13 +915,14 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port, { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_device *dev = ds->priv; - u16 data, new_pvid = 0; + u16 new_pvid = 0; + u32 data = 0; u8 fid, member, valid; ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); ksz8_r_vlan_table(dev, vlan->vid, &data); - ksz8_from_vlan(data, &fid, &member, &valid); + ksz8_from_vlan(dev, data, &fid, &member, &valid); /* First time to setup the VLAN entry. */ if (!valid) { @@ -809,7 +932,7 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port, } member |= BIT(port); - ksz8_to_vlan(fid, member, valid, &data); + ksz8_to_vlan(dev, fid, member, valid, &data); ksz8_w_vlan_table(dev, vlan->vid, data); /* change PVID */ @@ -833,7 +956,8 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port, { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_device *dev = ds->priv; - u16 data, pvid, new_pvid = 0; + u16 pvid, new_pvid = 0; + u32 data = 0; u8 fid, member, valid; ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); @@ -842,7 +966,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port, ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); ksz8_r_vlan_table(dev, vlan->vid, &data); - ksz8_from_vlan(data, &fid, &member, &valid); + ksz8_from_vlan(dev, data, &fid, &member, &valid); member &= ~BIT(port); @@ -855,7 +979,7 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port, if (pvid == vlan->vid) new_pvid = 1; - ksz8_to_vlan(fid, member, valid, &data); + ksz8_to_vlan(dev, fid, member, valid, &data); ksz8_w_vlan_table(dev, vlan->vid, data); if (new_pvid != pvid) @@ -960,8 +1084,12 @@ static void ksz8795_cpu_interface_select(struct ksz_device *dev, int port) static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) { struct ksz_port *p = &dev->ports[port]; + struct ksz8 *ksz8 = dev->priv; + const u32 *masks; u8 member; + masks = ksz8->masks; + /* enable broadcast storm limit */ ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); @@ -971,7 +1099,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false); /* replace priority */ - ksz_port_cfg(dev, port, P_802_1P_CTRL, PORT_802_1P_REMAPPING, false); + ksz_port_cfg(dev, port, P_802_1P_CTRL, + masks[PORT_802_1P_REMAPPING], false); /* enable 802.1p priority */ ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); @@ -989,13 +1118,18 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) static void ksz8_config_cpu_port(struct dsa_switch *ds) { struct ksz_device *dev = ds->priv; + struct ksz8 *ksz8 = dev->priv; + const u8 *regs = ksz8->regs; struct ksz_port *p; + const u32 *masks; u8 remote; int i; + masks = ksz8->masks; + /* Switch marks the maximum frame with extra byte as oversize. */ ksz_cfg(dev, REG_SW_CTRL_2, SW_LEGAL_PACKET_DISABLE, true); - ksz_cfg(dev, S_TAIL_TAG_CTRL, SW_TAIL_TAG_ENABLE, true); + ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true); p = &dev->ports[dev->cpu_port]; p->vid_member = dev->port_mask; @@ -1024,7 +1158,7 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds) p = &dev->ports[i]; if (!p->on) continue; - ksz_pread8(dev, i, P_REMOTE_STATUS, &remote); + ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); if (remote & PORT_FIBER_MODE) p->fiber = 1; if (p->fiber) @@ -1222,6 +1356,7 @@ static const struct ksz_chip_data ksz8_switch_chips[] = { static int ksz8_switch_init(struct ksz_device *dev) { + struct ksz8 *ksz8 = dev->priv; int i; dev->ds->ops = &ksz8_switch_ops; @@ -1249,6 +1384,10 @@ static int ksz8_switch_init(struct ksz_device *dev) if (!dev->cpu_ports) return -ENODEV; + ksz8->regs = ksz8795_regs; + ksz8->masks = ksz8795_masks; + ksz8->shifts = ksz8795_shifts; + dev->reg_mib_cnt = KSZ8795_COUNTER_NUM; dev->mib_cnt = ARRAY_SIZE(mib_names); diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h index 40372047d40d..eea78c5636a0 100644 --- a/drivers/net/dsa/microchip/ksz8795_reg.h +++ b/drivers/net/dsa/microchip/ksz8795_reg.h @@ -98,7 +98,6 @@ #define REG_SW_CTRL_10 0x0C -#define SW_TAIL_TAG_ENABLE BIT(1) #define SW_PASS_PAUSE BIT(0) #define REG_SW_CTRL_11 0x0D @@ -150,7 +149,6 @@ #define REG_PORT_4_CTRL_2 0x42 #define REG_PORT_5_CTRL_2 0x52 -#define PORT_802_1P_REMAPPING BIT(7) #define PORT_INGRESS_FILTER BIT(6) #define PORT_DISCARD_NON_VID BIT(5) #define PORT_FORCE_FLOW_CTRL BIT(4) @@ -319,14 +317,12 @@ #define REG_PORT_CTRL_5 0x05 -#define REG_PORT_CTRL_7 0x07 #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 #define REG_PORT_CTRL_9 0x0C #define REG_PORT_CTRL_10 0x0D -#define REG_PORT_STATUS_2 0x0E #define REG_PORT_STATUS_3 0x0F #define REG_PORT_CTRL_12 0xA0 @@ -356,8 +352,6 @@ #define REG_SW_MAC_ADDR_4 0x6C #define REG_SW_MAC_ADDR_5 0x6D -#define REG_IND_CTRL_0 0x6E - #define TABLE_EXT_SELECT_S 5 #define TABLE_EEE_V 1 #define TABLE_ACL_V 2 @@ -383,23 +377,13 @@ #define TABLE_ENTRY_MASK 0x03FF #define TABLE_EXT_ENTRY_MASK 0x0FFF -#define REG_IND_DATA_8 0x70 -#define REG_IND_DATA_7 0x71 -#define REG_IND_DATA_6 0x72 #define REG_IND_DATA_5 0x73 -#define REG_IND_DATA_4 0x74 -#define REG_IND_DATA_3 0x75 #define REG_IND_DATA_2 0x76 #define REG_IND_DATA_1 0x77 #define REG_IND_DATA_0 0x78 #define REG_IND_DATA_PME_EEE_ACL 0xA0 -#define REG_IND_DATA_CHECK REG_IND_DATA_6 -#define REG_IND_MIB_CHECK REG_IND_DATA_4 -#define REG_IND_DATA_HI REG_IND_DATA_7 -#define REG_IND_DATA_LO REG_IND_DATA_3 - #define REG_INT_STATUS 0x7C #define REG_INT_ENABLE 0x7D @@ -856,12 +840,6 @@ #define P_MIRROR_CTRL REG_PORT_CTRL_1 #define P_802_1P_CTRL REG_PORT_CTRL_2 #define P_STP_CTRL REG_PORT_CTRL_2 -#define P_LOCAL_CTRL REG_PORT_CTRL_7 -#define P_REMOTE_STATUS REG_PORT_STATUS_0 -#define P_FORCE_CTRL REG_PORT_CTRL_9 -#define P_NEG_RESTART_CTRL REG_PORT_CTRL_10 -#define P_SPEED_STATUS REG_PORT_STATUS_1 -#define P_LINK_STATUS REG_PORT_STATUS_2 #define P_PASS_ALL_CTRL REG_PORT_CTRL_12 #define P_INS_SRC_PVID_CTRL REG_PORT_CTRL_12 #define P_DROP_TAG_CTRL REG_PORT_CTRL_13 @@ -876,7 +854,6 @@ #define S_MIRROR_CTRL REG_SW_CTRL_3 #define S_REPLACE_VID_CTRL REG_SW_CTRL_4 #define S_PASS_PAUSE_CTRL REG_SW_CTRL_10 -#define S_TAIL_TAG_CTRL REG_SW_CTRL_10 #define S_802_1P_PRIO_CTRL REG_SW_CTRL_12 #define S_TOS_PRIO_CTRL REG_TOS_PRIO_CTRL_0 #define S_IPV6_MLD_CTRL REG_SW_CTRL_21 @@ -889,65 +866,6 @@ /* 148,800 frames * 67 ms / 100 */ #define BROADCAST_STORM_VALUE 9969 -/** - * STATIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF - * STATIC_MAC_TABLE_FWD_PORTS 00-001F0000-00000000 - * STATIC_MAC_TABLE_VALID 00-00200000-00000000 - * STATIC_MAC_TABLE_OVERRIDE 00-00400000-00000000 - * STATIC_MAC_TABLE_USE_FID 00-00800000-00000000 - * STATIC_MAC_TABLE_FID 00-7F000000-00000000 - */ - -#define STATIC_MAC_TABLE_ADDR 0x0000FFFF -#define STATIC_MAC_TABLE_FWD_PORTS 0x001F0000 -#define STATIC_MAC_TABLE_VALID 0x00200000 -#define STATIC_MAC_TABLE_OVERRIDE 0x00400000 -#define STATIC_MAC_TABLE_USE_FID 0x00800000 -#define STATIC_MAC_TABLE_FID 0x7F000000 - -#define STATIC_MAC_FWD_PORTS_S 16 -#define STATIC_MAC_FID_S 24 - -/** - * VLAN_TABLE_FID 00-007F007F-007F007F - * VLAN_TABLE_MEMBERSHIP 00-0F800F80-0F800F80 - * VLAN_TABLE_VALID 00-10001000-10001000 - */ - -#define VLAN_TABLE_FID 0x007F -#define VLAN_TABLE_MEMBERSHIP 0x0F80 -#define VLAN_TABLE_VALID 0x1000 - -#define VLAN_TABLE_MEMBERSHIP_S 7 -#define VLAN_TABLE_S 16 - -/** - * DYNAMIC_MAC_TABLE_ADDR 00-0000FFFF-FFFFFFFF - * DYNAMIC_MAC_TABLE_FID 00-007F0000-00000000 - * DYNAMIC_MAC_TABLE_NOT_READY 00-00800000-00000000 - * DYNAMIC_MAC_TABLE_SRC_PORT 00-07000000-00000000 - * DYNAMIC_MAC_TABLE_TIMESTAMP 00-18000000-00000000 - * DYNAMIC_MAC_TABLE_ENTRIES 7F-E0000000-00000000 - * DYNAMIC_MAC_TABLE_MAC_EMPTY 80-00000000-00000000 - */ - -#define DYNAMIC_MAC_TABLE_ADDR 0x0000FFFF -#define DYNAMIC_MAC_TABLE_FID 0x007F0000 -#define DYNAMIC_MAC_TABLE_SRC_PORT 0x07000000 -#define DYNAMIC_MAC_TABLE_TIMESTAMP 0x18000000 -#define DYNAMIC_MAC_TABLE_ENTRIES 0xE0000000 - -#define DYNAMIC_MAC_TABLE_NOT_READY 0x80 - -#define DYNAMIC_MAC_TABLE_ENTRIES_H 0x7F -#define DYNAMIC_MAC_TABLE_MAC_EMPTY 0x80 - -#define DYNAMIC_MAC_FID_S 16 -#define DYNAMIC_MAC_SRC_PORT_S 24 -#define DYNAMIC_MAC_TIMESTAMP_S 27 -#define DYNAMIC_MAC_ENTRIES_S 29 -#define DYNAMIC_MAC_ENTRIES_H_S 3 - /** * MIB_COUNTER_VALUE 00-00000000-3FFFFFFF * MIB_TOTAL_BYTES 00-0000000F-FFFFFFFF @@ -956,9 +874,6 @@ * MIB_COUNTER_OVERFLOW 00-00000040-00000000 */ -#define MIB_COUNTER_OVERFLOW BIT(6) -#define MIB_COUNTER_VALID BIT(5) - #define MIB_COUNTER_VALUE 0x3FFFFFFF #define KS_MIB_TOTAL_RX_0 0x100 From patchwork Mon Apr 26 13:19:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 427741 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 302CFC433B4 for ; Mon, 26 Apr 2021 13:19:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EE087613BA for ; Mon, 26 Apr 2021 13:19:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233806AbhDZNUU (ORCPT ); Mon, 26 Apr 2021 09:20:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233619AbhDZNUE (ORCPT ); Mon, 26 Apr 2021 09:20:04 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C19DC06175F for ; Mon, 26 Apr 2021 06:19:22 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Ua-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006ml-C5; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Oleksij Rempel , Michael Grzeschik , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 4/9] net: dsa: microchip: ksz8795: add support for ksz88xx chips Date: Mon, 26 Apr 2021 15:19:06 +0200 Message-Id: <20210426131911.25976-5-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org We add support for the ksz8863 and ksz8873 chips which are using the same register patterns but other offsets as the ksz8795. Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel --- v1 -> v4: - extracted this change from bigger previous patch v4 -> v5: - added clear of reset bit for ksz8863 reset code - using extra device flag IS_KSZ88x3 instead of is_ksz8795 function - using DSA_TAG_PROTO_KSZ9893 protocol for ksz88x3 instead v5 -> v6: - changed variable order to revers christmas tree - added back missed dropped handling in init_cnt for ksz8863 - disable VLAN support for ksz8863. Currently it need more work. --- drivers/net/dsa/microchip/ksz8795.c | 319 ++++++++++++++++++++---- drivers/net/dsa/microchip/ksz8795_reg.h | 40 ++- drivers/net/dsa/microchip/ksz_common.h | 1 + 3 files changed, 284 insertions(+), 76 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index 18534d6f640d..ad509a57a945 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -72,9 +72,60 @@ static const u8 ksz8795_shifts[] = { [DYNAMIC_MAC_SRC_PORT] = 24, }; -static const struct { +static const u8 ksz8863_regs[] = { + [REG_IND_CTRL_0] = 0x79, + [REG_IND_DATA_8] = 0x7B, + [REG_IND_DATA_CHECK] = 0x7B, + [REG_IND_DATA_HI] = 0x7C, + [REG_IND_DATA_LO] = 0x80, + [REG_IND_MIB_CHECK] = 0x80, + [P_FORCE_CTRL] = 0x0C, + [P_LINK_STATUS] = 0x0E, + [P_LOCAL_CTRL] = 0x0C, + [P_NEG_RESTART_CTRL] = 0x0D, + [P_REMOTE_STATUS] = 0x0E, + [P_SPEED_STATUS] = 0x0F, + [S_TAIL_TAG_CTRL] = 0x03, +}; + +static const u32 ksz8863_masks[] = { + [PORT_802_1P_REMAPPING] = BIT(3), + [SW_TAIL_TAG_ENABLE] = BIT(6), + [MIB_COUNTER_OVERFLOW] = BIT(7), + [MIB_COUNTER_VALID] = BIT(6), + [VLAN_TABLE_FID] = GENMASK(15, 12), + [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16), + [VLAN_TABLE_VALID] = BIT(19), + [STATIC_MAC_TABLE_VALID] = BIT(19), + [STATIC_MAC_TABLE_USE_FID] = BIT(21), + [STATIC_MAC_TABLE_FID] = GENMASK(29, 26), + [STATIC_MAC_TABLE_OVERRIDE] = BIT(20), + [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16), + [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(5, 0), + [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), + [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), + [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 28), + [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16), + [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20), + [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22), +}; + +static u8 ksz8863_shifts[] = { + [VLAN_TABLE_MEMBERSHIP_S] = 16, + [STATIC_MAC_FWD_PORTS] = 16, + [STATIC_MAC_FID] = 22, + [DYNAMIC_MAC_ENTRIES_H] = 3, + [DYNAMIC_MAC_ENTRIES] = 24, + [DYNAMIC_MAC_FID] = 16, + [DYNAMIC_MAC_TIMESTAMP] = 24, + [DYNAMIC_MAC_SRC_PORT] = 20, +}; + +struct mib_names { char string[ETH_GSTRING_LEN]; -} mib_names[] = { +}; + +static const struct mib_names ksz87xx_mib_names[] = { { "rx_hi" }, { "rx_undersize" }, { "rx_fragments" }, @@ -113,6 +164,48 @@ static const struct { { "tx_discards" }, }; +static const struct mib_names ksz88xx_mib_names[] = { + { "rx" }, + { "rx_hi" }, + { "rx_undersize" }, + { "rx_fragments" }, + { "rx_oversize" }, + { "rx_jabbers" }, + { "rx_symbol_err" }, + { "rx_crc_err" }, + { "rx_align_err" }, + { "rx_mac_ctrl" }, + { "rx_pause" }, + { "rx_bcast" }, + { "rx_mcast" }, + { "rx_ucast" }, + { "rx_64_or_less" }, + { "rx_65_127" }, + { "rx_128_255" }, + { "rx_256_511" }, + { "rx_512_1023" }, + { "rx_1024_1522" }, + { "tx" }, + { "tx_hi" }, + { "tx_late_col" }, + { "tx_pause" }, + { "tx_bcast" }, + { "tx_mcast" }, + { "tx_ucast" }, + { "tx_deferred" }, + { "tx_total_col" }, + { "tx_exc_col" }, + { "tx_single_col" }, + { "tx_mult_col" }, + { "rx_discards" }, + { "tx_discards" }, +}; + +static bool ksz_is_ksz88x3(struct ksz_device *dev) +{ + return dev->chip_id == 0x8830; +} + static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); @@ -127,10 +220,18 @@ static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, static int ksz8_reset_switch(struct ksz_device *dev) { - /* reset switch */ - ksz_write8(dev, REG_POWER_MANAGEMENT_1, - SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); - ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0); + if (ksz_is_ksz88x3(dev)) { + /* reset switch */ + ksz_cfg(dev, KSZ8863_REG_SW_RESET, + KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, true); + ksz_cfg(dev, KSZ8863_REG_SW_RESET, + KSZ8863_GLOBAL_SOFTWARE_RESET | KSZ8863_PCS_RESET, false); + } else { + /* reset switch */ + ksz_write8(dev, REG_POWER_MANAGEMENT_1, + SW_SOFTWARE_POWER_DOWN << SW_POWER_MANAGEMENT_MODE_S); + ksz_write8(dev, REG_POWER_MANAGEMENT_1, 0); + } return 0; } @@ -204,8 +305,8 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) mutex_unlock(&dev->alu_mutex); } -static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, - u64 *dropped, u64 *cnt) +static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) { struct ksz8 *ksz8 = dev->priv; const u32 *masks; @@ -219,8 +320,8 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, regs = ksz8->regs; addr -= dev->reg_mib_cnt; - ctrl_addr = (KS_MIB_TOTAL_RX_1 - KS_MIB_TOTAL_RX_0) * port; - ctrl_addr += addr + KS_MIB_TOTAL_RX_0; + ctrl_addr = (KSZ8795_MIB_TOTAL_RX_1 - KSZ8795_MIB_TOTAL_RX_0) * port; + ctrl_addr += addr + KSZ8795_MIB_TOTAL_RX_0; ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); mutex_lock(&dev->alu_mutex); @@ -257,8 +358,52 @@ static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, mutex_unlock(&dev->alu_mutex); } +static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) +{ + struct ksz8 *ksz8 = dev->priv; + const u8 *regs = ksz8->regs; + u32 *last = (u32 *)dropped; + u16 ctrl_addr; + u32 data; + u32 cur; + + addr -= dev->reg_mib_cnt; + ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 : + KSZ8863_MIB_PACKET_DROPPED_RX_0; + ctrl_addr += port; + ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); + + mutex_lock(&dev->alu_mutex); + ksz_write16(dev, regs[REG_IND_CTRL_0], ctrl_addr); + ksz_read32(dev, regs[REG_IND_DATA_LO], &data); + mutex_unlock(&dev->alu_mutex); + + data &= MIB_PACKET_DROPPED; + cur = last[addr]; + if (data != cur) { + last[addr] = data; + if (data < cur) + data += MIB_PACKET_DROPPED + 1; + data -= cur; + *cnt += data; + } +} + +static void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr, + u64 *dropped, u64 *cnt) +{ + if (ksz_is_ksz88x3(dev)) + ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt); + else + ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt); +} + static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) { + if (ksz_is_ksz88x3(dev)) + return; + /* enable the port for flush/freeze function */ if (freeze) ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); @@ -272,11 +417,14 @@ static void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze) static void ksz8_port_init_cnt(struct ksz_device *dev, int port) { struct ksz_port_mib *mib = &dev->ports[port].mib; + u64 *dropped; - /* flush all enabled port MIB counters */ - ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); - ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); - ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); + if (!ksz_is_ksz88x3(dev)) { + /* flush all enabled port MIB counters */ + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), true); + ksz_cfg(dev, REG_SW_CTRL_6, SW_MIB_COUNTER_FLUSH, true); + ksz_cfg(dev, REG_SW_CTRL_6, BIT(port), false); + } mib->cnt_ptr = 0; @@ -287,10 +435,13 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port) ++mib->cnt_ptr; } + /* last one in storage */ + dropped = &mib->counters[dev->mib_cnt]; + /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ while (mib->cnt_ptr < dev->mib_cnt) { dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, - NULL, &mib->counters[mib->cnt_ptr]); + dropped, &mib->counters[mib->cnt_ptr]); ++mib->cnt_ptr; } mib->cnt_ptr = 0; @@ -508,7 +659,7 @@ static void ksz8_from_vlan(struct ksz_device *dev, u32 vlan, u8 *fid, } static void ksz8_to_vlan(struct ksz_device *dev, u8 fid, u8 member, u8 valid, - u32 *vlan) + u16 *vlan) { struct ksz8 *ksz8 = dev->priv; const u8 *shifts; @@ -588,8 +739,13 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) data |= PHY_LOOPBACK; if (ctrl & PORT_FORCE_100_MBIT) data |= PHY_SPEED_100MBIT; - if (!(ctrl & PORT_AUTO_NEG_DISABLE)) - data |= PHY_AUTO_NEG_ENABLE; + if (ksz_is_ksz88x3(dev)) { + if ((ctrl & PORT_AUTO_NEG_ENABLE)) + data |= PHY_AUTO_NEG_ENABLE; + } else { + if (!(ctrl & PORT_AUTO_NEG_DISABLE)) + data |= PHY_AUTO_NEG_ENABLE; + } if (restart & PORT_POWER_DOWN) data |= PHY_POWER_DOWN; if (restart & PORT_AUTO_NEG_RESTART) @@ -623,7 +779,10 @@ static void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val) data = KSZ8795_ID_HI; break; case PHY_REG_ID_2: - data = KSZ8795_ID_LO; + if (ksz_is_ksz88x3(dev)) + data = KSZ8863_ID_LO; + else + data = KSZ8795_ID_LO; break; case PHY_REG_AUTO_NEGOTIATION: ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl); @@ -686,14 +845,22 @@ static void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val) ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data); ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl); data = ctrl; - if (!(val & PHY_AUTO_NEG_ENABLE)) - data |= PORT_AUTO_NEG_DISABLE; - else - data &= ~PORT_AUTO_NEG_DISABLE; + if (ksz_is_ksz88x3(dev)) { + if ((val & PHY_AUTO_NEG_ENABLE)) + data |= PORT_AUTO_NEG_ENABLE; + else + data &= ~PORT_AUTO_NEG_ENABLE; + } else { + if (!(val & PHY_AUTO_NEG_ENABLE)) + data |= PORT_AUTO_NEG_DISABLE; + else + data &= ~PORT_AUTO_NEG_DISABLE; + + /* Fiber port does not support auto-negotiation. */ + if (dev->ports[p].fiber) + data |= PORT_AUTO_NEG_DISABLE; + } - /* Fiber port does not support auto-negotiation. */ - if (dev->ports[p].fiber) - data |= PORT_AUTO_NEG_DISABLE; if (val & PHY_SPEED_100MBIT) data |= PORT_FORCE_100_MBIT; else @@ -767,7 +934,11 @@ static enum dsa_tag_protocol ksz8_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp) { - return DSA_TAG_PROTO_KSZ8795; + 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 void ksz8_get_strings(struct dsa_switch *ds, int port, @@ -777,8 +948,8 @@ static void ksz8_get_strings(struct dsa_switch *ds, int port, int i; for (i = 0; i < dev->mib_cnt; i++) { - memcpy(buf + i * ETH_GSTRING_LEN, mib_names[i].string, - ETH_GSTRING_LEN); + memcpy(buf + i * ETH_GSTRING_LEN, + dev->mib_names[i].string, ETH_GSTRING_LEN); } } @@ -904,6 +1075,9 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag, { struct ksz_device *dev = ds->priv; + if (ksz_is_ksz88x3(dev)) + return -ENOTSUPP; + ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag); return 0; @@ -915,10 +1089,12 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port, { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_device *dev = ds->priv; - u16 new_pvid = 0; - u32 data = 0; + u16 data, new_pvid = 0; u8 fid, member, valid; + if (ksz_is_ksz88x3(dev)) + return -ENOTSUPP; + ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged); ksz8_r_vlan_table(dev, vlan->vid, &data); @@ -956,10 +1132,12 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port, { bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; struct ksz_device *dev = ds->priv; - u16 pvid, new_pvid = 0; - u32 data = 0; + u16 data, pvid, new_pvid = 0; u8 fid, member, valid; + if (ksz_is_ksz88x3(dev)) + return -ENOTSUPP; + ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid); pvid = pvid & 0xFFF; @@ -1093,7 +1271,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) /* enable broadcast storm limit */ ksz_port_cfg(dev, port, P_BCAST_STORM_CTRL, PORT_BROADCAST_STORM, true); - ksz8795_set_prio_queue(dev, port, 4); + if (!ksz_is_ksz88x3(dev)) + ksz8795_set_prio_queue(dev, port, 4); /* disable DiffServ priority */ ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_DIFFSERV_ENABLE, false); @@ -1106,7 +1285,8 @@ static void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port) ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_ENABLE, true); if (cpu_port) { - ksz8795_cpu_interface_select(dev, port); + if (!ksz_is_ksz88x3(dev)) + ksz8795_cpu_interface_select(dev, port); member = dev->port_mask; } else { @@ -1158,9 +1338,11 @@ static void ksz8_config_cpu_port(struct dsa_switch *ds) p = &dev->ports[i]; if (!p->on) continue; - ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); - if (remote & PORT_FIBER_MODE) - p->fiber = 1; + if (!ksz_is_ksz88x3(dev)) { + ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); + if (remote & PORT_FIBER_MODE) + p->fiber = 1; + } if (p->fiber) ksz_port_cfg(dev, i, P_STP_CTRL, PORT_FORCE_FLOW_CTRL, true); @@ -1279,19 +1461,30 @@ static int ksz8_switch_detect(struct ksz_device *dev) id1 = id16 >> 8; id2 = id16 & SW_CHIP_ID_M; - if (id1 != FAMILY_ID || - (id2 != CHIP_ID_94 && id2 != CHIP_ID_95)) - return -ENODEV; - if (id2 == CHIP_ID_95) { - u8 val; + 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_1_STATUS_0, &val); - if (val & PORT_FIBER_MODE) - id2 = 0x65; - } else if (id2 == CHIP_ID_94) { - id2 = 0x94; + 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; @@ -1352,6 +1545,15 @@ static const struct ksz_chip_data ksz8_switch_chips[] = { .cpu_ports = 0x10, /* can be configured as cpu port */ .port_cnt = 5, /* total cpu and user ports */ }, + { + .chip_id = 0x8830, + .dev_name = "KSZ8863/KSZ8873", + .num_vlans = 16, + .num_alus = 0, + .num_statics = 8, + .cpu_ports = 0x4, /* can be configured as cpu port */ + .port_cnt = 3, + }, }; static int ksz8_switch_init(struct ksz_device *dev) @@ -1384,12 +1586,21 @@ static int ksz8_switch_init(struct ksz_device *dev) if (!dev->cpu_ports) return -ENODEV; - ksz8->regs = ksz8795_regs; - ksz8->masks = ksz8795_masks; - ksz8->shifts = ksz8795_shifts; + if (ksz_is_ksz88x3(dev)) { + ksz8->regs = ksz8863_regs; + ksz8->masks = ksz8863_masks; + ksz8->shifts = ksz8863_shifts; + dev->mib_cnt = ARRAY_SIZE(ksz88xx_mib_names); + dev->mib_names = ksz88xx_mib_names; + } else { + ksz8->regs = ksz8795_regs; + ksz8->masks = ksz8795_masks; + ksz8->shifts = ksz8795_shifts; + dev->mib_cnt = ARRAY_SIZE(ksz87xx_mib_names); + dev->mib_names = ksz87xx_mib_names; + } - dev->reg_mib_cnt = KSZ8795_COUNTER_NUM; - dev->mib_cnt = ARRAY_SIZE(mib_names); + dev->reg_mib_cnt = MIB_COUNTER_NUM; dev->ports = devm_kzalloc(dev->dev, dev->port_cnt * sizeof(struct ksz_port), diff --git a/drivers/net/dsa/microchip/ksz8795_reg.h b/drivers/net/dsa/microchip/ksz8795_reg.h index eea78c5636a0..c2e52c40a54c 100644 --- a/drivers/net/dsa/microchip/ksz8795_reg.h +++ b/drivers/net/dsa/microchip/ksz8795_reg.h @@ -16,7 +16,8 @@ #define REG_CHIP_ID0 0x00 -#define FAMILY_ID 0x87 +#define KSZ87_FAMILY_ID 0x87 +#define KSZ88_FAMILY_ID 0x88 #define REG_CHIP_ID1 0x01 @@ -28,6 +29,12 @@ #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) +#define KSZ8863_PCS_RESET BIT(0) #define REG_SW_CTRL_0 0x02 @@ -267,6 +274,7 @@ #define REG_PORT_3_CTRL_9 0x3C #define REG_PORT_4_CTRL_9 0x4C +#define PORT_AUTO_NEG_ENABLE BIT(7) #define PORT_AUTO_NEG_DISABLE BIT(7) #define PORT_FORCE_100_MBIT BIT(6) #define PORT_FORCE_FULL_DUPLEX BIT(5) @@ -800,6 +808,7 @@ #define KSZ8795_ID_HI 0x0022 #define KSZ8795_ID_LO 0x1550 +#define KSZ8863_ID_LO 0x1430 #define KSZ8795_SW_ID 0x8795 @@ -830,7 +839,7 @@ #define KS_PRIO_IN_REG 4 -#define KSZ8795_COUNTER_NUM 0x20 +#define MIB_COUNTER_NUM 0x20 /* Common names used by other drivers */ @@ -876,26 +885,13 @@ #define MIB_COUNTER_VALUE 0x3FFFFFFF -#define KS_MIB_TOTAL_RX_0 0x100 -#define KS_MIB_TOTAL_TX_0 0x101 -#define KS_MIB_PACKET_DROPPED_RX_0 0x102 -#define KS_MIB_PACKET_DROPPED_TX_0 0x103 -#define KS_MIB_TOTAL_RX_1 0x104 -#define KS_MIB_TOTAL_TX_1 0x105 -#define KS_MIB_PACKET_DROPPED_TX_1 0x106 -#define KS_MIB_PACKET_DROPPED_RX_1 0x107 -#define KS_MIB_TOTAL_RX_2 0x108 -#define KS_MIB_TOTAL_TX_2 0x109 -#define KS_MIB_PACKET_DROPPED_TX_2 0x10A -#define KS_MIB_PACKET_DROPPED_RX_2 0x10B -#define KS_MIB_TOTAL_RX_3 0x10C -#define KS_MIB_TOTAL_TX_3 0x10D -#define KS_MIB_PACKET_DROPPED_TX_3 0x10E -#define KS_MIB_PACKET_DROPPED_RX_3 0x10F -#define KS_MIB_TOTAL_RX_4 0x110 -#define KS_MIB_TOTAL_TX_4 0x111 -#define KS_MIB_PACKET_DROPPED_TX_4 0x112 -#define KS_MIB_PACKET_DROPPED_RX_4 0x113 +#define KSZ8795_MIB_TOTAL_RX_0 0x100 +#define KSZ8795_MIB_TOTAL_TX_0 0x101 +#define KSZ8795_MIB_TOTAL_RX_1 0x104 +#define KSZ8795_MIB_TOTAL_TX_1 0x105 + +#define KSZ8863_MIB_PACKET_DROPPED_TX_0 0x100 +#define KSZ8863_MIB_PACKET_DROPPED_RX_0 0x105 #define MIB_PACKET_DROPPED 0x0000FFFF diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index f0681a891cca..e0bbdca64375 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -71,6 +71,7 @@ struct ksz_device { int port_cnt; int reg_mib_cnt; int mib_cnt; + const struct mib_names *mib_names; phy_interface_t compat_interface; u32 regs_size; bool phy_errata_9477; From patchwork Mon Apr 26 13:19:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 427743 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 832C0C43600 for ; Mon, 26 Apr 2021 13:19:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 511EC61185 for ; Mon, 26 Apr 2021 13:19:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233725AbhDZNUH (ORCPT ); Mon, 26 Apr 2021 09:20:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232575AbhDZNUD (ORCPT ); Mon, 26 Apr 2021 09:20:03 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EFF28C06175F for ; Mon, 26 Apr 2021 06:19:21 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Ub-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006mu-D6; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 5/9] net: dsa: microchip: Add Microchip KSZ8863 SPI based driver support Date: Mon, 26 Apr 2021 15:19:07 +0200 Message-Id: <20210426131911.25976-6-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik Add KSZ88X3 driver support. We add support for the KXZ88X3 three port switches using the SPI Interface. Reviewed-by: Florian Fainelli Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn --- v1 -> v2: - this glue was not implemented v2 -> v3: - this glue was part of previous bigger patch v3 -> v4: - this glue was moved to this separate patch v4 -> v5: - added reviewed by from f.fainelli - using device_get_match_data instead of own matching code --- drivers/net/dsa/microchip/ksz8795_spi.c | 44 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index 45420c07c99f..85ba12aa82d8 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -14,34 +14,52 @@ #include #include +#include "ksz8.h" #include "ksz_common.h" -#define SPI_ADDR_SHIFT 12 -#define SPI_ADDR_ALIGN 3 -#define SPI_TURNAROUND_SHIFT 1 +#define KSZ8795_SPI_ADDR_SHIFT 12 +#define KSZ8795_SPI_ADDR_ALIGN 3 +#define KSZ8795_SPI_TURNAROUND_SHIFT 1 -KSZ_REGMAP_TABLE(ksz8795, 16, SPI_ADDR_SHIFT, - SPI_TURNAROUND_SHIFT, SPI_ADDR_ALIGN); +#define KSZ8863_SPI_ADDR_SHIFT 8 +#define KSZ8863_SPI_ADDR_ALIGN 8 +#define KSZ8863_SPI_TURNAROUND_SHIFT 0 + +KSZ_REGMAP_TABLE(ksz8795, 16, KSZ8795_SPI_ADDR_SHIFT, + KSZ8795_SPI_TURNAROUND_SHIFT, KSZ8795_SPI_ADDR_ALIGN); + +KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT, + KSZ8863_SPI_TURNAROUND_SHIFT, KSZ8863_SPI_ADDR_ALIGN); static int ksz8795_spi_probe(struct spi_device *spi) { + const struct regmap_config *regmap_config; + struct device *ddev = &spi->dev; struct regmap_config rc; struct ksz_device *dev; - int i, ret; + struct ksz8 *ksz8; + int i, ret = 0; - dev = ksz_switch_alloc(&spi->dev, spi); + ksz8 = devm_kzalloc(&spi->dev, sizeof(struct ksz8), GFP_KERNEL); + ksz8->priv = spi; + + dev = ksz_switch_alloc(&spi->dev, ksz8); if (!dev) return -ENOMEM; + regmap_config = device_get_match_data(ddev); + if (!regmap_config) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { - rc = ksz8795_regmap_config[i]; + rc = regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; dev->regmap[i] = devm_regmap_init_spi(spi, &rc); if (IS_ERR(dev->regmap[i])) { ret = PTR_ERR(dev->regmap[i]); dev_err(&spi->dev, "Failed to initialize regmap%i: %d\n", - ksz8795_regmap_config[i].val_bits, ret); + regmap_config[i].val_bits, ret); return ret; } } @@ -85,9 +103,11 @@ static void ksz8795_spi_shutdown(struct spi_device *spi) } static const struct of_device_id ksz8795_dt_ids[] = { - { .compatible = "microchip,ksz8765" }, - { .compatible = "microchip,ksz8794" }, - { .compatible = "microchip,ksz8795" }, + { .compatible = "microchip,ksz8765", .data = &ksz8795_regmap_config }, + { .compatible = "microchip,ksz8794", .data = &ksz8795_regmap_config }, + { .compatible = "microchip,ksz8795", .data = &ksz8795_regmap_config }, + { .compatible = "microchip,ksz8863", .data = &ksz8863_regmap_config }, + { .compatible = "microchip,ksz8873", .data = &ksz8863_regmap_config }, {}, }; MODULE_DEVICE_TABLE(of, ksz8795_dt_ids); From patchwork Mon Apr 26 13:19:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 428416 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB54BC43470 for ; Mon, 26 Apr 2021 13:19:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9B0BE61139 for ; Mon, 26 Apr 2021 13:19:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233864AbhDZNUY (ORCPT ); Mon, 26 Apr 2021 09:20:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233681AbhDZNUF (ORCPT ); Mon, 26 Apr 2021 09:20:05 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0EDEBC06175F for ; Mon, 26 Apr 2021 06:19:24 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Uc-CI; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006n3-E7; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , devicetree@vger.kernel.org, Rob Herring , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 6/9] dt-bindings: net: dsa: document additional Microchip KSZ8863/8873 switch Date: Mon, 26 Apr 2021 15:19:08 +0200 Message-Id: <20210426131911.25976-7-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik It is a 3-Port 10/100 Ethernet Switch. One CPU-Port and two Switch-Ports. Cc: devicetree@vger.kernel.org Reviewed-by: Andrew Lunn Acked-by: Rob Herring Reviewed-by: Florian Fainelli Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel --- v1 -> v3: - nothing changes - already Acked-by Rob Herring v1 -> v4: - nothing changes v4 -> v5: - nothing changes --- Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml index 9f7d131bbcef..84985f53bffd 100644 --- a/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml +++ b/Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml @@ -21,6 +21,8 @@ properties: - microchip,ksz8765 - microchip,ksz8794 - microchip,ksz8795 + - microchip,ksz8863 + - microchip,ksz8873 - microchip,ksz9477 - microchip,ksz9897 - microchip,ksz9896 From patchwork Mon Apr 26 13:19:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 427744 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7FA3C433B4 for ; Mon, 26 Apr 2021 13:19:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6150F6135A for ; Mon, 26 Apr 2021 13:19:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233494AbhDZNUE (ORCPT ); Mon, 26 Apr 2021 09:20:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231862AbhDZNUD (ORCPT ); Mon, 26 Apr 2021 09:20:03 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5E71C061574 for ; Mon, 26 Apr 2021 06:19:21 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Ud-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006nC-F7; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 7/9] net: phy: Add support for microchip SMI0 MDIO bus Date: Mon, 26 Apr 2021 15:19:09 +0200 Message-Id: <20210426131911.25976-8-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Andrew Lunn SMI0 is a mangled version of MDIO. The main low level difference is the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The read/write information is instead encoded in the PHY address. Extend the bit-bang code to allow the op code to be overridden, but default to normal C22 values. Add an extra compatible to the mdio-gpio driver, and when this compatible is present, set the op codes to 0. A higher level driver, sitting on top of the basic MDIO bus driver can then implement the rest of the microchip SMI0 odderties. Signed-off-by: Andrew Lunn Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Florian Fainelli --- v1 -> v2: - patch not present v2 -> v3: - first patch v3 -> v4: - added override_c22_op v4 -> v5: - moved override_c22_op out of else case --- drivers/net/mdio/mdio-bitbang.c | 8 ++++++-- drivers/net/mdio/mdio-gpio.c | 8 ++++++++ include/linux/mdio-bitbang.h | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/net/mdio/mdio-bitbang.c b/drivers/net/mdio/mdio-bitbang.c index 0f457c436335..07609114a26b 100644 --- a/drivers/net/mdio/mdio-bitbang.c +++ b/drivers/net/mdio/mdio-bitbang.c @@ -158,7 +158,7 @@ int mdiobb_read(struct mii_bus *bus, int phy, int reg) reg = mdiobb_cmd_addr(ctrl, phy, reg); mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg); } else - mdiobb_cmd(ctrl, MDIO_READ, phy, reg); + mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); ctrl->ops->set_mdio_dir(ctrl, 0); @@ -190,7 +190,7 @@ int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val) reg = mdiobb_cmd_addr(ctrl, phy, reg); mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg); } else - mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg); + mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); /* send the turnaround (10) */ mdiobb_send_bit(ctrl, 1); @@ -217,6 +217,10 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl) bus->read = mdiobb_read; bus->write = mdiobb_write; bus->priv = ctrl; + if (!ctrl->override_op_c22) { + ctrl->op_c22_read = MDIO_READ; + ctrl->op_c22_write = MDIO_WRITE; + } return bus; } diff --git a/drivers/net/mdio/mdio-gpio.c b/drivers/net/mdio/mdio-gpio.c index 56c8f914f893..0fb3c2de0845 100644 --- a/drivers/net/mdio/mdio-gpio.c +++ b/drivers/net/mdio/mdio-gpio.c @@ -132,6 +132,13 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask; } + if (dev->of_node && + of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) { + bitbang->ctrl.op_c22_read = 0; + bitbang->ctrl.op_c22_write = 0; + bitbang->ctrl.override_op_c22 = 1; + } + dev_set_drvdata(dev, new_bus); return new_bus; @@ -196,6 +203,7 @@ static int mdio_gpio_remove(struct platform_device *pdev) static const struct of_device_id mdio_gpio_of_match[] = { { .compatible = "virtual,mdio-gpio", }, + { .compatible = "microchip,mdio-smi0" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mdio_gpio_of_match); diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h index aca4dc037b70..373630fe5c28 100644 --- a/include/linux/mdio-bitbang.h +++ b/include/linux/mdio-bitbang.h @@ -33,6 +33,9 @@ struct mdiobb_ops { struct mdiobb_ctrl { const struct mdiobb_ops *ops; + unsigned int override_op_c22; + u8 op_c22_read; + u8 op_c22_write; }; int mdiobb_read(struct mii_bus *bus, int phy, int reg); From patchwork Mon Apr 26 13:19:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 427742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7AE9C43461 for ; Mon, 26 Apr 2021 13:19:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A4D2360FD9 for ; Mon, 26 Apr 2021 13:19:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233775AbhDZNUM (ORCPT ); Mon, 26 Apr 2021 09:20:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233294AbhDZNUD (ORCPT ); Mon, 26 Apr 2021 09:20:03 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FEB7C061760 for ; Mon, 26 Apr 2021 06:19:22 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Ue-CI; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006nL-G9; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 8/9] net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support Date: Mon, 26 Apr 2021 15:19:10 +0200 Message-Id: <20210426131911.25976-9-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik Add KSZ88X3 driver support. We add support for the KXZ88X3 three port switches using the Microchip SMI Interface. They are supported using the MDIO-Bitbang Interface. Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel Reviewed-by: Andrew Lunn --- v1 -> v2: - this code was part of previuos patch v2 -> v3: - this code was part of previuos patch v3 -> v4: - moved this glue code so separate patch - fixed locking in regmap and mdio_read/mdio_write v4 -> v5: - removed extra default y in Kconfig - fixed capitalization in Kconfig description - removed unnecessary cast - added back the define for READ operation - added KSZ88x3 to help text for KSZ8795 Kconfig entry --- drivers/net/dsa/microchip/Kconfig | 10 +- drivers/net/dsa/microchip/Makefile | 1 + drivers/net/dsa/microchip/ksz8863_smi.c | 213 ++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 drivers/net/dsa/microchip/ksz8863_smi.c diff --git a/drivers/net/dsa/microchip/Kconfig b/drivers/net/dsa/microchip/Kconfig index 4ec6a47b7f72..c9e2a8989556 100644 --- a/drivers/net/dsa/microchip/Kconfig +++ b/drivers/net/dsa/microchip/Kconfig @@ -29,7 +29,7 @@ menuconfig NET_DSA_MICROCHIP_KSZ8795 depends on NET_DSA select NET_DSA_MICROCHIP_KSZ_COMMON help - This driver adds support for Microchip KSZ8795 switch chips. + This driver adds support for Microchip KSZ8795/KSZ88X3 switch chips. config NET_DSA_MICROCHIP_KSZ8795_SPI tristate "KSZ8795 series SPI connected switch driver" @@ -40,3 +40,11 @@ config NET_DSA_MICROCHIP_KSZ8795_SPI It is required to use the KSZ8795 switch driver as the only access is through SPI. + +config NET_DSA_MICROCHIP_KSZ8863_SMI + tristate "KSZ series SMI connected switch driver" + depends on NET_DSA_MICROCHIP_KSZ8795 + select MDIO_BITBANG + help + Select to enable support for registering switches configured through + Microchip SMI. It supports the KSZ8863 and KSZ8873 switch. diff --git a/drivers/net/dsa/microchip/Makefile b/drivers/net/dsa/microchip/Makefile index 929caa81e782..2a03b21a3386 100644 --- a/drivers/net/dsa/microchip/Makefile +++ b/drivers/net/dsa/microchip/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C) += ksz9477_i2c.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI) += ksz9477_spi.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795) += ksz8795.o obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI) += ksz8795_spi.o +obj-$(CONFIG_NET_DSA_MICROCHIP_KSZ8863_SMI) += ksz8863_smi.o diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c new file mode 100644 index 000000000000..30d97ea7a949 --- /dev/null +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Microchip KSZ8863 series register access through SMI + * + * Copyright (C) 2019 Pengutronix, Michael Grzeschik + */ + +#include "ksz8.h" +#include "ksz_common.h" + +/* Serial Management Interface (SMI) uses the following frame format: + * + * preamble|start|Read/Write| PHY | REG |TA| Data bits | Idle + * |frame| OP code |address |address| | | + * read | 32x1´s | 01 | 00 | 1xRRR | RRRRR |Z0| 00000000DDDDDDDD | Z + * write| 32x1´s | 01 | 00 | 0xRRR | RRRRR |10| xxxxxxxxDDDDDDDD | Z + * + */ + +#define SMI_KSZ88XX_READ_PHY BIT(4) + +static int ksz8863_mdio_read(void *ctx, const void *reg_buf, size_t reg_len, + void *val_buf, size_t val_len) +{ + struct ksz_device *dev = ctx; + struct mdio_device *mdev; + u8 reg = *(u8 *)reg_buf; + u8 *val = val_buf; + struct ksz8 *ksz8; + int i, ret = 0; + + ksz8 = dev->priv; + mdev = ksz8->priv; + + mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED); + for (i = 0; i < val_len; i++) { + int tmp = reg + i; + + ret = __mdiobus_read(mdev->bus, ((tmp & 0xE0) >> 5) | + SMI_KSZ88XX_READ_PHY, tmp); + if (ret < 0) + goto out; + + val[i] = ret; + } + ret = 0; + + out: + mutex_unlock(&mdev->bus->mdio_lock); + + return ret; +} + +static int ksz8863_mdio_write(void *ctx, const void *data, size_t count) +{ + struct ksz_device *dev = ctx; + struct mdio_device *mdev; + struct ksz8 *ksz8; + int i, ret = 0; + u32 reg; + u8 *val; + + ksz8 = dev->priv; + mdev = ksz8->priv; + + val = (u8 *)(data + 4); + reg = *(u32 *)data; + + mutex_lock_nested(&mdev->bus->mdio_lock, MDIO_MUTEX_NESTED); + for (i = 0; i < (count - 4); i++) { + int tmp = reg + i; + + ret = __mdiobus_write(mdev->bus, ((tmp & 0xE0) >> 5), + tmp, val[i]); + if (ret < 0) + goto out; + } + + out: + mutex_unlock(&mdev->bus->mdio_lock); + + return ret; +} + +static const struct regmap_bus regmap_smi[] = { + { + .read = ksz8863_mdio_read, + .write = ksz8863_mdio_write, + .max_raw_read = 1, + .max_raw_write = 1, + }, + { + .read = ksz8863_mdio_read, + .write = ksz8863_mdio_write, + .val_format_endian_default = REGMAP_ENDIAN_BIG, + .max_raw_read = 2, + .max_raw_write = 2, + }, + { + .read = ksz8863_mdio_read, + .write = ksz8863_mdio_write, + .val_format_endian_default = REGMAP_ENDIAN_BIG, + .max_raw_read = 4, + .max_raw_write = 4, + } +}; + +static const struct regmap_config ksz8863_regmap_config[] = { + { + .name = "#8", + .reg_bits = 8, + .pad_bits = 24, + .val_bits = 8, + .cache_type = REGCACHE_NONE, + .use_single_read = 1, + .lock = ksz_regmap_lock, + .unlock = ksz_regmap_unlock, + }, + { + .name = "#16", + .reg_bits = 8, + .pad_bits = 24, + .val_bits = 16, + .cache_type = REGCACHE_NONE, + .use_single_read = 1, + .lock = ksz_regmap_lock, + .unlock = ksz_regmap_unlock, + }, + { + .name = "#32", + .reg_bits = 8, + .pad_bits = 24, + .val_bits = 32, + .cache_type = REGCACHE_NONE, + .use_single_read = 1, + .lock = ksz_regmap_lock, + .unlock = ksz_regmap_unlock, + } +}; + +static int ksz8863_smi_probe(struct mdio_device *mdiodev) +{ + struct regmap_config rc; + struct ksz_device *dev; + struct ksz8 *ksz8; + int ret; + int i; + + ksz8 = devm_kzalloc(&mdiodev->dev, sizeof(struct ksz8), GFP_KERNEL); + ksz8->priv = mdiodev; + + dev = ksz_switch_alloc(&mdiodev->dev, ksz8); + if (!dev) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) { + rc = ksz8863_regmap_config[i]; + rc.lock_arg = &dev->regmap_mutex; + dev->regmap[i] = devm_regmap_init(&mdiodev->dev, + ®map_smi[i], dev, + &rc); + if (IS_ERR(dev->regmap[i])) { + ret = PTR_ERR(dev->regmap[i]); + dev_err(&mdiodev->dev, + "Failed to initialize regmap%i: %d\n", + ksz8863_regmap_config[i].val_bits, ret); + return ret; + } + } + + if (mdiodev->dev.platform_data) + dev->pdata = mdiodev->dev.platform_data; + + ret = ksz8_switch_register(dev); + + /* Main DSA driver may not be started yet. */ + if (ret) + return ret; + + dev_set_drvdata(&mdiodev->dev, dev); + + return 0; +} + +static void ksz8863_smi_remove(struct mdio_device *mdiodev) +{ + struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev); + + if (dev) + ksz_switch_remove(dev); +} + +static const struct of_device_id ksz8863_dt_ids[] = { + { .compatible = "microchip,ksz8863" }, + { .compatible = "microchip,ksz8873" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ksz8863_dt_ids); + +static struct mdio_driver ksz8863_driver = { + .probe = ksz8863_smi_probe, + .remove = ksz8863_smi_remove, + .mdiodrv.driver = { + .name = "ksz8863-switch", + .of_match_table = ksz8863_dt_ids, + }, +}; + +mdio_module_driver(ksz8863_driver); + +MODULE_AUTHOR("Michael Grzeschik "); +MODULE_DESCRIPTION("Microchip KSZ8863 SMI Switch driver"); +MODULE_LICENSE("GPL v2"); From patchwork Mon Apr 26 13:19:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksij Rempel X-Patchwork-Id: 428415 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8938C433B4 for ; Mon, 26 Apr 2021 13:19:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ABA7461139 for ; Mon, 26 Apr 2021 13:19:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233753AbhDZNU0 (ORCPT ); Mon, 26 Apr 2021 09:20:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233682AbhDZNUF (ORCPT ); Mon, 26 Apr 2021 09:20:05 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10D7EC061760 for ; Mon, 26 Apr 2021 06:19:24 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lb18s-0004Uf-CJ; Mon, 26 Apr 2021 15:19:14 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lb18r-0006nU-HB; Mon, 26 Apr 2021 15:19:13 +0200 From: Oleksij Rempel To: Woojung Huh , UNGLinuxDriver@microchip.com, Andrew Lunn , Florian Fainelli , Vivien Didelot , Vladimir Oltean , "David S. Miller" , Jakub Kicinski Cc: Michael Grzeschik , devicetree@vger.kernel.org, Rob Herring , Oleksij Rempel , kernel@pengutronix.de, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Russell King Subject: [PATCH net-next v7 9/9] dt-bindings: net: mdio-gpio: add compatible for microchip, mdio-smi0 Date: Mon, 26 Apr 2021 15:19:11 +0200 Message-Id: <20210426131911.25976-10-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210426131911.25976-1-o.rempel@pengutronix.de> References: <20210426131911.25976-1-o.rempel@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: netdev@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Michael Grzeschik Microchip SMI0 Mode is a special mode, where the MDIO Read/Write commands are part of the PHY Address and the OP Code is always 0. We add the compatible for this special mode of the bitbanged mdio driver. Cc: devicetree@vger.kernel.org Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Acked-by: Rob Herring Signed-off-by: Michael Grzeschik Signed-off-by: Oleksij Rempel --- v1 -> v2: - patch not present v2 -> v3: - first patch v3 -> v4: - no changes --- Documentation/devicetree/bindings/net/mdio-gpio.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt index 8dbcf8295c6c..4d91a36c5cf5 100644 --- a/Documentation/devicetree/bindings/net/mdio-gpio.txt +++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt @@ -2,6 +2,7 @@ MDIO on GPIOs Currently defined compatibles: - virtual,gpio-mdio +- microchip,mdio-smi0 MDC and MDIO lines connected to GPIO controllers are listed in the gpios property as described in section VIII.1 in the following order: