mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
net: dsa: microchip: Add KSZ8895/KSZ8864 switch support
KSZ8895/KSZ8864 is a switch family between KSZ8863/73 and KSZ8795, so it shares some registers and functions in those switches already implemented in the KSZ DSA driver. Signed-off-by: Tristram Ha <tristram.ha@microchip.com> Tested-by: Pieter Van Trappen <pieter.van.trappen@cern.ch> Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e3717f2ad1
commit
a96c5515d0
@ -188,6 +188,8 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
|
||||
case KSZ8765_CHIP_ID:
|
||||
return ksz8795_change_mtu(dev, frame_size);
|
||||
case KSZ8830_CHIP_ID:
|
||||
case KSZ8864_CHIP_ID:
|
||||
case KSZ8895_CHIP_ID:
|
||||
return ksz8863_change_mtu(dev, frame_size);
|
||||
}
|
||||
|
||||
@ -384,7 +386,7 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
u64 *dropped, u64 *cnt)
|
||||
{
|
||||
if (ksz_is_ksz88x3(dev))
|
||||
if (is_ksz88xx(dev))
|
||||
ksz8863_r_mib_pkt(dev, port, addr, dropped, cnt);
|
||||
else
|
||||
ksz8795_r_mib_pkt(dev, port, addr, dropped, cnt);
|
||||
@ -392,7 +394,7 @@ void ksz8_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
|
||||
void ksz8_freeze_mib(struct ksz_device *dev, int port, bool freeze)
|
||||
{
|
||||
if (ksz_is_ksz88x3(dev))
|
||||
if (is_ksz88xx(dev))
|
||||
return;
|
||||
|
||||
/* enable the port for flush/freeze function */
|
||||
@ -410,7 +412,8 @@ void ksz8_port_init_cnt(struct ksz_device *dev, int port)
|
||||
struct ksz_port_mib *mib = &dev->ports[port].mib;
|
||||
u64 *dropped;
|
||||
|
||||
if (!ksz_is_ksz88x3(dev)) {
|
||||
/* For KSZ8795 family. */
|
||||
if (ksz_is_ksz87xx(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);
|
||||
@ -609,11 +612,11 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
|
||||
shifts[STATIC_MAC_FWD_PORTS];
|
||||
alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
|
||||
|
||||
/* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
|
||||
/* KSZ8795/KSZ8895 family switches have STATIC_MAC_TABLE_USE_FID and
|
||||
* STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
|
||||
* static MAC table compared to doing write.
|
||||
*/
|
||||
if (ksz_is_ksz87xx(dev))
|
||||
if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev))
|
||||
data_hi >>= 1;
|
||||
alu->is_static = true;
|
||||
alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
|
||||
@ -1692,7 +1695,8 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
|
||||
for (i = 0; i < dev->phy_port_cnt; i++) {
|
||||
p = &dev->ports[i];
|
||||
|
||||
if (!ksz_is_ksz88x3(dev)) {
|
||||
/* For KSZ8795 family. */
|
||||
if (ksz_is_ksz87xx(dev)) {
|
||||
ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote);
|
||||
if (remote & KSZ8_PORT_FIBER_MODE)
|
||||
p->fiber = 1;
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Microchip switch driver main logic
|
||||
*
|
||||
* Copyright (C) 2017-2019 Microchip Technology Inc.
|
||||
* Copyright (C) 2017-2024 Microchip Technology Inc.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@ -277,7 +277,7 @@ static const struct phylink_mac_ops ksz8_phylink_mac_ops = {
|
||||
.mac_link_up = ksz8_phylink_mac_link_up,
|
||||
};
|
||||
|
||||
static const struct ksz_dev_ops ksz88x3_dev_ops = {
|
||||
static const struct ksz_dev_ops ksz88xx_dev_ops = {
|
||||
.setup = ksz8_setup,
|
||||
.get_port_addr = ksz8_get_port_addr,
|
||||
.cfg_port_member = ksz8_cfg_port_member,
|
||||
@ -572,6 +572,61 @@ static u8 ksz8863_shifts[] = {
|
||||
[DYNAMIC_MAC_SRC_PORT] = 20,
|
||||
};
|
||||
|
||||
static const u16 ksz8895_regs[] = {
|
||||
[REG_SW_MAC_ADDR] = 0x68,
|
||||
[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] = 0x75,
|
||||
[P_FORCE_CTRL] = 0x0C,
|
||||
[P_LINK_STATUS] = 0x0E,
|
||||
[P_LOCAL_CTRL] = 0x0C,
|
||||
[P_NEG_RESTART_CTRL] = 0x0D,
|
||||
[P_REMOTE_STATUS] = 0x0E,
|
||||
[P_SPEED_STATUS] = 0x09,
|
||||
[S_TAIL_TAG_CTRL] = 0x0C,
|
||||
[P_STP_CTRL] = 0x02,
|
||||
[S_START_CTRL] = 0x01,
|
||||
[S_BROADCAST_CTRL] = 0x06,
|
||||
[S_MULTICAST_CTRL] = 0x04,
|
||||
};
|
||||
|
||||
static const u32 ksz8895_masks[] = {
|
||||
[PORT_802_1P_REMAPPING] = BIT(7),
|
||||
[SW_TAIL_TAG_ENABLE] = BIT(1),
|
||||
[MIB_COUNTER_OVERFLOW] = BIT(7),
|
||||
[MIB_COUNTER_VALID] = BIT(6),
|
||||
[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(22),
|
||||
[STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16),
|
||||
[DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0),
|
||||
[DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7),
|
||||
[DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
|
||||
[DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29),
|
||||
[DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16),
|
||||
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24),
|
||||
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27),
|
||||
};
|
||||
|
||||
static const u8 ksz8895_shifts[] = {
|
||||
[VLAN_TABLE_MEMBERSHIP_S] = 7,
|
||||
[VLAN_TABLE] = 13,
|
||||
[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 u16 ksz9477_regs[] = {
|
||||
[REG_SW_MAC_ADDR] = 0x0302,
|
||||
[P_STP_CTRL] = 0x0B04,
|
||||
@ -1397,7 +1452,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.port_cnt = 3,
|
||||
.num_tx_queues = 4,
|
||||
.num_ipms = 4,
|
||||
.ops = &ksz88x3_dev_ops,
|
||||
.ops = &ksz88xx_dev_ops,
|
||||
.phylink_mac_ops = &ksz8830_phylink_mac_ops,
|
||||
.mib_names = ksz88xx_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
|
||||
@ -1412,6 +1467,61 @@ const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
.rd_table = &ksz8873_register_set,
|
||||
},
|
||||
|
||||
[KSZ8864] = {
|
||||
/* WARNING
|
||||
* =======
|
||||
* KSZ8864 is similar to KSZ8895, except the first port
|
||||
* does not exist.
|
||||
* external cpu
|
||||
* KSZ8864 1,2,3 4
|
||||
* KSZ8895 0,1,2,3 4
|
||||
* port_cnt is configured as 5, even though it is 4
|
||||
*/
|
||||
.chip_id = KSZ8864_CHIP_ID,
|
||||
.dev_name = "KSZ8864",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 32,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.num_tx_queues = 4,
|
||||
.num_ipms = 4,
|
||||
.ops = &ksz88xx_dev_ops,
|
||||
.phylink_mac_ops = &ksz8830_phylink_mac_ops,
|
||||
.mib_names = ksz88xx_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.regs = ksz8895_regs,
|
||||
.masks = ksz8895_masks,
|
||||
.shifts = ksz8895_shifts,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.internal_phy = {false, true, true, true, false},
|
||||
},
|
||||
|
||||
[KSZ8895] = {
|
||||
.chip_id = KSZ8895_CHIP_ID,
|
||||
.dev_name = "KSZ8895",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 32,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.num_tx_queues = 4,
|
||||
.num_ipms = 4,
|
||||
.ops = &ksz88xx_dev_ops,
|
||||
.phylink_mac_ops = &ksz8830_phylink_mac_ops,
|
||||
.mib_names = ksz88xx_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.regs = ksz8895_regs,
|
||||
.masks = ksz8895_masks,
|
||||
.shifts = ksz8895_shifts,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, true, false},
|
||||
},
|
||||
|
||||
[KSZ9477] = {
|
||||
.chip_id = KSZ9477_CHIP_ID,
|
||||
.dev_name = "KSZ9477",
|
||||
@ -2937,9 +3047,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
|
||||
struct ksz_device *dev = ds->priv;
|
||||
enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE;
|
||||
|
||||
if (dev->chip_id == KSZ8795_CHIP_ID ||
|
||||
dev->chip_id == KSZ8794_CHIP_ID ||
|
||||
dev->chip_id == KSZ8765_CHIP_ID)
|
||||
if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev))
|
||||
proto = DSA_TAG_PROTO_KSZ8795;
|
||||
|
||||
if (dev->chip_id == KSZ8830_CHIP_ID ||
|
||||
@ -3055,6 +3163,8 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
|
||||
case KSZ8765_CHIP_ID:
|
||||
return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
|
||||
case KSZ8830_CHIP_ID:
|
||||
case KSZ8864_CHIP_ID:
|
||||
case KSZ8895_CHIP_ID:
|
||||
return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
|
||||
case KSZ8563_CHIP_ID:
|
||||
case KSZ8567_CHIP_ID:
|
||||
@ -3412,6 +3522,18 @@ static int ksz_switch_detect(struct ksz_device *dev)
|
||||
else
|
||||
return -ENODEV;
|
||||
break;
|
||||
case KSZ8895_FAMILY_ID:
|
||||
if (id2 == KSZ8895_CHIP_ID_95 ||
|
||||
id2 == KSZ8895_CHIP_ID_95R)
|
||||
dev->chip_id = KSZ8895_CHIP_ID;
|
||||
else
|
||||
return -ENODEV;
|
||||
ret = ksz_read8(dev, REG_KSZ8864_CHIP_ID, &id4);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (id4 & SW_KSZ8864)
|
||||
dev->chip_id = KSZ8864_CHIP_ID;
|
||||
break;
|
||||
default:
|
||||
ret = ksz_read32(dev, REG_CHIP_ID0, &id32);
|
||||
if (ret)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Microchip switch driver common header
|
||||
*
|
||||
* Copyright (C) 2017-2019 Microchip Technology Inc.
|
||||
* Copyright (C) 2017-2024 Microchip Technology Inc.
|
||||
*/
|
||||
|
||||
#ifndef __KSZ_COMMON_H
|
||||
@ -201,6 +201,8 @@ enum ksz_model {
|
||||
KSZ8794,
|
||||
KSZ8765,
|
||||
KSZ8830,
|
||||
KSZ8864,
|
||||
KSZ8895,
|
||||
KSZ9477,
|
||||
KSZ9896,
|
||||
KSZ9897,
|
||||
@ -629,9 +631,21 @@ static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
|
||||
return dev->chip_id == KSZ8830_CHIP_ID;
|
||||
}
|
||||
|
||||
static inline bool ksz_is_8895_family(struct ksz_device *dev)
|
||||
{
|
||||
return dev->chip_id == KSZ8895_CHIP_ID ||
|
||||
dev->chip_id == KSZ8864_CHIP_ID;
|
||||
}
|
||||
|
||||
static inline bool is_ksz8(struct ksz_device *dev)
|
||||
{
|
||||
return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev);
|
||||
return ksz_is_ksz87xx(dev) || ksz_is_ksz88x3(dev) ||
|
||||
ksz_is_8895_family(dev);
|
||||
}
|
||||
|
||||
static inline bool is_ksz88xx(struct ksz_device *dev)
|
||||
{
|
||||
return ksz_is_ksz88x3(dev) || ksz_is_8895_family(dev);
|
||||
}
|
||||
|
||||
static inline bool is_ksz9477(struct ksz_device *dev)
|
||||
@ -665,6 +679,7 @@ static inline bool is_lan937x_tx_phy(struct ksz_device *dev, int port)
|
||||
#define SW_FAMILY_ID_M GENMASK(15, 8)
|
||||
#define KSZ87_FAMILY_ID 0x87
|
||||
#define KSZ88_FAMILY_ID 0x88
|
||||
#define KSZ8895_FAMILY_ID 0x95
|
||||
|
||||
#define KSZ8_PORT_STATUS_0 0x08
|
||||
#define KSZ8_PORT_FIBER_MODE BIT(7)
|
||||
@ -673,6 +688,12 @@ static inline bool is_lan937x_tx_phy(struct ksz_device *dev, int port)
|
||||
#define KSZ87_CHIP_ID_94 0x6
|
||||
#define KSZ87_CHIP_ID_95 0x9
|
||||
#define KSZ88_CHIP_ID_63 0x3
|
||||
#define KSZ8895_CHIP_ID_95 0x4
|
||||
#define KSZ8895_CHIP_ID_95R 0x6
|
||||
|
||||
/* KSZ8895 specific register */
|
||||
#define REG_KSZ8864_CHIP_ID 0xFE
|
||||
#define SW_KSZ8864 BIT(7)
|
||||
|
||||
#define SW_REV_ID_M GENMASK(7, 4)
|
||||
|
||||
|
@ -113,7 +113,7 @@ static void ksz_get_default_port_prio_reg(struct ksz_device *dev, int *reg,
|
||||
static void ksz_get_dscp_prio_reg(struct ksz_device *dev, int *reg,
|
||||
int *per_reg, u8 *mask)
|
||||
{
|
||||
if (ksz_is_ksz87xx(dev)) {
|
||||
if (ksz_is_ksz87xx(dev) || ksz_is_8895_family(dev)) {
|
||||
*reg = KSZ8765_REG_TOS_DSCP_CTRL;
|
||||
*per_reg = 4;
|
||||
*mask = GENMASK(1, 0);
|
||||
|
@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Microchip ksz series register access through SPI
|
||||
*
|
||||
* Copyright (C) 2017 Microchip Technology Inc.
|
||||
* Copyright (C) 2017-2024 Microchip Technology Inc.
|
||||
* Tristram Ha <Tristram.Ha@microchip.com>
|
||||
*/
|
||||
|
||||
@ -60,6 +60,9 @@ static int ksz_spi_probe(struct spi_device *spi)
|
||||
chip->chip_id == KSZ8794_CHIP_ID ||
|
||||
chip->chip_id == KSZ8765_CHIP_ID)
|
||||
regmap_config = ksz8795_regmap_config;
|
||||
else if (chip->chip_id == KSZ8895_CHIP_ID ||
|
||||
chip->chip_id == KSZ8864_CHIP_ID)
|
||||
regmap_config = ksz8863_regmap_config;
|
||||
else
|
||||
regmap_config = ksz9477_regmap_config;
|
||||
|
||||
@ -136,10 +139,18 @@ static const struct of_device_id ksz_dt_ids[] = {
|
||||
.compatible = "microchip,ksz8863",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8864",
|
||||
.data = &ksz_switch_chips[KSZ8864]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8873",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8895",
|
||||
.data = &ksz_switch_chips[KSZ8895]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9477",
|
||||
.data = &ksz_switch_chips[KSZ9477]
|
||||
@ -201,7 +212,9 @@ static const struct spi_device_id ksz_spi_ids[] = {
|
||||
{ "ksz8794" },
|
||||
{ "ksz8795" },
|
||||
{ "ksz8863" },
|
||||
{ "ksz8864" },
|
||||
{ "ksz8873" },
|
||||
{ "ksz8895" },
|
||||
{ "ksz9477" },
|
||||
{ "ksz9896" },
|
||||
{ "ksz9897" },
|
||||
|
@ -28,6 +28,8 @@ enum ksz_chip_id {
|
||||
KSZ8794_CHIP_ID = 0x8794,
|
||||
KSZ8765_CHIP_ID = 0x8765,
|
||||
KSZ8830_CHIP_ID = 0x8830,
|
||||
KSZ8864_CHIP_ID = 0x8864,
|
||||
KSZ8895_CHIP_ID = 0x8895,
|
||||
KSZ9477_CHIP_ID = 0x00947700,
|
||||
KSZ9896_CHIP_ID = 0x00989600,
|
||||
KSZ9897_CHIP_ID = 0x00989700,
|
||||
|
Loading…
Reference in New Issue
Block a user