mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
Merge branch 'dsa-microchip-ksz_switch-refactor'
Arun Ramadoss says: ==================== net: dsa: microchip: refactor the ksz switch init function During the ksz_switch_register function, it calls the individual switches init functions (ksz8795.c and ksz9477.c). Both these functions have few things in common like, copying the chip specific data to struct ksz_dev, allocating ksz_port memory and mib_names memory & cnt. And to add the new LAN937x series switch, these allocations has to be replicated. Based on the review feedback of LAN937x part support patch, refactored the switch init function to move allocations to switch register. Link:https://patchwork.kernel.org/project/netdevbpf/patch/20220504151755.11737-8-arun.ramadoss@microchip.com/ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e8bacf408f
@ -126,86 +126,6 @@ static u8 ksz8863_shifts[] = {
|
||||
[DYNAMIC_MAC_SRC_PORT] = 20,
|
||||
};
|
||||
|
||||
struct mib_names {
|
||||
char string[ETH_GSTRING_LEN];
|
||||
};
|
||||
|
||||
static const struct mib_names ksz87xx_mib_names[] = {
|
||||
{ "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" },
|
||||
{ "rx_1523_2000" },
|
||||
{ "rx_2001" },
|
||||
{ "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_total" },
|
||||
{ "tx_total" },
|
||||
{ "rx_discards" },
|
||||
{ "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;
|
||||
@ -306,7 +226,7 @@ static void ksz8_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt)
|
||||
masks = ksz8->masks;
|
||||
regs = ksz8->regs;
|
||||
|
||||
ctrl_addr = addr + dev->reg_mib_cnt * port;
|
||||
ctrl_addr = addr + dev->info->reg_mib_cnt * port;
|
||||
ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ);
|
||||
|
||||
mutex_lock(&dev->alu_mutex);
|
||||
@ -343,7 +263,7 @@ static void ksz8795_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
masks = ksz8->masks;
|
||||
regs = ksz8->regs;
|
||||
|
||||
addr -= dev->reg_mib_cnt;
|
||||
addr -= dev->info->reg_mib_cnt;
|
||||
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);
|
||||
@ -392,7 +312,7 @@ static void ksz8863_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
u32 data;
|
||||
u32 cur;
|
||||
|
||||
addr -= dev->reg_mib_cnt;
|
||||
addr -= dev->info->reg_mib_cnt;
|
||||
ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 :
|
||||
KSZ8863_MIB_PACKET_DROPPED_RX_0;
|
||||
ctrl_addr += port;
|
||||
@ -453,23 +373,21 @@ static void ksz8_port_init_cnt(struct ksz_device *dev, int port)
|
||||
mib->cnt_ptr = 0;
|
||||
|
||||
/* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
|
||||
while (mib->cnt_ptr < dev->reg_mib_cnt) {
|
||||
while (mib->cnt_ptr < dev->info->reg_mib_cnt) {
|
||||
dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
|
||||
&mib->counters[mib->cnt_ptr]);
|
||||
++mib->cnt_ptr;
|
||||
}
|
||||
|
||||
/* last one in storage */
|
||||
dropped = &mib->counters[dev->mib_cnt];
|
||||
dropped = &mib->counters[dev->info->mib_cnt];
|
||||
|
||||
/* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
|
||||
while (mib->cnt_ptr < dev->mib_cnt) {
|
||||
while (mib->cnt_ptr < dev->info->mib_cnt) {
|
||||
dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
|
||||
dropped, &mib->counters[mib->cnt_ptr]);
|
||||
++mib->cnt_ptr;
|
||||
}
|
||||
mib->cnt_ptr = 0;
|
||||
memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
|
||||
}
|
||||
|
||||
static void ksz8_r_table(struct ksz_device *dev, int table, u16 addr, u64 *data)
|
||||
@ -1003,18 +921,6 @@ static u32 ksz8_sw_get_phy_flags(struct dsa_switch *ds, int port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ksz8_get_strings(struct dsa_switch *ds, int port,
|
||||
u32 stringset, uint8_t *buf)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->mib_cnt; i++) {
|
||||
memcpy(buf + i * ETH_GSTRING_LEN,
|
||||
dev->mib_names[i].string, ETH_GSTRING_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
|
||||
{
|
||||
u8 data;
|
||||
@ -1036,13 +942,13 @@ static void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
int first, index, cnt;
|
||||
struct ksz_port *p;
|
||||
|
||||
if ((uint)port < dev->port_cnt) {
|
||||
if ((uint)port < dev->info->port_cnt) {
|
||||
first = port;
|
||||
cnt = port + 1;
|
||||
} else {
|
||||
/* Flush all ports. */
|
||||
first = 0;
|
||||
cnt = dev->port_cnt;
|
||||
cnt = dev->info->port_cnt;
|
||||
}
|
||||
for (index = first; index < cnt; index++) {
|
||||
p = &dev->ports[index];
|
||||
@ -1118,7 +1024,7 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
|
||||
* Remove Tag flag to be changed, unless there are no
|
||||
* other VLANs currently configured.
|
||||
*/
|
||||
for (vid = 1; vid < dev->num_vlans; ++vid) {
|
||||
for (vid = 1; vid < dev->info->num_vlans; ++vid) {
|
||||
/* Skip the VID we are going to add or reconfigure */
|
||||
if (vid == vlan->vid)
|
||||
continue;
|
||||
@ -1389,7 +1295,7 @@ static int ksz8_handle_global_errata(struct dsa_switch *ds)
|
||||
* KSZ879x/KSZ877x/KSZ876x and some EEE link partners may result in
|
||||
* the link dropping.
|
||||
*/
|
||||
if (dev->ksz87xx_eee_link_erratum)
|
||||
if (dev->info->ksz87xx_eee_link_erratum)
|
||||
ret = ksz8_ind_write8(dev, TABLE_EEE, REG_IND_EEE_GLOB2_HI, 0);
|
||||
|
||||
return ret;
|
||||
@ -1402,7 +1308,7 @@ static int ksz8_setup(struct dsa_switch *ds)
|
||||
int i, ret = 0;
|
||||
|
||||
dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
|
||||
dev->num_vlans, GFP_KERNEL);
|
||||
dev->info->num_vlans, GFP_KERNEL);
|
||||
if (!dev->vlan_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1446,7 +1352,7 @@ static int ksz8_setup(struct dsa_switch *ds)
|
||||
(BROADCAST_STORM_VALUE *
|
||||
BROADCAST_STORM_PROT_RATE) / 100);
|
||||
|
||||
for (i = 0; i < (dev->num_vlans / 4); i++)
|
||||
for (i = 0; i < (dev->info->num_vlans / 4); i++)
|
||||
ksz8_r_vlan_entries(dev, i);
|
||||
|
||||
/* Setup STP address for STP operation. */
|
||||
@ -1454,7 +1360,7 @@ static int ksz8_setup(struct dsa_switch *ds)
|
||||
ether_addr_copy(alu.mac, eth_stp_addr);
|
||||
alu.is_static = true;
|
||||
alu.is_override = true;
|
||||
alu.port_forward = dev->host_mask;
|
||||
alu.port_forward = dev->info->cpu_ports;
|
||||
|
||||
ksz8_w_sta_mac_table(dev, 0, &alu);
|
||||
|
||||
@ -1470,15 +1376,7 @@ static void ksz8_get_caps(struct dsa_switch *ds, int port,
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (port == dev->cpu_port) {
|
||||
__set_bit(PHY_INTERFACE_MODE_RMII,
|
||||
config->supported_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_MII,
|
||||
config->supported_interfaces);
|
||||
} else {
|
||||
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
config->supported_interfaces);
|
||||
}
|
||||
ksz_phylink_get_caps(ds, port, config);
|
||||
|
||||
config->mac_capabilities = MAC_10 | MAC_100;
|
||||
|
||||
@ -1504,7 +1402,7 @@ static const struct dsa_switch_ops ksz8_switch_ops = {
|
||||
.phylink_get_caps = ksz8_get_caps,
|
||||
.phylink_mac_link_down = ksz_mac_link_down,
|
||||
.port_enable = ksz_enable_port,
|
||||
.get_strings = ksz8_get_strings,
|
||||
.get_strings = ksz_get_strings,
|
||||
.get_ethtool_stats = ksz_get_ethtool_stats,
|
||||
.get_sset_count = ksz_sset_count,
|
||||
.port_bridge_join = ksz_port_bridge_join,
|
||||
@ -1571,140 +1469,26 @@ static int ksz8_switch_detect(struct ksz_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ksz_chip_data {
|
||||
u16 chip_id;
|
||||
const char *dev_name;
|
||||
int num_vlans;
|
||||
int num_alus;
|
||||
int num_statics;
|
||||
int cpu_ports;
|
||||
int port_cnt;
|
||||
bool ksz87xx_eee_link_erratum;
|
||||
};
|
||||
|
||||
static const struct ksz_chip_data ksz8_switch_chips[] = {
|
||||
{
|
||||
.chip_id = 0x8795,
|
||||
.dev_name = "KSZ8795",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* WARNING
|
||||
* =======
|
||||
* KSZ8794 is similar to KSZ8795, except the port map
|
||||
* contains a gap between external and CPU ports, the
|
||||
* port map is NOT continuous. The per-port register
|
||||
* map is shifted accordingly too, i.e. registers at
|
||||
* offset 0x40 are NOT used on KSZ8794 and they ARE
|
||||
* used on KSZ8795 for external port 3.
|
||||
* external cpu
|
||||
* KSZ8794 0,1,2 4
|
||||
* KSZ8795 0,1,2,3 4
|
||||
* KSZ8765 0,1,2,3 4
|
||||
*/
|
||||
.chip_id = 0x8794,
|
||||
.dev_name = "KSZ8794",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 4, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
},
|
||||
{
|
||||
.chip_id = 0x8765,
|
||||
.dev_name = "KSZ8765",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
},
|
||||
{
|
||||
.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)
|
||||
{
|
||||
struct ksz8 *ksz8 = dev->priv;
|
||||
int i;
|
||||
|
||||
dev->ds->ops = &ksz8_switch_ops;
|
||||
|
||||
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;
|
||||
dev->num_vlans = chip->num_vlans;
|
||||
dev->num_alus = chip->num_alus;
|
||||
dev->num_statics = chip->num_statics;
|
||||
dev->port_cnt = fls(chip->cpu_ports);
|
||||
dev->cpu_port = fls(chip->cpu_ports) - 1;
|
||||
dev->phy_port_cnt = dev->port_cnt - 1;
|
||||
dev->cpu_ports = chip->cpu_ports;
|
||||
dev->host_mask = chip->cpu_ports;
|
||||
dev->port_mask = (BIT(dev->phy_port_cnt) - 1) |
|
||||
chip->cpu_ports;
|
||||
dev->ksz87xx_eee_link_erratum =
|
||||
chip->ksz87xx_eee_link_erratum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* no switch found */
|
||||
if (!dev->cpu_ports)
|
||||
return -ENODEV;
|
||||
dev->cpu_port = fls(dev->info->cpu_ports) - 1;
|
||||
dev->phy_port_cnt = dev->info->port_cnt - 1;
|
||||
dev->port_mask = (BIT(dev->phy_port_cnt) - 1) | dev->info->cpu_ports;
|
||||
|
||||
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 = MIB_COUNTER_NUM;
|
||||
|
||||
dev->ports = devm_kzalloc(dev->dev,
|
||||
dev->port_cnt * sizeof(struct ksz_port),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < dev->port_cnt; i++) {
|
||||
mutex_init(&dev->ports[i].mib.cnt_mutex);
|
||||
dev->ports[i].mib.counters =
|
||||
devm_kzalloc(dev->dev,
|
||||
sizeof(u64) *
|
||||
(dev->mib_cnt + 1),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports[i].mib.counters)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* set the real number of ports */
|
||||
dev->ds->num_ports = dev->port_cnt;
|
||||
|
||||
/* We rely on software untagging on the CPU port, so that we
|
||||
* can support both tagged and untagged VLANs
|
||||
*/
|
||||
|
@ -34,6 +34,7 @@ KSZ_REGMAP_TABLE(ksz8863, 16, KSZ8863_SPI_ADDR_SHIFT,
|
||||
static int ksz8795_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
const struct regmap_config *regmap_config;
|
||||
const struct ksz_chip_data *chip;
|
||||
struct device *ddev = &spi->dev;
|
||||
struct regmap_config rc;
|
||||
struct ksz_device *dev;
|
||||
@ -50,10 +51,15 @@ static int ksz8795_spi_probe(struct spi_device *spi)
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
regmap_config = device_get_match_data(ddev);
|
||||
if (!regmap_config)
|
||||
chip = device_get_match_data(ddev);
|
||||
if (!chip)
|
||||
return -EINVAL;
|
||||
|
||||
if (chip->chip_id == KSZ8830_CHIP_ID)
|
||||
regmap_config = ksz8863_regmap_config;
|
||||
else
|
||||
regmap_config = ksz8795_regmap_config;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
|
||||
rc = regmap_config[i];
|
||||
rc.lock_arg = &dev->regmap_mutex;
|
||||
@ -113,11 +119,26 @@ static void ksz8795_spi_shutdown(struct spi_device *spi)
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz8795_dt_ids[] = {
|
||||
{ .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 },
|
||||
{
|
||||
.compatible = "microchip,ksz8765",
|
||||
.data = &ksz_switch_chips[KSZ8765]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8794",
|
||||
.data = &ksz_switch_chips[KSZ8794]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8795",
|
||||
.data = &ksz_switch_chips[KSZ8795]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8863",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8873",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
|
||||
|
@ -206,8 +206,14 @@ static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz8863_dt_ids[] = {
|
||||
{ .compatible = "microchip,ksz8863" },
|
||||
{ .compatible = "microchip,ksz8873" },
|
||||
{
|
||||
.compatible = "microchip,ksz8863",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8873",
|
||||
.data = &ksz_switch_chips[KSZ8830]
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
|
||||
|
@ -23,48 +23,6 @@
|
||||
#define NEW_XMII BIT(1)
|
||||
#define IS_9893 BIT(2)
|
||||
|
||||
static const struct {
|
||||
int index;
|
||||
char string[ETH_GSTRING_LEN];
|
||||
} ksz9477_mib_names[TOTAL_SWITCH_COUNTER_NUM] = {
|
||||
{ 0x00, "rx_hi" },
|
||||
{ 0x01, "rx_undersize" },
|
||||
{ 0x02, "rx_fragments" },
|
||||
{ 0x03, "rx_oversize" },
|
||||
{ 0x04, "rx_jabbers" },
|
||||
{ 0x05, "rx_symbol_err" },
|
||||
{ 0x06, "rx_crc_err" },
|
||||
{ 0x07, "rx_align_err" },
|
||||
{ 0x08, "rx_mac_ctrl" },
|
||||
{ 0x09, "rx_pause" },
|
||||
{ 0x0A, "rx_bcast" },
|
||||
{ 0x0B, "rx_mcast" },
|
||||
{ 0x0C, "rx_ucast" },
|
||||
{ 0x0D, "rx_64_or_less" },
|
||||
{ 0x0E, "rx_65_127" },
|
||||
{ 0x0F, "rx_128_255" },
|
||||
{ 0x10, "rx_256_511" },
|
||||
{ 0x11, "rx_512_1023" },
|
||||
{ 0x12, "rx_1024_1522" },
|
||||
{ 0x13, "rx_1523_2000" },
|
||||
{ 0x14, "rx_2001" },
|
||||
{ 0x15, "tx_hi" },
|
||||
{ 0x16, "tx_late_col" },
|
||||
{ 0x17, "tx_pause" },
|
||||
{ 0x18, "tx_bcast" },
|
||||
{ 0x19, "tx_mcast" },
|
||||
{ 0x1A, "tx_ucast" },
|
||||
{ 0x1B, "tx_deferred" },
|
||||
{ 0x1C, "tx_total_col" },
|
||||
{ 0x1D, "tx_exc_col" },
|
||||
{ 0x1E, "tx_single_col" },
|
||||
{ 0x1F, "tx_mult_col" },
|
||||
{ 0x80, "rx_total" },
|
||||
{ 0x81, "tx_total" },
|
||||
{ 0x82, "rx_discards" },
|
||||
{ 0x83, "tx_discards" },
|
||||
};
|
||||
|
||||
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);
|
||||
@ -100,7 +58,7 @@ static int ksz9477_change_mtu(struct dsa_switch *ds, int port, int mtu)
|
||||
/* Cache the per-port MTU setting */
|
||||
dev->ports[port].max_frame = frame_size;
|
||||
|
||||
for (i = 0; i < dev->port_cnt; i++)
|
||||
for (i = 0; i < dev->info->port_cnt; i++)
|
||||
max_frame = max(max_frame, dev->ports[i].max_frame);
|
||||
|
||||
return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2,
|
||||
@ -287,7 +245,7 @@ static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
|
||||
static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
|
||||
u64 *dropped, u64 *cnt)
|
||||
{
|
||||
addr = ksz9477_mib_names[addr].index;
|
||||
addr = dev->info->mib_names[addr].index;
|
||||
ksz9477_r_mib_cnt(dev, port, addr, cnt);
|
||||
}
|
||||
|
||||
@ -316,9 +274,6 @@ static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
|
||||
ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
|
||||
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
|
||||
mutex_unlock(&mib->cnt_mutex);
|
||||
|
||||
mib->cnt_ptr = 0;
|
||||
memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
|
||||
}
|
||||
|
||||
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
|
||||
@ -400,20 +355,6 @@ static int ksz9477_phy_write16(struct dsa_switch *ds, int addr, int reg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ksz9477_get_strings(struct dsa_switch *ds, int port,
|
||||
u32 stringset, uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (stringset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
|
||||
memcpy(buf + i * ETH_GSTRING_LEN, ksz9477_mib_names[i].string,
|
||||
ETH_GSTRING_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
|
||||
u8 member)
|
||||
{
|
||||
@ -434,7 +375,7 @@ static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
|
||||
SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S,
|
||||
SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S);
|
||||
|
||||
if (port < dev->port_cnt) {
|
||||
if (port < dev->info->port_cnt) {
|
||||
/* flush individual port */
|
||||
ksz_pread8(dev, port, P_STP_CTRL, &data);
|
||||
if (!(data & PORT_LEARN_DISABLE))
|
||||
@ -756,7 +697,7 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
|
||||
mutex_lock(&dev->alu_mutex);
|
||||
|
||||
for (index = 0; index < dev->num_statics; index++) {
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
/* find empty slot first */
|
||||
data = (index << ALU_STAT_INDEX_S) |
|
||||
ALU_STAT_READ | ALU_STAT_START;
|
||||
@ -787,7 +728,7 @@ static int ksz9477_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->num_statics) {
|
||||
if (index == dev->info->num_statics) {
|
||||
err = -ENOSPC;
|
||||
goto exit;
|
||||
}
|
||||
@ -832,7 +773,7 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
|
||||
mutex_lock(&dev->alu_mutex);
|
||||
|
||||
for (index = 0; index < dev->num_statics; index++) {
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
/* find empty slot first */
|
||||
data = (index << ALU_STAT_INDEX_S) |
|
||||
ALU_STAT_READ | ALU_STAT_START;
|
||||
@ -861,7 +802,7 @@ static int ksz9477_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->num_statics)
|
||||
if (index == dev->info->num_statics)
|
||||
goto exit;
|
||||
|
||||
/* clear port */
|
||||
@ -903,7 +844,7 @@ static int ksz9477_port_mirror_add(struct dsa_switch *ds, int port,
|
||||
* Check if any of the port is already set for sniffing
|
||||
* If yes, instruct the user to remove the previous entry & exit
|
||||
*/
|
||||
for (p = 0; p < dev->port_cnt; p++) {
|
||||
for (p = 0; p < dev->info->port_cnt; p++) {
|
||||
/* Skip the current sniffing port */
|
||||
if (p == mirror->to_local_port)
|
||||
continue;
|
||||
@ -946,7 +887,7 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
|
||||
|
||||
|
||||
/* Check if any of the port is still referring to sniffer port */
|
||||
for (p = 0; p < dev->port_cnt; p++) {
|
||||
for (p = 0; p < dev->info->port_cnt; p++) {
|
||||
ksz_pread8(dev, p, P_MIRROR_CTRL, &data);
|
||||
|
||||
if ((data & (PORT_MIRROR_RX | PORT_MIRROR_TX))) {
|
||||
@ -1156,6 +1097,15 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
|
||||
ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
|
||||
}
|
||||
|
||||
static void ksz9477_get_caps(struct dsa_switch *ds, int port,
|
||||
struct phylink_config *config)
|
||||
{
|
||||
ksz_phylink_get_caps(ds, port, config);
|
||||
|
||||
config->mac_capabilities = MAC_10 | MAC_100 | MAC_1000FD |
|
||||
MAC_ASYM_PAUSE | MAC_SYM_PAUSE;
|
||||
}
|
||||
|
||||
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
||||
{
|
||||
struct ksz_port *p = &dev->ports[port];
|
||||
@ -1194,7 +1144,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
|
||||
PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL,
|
||||
false);
|
||||
|
||||
if (dev->phy_errata_9477)
|
||||
if (dev->info->phy_errata_9477)
|
||||
ksz9477_phy_errata_setup(dev, port);
|
||||
} else {
|
||||
/* force flow control */
|
||||
@ -1259,8 +1209,9 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
|
||||
struct ksz_port *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->port_cnt; i++) {
|
||||
if (dsa_is_cpu_port(ds, i) && (dev->cpu_ports & (1 << i))) {
|
||||
for (i = 0; i < dev->info->port_cnt; i++) {
|
||||
if (dsa_is_cpu_port(ds, i) &&
|
||||
(dev->info->cpu_ports & (1 << i))) {
|
||||
phy_interface_t interface;
|
||||
const char *prev_msg;
|
||||
const char *prev_mode;
|
||||
@ -1304,7 +1255,7 @@ static void ksz9477_config_cpu_port(struct dsa_switch *ds)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->port_cnt; i++) {
|
||||
for (i = 0; i < dev->info->port_cnt; i++) {
|
||||
if (i == dev->cpu_port)
|
||||
continue;
|
||||
p = &dev->ports[i];
|
||||
@ -1328,7 +1279,7 @@ static int ksz9477_setup(struct dsa_switch *ds)
|
||||
int ret = 0;
|
||||
|
||||
dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table),
|
||||
dev->num_vlans, GFP_KERNEL);
|
||||
dev->info->num_vlans, GFP_KERNEL);
|
||||
if (!dev->vlan_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -1380,8 +1331,9 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
|
||||
.phy_read = ksz9477_phy_read16,
|
||||
.phy_write = ksz9477_phy_write16,
|
||||
.phylink_mac_link_down = ksz_mac_link_down,
|
||||
.phylink_get_caps = ksz9477_get_caps,
|
||||
.port_enable = ksz_enable_port,
|
||||
.get_strings = ksz9477_get_strings,
|
||||
.get_strings = ksz_get_strings,
|
||||
.get_ethtool_stats = ksz_get_ethtool_stats,
|
||||
.get_sset_count = ksz_sset_count,
|
||||
.port_bridge_join = ksz_port_bridge_join,
|
||||
@ -1470,109 +1422,11 @@ static int ksz9477_switch_detect(struct ksz_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ksz_chip_data {
|
||||
u32 chip_id;
|
||||
const char *dev_name;
|
||||
int num_vlans;
|
||||
int num_alus;
|
||||
int num_statics;
|
||||
int cpu_ports;
|
||||
int port_cnt;
|
||||
bool phy_errata_9477;
|
||||
};
|
||||
|
||||
static const struct ksz_chip_data ksz9477_switch_chips[] = {
|
||||
{
|
||||
.chip_id = 0x00947700,
|
||||
.dev_name = "KSZ9477",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
},
|
||||
{
|
||||
.chip_id = 0x00989700,
|
||||
.dev_name = "KSZ9897",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
},
|
||||
{
|
||||
.chip_id = 0x00989300,
|
||||
.dev_name = "KSZ9893",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x07, /* can be configured as cpu port */
|
||||
.port_cnt = 3, /* total port count */
|
||||
},
|
||||
{
|
||||
.chip_id = 0x00956700,
|
||||
.dev_name = "KSZ9567",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
},
|
||||
};
|
||||
|
||||
static int ksz9477_switch_init(struct ksz_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev->ds->ops = &ksz9477_switch_ops;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ksz9477_switch_chips); i++) {
|
||||
const struct ksz_chip_data *chip = &ksz9477_switch_chips[i];
|
||||
|
||||
if (dev->chip_id == chip->chip_id) {
|
||||
dev->name = chip->dev_name;
|
||||
dev->num_vlans = chip->num_vlans;
|
||||
dev->num_alus = chip->num_alus;
|
||||
dev->num_statics = chip->num_statics;
|
||||
dev->port_cnt = chip->port_cnt;
|
||||
dev->cpu_ports = chip->cpu_ports;
|
||||
dev->phy_errata_9477 = chip->phy_errata_9477;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* no switch found */
|
||||
if (!dev->port_cnt)
|
||||
return -ENODEV;
|
||||
|
||||
dev->port_mask = (1 << dev->port_cnt) - 1;
|
||||
|
||||
dev->reg_mib_cnt = SWITCH_COUNTER_NUM;
|
||||
dev->mib_cnt = TOTAL_SWITCH_COUNTER_NUM;
|
||||
|
||||
dev->ports = devm_kzalloc(dev->dev,
|
||||
dev->port_cnt * sizeof(struct ksz_port),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < dev->port_cnt; i++) {
|
||||
spin_lock_init(&dev->ports[i].mib.stats64_lock);
|
||||
mutex_init(&dev->ports[i].mib.cnt_mutex);
|
||||
dev->ports[i].mib.counters =
|
||||
devm_kzalloc(dev->dev,
|
||||
sizeof(u64) *
|
||||
(TOTAL_SWITCH_COUNTER_NUM + 1),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports[i].mib.counters)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* set the real number of ports */
|
||||
dev->ds->num_ports = dev->port_cnt;
|
||||
dev->port_mask = (1 << dev->info->port_cnt) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -87,12 +87,30 @@ static const struct i2c_device_id ksz9477_i2c_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, ksz9477_i2c_id);
|
||||
|
||||
static const struct of_device_id ksz9477_dt_ids[] = {
|
||||
{ .compatible = "microchip,ksz9477" },
|
||||
{ .compatible = "microchip,ksz9897" },
|
||||
{ .compatible = "microchip,ksz9893" },
|
||||
{ .compatible = "microchip,ksz9563" },
|
||||
{ .compatible = "microchip,ksz9567" },
|
||||
{ .compatible = "microchip,ksz8563" },
|
||||
{
|
||||
.compatible = "microchip,ksz9477",
|
||||
.data = &ksz_switch_chips[KSZ9477]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9897",
|
||||
.data = &ksz_switch_chips[KSZ9897]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9893",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9563",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8563",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9567",
|
||||
.data = &ksz_switch_chips[KSZ9567]
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
|
||||
|
@ -86,12 +86,30 @@ static void ksz9477_spi_shutdown(struct spi_device *spi)
|
||||
}
|
||||
|
||||
static const struct of_device_id ksz9477_dt_ids[] = {
|
||||
{ .compatible = "microchip,ksz9477" },
|
||||
{ .compatible = "microchip,ksz9897" },
|
||||
{ .compatible = "microchip,ksz9893" },
|
||||
{ .compatible = "microchip,ksz9563" },
|
||||
{ .compatible = "microchip,ksz8563" },
|
||||
{ .compatible = "microchip,ksz9567" },
|
||||
{
|
||||
.compatible = "microchip,ksz9477",
|
||||
.data = &ksz_switch_chips[KSZ9477]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9897",
|
||||
.data = &ksz_switch_chips[KSZ9897]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9893",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9563",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz8563",
|
||||
.data = &ksz_switch_chips[KSZ9893]
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,ksz9567",
|
||||
.data = &ksz_switch_chips[KSZ9567]
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
|
||||
|
@ -14,12 +14,15 @@
|
||||
#include <linux/phy.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/switchdev.h>
|
||||
|
||||
#include "ksz_common.h"
|
||||
|
||||
#define MIB_COUNTER_NUM 0x20
|
||||
|
||||
struct ksz_stats_raw {
|
||||
u64 rx_hi;
|
||||
u64 rx_undersize;
|
||||
@ -59,6 +62,403 @@ struct ksz_stats_raw {
|
||||
u64 tx_discards;
|
||||
};
|
||||
|
||||
static const struct ksz_mib_names ksz88xx_mib_names[] = {
|
||||
{ 0x00, "rx" },
|
||||
{ 0x01, "rx_hi" },
|
||||
{ 0x02, "rx_undersize" },
|
||||
{ 0x03, "rx_fragments" },
|
||||
{ 0x04, "rx_oversize" },
|
||||
{ 0x05, "rx_jabbers" },
|
||||
{ 0x06, "rx_symbol_err" },
|
||||
{ 0x07, "rx_crc_err" },
|
||||
{ 0x08, "rx_align_err" },
|
||||
{ 0x09, "rx_mac_ctrl" },
|
||||
{ 0x0a, "rx_pause" },
|
||||
{ 0x0b, "rx_bcast" },
|
||||
{ 0x0c, "rx_mcast" },
|
||||
{ 0x0d, "rx_ucast" },
|
||||
{ 0x0e, "rx_64_or_less" },
|
||||
{ 0x0f, "rx_65_127" },
|
||||
{ 0x10, "rx_128_255" },
|
||||
{ 0x11, "rx_256_511" },
|
||||
{ 0x12, "rx_512_1023" },
|
||||
{ 0x13, "rx_1024_1522" },
|
||||
{ 0x14, "tx" },
|
||||
{ 0x15, "tx_hi" },
|
||||
{ 0x16, "tx_late_col" },
|
||||
{ 0x17, "tx_pause" },
|
||||
{ 0x18, "tx_bcast" },
|
||||
{ 0x19, "tx_mcast" },
|
||||
{ 0x1a, "tx_ucast" },
|
||||
{ 0x1b, "tx_deferred" },
|
||||
{ 0x1c, "tx_total_col" },
|
||||
{ 0x1d, "tx_exc_col" },
|
||||
{ 0x1e, "tx_single_col" },
|
||||
{ 0x1f, "tx_mult_col" },
|
||||
{ 0x100, "rx_discards" },
|
||||
{ 0x101, "tx_discards" },
|
||||
};
|
||||
|
||||
static const struct ksz_mib_names ksz9477_mib_names[] = {
|
||||
{ 0x00, "rx_hi" },
|
||||
{ 0x01, "rx_undersize" },
|
||||
{ 0x02, "rx_fragments" },
|
||||
{ 0x03, "rx_oversize" },
|
||||
{ 0x04, "rx_jabbers" },
|
||||
{ 0x05, "rx_symbol_err" },
|
||||
{ 0x06, "rx_crc_err" },
|
||||
{ 0x07, "rx_align_err" },
|
||||
{ 0x08, "rx_mac_ctrl" },
|
||||
{ 0x09, "rx_pause" },
|
||||
{ 0x0A, "rx_bcast" },
|
||||
{ 0x0B, "rx_mcast" },
|
||||
{ 0x0C, "rx_ucast" },
|
||||
{ 0x0D, "rx_64_or_less" },
|
||||
{ 0x0E, "rx_65_127" },
|
||||
{ 0x0F, "rx_128_255" },
|
||||
{ 0x10, "rx_256_511" },
|
||||
{ 0x11, "rx_512_1023" },
|
||||
{ 0x12, "rx_1024_1522" },
|
||||
{ 0x13, "rx_1523_2000" },
|
||||
{ 0x14, "rx_2001" },
|
||||
{ 0x15, "tx_hi" },
|
||||
{ 0x16, "tx_late_col" },
|
||||
{ 0x17, "tx_pause" },
|
||||
{ 0x18, "tx_bcast" },
|
||||
{ 0x19, "tx_mcast" },
|
||||
{ 0x1A, "tx_ucast" },
|
||||
{ 0x1B, "tx_deferred" },
|
||||
{ 0x1C, "tx_total_col" },
|
||||
{ 0x1D, "tx_exc_col" },
|
||||
{ 0x1E, "tx_single_col" },
|
||||
{ 0x1F, "tx_mult_col" },
|
||||
{ 0x80, "rx_total" },
|
||||
{ 0x81, "tx_total" },
|
||||
{ 0x82, "rx_discards" },
|
||||
{ 0x83, "tx_discards" },
|
||||
};
|
||||
|
||||
const struct ksz_chip_data ksz_switch_chips[] = {
|
||||
[KSZ8795] = {
|
||||
.chip_id = KSZ8795_CHIP_ID,
|
||||
.dev_name = "KSZ8795",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, true, false},
|
||||
},
|
||||
|
||||
[KSZ8794] = {
|
||||
/* WARNING
|
||||
* =======
|
||||
* KSZ8794 is similar to KSZ8795, except the port map
|
||||
* contains a gap between external and CPU ports, the
|
||||
* port map is NOT continuous. The per-port register
|
||||
* map is shifted accordingly too, i.e. registers at
|
||||
* offset 0x40 are NOT used on KSZ8794 and they ARE
|
||||
* used on KSZ8795 for external port 3.
|
||||
* external cpu
|
||||
* KSZ8794 0,1,2 4
|
||||
* KSZ8795 0,1,2,3 4
|
||||
* KSZ8765 0,1,2,3 4
|
||||
* port_cnt is configured as 5, even though it is 4
|
||||
*/
|
||||
.chip_id = KSZ8794_CHIP_ID,
|
||||
.dev_name = "KSZ8794",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, false, false},
|
||||
},
|
||||
|
||||
[KSZ8765] = {
|
||||
.chip_id = KSZ8765_CHIP_ID,
|
||||
.dev_name = "KSZ8765",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 0,
|
||||
.num_statics = 8,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total cpu and user ports */
|
||||
.ksz87xx_eee_link_erratum = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, true, false},
|
||||
},
|
||||
|
||||
[KSZ8830] = {
|
||||
.chip_id = KSZ8830_CHIP_ID,
|
||||
.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,
|
||||
.mib_names = ksz88xx_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz88xx_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, true},
|
||||
.supports_rmii = {false, false, true},
|
||||
.internal_phy = {true, true, false},
|
||||
},
|
||||
|
||||
[KSZ9477] = {
|
||||
.chip_id = KSZ9477_CHIP_ID,
|
||||
.dev_name = "KSZ9477",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
false, true, false},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
false, true, false},
|
||||
.internal_phy = {true, true, true, true,
|
||||
true, false, false},
|
||||
},
|
||||
|
||||
[KSZ9897] = {
|
||||
.chip_id = KSZ9897_CHIP_ID,
|
||||
.dev_name = "KSZ9897",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.internal_phy = {true, true, true, true,
|
||||
true, false, false},
|
||||
},
|
||||
|
||||
[KSZ9893] = {
|
||||
.chip_id = KSZ9893_CHIP_ID,
|
||||
.dev_name = "KSZ9893",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x07, /* can be configured as cpu port */
|
||||
.port_cnt = 3, /* total port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, true},
|
||||
.supports_rmii = {false, false, true},
|
||||
.supports_rgmii = {false, false, true},
|
||||
.internal_phy = {true, true, false},
|
||||
},
|
||||
|
||||
[KSZ9567] = {
|
||||
.chip_id = KSZ9567_CHIP_ID,
|
||||
.dev_name = "KSZ9567",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 4096,
|
||||
.num_statics = 16,
|
||||
.cpu_ports = 0x7F, /* can be configured as cpu port */
|
||||
.port_cnt = 7, /* total physical port count */
|
||||
.phy_errata_9477 = true,
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
false, true, true},
|
||||
.internal_phy = {true, true, true, true,
|
||||
true, false, false},
|
||||
},
|
||||
|
||||
[LAN9370] = {
|
||||
.chip_id = LAN9370_CHIP_ID,
|
||||
.dev_name = "LAN9370",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 1024,
|
||||
.num_statics = 256,
|
||||
.cpu_ports = 0x10, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total physical port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false, true},
|
||||
.supports_rmii = {false, false, false, false, true},
|
||||
.supports_rgmii = {false, false, false, false, true},
|
||||
.internal_phy = {true, true, true, true, false},
|
||||
},
|
||||
|
||||
[LAN9371] = {
|
||||
.chip_id = LAN9371_CHIP_ID,
|
||||
.dev_name = "LAN9371",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 1024,
|
||||
.num_statics = 256,
|
||||
.cpu_ports = 0x30, /* can be configured as cpu port */
|
||||
.port_cnt = 6, /* total physical port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false, true, true},
|
||||
.supports_rmii = {false, false, false, false, true, true},
|
||||
.supports_rgmii = {false, false, false, false, true, true},
|
||||
.internal_phy = {true, true, true, true, false, false},
|
||||
},
|
||||
|
||||
[LAN9372] = {
|
||||
.chip_id = LAN9372_CHIP_ID,
|
||||
.dev_name = "LAN9372",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 1024,
|
||||
.num_statics = 256,
|
||||
.cpu_ports = 0x30, /* can be configured as cpu port */
|
||||
.port_cnt = 8, /* total physical port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, true,
|
||||
false, false, true, true},
|
||||
},
|
||||
|
||||
[LAN9373] = {
|
||||
.chip_id = LAN9373_CHIP_ID,
|
||||
.dev_name = "LAN9373",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 1024,
|
||||
.num_statics = 256,
|
||||
.cpu_ports = 0x38, /* can be configured as cpu port */
|
||||
.port_cnt = 5, /* total physical port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, false,
|
||||
false, false, true, true},
|
||||
},
|
||||
|
||||
[LAN9374] = {
|
||||
.chip_id = LAN9374_CHIP_ID,
|
||||
.dev_name = "LAN9374",
|
||||
.num_vlans = 4096,
|
||||
.num_alus = 1024,
|
||||
.num_statics = 256,
|
||||
.cpu_ports = 0x30, /* can be configured as cpu port */
|
||||
.port_cnt = 8, /* total physical port count */
|
||||
.mib_names = ksz9477_mib_names,
|
||||
.mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
|
||||
.reg_mib_cnt = MIB_COUNTER_NUM,
|
||||
.supports_mii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.supports_rgmii = {false, false, false, false,
|
||||
true, true, false, false},
|
||||
.internal_phy = {true, true, true, true,
|
||||
false, false, true, true},
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ksz_switch_chips);
|
||||
|
||||
static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) {
|
||||
const struct ksz_chip_data *chip = &ksz_switch_chips[i];
|
||||
|
||||
if (chip->chip_id == prod_num)
|
||||
return chip;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ksz_check_device_id(struct ksz_device *dev)
|
||||
{
|
||||
const struct ksz_chip_data *dt_chip_data;
|
||||
|
||||
dt_chip_data = of_device_get_match_data(dev->dev);
|
||||
|
||||
/* Check for Device Tree and Chip ID */
|
||||
if (dt_chip_data->chip_id != dev->chip_id) {
|
||||
dev_err(dev->dev,
|
||||
"Device tree specifies chip %s but found %s, please fix it!\n",
|
||||
dt_chip_data->dev_name, dev->info->dev_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
struct phylink_config *config)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
config->legacy_pre_march2020 = false;
|
||||
|
||||
if (dev->info->supports_mii[port])
|
||||
__set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
|
||||
|
||||
if (dev->info->supports_rmii[port])
|
||||
__set_bit(PHY_INTERFACE_MODE_RMII,
|
||||
config->supported_interfaces);
|
||||
|
||||
if (dev->info->supports_rgmii[port])
|
||||
phy_interface_set_rgmii(config->supported_interfaces);
|
||||
|
||||
if (dev->info->internal_phy[port])
|
||||
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
config->supported_interfaces);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_phylink_get_caps);
|
||||
|
||||
void ksz_r_mib_stats64(struct ksz_device *dev, int port)
|
||||
{
|
||||
struct rtnl_link_stats64 *stats;
|
||||
@ -116,6 +516,22 @@ void ksz_get_stats64(struct dsa_switch *ds, int port,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_stats64);
|
||||
|
||||
void ksz_get_strings(struct dsa_switch *ds, int port,
|
||||
u32 stringset, uint8_t *buf)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int i;
|
||||
|
||||
if (stringset != ETH_SS_STATS)
|
||||
return;
|
||||
|
||||
for (i = 0; i < dev->info->mib_cnt; i++) {
|
||||
memcpy(buf + i * ETH_GSTRING_LEN,
|
||||
dev->info->mib_names[i].string, ETH_GSTRING_LEN);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_strings);
|
||||
|
||||
void ksz_update_port_member(struct ksz_device *dev, int port)
|
||||
{
|
||||
struct ksz_port *p = &dev->ports[port];
|
||||
@ -181,17 +597,17 @@ static void port_r_cnt(struct ksz_device *dev, int port)
|
||||
u64 *dropped;
|
||||
|
||||
/* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */
|
||||
while (mib->cnt_ptr < dev->reg_mib_cnt) {
|
||||
while (mib->cnt_ptr < dev->info->reg_mib_cnt) {
|
||||
dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr,
|
||||
&mib->counters[mib->cnt_ptr]);
|
||||
++mib->cnt_ptr;
|
||||
}
|
||||
|
||||
/* last one in storage */
|
||||
dropped = &mib->counters[dev->mib_cnt];
|
||||
dropped = &mib->counters[dev->info->mib_cnt];
|
||||
|
||||
/* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */
|
||||
while (mib->cnt_ptr < dev->mib_cnt) {
|
||||
while (mib->cnt_ptr < dev->info->mib_cnt) {
|
||||
dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr,
|
||||
dropped, &mib->counters[mib->cnt_ptr]);
|
||||
++mib->cnt_ptr;
|
||||
@ -207,7 +623,7 @@ static void ksz_mib_read_work(struct work_struct *work)
|
||||
struct ksz_port *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->port_cnt; i++) {
|
||||
for (i = 0; i < dev->info->port_cnt; i++) {
|
||||
if (dsa_is_unused_port(dev->ds, i))
|
||||
continue;
|
||||
|
||||
@ -222,7 +638,7 @@ static void ksz_mib_read_work(struct work_struct *work)
|
||||
const struct dsa_port *dp = dsa_to_port(dev->ds, i);
|
||||
|
||||
if (!netif_carrier_ok(dp->slave))
|
||||
mib->cnt_ptr = dev->reg_mib_cnt;
|
||||
mib->cnt_ptr = dev->info->reg_mib_cnt;
|
||||
}
|
||||
port_r_cnt(dev, i);
|
||||
p->read = false;
|
||||
@ -242,8 +658,14 @@ void ksz_init_mib_timer(struct ksz_device *dev)
|
||||
|
||||
INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work);
|
||||
|
||||
for (i = 0; i < dev->port_cnt; i++)
|
||||
for (i = 0; i < dev->info->port_cnt; i++) {
|
||||
struct ksz_port_mib *mib = &dev->ports[i].mib;
|
||||
|
||||
dev->dev_ops->port_init_cnt(dev, i);
|
||||
|
||||
mib->cnt_ptr = 0;
|
||||
memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_init_mib_timer);
|
||||
|
||||
@ -289,7 +711,7 @@ int ksz_sset_count(struct dsa_switch *ds, int port, int sset)
|
||||
if (sset != ETH_SS_STATS)
|
||||
return 0;
|
||||
|
||||
return dev->mib_cnt;
|
||||
return dev->info->mib_cnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_sset_count);
|
||||
|
||||
@ -304,9 +726,9 @@ void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
|
||||
|
||||
/* Only read dropped counters if no link. */
|
||||
if (!netif_carrier_ok(dp->slave))
|
||||
mib->cnt_ptr = dev->reg_mib_cnt;
|
||||
mib->cnt_ptr = dev->info->reg_mib_cnt;
|
||||
port_r_cnt(dev, port);
|
||||
memcpy(buf, mib->counters, dev->mib_cnt * sizeof(u64));
|
||||
memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64));
|
||||
mutex_unlock(&mib->cnt_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
|
||||
@ -382,7 +804,7 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
int empty = 0;
|
||||
|
||||
alu.port_forward = 0;
|
||||
for (index = 0; index < dev->num_statics; index++) {
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
@ -395,11 +817,11 @@ int ksz_port_mdb_add(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->num_statics && !empty)
|
||||
if (index == dev->info->num_statics && !empty)
|
||||
return -ENOSPC;
|
||||
|
||||
/* add entry */
|
||||
if (index == dev->num_statics) {
|
||||
if (index == dev->info->num_statics) {
|
||||
index = empty - 1;
|
||||
memset(&alu, 0, sizeof(alu));
|
||||
memcpy(alu.mac, mdb->addr, ETH_ALEN);
|
||||
@ -426,7 +848,7 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
struct alu_struct alu;
|
||||
int index;
|
||||
|
||||
for (index = 0; index < dev->num_statics; index++) {
|
||||
for (index = 0; index < dev->info->num_statics; index++) {
|
||||
if (!dev->dev_ops->r_sta_mac_table(dev, index, &alu)) {
|
||||
/* Found one already in static MAC table. */
|
||||
if (!memcmp(alu.mac, mdb->addr, ETH_ALEN) &&
|
||||
@ -436,7 +858,7 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
}
|
||||
|
||||
/* no available entry */
|
||||
if (index == dev->num_statics)
|
||||
if (index == dev->info->num_statics)
|
||||
goto exit;
|
||||
|
||||
/* clear port */
|
||||
@ -537,10 +959,12 @@ EXPORT_SYMBOL(ksz_switch_alloc);
|
||||
int ksz_switch_register(struct ksz_device *dev,
|
||||
const struct ksz_dev_ops *ops)
|
||||
{
|
||||
const struct ksz_chip_data *info;
|
||||
struct device_node *port, *ports;
|
||||
phy_interface_t interface;
|
||||
unsigned int port_num;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (dev->pdata)
|
||||
dev->chip_id = dev->pdata->chip_id;
|
||||
@ -567,14 +991,45 @@ int ksz_switch_register(struct ksz_device *dev,
|
||||
if (dev->dev_ops->detect(dev))
|
||||
return -EINVAL;
|
||||
|
||||
info = ksz_lookup_info(dev->chip_id);
|
||||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
/* Update the compatible info with the probed one */
|
||||
dev->info = info;
|
||||
|
||||
ret = ksz_check_device_id(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dev->dev_ops->init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->ports = devm_kzalloc(dev->dev,
|
||||
dev->info->port_cnt * sizeof(struct ksz_port),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < dev->info->port_cnt; i++) {
|
||||
spin_lock_init(&dev->ports[i].mib.stats64_lock);
|
||||
mutex_init(&dev->ports[i].mib.cnt_mutex);
|
||||
dev->ports[i].mib.counters =
|
||||
devm_kzalloc(dev->dev,
|
||||
sizeof(u64) * (dev->info->mib_cnt + 1),
|
||||
GFP_KERNEL);
|
||||
if (!dev->ports[i].mib.counters)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* set the real number of ports */
|
||||
dev->ds->num_ports = dev->info->port_cnt;
|
||||
|
||||
/* Host port interface will be self detected, or specifically set in
|
||||
* device tree.
|
||||
*/
|
||||
for (port_num = 0; port_num < dev->port_cnt; ++port_num)
|
||||
for (port_num = 0; port_num < dev->info->port_cnt; ++port_num)
|
||||
dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA;
|
||||
if (dev->dev->of_node) {
|
||||
ret = of_get_phy_mode(dev->dev->of_node, &interface);
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <net/dsa.h>
|
||||
|
||||
#define KSZ_MAX_NUM_PORTS 8
|
||||
|
||||
struct vlan_table {
|
||||
u32 table[3];
|
||||
};
|
||||
@ -26,6 +28,30 @@ struct ksz_port_mib {
|
||||
struct spinlock stats64_lock;
|
||||
};
|
||||
|
||||
struct ksz_mib_names {
|
||||
int index;
|
||||
char string[ETH_GSTRING_LEN];
|
||||
};
|
||||
|
||||
struct ksz_chip_data {
|
||||
u32 chip_id;
|
||||
const char *dev_name;
|
||||
int num_vlans;
|
||||
int num_alus;
|
||||
int num_statics;
|
||||
int cpu_ports;
|
||||
int port_cnt;
|
||||
bool phy_errata_9477;
|
||||
bool ksz87xx_eee_link_erratum;
|
||||
const struct ksz_mib_names *mib_names;
|
||||
int mib_cnt;
|
||||
u8 reg_mib_cnt;
|
||||
bool supports_mii[KSZ_MAX_NUM_PORTS];
|
||||
bool supports_rmii[KSZ_MAX_NUM_PORTS];
|
||||
bool supports_rgmii[KSZ_MAX_NUM_PORTS];
|
||||
bool internal_phy[KSZ_MAX_NUM_PORTS];
|
||||
};
|
||||
|
||||
struct ksz_port {
|
||||
bool remove_tag; /* Remove Tag flag set, for ksz8795 only */
|
||||
int stp_state;
|
||||
@ -47,7 +73,7 @@ struct ksz_port {
|
||||
struct ksz_device {
|
||||
struct dsa_switch *ds;
|
||||
struct ksz_platform_data *pdata;
|
||||
const char *name;
|
||||
const struct ksz_chip_data *info;
|
||||
|
||||
struct mutex dev_mutex; /* device access */
|
||||
struct mutex regmap_mutex; /* regmap access */
|
||||
@ -64,20 +90,9 @@ struct ksz_device {
|
||||
|
||||
/* chip specific data */
|
||||
u32 chip_id;
|
||||
int num_vlans;
|
||||
int num_alus;
|
||||
int num_statics;
|
||||
int cpu_port; /* port connected to CPU */
|
||||
int cpu_ports; /* port bitmap can be cpu port */
|
||||
int phy_port_cnt;
|
||||
int port_cnt;
|
||||
u8 reg_mib_cnt;
|
||||
int mib_cnt;
|
||||
const struct mib_names *mib_names;
|
||||
phy_interface_t compat_interface;
|
||||
u32 regs_size;
|
||||
bool phy_errata_9477;
|
||||
bool ksz87xx_eee_link_erratum;
|
||||
bool synclko_125;
|
||||
bool synclko_disable;
|
||||
|
||||
@ -89,11 +104,42 @@ struct ksz_device {
|
||||
u16 mirror_rx;
|
||||
u16 mirror_tx;
|
||||
u32 features; /* chip specific features */
|
||||
u32 overrides; /* chip functions set by user */
|
||||
u16 host_mask;
|
||||
u16 port_mask;
|
||||
};
|
||||
|
||||
/* List of supported models */
|
||||
enum ksz_model {
|
||||
KSZ8795,
|
||||
KSZ8794,
|
||||
KSZ8765,
|
||||
KSZ8830,
|
||||
KSZ9477,
|
||||
KSZ9897,
|
||||
KSZ9893,
|
||||
KSZ9567,
|
||||
LAN9370,
|
||||
LAN9371,
|
||||
LAN9372,
|
||||
LAN9373,
|
||||
LAN9374,
|
||||
};
|
||||
|
||||
enum ksz_chip_id {
|
||||
KSZ8795_CHIP_ID = 0x8795,
|
||||
KSZ8794_CHIP_ID = 0x8794,
|
||||
KSZ8765_CHIP_ID = 0x8765,
|
||||
KSZ8830_CHIP_ID = 0x8830,
|
||||
KSZ9477_CHIP_ID = 0x00947700,
|
||||
KSZ9897_CHIP_ID = 0x00989700,
|
||||
KSZ9893_CHIP_ID = 0x00989300,
|
||||
KSZ9567_CHIP_ID = 0x00956700,
|
||||
LAN9370_CHIP_ID = 0x00937000,
|
||||
LAN9371_CHIP_ID = 0x00937100,
|
||||
LAN9372_CHIP_ID = 0x00937200,
|
||||
LAN9373_CHIP_ID = 0x00937300,
|
||||
LAN9374_CHIP_ID = 0x00937400,
|
||||
};
|
||||
|
||||
struct alu_struct {
|
||||
/* entry 1 */
|
||||
u8 is_static:1;
|
||||
@ -154,6 +200,9 @@ void ksz_init_mib_timer(struct ksz_device *dev);
|
||||
void ksz_r_mib_stats64(struct ksz_device *dev, int port);
|
||||
void ksz_get_stats64(struct dsa_switch *ds, int port,
|
||||
struct rtnl_link_stats64 *s);
|
||||
void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
struct phylink_config *config);
|
||||
extern const struct ksz_chip_data ksz_switch_chips[];
|
||||
|
||||
/* Common DSA access functions */
|
||||
|
||||
@ -180,6 +229,8 @@ int ksz_port_mdb_del(struct dsa_switch *ds, int port,
|
||||
const struct switchdev_obj_port_mdb *mdb,
|
||||
struct dsa_db db);
|
||||
int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
|
||||
void ksz_get_strings(struct dsa_switch *ds, int port,
|
||||
u32 stringset, uint8_t *buf);
|
||||
|
||||
/* Common register access functions */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user