Skip to content

Commit 84c47bf

Browse files
triha2workkuba-moo
authored andcommitted
net: dsa: microchip: Add KSZ8463 switch support to KSZ DSA driver
KSZ8463 switch is a 3-port switch based from KSZ8863. Its major difference from other KSZ SPI switches is its register access is not a simple continual 8-bit transfer with automatic address increase but uses a byte-enable mechanism specifying 8-bit, 16-bit, or 32-bit access. Its registers are also defined in 16-bit format because it shares a design with a MAC controller using 16-bit access. As a result some common register accesses need to be re-arranged. This patch adds the basic structure for using KSZ8463. It cannot use the same regmap table for other KSZ switches as it interprets the 16-bit value as little-endian and its SPI commands are different. KSZ8463 uses a byte-enable mechanism to specify 8-bit, 16-bit, and 32-bit access. The register is first shifted right by 2 then left by 4. Extra 4 bits are added. If the access is 8-bit one of the 4 bits is set. If the access is 16-bit two of the 4 bits are set. If the access is 32-bit all 4 bits are set. The SPI command for read or write is then added. Because of this register transformation separate SPI read and write functions are provided for KSZ8463. KSZ8463's internal PHYs use standard PHY register definitions so there is no need to remap things. However, the hardware has a bug that the high word and low word of the PHY id are swapped. In addition the port registers are arranged differently so KSZ8463 has its own mapping for port registers and PHY registers. Therefore the PORT_CTRL_ADDR macro is replaced with the get_port_addr helper function. Signed-off-by: Tristram Ha <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ba37d55 commit 84c47bf

File tree

7 files changed

+389
-3
lines changed

7 files changed

+389
-3
lines changed

drivers/net/dsa/microchip/ksz8.c

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Microchip KSZ8XXX series switch driver
44
*
55
* It supports the following switches:
6+
* - KSZ8463
67
* - KSZ8863, KSZ8873 aka KSZ88X3
78
* - KSZ8895, KSZ8864 aka KSZ8895 family
89
* - KSZ8794, KSZ8795, KSZ8765 aka KSZ87XX
@@ -41,7 +42,8 @@ static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set)
4142
static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits,
4243
bool set)
4344
{
44-
regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset),
45+
regmap_update_bits(ksz_regmap_8(dev),
46+
dev->dev_ops->get_port_addr(port, offset),
4547
bits, set ? bits : 0);
4648
}
4749

@@ -194,6 +196,7 @@ int ksz8_change_mtu(struct ksz_device *dev, int port, int mtu)
194196
case KSZ8794_CHIP_ID:
195197
case KSZ8765_CHIP_ID:
196198
return ksz8795_change_mtu(dev, frame_size);
199+
case KSZ8463_CHIP_ID:
197200
case KSZ88X3_CHIP_ID:
198201
case KSZ8864_CHIP_ID:
199202
case KSZ8895_CHIP_ID:
@@ -1947,6 +1950,84 @@ u32 ksz8_get_port_addr(int port, int offset)
19471950
return PORT_CTRL_ADDR(port, offset);
19481951
}
19491952

1953+
u32 ksz8463_get_port_addr(int port, int offset)
1954+
{
1955+
return offset + 0x18 * port;
1956+
}
1957+
1958+
static u16 ksz8463_get_phy_addr(u16 phy, u16 reg, u16 offset)
1959+
{
1960+
return offset + reg * 2 + phy * (P2MBCR - P1MBCR);
1961+
}
1962+
1963+
int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
1964+
{
1965+
u16 sw_reg = 0;
1966+
u16 data = 0;
1967+
int ret;
1968+
1969+
if (phy > 1)
1970+
return -ENOSPC;
1971+
switch (reg) {
1972+
case MII_PHYSID1:
1973+
sw_reg = ksz8463_get_phy_addr(phy, 0, PHY1IHR);
1974+
break;
1975+
case MII_PHYSID2:
1976+
sw_reg = ksz8463_get_phy_addr(phy, 0, PHY1ILR);
1977+
break;
1978+
case MII_BMCR:
1979+
case MII_BMSR:
1980+
case MII_ADVERTISE:
1981+
case MII_LPA:
1982+
sw_reg = ksz8463_get_phy_addr(phy, reg, P1MBCR);
1983+
break;
1984+
case MII_TPISTATUS:
1985+
/* This register holds the PHY interrupt status for simulated
1986+
* Micrel KSZ PHY.
1987+
*/
1988+
data = 0x0505;
1989+
break;
1990+
default:
1991+
break;
1992+
}
1993+
if (sw_reg) {
1994+
ret = ksz_read16(dev, sw_reg, &data);
1995+
if (ret)
1996+
return ret;
1997+
}
1998+
*val = data;
1999+
2000+
return 0;
2001+
}
2002+
2003+
int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
2004+
{
2005+
u16 sw_reg = 0;
2006+
int ret;
2007+
2008+
if (phy > 1)
2009+
return -ENOSPC;
2010+
2011+
/* No write to fiber port. */
2012+
if (dev->ports[phy].fiber)
2013+
return 0;
2014+
switch (reg) {
2015+
case MII_BMCR:
2016+
case MII_ADVERTISE:
2017+
sw_reg = ksz8463_get_phy_addr(phy, reg, P1MBCR);
2018+
break;
2019+
default:
2020+
break;
2021+
}
2022+
if (sw_reg) {
2023+
ret = ksz_write16(dev, sw_reg, val);
2024+
if (ret)
2025+
return ret;
2026+
}
2027+
2028+
return 0;
2029+
}
2030+
19502031
int ksz8_switch_init(struct ksz_device *dev)
19512032
{
19522033
dev->cpu_port = fls(dev->info->cpu_ports) - 1;

drivers/net/dsa/microchip/ksz8.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,8 @@ void ksz8_phylink_mac_link_up(struct phylink_config *config,
6363
bool tx_pause, bool rx_pause);
6464
int ksz8_all_queues_split(struct ksz_device *dev, int queues);
6565

66+
u32 ksz8463_get_port_addr(int port, int offset);
67+
int ksz8463_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
68+
int ksz8463_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
69+
6670
#endif

drivers/net/dsa/microchip/ksz8_reg.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,55 @@
729729
#define PHY_POWER_SAVING_ENABLE BIT(2)
730730
#define PHY_REMOTE_LOOPBACK BIT(1)
731731

732+
/* KSZ8463 specific registers. */
733+
#define P1MBCR 0x4C
734+
#define P1MBSR 0x4E
735+
#define PHY1ILR 0x50
736+
#define PHY1IHR 0x52
737+
#define P1ANAR 0x54
738+
#define P1ANLPR 0x56
739+
#define P2MBCR 0x58
740+
#define P2MBSR 0x5A
741+
#define PHY2ILR 0x5C
742+
#define PHY2IHR 0x5E
743+
#define P2ANAR 0x60
744+
#define P2ANLPR 0x62
745+
746+
#define P1CR1 0x6C
747+
#define P1CR2 0x6E
748+
#define P1CR3 0x72
749+
#define P1CR4 0x7E
750+
#define P1SR 0x80
751+
752+
#define KSZ8463_FLUSH_TABLE_CTRL 0xAD
753+
754+
#define KSZ8463_FLUSH_DYN_MAC_TABLE BIT(2)
755+
#define KSZ8463_FLUSH_STA_MAC_TABLE BIT(1)
756+
757+
#define KSZ8463_REG_SW_CTRL_9 0xAE
758+
759+
#define KSZ8463_REG_CFG_CTRL 0xD8
760+
761+
#define PORT_2_COPPER_MODE BIT(7)
762+
#define PORT_1_COPPER_MODE BIT(6)
763+
#define PORT_COPPER_MODE_S 6
764+
765+
#define KSZ8463_REG_SW_RESET 0x126
766+
767+
#define KSZ8463_GLOBAL_SOFTWARE_RESET BIT(0)
768+
769+
#define KSZ8463_PTP_CLK_CTRL 0x600
770+
771+
#define PTP_CLK_ENABLE BIT(1)
772+
773+
#define KSZ8463_PTP_MSG_CONF1 0x620
774+
775+
#define PTP_ENABLE BIT(6)
776+
777+
#define KSZ8463_REG_DSP_CTRL_6 0x734
778+
779+
#define COPPER_RECEIVE_ADJUSTMENT BIT(13)
780+
732781
/* Chip resource */
733782

734783
#define PRIO_QUEUES 4

drivers/net/dsa/microchip/ksz_common.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,38 @@ static const struct phylink_mac_ops ksz8_phylink_mac_ops = {
331331
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
332332
};
333333

334+
static const struct ksz_dev_ops ksz8463_dev_ops = {
335+
.setup = ksz8_setup,
336+
.get_port_addr = ksz8463_get_port_addr,
337+
.cfg_port_member = ksz8_cfg_port_member,
338+
.flush_dyn_mac_table = ksz8_flush_dyn_mac_table,
339+
.port_setup = ksz8_port_setup,
340+
.r_phy = ksz8463_r_phy,
341+
.w_phy = ksz8463_w_phy,
342+
.r_mib_cnt = ksz8_r_mib_cnt,
343+
.r_mib_pkt = ksz8_r_mib_pkt,
344+
.r_mib_stat64 = ksz88xx_r_mib_stats64,
345+
.freeze_mib = ksz8_freeze_mib,
346+
.port_init_cnt = ksz8_port_init_cnt,
347+
.fdb_dump = ksz8_fdb_dump,
348+
.fdb_add = ksz8_fdb_add,
349+
.fdb_del = ksz8_fdb_del,
350+
.mdb_add = ksz8_mdb_add,
351+
.mdb_del = ksz8_mdb_del,
352+
.vlan_filtering = ksz8_port_vlan_filtering,
353+
.vlan_add = ksz8_port_vlan_add,
354+
.vlan_del = ksz8_port_vlan_del,
355+
.mirror_add = ksz8_port_mirror_add,
356+
.mirror_del = ksz8_port_mirror_del,
357+
.get_caps = ksz8_get_caps,
358+
.config_cpu_port = ksz8_config_cpu_port,
359+
.enable_stp_addr = ksz8_enable_stp_addr,
360+
.reset = ksz8_reset_switch,
361+
.init = ksz8_switch_init,
362+
.exit = ksz8_switch_exit,
363+
.change_mtu = ksz8_change_mtu,
364+
};
365+
334366
static const struct ksz_dev_ops ksz88xx_dev_ops = {
335367
.setup = ksz8_setup,
336368
.get_port_addr = ksz8_get_port_addr,
@@ -517,6 +549,60 @@ static const struct ksz_dev_ops lan937x_dev_ops = {
517549
.exit = lan937x_switch_exit,
518550
};
519551

552+
static const u16 ksz8463_regs[] = {
553+
[REG_SW_MAC_ADDR] = 0x10,
554+
[REG_IND_CTRL_0] = 0x30,
555+
[REG_IND_DATA_8] = 0x26,
556+
[REG_IND_DATA_CHECK] = 0x26,
557+
[REG_IND_DATA_HI] = 0x28,
558+
[REG_IND_DATA_LO] = 0x2C,
559+
[REG_IND_MIB_CHECK] = 0x2F,
560+
[P_FORCE_CTRL] = 0x0C,
561+
[P_LINK_STATUS] = 0x0E,
562+
[P_LOCAL_CTRL] = 0x0C,
563+
[P_NEG_RESTART_CTRL] = 0x0D,
564+
[P_REMOTE_STATUS] = 0x0E,
565+
[P_SPEED_STATUS] = 0x0F,
566+
[S_TAIL_TAG_CTRL] = 0xAD,
567+
[P_STP_CTRL] = 0x6F,
568+
[S_START_CTRL] = 0x01,
569+
[S_BROADCAST_CTRL] = 0x06,
570+
[S_MULTICAST_CTRL] = 0x04,
571+
};
572+
573+
static const u32 ksz8463_masks[] = {
574+
[PORT_802_1P_REMAPPING] = BIT(3),
575+
[SW_TAIL_TAG_ENABLE] = BIT(0),
576+
[MIB_COUNTER_OVERFLOW] = BIT(7),
577+
[MIB_COUNTER_VALID] = BIT(6),
578+
[VLAN_TABLE_FID] = GENMASK(15, 12),
579+
[VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16),
580+
[VLAN_TABLE_VALID] = BIT(19),
581+
[STATIC_MAC_TABLE_VALID] = BIT(19),
582+
[STATIC_MAC_TABLE_USE_FID] = BIT(21),
583+
[STATIC_MAC_TABLE_FID] = GENMASK(25, 22),
584+
[STATIC_MAC_TABLE_OVERRIDE] = BIT(20),
585+
[STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16),
586+
[DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(1, 0),
587+
[DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(2),
588+
[DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7),
589+
[DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 24),
590+
[DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16),
591+
[DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20),
592+
[DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22),
593+
};
594+
595+
static u8 ksz8463_shifts[] = {
596+
[VLAN_TABLE_MEMBERSHIP_S] = 16,
597+
[STATIC_MAC_FWD_PORTS] = 16,
598+
[STATIC_MAC_FID] = 22,
599+
[DYNAMIC_MAC_ENTRIES_H] = 8,
600+
[DYNAMIC_MAC_ENTRIES] = 24,
601+
[DYNAMIC_MAC_FID] = 16,
602+
[DYNAMIC_MAC_TIMESTAMP] = 22,
603+
[DYNAMIC_MAC_SRC_PORT] = 20,
604+
};
605+
520606
static const u16 ksz8795_regs[] = {
521607
[REG_SW_MAC_ADDR] = 0x68,
522608
[REG_IND_CTRL_0] = 0x6E,
@@ -1387,6 +1473,29 @@ static const struct regmap_access_table ksz8873_register_set = {
13871473
};
13881474

13891475
const struct ksz_chip_data ksz_switch_chips[] = {
1476+
[KSZ8463] = {
1477+
.chip_id = KSZ8463_CHIP_ID,
1478+
.dev_name = "KSZ8463",
1479+
.num_vlans = 16,
1480+
.num_alus = 0,
1481+
.num_statics = 8,
1482+
.cpu_ports = 0x4, /* can be configured as cpu port */
1483+
.port_cnt = 3,
1484+
.num_tx_queues = 4,
1485+
.num_ipms = 4,
1486+
.ops = &ksz8463_dev_ops,
1487+
.phylink_mac_ops = &ksz88x3_phylink_mac_ops,
1488+
.mib_names = ksz88xx_mib_names,
1489+
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
1490+
.reg_mib_cnt = MIB_COUNTER_NUM,
1491+
.regs = ksz8463_regs,
1492+
.masks = ksz8463_masks,
1493+
.shifts = ksz8463_shifts,
1494+
.supports_mii = {false, false, true},
1495+
.supports_rmii = {false, false, true},
1496+
.internal_phy = {true, true, false},
1497+
},
1498+
13901499
[KSZ8563] = {
13911500
.chip_id = KSZ8563_CHIP_ID,
13921501
.dev_name = "KSZ8563",
@@ -3400,6 +3509,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
34003509
proto = DSA_TAG_PROTO_KSZ8795;
34013510

34023511
if (dev->chip_id == KSZ88X3_CHIP_ID ||
3512+
dev->chip_id == KSZ8463_CHIP_ID ||
34033513
dev->chip_id == KSZ8563_CHIP_ID ||
34043514
dev->chip_id == KSZ9893_CHIP_ID ||
34053515
dev->chip_id == KSZ9563_CHIP_ID)
@@ -3512,6 +3622,7 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
35123622
case KSZ8794_CHIP_ID:
35133623
case KSZ8765_CHIP_ID:
35143624
return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN;
3625+
case KSZ8463_CHIP_ID:
35153626
case KSZ88X3_CHIP_ID:
35163627
case KSZ8864_CHIP_ID:
35173628
case KSZ8895_CHIP_ID:
@@ -3866,6 +3977,9 @@ static int ksz_switch_detect(struct ksz_device *dev)
38663977
id2 = FIELD_GET(SW_CHIP_ID_M, id16);
38673978

38683979
switch (id1) {
3980+
case KSZ84_FAMILY_ID:
3981+
dev->chip_id = KSZ8463_CHIP_ID;
3982+
break;
38693983
case KSZ87_FAMILY_ID:
38703984
if (id2 == KSZ87_CHIP_ID_95) {
38713985
u8 val;

0 commit comments

Comments
 (0)