Skip to content

Commit 8c29beb

Browse files
triha2workdavem330
authored andcommitted
net: dsa: microchip: add KSZ9893 switch support
Add KSZ9893 switch support in KSZ9477 driver. This switch is similar to KSZ9477 except the ingress tail tag has 1 byte instead of 2 bytes, so KSZ9893 tagging will be used. The XMII register that governs how the host port communicates with the MAC also has different register definitions. Signed-off-by: Tristram Ha <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 88b573a commit 8c29beb

File tree

3 files changed

+235
-15
lines changed

3 files changed

+235
-15
lines changed

drivers/net/dsa/microchip/ksz9477.c

Lines changed: 229 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
#include "ksz9477_reg.h"
1919
#include "ksz_common.h"
2020

21+
/* Used with variable features to indicate capabilities. */
22+
#define GBIT_SUPPORT BIT(0)
23+
#define NEW_XMII BIT(1)
24+
#define IS_9893 BIT(2)
25+
2126
static const struct {
2227
int index;
2328
char string[ETH_GSTRING_LEN];
@@ -328,7 +333,12 @@ static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
328333
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
329334
int port)
330335
{
331-
return DSA_TAG_PROTO_KSZ9477;
336+
enum dsa_tag_protocol proto = DSA_TAG_PROTO_KSZ9477;
337+
struct ksz_device *dev = ds->priv;
338+
339+
if (dev->features & IS_9893)
340+
proto = DSA_TAG_PROTO_KSZ9893;
341+
return proto;
332342
}
333343

334344
static int ksz9477_phy_read16(struct dsa_switch *ds, int addr, int reg)
@@ -389,6 +399,10 @@ static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
389399
/* No real PHY after this. */
390400
if (addr >= dev->phy_port_cnt)
391401
return 0;
402+
403+
/* No gigabit support. Do not write to this register. */
404+
if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
405+
return 0;
392406
ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
393407

394408
return 0;
@@ -998,11 +1012,156 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
9981012
static void ksz9477_phy_setup(struct ksz_device *dev, int port,
9991013
struct phy_device *phy)
10001014
{
1001-
if (port < dev->phy_port_cnt) {
1002-
/* The MAC actually cannot run in 1000 half-duplex mode. */
1015+
/* Only apply to port with PHY. */
1016+
if (port >= dev->phy_port_cnt)
1017+
return;
1018+
1019+
/* The MAC actually cannot run in 1000 half-duplex mode. */
1020+
phy_remove_link_mode(phy,
1021+
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
1022+
1023+
/* PHY does not support gigabit. */
1024+
if (!(dev->features & GBIT_SUPPORT))
10031025
phy_remove_link_mode(phy,
1004-
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
1026+
ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
1027+
}
1028+
1029+
static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
1030+
{
1031+
bool gbit;
1032+
1033+
if (dev->features & NEW_XMII)
1034+
gbit = !(data & PORT_MII_NOT_1GBIT);
1035+
else
1036+
gbit = !!(data & PORT_MII_1000MBIT_S1);
1037+
return gbit;
1038+
}
1039+
1040+
static void ksz9477_set_gbit(struct ksz_device *dev, bool gbit, u8 *data)
1041+
{
1042+
if (dev->features & NEW_XMII) {
1043+
if (gbit)
1044+
*data &= ~PORT_MII_NOT_1GBIT;
1045+
else
1046+
*data |= PORT_MII_NOT_1GBIT;
1047+
} else {
1048+
if (gbit)
1049+
*data |= PORT_MII_1000MBIT_S1;
1050+
else
1051+
*data &= ~PORT_MII_1000MBIT_S1;
1052+
}
1053+
}
1054+
1055+
static int ksz9477_get_xmii(struct ksz_device *dev, u8 data)
1056+
{
1057+
int mode;
1058+
1059+
if (dev->features & NEW_XMII) {
1060+
switch (data & PORT_MII_SEL_M) {
1061+
case PORT_MII_SEL:
1062+
mode = 0;
1063+
break;
1064+
case PORT_RMII_SEL:
1065+
mode = 1;
1066+
break;
1067+
case PORT_GMII_SEL:
1068+
mode = 2;
1069+
break;
1070+
default:
1071+
mode = 3;
1072+
}
1073+
} else {
1074+
switch (data & PORT_MII_SEL_M) {
1075+
case PORT_MII_SEL_S1:
1076+
mode = 0;
1077+
break;
1078+
case PORT_RMII_SEL_S1:
1079+
mode = 1;
1080+
break;
1081+
case PORT_GMII_SEL_S1:
1082+
mode = 2;
1083+
break;
1084+
default:
1085+
mode = 3;
1086+
}
1087+
}
1088+
return mode;
1089+
}
1090+
1091+
static void ksz9477_set_xmii(struct ksz_device *dev, int mode, u8 *data)
1092+
{
1093+
u8 xmii;
1094+
1095+
if (dev->features & NEW_XMII) {
1096+
switch (mode) {
1097+
case 0:
1098+
xmii = PORT_MII_SEL;
1099+
break;
1100+
case 1:
1101+
xmii = PORT_RMII_SEL;
1102+
break;
1103+
case 2:
1104+
xmii = PORT_GMII_SEL;
1105+
break;
1106+
default:
1107+
xmii = PORT_RGMII_SEL;
1108+
break;
1109+
}
1110+
} else {
1111+
switch (mode) {
1112+
case 0:
1113+
xmii = PORT_MII_SEL_S1;
1114+
break;
1115+
case 1:
1116+
xmii = PORT_RMII_SEL_S1;
1117+
break;
1118+
case 2:
1119+
xmii = PORT_GMII_SEL_S1;
1120+
break;
1121+
default:
1122+
xmii = PORT_RGMII_SEL_S1;
1123+
break;
1124+
}
1125+
}
1126+
*data &= ~PORT_MII_SEL_M;
1127+
*data |= xmii;
1128+
}
1129+
1130+
static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
1131+
{
1132+
phy_interface_t interface;
1133+
bool gbit;
1134+
int mode;
1135+
u8 data8;
1136+
1137+
if (port < dev->phy_port_cnt)
1138+
return PHY_INTERFACE_MODE_NA;
1139+
ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
1140+
gbit = ksz9477_get_gbit(dev, data8);
1141+
mode = ksz9477_get_xmii(dev, data8);
1142+
switch (mode) {
1143+
case 2:
1144+
interface = PHY_INTERFACE_MODE_GMII;
1145+
if (gbit)
1146+
break;
1147+
case 0:
1148+
interface = PHY_INTERFACE_MODE_MII;
1149+
break;
1150+
case 1:
1151+
interface = PHY_INTERFACE_MODE_RMII;
1152+
break;
1153+
default:
1154+
interface = PHY_INTERFACE_MODE_RGMII;
1155+
if (data8 & PORT_RGMII_ID_EG_ENABLE)
1156+
interface = PHY_INTERFACE_MODE_RGMII_TXID;
1157+
if (data8 & PORT_RGMII_ID_IG_ENABLE) {
1158+
interface = PHY_INTERFACE_MODE_RGMII_RXID;
1159+
if (data8 & PORT_RGMII_ID_EG_ENABLE)
1160+
interface = PHY_INTERFACE_MODE_RGMII_ID;
1161+
}
1162+
break;
10051163
}
1164+
return interface;
10061165
}
10071166

10081167
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
@@ -1051,24 +1210,25 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
10511210

10521211
/* configure MAC to 1G & RGMII mode */
10531212
ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
1054-
data8 &= ~PORT_MII_NOT_1GBIT;
1055-
data8 &= ~PORT_MII_SEL_M;
10561213
switch (dev->interface) {
10571214
case PHY_INTERFACE_MODE_MII:
1058-
data8 |= PORT_MII_NOT_1GBIT;
1059-
data8 |= PORT_MII_SEL;
1215+
ksz9477_set_xmii(dev, 0, &data8);
1216+
ksz9477_set_gbit(dev, false, &data8);
10601217
p->phydev.speed = SPEED_100;
10611218
break;
10621219
case PHY_INTERFACE_MODE_RMII:
1063-
data8 |= PORT_MII_NOT_1GBIT;
1064-
data8 |= PORT_RMII_SEL;
1220+
ksz9477_set_xmii(dev, 1, &data8);
1221+
ksz9477_set_gbit(dev, false, &data8);
10651222
p->phydev.speed = SPEED_100;
10661223
break;
10671224
case PHY_INTERFACE_MODE_GMII:
1068-
data8 |= PORT_GMII_SEL;
1225+
ksz9477_set_xmii(dev, 2, &data8);
1226+
ksz9477_set_gbit(dev, true, &data8);
10691227
p->phydev.speed = SPEED_1000;
10701228
break;
10711229
default:
1230+
ksz9477_set_xmii(dev, 3, &data8);
1231+
ksz9477_set_gbit(dev, true, &data8);
10721232
data8 &= ~PORT_RGMII_ID_IG_ENABLE;
10731233
data8 &= ~PORT_RGMII_ID_EG_ENABLE;
10741234
if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
@@ -1077,7 +1237,6 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
10771237
if (dev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
10781238
dev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
10791239
data8 |= PORT_RGMII_ID_EG_ENABLE;
1080-
data8 |= PORT_RGMII_SEL;
10811240
p->phydev.speed = SPEED_1000;
10821241
break;
10831242
}
@@ -1115,10 +1274,25 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
11151274

11161275
for (i = 0; i < dev->port_cnt; i++) {
11171276
if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
1277+
phy_interface_t interface;
1278+
11181279
dev->cpu_port = i;
11191280
dev->host_mask = (1 << dev->cpu_port);
11201281
dev->port_mask |= dev->host_mask;
11211282

1283+
/* Read from XMII register to determine host port
1284+
* interface. If set specifically in device tree
1285+
* note the difference to help debugging.
1286+
*/
1287+
interface = ksz9477_get_interface(dev, i);
1288+
if (!dev->interface)
1289+
dev->interface = interface;
1290+
if (interface && interface != dev->interface)
1291+
dev_info(dev->dev,
1292+
"use %s instead of %s\n",
1293+
phy_modes(dev->interface),
1294+
phy_modes(interface));
1295+
11221296
/* enable cpu port */
11231297
ksz9477_port_setup(dev, i, true);
11241298
p = &dev->ports[dev->cpu_port];
@@ -1172,6 +1346,9 @@ static int ksz9477_setup(struct dsa_switch *ds)
11721346
ksz9477_cfg32(dev, REG_SW_QM_CTRL__4, UNICAST_VLAN_BOUNDARY,
11731347
true);
11741348

1349+
/* Do not work correctly with tail tagging. */
1350+
ksz_cfg(dev, REG_SW_MAC_CTRL_0, SW_CHECK_LENGTH, false);
1351+
11751352
/* accept packet up to 2000bytes */
11761353
ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_LEGAL_PACKET_DISABLE, true);
11771354

@@ -1230,6 +1407,8 @@ static u32 ksz9477_get_port_addr(int port, int offset)
12301407
static int ksz9477_switch_detect(struct ksz_device *dev)
12311408
{
12321409
u8 data8;
1410+
u8 id_hi;
1411+
u8 id_lo;
12331412
u32 id32;
12341413
int ret;
12351414

@@ -1245,13 +1424,42 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
12451424

12461425
/* read chip id */
12471426
ret = ksz_read32(dev, REG_CHIP_ID0__1, &id32);
1427+
if (ret)
1428+
return ret;
1429+
ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
12481430
if (ret)
12491431
return ret;
12501432

12511433
/* Number of ports can be reduced depending on chip. */
12521434
dev->mib_port_cnt = TOTAL_PORT_NUM;
12531435
dev->phy_port_cnt = 5;
12541436

1437+
/* Default capability is gigabit capable. */
1438+
dev->features = GBIT_SUPPORT;
1439+
1440+
id_hi = (u8)(id32 >> 16);
1441+
id_lo = (u8)(id32 >> 8);
1442+
if ((id_lo & 0xf) == 3) {
1443+
/* Chip is from KSZ9893 design. */
1444+
dev->features |= IS_9893;
1445+
1446+
/* Chip does not support gigabit. */
1447+
if (data8 & SW_QW_ABLE)
1448+
dev->features &= ~GBIT_SUPPORT;
1449+
dev->mib_port_cnt = 3;
1450+
dev->phy_port_cnt = 2;
1451+
} else {
1452+
/* Chip uses new XMII register definitions. */
1453+
dev->features |= NEW_XMII;
1454+
1455+
/* Chip does not support gigabit. */
1456+
if (!(data8 & SW_GIGABIT_ABLE))
1457+
dev->features &= ~GBIT_SUPPORT;
1458+
}
1459+
1460+
/* Change chip id to known ones so it can be matched against them. */
1461+
id32 = (id_hi << 16) | (id_lo << 8);
1462+
12551463
dev->chip_id = id32;
12561464

12571465
return 0;
@@ -1286,6 +1494,15 @@ static const struct ksz_chip_data ksz9477_switch_chips[] = {
12861494
.cpu_ports = 0x7F, /* can be configured as cpu port */
12871495
.port_cnt = 7, /* total physical port count */
12881496
},
1497+
{
1498+
.chip_id = 0x00989300,
1499+
.dev_name = "KSZ9893",
1500+
.num_vlans = 4096,
1501+
.num_alus = 4096,
1502+
.num_statics = 16,
1503+
.cpu_ports = 0x07, /* can be configured as cpu port */
1504+
.port_cnt = 3, /* total port count */
1505+
},
12891506
};
12901507

12911508
static int ksz9477_switch_init(struct ksz_device *dev)
@@ -1333,7 +1550,6 @@ static int ksz9477_switch_init(struct ksz_device *dev)
13331550
if (!dev->ports[i].mib.counters)
13341551
return -ENOMEM;
13351552
}
1336-
dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
13371553

13381554
return 0;
13391555
}

drivers/net/dsa/microchip/ksz9477_spi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Microchip KSZ9477 series register access through SPI
44
*
5-
* Copyright (C) 2017-2018 Microchip Technology Inc.
5+
* Copyright (C) 2017-2019 Microchip Technology Inc.
66
*/
77

88
#include <asm/unaligned.h>
@@ -155,6 +155,8 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)
155155
static const struct of_device_id ksz9477_dt_ids[] = {
156156
{ .compatible = "microchip,ksz9477" },
157157
{ .compatible = "microchip,ksz9897" },
158+
{ .compatible = "microchip,ksz9893" },
159+
{ .compatible = "microchip,ksz9563" },
158160
{},
159161
};
160162
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);

drivers/net/dsa/microchip/ksz_common.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,9 @@ int ksz_switch_register(struct ksz_device *dev,
453453
if (ret)
454454
return ret;
455455

456-
dev->interface = PHY_INTERFACE_MODE_MII;
456+
/* Host port interface will be self detected, or specifically set in
457+
* device tree.
458+
*/
457459
if (dev->dev->of_node) {
458460
ret = of_get_phy_mode(dev->dev->of_node);
459461
if (ret >= 0)

0 commit comments

Comments
 (0)