15b79c72eSTristram Ha // SPDX-License-Identifier: GPL-2.0 2b987e98eSWoojung Huh /* 3b987e98eSWoojung Huh * Microchip switch driver main logic 4b987e98eSWoojung Huh * 542fc6a4cSTristram Ha * Copyright (C) 2017-2019 Microchip Technology Inc. 6b987e98eSWoojung Huh */ 7b987e98eSWoojung Huh 8b987e98eSWoojung Huh #include <linux/delay.h> 9b987e98eSWoojung Huh #include <linux/export.h> 10924352c3SMarek Vasut #include <linux/gpio/consumer.h> 11b987e98eSWoojung Huh #include <linux/kernel.h> 12b987e98eSWoojung Huh #include <linux/module.h> 13b987e98eSWoojung Huh #include <linux/platform_data/microchip-ksz.h> 14b987e98eSWoojung Huh #include <linux/phy.h> 15b987e98eSWoojung Huh #include <linux/etherdevice.h> 16b987e98eSWoojung Huh #include <linux/if_bridge.h> 17eee16b14SArun Ramadoss #include <linux/of_device.h> 18c2e86691STristram Ha #include <linux/of_net.h> 191fe94f54SArun Ramadoss #include <linux/micrel_phy.h> 20b987e98eSWoojung Huh #include <net/dsa.h> 21b987e98eSWoojung Huh #include <net/switchdev.h> 22b987e98eSWoojung Huh 23ffc60b55SMarek Vasut #include "ksz_common.h" 246ec23aaaSArun Ramadoss #include "ksz8.h" 256ec23aaaSArun Ramadoss #include "ksz9477.h" 2655ab6ffaSArun Ramadoss #include "lan937x.h" 277049f9b5STristram Ha 28a530e6f2SArun Ramadoss #define MIB_COUNTER_NUM 0x20 29a530e6f2SArun Ramadoss 30c6101dd7SArun Ramadoss struct ksz_stats_raw { 31c6101dd7SArun Ramadoss u64 rx_hi; 32c6101dd7SArun Ramadoss u64 rx_undersize; 33c6101dd7SArun Ramadoss u64 rx_fragments; 34c6101dd7SArun Ramadoss u64 rx_oversize; 35c6101dd7SArun Ramadoss u64 rx_jabbers; 36c6101dd7SArun Ramadoss u64 rx_symbol_err; 37c6101dd7SArun Ramadoss u64 rx_crc_err; 38c6101dd7SArun Ramadoss u64 rx_align_err; 39c6101dd7SArun Ramadoss u64 rx_mac_ctrl; 40c6101dd7SArun Ramadoss u64 rx_pause; 41c6101dd7SArun Ramadoss u64 rx_bcast; 42c6101dd7SArun Ramadoss u64 rx_mcast; 43c6101dd7SArun Ramadoss u64 rx_ucast; 44c6101dd7SArun Ramadoss u64 rx_64_or_less; 45c6101dd7SArun Ramadoss u64 rx_65_127; 46c6101dd7SArun Ramadoss u64 rx_128_255; 47c6101dd7SArun Ramadoss u64 rx_256_511; 48c6101dd7SArun Ramadoss u64 rx_512_1023; 49c6101dd7SArun Ramadoss u64 rx_1024_1522; 50c6101dd7SArun Ramadoss u64 rx_1523_2000; 51c6101dd7SArun Ramadoss u64 rx_2001; 52c6101dd7SArun Ramadoss u64 tx_hi; 53c6101dd7SArun Ramadoss u64 tx_late_col; 54c6101dd7SArun Ramadoss u64 tx_pause; 55c6101dd7SArun Ramadoss u64 tx_bcast; 56c6101dd7SArun Ramadoss u64 tx_mcast; 57c6101dd7SArun Ramadoss u64 tx_ucast; 58c6101dd7SArun Ramadoss u64 tx_deferred; 59c6101dd7SArun Ramadoss u64 tx_total_col; 60c6101dd7SArun Ramadoss u64 tx_exc_col; 61c6101dd7SArun Ramadoss u64 tx_single_col; 62c6101dd7SArun Ramadoss u64 tx_mult_col; 63c6101dd7SArun Ramadoss u64 rx_total; 64c6101dd7SArun Ramadoss u64 tx_total; 65c6101dd7SArun Ramadoss u64 rx_discards; 66c6101dd7SArun Ramadoss u64 tx_discards; 67c6101dd7SArun Ramadoss }; 68c6101dd7SArun Ramadoss 69a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz88xx_mib_names[] = { 70a530e6f2SArun Ramadoss { 0x00, "rx" }, 71a530e6f2SArun Ramadoss { 0x01, "rx_hi" }, 72a530e6f2SArun Ramadoss { 0x02, "rx_undersize" }, 73a530e6f2SArun Ramadoss { 0x03, "rx_fragments" }, 74a530e6f2SArun Ramadoss { 0x04, "rx_oversize" }, 75a530e6f2SArun Ramadoss { 0x05, "rx_jabbers" }, 76a530e6f2SArun Ramadoss { 0x06, "rx_symbol_err" }, 77a530e6f2SArun Ramadoss { 0x07, "rx_crc_err" }, 78a530e6f2SArun Ramadoss { 0x08, "rx_align_err" }, 79a530e6f2SArun Ramadoss { 0x09, "rx_mac_ctrl" }, 80a530e6f2SArun Ramadoss { 0x0a, "rx_pause" }, 81a530e6f2SArun Ramadoss { 0x0b, "rx_bcast" }, 82a530e6f2SArun Ramadoss { 0x0c, "rx_mcast" }, 83a530e6f2SArun Ramadoss { 0x0d, "rx_ucast" }, 84a530e6f2SArun Ramadoss { 0x0e, "rx_64_or_less" }, 85a530e6f2SArun Ramadoss { 0x0f, "rx_65_127" }, 86a530e6f2SArun Ramadoss { 0x10, "rx_128_255" }, 87a530e6f2SArun Ramadoss { 0x11, "rx_256_511" }, 88a530e6f2SArun Ramadoss { 0x12, "rx_512_1023" }, 89a530e6f2SArun Ramadoss { 0x13, "rx_1024_1522" }, 90a530e6f2SArun Ramadoss { 0x14, "tx" }, 91a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 92a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 93a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 94a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 95a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 96a530e6f2SArun Ramadoss { 0x1a, "tx_ucast" }, 97a530e6f2SArun Ramadoss { 0x1b, "tx_deferred" }, 98a530e6f2SArun Ramadoss { 0x1c, "tx_total_col" }, 99a530e6f2SArun Ramadoss { 0x1d, "tx_exc_col" }, 100a530e6f2SArun Ramadoss { 0x1e, "tx_single_col" }, 101a530e6f2SArun Ramadoss { 0x1f, "tx_mult_col" }, 102a530e6f2SArun Ramadoss { 0x100, "rx_discards" }, 103a530e6f2SArun Ramadoss { 0x101, "tx_discards" }, 104a530e6f2SArun Ramadoss }; 105a530e6f2SArun Ramadoss 106a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz9477_mib_names[] = { 107a530e6f2SArun Ramadoss { 0x00, "rx_hi" }, 108a530e6f2SArun Ramadoss { 0x01, "rx_undersize" }, 109a530e6f2SArun Ramadoss { 0x02, "rx_fragments" }, 110a530e6f2SArun Ramadoss { 0x03, "rx_oversize" }, 111a530e6f2SArun Ramadoss { 0x04, "rx_jabbers" }, 112a530e6f2SArun Ramadoss { 0x05, "rx_symbol_err" }, 113a530e6f2SArun Ramadoss { 0x06, "rx_crc_err" }, 114a530e6f2SArun Ramadoss { 0x07, "rx_align_err" }, 115a530e6f2SArun Ramadoss { 0x08, "rx_mac_ctrl" }, 116a530e6f2SArun Ramadoss { 0x09, "rx_pause" }, 117a530e6f2SArun Ramadoss { 0x0A, "rx_bcast" }, 118a530e6f2SArun Ramadoss { 0x0B, "rx_mcast" }, 119a530e6f2SArun Ramadoss { 0x0C, "rx_ucast" }, 120a530e6f2SArun Ramadoss { 0x0D, "rx_64_or_less" }, 121a530e6f2SArun Ramadoss { 0x0E, "rx_65_127" }, 122a530e6f2SArun Ramadoss { 0x0F, "rx_128_255" }, 123a530e6f2SArun Ramadoss { 0x10, "rx_256_511" }, 124a530e6f2SArun Ramadoss { 0x11, "rx_512_1023" }, 125a530e6f2SArun Ramadoss { 0x12, "rx_1024_1522" }, 126a530e6f2SArun Ramadoss { 0x13, "rx_1523_2000" }, 127a530e6f2SArun Ramadoss { 0x14, "rx_2001" }, 128a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 129a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 130a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 131a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 132a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 133a530e6f2SArun Ramadoss { 0x1A, "tx_ucast" }, 134a530e6f2SArun Ramadoss { 0x1B, "tx_deferred" }, 135a530e6f2SArun Ramadoss { 0x1C, "tx_total_col" }, 136a530e6f2SArun Ramadoss { 0x1D, "tx_exc_col" }, 137a530e6f2SArun Ramadoss { 0x1E, "tx_single_col" }, 138a530e6f2SArun Ramadoss { 0x1F, "tx_mult_col" }, 139a530e6f2SArun Ramadoss { 0x80, "rx_total" }, 140a530e6f2SArun Ramadoss { 0x81, "tx_total" }, 141a530e6f2SArun Ramadoss { 0x82, "rx_discards" }, 142a530e6f2SArun Ramadoss { 0x83, "tx_discards" }, 143a530e6f2SArun Ramadoss }; 144a530e6f2SArun Ramadoss 1456ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz8_dev_ops = { 1466ec23aaaSArun Ramadoss .setup = ksz8_setup, 1476ec23aaaSArun Ramadoss .get_port_addr = ksz8_get_port_addr, 1486ec23aaaSArun Ramadoss .cfg_port_member = ksz8_cfg_port_member, 1496ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, 1506ec23aaaSArun Ramadoss .port_setup = ksz8_port_setup, 1516ec23aaaSArun Ramadoss .r_phy = ksz8_r_phy, 1526ec23aaaSArun Ramadoss .w_phy = ksz8_w_phy, 153769e2695SArun Ramadoss .r_mib_cnt = ksz8_r_mib_cnt, 1546ec23aaaSArun Ramadoss .r_mib_pkt = ksz8_r_mib_pkt, 1556ec23aaaSArun Ramadoss .freeze_mib = ksz8_freeze_mib, 1566ec23aaaSArun Ramadoss .port_init_cnt = ksz8_port_init_cnt, 1576ec23aaaSArun Ramadoss .fdb_dump = ksz8_fdb_dump, 1586ec23aaaSArun Ramadoss .mdb_add = ksz8_mdb_add, 1596ec23aaaSArun Ramadoss .mdb_del = ksz8_mdb_del, 1606ec23aaaSArun Ramadoss .vlan_filtering = ksz8_port_vlan_filtering, 1616ec23aaaSArun Ramadoss .vlan_add = ksz8_port_vlan_add, 1626ec23aaaSArun Ramadoss .vlan_del = ksz8_port_vlan_del, 1636ec23aaaSArun Ramadoss .mirror_add = ksz8_port_mirror_add, 1646ec23aaaSArun Ramadoss .mirror_del = ksz8_port_mirror_del, 1656ec23aaaSArun Ramadoss .get_caps = ksz8_get_caps, 1666ec23aaaSArun Ramadoss .config_cpu_port = ksz8_config_cpu_port, 1676ec23aaaSArun Ramadoss .enable_stp_addr = ksz8_enable_stp_addr, 1686ec23aaaSArun Ramadoss .reset = ksz8_reset_switch, 1696ec23aaaSArun Ramadoss .init = ksz8_switch_init, 1706ec23aaaSArun Ramadoss .exit = ksz8_switch_exit, 1716ec23aaaSArun Ramadoss }; 1726ec23aaaSArun Ramadoss 1736ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz9477_dev_ops = { 1746ec23aaaSArun Ramadoss .setup = ksz9477_setup, 1756ec23aaaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 1766ec23aaaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 1776ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 1786ec23aaaSArun Ramadoss .port_setup = ksz9477_port_setup, 1796ec23aaaSArun Ramadoss .r_phy = ksz9477_r_phy, 1806ec23aaaSArun Ramadoss .w_phy = ksz9477_w_phy, 1816ec23aaaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 1826ec23aaaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 1836ec23aaaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 1846ec23aaaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 1856ec23aaaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 1866ec23aaaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 1876ec23aaaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 1886ec23aaaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 1896ec23aaaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 1906ec23aaaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 1916ec23aaaSArun Ramadoss .get_caps = ksz9477_get_caps, 1926ec23aaaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 1936ec23aaaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 1946ec23aaaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 1956ec23aaaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 1966ec23aaaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 1976ec23aaaSArun Ramadoss .change_mtu = ksz9477_change_mtu, 1986ec23aaaSArun Ramadoss .max_mtu = ksz9477_max_mtu, 1996ec23aaaSArun Ramadoss .config_cpu_port = ksz9477_config_cpu_port, 2006ec23aaaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 2016ec23aaaSArun Ramadoss .reset = ksz9477_reset_switch, 2026ec23aaaSArun Ramadoss .init = ksz9477_switch_init, 2036ec23aaaSArun Ramadoss .exit = ksz9477_switch_exit, 2046ec23aaaSArun Ramadoss }; 2056ec23aaaSArun Ramadoss 20655ab6ffaSArun Ramadoss static const struct ksz_dev_ops lan937x_dev_ops = { 20755ab6ffaSArun Ramadoss .setup = lan937x_setup, 20855ab6ffaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 20955ab6ffaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 210ab882368SArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 21155ab6ffaSArun Ramadoss .port_setup = lan937x_port_setup, 212ffaf1de2SArun Ramadoss .r_phy = lan937x_r_phy, 213ffaf1de2SArun Ramadoss .w_phy = lan937x_w_phy, 21455ab6ffaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 21555ab6ffaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 21655ab6ffaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 21755ab6ffaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 21855ab6ffaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 21955ab6ffaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 22055ab6ffaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 22155ab6ffaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 22255ab6ffaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 22355ab6ffaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 224c14e878dSArun Ramadoss .get_caps = lan937x_phylink_get_caps, 225a0cb1aa4SArun Ramadoss .phylink_mac_config = lan937x_phylink_mac_config, 226f597d3adSArun Ramadoss .phylink_mac_link_up = lan937x_phylink_mac_link_up, 22755ab6ffaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 22855ab6ffaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 22955ab6ffaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 23055ab6ffaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 23155ab6ffaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 232ab882368SArun Ramadoss .change_mtu = lan937x_change_mtu, 23355ab6ffaSArun Ramadoss .max_mtu = ksz9477_max_mtu, 23455ab6ffaSArun Ramadoss .config_cpu_port = lan937x_config_cpu_port, 23555ab6ffaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 23655ab6ffaSArun Ramadoss .reset = lan937x_reset_switch, 23755ab6ffaSArun Ramadoss .init = lan937x_switch_init, 23855ab6ffaSArun Ramadoss .exit = lan937x_switch_exit, 23955ab6ffaSArun Ramadoss }; 24055ab6ffaSArun Ramadoss 241a02579dfSArun Ramadoss static const u16 ksz8795_regs[] = { 242486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x6E, 243486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x70, 244486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x72, 245486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x71, 246486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x75, 247486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x74, 248486f9ca7SArun Ramadoss [REG_IND_BYTE] = 0xA0, 249486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 250486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 251486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x07, 252486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 253486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x08, 254486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x09, 255486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x0C, 2566877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 2579d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 2589d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 2599d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 260*aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x06, 26146f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x56, 262486f9ca7SArun Ramadoss }; 263486f9ca7SArun Ramadoss 264d23a5e18SArun Ramadoss static const u32 ksz8795_masks[] = { 265d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(7), 266d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(1), 267d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(6), 268d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(5), 269d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(6, 0), 270d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), 271d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(12), 272d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(21), 273d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(23), 274d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), 275d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(26), 276d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20), 277d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), 278d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8), 279d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 280d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), 281d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20), 282d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), 283d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), 284d23a5e18SArun Ramadoss }; 285d23a5e18SArun Ramadoss 286*aa5b8b73SArun Ramadoss static const u8 ksz8795_xmii_ctrl0[] = { 287*aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 0, 288*aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 1, 289*aa5b8b73SArun Ramadoss }; 290*aa5b8b73SArun Ramadoss 29146f80fa8SArun Ramadoss static const u8 ksz8795_xmii_ctrl1[] = { 29246f80fa8SArun Ramadoss [P_GMII_1GBIT] = 1, 29346f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 0, 29446f80fa8SArun Ramadoss }; 29546f80fa8SArun Ramadoss 29634e48383SArun Ramadoss static const u8 ksz8795_shifts[] = { 29734e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 7, 29834e48383SArun Ramadoss [VLAN_TABLE] = 16, 29934e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 30034e48383SArun Ramadoss [STATIC_MAC_FID] = 24, 30134e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 30234e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 29, 30334e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 30434e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 27, 30534e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 24, 30634e48383SArun Ramadoss }; 30734e48383SArun Ramadoss 308a02579dfSArun Ramadoss static const u16 ksz8863_regs[] = { 309486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x79, 310486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x7B, 311486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x7B, 312486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x7C, 313486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x80, 314486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x80, 315486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 316486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 317486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x0C, 318486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 319486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x0E, 320486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x0F, 321486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x03, 3226877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3239d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3249d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3259d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 326486f9ca7SArun Ramadoss }; 327486f9ca7SArun Ramadoss 328d23a5e18SArun Ramadoss static const u32 ksz8863_masks[] = { 329d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(3), 330d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(6), 331d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(7), 332d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(6), 333d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(15, 12), 334d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16), 335d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(19), 336d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(19), 337d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(21), 338d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(29, 26), 339d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(20), 340d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16), 341d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(5, 0), 342d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), 343d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 344d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 28), 345d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16), 346d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20), 347d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22), 348d23a5e18SArun Ramadoss }; 349d23a5e18SArun Ramadoss 35034e48383SArun Ramadoss static u8 ksz8863_shifts[] = { 35134e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 16, 35234e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 35334e48383SArun Ramadoss [STATIC_MAC_FID] = 22, 35434e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 35534e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 24, 35634e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 35734e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 24, 35834e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 20, 35934e48383SArun Ramadoss }; 36034e48383SArun Ramadoss 3616877102fSArun Ramadoss static const u16 ksz9477_regs[] = { 3626877102fSArun Ramadoss [P_STP_CTRL] = 0x0B04, 3639d95329cSArun Ramadoss [S_START_CTRL] = 0x0300, 3649d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x0332, 3659d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x0331, 366*aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x0300, 36746f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x0301, 368457c182aSArun Ramadoss }; 3696877102fSArun Ramadoss 370457c182aSArun Ramadoss static const u32 ksz9477_masks[] = { 371457c182aSArun Ramadoss [ALU_STAT_WRITE] = 0, 372457c182aSArun Ramadoss [ALU_STAT_READ] = 1, 373457c182aSArun Ramadoss }; 374457c182aSArun Ramadoss 375457c182aSArun Ramadoss static const u8 ksz9477_shifts[] = { 376457c182aSArun Ramadoss [ALU_STAT_INDEX] = 16, 377457c182aSArun Ramadoss }; 378457c182aSArun Ramadoss 379*aa5b8b73SArun Ramadoss static const u8 ksz9477_xmii_ctrl0[] = { 380*aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 1, 381*aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 0, 382*aa5b8b73SArun Ramadoss }; 383*aa5b8b73SArun Ramadoss 38446f80fa8SArun Ramadoss static const u8 ksz9477_xmii_ctrl1[] = { 38546f80fa8SArun Ramadoss [P_GMII_1GBIT] = 0, 38646f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 1, 38746f80fa8SArun Ramadoss }; 38846f80fa8SArun Ramadoss 389457c182aSArun Ramadoss static const u32 lan937x_masks[] = { 390457c182aSArun Ramadoss [ALU_STAT_WRITE] = 1, 391457c182aSArun Ramadoss [ALU_STAT_READ] = 2, 392457c182aSArun Ramadoss }; 393457c182aSArun Ramadoss 394457c182aSArun Ramadoss static const u8 lan937x_shifts[] = { 395457c182aSArun Ramadoss [ALU_STAT_INDEX] = 8, 3966877102fSArun Ramadoss }; 3976877102fSArun Ramadoss 398eee16b14SArun Ramadoss const struct ksz_chip_data ksz_switch_chips[] = { 399462d5250SArun Ramadoss [KSZ8795] = { 400462d5250SArun Ramadoss .chip_id = KSZ8795_CHIP_ID, 401462d5250SArun Ramadoss .dev_name = "KSZ8795", 402462d5250SArun Ramadoss .num_vlans = 4096, 403462d5250SArun Ramadoss .num_alus = 0, 404462d5250SArun Ramadoss .num_statics = 8, 405462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 406462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 4076ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 408462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 409a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 410a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 411a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 412486f9ca7SArun Ramadoss .regs = ksz8795_regs, 413d23a5e18SArun Ramadoss .masks = ksz8795_masks, 41434e48383SArun Ramadoss .shifts = ksz8795_shifts, 415*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 41646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 41765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 41865ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 41965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 42065ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 421462d5250SArun Ramadoss }, 422462d5250SArun Ramadoss 423462d5250SArun Ramadoss [KSZ8794] = { 424462d5250SArun Ramadoss /* WARNING 425462d5250SArun Ramadoss * ======= 426462d5250SArun Ramadoss * KSZ8794 is similar to KSZ8795, except the port map 427462d5250SArun Ramadoss * contains a gap between external and CPU ports, the 428462d5250SArun Ramadoss * port map is NOT continuous. The per-port register 429462d5250SArun Ramadoss * map is shifted accordingly too, i.e. registers at 430462d5250SArun Ramadoss * offset 0x40 are NOT used on KSZ8794 and they ARE 431462d5250SArun Ramadoss * used on KSZ8795 for external port 3. 432462d5250SArun Ramadoss * external cpu 433462d5250SArun Ramadoss * KSZ8794 0,1,2 4 434462d5250SArun Ramadoss * KSZ8795 0,1,2,3 4 435462d5250SArun Ramadoss * KSZ8765 0,1,2,3 4 436462d5250SArun Ramadoss * port_cnt is configured as 5, even though it is 4 437462d5250SArun Ramadoss */ 438462d5250SArun Ramadoss .chip_id = KSZ8794_CHIP_ID, 439462d5250SArun Ramadoss .dev_name = "KSZ8794", 440462d5250SArun Ramadoss .num_vlans = 4096, 441462d5250SArun Ramadoss .num_alus = 0, 442462d5250SArun Ramadoss .num_statics = 8, 443462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 444462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 4456ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 446462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 447a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 448a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 449a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 450486f9ca7SArun Ramadoss .regs = ksz8795_regs, 451d23a5e18SArun Ramadoss .masks = ksz8795_masks, 45234e48383SArun Ramadoss .shifts = ksz8795_shifts, 453*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 45446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 45565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 45665ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 45765ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 45865ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, false}, 459462d5250SArun Ramadoss }, 460462d5250SArun Ramadoss 461462d5250SArun Ramadoss [KSZ8765] = { 462462d5250SArun Ramadoss .chip_id = KSZ8765_CHIP_ID, 463462d5250SArun Ramadoss .dev_name = "KSZ8765", 464462d5250SArun Ramadoss .num_vlans = 4096, 465462d5250SArun Ramadoss .num_alus = 0, 466462d5250SArun Ramadoss .num_statics = 8, 467462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 468462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 4696ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 470462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 471a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 472a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 473a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 474486f9ca7SArun Ramadoss .regs = ksz8795_regs, 475d23a5e18SArun Ramadoss .masks = ksz8795_masks, 47634e48383SArun Ramadoss .shifts = ksz8795_shifts, 477*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 47846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 47965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 48065ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 48165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 48265ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 483462d5250SArun Ramadoss }, 484462d5250SArun Ramadoss 485462d5250SArun Ramadoss [KSZ8830] = { 486462d5250SArun Ramadoss .chip_id = KSZ8830_CHIP_ID, 487462d5250SArun Ramadoss .dev_name = "KSZ8863/KSZ8873", 488462d5250SArun Ramadoss .num_vlans = 16, 489462d5250SArun Ramadoss .num_alus = 0, 490462d5250SArun Ramadoss .num_statics = 8, 491462d5250SArun Ramadoss .cpu_ports = 0x4, /* can be configured as cpu port */ 492462d5250SArun Ramadoss .port_cnt = 3, 4936ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 494a530e6f2SArun Ramadoss .mib_names = ksz88xx_mib_names, 495a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), 496a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 497486f9ca7SArun Ramadoss .regs = ksz8863_regs, 498d23a5e18SArun Ramadoss .masks = ksz8863_masks, 49934e48383SArun Ramadoss .shifts = ksz8863_shifts, 50065ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 50165ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 50265ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 503462d5250SArun Ramadoss }, 504462d5250SArun Ramadoss 505462d5250SArun Ramadoss [KSZ9477] = { 506462d5250SArun Ramadoss .chip_id = KSZ9477_CHIP_ID, 507462d5250SArun Ramadoss .dev_name = "KSZ9477", 508462d5250SArun Ramadoss .num_vlans = 4096, 509462d5250SArun Ramadoss .num_alus = 4096, 510462d5250SArun Ramadoss .num_statics = 16, 511462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 512462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 5136ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 514462d5250SArun Ramadoss .phy_errata_9477 = true, 515a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 516a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 517a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 5186877102fSArun Ramadoss .regs = ksz9477_regs, 519457c182aSArun Ramadoss .masks = ksz9477_masks, 520457c182aSArun Ramadoss .shifts = ksz9477_shifts, 521*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 52246f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 52365ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 52465ac79e1SArun Ramadoss false, true, false}, 52565ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 52665ac79e1SArun Ramadoss false, true, false}, 52765ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 52865ac79e1SArun Ramadoss false, true, false}, 52965ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 53065ac79e1SArun Ramadoss true, false, false}, 531462d5250SArun Ramadoss }, 532462d5250SArun Ramadoss 533462d5250SArun Ramadoss [KSZ9897] = { 534462d5250SArun Ramadoss .chip_id = KSZ9897_CHIP_ID, 535462d5250SArun Ramadoss .dev_name = "KSZ9897", 536462d5250SArun Ramadoss .num_vlans = 4096, 537462d5250SArun Ramadoss .num_alus = 4096, 538462d5250SArun Ramadoss .num_statics = 16, 539462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 540462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 5416ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 542462d5250SArun Ramadoss .phy_errata_9477 = true, 543a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 544a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 545a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 5466877102fSArun Ramadoss .regs = ksz9477_regs, 547457c182aSArun Ramadoss .masks = ksz9477_masks, 548457c182aSArun Ramadoss .shifts = ksz9477_shifts, 549*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 55046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 55165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 55265ac79e1SArun Ramadoss false, true, true}, 55365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 55465ac79e1SArun Ramadoss false, true, true}, 55565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 55665ac79e1SArun Ramadoss false, true, true}, 55765ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 55865ac79e1SArun Ramadoss true, false, false}, 559462d5250SArun Ramadoss }, 560462d5250SArun Ramadoss 561462d5250SArun Ramadoss [KSZ9893] = { 562462d5250SArun Ramadoss .chip_id = KSZ9893_CHIP_ID, 563462d5250SArun Ramadoss .dev_name = "KSZ9893", 564462d5250SArun Ramadoss .num_vlans = 4096, 565462d5250SArun Ramadoss .num_alus = 4096, 566462d5250SArun Ramadoss .num_statics = 16, 567462d5250SArun Ramadoss .cpu_ports = 0x07, /* can be configured as cpu port */ 568462d5250SArun Ramadoss .port_cnt = 3, /* total port count */ 5696ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 570a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 571a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 572a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 5736877102fSArun Ramadoss .regs = ksz9477_regs, 574457c182aSArun Ramadoss .masks = ksz9477_masks, 575457c182aSArun Ramadoss .shifts = ksz9477_shifts, 576*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 57746f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 57865ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 57965ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 58065ac79e1SArun Ramadoss .supports_rgmii = {false, false, true}, 58165ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 582462d5250SArun Ramadoss }, 583462d5250SArun Ramadoss 584462d5250SArun Ramadoss [KSZ9567] = { 585462d5250SArun Ramadoss .chip_id = KSZ9567_CHIP_ID, 586462d5250SArun Ramadoss .dev_name = "KSZ9567", 587462d5250SArun Ramadoss .num_vlans = 4096, 588462d5250SArun Ramadoss .num_alus = 4096, 589462d5250SArun Ramadoss .num_statics = 16, 590462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 591462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 5926ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 593462d5250SArun Ramadoss .phy_errata_9477 = true, 594a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 595a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 596a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 5976877102fSArun Ramadoss .regs = ksz9477_regs, 598457c182aSArun Ramadoss .masks = ksz9477_masks, 599457c182aSArun Ramadoss .shifts = ksz9477_shifts, 600*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 60146f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 60265ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 60365ac79e1SArun Ramadoss false, true, true}, 60465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 60565ac79e1SArun Ramadoss false, true, true}, 60665ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 60765ac79e1SArun Ramadoss false, true, true}, 60865ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 60965ac79e1SArun Ramadoss true, false, false}, 610462d5250SArun Ramadoss }, 611462d5250SArun Ramadoss 612462d5250SArun Ramadoss [LAN9370] = { 613462d5250SArun Ramadoss .chip_id = LAN9370_CHIP_ID, 614462d5250SArun Ramadoss .dev_name = "LAN9370", 615462d5250SArun Ramadoss .num_vlans = 4096, 616462d5250SArun Ramadoss .num_alus = 1024, 617462d5250SArun Ramadoss .num_statics = 256, 618462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 619462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 62055ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 621a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 622a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 623a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 6246877102fSArun Ramadoss .regs = ksz9477_regs, 625457c182aSArun Ramadoss .masks = lan937x_masks, 626457c182aSArun Ramadoss .shifts = lan937x_shifts, 627*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 62846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 62965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 63065ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 63165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 63265ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 633462d5250SArun Ramadoss }, 634462d5250SArun Ramadoss 635462d5250SArun Ramadoss [LAN9371] = { 636462d5250SArun Ramadoss .chip_id = LAN9371_CHIP_ID, 637462d5250SArun Ramadoss .dev_name = "LAN9371", 638462d5250SArun Ramadoss .num_vlans = 4096, 639462d5250SArun Ramadoss .num_alus = 1024, 640462d5250SArun Ramadoss .num_statics = 256, 641462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 642462d5250SArun Ramadoss .port_cnt = 6, /* total physical port count */ 64355ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 644a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 645a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 646a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 6476877102fSArun Ramadoss .regs = ksz9477_regs, 648457c182aSArun Ramadoss .masks = lan937x_masks, 649457c182aSArun Ramadoss .shifts = lan937x_shifts, 650*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 65146f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 65265ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true, true}, 65365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true, true}, 65465ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true, true}, 65565ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false, false}, 656462d5250SArun Ramadoss }, 657462d5250SArun Ramadoss 658462d5250SArun Ramadoss [LAN9372] = { 659462d5250SArun Ramadoss .chip_id = LAN9372_CHIP_ID, 660462d5250SArun Ramadoss .dev_name = "LAN9372", 661462d5250SArun Ramadoss .num_vlans = 4096, 662462d5250SArun Ramadoss .num_alus = 1024, 663462d5250SArun Ramadoss .num_statics = 256, 664462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 665462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 66655ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 667a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 668a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 669a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 6706877102fSArun Ramadoss .regs = ksz9477_regs, 671457c182aSArun Ramadoss .masks = lan937x_masks, 672457c182aSArun Ramadoss .shifts = lan937x_shifts, 673*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 67446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 67565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 67665ac79e1SArun Ramadoss true, true, false, false}, 67765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 67865ac79e1SArun Ramadoss true, true, false, false}, 67965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 68065ac79e1SArun Ramadoss true, true, false, false}, 68165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 68265ac79e1SArun Ramadoss false, false, true, true}, 683462d5250SArun Ramadoss }, 684462d5250SArun Ramadoss 685462d5250SArun Ramadoss [LAN9373] = { 686462d5250SArun Ramadoss .chip_id = LAN9373_CHIP_ID, 687462d5250SArun Ramadoss .dev_name = "LAN9373", 688462d5250SArun Ramadoss .num_vlans = 4096, 689462d5250SArun Ramadoss .num_alus = 1024, 690462d5250SArun Ramadoss .num_statics = 256, 691462d5250SArun Ramadoss .cpu_ports = 0x38, /* can be configured as cpu port */ 692462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 69355ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 694a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 695a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 696a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 6976877102fSArun Ramadoss .regs = ksz9477_regs, 698457c182aSArun Ramadoss .masks = lan937x_masks, 699457c182aSArun Ramadoss .shifts = lan937x_shifts, 700*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 70146f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 70265ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 70365ac79e1SArun Ramadoss true, true, false, false}, 70465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 70565ac79e1SArun Ramadoss true, true, false, false}, 70665ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 70765ac79e1SArun Ramadoss true, true, false, false}, 70865ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, 70965ac79e1SArun Ramadoss false, false, true, true}, 710462d5250SArun Ramadoss }, 711462d5250SArun Ramadoss 712462d5250SArun Ramadoss [LAN9374] = { 713462d5250SArun Ramadoss .chip_id = LAN9374_CHIP_ID, 714462d5250SArun Ramadoss .dev_name = "LAN9374", 715462d5250SArun Ramadoss .num_vlans = 4096, 716462d5250SArun Ramadoss .num_alus = 1024, 717462d5250SArun Ramadoss .num_statics = 256, 718462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 719462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 72055ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 721a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 722a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 723a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 7246877102fSArun Ramadoss .regs = ksz9477_regs, 725457c182aSArun Ramadoss .masks = lan937x_masks, 726457c182aSArun Ramadoss .shifts = lan937x_shifts, 727*aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 72846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 72965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 73065ac79e1SArun Ramadoss true, true, false, false}, 73165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 73265ac79e1SArun Ramadoss true, true, false, false}, 73365ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 73465ac79e1SArun Ramadoss true, true, false, false}, 73565ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 73665ac79e1SArun Ramadoss false, false, true, true}, 737462d5250SArun Ramadoss }, 738462d5250SArun Ramadoss }; 739eee16b14SArun Ramadoss EXPORT_SYMBOL_GPL(ksz_switch_chips); 740462d5250SArun Ramadoss 741462d5250SArun Ramadoss static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num) 742462d5250SArun Ramadoss { 743462d5250SArun Ramadoss int i; 744462d5250SArun Ramadoss 745462d5250SArun Ramadoss for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) { 746462d5250SArun Ramadoss const struct ksz_chip_data *chip = &ksz_switch_chips[i]; 747462d5250SArun Ramadoss 748462d5250SArun Ramadoss if (chip->chip_id == prod_num) 749462d5250SArun Ramadoss return chip; 750462d5250SArun Ramadoss } 751462d5250SArun Ramadoss 752462d5250SArun Ramadoss return NULL; 753462d5250SArun Ramadoss } 754462d5250SArun Ramadoss 755eee16b14SArun Ramadoss static int ksz_check_device_id(struct ksz_device *dev) 756eee16b14SArun Ramadoss { 757eee16b14SArun Ramadoss const struct ksz_chip_data *dt_chip_data; 758eee16b14SArun Ramadoss 759eee16b14SArun Ramadoss dt_chip_data = of_device_get_match_data(dev->dev); 760eee16b14SArun Ramadoss 761eee16b14SArun Ramadoss /* Check for Device Tree and Chip ID */ 762eee16b14SArun Ramadoss if (dt_chip_data->chip_id != dev->chip_id) { 763eee16b14SArun Ramadoss dev_err(dev->dev, 764eee16b14SArun Ramadoss "Device tree specifies chip %s but found %s, please fix it!\n", 765eee16b14SArun Ramadoss dt_chip_data->dev_name, dev->info->dev_name); 766eee16b14SArun Ramadoss return -ENODEV; 767eee16b14SArun Ramadoss } 768eee16b14SArun Ramadoss 769eee16b14SArun Ramadoss return 0; 770eee16b14SArun Ramadoss } 771eee16b14SArun Ramadoss 7721958eee8SArun Ramadoss static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, 77365ac79e1SArun Ramadoss struct phylink_config *config) 77465ac79e1SArun Ramadoss { 77565ac79e1SArun Ramadoss struct ksz_device *dev = ds->priv; 77665ac79e1SArun Ramadoss 77765ac79e1SArun Ramadoss config->legacy_pre_march2020 = false; 77865ac79e1SArun Ramadoss 77965ac79e1SArun Ramadoss if (dev->info->supports_mii[port]) 78065ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); 78165ac79e1SArun Ramadoss 78265ac79e1SArun Ramadoss if (dev->info->supports_rmii[port]) 78365ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_RMII, 78465ac79e1SArun Ramadoss config->supported_interfaces); 78565ac79e1SArun Ramadoss 78665ac79e1SArun Ramadoss if (dev->info->supports_rgmii[port]) 78765ac79e1SArun Ramadoss phy_interface_set_rgmii(config->supported_interfaces); 78865ac79e1SArun Ramadoss 78965ac79e1SArun Ramadoss if (dev->info->internal_phy[port]) 79065ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_INTERNAL, 79165ac79e1SArun Ramadoss config->supported_interfaces); 7927012033cSArun Ramadoss 7937012033cSArun Ramadoss if (dev->dev_ops->get_caps) 7947012033cSArun Ramadoss dev->dev_ops->get_caps(dev, port, config); 79565ac79e1SArun Ramadoss } 79665ac79e1SArun Ramadoss 797c6101dd7SArun Ramadoss void ksz_r_mib_stats64(struct ksz_device *dev, int port) 798c6101dd7SArun Ramadoss { 799c4748ff6SOleksij Rempel struct ethtool_pause_stats *pstats; 800c6101dd7SArun Ramadoss struct rtnl_link_stats64 *stats; 801c6101dd7SArun Ramadoss struct ksz_stats_raw *raw; 802c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 803c6101dd7SArun Ramadoss 804c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 805c6101dd7SArun Ramadoss stats = &mib->stats64; 806c4748ff6SOleksij Rempel pstats = &mib->pause_stats; 807c6101dd7SArun Ramadoss raw = (struct ksz_stats_raw *)mib->counters; 808c6101dd7SArun Ramadoss 809c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 810c6101dd7SArun Ramadoss 811961d6c70SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 812961d6c70SOleksij Rempel raw->rx_pause; 813961d6c70SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 814961d6c70SOleksij Rempel raw->tx_pause; 815c6101dd7SArun Ramadoss 816c6101dd7SArun Ramadoss /* HW counters are counting bytes + FCS which is not acceptable 817c6101dd7SArun Ramadoss * for rtnl_link_stats64 interface 818c6101dd7SArun Ramadoss */ 819c6101dd7SArun Ramadoss stats->rx_bytes = raw->rx_total - stats->rx_packets * ETH_FCS_LEN; 820c6101dd7SArun Ramadoss stats->tx_bytes = raw->tx_total - stats->tx_packets * ETH_FCS_LEN; 821c6101dd7SArun Ramadoss 822c6101dd7SArun Ramadoss stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 823c6101dd7SArun Ramadoss raw->rx_oversize; 824c6101dd7SArun Ramadoss 825c6101dd7SArun Ramadoss stats->rx_crc_errors = raw->rx_crc_err; 826c6101dd7SArun Ramadoss stats->rx_frame_errors = raw->rx_align_err; 827c6101dd7SArun Ramadoss stats->rx_dropped = raw->rx_discards; 828c6101dd7SArun Ramadoss stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 829c6101dd7SArun Ramadoss stats->rx_frame_errors + stats->rx_dropped; 830c6101dd7SArun Ramadoss 831c6101dd7SArun Ramadoss stats->tx_window_errors = raw->tx_late_col; 832c6101dd7SArun Ramadoss stats->tx_fifo_errors = raw->tx_discards; 833c6101dd7SArun Ramadoss stats->tx_aborted_errors = raw->tx_exc_col; 834c6101dd7SArun Ramadoss stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 835c6101dd7SArun Ramadoss stats->tx_aborted_errors; 836c6101dd7SArun Ramadoss 837c6101dd7SArun Ramadoss stats->multicast = raw->rx_mcast; 838c6101dd7SArun Ramadoss stats->collisions = raw->tx_total_col; 839c6101dd7SArun Ramadoss 840c4748ff6SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 841c4748ff6SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 842c4748ff6SOleksij Rempel 843c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 844c6101dd7SArun Ramadoss } 845c6101dd7SArun Ramadoss 8461958eee8SArun Ramadoss static void ksz_get_stats64(struct dsa_switch *ds, int port, 847c6101dd7SArun Ramadoss struct rtnl_link_stats64 *s) 848c6101dd7SArun Ramadoss { 849c6101dd7SArun Ramadoss struct ksz_device *dev = ds->priv; 850c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 851c6101dd7SArun Ramadoss 852c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 853c6101dd7SArun Ramadoss 854c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 855c6101dd7SArun Ramadoss memcpy(s, &mib->stats64, sizeof(*s)); 856c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 857c6101dd7SArun Ramadoss } 858c6101dd7SArun Ramadoss 859c4748ff6SOleksij Rempel static void ksz_get_pause_stats(struct dsa_switch *ds, int port, 860c4748ff6SOleksij Rempel struct ethtool_pause_stats *pause_stats) 861c4748ff6SOleksij Rempel { 862c4748ff6SOleksij Rempel struct ksz_device *dev = ds->priv; 863c4748ff6SOleksij Rempel struct ksz_port_mib *mib; 864c4748ff6SOleksij Rempel 865c4748ff6SOleksij Rempel mib = &dev->ports[port].mib; 866c4748ff6SOleksij Rempel 867c4748ff6SOleksij Rempel spin_lock(&mib->stats64_lock); 868c4748ff6SOleksij Rempel memcpy(pause_stats, &mib->pause_stats, sizeof(*pause_stats)); 869c4748ff6SOleksij Rempel spin_unlock(&mib->stats64_lock); 870c4748ff6SOleksij Rempel } 871c4748ff6SOleksij Rempel 8721958eee8SArun Ramadoss static void ksz_get_strings(struct dsa_switch *ds, int port, 873997d2126SArun Ramadoss u32 stringset, uint8_t *buf) 874997d2126SArun Ramadoss { 875997d2126SArun Ramadoss struct ksz_device *dev = ds->priv; 876997d2126SArun Ramadoss int i; 877997d2126SArun Ramadoss 878997d2126SArun Ramadoss if (stringset != ETH_SS_STATS) 879997d2126SArun Ramadoss return; 880997d2126SArun Ramadoss 881997d2126SArun Ramadoss for (i = 0; i < dev->info->mib_cnt; i++) { 882997d2126SArun Ramadoss memcpy(buf + i * ETH_GSTRING_LEN, 883997d2126SArun Ramadoss dev->info->mib_names[i].string, ETH_GSTRING_LEN); 884997d2126SArun Ramadoss } 885997d2126SArun Ramadoss } 886997d2126SArun Ramadoss 887e593df51SArun Ramadoss static void ksz_update_port_member(struct ksz_device *dev, int port) 888b987e98eSWoojung Huh { 889b3612ccdSOleksij Rempel struct ksz_port *p = &dev->ports[port]; 890b3612ccdSOleksij Rempel struct dsa_switch *ds = dev->ds; 891b3612ccdSOleksij Rempel u8 port_member = 0, cpu_port; 892b3612ccdSOleksij Rempel const struct dsa_port *dp; 8933d00827aSSvenning Sørensen int i, j; 894b987e98eSWoojung Huh 895b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, port)) 896b3612ccdSOleksij Rempel return; 897b3612ccdSOleksij Rempel 898b3612ccdSOleksij Rempel dp = dsa_to_port(ds, port); 899b3612ccdSOleksij Rempel cpu_port = BIT(dsa_upstream_port(ds, port)); 900b3612ccdSOleksij Rempel 901b3612ccdSOleksij Rempel for (i = 0; i < ds->num_ports; i++) { 902b3612ccdSOleksij Rempel const struct dsa_port *other_dp = dsa_to_port(ds, i); 903b3612ccdSOleksij Rempel struct ksz_port *other_p = &dev->ports[i]; 904b3612ccdSOleksij Rempel u8 val = 0; 905b3612ccdSOleksij Rempel 906b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, i)) 907c2e86691STristram Ha continue; 908b3612ccdSOleksij Rempel if (port == i) 909b3612ccdSOleksij Rempel continue; 91041fb0cf1SVladimir Oltean if (!dsa_port_bridge_same(dp, other_dp)) 911c2e86691STristram Ha continue; 9123d00827aSSvenning Sørensen if (other_p->stp_state != BR_STATE_FORWARDING) 9133d00827aSSvenning Sørensen continue; 914b987e98eSWoojung Huh 9153d00827aSSvenning Sørensen if (p->stp_state == BR_STATE_FORWARDING) { 916b3612ccdSOleksij Rempel val |= BIT(port); 917b3612ccdSOleksij Rempel port_member |= BIT(i); 918b987e98eSWoojung Huh } 919b3612ccdSOleksij Rempel 9203d00827aSSvenning Sørensen /* Retain port [i]'s relationship to other ports than [port] */ 9213d00827aSSvenning Sørensen for (j = 0; j < ds->num_ports; j++) { 9223d00827aSSvenning Sørensen const struct dsa_port *third_dp; 9233d00827aSSvenning Sørensen struct ksz_port *third_p; 9243d00827aSSvenning Sørensen 9253d00827aSSvenning Sørensen if (j == i) 9263d00827aSSvenning Sørensen continue; 9273d00827aSSvenning Sørensen if (j == port) 9283d00827aSSvenning Sørensen continue; 9293d00827aSSvenning Sørensen if (!dsa_is_user_port(ds, j)) 9303d00827aSSvenning Sørensen continue; 9313d00827aSSvenning Sørensen third_p = &dev->ports[j]; 9323d00827aSSvenning Sørensen if (third_p->stp_state != BR_STATE_FORWARDING) 9333d00827aSSvenning Sørensen continue; 9343d00827aSSvenning Sørensen third_dp = dsa_to_port(ds, j); 9353d00827aSSvenning Sørensen if (dsa_port_bridge_same(other_dp, third_dp)) 9363d00827aSSvenning Sørensen val |= BIT(j); 9373d00827aSSvenning Sørensen } 9383d00827aSSvenning Sørensen 939b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); 940b3612ccdSOleksij Rempel } 941b3612ccdSOleksij Rempel 942b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); 943b987e98eSWoojung Huh } 944b987e98eSWoojung Huh 9451958eee8SArun Ramadoss static int ksz_setup(struct dsa_switch *ds) 946d2822e68SArun Ramadoss { 947d2822e68SArun Ramadoss struct ksz_device *dev = ds->priv; 9489d95329cSArun Ramadoss const u16 *regs; 949d2822e68SArun Ramadoss int ret; 950d2822e68SArun Ramadoss 9519d95329cSArun Ramadoss regs = dev->info->regs; 9529d95329cSArun Ramadoss 953d2822e68SArun Ramadoss dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), 954d2822e68SArun Ramadoss dev->info->num_vlans, GFP_KERNEL); 955d2822e68SArun Ramadoss if (!dev->vlan_cache) 956d2822e68SArun Ramadoss return -ENOMEM; 957d2822e68SArun Ramadoss 958d2822e68SArun Ramadoss ret = dev->dev_ops->reset(dev); 959d2822e68SArun Ramadoss if (ret) { 960d2822e68SArun Ramadoss dev_err(ds->dev, "failed to reset switch\n"); 961d2822e68SArun Ramadoss return ret; 962d2822e68SArun Ramadoss } 963d2822e68SArun Ramadoss 9641ca6437fSArun Ramadoss /* set broadcast storm protection 10% rate */ 9659d95329cSArun Ramadoss regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL], 9661ca6437fSArun Ramadoss BROADCAST_STORM_RATE, 9671ca6437fSArun Ramadoss (BROADCAST_STORM_VALUE * 9681ca6437fSArun Ramadoss BROADCAST_STORM_PROT_RATE) / 100); 9691ca6437fSArun Ramadoss 970d2822e68SArun Ramadoss dev->dev_ops->config_cpu_port(ds); 971d2822e68SArun Ramadoss 972d2822e68SArun Ramadoss dev->dev_ops->enable_stp_addr(dev); 973d2822e68SArun Ramadoss 9749d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], 9750abab9f3SArun Ramadoss MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); 9760abab9f3SArun Ramadoss 977d2822e68SArun Ramadoss ksz_init_mib_timer(dev); 978d2822e68SArun Ramadoss 979d2822e68SArun Ramadoss ds->configure_vlan_while_not_filtering = false; 980d2822e68SArun Ramadoss 981d2822e68SArun Ramadoss if (dev->dev_ops->setup) { 982d2822e68SArun Ramadoss ret = dev->dev_ops->setup(ds); 983d2822e68SArun Ramadoss if (ret) 984d2822e68SArun Ramadoss return ret; 985d2822e68SArun Ramadoss } 986d2822e68SArun Ramadoss 987ad08ac18SArun Ramadoss /* start switch */ 9889d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_START_CTRL], 989ad08ac18SArun Ramadoss SW_START, SW_START); 990ad08ac18SArun Ramadoss 991d2822e68SArun Ramadoss return 0; 992d2822e68SArun Ramadoss } 993d2822e68SArun Ramadoss 9947c6ff470STristram Ha static void port_r_cnt(struct ksz_device *dev, int port) 9957c6ff470STristram Ha { 9967c6ff470STristram Ha struct ksz_port_mib *mib = &dev->ports[port].mib; 9977c6ff470STristram Ha u64 *dropped; 9987c6ff470STristram Ha 9997c6ff470STristram Ha /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ 1000a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->reg_mib_cnt) { 10017c6ff470STristram Ha dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, 10027c6ff470STristram Ha &mib->counters[mib->cnt_ptr]); 10037c6ff470STristram Ha ++mib->cnt_ptr; 10047c6ff470STristram Ha } 10057c6ff470STristram Ha 10067c6ff470STristram Ha /* last one in storage */ 1007a530e6f2SArun Ramadoss dropped = &mib->counters[dev->info->mib_cnt]; 10087c6ff470STristram Ha 10097c6ff470STristram Ha /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ 1010a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->mib_cnt) { 10117c6ff470STristram Ha dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, 10127c6ff470STristram Ha dropped, &mib->counters[mib->cnt_ptr]); 10137c6ff470STristram Ha ++mib->cnt_ptr; 10147c6ff470STristram Ha } 10157c6ff470STristram Ha mib->cnt_ptr = 0; 10167c6ff470STristram Ha } 10177c6ff470STristram Ha 10187c6ff470STristram Ha static void ksz_mib_read_work(struct work_struct *work) 10197c6ff470STristram Ha { 10207c6ff470STristram Ha struct ksz_device *dev = container_of(work, struct ksz_device, 1021469b390eSGeorge McCollister mib_read.work); 10227c6ff470STristram Ha struct ksz_port_mib *mib; 10237c6ff470STristram Ha struct ksz_port *p; 10247c6ff470STristram Ha int i; 10257c6ff470STristram Ha 1026462d5250SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 10276bb9e376SRobert Hancock if (dsa_is_unused_port(dev->ds, i)) 10286bb9e376SRobert Hancock continue; 10296bb9e376SRobert Hancock 10307c6ff470STristram Ha p = &dev->ports[i]; 10317c6ff470STristram Ha mib = &p->mib; 10327c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 10337c6ff470STristram Ha 10347c6ff470STristram Ha /* Only read MIB counters when the port is told to do. 10357c6ff470STristram Ha * If not, read only dropped counters when link is not up. 10367c6ff470STristram Ha */ 10377c6ff470STristram Ha if (!p->read) { 10387c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(dev->ds, i); 10397c6ff470STristram Ha 10407c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 1041a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 10427c6ff470STristram Ha } 10437c6ff470STristram Ha port_r_cnt(dev, i); 10447c6ff470STristram Ha p->read = false; 1045a7f4f13aSOleksij Rempel 1046a7f4f13aSOleksij Rempel if (dev->dev_ops->r_mib_stat64) 1047a7f4f13aSOleksij Rempel dev->dev_ops->r_mib_stat64(dev, i); 1048a7f4f13aSOleksij Rempel 10497c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 10507c6ff470STristram Ha } 10517c6ff470STristram Ha 1052469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, dev->mib_read_interval); 10537c6ff470STristram Ha } 10547c6ff470STristram Ha 10557c6ff470STristram Ha void ksz_init_mib_timer(struct ksz_device *dev) 10567c6ff470STristram Ha { 10577c6ff470STristram Ha int i; 10587c6ff470STristram Ha 1059469b390eSGeorge McCollister INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work); 1060469b390eSGeorge McCollister 1061b094c679SPrasanna Vengateshan for (i = 0; i < dev->info->port_cnt; i++) { 1062b094c679SPrasanna Vengateshan struct ksz_port_mib *mib = &dev->ports[i].mib; 1063b094c679SPrasanna Vengateshan 10647c6ff470STristram Ha dev->dev_ops->port_init_cnt(dev, i); 1065b094c679SPrasanna Vengateshan 1066b094c679SPrasanna Vengateshan mib->cnt_ptr = 0; 1067b094c679SPrasanna Vengateshan memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64)); 1068b094c679SPrasanna Vengateshan } 10697c6ff470STristram Ha } 10707c6ff470STristram Ha 10711958eee8SArun Ramadoss static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) 1072b987e98eSWoojung Huh { 1073b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1074c2e86691STristram Ha u16 val = 0xffff; 1075b987e98eSWoojung Huh 1076c2e86691STristram Ha dev->dev_ops->r_phy(dev, addr, reg, &val); 1077b987e98eSWoojung Huh 1078b987e98eSWoojung Huh return val; 1079b987e98eSWoojung Huh } 1080b987e98eSWoojung Huh 10811958eee8SArun Ramadoss static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) 1082b987e98eSWoojung Huh { 1083b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1084b987e98eSWoojung Huh 1085c2e86691STristram Ha dev->dev_ops->w_phy(dev, addr, reg, val); 1086b987e98eSWoojung Huh 1087b987e98eSWoojung Huh return 0; 1088b987e98eSWoojung Huh } 1089b987e98eSWoojung Huh 10901958eee8SArun Ramadoss static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) 10911fe94f54SArun Ramadoss { 10921fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 10931fe94f54SArun Ramadoss 10941fe94f54SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID) { 10951fe94f54SArun Ramadoss /* Silicon Errata Sheet (DS80000830A): 10961fe94f54SArun Ramadoss * Port 1 does not work with LinkMD Cable-Testing. 10971fe94f54SArun Ramadoss * Port 1 does not respond to received PAUSE control frames. 10981fe94f54SArun Ramadoss */ 10991fe94f54SArun Ramadoss if (!port) 11001fe94f54SArun Ramadoss return MICREL_KSZ8_P1_ERRATA; 11011fe94f54SArun Ramadoss } 11021fe94f54SArun Ramadoss 11031fe94f54SArun Ramadoss return 0; 11041fe94f54SArun Ramadoss } 11051fe94f54SArun Ramadoss 11061958eee8SArun Ramadoss static void ksz_mac_link_down(struct dsa_switch *ds, int port, 11071958eee8SArun Ramadoss unsigned int mode, phy_interface_t interface) 1108c30d894bSTristram Ha { 1109c30d894bSTristram Ha struct ksz_device *dev = ds->priv; 1110c30d894bSTristram Ha struct ksz_port *p = &dev->ports[port]; 1111c30d894bSTristram Ha 1112c30d894bSTristram Ha /* Read all MIB counters when the link is going down. */ 1113c30d894bSTristram Ha p->read = true; 11148098bd69SChristian Eggers /* timer started */ 11158098bd69SChristian Eggers if (dev->mib_read_interval) 1116469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, 0); 1117143a102eSCodrin Ciubotariu } 1118143a102eSCodrin Ciubotariu 11191958eee8SArun Ramadoss static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) 1120b987e98eSWoojung Huh { 1121b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1122b987e98eSWoojung Huh 112389f09048SFlorian Fainelli if (sset != ETH_SS_STATS) 112489f09048SFlorian Fainelli return 0; 112589f09048SFlorian Fainelli 1126a530e6f2SArun Ramadoss return dev->info->mib_cnt; 1127b987e98eSWoojung Huh } 1128b987e98eSWoojung Huh 11291958eee8SArun Ramadoss static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, 11301958eee8SArun Ramadoss uint64_t *buf) 11317c6ff470STristram Ha { 11327c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(ds, port); 11337c6ff470STristram Ha struct ksz_device *dev = ds->priv; 11347c6ff470STristram Ha struct ksz_port_mib *mib; 11357c6ff470STristram Ha 11367c6ff470STristram Ha mib = &dev->ports[port].mib; 11377c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 11387c6ff470STristram Ha 11397c6ff470STristram Ha /* Only read dropped counters if no link. */ 11407c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 1141a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 11427c6ff470STristram Ha port_r_cnt(dev, port); 1143a530e6f2SArun Ramadoss memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64)); 11447c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 11457c6ff470STristram Ha } 11467c6ff470STristram Ha 11471958eee8SArun Ramadoss static int ksz_port_bridge_join(struct dsa_switch *ds, int port, 1148b079922bSVladimir Oltean struct dsa_bridge bridge, 114906b9cce4SVladimir Oltean bool *tx_fwd_offload, 115006b9cce4SVladimir Oltean struct netlink_ext_ack *extack) 1151b987e98eSWoojung Huh { 1152c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 1153c2e86691STristram Ha * appropriate state so there is no need to do anything. 1154c2e86691STristram Ha */ 1155b987e98eSWoojung Huh 1156b987e98eSWoojung Huh return 0; 1157b987e98eSWoojung Huh } 1158b987e98eSWoojung Huh 11591958eee8SArun Ramadoss static void ksz_port_bridge_leave(struct dsa_switch *ds, int port, 1160d3eed0e5SVladimir Oltean struct dsa_bridge bridge) 1161c2e86691STristram Ha { 1162c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 1163c2e86691STristram Ha * forwarding state so there is no need to do anything. 1164c2e86691STristram Ha */ 1165c2e86691STristram Ha } 1166c2e86691STristram Ha 11671958eee8SArun Ramadoss static void ksz_port_fast_age(struct dsa_switch *ds, int port) 1168c2e86691STristram Ha { 1169c2e86691STristram Ha struct ksz_device *dev = ds->priv; 1170c2e86691STristram Ha 1171c2e86691STristram Ha dev->dev_ops->flush_dyn_mac_table(dev, port); 1172c2e86691STristram Ha } 1173c2e86691STristram Ha 11741958eee8SArun Ramadoss static int ksz_port_fdb_add(struct dsa_switch *ds, int port, 11751958eee8SArun Ramadoss const unsigned char *addr, u16 vid, 11761958eee8SArun Ramadoss struct dsa_db db) 1177e587be75SArun Ramadoss { 1178e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 1179e587be75SArun Ramadoss 1180e587be75SArun Ramadoss if (!dev->dev_ops->fdb_add) 1181e587be75SArun Ramadoss return -EOPNOTSUPP; 1182e587be75SArun Ramadoss 1183e587be75SArun Ramadoss return dev->dev_ops->fdb_add(dev, port, addr, vid, db); 1184e587be75SArun Ramadoss } 1185e587be75SArun Ramadoss 11861958eee8SArun Ramadoss static int ksz_port_fdb_del(struct dsa_switch *ds, int port, 11871958eee8SArun Ramadoss const unsigned char *addr, 11881958eee8SArun Ramadoss u16 vid, struct dsa_db db) 1189e587be75SArun Ramadoss { 1190e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 1191e587be75SArun Ramadoss 1192e587be75SArun Ramadoss if (!dev->dev_ops->fdb_del) 1193e587be75SArun Ramadoss return -EOPNOTSUPP; 1194e587be75SArun Ramadoss 1195e587be75SArun Ramadoss return dev->dev_ops->fdb_del(dev, port, addr, vid, db); 1196e587be75SArun Ramadoss } 1197e587be75SArun Ramadoss 11981958eee8SArun Ramadoss static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, 11991958eee8SArun Ramadoss dsa_fdb_dump_cb_t *cb, void *data) 1200b987e98eSWoojung Huh { 1201b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1202b987e98eSWoojung Huh 1203e587be75SArun Ramadoss if (!dev->dev_ops->fdb_dump) 1204e587be75SArun Ramadoss return -EOPNOTSUPP; 1205b987e98eSWoojung Huh 1206e587be75SArun Ramadoss return dev->dev_ops->fdb_dump(dev, port, cb, data); 1207b987e98eSWoojung Huh } 1208b987e98eSWoojung Huh 12091958eee8SArun Ramadoss static int ksz_port_mdb_add(struct dsa_switch *ds, int port, 1210c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 1211c2693363SVladimir Oltean struct dsa_db db) 1212b987e98eSWoojung Huh { 1213b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1214b987e98eSWoojung Huh 1215980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_add) 1216980c7d17SArun Ramadoss return -EOPNOTSUPP; 1217b987e98eSWoojung Huh 1218980c7d17SArun Ramadoss return dev->dev_ops->mdb_add(dev, port, mdb, db); 1219c2e86691STristram Ha } 1220c2e86691STristram Ha 12211958eee8SArun Ramadoss static int ksz_port_mdb_del(struct dsa_switch *ds, int port, 1222c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 1223c2693363SVladimir Oltean struct dsa_db db) 1224c2e86691STristram Ha { 1225c2e86691STristram Ha struct ksz_device *dev = ds->priv; 1226b987e98eSWoojung Huh 1227980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_del) 1228980c7d17SArun Ramadoss return -EOPNOTSUPP; 1229b987e98eSWoojung Huh 1230980c7d17SArun Ramadoss return dev->dev_ops->mdb_del(dev, port, mdb, db); 1231b987e98eSWoojung Huh } 1232b987e98eSWoojung Huh 12331958eee8SArun Ramadoss static int ksz_enable_port(struct dsa_switch *ds, int port, 12341958eee8SArun Ramadoss struct phy_device *phy) 1235b987e98eSWoojung Huh { 1236b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 1237b987e98eSWoojung Huh 123874be4babSVivien Didelot if (!dsa_is_user_port(ds, port)) 123974be4babSVivien Didelot return 0; 124074be4babSVivien Didelot 1241c2e86691STristram Ha /* setup slave port */ 1242c2e86691STristram Ha dev->dev_ops->port_setup(dev, port, false); 1243b987e98eSWoojung Huh 1244c2e86691STristram Ha /* port_stp_state_set() will be called after to enable the port so 1245c2e86691STristram Ha * there is no need to do anything. 1246c2e86691STristram Ha */ 1247b987e98eSWoojung Huh 1248b987e98eSWoojung Huh return 0; 1249b987e98eSWoojung Huh } 1250b987e98eSWoojung Huh 1251e593df51SArun Ramadoss void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) 1252de6dd626SArun Ramadoss { 1253de6dd626SArun Ramadoss struct ksz_device *dev = ds->priv; 1254de6dd626SArun Ramadoss struct ksz_port *p; 12556877102fSArun Ramadoss const u16 *regs; 1256de6dd626SArun Ramadoss u8 data; 1257e593df51SArun Ramadoss 12586877102fSArun Ramadoss regs = dev->info->regs; 1259de6dd626SArun Ramadoss 12606877102fSArun Ramadoss ksz_pread8(dev, port, regs[P_STP_CTRL], &data); 1261de6dd626SArun Ramadoss data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); 1262de6dd626SArun Ramadoss 1263de6dd626SArun Ramadoss switch (state) { 1264de6dd626SArun Ramadoss case BR_STATE_DISABLED: 1265de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 1266de6dd626SArun Ramadoss break; 1267de6dd626SArun Ramadoss case BR_STATE_LISTENING: 1268de6dd626SArun Ramadoss data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); 1269de6dd626SArun Ramadoss break; 1270de6dd626SArun Ramadoss case BR_STATE_LEARNING: 1271de6dd626SArun Ramadoss data |= PORT_RX_ENABLE; 1272de6dd626SArun Ramadoss break; 1273de6dd626SArun Ramadoss case BR_STATE_FORWARDING: 1274de6dd626SArun Ramadoss data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); 1275de6dd626SArun Ramadoss break; 1276de6dd626SArun Ramadoss case BR_STATE_BLOCKING: 1277de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 1278de6dd626SArun Ramadoss break; 1279de6dd626SArun Ramadoss default: 1280de6dd626SArun Ramadoss dev_err(ds->dev, "invalid STP state: %d\n", state); 1281de6dd626SArun Ramadoss return; 1282de6dd626SArun Ramadoss } 1283de6dd626SArun Ramadoss 12846877102fSArun Ramadoss ksz_pwrite8(dev, port, regs[P_STP_CTRL], data); 1285de6dd626SArun Ramadoss 1286de6dd626SArun Ramadoss p = &dev->ports[port]; 1287de6dd626SArun Ramadoss p->stp_state = state; 1288de6dd626SArun Ramadoss 1289de6dd626SArun Ramadoss ksz_update_port_member(dev, port); 1290de6dd626SArun Ramadoss } 1291de6dd626SArun Ramadoss 12921958eee8SArun Ramadoss static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, 12931958eee8SArun Ramadoss int port, 12941958eee8SArun Ramadoss enum dsa_tag_protocol mp) 1295534a0431SArun Ramadoss { 1296534a0431SArun Ramadoss struct ksz_device *dev = ds->priv; 1297534a0431SArun Ramadoss enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; 1298534a0431SArun Ramadoss 1299534a0431SArun Ramadoss if (dev->chip_id == KSZ8795_CHIP_ID || 1300534a0431SArun Ramadoss dev->chip_id == KSZ8794_CHIP_ID || 1301534a0431SArun Ramadoss dev->chip_id == KSZ8765_CHIP_ID) 1302534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ8795; 1303534a0431SArun Ramadoss 1304534a0431SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID || 1305534a0431SArun Ramadoss dev->chip_id == KSZ9893_CHIP_ID) 1306534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9893; 1307534a0431SArun Ramadoss 1308534a0431SArun Ramadoss if (dev->chip_id == KSZ9477_CHIP_ID || 1309534a0431SArun Ramadoss dev->chip_id == KSZ9897_CHIP_ID || 1310534a0431SArun Ramadoss dev->chip_id == KSZ9567_CHIP_ID) 1311534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9477; 1312534a0431SArun Ramadoss 131399b16df0SArun Ramadoss if (is_lan937x(dev)) 131499b16df0SArun Ramadoss proto = DSA_TAG_PROTO_LAN937X_VALUE; 131599b16df0SArun Ramadoss 1316534a0431SArun Ramadoss return proto; 1317534a0431SArun Ramadoss } 1318534a0431SArun Ramadoss 13191958eee8SArun Ramadoss static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, 1320f0d997e3SArun Ramadoss bool flag, struct netlink_ext_ack *extack) 1321f0d997e3SArun Ramadoss { 1322f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 1323f0d997e3SArun Ramadoss 1324f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_filtering) 1325f0d997e3SArun Ramadoss return -EOPNOTSUPP; 1326f0d997e3SArun Ramadoss 1327f0d997e3SArun Ramadoss return dev->dev_ops->vlan_filtering(dev, port, flag, extack); 1328f0d997e3SArun Ramadoss } 1329f0d997e3SArun Ramadoss 13301958eee8SArun Ramadoss static int ksz_port_vlan_add(struct dsa_switch *ds, int port, 1331f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan, 1332f0d997e3SArun Ramadoss struct netlink_ext_ack *extack) 1333f0d997e3SArun Ramadoss { 1334f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 1335f0d997e3SArun Ramadoss 1336f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_add) 1337f0d997e3SArun Ramadoss return -EOPNOTSUPP; 1338f0d997e3SArun Ramadoss 1339f0d997e3SArun Ramadoss return dev->dev_ops->vlan_add(dev, port, vlan, extack); 1340f0d997e3SArun Ramadoss } 1341f0d997e3SArun Ramadoss 13421958eee8SArun Ramadoss static int ksz_port_vlan_del(struct dsa_switch *ds, int port, 1343f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan) 1344f0d997e3SArun Ramadoss { 1345f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 1346f0d997e3SArun Ramadoss 1347f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_del) 1348f0d997e3SArun Ramadoss return -EOPNOTSUPP; 1349f0d997e3SArun Ramadoss 1350f0d997e3SArun Ramadoss return dev->dev_ops->vlan_del(dev, port, vlan); 1351f0d997e3SArun Ramadoss } 1352f0d997e3SArun Ramadoss 13531958eee8SArun Ramadoss static int ksz_port_mirror_add(struct dsa_switch *ds, int port, 135400a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror, 135500a298bbSArun Ramadoss bool ingress, struct netlink_ext_ack *extack) 135600a298bbSArun Ramadoss { 135700a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 135800a298bbSArun Ramadoss 135900a298bbSArun Ramadoss if (!dev->dev_ops->mirror_add) 136000a298bbSArun Ramadoss return -EOPNOTSUPP; 136100a298bbSArun Ramadoss 136200a298bbSArun Ramadoss return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack); 136300a298bbSArun Ramadoss } 136400a298bbSArun Ramadoss 13651958eee8SArun Ramadoss static void ksz_port_mirror_del(struct dsa_switch *ds, int port, 136600a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror) 136700a298bbSArun Ramadoss { 136800a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 136900a298bbSArun Ramadoss 137000a298bbSArun Ramadoss if (dev->dev_ops->mirror_del) 137100a298bbSArun Ramadoss dev->dev_ops->mirror_del(dev, port, mirror); 137200a298bbSArun Ramadoss } 137300a298bbSArun Ramadoss 13741958eee8SArun Ramadoss static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) 13751fe94f54SArun Ramadoss { 13761fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 13771fe94f54SArun Ramadoss 13781fe94f54SArun Ramadoss if (!dev->dev_ops->change_mtu) 13791fe94f54SArun Ramadoss return -EOPNOTSUPP; 13801fe94f54SArun Ramadoss 13811fe94f54SArun Ramadoss return dev->dev_ops->change_mtu(dev, port, mtu); 13821fe94f54SArun Ramadoss } 13831fe94f54SArun Ramadoss 13841958eee8SArun Ramadoss static int ksz_max_mtu(struct dsa_switch *ds, int port) 13851fe94f54SArun Ramadoss { 13861fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 13871fe94f54SArun Ramadoss 13881fe94f54SArun Ramadoss if (!dev->dev_ops->max_mtu) 13891fe94f54SArun Ramadoss return -EOPNOTSUPP; 13901fe94f54SArun Ramadoss 13911fe94f54SArun Ramadoss return dev->dev_ops->max_mtu(dev, port); 13921fe94f54SArun Ramadoss } 13931fe94f54SArun Ramadoss 1394a0cb1aa4SArun Ramadoss static void ksz_phylink_mac_config(struct dsa_switch *ds, int port, 1395a0cb1aa4SArun Ramadoss unsigned int mode, 1396a0cb1aa4SArun Ramadoss const struct phylink_link_state *state) 1397a0cb1aa4SArun Ramadoss { 1398a0cb1aa4SArun Ramadoss struct ksz_device *dev = ds->priv; 1399a0cb1aa4SArun Ramadoss 1400a0cb1aa4SArun Ramadoss if (dev->dev_ops->phylink_mac_config) 1401a0cb1aa4SArun Ramadoss dev->dev_ops->phylink_mac_config(dev, port, mode, state); 1402a0cb1aa4SArun Ramadoss } 1403a0cb1aa4SArun Ramadoss 140446f80fa8SArun Ramadoss bool ksz_get_gbit(struct ksz_device *dev, int port) 140546f80fa8SArun Ramadoss { 140646f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 140746f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 140846f80fa8SArun Ramadoss bool gbit = false; 140946f80fa8SArun Ramadoss u8 data8; 141046f80fa8SArun Ramadoss bool val; 141146f80fa8SArun Ramadoss 141246f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 141346f80fa8SArun Ramadoss 141446f80fa8SArun Ramadoss val = FIELD_GET(P_GMII_1GBIT_M, data8); 141546f80fa8SArun Ramadoss 141646f80fa8SArun Ramadoss if (val == bitval[P_GMII_1GBIT]) 141746f80fa8SArun Ramadoss gbit = true; 141846f80fa8SArun Ramadoss 141946f80fa8SArun Ramadoss return gbit; 142046f80fa8SArun Ramadoss } 142146f80fa8SArun Ramadoss 142246f80fa8SArun Ramadoss void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit) 142346f80fa8SArun Ramadoss { 142446f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 142546f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 142646f80fa8SArun Ramadoss u8 data8; 142746f80fa8SArun Ramadoss 142846f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 142946f80fa8SArun Ramadoss 143046f80fa8SArun Ramadoss data8 &= ~P_GMII_1GBIT_M; 143146f80fa8SArun Ramadoss 143246f80fa8SArun Ramadoss if (gbit) 143346f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); 143446f80fa8SArun Ramadoss else 143546f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); 143646f80fa8SArun Ramadoss 143746f80fa8SArun Ramadoss /* Write the updated value */ 143846f80fa8SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 143946f80fa8SArun Ramadoss } 144046f80fa8SArun Ramadoss 1441*aa5b8b73SArun Ramadoss static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed) 1442*aa5b8b73SArun Ramadoss { 1443*aa5b8b73SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 1444*aa5b8b73SArun Ramadoss const u16 *regs = dev->info->regs; 1445*aa5b8b73SArun Ramadoss u8 data8; 1446*aa5b8b73SArun Ramadoss 1447*aa5b8b73SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); 1448*aa5b8b73SArun Ramadoss 1449*aa5b8b73SArun Ramadoss data8 &= ~P_MII_100MBIT_M; 1450*aa5b8b73SArun Ramadoss 1451*aa5b8b73SArun Ramadoss if (speed == SPEED_100) 1452*aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); 1453*aa5b8b73SArun Ramadoss else 1454*aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); 1455*aa5b8b73SArun Ramadoss 1456*aa5b8b73SArun Ramadoss /* Write the updated value */ 1457*aa5b8b73SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); 1458*aa5b8b73SArun Ramadoss } 1459*aa5b8b73SArun Ramadoss 1460*aa5b8b73SArun Ramadoss void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed) 1461*aa5b8b73SArun Ramadoss { 1462*aa5b8b73SArun Ramadoss if (speed == SPEED_1000) 1463*aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, true); 1464*aa5b8b73SArun Ramadoss else 1465*aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, false); 1466*aa5b8b73SArun Ramadoss 1467*aa5b8b73SArun Ramadoss if (speed == SPEED_100 || speed == SPEED_10) 1468*aa5b8b73SArun Ramadoss ksz_set_100_10mbit(dev, port, speed); 1469*aa5b8b73SArun Ramadoss } 1470*aa5b8b73SArun Ramadoss 1471f597d3adSArun Ramadoss static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port, 1472f597d3adSArun Ramadoss unsigned int mode, 1473f597d3adSArun Ramadoss phy_interface_t interface, 1474f597d3adSArun Ramadoss struct phy_device *phydev, int speed, 1475f597d3adSArun Ramadoss int duplex, bool tx_pause, bool rx_pause) 1476f597d3adSArun Ramadoss { 1477f597d3adSArun Ramadoss struct ksz_device *dev = ds->priv; 1478f597d3adSArun Ramadoss 1479f597d3adSArun Ramadoss if (dev->dev_ops->phylink_mac_link_up) 1480f597d3adSArun Ramadoss dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface, 1481f597d3adSArun Ramadoss phydev, speed, duplex, 1482f597d3adSArun Ramadoss tx_pause, rx_pause); 1483f597d3adSArun Ramadoss } 1484f597d3adSArun Ramadoss 148591a98917SArun Ramadoss static int ksz_switch_detect(struct ksz_device *dev) 148691a98917SArun Ramadoss { 148791a98917SArun Ramadoss u8 id1, id2; 148891a98917SArun Ramadoss u16 id16; 148991a98917SArun Ramadoss u32 id32; 149091a98917SArun Ramadoss int ret; 149191a98917SArun Ramadoss 149291a98917SArun Ramadoss /* read chip id */ 149391a98917SArun Ramadoss ret = ksz_read16(dev, REG_CHIP_ID0, &id16); 149491a98917SArun Ramadoss if (ret) 149591a98917SArun Ramadoss return ret; 149691a98917SArun Ramadoss 149791a98917SArun Ramadoss id1 = FIELD_GET(SW_FAMILY_ID_M, id16); 149891a98917SArun Ramadoss id2 = FIELD_GET(SW_CHIP_ID_M, id16); 149991a98917SArun Ramadoss 150091a98917SArun Ramadoss switch (id1) { 150191a98917SArun Ramadoss case KSZ87_FAMILY_ID: 150291a98917SArun Ramadoss if (id2 == KSZ87_CHIP_ID_95) { 150391a98917SArun Ramadoss u8 val; 150491a98917SArun Ramadoss 150591a98917SArun Ramadoss dev->chip_id = KSZ8795_CHIP_ID; 150691a98917SArun Ramadoss 150791a98917SArun Ramadoss ksz_read8(dev, KSZ8_PORT_STATUS_0, &val); 150891a98917SArun Ramadoss if (val & KSZ8_PORT_FIBER_MODE) 150991a98917SArun Ramadoss dev->chip_id = KSZ8765_CHIP_ID; 151091a98917SArun Ramadoss } else if (id2 == KSZ87_CHIP_ID_94) { 151191a98917SArun Ramadoss dev->chip_id = KSZ8794_CHIP_ID; 151291a98917SArun Ramadoss } else { 151391a98917SArun Ramadoss return -ENODEV; 151491a98917SArun Ramadoss } 151591a98917SArun Ramadoss break; 151691a98917SArun Ramadoss case KSZ88_FAMILY_ID: 151791a98917SArun Ramadoss if (id2 == KSZ88_CHIP_ID_63) 151891a98917SArun Ramadoss dev->chip_id = KSZ8830_CHIP_ID; 151991a98917SArun Ramadoss else 152091a98917SArun Ramadoss return -ENODEV; 152191a98917SArun Ramadoss break; 152291a98917SArun Ramadoss default: 152391a98917SArun Ramadoss ret = ksz_read32(dev, REG_CHIP_ID0, &id32); 152491a98917SArun Ramadoss if (ret) 152591a98917SArun Ramadoss return ret; 152691a98917SArun Ramadoss 152791a98917SArun Ramadoss dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32); 152891a98917SArun Ramadoss id32 &= ~0xFF; 152991a98917SArun Ramadoss 153091a98917SArun Ramadoss switch (id32) { 153191a98917SArun Ramadoss case KSZ9477_CHIP_ID: 153291a98917SArun Ramadoss case KSZ9897_CHIP_ID: 153391a98917SArun Ramadoss case KSZ9893_CHIP_ID: 153491a98917SArun Ramadoss case KSZ9567_CHIP_ID: 153591a98917SArun Ramadoss case LAN9370_CHIP_ID: 153691a98917SArun Ramadoss case LAN9371_CHIP_ID: 153791a98917SArun Ramadoss case LAN9372_CHIP_ID: 153891a98917SArun Ramadoss case LAN9373_CHIP_ID: 153991a98917SArun Ramadoss case LAN9374_CHIP_ID: 154091a98917SArun Ramadoss dev->chip_id = id32; 154191a98917SArun Ramadoss break; 154291a98917SArun Ramadoss default: 154391a98917SArun Ramadoss dev_err(dev->dev, 154491a98917SArun Ramadoss "unsupported switch detected %x)\n", id32); 154591a98917SArun Ramadoss return -ENODEV; 154691a98917SArun Ramadoss } 154791a98917SArun Ramadoss } 154891a98917SArun Ramadoss return 0; 154991a98917SArun Ramadoss } 155091a98917SArun Ramadoss 15511958eee8SArun Ramadoss static const struct dsa_switch_ops ksz_switch_ops = { 15521958eee8SArun Ramadoss .get_tag_protocol = ksz_get_tag_protocol, 15531958eee8SArun Ramadoss .get_phy_flags = ksz_get_phy_flags, 15541958eee8SArun Ramadoss .setup = ksz_setup, 15551958eee8SArun Ramadoss .phy_read = ksz_phy_read16, 15561958eee8SArun Ramadoss .phy_write = ksz_phy_write16, 15571958eee8SArun Ramadoss .phylink_get_caps = ksz_phylink_get_caps, 1558a0cb1aa4SArun Ramadoss .phylink_mac_config = ksz_phylink_mac_config, 1559f597d3adSArun Ramadoss .phylink_mac_link_up = ksz_phylink_mac_link_up, 15601958eee8SArun Ramadoss .phylink_mac_link_down = ksz_mac_link_down, 15611958eee8SArun Ramadoss .port_enable = ksz_enable_port, 15621958eee8SArun Ramadoss .get_strings = ksz_get_strings, 15631958eee8SArun Ramadoss .get_ethtool_stats = ksz_get_ethtool_stats, 15641958eee8SArun Ramadoss .get_sset_count = ksz_sset_count, 15651958eee8SArun Ramadoss .port_bridge_join = ksz_port_bridge_join, 15661958eee8SArun Ramadoss .port_bridge_leave = ksz_port_bridge_leave, 15671958eee8SArun Ramadoss .port_stp_state_set = ksz_port_stp_state_set, 15681958eee8SArun Ramadoss .port_fast_age = ksz_port_fast_age, 15691958eee8SArun Ramadoss .port_vlan_filtering = ksz_port_vlan_filtering, 15701958eee8SArun Ramadoss .port_vlan_add = ksz_port_vlan_add, 15711958eee8SArun Ramadoss .port_vlan_del = ksz_port_vlan_del, 15721958eee8SArun Ramadoss .port_fdb_dump = ksz_port_fdb_dump, 15731958eee8SArun Ramadoss .port_fdb_add = ksz_port_fdb_add, 15741958eee8SArun Ramadoss .port_fdb_del = ksz_port_fdb_del, 15751958eee8SArun Ramadoss .port_mdb_add = ksz_port_mdb_add, 15761958eee8SArun Ramadoss .port_mdb_del = ksz_port_mdb_del, 15771958eee8SArun Ramadoss .port_mirror_add = ksz_port_mirror_add, 15781958eee8SArun Ramadoss .port_mirror_del = ksz_port_mirror_del, 15791958eee8SArun Ramadoss .get_stats64 = ksz_get_stats64, 1580c4748ff6SOleksij Rempel .get_pause_stats = ksz_get_pause_stats, 15811958eee8SArun Ramadoss .port_change_mtu = ksz_change_mtu, 15821958eee8SArun Ramadoss .port_max_mtu = ksz_max_mtu, 15831958eee8SArun Ramadoss }; 15841958eee8SArun Ramadoss 1585ee394feaSMarek Vasut struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) 1586b987e98eSWoojung Huh { 1587b987e98eSWoojung Huh struct dsa_switch *ds; 1588b987e98eSWoojung Huh struct ksz_device *swdev; 1589b987e98eSWoojung Huh 15907e99e347SVivien Didelot ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL); 1591b987e98eSWoojung Huh if (!ds) 1592b987e98eSWoojung Huh return NULL; 1593b987e98eSWoojung Huh 15947e99e347SVivien Didelot ds->dev = base; 15957e99e347SVivien Didelot ds->num_ports = DSA_MAX_PORTS; 15961958eee8SArun Ramadoss ds->ops = &ksz_switch_ops; 15977e99e347SVivien Didelot 1598b987e98eSWoojung Huh swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); 1599b987e98eSWoojung Huh if (!swdev) 1600b987e98eSWoojung Huh return NULL; 1601b987e98eSWoojung Huh 1602b987e98eSWoojung Huh ds->priv = swdev; 1603b987e98eSWoojung Huh swdev->dev = base; 1604b987e98eSWoojung Huh 1605b987e98eSWoojung Huh swdev->ds = ds; 1606b987e98eSWoojung Huh swdev->priv = priv; 1607b987e98eSWoojung Huh 1608b987e98eSWoojung Huh return swdev; 1609b987e98eSWoojung Huh } 1610b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_alloc); 1611b987e98eSWoojung Huh 16126ec23aaaSArun Ramadoss int ksz_switch_register(struct ksz_device *dev) 1613b987e98eSWoojung Huh { 1614462d5250SArun Ramadoss const struct ksz_chip_data *info; 1615912aae27SHelmut Grohne struct device_node *port, *ports; 16160c65b2b9SAndrew Lunn phy_interface_t interface; 1617edecfa98SHelmut Grohne unsigned int port_num; 1618b987e98eSWoojung Huh int ret; 1619198b3478SArun Ramadoss int i; 1620b987e98eSWoojung Huh 1621b987e98eSWoojung Huh if (dev->pdata) 1622b987e98eSWoojung Huh dev->chip_id = dev->pdata->chip_id; 1623b987e98eSWoojung Huh 1624924352c3SMarek Vasut dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset", 1625924352c3SMarek Vasut GPIOD_OUT_LOW); 1626924352c3SMarek Vasut if (IS_ERR(dev->reset_gpio)) 1627924352c3SMarek Vasut return PTR_ERR(dev->reset_gpio); 1628924352c3SMarek Vasut 1629924352c3SMarek Vasut if (dev->reset_gpio) { 163022e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 16315b797980SPaul Barker usleep_range(10000, 12000); 163222e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 0); 16331c45ba93SMarek Vasut msleep(100); 1634924352c3SMarek Vasut } 1635924352c3SMarek Vasut 16367049f9b5STristram Ha mutex_init(&dev->dev_mutex); 1637013572a2SMarek Vasut mutex_init(&dev->regmap_mutex); 1638284fb78eSTristram Ha mutex_init(&dev->alu_mutex); 1639284fb78eSTristram Ha mutex_init(&dev->vlan_mutex); 1640284fb78eSTristram Ha 164191a98917SArun Ramadoss ret = ksz_switch_detect(dev); 164291a98917SArun Ramadoss if (ret) 164391a98917SArun Ramadoss return ret; 1644b987e98eSWoojung Huh 1645462d5250SArun Ramadoss info = ksz_lookup_info(dev->chip_id); 1646462d5250SArun Ramadoss if (!info) 1647462d5250SArun Ramadoss return -ENODEV; 1648462d5250SArun Ramadoss 1649462d5250SArun Ramadoss /* Update the compatible info with the probed one */ 1650462d5250SArun Ramadoss dev->info = info; 1651462d5250SArun Ramadoss 165291a98917SArun Ramadoss dev_info(dev->dev, "found switch: %s, rev %i\n", 165391a98917SArun Ramadoss dev->info->dev_name, dev->chip_rev); 165491a98917SArun Ramadoss 1655eee16b14SArun Ramadoss ret = ksz_check_device_id(dev); 1656eee16b14SArun Ramadoss if (ret) 1657eee16b14SArun Ramadoss return ret; 1658eee16b14SArun Ramadoss 16596ec23aaaSArun Ramadoss dev->dev_ops = dev->info->ops; 166091a98917SArun Ramadoss 1661c2e86691STristram Ha ret = dev->dev_ops->init(dev); 1662b987e98eSWoojung Huh if (ret) 1663b987e98eSWoojung Huh return ret; 1664b987e98eSWoojung Huh 1665198b3478SArun Ramadoss dev->ports = devm_kzalloc(dev->dev, 1666198b3478SArun Ramadoss dev->info->port_cnt * sizeof(struct ksz_port), 1667198b3478SArun Ramadoss GFP_KERNEL); 1668198b3478SArun Ramadoss if (!dev->ports) 1669198b3478SArun Ramadoss return -ENOMEM; 1670198b3478SArun Ramadoss 1671198b3478SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 1672198b3478SArun Ramadoss spin_lock_init(&dev->ports[i].mib.stats64_lock); 1673198b3478SArun Ramadoss mutex_init(&dev->ports[i].mib.cnt_mutex); 1674198b3478SArun Ramadoss dev->ports[i].mib.counters = 1675198b3478SArun Ramadoss devm_kzalloc(dev->dev, 1676198b3478SArun Ramadoss sizeof(u64) * (dev->info->mib_cnt + 1), 1677198b3478SArun Ramadoss GFP_KERNEL); 1678198b3478SArun Ramadoss if (!dev->ports[i].mib.counters) 1679198b3478SArun Ramadoss return -ENOMEM; 1680198b3478SArun Ramadoss } 1681198b3478SArun Ramadoss 1682198b3478SArun Ramadoss /* set the real number of ports */ 1683198b3478SArun Ramadoss dev->ds->num_ports = dev->info->port_cnt; 1684198b3478SArun Ramadoss 16858c29bebbSTristram Ha /* Host port interface will be self detected, or specifically set in 16868c29bebbSTristram Ha * device tree. 16878c29bebbSTristram Ha */ 1688462d5250SArun Ramadoss for (port_num = 0; port_num < dev->info->port_cnt; ++port_num) 1689edecfa98SHelmut Grohne dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA; 1690c2e86691STristram Ha if (dev->dev->of_node) { 16910c65b2b9SAndrew Lunn ret = of_get_phy_mode(dev->dev->of_node, &interface); 16920c65b2b9SAndrew Lunn if (ret == 0) 1693edecfa98SHelmut Grohne dev->compat_interface = interface; 169444e53c88SChristian Eggers ports = of_get_child_by_name(dev->dev->of_node, "ethernet-ports"); 169544e53c88SChristian Eggers if (!ports) 1696912aae27SHelmut Grohne ports = of_get_child_by_name(dev->dev->of_node, "ports"); 1697a14bd747SLiang He if (ports) { 1698912aae27SHelmut Grohne for_each_available_child_of_node(ports, port) { 1699912aae27SHelmut Grohne if (of_property_read_u32(port, "reg", 1700912aae27SHelmut Grohne &port_num)) 1701edecfa98SHelmut Grohne continue; 170284f7e0bbSkernel test robot if (!(dev->port_mask & BIT(port_num))) { 170384f7e0bbSkernel test robot of_node_put(port); 1704a14bd747SLiang He of_node_put(ports); 1705edecfa98SHelmut Grohne return -EINVAL; 170684f7e0bbSkernel test robot } 1707912aae27SHelmut Grohne of_get_phy_mode(port, 1708912aae27SHelmut Grohne &dev->ports[port_num].interface); 1709edecfa98SHelmut Grohne } 1710a14bd747SLiang He of_node_put(ports); 1711a14bd747SLiang He } 171279c8bd15SRobert Hancock dev->synclko_125 = of_property_read_bool(dev->dev->of_node, 171379c8bd15SRobert Hancock "microchip,synclko-125"); 171448bf8b8aSRobert Hancock dev->synclko_disable = of_property_read_bool(dev->dev->of_node, 171548bf8b8aSRobert Hancock "microchip,synclko-disable"); 171648bf8b8aSRobert Hancock if (dev->synclko_125 && dev->synclko_disable) { 171748bf8b8aSRobert Hancock dev_err(dev->dev, "inconsistent synclko settings\n"); 171848bf8b8aSRobert Hancock return -EINVAL; 171948bf8b8aSRobert Hancock } 1720c2e86691STristram Ha } 1721c2e86691STristram Ha 1722c2e86691STristram Ha ret = dsa_register_switch(dev->ds); 1723c2e86691STristram Ha if (ret) { 1724c2e86691STristram Ha dev->dev_ops->exit(dev); 1725c2e86691STristram Ha return ret; 1726c2e86691STristram Ha } 1727c2e86691STristram Ha 17288098bd69SChristian Eggers /* Read MIB counters every 30 seconds to avoid overflow. */ 172912c740c8SOleksij Rempel dev->mib_read_interval = msecs_to_jiffies(5000); 17308098bd69SChristian Eggers 17318098bd69SChristian Eggers /* Start the MIB timer. */ 17328098bd69SChristian Eggers schedule_delayed_work(&dev->mib_read, 0); 17338098bd69SChristian Eggers 17347a8988a1SArun Ramadoss return ret; 1735b987e98eSWoojung Huh } 1736b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_register); 1737b987e98eSWoojung Huh 1738b987e98eSWoojung Huh void ksz_switch_remove(struct ksz_device *dev) 1739b987e98eSWoojung Huh { 17407c6ff470STristram Ha /* timer started */ 1741ef1100efSArun Ramadoss if (dev->mib_read_interval) { 1742ef1100efSArun Ramadoss dev->mib_read_interval = 0; 1743469b390eSGeorge McCollister cancel_delayed_work_sync(&dev->mib_read); 1744ef1100efSArun Ramadoss } 17457c6ff470STristram Ha 1746c2e86691STristram Ha dev->dev_ops->exit(dev); 1747b987e98eSWoojung Huh dsa_unregister_switch(dev->ds); 1748924352c3SMarek Vasut 1749924352c3SMarek Vasut if (dev->reset_gpio) 175022e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 1751924352c3SMarek Vasut 1752b987e98eSWoojung Huh } 1753b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_remove); 1754b987e98eSWoojung Huh 1755b987e98eSWoojung Huh MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 1756b987e98eSWoojung Huh MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver"); 1757b987e98eSWoojung Huh MODULE_LICENSE("GPL"); 1758