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> 17ff319a64SArun Ramadoss #include <linux/irq.h> 18ff319a64SArun Ramadoss #include <linux/irqdomain.h> 19ff319a64SArun Ramadoss #include <linux/of_mdio.h> 20eee16b14SArun Ramadoss #include <linux/of_device.h> 21c2e86691STristram Ha #include <linux/of_net.h> 221fe94f54SArun Ramadoss #include <linux/micrel_phy.h> 23b987e98eSWoojung Huh #include <net/dsa.h> 24b987e98eSWoojung Huh #include <net/switchdev.h> 25b987e98eSWoojung Huh 26ffc60b55SMarek Vasut #include "ksz_common.h" 276ec23aaaSArun Ramadoss #include "ksz8.h" 286ec23aaaSArun Ramadoss #include "ksz9477.h" 2955ab6ffaSArun Ramadoss #include "lan937x.h" 307049f9b5STristram Ha 31a530e6f2SArun Ramadoss #define MIB_COUNTER_NUM 0x20 32a530e6f2SArun Ramadoss 33c6101dd7SArun Ramadoss struct ksz_stats_raw { 34c6101dd7SArun Ramadoss u64 rx_hi; 35c6101dd7SArun Ramadoss u64 rx_undersize; 36c6101dd7SArun Ramadoss u64 rx_fragments; 37c6101dd7SArun Ramadoss u64 rx_oversize; 38c6101dd7SArun Ramadoss u64 rx_jabbers; 39c6101dd7SArun Ramadoss u64 rx_symbol_err; 40c6101dd7SArun Ramadoss u64 rx_crc_err; 41c6101dd7SArun Ramadoss u64 rx_align_err; 42c6101dd7SArun Ramadoss u64 rx_mac_ctrl; 43c6101dd7SArun Ramadoss u64 rx_pause; 44c6101dd7SArun Ramadoss u64 rx_bcast; 45c6101dd7SArun Ramadoss u64 rx_mcast; 46c6101dd7SArun Ramadoss u64 rx_ucast; 47c6101dd7SArun Ramadoss u64 rx_64_or_less; 48c6101dd7SArun Ramadoss u64 rx_65_127; 49c6101dd7SArun Ramadoss u64 rx_128_255; 50c6101dd7SArun Ramadoss u64 rx_256_511; 51c6101dd7SArun Ramadoss u64 rx_512_1023; 52c6101dd7SArun Ramadoss u64 rx_1024_1522; 53c6101dd7SArun Ramadoss u64 rx_1523_2000; 54c6101dd7SArun Ramadoss u64 rx_2001; 55c6101dd7SArun Ramadoss u64 tx_hi; 56c6101dd7SArun Ramadoss u64 tx_late_col; 57c6101dd7SArun Ramadoss u64 tx_pause; 58c6101dd7SArun Ramadoss u64 tx_bcast; 59c6101dd7SArun Ramadoss u64 tx_mcast; 60c6101dd7SArun Ramadoss u64 tx_ucast; 61c6101dd7SArun Ramadoss u64 tx_deferred; 62c6101dd7SArun Ramadoss u64 tx_total_col; 63c6101dd7SArun Ramadoss u64 tx_exc_col; 64c6101dd7SArun Ramadoss u64 tx_single_col; 65c6101dd7SArun Ramadoss u64 tx_mult_col; 66c6101dd7SArun Ramadoss u64 rx_total; 67c6101dd7SArun Ramadoss u64 tx_total; 68c6101dd7SArun Ramadoss u64 rx_discards; 69c6101dd7SArun Ramadoss u64 tx_discards; 70c6101dd7SArun Ramadoss }; 71c6101dd7SArun Ramadoss 72a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz88xx_mib_names[] = { 73a530e6f2SArun Ramadoss { 0x00, "rx" }, 74a530e6f2SArun Ramadoss { 0x01, "rx_hi" }, 75a530e6f2SArun Ramadoss { 0x02, "rx_undersize" }, 76a530e6f2SArun Ramadoss { 0x03, "rx_fragments" }, 77a530e6f2SArun Ramadoss { 0x04, "rx_oversize" }, 78a530e6f2SArun Ramadoss { 0x05, "rx_jabbers" }, 79a530e6f2SArun Ramadoss { 0x06, "rx_symbol_err" }, 80a530e6f2SArun Ramadoss { 0x07, "rx_crc_err" }, 81a530e6f2SArun Ramadoss { 0x08, "rx_align_err" }, 82a530e6f2SArun Ramadoss { 0x09, "rx_mac_ctrl" }, 83a530e6f2SArun Ramadoss { 0x0a, "rx_pause" }, 84a530e6f2SArun Ramadoss { 0x0b, "rx_bcast" }, 85a530e6f2SArun Ramadoss { 0x0c, "rx_mcast" }, 86a530e6f2SArun Ramadoss { 0x0d, "rx_ucast" }, 87a530e6f2SArun Ramadoss { 0x0e, "rx_64_or_less" }, 88a530e6f2SArun Ramadoss { 0x0f, "rx_65_127" }, 89a530e6f2SArun Ramadoss { 0x10, "rx_128_255" }, 90a530e6f2SArun Ramadoss { 0x11, "rx_256_511" }, 91a530e6f2SArun Ramadoss { 0x12, "rx_512_1023" }, 92a530e6f2SArun Ramadoss { 0x13, "rx_1024_1522" }, 93a530e6f2SArun Ramadoss { 0x14, "tx" }, 94a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 95a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 96a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 97a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 98a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 99a530e6f2SArun Ramadoss { 0x1a, "tx_ucast" }, 100a530e6f2SArun Ramadoss { 0x1b, "tx_deferred" }, 101a530e6f2SArun Ramadoss { 0x1c, "tx_total_col" }, 102a530e6f2SArun Ramadoss { 0x1d, "tx_exc_col" }, 103a530e6f2SArun Ramadoss { 0x1e, "tx_single_col" }, 104a530e6f2SArun Ramadoss { 0x1f, "tx_mult_col" }, 105a530e6f2SArun Ramadoss { 0x100, "rx_discards" }, 106a530e6f2SArun Ramadoss { 0x101, "tx_discards" }, 107a530e6f2SArun Ramadoss }; 108a530e6f2SArun Ramadoss 109a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz9477_mib_names[] = { 110a530e6f2SArun Ramadoss { 0x00, "rx_hi" }, 111a530e6f2SArun Ramadoss { 0x01, "rx_undersize" }, 112a530e6f2SArun Ramadoss { 0x02, "rx_fragments" }, 113a530e6f2SArun Ramadoss { 0x03, "rx_oversize" }, 114a530e6f2SArun Ramadoss { 0x04, "rx_jabbers" }, 115a530e6f2SArun Ramadoss { 0x05, "rx_symbol_err" }, 116a530e6f2SArun Ramadoss { 0x06, "rx_crc_err" }, 117a530e6f2SArun Ramadoss { 0x07, "rx_align_err" }, 118a530e6f2SArun Ramadoss { 0x08, "rx_mac_ctrl" }, 119a530e6f2SArun Ramadoss { 0x09, "rx_pause" }, 120a530e6f2SArun Ramadoss { 0x0A, "rx_bcast" }, 121a530e6f2SArun Ramadoss { 0x0B, "rx_mcast" }, 122a530e6f2SArun Ramadoss { 0x0C, "rx_ucast" }, 123a530e6f2SArun Ramadoss { 0x0D, "rx_64_or_less" }, 124a530e6f2SArun Ramadoss { 0x0E, "rx_65_127" }, 125a530e6f2SArun Ramadoss { 0x0F, "rx_128_255" }, 126a530e6f2SArun Ramadoss { 0x10, "rx_256_511" }, 127a530e6f2SArun Ramadoss { 0x11, "rx_512_1023" }, 128a530e6f2SArun Ramadoss { 0x12, "rx_1024_1522" }, 129a530e6f2SArun Ramadoss { 0x13, "rx_1523_2000" }, 130a530e6f2SArun Ramadoss { 0x14, "rx_2001" }, 131a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 132a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 133a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 134a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 135a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 136a530e6f2SArun Ramadoss { 0x1A, "tx_ucast" }, 137a530e6f2SArun Ramadoss { 0x1B, "tx_deferred" }, 138a530e6f2SArun Ramadoss { 0x1C, "tx_total_col" }, 139a530e6f2SArun Ramadoss { 0x1D, "tx_exc_col" }, 140a530e6f2SArun Ramadoss { 0x1E, "tx_single_col" }, 141a530e6f2SArun Ramadoss { 0x1F, "tx_mult_col" }, 142a530e6f2SArun Ramadoss { 0x80, "rx_total" }, 143a530e6f2SArun Ramadoss { 0x81, "tx_total" }, 144a530e6f2SArun Ramadoss { 0x82, "rx_discards" }, 145a530e6f2SArun Ramadoss { 0x83, "tx_discards" }, 146a530e6f2SArun Ramadoss }; 147a530e6f2SArun Ramadoss 1486ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz8_dev_ops = { 1496ec23aaaSArun Ramadoss .setup = ksz8_setup, 1506ec23aaaSArun Ramadoss .get_port_addr = ksz8_get_port_addr, 1516ec23aaaSArun Ramadoss .cfg_port_member = ksz8_cfg_port_member, 1526ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, 1536ec23aaaSArun Ramadoss .port_setup = ksz8_port_setup, 1546ec23aaaSArun Ramadoss .r_phy = ksz8_r_phy, 1556ec23aaaSArun Ramadoss .w_phy = ksz8_w_phy, 156769e2695SArun Ramadoss .r_mib_cnt = ksz8_r_mib_cnt, 1576ec23aaaSArun Ramadoss .r_mib_pkt = ksz8_r_mib_pkt, 1586ec23aaaSArun Ramadoss .freeze_mib = ksz8_freeze_mib, 1596ec23aaaSArun Ramadoss .port_init_cnt = ksz8_port_init_cnt, 1606ec23aaaSArun Ramadoss .fdb_dump = ksz8_fdb_dump, 1616ec23aaaSArun Ramadoss .mdb_add = ksz8_mdb_add, 1626ec23aaaSArun Ramadoss .mdb_del = ksz8_mdb_del, 1636ec23aaaSArun Ramadoss .vlan_filtering = ksz8_port_vlan_filtering, 1646ec23aaaSArun Ramadoss .vlan_add = ksz8_port_vlan_add, 1656ec23aaaSArun Ramadoss .vlan_del = ksz8_port_vlan_del, 1666ec23aaaSArun Ramadoss .mirror_add = ksz8_port_mirror_add, 1676ec23aaaSArun Ramadoss .mirror_del = ksz8_port_mirror_del, 1686ec23aaaSArun Ramadoss .get_caps = ksz8_get_caps, 1696ec23aaaSArun Ramadoss .config_cpu_port = ksz8_config_cpu_port, 1706ec23aaaSArun Ramadoss .enable_stp_addr = ksz8_enable_stp_addr, 1716ec23aaaSArun Ramadoss .reset = ksz8_reset_switch, 1726ec23aaaSArun Ramadoss .init = ksz8_switch_init, 1736ec23aaaSArun Ramadoss .exit = ksz8_switch_exit, 1746ec23aaaSArun Ramadoss }; 1756ec23aaaSArun Ramadoss 1763015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 1773015c503SOleksij Rempel unsigned int mode, 1783015c503SOleksij Rempel phy_interface_t interface, 1793015c503SOleksij Rempel struct phy_device *phydev, int speed, 1803015c503SOleksij Rempel int duplex, bool tx_pause, 1813015c503SOleksij Rempel bool rx_pause); 1823015c503SOleksij Rempel 1836ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz9477_dev_ops = { 1846ec23aaaSArun Ramadoss .setup = ksz9477_setup, 1856ec23aaaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 1866ec23aaaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 1876ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 1886ec23aaaSArun Ramadoss .port_setup = ksz9477_port_setup, 1892c119d99SArun Ramadoss .set_ageing_time = ksz9477_set_ageing_time, 1906ec23aaaSArun Ramadoss .r_phy = ksz9477_r_phy, 1916ec23aaaSArun Ramadoss .w_phy = ksz9477_w_phy, 1926ec23aaaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 1936ec23aaaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 1946ec23aaaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 1956ec23aaaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 1966ec23aaaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 1976ec23aaaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 1986ec23aaaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 1996ec23aaaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 2006ec23aaaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 2016ec23aaaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 2026ec23aaaSArun Ramadoss .get_caps = ksz9477_get_caps, 2036ec23aaaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 2046ec23aaaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 2056ec23aaaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 2066ec23aaaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 2076ec23aaaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 2086ec23aaaSArun Ramadoss .change_mtu = ksz9477_change_mtu, 2096ec23aaaSArun Ramadoss .max_mtu = ksz9477_max_mtu, 2103015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 2116ec23aaaSArun Ramadoss .config_cpu_port = ksz9477_config_cpu_port, 2126ec23aaaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 2136ec23aaaSArun Ramadoss .reset = ksz9477_reset_switch, 2146ec23aaaSArun Ramadoss .init = ksz9477_switch_init, 2156ec23aaaSArun Ramadoss .exit = ksz9477_switch_exit, 2166ec23aaaSArun Ramadoss }; 2176ec23aaaSArun Ramadoss 21855ab6ffaSArun Ramadoss static const struct ksz_dev_ops lan937x_dev_ops = { 21955ab6ffaSArun Ramadoss .setup = lan937x_setup, 220c9cd961cSArun Ramadoss .teardown = lan937x_teardown, 22155ab6ffaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 22255ab6ffaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 223ab882368SArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 22455ab6ffaSArun Ramadoss .port_setup = lan937x_port_setup, 2252c119d99SArun Ramadoss .set_ageing_time = lan937x_set_ageing_time, 226ffaf1de2SArun Ramadoss .r_phy = lan937x_r_phy, 227ffaf1de2SArun Ramadoss .w_phy = lan937x_w_phy, 22855ab6ffaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 22955ab6ffaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 23055ab6ffaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 23155ab6ffaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 23255ab6ffaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 23355ab6ffaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 23455ab6ffaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 23555ab6ffaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 23655ab6ffaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 23755ab6ffaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 238c14e878dSArun Ramadoss .get_caps = lan937x_phylink_get_caps, 239b19ac41fSArun Ramadoss .setup_rgmii_delay = lan937x_setup_rgmii_delay, 24055ab6ffaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 24155ab6ffaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 24255ab6ffaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 24355ab6ffaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 24455ab6ffaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 245ab882368SArun Ramadoss .change_mtu = lan937x_change_mtu, 24655ab6ffaSArun Ramadoss .max_mtu = ksz9477_max_mtu, 2473015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 24855ab6ffaSArun Ramadoss .config_cpu_port = lan937x_config_cpu_port, 24955ab6ffaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 25055ab6ffaSArun Ramadoss .reset = lan937x_reset_switch, 25155ab6ffaSArun Ramadoss .init = lan937x_switch_init, 25255ab6ffaSArun Ramadoss .exit = lan937x_switch_exit, 25355ab6ffaSArun Ramadoss }; 25455ab6ffaSArun Ramadoss 255a02579dfSArun Ramadoss static const u16 ksz8795_regs[] = { 256486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x6E, 257486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x70, 258486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x72, 259486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x71, 260486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x75, 261486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x74, 262486f9ca7SArun Ramadoss [REG_IND_BYTE] = 0xA0, 263486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 264486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 265486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x07, 266486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 267486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x08, 268486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x09, 269486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x0C, 2706877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 2719d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 2729d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 2739d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 274aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x06, 27546f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x56, 276486f9ca7SArun Ramadoss }; 277486f9ca7SArun Ramadoss 278d23a5e18SArun Ramadoss static const u32 ksz8795_masks[] = { 279d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(7), 280d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(1), 281d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(6), 282d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(5), 283d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(6, 0), 284d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), 285d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(12), 286d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(21), 287d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(23), 288d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), 289d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(26), 290d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20), 291d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), 292d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8), 293d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 294d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), 295d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20), 296d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), 297d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), 2988560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 2998560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(5), 300d23a5e18SArun Ramadoss }; 301d23a5e18SArun Ramadoss 302aa5b8b73SArun Ramadoss static const u8 ksz8795_xmii_ctrl0[] = { 303aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 0, 304aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 1, 3058560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 0, 3068560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 1, 307aa5b8b73SArun Ramadoss }; 308aa5b8b73SArun Ramadoss 30946f80fa8SArun Ramadoss static const u8 ksz8795_xmii_ctrl1[] = { 310dc1c596eSArun Ramadoss [P_RGMII_SEL] = 3, 311dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 312dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 313dc1c596eSArun Ramadoss [P_MII_SEL] = 0, 31446f80fa8SArun Ramadoss [P_GMII_1GBIT] = 1, 31546f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 0, 31646f80fa8SArun Ramadoss }; 31746f80fa8SArun Ramadoss 31834e48383SArun Ramadoss static const u8 ksz8795_shifts[] = { 31934e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 7, 32034e48383SArun Ramadoss [VLAN_TABLE] = 16, 32134e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 32234e48383SArun Ramadoss [STATIC_MAC_FID] = 24, 32334e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 32434e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 29, 32534e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 32634e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 27, 32734e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 24, 32834e48383SArun Ramadoss }; 32934e48383SArun Ramadoss 330a02579dfSArun Ramadoss static const u16 ksz8863_regs[] = { 331486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x79, 332486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x7B, 333486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x7B, 334486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x7C, 335486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x80, 336486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x80, 337486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 338486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 339486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x0C, 340486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 341486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x0E, 342486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x0F, 343486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x03, 3446877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3459d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3469d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3479d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 348486f9ca7SArun Ramadoss }; 349486f9ca7SArun Ramadoss 350d23a5e18SArun Ramadoss static const u32 ksz8863_masks[] = { 351d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(3), 352d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(6), 353d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(7), 354d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(6), 355d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(15, 12), 356d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16), 357d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(19), 358d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(19), 359d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(21), 360d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(29, 26), 361d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(20), 362d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16), 363d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(5, 0), 364d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), 365d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 366d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 28), 367d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16), 368d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20), 369d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22), 370d23a5e18SArun Ramadoss }; 371d23a5e18SArun Ramadoss 37234e48383SArun Ramadoss static u8 ksz8863_shifts[] = { 37334e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 16, 37434e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 37534e48383SArun Ramadoss [STATIC_MAC_FID] = 22, 37634e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 37734e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 24, 37834e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 37934e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 24, 38034e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 20, 38134e48383SArun Ramadoss }; 38234e48383SArun Ramadoss 3836877102fSArun Ramadoss static const u16 ksz9477_regs[] = { 3846877102fSArun Ramadoss [P_STP_CTRL] = 0x0B04, 3859d95329cSArun Ramadoss [S_START_CTRL] = 0x0300, 3869d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x0332, 3879d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x0331, 388aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x0300, 38946f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x0301, 390457c182aSArun Ramadoss }; 3916877102fSArun Ramadoss 392457c182aSArun Ramadoss static const u32 ksz9477_masks[] = { 393457c182aSArun Ramadoss [ALU_STAT_WRITE] = 0, 394457c182aSArun Ramadoss [ALU_STAT_READ] = 1, 3958560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 3968560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 397457c182aSArun Ramadoss }; 398457c182aSArun Ramadoss 399457c182aSArun Ramadoss static const u8 ksz9477_shifts[] = { 400457c182aSArun Ramadoss [ALU_STAT_INDEX] = 16, 401457c182aSArun Ramadoss }; 402457c182aSArun Ramadoss 403aa5b8b73SArun Ramadoss static const u8 ksz9477_xmii_ctrl0[] = { 404aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 1, 405aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 0, 4068560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 1, 4078560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 0, 408aa5b8b73SArun Ramadoss }; 409aa5b8b73SArun Ramadoss 41046f80fa8SArun Ramadoss static const u8 ksz9477_xmii_ctrl1[] = { 411dc1c596eSArun Ramadoss [P_RGMII_SEL] = 0, 412dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 413dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 414dc1c596eSArun Ramadoss [P_MII_SEL] = 3, 41546f80fa8SArun Ramadoss [P_GMII_1GBIT] = 0, 41646f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 1, 41746f80fa8SArun Ramadoss }; 41846f80fa8SArun Ramadoss 419457c182aSArun Ramadoss static const u32 lan937x_masks[] = { 420457c182aSArun Ramadoss [ALU_STAT_WRITE] = 1, 421457c182aSArun Ramadoss [ALU_STAT_READ] = 2, 4228560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 4238560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 424457c182aSArun Ramadoss }; 425457c182aSArun Ramadoss 426457c182aSArun Ramadoss static const u8 lan937x_shifts[] = { 427457c182aSArun Ramadoss [ALU_STAT_INDEX] = 8, 4286877102fSArun Ramadoss }; 4296877102fSArun Ramadoss 43041131bacSOleksij Rempel static const struct regmap_range ksz8563_valid_regs[] = { 43141131bacSOleksij Rempel regmap_reg_range(0x0000, 0x0003), 43241131bacSOleksij Rempel regmap_reg_range(0x0006, 0x0006), 43341131bacSOleksij Rempel regmap_reg_range(0x000f, 0x001f), 43441131bacSOleksij Rempel regmap_reg_range(0x0100, 0x0100), 43541131bacSOleksij Rempel regmap_reg_range(0x0104, 0x0107), 43641131bacSOleksij Rempel regmap_reg_range(0x010d, 0x010d), 43741131bacSOleksij Rempel regmap_reg_range(0x0110, 0x0113), 43841131bacSOleksij Rempel regmap_reg_range(0x0120, 0x012b), 43941131bacSOleksij Rempel regmap_reg_range(0x0201, 0x0201), 44041131bacSOleksij Rempel regmap_reg_range(0x0210, 0x0213), 44141131bacSOleksij Rempel regmap_reg_range(0x0300, 0x0300), 44241131bacSOleksij Rempel regmap_reg_range(0x0302, 0x031b), 44341131bacSOleksij Rempel regmap_reg_range(0x0320, 0x032b), 44441131bacSOleksij Rempel regmap_reg_range(0x0330, 0x0336), 44541131bacSOleksij Rempel regmap_reg_range(0x0338, 0x033e), 44641131bacSOleksij Rempel regmap_reg_range(0x0340, 0x035f), 44741131bacSOleksij Rempel regmap_reg_range(0x0370, 0x0370), 44841131bacSOleksij Rempel regmap_reg_range(0x0378, 0x0378), 44941131bacSOleksij Rempel regmap_reg_range(0x037c, 0x037d), 45041131bacSOleksij Rempel regmap_reg_range(0x0390, 0x0393), 45141131bacSOleksij Rempel regmap_reg_range(0x0400, 0x040e), 45241131bacSOleksij Rempel regmap_reg_range(0x0410, 0x042f), 45341131bacSOleksij Rempel regmap_reg_range(0x0500, 0x0519), 45441131bacSOleksij Rempel regmap_reg_range(0x0520, 0x054b), 45541131bacSOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 45641131bacSOleksij Rempel 45741131bacSOleksij Rempel /* port 1 */ 45841131bacSOleksij Rempel regmap_reg_range(0x1000, 0x1001), 45941131bacSOleksij Rempel regmap_reg_range(0x1004, 0x100b), 46041131bacSOleksij Rempel regmap_reg_range(0x1013, 0x1013), 46141131bacSOleksij Rempel regmap_reg_range(0x1017, 0x1017), 46241131bacSOleksij Rempel regmap_reg_range(0x101b, 0x101b), 46341131bacSOleksij Rempel regmap_reg_range(0x101f, 0x1021), 46441131bacSOleksij Rempel regmap_reg_range(0x1030, 0x1030), 46541131bacSOleksij Rempel regmap_reg_range(0x1100, 0x1111), 46641131bacSOleksij Rempel regmap_reg_range(0x111a, 0x111d), 46741131bacSOleksij Rempel regmap_reg_range(0x1122, 0x1127), 46841131bacSOleksij Rempel regmap_reg_range(0x112a, 0x112b), 46941131bacSOleksij Rempel regmap_reg_range(0x1136, 0x1139), 47041131bacSOleksij Rempel regmap_reg_range(0x113e, 0x113f), 47141131bacSOleksij Rempel regmap_reg_range(0x1400, 0x1401), 47241131bacSOleksij Rempel regmap_reg_range(0x1403, 0x1403), 47341131bacSOleksij Rempel regmap_reg_range(0x1410, 0x1417), 47441131bacSOleksij Rempel regmap_reg_range(0x1420, 0x1423), 47541131bacSOleksij Rempel regmap_reg_range(0x1500, 0x1507), 47641131bacSOleksij Rempel regmap_reg_range(0x1600, 0x1612), 47741131bacSOleksij Rempel regmap_reg_range(0x1800, 0x180f), 47841131bacSOleksij Rempel regmap_reg_range(0x1900, 0x1907), 47941131bacSOleksij Rempel regmap_reg_range(0x1914, 0x191b), 48041131bacSOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 48141131bacSOleksij Rempel regmap_reg_range(0x1a04, 0x1a08), 48241131bacSOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 48341131bacSOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 48441131bacSOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 48541131bacSOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 48641131bacSOleksij Rempel 48741131bacSOleksij Rempel /* port 2 */ 48841131bacSOleksij Rempel regmap_reg_range(0x2000, 0x2001), 48941131bacSOleksij Rempel regmap_reg_range(0x2004, 0x200b), 49041131bacSOleksij Rempel regmap_reg_range(0x2013, 0x2013), 49141131bacSOleksij Rempel regmap_reg_range(0x2017, 0x2017), 49241131bacSOleksij Rempel regmap_reg_range(0x201b, 0x201b), 49341131bacSOleksij Rempel regmap_reg_range(0x201f, 0x2021), 49441131bacSOleksij Rempel regmap_reg_range(0x2030, 0x2030), 49541131bacSOleksij Rempel regmap_reg_range(0x2100, 0x2111), 49641131bacSOleksij Rempel regmap_reg_range(0x211a, 0x211d), 49741131bacSOleksij Rempel regmap_reg_range(0x2122, 0x2127), 49841131bacSOleksij Rempel regmap_reg_range(0x212a, 0x212b), 49941131bacSOleksij Rempel regmap_reg_range(0x2136, 0x2139), 50041131bacSOleksij Rempel regmap_reg_range(0x213e, 0x213f), 50141131bacSOleksij Rempel regmap_reg_range(0x2400, 0x2401), 50241131bacSOleksij Rempel regmap_reg_range(0x2403, 0x2403), 50341131bacSOleksij Rempel regmap_reg_range(0x2410, 0x2417), 50441131bacSOleksij Rempel regmap_reg_range(0x2420, 0x2423), 50541131bacSOleksij Rempel regmap_reg_range(0x2500, 0x2507), 50641131bacSOleksij Rempel regmap_reg_range(0x2600, 0x2612), 50741131bacSOleksij Rempel regmap_reg_range(0x2800, 0x280f), 50841131bacSOleksij Rempel regmap_reg_range(0x2900, 0x2907), 50941131bacSOleksij Rempel regmap_reg_range(0x2914, 0x291b), 51041131bacSOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 51141131bacSOleksij Rempel regmap_reg_range(0x2a04, 0x2a08), 51241131bacSOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 51341131bacSOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 51441131bacSOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 51541131bacSOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 51641131bacSOleksij Rempel 51741131bacSOleksij Rempel /* port 3 */ 51841131bacSOleksij Rempel regmap_reg_range(0x3000, 0x3001), 51941131bacSOleksij Rempel regmap_reg_range(0x3004, 0x300b), 52041131bacSOleksij Rempel regmap_reg_range(0x3013, 0x3013), 52141131bacSOleksij Rempel regmap_reg_range(0x3017, 0x3017), 52241131bacSOleksij Rempel regmap_reg_range(0x301b, 0x301b), 52341131bacSOleksij Rempel regmap_reg_range(0x301f, 0x3021), 52441131bacSOleksij Rempel regmap_reg_range(0x3030, 0x3030), 52541131bacSOleksij Rempel regmap_reg_range(0x3300, 0x3301), 52641131bacSOleksij Rempel regmap_reg_range(0x3303, 0x3303), 52741131bacSOleksij Rempel regmap_reg_range(0x3400, 0x3401), 52841131bacSOleksij Rempel regmap_reg_range(0x3403, 0x3403), 52941131bacSOleksij Rempel regmap_reg_range(0x3410, 0x3417), 53041131bacSOleksij Rempel regmap_reg_range(0x3420, 0x3423), 53141131bacSOleksij Rempel regmap_reg_range(0x3500, 0x3507), 53241131bacSOleksij Rempel regmap_reg_range(0x3600, 0x3612), 53341131bacSOleksij Rempel regmap_reg_range(0x3800, 0x380f), 53441131bacSOleksij Rempel regmap_reg_range(0x3900, 0x3907), 53541131bacSOleksij Rempel regmap_reg_range(0x3914, 0x391b), 53641131bacSOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 53741131bacSOleksij Rempel regmap_reg_range(0x3a04, 0x3a08), 53841131bacSOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 53941131bacSOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 54041131bacSOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 54141131bacSOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 54241131bacSOleksij Rempel }; 54341131bacSOleksij Rempel 54441131bacSOleksij Rempel static const struct regmap_access_table ksz8563_register_set = { 54541131bacSOleksij Rempel .yes_ranges = ksz8563_valid_regs, 54641131bacSOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs), 54741131bacSOleksij Rempel }; 54841131bacSOleksij Rempel 54974e792b5SOleksij Rempel static const struct regmap_range ksz9477_valid_regs[] = { 55074e792b5SOleksij Rempel regmap_reg_range(0x0000, 0x0003), 55174e792b5SOleksij Rempel regmap_reg_range(0x0006, 0x0006), 55274e792b5SOleksij Rempel regmap_reg_range(0x0010, 0x001f), 55374e792b5SOleksij Rempel regmap_reg_range(0x0100, 0x0100), 55474e792b5SOleksij Rempel regmap_reg_range(0x0103, 0x0107), 55574e792b5SOleksij Rempel regmap_reg_range(0x010d, 0x010d), 55674e792b5SOleksij Rempel regmap_reg_range(0x0110, 0x0113), 55774e792b5SOleksij Rempel regmap_reg_range(0x0120, 0x012b), 55874e792b5SOleksij Rempel regmap_reg_range(0x0201, 0x0201), 55974e792b5SOleksij Rempel regmap_reg_range(0x0210, 0x0213), 56074e792b5SOleksij Rempel regmap_reg_range(0x0300, 0x0300), 56174e792b5SOleksij Rempel regmap_reg_range(0x0302, 0x031b), 56274e792b5SOleksij Rempel regmap_reg_range(0x0320, 0x032b), 56374e792b5SOleksij Rempel regmap_reg_range(0x0330, 0x0336), 5643a8b8ea6SRomain Naour regmap_reg_range(0x0338, 0x033b), 5653a8b8ea6SRomain Naour regmap_reg_range(0x033e, 0x033e), 56674e792b5SOleksij Rempel regmap_reg_range(0x0340, 0x035f), 56774e792b5SOleksij Rempel regmap_reg_range(0x0370, 0x0370), 56874e792b5SOleksij Rempel regmap_reg_range(0x0378, 0x0378), 56974e792b5SOleksij Rempel regmap_reg_range(0x037c, 0x037d), 57074e792b5SOleksij Rempel regmap_reg_range(0x0390, 0x0393), 57174e792b5SOleksij Rempel regmap_reg_range(0x0400, 0x040e), 57274e792b5SOleksij Rempel regmap_reg_range(0x0410, 0x042f), 57374e792b5SOleksij Rempel regmap_reg_range(0x0444, 0x044b), 57474e792b5SOleksij Rempel regmap_reg_range(0x0450, 0x046f), 57574e792b5SOleksij Rempel regmap_reg_range(0x0500, 0x0519), 57674e792b5SOleksij Rempel regmap_reg_range(0x0520, 0x054b), 57774e792b5SOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 57874e792b5SOleksij Rempel regmap_reg_range(0x0604, 0x060b), 57974e792b5SOleksij Rempel regmap_reg_range(0x0610, 0x0612), 58074e792b5SOleksij Rempel regmap_reg_range(0x0614, 0x062c), 58174e792b5SOleksij Rempel regmap_reg_range(0x0640, 0x0645), 58274e792b5SOleksij Rempel regmap_reg_range(0x0648, 0x064d), 58374e792b5SOleksij Rempel 58474e792b5SOleksij Rempel /* port 1 */ 58574e792b5SOleksij Rempel regmap_reg_range(0x1000, 0x1001), 58674e792b5SOleksij Rempel regmap_reg_range(0x1013, 0x1013), 58774e792b5SOleksij Rempel regmap_reg_range(0x1017, 0x1017), 58874e792b5SOleksij Rempel regmap_reg_range(0x101b, 0x101b), 58974e792b5SOleksij Rempel regmap_reg_range(0x101f, 0x1020), 59074e792b5SOleksij Rempel regmap_reg_range(0x1030, 0x1030), 59174e792b5SOleksij Rempel regmap_reg_range(0x1100, 0x1115), 59274e792b5SOleksij Rempel regmap_reg_range(0x111a, 0x111f), 59374e792b5SOleksij Rempel regmap_reg_range(0x1122, 0x1127), 59474e792b5SOleksij Rempel regmap_reg_range(0x112a, 0x112b), 59574e792b5SOleksij Rempel regmap_reg_range(0x1136, 0x1139), 59674e792b5SOleksij Rempel regmap_reg_range(0x113e, 0x113f), 59774e792b5SOleksij Rempel regmap_reg_range(0x1400, 0x1401), 59874e792b5SOleksij Rempel regmap_reg_range(0x1403, 0x1403), 59974e792b5SOleksij Rempel regmap_reg_range(0x1410, 0x1417), 60074e792b5SOleksij Rempel regmap_reg_range(0x1420, 0x1423), 60174e792b5SOleksij Rempel regmap_reg_range(0x1500, 0x1507), 60274e792b5SOleksij Rempel regmap_reg_range(0x1600, 0x1613), 60374e792b5SOleksij Rempel regmap_reg_range(0x1800, 0x180f), 60474e792b5SOleksij Rempel regmap_reg_range(0x1820, 0x1827), 60574e792b5SOleksij Rempel regmap_reg_range(0x1830, 0x1837), 60674e792b5SOleksij Rempel regmap_reg_range(0x1840, 0x184b), 60774e792b5SOleksij Rempel regmap_reg_range(0x1900, 0x1907), 60874e792b5SOleksij Rempel regmap_reg_range(0x1914, 0x191b), 60974e792b5SOleksij Rempel regmap_reg_range(0x1920, 0x1920), 61074e792b5SOleksij Rempel regmap_reg_range(0x1923, 0x1927), 61174e792b5SOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 61274e792b5SOleksij Rempel regmap_reg_range(0x1a04, 0x1a07), 61374e792b5SOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 61474e792b5SOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 61574e792b5SOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 61674e792b5SOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 61774e792b5SOleksij Rempel 61874e792b5SOleksij Rempel /* port 2 */ 61974e792b5SOleksij Rempel regmap_reg_range(0x2000, 0x2001), 62074e792b5SOleksij Rempel regmap_reg_range(0x2013, 0x2013), 62174e792b5SOleksij Rempel regmap_reg_range(0x2017, 0x2017), 62274e792b5SOleksij Rempel regmap_reg_range(0x201b, 0x201b), 62374e792b5SOleksij Rempel regmap_reg_range(0x201f, 0x2020), 62474e792b5SOleksij Rempel regmap_reg_range(0x2030, 0x2030), 62574e792b5SOleksij Rempel regmap_reg_range(0x2100, 0x2115), 62674e792b5SOleksij Rempel regmap_reg_range(0x211a, 0x211f), 62774e792b5SOleksij Rempel regmap_reg_range(0x2122, 0x2127), 62874e792b5SOleksij Rempel regmap_reg_range(0x212a, 0x212b), 62974e792b5SOleksij Rempel regmap_reg_range(0x2136, 0x2139), 63074e792b5SOleksij Rempel regmap_reg_range(0x213e, 0x213f), 63174e792b5SOleksij Rempel regmap_reg_range(0x2400, 0x2401), 63274e792b5SOleksij Rempel regmap_reg_range(0x2403, 0x2403), 63374e792b5SOleksij Rempel regmap_reg_range(0x2410, 0x2417), 63474e792b5SOleksij Rempel regmap_reg_range(0x2420, 0x2423), 63574e792b5SOleksij Rempel regmap_reg_range(0x2500, 0x2507), 63674e792b5SOleksij Rempel regmap_reg_range(0x2600, 0x2613), 63774e792b5SOleksij Rempel regmap_reg_range(0x2800, 0x280f), 63874e792b5SOleksij Rempel regmap_reg_range(0x2820, 0x2827), 63974e792b5SOleksij Rempel regmap_reg_range(0x2830, 0x2837), 64074e792b5SOleksij Rempel regmap_reg_range(0x2840, 0x284b), 64174e792b5SOleksij Rempel regmap_reg_range(0x2900, 0x2907), 64274e792b5SOleksij Rempel regmap_reg_range(0x2914, 0x291b), 64374e792b5SOleksij Rempel regmap_reg_range(0x2920, 0x2920), 64474e792b5SOleksij Rempel regmap_reg_range(0x2923, 0x2927), 64574e792b5SOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 64674e792b5SOleksij Rempel regmap_reg_range(0x2a04, 0x2a07), 64774e792b5SOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 64874e792b5SOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 64974e792b5SOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 65074e792b5SOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 65174e792b5SOleksij Rempel 65274e792b5SOleksij Rempel /* port 3 */ 65374e792b5SOleksij Rempel regmap_reg_range(0x3000, 0x3001), 65474e792b5SOleksij Rempel regmap_reg_range(0x3013, 0x3013), 65574e792b5SOleksij Rempel regmap_reg_range(0x3017, 0x3017), 65674e792b5SOleksij Rempel regmap_reg_range(0x301b, 0x301b), 65774e792b5SOleksij Rempel regmap_reg_range(0x301f, 0x3020), 65874e792b5SOleksij Rempel regmap_reg_range(0x3030, 0x3030), 65974e792b5SOleksij Rempel regmap_reg_range(0x3100, 0x3115), 66074e792b5SOleksij Rempel regmap_reg_range(0x311a, 0x311f), 66174e792b5SOleksij Rempel regmap_reg_range(0x3122, 0x3127), 66274e792b5SOleksij Rempel regmap_reg_range(0x312a, 0x312b), 66374e792b5SOleksij Rempel regmap_reg_range(0x3136, 0x3139), 66474e792b5SOleksij Rempel regmap_reg_range(0x313e, 0x313f), 66574e792b5SOleksij Rempel regmap_reg_range(0x3400, 0x3401), 66674e792b5SOleksij Rempel regmap_reg_range(0x3403, 0x3403), 66774e792b5SOleksij Rempel regmap_reg_range(0x3410, 0x3417), 66874e792b5SOleksij Rempel regmap_reg_range(0x3420, 0x3423), 66974e792b5SOleksij Rempel regmap_reg_range(0x3500, 0x3507), 67074e792b5SOleksij Rempel regmap_reg_range(0x3600, 0x3613), 67174e792b5SOleksij Rempel regmap_reg_range(0x3800, 0x380f), 67274e792b5SOleksij Rempel regmap_reg_range(0x3820, 0x3827), 67374e792b5SOleksij Rempel regmap_reg_range(0x3830, 0x3837), 67474e792b5SOleksij Rempel regmap_reg_range(0x3840, 0x384b), 67574e792b5SOleksij Rempel regmap_reg_range(0x3900, 0x3907), 67674e792b5SOleksij Rempel regmap_reg_range(0x3914, 0x391b), 67774e792b5SOleksij Rempel regmap_reg_range(0x3920, 0x3920), 67874e792b5SOleksij Rempel regmap_reg_range(0x3923, 0x3927), 67974e792b5SOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 68074e792b5SOleksij Rempel regmap_reg_range(0x3a04, 0x3a07), 68174e792b5SOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 68274e792b5SOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 68374e792b5SOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 68474e792b5SOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 68574e792b5SOleksij Rempel 68674e792b5SOleksij Rempel /* port 4 */ 68774e792b5SOleksij Rempel regmap_reg_range(0x4000, 0x4001), 68874e792b5SOleksij Rempel regmap_reg_range(0x4013, 0x4013), 68974e792b5SOleksij Rempel regmap_reg_range(0x4017, 0x4017), 69074e792b5SOleksij Rempel regmap_reg_range(0x401b, 0x401b), 69174e792b5SOleksij Rempel regmap_reg_range(0x401f, 0x4020), 69274e792b5SOleksij Rempel regmap_reg_range(0x4030, 0x4030), 69374e792b5SOleksij Rempel regmap_reg_range(0x4100, 0x4115), 69474e792b5SOleksij Rempel regmap_reg_range(0x411a, 0x411f), 69574e792b5SOleksij Rempel regmap_reg_range(0x4122, 0x4127), 69674e792b5SOleksij Rempel regmap_reg_range(0x412a, 0x412b), 69774e792b5SOleksij Rempel regmap_reg_range(0x4136, 0x4139), 69874e792b5SOleksij Rempel regmap_reg_range(0x413e, 0x413f), 69974e792b5SOleksij Rempel regmap_reg_range(0x4400, 0x4401), 70074e792b5SOleksij Rempel regmap_reg_range(0x4403, 0x4403), 70174e792b5SOleksij Rempel regmap_reg_range(0x4410, 0x4417), 70274e792b5SOleksij Rempel regmap_reg_range(0x4420, 0x4423), 70374e792b5SOleksij Rempel regmap_reg_range(0x4500, 0x4507), 70474e792b5SOleksij Rempel regmap_reg_range(0x4600, 0x4613), 70574e792b5SOleksij Rempel regmap_reg_range(0x4800, 0x480f), 70674e792b5SOleksij Rempel regmap_reg_range(0x4820, 0x4827), 70774e792b5SOleksij Rempel regmap_reg_range(0x4830, 0x4837), 70874e792b5SOleksij Rempel regmap_reg_range(0x4840, 0x484b), 70974e792b5SOleksij Rempel regmap_reg_range(0x4900, 0x4907), 71074e792b5SOleksij Rempel regmap_reg_range(0x4914, 0x491b), 71174e792b5SOleksij Rempel regmap_reg_range(0x4920, 0x4920), 71274e792b5SOleksij Rempel regmap_reg_range(0x4923, 0x4927), 71374e792b5SOleksij Rempel regmap_reg_range(0x4a00, 0x4a03), 71474e792b5SOleksij Rempel regmap_reg_range(0x4a04, 0x4a07), 71574e792b5SOleksij Rempel regmap_reg_range(0x4b00, 0x4b01), 71674e792b5SOleksij Rempel regmap_reg_range(0x4b04, 0x4b04), 71774e792b5SOleksij Rempel regmap_reg_range(0x4c00, 0x4c05), 71874e792b5SOleksij Rempel regmap_reg_range(0x4c08, 0x4c1b), 71974e792b5SOleksij Rempel 72074e792b5SOleksij Rempel /* port 5 */ 72174e792b5SOleksij Rempel regmap_reg_range(0x5000, 0x5001), 72274e792b5SOleksij Rempel regmap_reg_range(0x5013, 0x5013), 72374e792b5SOleksij Rempel regmap_reg_range(0x5017, 0x5017), 72474e792b5SOleksij Rempel regmap_reg_range(0x501b, 0x501b), 72574e792b5SOleksij Rempel regmap_reg_range(0x501f, 0x5020), 72674e792b5SOleksij Rempel regmap_reg_range(0x5030, 0x5030), 72774e792b5SOleksij Rempel regmap_reg_range(0x5100, 0x5115), 72874e792b5SOleksij Rempel regmap_reg_range(0x511a, 0x511f), 72974e792b5SOleksij Rempel regmap_reg_range(0x5122, 0x5127), 73074e792b5SOleksij Rempel regmap_reg_range(0x512a, 0x512b), 73174e792b5SOleksij Rempel regmap_reg_range(0x5136, 0x5139), 73274e792b5SOleksij Rempel regmap_reg_range(0x513e, 0x513f), 73374e792b5SOleksij Rempel regmap_reg_range(0x5400, 0x5401), 73474e792b5SOleksij Rempel regmap_reg_range(0x5403, 0x5403), 73574e792b5SOleksij Rempel regmap_reg_range(0x5410, 0x5417), 73674e792b5SOleksij Rempel regmap_reg_range(0x5420, 0x5423), 73774e792b5SOleksij Rempel regmap_reg_range(0x5500, 0x5507), 73874e792b5SOleksij Rempel regmap_reg_range(0x5600, 0x5613), 73974e792b5SOleksij Rempel regmap_reg_range(0x5800, 0x580f), 74074e792b5SOleksij Rempel regmap_reg_range(0x5820, 0x5827), 74174e792b5SOleksij Rempel regmap_reg_range(0x5830, 0x5837), 74274e792b5SOleksij Rempel regmap_reg_range(0x5840, 0x584b), 74374e792b5SOleksij Rempel regmap_reg_range(0x5900, 0x5907), 74474e792b5SOleksij Rempel regmap_reg_range(0x5914, 0x591b), 74574e792b5SOleksij Rempel regmap_reg_range(0x5920, 0x5920), 74674e792b5SOleksij Rempel regmap_reg_range(0x5923, 0x5927), 74774e792b5SOleksij Rempel regmap_reg_range(0x5a00, 0x5a03), 74874e792b5SOleksij Rempel regmap_reg_range(0x5a04, 0x5a07), 74974e792b5SOleksij Rempel regmap_reg_range(0x5b00, 0x5b01), 75074e792b5SOleksij Rempel regmap_reg_range(0x5b04, 0x5b04), 75174e792b5SOleksij Rempel regmap_reg_range(0x5c00, 0x5c05), 75274e792b5SOleksij Rempel regmap_reg_range(0x5c08, 0x5c1b), 75374e792b5SOleksij Rempel 75474e792b5SOleksij Rempel /* port 6 */ 75574e792b5SOleksij Rempel regmap_reg_range(0x6000, 0x6001), 75674e792b5SOleksij Rempel regmap_reg_range(0x6013, 0x6013), 75774e792b5SOleksij Rempel regmap_reg_range(0x6017, 0x6017), 75874e792b5SOleksij Rempel regmap_reg_range(0x601b, 0x601b), 75974e792b5SOleksij Rempel regmap_reg_range(0x601f, 0x6020), 76074e792b5SOleksij Rempel regmap_reg_range(0x6030, 0x6030), 76174e792b5SOleksij Rempel regmap_reg_range(0x6300, 0x6301), 76274e792b5SOleksij Rempel regmap_reg_range(0x6400, 0x6401), 76374e792b5SOleksij Rempel regmap_reg_range(0x6403, 0x6403), 76474e792b5SOleksij Rempel regmap_reg_range(0x6410, 0x6417), 76574e792b5SOleksij Rempel regmap_reg_range(0x6420, 0x6423), 76674e792b5SOleksij Rempel regmap_reg_range(0x6500, 0x6507), 76774e792b5SOleksij Rempel regmap_reg_range(0x6600, 0x6613), 76874e792b5SOleksij Rempel regmap_reg_range(0x6800, 0x680f), 76974e792b5SOleksij Rempel regmap_reg_range(0x6820, 0x6827), 77074e792b5SOleksij Rempel regmap_reg_range(0x6830, 0x6837), 77174e792b5SOleksij Rempel regmap_reg_range(0x6840, 0x684b), 77274e792b5SOleksij Rempel regmap_reg_range(0x6900, 0x6907), 77374e792b5SOleksij Rempel regmap_reg_range(0x6914, 0x691b), 77474e792b5SOleksij Rempel regmap_reg_range(0x6920, 0x6920), 77574e792b5SOleksij Rempel regmap_reg_range(0x6923, 0x6927), 77674e792b5SOleksij Rempel regmap_reg_range(0x6a00, 0x6a03), 77774e792b5SOleksij Rempel regmap_reg_range(0x6a04, 0x6a07), 77874e792b5SOleksij Rempel regmap_reg_range(0x6b00, 0x6b01), 77974e792b5SOleksij Rempel regmap_reg_range(0x6b04, 0x6b04), 78074e792b5SOleksij Rempel regmap_reg_range(0x6c00, 0x6c05), 78174e792b5SOleksij Rempel regmap_reg_range(0x6c08, 0x6c1b), 78274e792b5SOleksij Rempel 78374e792b5SOleksij Rempel /* port 7 */ 78474e792b5SOleksij Rempel regmap_reg_range(0x7000, 0x7001), 78574e792b5SOleksij Rempel regmap_reg_range(0x7013, 0x7013), 78674e792b5SOleksij Rempel regmap_reg_range(0x7017, 0x7017), 78774e792b5SOleksij Rempel regmap_reg_range(0x701b, 0x701b), 78874e792b5SOleksij Rempel regmap_reg_range(0x701f, 0x7020), 78974e792b5SOleksij Rempel regmap_reg_range(0x7030, 0x7030), 79074e792b5SOleksij Rempel regmap_reg_range(0x7200, 0x7203), 79174e792b5SOleksij Rempel regmap_reg_range(0x7206, 0x7207), 79274e792b5SOleksij Rempel regmap_reg_range(0x7300, 0x7301), 79374e792b5SOleksij Rempel regmap_reg_range(0x7400, 0x7401), 79474e792b5SOleksij Rempel regmap_reg_range(0x7403, 0x7403), 79574e792b5SOleksij Rempel regmap_reg_range(0x7410, 0x7417), 79674e792b5SOleksij Rempel regmap_reg_range(0x7420, 0x7423), 79774e792b5SOleksij Rempel regmap_reg_range(0x7500, 0x7507), 79874e792b5SOleksij Rempel regmap_reg_range(0x7600, 0x7613), 79974e792b5SOleksij Rempel regmap_reg_range(0x7800, 0x780f), 80074e792b5SOleksij Rempel regmap_reg_range(0x7820, 0x7827), 80174e792b5SOleksij Rempel regmap_reg_range(0x7830, 0x7837), 80274e792b5SOleksij Rempel regmap_reg_range(0x7840, 0x784b), 80374e792b5SOleksij Rempel regmap_reg_range(0x7900, 0x7907), 80474e792b5SOleksij Rempel regmap_reg_range(0x7914, 0x791b), 80574e792b5SOleksij Rempel regmap_reg_range(0x7920, 0x7920), 80674e792b5SOleksij Rempel regmap_reg_range(0x7923, 0x7927), 80774e792b5SOleksij Rempel regmap_reg_range(0x7a00, 0x7a03), 80874e792b5SOleksij Rempel regmap_reg_range(0x7a04, 0x7a07), 80974e792b5SOleksij Rempel regmap_reg_range(0x7b00, 0x7b01), 81074e792b5SOleksij Rempel regmap_reg_range(0x7b04, 0x7b04), 81174e792b5SOleksij Rempel regmap_reg_range(0x7c00, 0x7c05), 81274e792b5SOleksij Rempel regmap_reg_range(0x7c08, 0x7c1b), 81374e792b5SOleksij Rempel }; 81474e792b5SOleksij Rempel 81574e792b5SOleksij Rempel static const struct regmap_access_table ksz9477_register_set = { 81674e792b5SOleksij Rempel .yes_ranges = ksz9477_valid_regs, 81774e792b5SOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs), 81874e792b5SOleksij Rempel }; 81974e792b5SOleksij Rempel 8206674e7fdSRomain Naour static const struct regmap_range ksz9896_valid_regs[] = { 8216674e7fdSRomain Naour regmap_reg_range(0x0000, 0x0003), 8226674e7fdSRomain Naour regmap_reg_range(0x0006, 0x0006), 8236674e7fdSRomain Naour regmap_reg_range(0x0010, 0x001f), 8246674e7fdSRomain Naour regmap_reg_range(0x0100, 0x0100), 8256674e7fdSRomain Naour regmap_reg_range(0x0103, 0x0107), 8266674e7fdSRomain Naour regmap_reg_range(0x010d, 0x010d), 8276674e7fdSRomain Naour regmap_reg_range(0x0110, 0x0113), 8286674e7fdSRomain Naour regmap_reg_range(0x0120, 0x0127), 8296674e7fdSRomain Naour regmap_reg_range(0x0201, 0x0201), 8306674e7fdSRomain Naour regmap_reg_range(0x0210, 0x0213), 8316674e7fdSRomain Naour regmap_reg_range(0x0300, 0x0300), 8326674e7fdSRomain Naour regmap_reg_range(0x0302, 0x030b), 8336674e7fdSRomain Naour regmap_reg_range(0x0310, 0x031b), 8346674e7fdSRomain Naour regmap_reg_range(0x0320, 0x032b), 8356674e7fdSRomain Naour regmap_reg_range(0x0330, 0x0336), 8366674e7fdSRomain Naour regmap_reg_range(0x0338, 0x033b), 8376674e7fdSRomain Naour regmap_reg_range(0x033e, 0x033e), 8386674e7fdSRomain Naour regmap_reg_range(0x0340, 0x035f), 8396674e7fdSRomain Naour regmap_reg_range(0x0370, 0x0370), 8406674e7fdSRomain Naour regmap_reg_range(0x0378, 0x0378), 8416674e7fdSRomain Naour regmap_reg_range(0x037c, 0x037d), 8426674e7fdSRomain Naour regmap_reg_range(0x0390, 0x0393), 8436674e7fdSRomain Naour regmap_reg_range(0x0400, 0x040e), 8446674e7fdSRomain Naour regmap_reg_range(0x0410, 0x042f), 8456674e7fdSRomain Naour 8466674e7fdSRomain Naour /* port 1 */ 8476674e7fdSRomain Naour regmap_reg_range(0x1000, 0x1001), 8486674e7fdSRomain Naour regmap_reg_range(0x1013, 0x1013), 8496674e7fdSRomain Naour regmap_reg_range(0x1017, 0x1017), 8506674e7fdSRomain Naour regmap_reg_range(0x101b, 0x101b), 8516674e7fdSRomain Naour regmap_reg_range(0x101f, 0x1020), 8526674e7fdSRomain Naour regmap_reg_range(0x1030, 0x1030), 8536674e7fdSRomain Naour regmap_reg_range(0x1100, 0x1115), 8546674e7fdSRomain Naour regmap_reg_range(0x111a, 0x111f), 8556674e7fdSRomain Naour regmap_reg_range(0x1122, 0x1127), 8566674e7fdSRomain Naour regmap_reg_range(0x112a, 0x112b), 8576674e7fdSRomain Naour regmap_reg_range(0x1136, 0x1139), 8586674e7fdSRomain Naour regmap_reg_range(0x113e, 0x113f), 8596674e7fdSRomain Naour regmap_reg_range(0x1400, 0x1401), 8606674e7fdSRomain Naour regmap_reg_range(0x1403, 0x1403), 8616674e7fdSRomain Naour regmap_reg_range(0x1410, 0x1417), 8626674e7fdSRomain Naour regmap_reg_range(0x1420, 0x1423), 8636674e7fdSRomain Naour regmap_reg_range(0x1500, 0x1507), 8646674e7fdSRomain Naour regmap_reg_range(0x1600, 0x1612), 8656674e7fdSRomain Naour regmap_reg_range(0x1800, 0x180f), 8666674e7fdSRomain Naour regmap_reg_range(0x1820, 0x1827), 8676674e7fdSRomain Naour regmap_reg_range(0x1830, 0x1837), 8686674e7fdSRomain Naour regmap_reg_range(0x1840, 0x184b), 8696674e7fdSRomain Naour regmap_reg_range(0x1900, 0x1907), 8706674e7fdSRomain Naour regmap_reg_range(0x1914, 0x1915), 8716674e7fdSRomain Naour regmap_reg_range(0x1a00, 0x1a03), 8726674e7fdSRomain Naour regmap_reg_range(0x1a04, 0x1a07), 8736674e7fdSRomain Naour regmap_reg_range(0x1b00, 0x1b01), 8746674e7fdSRomain Naour regmap_reg_range(0x1b04, 0x1b04), 8756674e7fdSRomain Naour 8766674e7fdSRomain Naour /* port 2 */ 8776674e7fdSRomain Naour regmap_reg_range(0x2000, 0x2001), 8786674e7fdSRomain Naour regmap_reg_range(0x2013, 0x2013), 8796674e7fdSRomain Naour regmap_reg_range(0x2017, 0x2017), 8806674e7fdSRomain Naour regmap_reg_range(0x201b, 0x201b), 8816674e7fdSRomain Naour regmap_reg_range(0x201f, 0x2020), 8826674e7fdSRomain Naour regmap_reg_range(0x2030, 0x2030), 8836674e7fdSRomain Naour regmap_reg_range(0x2100, 0x2115), 8846674e7fdSRomain Naour regmap_reg_range(0x211a, 0x211f), 8856674e7fdSRomain Naour regmap_reg_range(0x2122, 0x2127), 8866674e7fdSRomain Naour regmap_reg_range(0x212a, 0x212b), 8876674e7fdSRomain Naour regmap_reg_range(0x2136, 0x2139), 8886674e7fdSRomain Naour regmap_reg_range(0x213e, 0x213f), 8896674e7fdSRomain Naour regmap_reg_range(0x2400, 0x2401), 8906674e7fdSRomain Naour regmap_reg_range(0x2403, 0x2403), 8916674e7fdSRomain Naour regmap_reg_range(0x2410, 0x2417), 8926674e7fdSRomain Naour regmap_reg_range(0x2420, 0x2423), 8936674e7fdSRomain Naour regmap_reg_range(0x2500, 0x2507), 8946674e7fdSRomain Naour regmap_reg_range(0x2600, 0x2612), 8956674e7fdSRomain Naour regmap_reg_range(0x2800, 0x280f), 8966674e7fdSRomain Naour regmap_reg_range(0x2820, 0x2827), 8976674e7fdSRomain Naour regmap_reg_range(0x2830, 0x2837), 8986674e7fdSRomain Naour regmap_reg_range(0x2840, 0x284b), 8996674e7fdSRomain Naour regmap_reg_range(0x2900, 0x2907), 9006674e7fdSRomain Naour regmap_reg_range(0x2914, 0x2915), 9016674e7fdSRomain Naour regmap_reg_range(0x2a00, 0x2a03), 9026674e7fdSRomain Naour regmap_reg_range(0x2a04, 0x2a07), 9036674e7fdSRomain Naour regmap_reg_range(0x2b00, 0x2b01), 9046674e7fdSRomain Naour regmap_reg_range(0x2b04, 0x2b04), 9056674e7fdSRomain Naour 9066674e7fdSRomain Naour /* port 3 */ 9076674e7fdSRomain Naour regmap_reg_range(0x3000, 0x3001), 9086674e7fdSRomain Naour regmap_reg_range(0x3013, 0x3013), 9096674e7fdSRomain Naour regmap_reg_range(0x3017, 0x3017), 9106674e7fdSRomain Naour regmap_reg_range(0x301b, 0x301b), 9116674e7fdSRomain Naour regmap_reg_range(0x301f, 0x3020), 9126674e7fdSRomain Naour regmap_reg_range(0x3030, 0x3030), 9136674e7fdSRomain Naour regmap_reg_range(0x3100, 0x3115), 9146674e7fdSRomain Naour regmap_reg_range(0x311a, 0x311f), 9156674e7fdSRomain Naour regmap_reg_range(0x3122, 0x3127), 9166674e7fdSRomain Naour regmap_reg_range(0x312a, 0x312b), 9176674e7fdSRomain Naour regmap_reg_range(0x3136, 0x3139), 9186674e7fdSRomain Naour regmap_reg_range(0x313e, 0x313f), 9196674e7fdSRomain Naour regmap_reg_range(0x3400, 0x3401), 9206674e7fdSRomain Naour regmap_reg_range(0x3403, 0x3403), 9216674e7fdSRomain Naour regmap_reg_range(0x3410, 0x3417), 9226674e7fdSRomain Naour regmap_reg_range(0x3420, 0x3423), 9236674e7fdSRomain Naour regmap_reg_range(0x3500, 0x3507), 9246674e7fdSRomain Naour regmap_reg_range(0x3600, 0x3612), 9256674e7fdSRomain Naour regmap_reg_range(0x3800, 0x380f), 9266674e7fdSRomain Naour regmap_reg_range(0x3820, 0x3827), 9276674e7fdSRomain Naour regmap_reg_range(0x3830, 0x3837), 9286674e7fdSRomain Naour regmap_reg_range(0x3840, 0x384b), 9296674e7fdSRomain Naour regmap_reg_range(0x3900, 0x3907), 9306674e7fdSRomain Naour regmap_reg_range(0x3914, 0x3915), 9316674e7fdSRomain Naour regmap_reg_range(0x3a00, 0x3a03), 9326674e7fdSRomain Naour regmap_reg_range(0x3a04, 0x3a07), 9336674e7fdSRomain Naour regmap_reg_range(0x3b00, 0x3b01), 9346674e7fdSRomain Naour regmap_reg_range(0x3b04, 0x3b04), 9356674e7fdSRomain Naour 9366674e7fdSRomain Naour /* port 4 */ 9376674e7fdSRomain Naour regmap_reg_range(0x4000, 0x4001), 9386674e7fdSRomain Naour regmap_reg_range(0x4013, 0x4013), 9396674e7fdSRomain Naour regmap_reg_range(0x4017, 0x4017), 9406674e7fdSRomain Naour regmap_reg_range(0x401b, 0x401b), 9416674e7fdSRomain Naour regmap_reg_range(0x401f, 0x4020), 9426674e7fdSRomain Naour regmap_reg_range(0x4030, 0x4030), 9436674e7fdSRomain Naour regmap_reg_range(0x4100, 0x4115), 9446674e7fdSRomain Naour regmap_reg_range(0x411a, 0x411f), 9456674e7fdSRomain Naour regmap_reg_range(0x4122, 0x4127), 9466674e7fdSRomain Naour regmap_reg_range(0x412a, 0x412b), 9476674e7fdSRomain Naour regmap_reg_range(0x4136, 0x4139), 9486674e7fdSRomain Naour regmap_reg_range(0x413e, 0x413f), 9496674e7fdSRomain Naour regmap_reg_range(0x4400, 0x4401), 9506674e7fdSRomain Naour regmap_reg_range(0x4403, 0x4403), 9516674e7fdSRomain Naour regmap_reg_range(0x4410, 0x4417), 9526674e7fdSRomain Naour regmap_reg_range(0x4420, 0x4423), 9536674e7fdSRomain Naour regmap_reg_range(0x4500, 0x4507), 9546674e7fdSRomain Naour regmap_reg_range(0x4600, 0x4612), 9556674e7fdSRomain Naour regmap_reg_range(0x4800, 0x480f), 9566674e7fdSRomain Naour regmap_reg_range(0x4820, 0x4827), 9576674e7fdSRomain Naour regmap_reg_range(0x4830, 0x4837), 9586674e7fdSRomain Naour regmap_reg_range(0x4840, 0x484b), 9596674e7fdSRomain Naour regmap_reg_range(0x4900, 0x4907), 9606674e7fdSRomain Naour regmap_reg_range(0x4914, 0x4915), 9616674e7fdSRomain Naour regmap_reg_range(0x4a00, 0x4a03), 9626674e7fdSRomain Naour regmap_reg_range(0x4a04, 0x4a07), 9636674e7fdSRomain Naour regmap_reg_range(0x4b00, 0x4b01), 9646674e7fdSRomain Naour regmap_reg_range(0x4b04, 0x4b04), 9656674e7fdSRomain Naour 9666674e7fdSRomain Naour /* port 5 */ 9676674e7fdSRomain Naour regmap_reg_range(0x5000, 0x5001), 9686674e7fdSRomain Naour regmap_reg_range(0x5013, 0x5013), 9696674e7fdSRomain Naour regmap_reg_range(0x5017, 0x5017), 9706674e7fdSRomain Naour regmap_reg_range(0x501b, 0x501b), 9716674e7fdSRomain Naour regmap_reg_range(0x501f, 0x5020), 9726674e7fdSRomain Naour regmap_reg_range(0x5030, 0x5030), 9736674e7fdSRomain Naour regmap_reg_range(0x5100, 0x5115), 9746674e7fdSRomain Naour regmap_reg_range(0x511a, 0x511f), 9756674e7fdSRomain Naour regmap_reg_range(0x5122, 0x5127), 9766674e7fdSRomain Naour regmap_reg_range(0x512a, 0x512b), 9776674e7fdSRomain Naour regmap_reg_range(0x5136, 0x5139), 9786674e7fdSRomain Naour regmap_reg_range(0x513e, 0x513f), 9796674e7fdSRomain Naour regmap_reg_range(0x5400, 0x5401), 9806674e7fdSRomain Naour regmap_reg_range(0x5403, 0x5403), 9816674e7fdSRomain Naour regmap_reg_range(0x5410, 0x5417), 9826674e7fdSRomain Naour regmap_reg_range(0x5420, 0x5423), 9836674e7fdSRomain Naour regmap_reg_range(0x5500, 0x5507), 9846674e7fdSRomain Naour regmap_reg_range(0x5600, 0x5612), 9856674e7fdSRomain Naour regmap_reg_range(0x5800, 0x580f), 9866674e7fdSRomain Naour regmap_reg_range(0x5820, 0x5827), 9876674e7fdSRomain Naour regmap_reg_range(0x5830, 0x5837), 9886674e7fdSRomain Naour regmap_reg_range(0x5840, 0x584b), 9896674e7fdSRomain Naour regmap_reg_range(0x5900, 0x5907), 9906674e7fdSRomain Naour regmap_reg_range(0x5914, 0x5915), 9916674e7fdSRomain Naour regmap_reg_range(0x5a00, 0x5a03), 9926674e7fdSRomain Naour regmap_reg_range(0x5a04, 0x5a07), 9936674e7fdSRomain Naour regmap_reg_range(0x5b00, 0x5b01), 9946674e7fdSRomain Naour regmap_reg_range(0x5b04, 0x5b04), 9956674e7fdSRomain Naour 9966674e7fdSRomain Naour /* port 6 */ 9976674e7fdSRomain Naour regmap_reg_range(0x6000, 0x6001), 9986674e7fdSRomain Naour regmap_reg_range(0x6013, 0x6013), 9996674e7fdSRomain Naour regmap_reg_range(0x6017, 0x6017), 10006674e7fdSRomain Naour regmap_reg_range(0x601b, 0x601b), 10016674e7fdSRomain Naour regmap_reg_range(0x601f, 0x6020), 10026674e7fdSRomain Naour regmap_reg_range(0x6030, 0x6030), 10036674e7fdSRomain Naour regmap_reg_range(0x6100, 0x6115), 10046674e7fdSRomain Naour regmap_reg_range(0x611a, 0x611f), 10056674e7fdSRomain Naour regmap_reg_range(0x6122, 0x6127), 10066674e7fdSRomain Naour regmap_reg_range(0x612a, 0x612b), 10076674e7fdSRomain Naour regmap_reg_range(0x6136, 0x6139), 10086674e7fdSRomain Naour regmap_reg_range(0x613e, 0x613f), 10096674e7fdSRomain Naour regmap_reg_range(0x6300, 0x6301), 10106674e7fdSRomain Naour regmap_reg_range(0x6400, 0x6401), 10116674e7fdSRomain Naour regmap_reg_range(0x6403, 0x6403), 10126674e7fdSRomain Naour regmap_reg_range(0x6410, 0x6417), 10136674e7fdSRomain Naour regmap_reg_range(0x6420, 0x6423), 10146674e7fdSRomain Naour regmap_reg_range(0x6500, 0x6507), 10156674e7fdSRomain Naour regmap_reg_range(0x6600, 0x6612), 10166674e7fdSRomain Naour regmap_reg_range(0x6800, 0x680f), 10176674e7fdSRomain Naour regmap_reg_range(0x6820, 0x6827), 10186674e7fdSRomain Naour regmap_reg_range(0x6830, 0x6837), 10196674e7fdSRomain Naour regmap_reg_range(0x6840, 0x684b), 10206674e7fdSRomain Naour regmap_reg_range(0x6900, 0x6907), 10216674e7fdSRomain Naour regmap_reg_range(0x6914, 0x6915), 10226674e7fdSRomain Naour regmap_reg_range(0x6a00, 0x6a03), 10236674e7fdSRomain Naour regmap_reg_range(0x6a04, 0x6a07), 10246674e7fdSRomain Naour regmap_reg_range(0x6b00, 0x6b01), 10256674e7fdSRomain Naour regmap_reg_range(0x6b04, 0x6b04), 10266674e7fdSRomain Naour }; 10276674e7fdSRomain Naour 10286674e7fdSRomain Naour static const struct regmap_access_table ksz9896_register_set = { 10296674e7fdSRomain Naour .yes_ranges = ksz9896_valid_regs, 10306674e7fdSRomain Naour .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs), 10316674e7fdSRomain Naour }; 10326674e7fdSRomain Naour 1033eee16b14SArun Ramadoss const struct ksz_chip_data ksz_switch_chips[] = { 1034b4490809SOleksij Rempel [KSZ8563] = { 1035b4490809SOleksij Rempel .chip_id = KSZ8563_CHIP_ID, 1036b4490809SOleksij Rempel .dev_name = "KSZ8563", 1037b4490809SOleksij Rempel .num_vlans = 4096, 1038b4490809SOleksij Rempel .num_alus = 4096, 1039b4490809SOleksij Rempel .num_statics = 16, 1040b4490809SOleksij Rempel .cpu_ports = 0x07, /* can be configured as cpu port */ 1041b4490809SOleksij Rempel .port_cnt = 3, /* total port count */ 1042b4490809SOleksij Rempel .ops = &ksz9477_dev_ops, 1043b4490809SOleksij Rempel .mib_names = ksz9477_mib_names, 1044b4490809SOleksij Rempel .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1045b4490809SOleksij Rempel .reg_mib_cnt = MIB_COUNTER_NUM, 1046b4490809SOleksij Rempel .regs = ksz9477_regs, 1047b4490809SOleksij Rempel .masks = ksz9477_masks, 1048b4490809SOleksij Rempel .shifts = ksz9477_shifts, 1049b4490809SOleksij Rempel .xmii_ctrl0 = ksz9477_xmii_ctrl0, 1050b4490809SOleksij Rempel .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 1051b4490809SOleksij Rempel .supports_mii = {false, false, true}, 1052b4490809SOleksij Rempel .supports_rmii = {false, false, true}, 1053b4490809SOleksij Rempel .supports_rgmii = {false, false, true}, 1054b4490809SOleksij Rempel .internal_phy = {true, true, false}, 1055505bf320SOleksij Rempel .gbit_capable = {false, false, true}, 105641131bacSOleksij Rempel .wr_table = &ksz8563_register_set, 105741131bacSOleksij Rempel .rd_table = &ksz8563_register_set, 1058b4490809SOleksij Rempel }, 1059b4490809SOleksij Rempel 1060462d5250SArun Ramadoss [KSZ8795] = { 1061462d5250SArun Ramadoss .chip_id = KSZ8795_CHIP_ID, 1062462d5250SArun Ramadoss .dev_name = "KSZ8795", 1063462d5250SArun Ramadoss .num_vlans = 4096, 1064462d5250SArun Ramadoss .num_alus = 0, 1065462d5250SArun Ramadoss .num_statics = 8, 1066462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1067462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 10686ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1069462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1070a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1071a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1072a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1073486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1074d23a5e18SArun Ramadoss .masks = ksz8795_masks, 107534e48383SArun Ramadoss .shifts = ksz8795_shifts, 1076aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 107746f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 107865ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 107965ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 108065ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 108165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1082462d5250SArun Ramadoss }, 1083462d5250SArun Ramadoss 1084462d5250SArun Ramadoss [KSZ8794] = { 1085462d5250SArun Ramadoss /* WARNING 1086462d5250SArun Ramadoss * ======= 1087462d5250SArun Ramadoss * KSZ8794 is similar to KSZ8795, except the port map 1088462d5250SArun Ramadoss * contains a gap between external and CPU ports, the 1089462d5250SArun Ramadoss * port map is NOT continuous. The per-port register 1090462d5250SArun Ramadoss * map is shifted accordingly too, i.e. registers at 1091462d5250SArun Ramadoss * offset 0x40 are NOT used on KSZ8794 and they ARE 1092462d5250SArun Ramadoss * used on KSZ8795 for external port 3. 1093462d5250SArun Ramadoss * external cpu 1094462d5250SArun Ramadoss * KSZ8794 0,1,2 4 1095462d5250SArun Ramadoss * KSZ8795 0,1,2,3 4 1096462d5250SArun Ramadoss * KSZ8765 0,1,2,3 4 1097462d5250SArun Ramadoss * port_cnt is configured as 5, even though it is 4 1098462d5250SArun Ramadoss */ 1099462d5250SArun Ramadoss .chip_id = KSZ8794_CHIP_ID, 1100462d5250SArun Ramadoss .dev_name = "KSZ8794", 1101462d5250SArun Ramadoss .num_vlans = 4096, 1102462d5250SArun Ramadoss .num_alus = 0, 1103462d5250SArun Ramadoss .num_statics = 8, 1104462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1105462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 11066ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1107462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1108a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1109a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1110a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1111486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1112d23a5e18SArun Ramadoss .masks = ksz8795_masks, 111334e48383SArun Ramadoss .shifts = ksz8795_shifts, 1114aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 111546f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 111665ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 111765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 111865ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 111965ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, false}, 1120462d5250SArun Ramadoss }, 1121462d5250SArun Ramadoss 1122462d5250SArun Ramadoss [KSZ8765] = { 1123462d5250SArun Ramadoss .chip_id = KSZ8765_CHIP_ID, 1124462d5250SArun Ramadoss .dev_name = "KSZ8765", 1125462d5250SArun Ramadoss .num_vlans = 4096, 1126462d5250SArun Ramadoss .num_alus = 0, 1127462d5250SArun Ramadoss .num_statics = 8, 1128462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1129462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 11306ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1131462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1132a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1133a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1134a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1135486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1136d23a5e18SArun Ramadoss .masks = ksz8795_masks, 113734e48383SArun Ramadoss .shifts = ksz8795_shifts, 1138aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 113946f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 114065ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 114165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 114265ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 114365ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1144462d5250SArun Ramadoss }, 1145462d5250SArun Ramadoss 1146462d5250SArun Ramadoss [KSZ8830] = { 1147462d5250SArun Ramadoss .chip_id = KSZ8830_CHIP_ID, 1148462d5250SArun Ramadoss .dev_name = "KSZ8863/KSZ8873", 1149462d5250SArun Ramadoss .num_vlans = 16, 1150462d5250SArun Ramadoss .num_alus = 0, 1151462d5250SArun Ramadoss .num_statics = 8, 1152462d5250SArun Ramadoss .cpu_ports = 0x4, /* can be configured as cpu port */ 1153462d5250SArun Ramadoss .port_cnt = 3, 11546ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1155a530e6f2SArun Ramadoss .mib_names = ksz88xx_mib_names, 1156a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), 1157a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1158486f9ca7SArun Ramadoss .regs = ksz8863_regs, 1159d23a5e18SArun Ramadoss .masks = ksz8863_masks, 116034e48383SArun Ramadoss .shifts = ksz8863_shifts, 116165ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 116265ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 116365ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1164462d5250SArun Ramadoss }, 1165462d5250SArun Ramadoss 1166462d5250SArun Ramadoss [KSZ9477] = { 1167462d5250SArun Ramadoss .chip_id = KSZ9477_CHIP_ID, 1168462d5250SArun Ramadoss .dev_name = "KSZ9477", 1169462d5250SArun Ramadoss .num_vlans = 4096, 1170462d5250SArun Ramadoss .num_alus = 4096, 1171462d5250SArun Ramadoss .num_statics = 16, 1172462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1173462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1174978f1f72SArun Ramadoss .port_nirqs = 4, 11756ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1176462d5250SArun Ramadoss .phy_errata_9477 = true, 1177a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1178a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1179a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 11806877102fSArun Ramadoss .regs = ksz9477_regs, 1181457c182aSArun Ramadoss .masks = ksz9477_masks, 1182457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1183aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 118446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 118565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 118665ac79e1SArun Ramadoss false, true, false}, 118765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 118865ac79e1SArun Ramadoss false, true, false}, 118965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 119065ac79e1SArun Ramadoss false, true, false}, 119165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 119265ac79e1SArun Ramadoss true, false, false}, 1193505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 119474e792b5SOleksij Rempel .wr_table = &ksz9477_register_set, 119574e792b5SOleksij Rempel .rd_table = &ksz9477_register_set, 1196462d5250SArun Ramadoss }, 1197462d5250SArun Ramadoss 11982eb3ff3cSRomain Naour [KSZ9896] = { 11992eb3ff3cSRomain Naour .chip_id = KSZ9896_CHIP_ID, 12002eb3ff3cSRomain Naour .dev_name = "KSZ9896", 12012eb3ff3cSRomain Naour .num_vlans = 4096, 12022eb3ff3cSRomain Naour .num_alus = 4096, 12032eb3ff3cSRomain Naour .num_statics = 16, 12042eb3ff3cSRomain Naour .cpu_ports = 0x3F, /* can be configured as cpu port */ 12052eb3ff3cSRomain Naour .port_cnt = 6, /* total physical port count */ 1206978f1f72SArun Ramadoss .port_nirqs = 2, 12072eb3ff3cSRomain Naour .ops = &ksz9477_dev_ops, 12082eb3ff3cSRomain Naour .phy_errata_9477 = true, 12092eb3ff3cSRomain Naour .mib_names = ksz9477_mib_names, 12102eb3ff3cSRomain Naour .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 12112eb3ff3cSRomain Naour .reg_mib_cnt = MIB_COUNTER_NUM, 12122eb3ff3cSRomain Naour .regs = ksz9477_regs, 12132eb3ff3cSRomain Naour .masks = ksz9477_masks, 12142eb3ff3cSRomain Naour .shifts = ksz9477_shifts, 12152eb3ff3cSRomain Naour .xmii_ctrl0 = ksz9477_xmii_ctrl0, 12162eb3ff3cSRomain Naour .xmii_ctrl1 = ksz9477_xmii_ctrl1, 12172eb3ff3cSRomain Naour .supports_mii = {false, false, false, false, 12182eb3ff3cSRomain Naour false, true}, 12192eb3ff3cSRomain Naour .supports_rmii = {false, false, false, false, 12202eb3ff3cSRomain Naour false, true}, 12212eb3ff3cSRomain Naour .supports_rgmii = {false, false, false, false, 12222eb3ff3cSRomain Naour false, true}, 12232eb3ff3cSRomain Naour .internal_phy = {true, true, true, true, 12242eb3ff3cSRomain Naour true, false}, 12252eb3ff3cSRomain Naour .gbit_capable = {true, true, true, true, true, true}, 12266674e7fdSRomain Naour .wr_table = &ksz9896_register_set, 12276674e7fdSRomain Naour .rd_table = &ksz9896_register_set, 12282eb3ff3cSRomain Naour }, 12292eb3ff3cSRomain Naour 1230462d5250SArun Ramadoss [KSZ9897] = { 1231462d5250SArun Ramadoss .chip_id = KSZ9897_CHIP_ID, 1232462d5250SArun Ramadoss .dev_name = "KSZ9897", 1233462d5250SArun Ramadoss .num_vlans = 4096, 1234462d5250SArun Ramadoss .num_alus = 4096, 1235462d5250SArun Ramadoss .num_statics = 16, 1236462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1237462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1238978f1f72SArun Ramadoss .port_nirqs = 2, 12396ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1240462d5250SArun Ramadoss .phy_errata_9477 = true, 1241a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1242a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1243a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 12446877102fSArun Ramadoss .regs = ksz9477_regs, 1245457c182aSArun Ramadoss .masks = ksz9477_masks, 1246457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1247aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 124846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 124965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 125065ac79e1SArun Ramadoss false, true, true}, 125165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 125265ac79e1SArun Ramadoss false, true, true}, 125365ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 125465ac79e1SArun Ramadoss false, true, true}, 125565ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 125665ac79e1SArun Ramadoss true, false, false}, 1257505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1258462d5250SArun Ramadoss }, 1259462d5250SArun Ramadoss 1260462d5250SArun Ramadoss [KSZ9893] = { 1261462d5250SArun Ramadoss .chip_id = KSZ9893_CHIP_ID, 1262462d5250SArun Ramadoss .dev_name = "KSZ9893", 1263462d5250SArun Ramadoss .num_vlans = 4096, 1264462d5250SArun Ramadoss .num_alus = 4096, 1265462d5250SArun Ramadoss .num_statics = 16, 1266462d5250SArun Ramadoss .cpu_ports = 0x07, /* can be configured as cpu port */ 1267462d5250SArun Ramadoss .port_cnt = 3, /* total port count */ 1268978f1f72SArun Ramadoss .port_nirqs = 2, 12696ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1270a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1271a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1272a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 12736877102fSArun Ramadoss .regs = ksz9477_regs, 1274457c182aSArun Ramadoss .masks = ksz9477_masks, 1275457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1276aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 127746f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 127865ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 127965ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 128065ac79e1SArun Ramadoss .supports_rgmii = {false, false, true}, 128165ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1282505bf320SOleksij Rempel .gbit_capable = {true, true, true}, 1283462d5250SArun Ramadoss }, 1284462d5250SArun Ramadoss 1285462d5250SArun Ramadoss [KSZ9567] = { 1286462d5250SArun Ramadoss .chip_id = KSZ9567_CHIP_ID, 1287462d5250SArun Ramadoss .dev_name = "KSZ9567", 1288462d5250SArun Ramadoss .num_vlans = 4096, 1289462d5250SArun Ramadoss .num_alus = 4096, 1290462d5250SArun Ramadoss .num_statics = 16, 1291462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1292462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1293978f1f72SArun Ramadoss .port_nirqs = 3, 12946ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1295462d5250SArun Ramadoss .phy_errata_9477 = true, 1296a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1297a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1298a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 12996877102fSArun Ramadoss .regs = ksz9477_regs, 1300457c182aSArun Ramadoss .masks = ksz9477_masks, 1301457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1302aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 130346f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 130465ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 130565ac79e1SArun Ramadoss false, true, true}, 130665ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 130765ac79e1SArun Ramadoss false, true, true}, 130865ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 130965ac79e1SArun Ramadoss false, true, true}, 131065ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 131165ac79e1SArun Ramadoss true, false, false}, 1312505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1313462d5250SArun Ramadoss }, 1314462d5250SArun Ramadoss 1315462d5250SArun Ramadoss [LAN9370] = { 1316462d5250SArun Ramadoss .chip_id = LAN9370_CHIP_ID, 1317462d5250SArun Ramadoss .dev_name = "LAN9370", 1318462d5250SArun Ramadoss .num_vlans = 4096, 1319462d5250SArun Ramadoss .num_alus = 1024, 1320462d5250SArun Ramadoss .num_statics = 256, 1321462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1322462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1323978f1f72SArun Ramadoss .port_nirqs = 6, 132455ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1325a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1326a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1327a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13286877102fSArun Ramadoss .regs = ksz9477_regs, 1329457c182aSArun Ramadoss .masks = lan937x_masks, 1330457c182aSArun Ramadoss .shifts = lan937x_shifts, 1331aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 133246f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 133365ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 133465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 133565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 133665ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1337462d5250SArun Ramadoss }, 1338462d5250SArun Ramadoss 1339462d5250SArun Ramadoss [LAN9371] = { 1340462d5250SArun Ramadoss .chip_id = LAN9371_CHIP_ID, 1341462d5250SArun Ramadoss .dev_name = "LAN9371", 1342462d5250SArun Ramadoss .num_vlans = 4096, 1343462d5250SArun Ramadoss .num_alus = 1024, 1344462d5250SArun Ramadoss .num_statics = 256, 1345462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1346462d5250SArun Ramadoss .port_cnt = 6, /* total physical port count */ 1347978f1f72SArun Ramadoss .port_nirqs = 6, 134855ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1349a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1350a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1351a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13526877102fSArun Ramadoss .regs = ksz9477_regs, 1353457c182aSArun Ramadoss .masks = lan937x_masks, 1354457c182aSArun Ramadoss .shifts = lan937x_shifts, 1355aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 135646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 135765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true, true}, 135865ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true, true}, 135965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true, true}, 136065ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false, false}, 1361462d5250SArun Ramadoss }, 1362462d5250SArun Ramadoss 1363462d5250SArun Ramadoss [LAN9372] = { 1364462d5250SArun Ramadoss .chip_id = LAN9372_CHIP_ID, 1365462d5250SArun Ramadoss .dev_name = "LAN9372", 1366462d5250SArun Ramadoss .num_vlans = 4096, 1367462d5250SArun Ramadoss .num_alus = 1024, 1368462d5250SArun Ramadoss .num_statics = 256, 1369462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1370462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1371978f1f72SArun Ramadoss .port_nirqs = 6, 137255ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1373a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1374a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1375a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13766877102fSArun Ramadoss .regs = ksz9477_regs, 1377457c182aSArun Ramadoss .masks = lan937x_masks, 1378457c182aSArun Ramadoss .shifts = lan937x_shifts, 1379aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 138046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 138165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 138265ac79e1SArun Ramadoss true, true, false, false}, 138365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 138465ac79e1SArun Ramadoss true, true, false, false}, 138565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 138665ac79e1SArun Ramadoss true, true, false, false}, 138765ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 138865ac79e1SArun Ramadoss false, false, true, true}, 1389462d5250SArun Ramadoss }, 1390462d5250SArun Ramadoss 1391462d5250SArun Ramadoss [LAN9373] = { 1392462d5250SArun Ramadoss .chip_id = LAN9373_CHIP_ID, 1393462d5250SArun Ramadoss .dev_name = "LAN9373", 1394462d5250SArun Ramadoss .num_vlans = 4096, 1395462d5250SArun Ramadoss .num_alus = 1024, 1396462d5250SArun Ramadoss .num_statics = 256, 1397462d5250SArun Ramadoss .cpu_ports = 0x38, /* can be configured as cpu port */ 1398462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1399978f1f72SArun Ramadoss .port_nirqs = 6, 140055ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1401a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1402a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1403a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14046877102fSArun Ramadoss .regs = ksz9477_regs, 1405457c182aSArun Ramadoss .masks = lan937x_masks, 1406457c182aSArun Ramadoss .shifts = lan937x_shifts, 1407aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 140846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 140965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 141065ac79e1SArun Ramadoss true, true, false, false}, 141165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 141265ac79e1SArun Ramadoss true, true, false, false}, 141365ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 141465ac79e1SArun Ramadoss true, true, false, false}, 141565ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, 141665ac79e1SArun Ramadoss false, false, true, true}, 1417462d5250SArun Ramadoss }, 1418462d5250SArun Ramadoss 1419462d5250SArun Ramadoss [LAN9374] = { 1420462d5250SArun Ramadoss .chip_id = LAN9374_CHIP_ID, 1421462d5250SArun Ramadoss .dev_name = "LAN9374", 1422462d5250SArun Ramadoss .num_vlans = 4096, 1423462d5250SArun Ramadoss .num_alus = 1024, 1424462d5250SArun Ramadoss .num_statics = 256, 1425462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1426462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1427978f1f72SArun Ramadoss .port_nirqs = 6, 142855ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1429a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1430a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1431a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14326877102fSArun Ramadoss .regs = ksz9477_regs, 1433457c182aSArun Ramadoss .masks = lan937x_masks, 1434457c182aSArun Ramadoss .shifts = lan937x_shifts, 1435aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 143646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 143765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 143865ac79e1SArun Ramadoss true, true, false, false}, 143965ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 144065ac79e1SArun Ramadoss true, true, false, false}, 144165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 144265ac79e1SArun Ramadoss true, true, false, false}, 144365ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 144465ac79e1SArun Ramadoss false, false, true, true}, 1445462d5250SArun Ramadoss }, 1446462d5250SArun Ramadoss }; 1447eee16b14SArun Ramadoss EXPORT_SYMBOL_GPL(ksz_switch_chips); 1448462d5250SArun Ramadoss 1449462d5250SArun Ramadoss static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num) 1450462d5250SArun Ramadoss { 1451462d5250SArun Ramadoss int i; 1452462d5250SArun Ramadoss 1453462d5250SArun Ramadoss for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) { 1454462d5250SArun Ramadoss const struct ksz_chip_data *chip = &ksz_switch_chips[i]; 1455462d5250SArun Ramadoss 1456462d5250SArun Ramadoss if (chip->chip_id == prod_num) 1457462d5250SArun Ramadoss return chip; 1458462d5250SArun Ramadoss } 1459462d5250SArun Ramadoss 1460462d5250SArun Ramadoss return NULL; 1461462d5250SArun Ramadoss } 1462462d5250SArun Ramadoss 1463eee16b14SArun Ramadoss static int ksz_check_device_id(struct ksz_device *dev) 1464eee16b14SArun Ramadoss { 1465eee16b14SArun Ramadoss const struct ksz_chip_data *dt_chip_data; 1466eee16b14SArun Ramadoss 1467eee16b14SArun Ramadoss dt_chip_data = of_device_get_match_data(dev->dev); 1468eee16b14SArun Ramadoss 1469eee16b14SArun Ramadoss /* Check for Device Tree and Chip ID */ 1470eee16b14SArun Ramadoss if (dt_chip_data->chip_id != dev->chip_id) { 1471eee16b14SArun Ramadoss dev_err(dev->dev, 1472eee16b14SArun Ramadoss "Device tree specifies chip %s but found %s, please fix it!\n", 1473eee16b14SArun Ramadoss dt_chip_data->dev_name, dev->info->dev_name); 1474eee16b14SArun Ramadoss return -ENODEV; 1475eee16b14SArun Ramadoss } 1476eee16b14SArun Ramadoss 1477eee16b14SArun Ramadoss return 0; 1478eee16b14SArun Ramadoss } 1479eee16b14SArun Ramadoss 14801958eee8SArun Ramadoss static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, 148165ac79e1SArun Ramadoss struct phylink_config *config) 148265ac79e1SArun Ramadoss { 148365ac79e1SArun Ramadoss struct ksz_device *dev = ds->priv; 148465ac79e1SArun Ramadoss 148565ac79e1SArun Ramadoss config->legacy_pre_march2020 = false; 148665ac79e1SArun Ramadoss 148765ac79e1SArun Ramadoss if (dev->info->supports_mii[port]) 148865ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); 148965ac79e1SArun Ramadoss 149065ac79e1SArun Ramadoss if (dev->info->supports_rmii[port]) 149165ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_RMII, 149265ac79e1SArun Ramadoss config->supported_interfaces); 149365ac79e1SArun Ramadoss 149465ac79e1SArun Ramadoss if (dev->info->supports_rgmii[port]) 149565ac79e1SArun Ramadoss phy_interface_set_rgmii(config->supported_interfaces); 149665ac79e1SArun Ramadoss 14975fbb08ebSVladimir Oltean if (dev->info->internal_phy[port]) { 149865ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_INTERNAL, 149965ac79e1SArun Ramadoss config->supported_interfaces); 15005fbb08ebSVladimir Oltean /* Compatibility for phylib's default interface type when the 15015fbb08ebSVladimir Oltean * phy-mode property is absent 15025fbb08ebSVladimir Oltean */ 15035fbb08ebSVladimir Oltean __set_bit(PHY_INTERFACE_MODE_GMII, 15045fbb08ebSVladimir Oltean config->supported_interfaces); 15055fbb08ebSVladimir Oltean } 15067012033cSArun Ramadoss 15077012033cSArun Ramadoss if (dev->dev_ops->get_caps) 15087012033cSArun Ramadoss dev->dev_ops->get_caps(dev, port, config); 150965ac79e1SArun Ramadoss } 151065ac79e1SArun Ramadoss 1511c6101dd7SArun Ramadoss void ksz_r_mib_stats64(struct ksz_device *dev, int port) 1512c6101dd7SArun Ramadoss { 1513c4748ff6SOleksij Rempel struct ethtool_pause_stats *pstats; 1514c6101dd7SArun Ramadoss struct rtnl_link_stats64 *stats; 1515c6101dd7SArun Ramadoss struct ksz_stats_raw *raw; 1516c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1517c6101dd7SArun Ramadoss 1518c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1519c6101dd7SArun Ramadoss stats = &mib->stats64; 1520c4748ff6SOleksij Rempel pstats = &mib->pause_stats; 1521c6101dd7SArun Ramadoss raw = (struct ksz_stats_raw *)mib->counters; 1522c6101dd7SArun Ramadoss 1523c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1524c6101dd7SArun Ramadoss 1525961d6c70SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 1526961d6c70SOleksij Rempel raw->rx_pause; 1527961d6c70SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 1528961d6c70SOleksij Rempel raw->tx_pause; 1529c6101dd7SArun Ramadoss 1530c6101dd7SArun Ramadoss /* HW counters are counting bytes + FCS which is not acceptable 1531c6101dd7SArun Ramadoss * for rtnl_link_stats64 interface 1532c6101dd7SArun Ramadoss */ 1533c6101dd7SArun Ramadoss stats->rx_bytes = raw->rx_total - stats->rx_packets * ETH_FCS_LEN; 1534c6101dd7SArun Ramadoss stats->tx_bytes = raw->tx_total - stats->tx_packets * ETH_FCS_LEN; 1535c6101dd7SArun Ramadoss 1536c6101dd7SArun Ramadoss stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 1537c6101dd7SArun Ramadoss raw->rx_oversize; 1538c6101dd7SArun Ramadoss 1539c6101dd7SArun Ramadoss stats->rx_crc_errors = raw->rx_crc_err; 1540c6101dd7SArun Ramadoss stats->rx_frame_errors = raw->rx_align_err; 1541c6101dd7SArun Ramadoss stats->rx_dropped = raw->rx_discards; 1542c6101dd7SArun Ramadoss stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 1543c6101dd7SArun Ramadoss stats->rx_frame_errors + stats->rx_dropped; 1544c6101dd7SArun Ramadoss 1545c6101dd7SArun Ramadoss stats->tx_window_errors = raw->tx_late_col; 1546c6101dd7SArun Ramadoss stats->tx_fifo_errors = raw->tx_discards; 1547c6101dd7SArun Ramadoss stats->tx_aborted_errors = raw->tx_exc_col; 1548c6101dd7SArun Ramadoss stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 1549c6101dd7SArun Ramadoss stats->tx_aborted_errors; 1550c6101dd7SArun Ramadoss 1551c6101dd7SArun Ramadoss stats->multicast = raw->rx_mcast; 1552c6101dd7SArun Ramadoss stats->collisions = raw->tx_total_col; 1553c6101dd7SArun Ramadoss 1554c4748ff6SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 1555c4748ff6SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 1556c4748ff6SOleksij Rempel 1557c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1558c6101dd7SArun Ramadoss } 1559c6101dd7SArun Ramadoss 15601958eee8SArun Ramadoss static void ksz_get_stats64(struct dsa_switch *ds, int port, 1561c6101dd7SArun Ramadoss struct rtnl_link_stats64 *s) 1562c6101dd7SArun Ramadoss { 1563c6101dd7SArun Ramadoss struct ksz_device *dev = ds->priv; 1564c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1565c6101dd7SArun Ramadoss 1566c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1567c6101dd7SArun Ramadoss 1568c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1569c6101dd7SArun Ramadoss memcpy(s, &mib->stats64, sizeof(*s)); 1570c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1571c6101dd7SArun Ramadoss } 1572c6101dd7SArun Ramadoss 1573c4748ff6SOleksij Rempel static void ksz_get_pause_stats(struct dsa_switch *ds, int port, 1574c4748ff6SOleksij Rempel struct ethtool_pause_stats *pause_stats) 1575c4748ff6SOleksij Rempel { 1576c4748ff6SOleksij Rempel struct ksz_device *dev = ds->priv; 1577c4748ff6SOleksij Rempel struct ksz_port_mib *mib; 1578c4748ff6SOleksij Rempel 1579c4748ff6SOleksij Rempel mib = &dev->ports[port].mib; 1580c4748ff6SOleksij Rempel 1581c4748ff6SOleksij Rempel spin_lock(&mib->stats64_lock); 1582c4748ff6SOleksij Rempel memcpy(pause_stats, &mib->pause_stats, sizeof(*pause_stats)); 1583c4748ff6SOleksij Rempel spin_unlock(&mib->stats64_lock); 1584c4748ff6SOleksij Rempel } 1585c4748ff6SOleksij Rempel 15861958eee8SArun Ramadoss static void ksz_get_strings(struct dsa_switch *ds, int port, 1587997d2126SArun Ramadoss u32 stringset, uint8_t *buf) 1588997d2126SArun Ramadoss { 1589997d2126SArun Ramadoss struct ksz_device *dev = ds->priv; 1590997d2126SArun Ramadoss int i; 1591997d2126SArun Ramadoss 1592997d2126SArun Ramadoss if (stringset != ETH_SS_STATS) 1593997d2126SArun Ramadoss return; 1594997d2126SArun Ramadoss 1595997d2126SArun Ramadoss for (i = 0; i < dev->info->mib_cnt; i++) { 1596997d2126SArun Ramadoss memcpy(buf + i * ETH_GSTRING_LEN, 1597997d2126SArun Ramadoss dev->info->mib_names[i].string, ETH_GSTRING_LEN); 1598997d2126SArun Ramadoss } 1599997d2126SArun Ramadoss } 1600997d2126SArun Ramadoss 1601e593df51SArun Ramadoss static void ksz_update_port_member(struct ksz_device *dev, int port) 1602b987e98eSWoojung Huh { 1603b3612ccdSOleksij Rempel struct ksz_port *p = &dev->ports[port]; 1604b3612ccdSOleksij Rempel struct dsa_switch *ds = dev->ds; 1605b3612ccdSOleksij Rempel u8 port_member = 0, cpu_port; 1606b3612ccdSOleksij Rempel const struct dsa_port *dp; 16073d00827aSSvenning Sørensen int i, j; 1608b987e98eSWoojung Huh 1609b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, port)) 1610b3612ccdSOleksij Rempel return; 1611b3612ccdSOleksij Rempel 1612b3612ccdSOleksij Rempel dp = dsa_to_port(ds, port); 1613b3612ccdSOleksij Rempel cpu_port = BIT(dsa_upstream_port(ds, port)); 1614b3612ccdSOleksij Rempel 1615b3612ccdSOleksij Rempel for (i = 0; i < ds->num_ports; i++) { 1616b3612ccdSOleksij Rempel const struct dsa_port *other_dp = dsa_to_port(ds, i); 1617b3612ccdSOleksij Rempel struct ksz_port *other_p = &dev->ports[i]; 1618b3612ccdSOleksij Rempel u8 val = 0; 1619b3612ccdSOleksij Rempel 1620b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, i)) 1621c2e86691STristram Ha continue; 1622b3612ccdSOleksij Rempel if (port == i) 1623b3612ccdSOleksij Rempel continue; 162441fb0cf1SVladimir Oltean if (!dsa_port_bridge_same(dp, other_dp)) 1625c2e86691STristram Ha continue; 16263d00827aSSvenning Sørensen if (other_p->stp_state != BR_STATE_FORWARDING) 16273d00827aSSvenning Sørensen continue; 1628b987e98eSWoojung Huh 16293d00827aSSvenning Sørensen if (p->stp_state == BR_STATE_FORWARDING) { 1630b3612ccdSOleksij Rempel val |= BIT(port); 1631b3612ccdSOleksij Rempel port_member |= BIT(i); 1632b987e98eSWoojung Huh } 1633b3612ccdSOleksij Rempel 16343d00827aSSvenning Sørensen /* Retain port [i]'s relationship to other ports than [port] */ 16353d00827aSSvenning Sørensen for (j = 0; j < ds->num_ports; j++) { 16363d00827aSSvenning Sørensen const struct dsa_port *third_dp; 16373d00827aSSvenning Sørensen struct ksz_port *third_p; 16383d00827aSSvenning Sørensen 16393d00827aSSvenning Sørensen if (j == i) 16403d00827aSSvenning Sørensen continue; 16413d00827aSSvenning Sørensen if (j == port) 16423d00827aSSvenning Sørensen continue; 16433d00827aSSvenning Sørensen if (!dsa_is_user_port(ds, j)) 16443d00827aSSvenning Sørensen continue; 16453d00827aSSvenning Sørensen third_p = &dev->ports[j]; 16463d00827aSSvenning Sørensen if (third_p->stp_state != BR_STATE_FORWARDING) 16473d00827aSSvenning Sørensen continue; 16483d00827aSSvenning Sørensen third_dp = dsa_to_port(ds, j); 16493d00827aSSvenning Sørensen if (dsa_port_bridge_same(other_dp, third_dp)) 16503d00827aSSvenning Sørensen val |= BIT(j); 16513d00827aSSvenning Sørensen } 16523d00827aSSvenning Sørensen 1653b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); 1654b3612ccdSOleksij Rempel } 1655b3612ccdSOleksij Rempel 1656b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); 1657b987e98eSWoojung Huh } 1658b987e98eSWoojung Huh 1659ff319a64SArun Ramadoss static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum) 1660ff319a64SArun Ramadoss { 1661ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1662ff319a64SArun Ramadoss u16 val; 1663ff319a64SArun Ramadoss int ret; 1664ff319a64SArun Ramadoss 1665ff319a64SArun Ramadoss if (regnum & MII_ADDR_C45) 1666ff319a64SArun Ramadoss return -EOPNOTSUPP; 1667ff319a64SArun Ramadoss 1668ff319a64SArun Ramadoss ret = dev->dev_ops->r_phy(dev, addr, regnum, &val); 1669ff319a64SArun Ramadoss if (ret < 0) 1670ff319a64SArun Ramadoss return ret; 1671ff319a64SArun Ramadoss 1672ff319a64SArun Ramadoss return val; 1673ff319a64SArun Ramadoss } 1674ff319a64SArun Ramadoss 1675ff319a64SArun Ramadoss static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, 1676ff319a64SArun Ramadoss u16 val) 1677ff319a64SArun Ramadoss { 1678ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1679ff319a64SArun Ramadoss 1680ff319a64SArun Ramadoss if (regnum & MII_ADDR_C45) 1681ff319a64SArun Ramadoss return -EOPNOTSUPP; 1682ff319a64SArun Ramadoss 1683ff319a64SArun Ramadoss return dev->dev_ops->w_phy(dev, addr, regnum, val); 1684ff319a64SArun Ramadoss } 1685ff319a64SArun Ramadoss 1686ff319a64SArun Ramadoss static int ksz_irq_phy_setup(struct ksz_device *dev) 1687ff319a64SArun Ramadoss { 1688ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1689ff319a64SArun Ramadoss int phy; 1690ff319a64SArun Ramadoss int irq; 1691ff319a64SArun Ramadoss int ret; 1692ff319a64SArun Ramadoss 1693ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) { 1694ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) { 1695ff319a64SArun Ramadoss irq = irq_find_mapping(dev->ports[phy].pirq.domain, 1696ff319a64SArun Ramadoss PORT_SRC_PHY_INT); 1697ff319a64SArun Ramadoss if (irq < 0) { 1698ff319a64SArun Ramadoss ret = irq; 1699ff319a64SArun Ramadoss goto out; 1700ff319a64SArun Ramadoss } 1701ff319a64SArun Ramadoss ds->slave_mii_bus->irq[phy] = irq; 1702ff319a64SArun Ramadoss } 1703ff319a64SArun Ramadoss } 1704ff319a64SArun Ramadoss return 0; 1705ff319a64SArun Ramadoss out: 1706ff319a64SArun Ramadoss while (phy--) 1707ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1708ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1709ff319a64SArun Ramadoss 1710ff319a64SArun Ramadoss return ret; 1711ff319a64SArun Ramadoss } 1712ff319a64SArun Ramadoss 1713ff319a64SArun Ramadoss static void ksz_irq_phy_free(struct ksz_device *dev) 1714ff319a64SArun Ramadoss { 1715ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1716ff319a64SArun Ramadoss int phy; 1717ff319a64SArun Ramadoss 1718ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) 1719ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1720ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1721ff319a64SArun Ramadoss } 1722ff319a64SArun Ramadoss 1723ff319a64SArun Ramadoss static int ksz_mdio_register(struct ksz_device *dev) 1724ff319a64SArun Ramadoss { 1725ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1726ff319a64SArun Ramadoss struct device_node *mdio_np; 1727ff319a64SArun Ramadoss struct mii_bus *bus; 1728ff319a64SArun Ramadoss int ret; 1729ff319a64SArun Ramadoss 1730ff319a64SArun Ramadoss mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio"); 1731ff319a64SArun Ramadoss if (!mdio_np) 1732ff319a64SArun Ramadoss return 0; 1733ff319a64SArun Ramadoss 1734ff319a64SArun Ramadoss bus = devm_mdiobus_alloc(ds->dev); 1735ff319a64SArun Ramadoss if (!bus) { 1736ff319a64SArun Ramadoss of_node_put(mdio_np); 1737ff319a64SArun Ramadoss return -ENOMEM; 1738ff319a64SArun Ramadoss } 1739ff319a64SArun Ramadoss 1740ff319a64SArun Ramadoss bus->priv = dev; 1741ff319a64SArun Ramadoss bus->read = ksz_sw_mdio_read; 1742ff319a64SArun Ramadoss bus->write = ksz_sw_mdio_write; 1743ff319a64SArun Ramadoss bus->name = "ksz slave smi"; 1744ff319a64SArun Ramadoss snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index); 1745ff319a64SArun Ramadoss bus->parent = ds->dev; 1746ff319a64SArun Ramadoss bus->phy_mask = ~ds->phys_mii_mask; 1747ff319a64SArun Ramadoss 1748ff319a64SArun Ramadoss ds->slave_mii_bus = bus; 1749ff319a64SArun Ramadoss 1750ff319a64SArun Ramadoss if (dev->irq > 0) { 1751ff319a64SArun Ramadoss ret = ksz_irq_phy_setup(dev); 1752ff319a64SArun Ramadoss if (ret) { 1753ff319a64SArun Ramadoss of_node_put(mdio_np); 1754ff319a64SArun Ramadoss return ret; 1755ff319a64SArun Ramadoss } 1756ff319a64SArun Ramadoss } 1757ff319a64SArun Ramadoss 1758ff319a64SArun Ramadoss ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np); 1759ff319a64SArun Ramadoss if (ret) { 1760ff319a64SArun Ramadoss dev_err(ds->dev, "unable to register MDIO bus %s\n", 1761ff319a64SArun Ramadoss bus->id); 1762ff319a64SArun Ramadoss if (dev->irq > 0) 1763ff319a64SArun Ramadoss ksz_irq_phy_free(dev); 1764ff319a64SArun Ramadoss } 1765ff319a64SArun Ramadoss 1766ff319a64SArun Ramadoss of_node_put(mdio_np); 1767ff319a64SArun Ramadoss 1768ff319a64SArun Ramadoss return ret; 1769ff319a64SArun Ramadoss } 1770ff319a64SArun Ramadoss 1771*e1add7ddSArun Ramadoss static void ksz_irq_mask(struct irq_data *d) 1772ff319a64SArun Ramadoss { 1773*e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1774ff319a64SArun Ramadoss 1775*e1add7ddSArun Ramadoss kirq->masked |= BIT(d->hwirq); 1776ff319a64SArun Ramadoss } 1777ff319a64SArun Ramadoss 1778*e1add7ddSArun Ramadoss static void ksz_irq_unmask(struct irq_data *d) 1779ff319a64SArun Ramadoss { 1780*e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1781ff319a64SArun Ramadoss 1782*e1add7ddSArun Ramadoss kirq->masked &= ~BIT(d->hwirq); 1783ff319a64SArun Ramadoss } 1784ff319a64SArun Ramadoss 1785*e1add7ddSArun Ramadoss static void ksz_irq_bus_lock(struct irq_data *d) 1786ff319a64SArun Ramadoss { 1787*e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1788ff319a64SArun Ramadoss 1789*e1add7ddSArun Ramadoss mutex_lock(&kirq->dev->lock_irq); 1790ff319a64SArun Ramadoss } 1791ff319a64SArun Ramadoss 1792*e1add7ddSArun Ramadoss static void ksz_irq_bus_sync_unlock(struct irq_data *d) 1793ff319a64SArun Ramadoss { 1794*e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1795*e1add7ddSArun Ramadoss struct ksz_device *dev = kirq->dev; 1796ff319a64SArun Ramadoss int ret; 1797ff319a64SArun Ramadoss 1798*e1add7ddSArun Ramadoss ret = ksz_write32(dev, kirq->reg_mask, kirq->masked); 1799ff319a64SArun Ramadoss if (ret) 1800ff319a64SArun Ramadoss dev_err(dev->dev, "failed to change IRQ mask\n"); 1801ff319a64SArun Ramadoss 1802ff319a64SArun Ramadoss mutex_unlock(&dev->lock_irq); 1803ff319a64SArun Ramadoss } 1804ff319a64SArun Ramadoss 1805*e1add7ddSArun Ramadoss static const struct irq_chip ksz_irq_chip = { 1806*e1add7ddSArun Ramadoss .name = "ksz-irq", 1807*e1add7ddSArun Ramadoss .irq_mask = ksz_irq_mask, 1808*e1add7ddSArun Ramadoss .irq_unmask = ksz_irq_unmask, 1809*e1add7ddSArun Ramadoss .irq_bus_lock = ksz_irq_bus_lock, 1810*e1add7ddSArun Ramadoss .irq_bus_sync_unlock = ksz_irq_bus_sync_unlock, 1811ff319a64SArun Ramadoss }; 1812ff319a64SArun Ramadoss 1813*e1add7ddSArun Ramadoss static int ksz_irq_domain_map(struct irq_domain *d, 1814ff319a64SArun Ramadoss unsigned int irq, irq_hw_number_t hwirq) 1815ff319a64SArun Ramadoss { 1816ff319a64SArun Ramadoss irq_set_chip_data(irq, d->host_data); 1817*e1add7ddSArun Ramadoss irq_set_chip_and_handler(irq, &ksz_irq_chip, handle_level_irq); 1818ff319a64SArun Ramadoss irq_set_noprobe(irq); 1819ff319a64SArun Ramadoss 1820ff319a64SArun Ramadoss return 0; 1821ff319a64SArun Ramadoss } 1822ff319a64SArun Ramadoss 1823*e1add7ddSArun Ramadoss static const struct irq_domain_ops ksz_irq_domain_ops = { 1824*e1add7ddSArun Ramadoss .map = ksz_irq_domain_map, 1825ff319a64SArun Ramadoss .xlate = irq_domain_xlate_twocell, 1826ff319a64SArun Ramadoss }; 1827ff319a64SArun Ramadoss 1828*e1add7ddSArun Ramadoss static void ksz_irq_free(struct ksz_irq *kirq) 1829ff319a64SArun Ramadoss { 1830ff319a64SArun Ramadoss int irq, virq; 1831ff319a64SArun Ramadoss 1832*e1add7ddSArun Ramadoss free_irq(kirq->irq_num, kirq); 1833ff319a64SArun Ramadoss 1834*e1add7ddSArun Ramadoss for (irq = 0; irq < kirq->nirqs; irq++) { 1835*e1add7ddSArun Ramadoss virq = irq_find_mapping(kirq->domain, irq); 1836ff319a64SArun Ramadoss irq_dispose_mapping(virq); 1837ff319a64SArun Ramadoss } 1838ff319a64SArun Ramadoss 1839*e1add7ddSArun Ramadoss irq_domain_remove(kirq->domain); 1840ff319a64SArun Ramadoss } 1841ff319a64SArun Ramadoss 1842*e1add7ddSArun Ramadoss static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id) 1843ff319a64SArun Ramadoss { 1844*e1add7ddSArun Ramadoss struct ksz_irq *kirq = dev_id; 1845ff319a64SArun Ramadoss unsigned int nhandled = 0; 1846*e1add7ddSArun Ramadoss struct ksz_device *dev; 1847ff319a64SArun Ramadoss unsigned int sub_irq; 1848*e1add7ddSArun Ramadoss u8 data; 1849ff319a64SArun Ramadoss int ret; 1850*e1add7ddSArun Ramadoss u8 n; 1851ff319a64SArun Ramadoss 1852*e1add7ddSArun Ramadoss dev = kirq->dev; 1853*e1add7ddSArun Ramadoss 1854*e1add7ddSArun Ramadoss /* Read interrupt status register */ 1855*e1add7ddSArun Ramadoss ret = ksz_read8(dev, kirq->reg_status, &data); 1856ff319a64SArun Ramadoss if (ret) 1857ff319a64SArun Ramadoss goto out; 1858ff319a64SArun Ramadoss 1859*e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; ++n) { 1860*e1add7ddSArun Ramadoss if (data & BIT(n)) { 1861*e1add7ddSArun Ramadoss sub_irq = irq_find_mapping(kirq->domain, n); 1862ff319a64SArun Ramadoss handle_nested_irq(sub_irq); 1863ff319a64SArun Ramadoss ++nhandled; 1864ff319a64SArun Ramadoss } 1865ff319a64SArun Ramadoss } 1866ff319a64SArun Ramadoss out: 1867ff319a64SArun Ramadoss return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 1868ff319a64SArun Ramadoss } 1869ff319a64SArun Ramadoss 1870*e1add7ddSArun Ramadoss static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq) 1871*e1add7ddSArun Ramadoss { 1872*e1add7ddSArun Ramadoss int ret, n; 1873*e1add7ddSArun Ramadoss 1874*e1add7ddSArun Ramadoss kirq->dev = dev; 1875*e1add7ddSArun Ramadoss kirq->masked = ~0; 1876*e1add7ddSArun Ramadoss 1877*e1add7ddSArun Ramadoss kirq->domain = irq_domain_add_simple(dev->dev->of_node, kirq->nirqs, 0, 1878*e1add7ddSArun Ramadoss &ksz_irq_domain_ops, kirq); 1879*e1add7ddSArun Ramadoss if (!kirq->domain) 1880*e1add7ddSArun Ramadoss return -ENOMEM; 1881*e1add7ddSArun Ramadoss 1882*e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; n++) 1883*e1add7ddSArun Ramadoss irq_create_mapping(kirq->domain, n); 1884*e1add7ddSArun Ramadoss 1885*e1add7ddSArun Ramadoss ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn, 1886*e1add7ddSArun Ramadoss IRQF_ONESHOT | IRQF_TRIGGER_FALLING, 1887*e1add7ddSArun Ramadoss kirq->name, kirq); 1888*e1add7ddSArun Ramadoss if (ret) 1889*e1add7ddSArun Ramadoss goto out; 1890*e1add7ddSArun Ramadoss 1891*e1add7ddSArun Ramadoss return 0; 1892*e1add7ddSArun Ramadoss 1893*e1add7ddSArun Ramadoss out: 1894*e1add7ddSArun Ramadoss ksz_irq_free(kirq); 1895*e1add7ddSArun Ramadoss 1896*e1add7ddSArun Ramadoss return ret; 1897*e1add7ddSArun Ramadoss } 1898*e1add7ddSArun Ramadoss 1899ff319a64SArun Ramadoss static int ksz_girq_setup(struct ksz_device *dev) 1900ff319a64SArun Ramadoss { 1901*e1add7ddSArun Ramadoss struct ksz_irq *girq = &dev->girq; 1902ff319a64SArun Ramadoss 1903*e1add7ddSArun Ramadoss girq->nirqs = dev->info->port_cnt; 1904*e1add7ddSArun Ramadoss girq->reg_mask = REG_SW_PORT_INT_MASK__1; 1905*e1add7ddSArun Ramadoss girq->reg_status = REG_SW_PORT_INT_STATUS__1; 1906*e1add7ddSArun Ramadoss snprintf(girq->name, sizeof(girq->name), "global_port_irq"); 1907ff319a64SArun Ramadoss 1908*e1add7ddSArun Ramadoss girq->irq_num = dev->irq; 1909ff319a64SArun Ramadoss 1910*e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, girq); 1911ff319a64SArun Ramadoss } 1912ff319a64SArun Ramadoss 1913ff319a64SArun Ramadoss static int ksz_pirq_setup(struct ksz_device *dev, u8 p) 1914ff319a64SArun Ramadoss { 1915*e1add7ddSArun Ramadoss struct ksz_irq *pirq = &dev->ports[p].pirq; 1916ff319a64SArun Ramadoss 1917*e1add7ddSArun Ramadoss pirq->nirqs = dev->info->port_nirqs; 1918*e1add7ddSArun Ramadoss pirq->reg_mask = dev->dev_ops->get_port_addr(p, REG_PORT_INT_MASK); 1919*e1add7ddSArun Ramadoss pirq->reg_status = dev->dev_ops->get_port_addr(p, REG_PORT_INT_STATUS); 1920*e1add7ddSArun Ramadoss snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p); 1921ff319a64SArun Ramadoss 1922*e1add7ddSArun Ramadoss pirq->irq_num = irq_find_mapping(dev->girq.domain, p); 1923*e1add7ddSArun Ramadoss if (pirq->irq_num < 0) 1924*e1add7ddSArun Ramadoss return pirq->irq_num; 1925ff319a64SArun Ramadoss 1926*e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, pirq); 1927ff319a64SArun Ramadoss } 1928ff319a64SArun Ramadoss 19291958eee8SArun Ramadoss static int ksz_setup(struct dsa_switch *ds) 1930d2822e68SArun Ramadoss { 1931d2822e68SArun Ramadoss struct ksz_device *dev = ds->priv; 1932ff319a64SArun Ramadoss struct dsa_port *dp; 193315f7cfaeSVladimir Oltean struct ksz_port *p; 19349d95329cSArun Ramadoss const u16 *regs; 1935d2822e68SArun Ramadoss int ret; 1936d2822e68SArun Ramadoss 19379d95329cSArun Ramadoss regs = dev->info->regs; 19389d95329cSArun Ramadoss 1939d2822e68SArun Ramadoss dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), 1940d2822e68SArun Ramadoss dev->info->num_vlans, GFP_KERNEL); 1941d2822e68SArun Ramadoss if (!dev->vlan_cache) 1942d2822e68SArun Ramadoss return -ENOMEM; 1943d2822e68SArun Ramadoss 1944d2822e68SArun Ramadoss ret = dev->dev_ops->reset(dev); 1945d2822e68SArun Ramadoss if (ret) { 1946d2822e68SArun Ramadoss dev_err(ds->dev, "failed to reset switch\n"); 1947d2822e68SArun Ramadoss return ret; 1948d2822e68SArun Ramadoss } 1949d2822e68SArun Ramadoss 19501ca6437fSArun Ramadoss /* set broadcast storm protection 10% rate */ 19519d95329cSArun Ramadoss regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL], 19521ca6437fSArun Ramadoss BROADCAST_STORM_RATE, 19531ca6437fSArun Ramadoss (BROADCAST_STORM_VALUE * 19541ca6437fSArun Ramadoss BROADCAST_STORM_PROT_RATE) / 100); 19551ca6437fSArun Ramadoss 1956d2822e68SArun Ramadoss dev->dev_ops->config_cpu_port(ds); 1957d2822e68SArun Ramadoss 1958d2822e68SArun Ramadoss dev->dev_ops->enable_stp_addr(dev); 1959d2822e68SArun Ramadoss 19609d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], 19610abab9f3SArun Ramadoss MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); 19620abab9f3SArun Ramadoss 1963d2822e68SArun Ramadoss ksz_init_mib_timer(dev); 1964d2822e68SArun Ramadoss 1965d2822e68SArun Ramadoss ds->configure_vlan_while_not_filtering = false; 1966d2822e68SArun Ramadoss 1967d2822e68SArun Ramadoss if (dev->dev_ops->setup) { 1968d2822e68SArun Ramadoss ret = dev->dev_ops->setup(ds); 1969d2822e68SArun Ramadoss if (ret) 1970d2822e68SArun Ramadoss return ret; 1971d2822e68SArun Ramadoss } 1972d2822e68SArun Ramadoss 197315f7cfaeSVladimir Oltean /* Start with learning disabled on standalone user ports, and enabled 197415f7cfaeSVladimir Oltean * on the CPU port. In lack of other finer mechanisms, learning on the 197515f7cfaeSVladimir Oltean * CPU port will avoid flooding bridge local addresses on the network 197615f7cfaeSVladimir Oltean * in some cases. 197715f7cfaeSVladimir Oltean */ 197815f7cfaeSVladimir Oltean p = &dev->ports[dev->cpu_port]; 197915f7cfaeSVladimir Oltean p->learning = true; 198015f7cfaeSVladimir Oltean 1981ff319a64SArun Ramadoss if (dev->irq > 0) { 1982ff319a64SArun Ramadoss ret = ksz_girq_setup(dev); 1983ff319a64SArun Ramadoss if (ret) 1984ff319a64SArun Ramadoss return ret; 1985ff319a64SArun Ramadoss 1986ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) { 1987ff319a64SArun Ramadoss ret = ksz_pirq_setup(dev, dp->index); 1988ff319a64SArun Ramadoss if (ret) 1989ff319a64SArun Ramadoss goto out_girq; 1990ff319a64SArun Ramadoss } 1991ff319a64SArun Ramadoss } 1992ff319a64SArun Ramadoss 1993ff319a64SArun Ramadoss ret = ksz_mdio_register(dev); 1994ff319a64SArun Ramadoss if (ret < 0) { 1995ff319a64SArun Ramadoss dev_err(dev->dev, "failed to register the mdio"); 1996ff319a64SArun Ramadoss goto out_pirq; 1997ff319a64SArun Ramadoss } 1998ff319a64SArun Ramadoss 1999ad08ac18SArun Ramadoss /* start switch */ 20009d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_START_CTRL], 2001ad08ac18SArun Ramadoss SW_START, SW_START); 2002ad08ac18SArun Ramadoss 2003d2822e68SArun Ramadoss return 0; 2004ff319a64SArun Ramadoss 2005ff319a64SArun Ramadoss out_pirq: 2006ff319a64SArun Ramadoss if (dev->irq > 0) 2007ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2008*e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2009ff319a64SArun Ramadoss out_girq: 2010ff319a64SArun Ramadoss if (dev->irq > 0) 2011*e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2012ff319a64SArun Ramadoss 2013ff319a64SArun Ramadoss return ret; 2014d2822e68SArun Ramadoss } 2015d2822e68SArun Ramadoss 2016c9cd961cSArun Ramadoss static void ksz_teardown(struct dsa_switch *ds) 2017c9cd961cSArun Ramadoss { 2018c9cd961cSArun Ramadoss struct ksz_device *dev = ds->priv; 2019ff319a64SArun Ramadoss struct dsa_port *dp; 2020ff319a64SArun Ramadoss 2021ff319a64SArun Ramadoss if (dev->irq > 0) { 2022ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2023*e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2024ff319a64SArun Ramadoss 2025*e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2026ff319a64SArun Ramadoss } 2027c9cd961cSArun Ramadoss 2028c9cd961cSArun Ramadoss if (dev->dev_ops->teardown) 2029c9cd961cSArun Ramadoss dev->dev_ops->teardown(ds); 2030c9cd961cSArun Ramadoss } 2031c9cd961cSArun Ramadoss 20327c6ff470STristram Ha static void port_r_cnt(struct ksz_device *dev, int port) 20337c6ff470STristram Ha { 20347c6ff470STristram Ha struct ksz_port_mib *mib = &dev->ports[port].mib; 20357c6ff470STristram Ha u64 *dropped; 20367c6ff470STristram Ha 20377c6ff470STristram Ha /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ 2038a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->reg_mib_cnt) { 20397c6ff470STristram Ha dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, 20407c6ff470STristram Ha &mib->counters[mib->cnt_ptr]); 20417c6ff470STristram Ha ++mib->cnt_ptr; 20427c6ff470STristram Ha } 20437c6ff470STristram Ha 20447c6ff470STristram Ha /* last one in storage */ 2045a530e6f2SArun Ramadoss dropped = &mib->counters[dev->info->mib_cnt]; 20467c6ff470STristram Ha 20477c6ff470STristram Ha /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ 2048a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->mib_cnt) { 20497c6ff470STristram Ha dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, 20507c6ff470STristram Ha dropped, &mib->counters[mib->cnt_ptr]); 20517c6ff470STristram Ha ++mib->cnt_ptr; 20527c6ff470STristram Ha } 20537c6ff470STristram Ha mib->cnt_ptr = 0; 20547c6ff470STristram Ha } 20557c6ff470STristram Ha 20567c6ff470STristram Ha static void ksz_mib_read_work(struct work_struct *work) 20577c6ff470STristram Ha { 20587c6ff470STristram Ha struct ksz_device *dev = container_of(work, struct ksz_device, 2059469b390eSGeorge McCollister mib_read.work); 20607c6ff470STristram Ha struct ksz_port_mib *mib; 20617c6ff470STristram Ha struct ksz_port *p; 20627c6ff470STristram Ha int i; 20637c6ff470STristram Ha 2064462d5250SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 20656bb9e376SRobert Hancock if (dsa_is_unused_port(dev->ds, i)) 20666bb9e376SRobert Hancock continue; 20676bb9e376SRobert Hancock 20687c6ff470STristram Ha p = &dev->ports[i]; 20697c6ff470STristram Ha mib = &p->mib; 20707c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 20717c6ff470STristram Ha 20727c6ff470STristram Ha /* Only read MIB counters when the port is told to do. 20737c6ff470STristram Ha * If not, read only dropped counters when link is not up. 20747c6ff470STristram Ha */ 20757c6ff470STristram Ha if (!p->read) { 20767c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(dev->ds, i); 20777c6ff470STristram Ha 20787c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2079a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 20807c6ff470STristram Ha } 20817c6ff470STristram Ha port_r_cnt(dev, i); 20827c6ff470STristram Ha p->read = false; 2083a7f4f13aSOleksij Rempel 2084a7f4f13aSOleksij Rempel if (dev->dev_ops->r_mib_stat64) 2085a7f4f13aSOleksij Rempel dev->dev_ops->r_mib_stat64(dev, i); 2086a7f4f13aSOleksij Rempel 20877c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 20887c6ff470STristram Ha } 20897c6ff470STristram Ha 2090469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, dev->mib_read_interval); 20917c6ff470STristram Ha } 20927c6ff470STristram Ha 20937c6ff470STristram Ha void ksz_init_mib_timer(struct ksz_device *dev) 20947c6ff470STristram Ha { 20957c6ff470STristram Ha int i; 20967c6ff470STristram Ha 2097469b390eSGeorge McCollister INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work); 2098469b390eSGeorge McCollister 2099b094c679SPrasanna Vengateshan for (i = 0; i < dev->info->port_cnt; i++) { 2100b094c679SPrasanna Vengateshan struct ksz_port_mib *mib = &dev->ports[i].mib; 2101b094c679SPrasanna Vengateshan 21027c6ff470STristram Ha dev->dev_ops->port_init_cnt(dev, i); 2103b094c679SPrasanna Vengateshan 2104b094c679SPrasanna Vengateshan mib->cnt_ptr = 0; 2105b094c679SPrasanna Vengateshan memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64)); 2106b094c679SPrasanna Vengateshan } 21077c6ff470STristram Ha } 21087c6ff470STristram Ha 21091958eee8SArun Ramadoss static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) 2110b987e98eSWoojung Huh { 2111b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2112c2e86691STristram Ha u16 val = 0xffff; 21138f420456SOleksij Rempel int ret; 2114b987e98eSWoojung Huh 21158f420456SOleksij Rempel ret = dev->dev_ops->r_phy(dev, addr, reg, &val); 21168f420456SOleksij Rempel if (ret) 21178f420456SOleksij Rempel return ret; 2118b987e98eSWoojung Huh 2119b987e98eSWoojung Huh return val; 2120b987e98eSWoojung Huh } 2121b987e98eSWoojung Huh 21221958eee8SArun Ramadoss static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) 2123b987e98eSWoojung Huh { 2124b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 21258f420456SOleksij Rempel int ret; 2126b987e98eSWoojung Huh 21278f420456SOleksij Rempel ret = dev->dev_ops->w_phy(dev, addr, reg, val); 21288f420456SOleksij Rempel if (ret) 21298f420456SOleksij Rempel return ret; 2130b987e98eSWoojung Huh 2131b987e98eSWoojung Huh return 0; 2132b987e98eSWoojung Huh } 2133b987e98eSWoojung Huh 21341958eee8SArun Ramadoss static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) 21351fe94f54SArun Ramadoss { 21361fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 21371fe94f54SArun Ramadoss 21381fe94f54SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID) { 21391fe94f54SArun Ramadoss /* Silicon Errata Sheet (DS80000830A): 21401fe94f54SArun Ramadoss * Port 1 does not work with LinkMD Cable-Testing. 21411fe94f54SArun Ramadoss * Port 1 does not respond to received PAUSE control frames. 21421fe94f54SArun Ramadoss */ 21431fe94f54SArun Ramadoss if (!port) 21441fe94f54SArun Ramadoss return MICREL_KSZ8_P1_ERRATA; 21451fe94f54SArun Ramadoss } 21461fe94f54SArun Ramadoss 21471fe94f54SArun Ramadoss return 0; 21481fe94f54SArun Ramadoss } 21491fe94f54SArun Ramadoss 21501958eee8SArun Ramadoss static void ksz_mac_link_down(struct dsa_switch *ds, int port, 21511958eee8SArun Ramadoss unsigned int mode, phy_interface_t interface) 2152c30d894bSTristram Ha { 2153c30d894bSTristram Ha struct ksz_device *dev = ds->priv; 2154c30d894bSTristram Ha struct ksz_port *p = &dev->ports[port]; 2155c30d894bSTristram Ha 2156c30d894bSTristram Ha /* Read all MIB counters when the link is going down. */ 2157c30d894bSTristram Ha p->read = true; 21588098bd69SChristian Eggers /* timer started */ 21598098bd69SChristian Eggers if (dev->mib_read_interval) 2160469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, 0); 2161143a102eSCodrin Ciubotariu } 2162143a102eSCodrin Ciubotariu 21631958eee8SArun Ramadoss static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) 2164b987e98eSWoojung Huh { 2165b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2166b987e98eSWoojung Huh 216789f09048SFlorian Fainelli if (sset != ETH_SS_STATS) 216889f09048SFlorian Fainelli return 0; 216989f09048SFlorian Fainelli 2170a530e6f2SArun Ramadoss return dev->info->mib_cnt; 2171b987e98eSWoojung Huh } 2172b987e98eSWoojung Huh 21731958eee8SArun Ramadoss static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, 21741958eee8SArun Ramadoss uint64_t *buf) 21757c6ff470STristram Ha { 21767c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(ds, port); 21777c6ff470STristram Ha struct ksz_device *dev = ds->priv; 21787c6ff470STristram Ha struct ksz_port_mib *mib; 21797c6ff470STristram Ha 21807c6ff470STristram Ha mib = &dev->ports[port].mib; 21817c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 21827c6ff470STristram Ha 21837c6ff470STristram Ha /* Only read dropped counters if no link. */ 21847c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2185a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 21867c6ff470STristram Ha port_r_cnt(dev, port); 2187a530e6f2SArun Ramadoss memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64)); 21887c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 21897c6ff470STristram Ha } 21907c6ff470STristram Ha 21911958eee8SArun Ramadoss static int ksz_port_bridge_join(struct dsa_switch *ds, int port, 2192b079922bSVladimir Oltean struct dsa_bridge bridge, 219306b9cce4SVladimir Oltean bool *tx_fwd_offload, 219406b9cce4SVladimir Oltean struct netlink_ext_ack *extack) 2195b987e98eSWoojung Huh { 2196c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2197c2e86691STristram Ha * appropriate state so there is no need to do anything. 2198c2e86691STristram Ha */ 2199b987e98eSWoojung Huh 2200b987e98eSWoojung Huh return 0; 2201b987e98eSWoojung Huh } 2202b987e98eSWoojung Huh 22031958eee8SArun Ramadoss static void ksz_port_bridge_leave(struct dsa_switch *ds, int port, 2204d3eed0e5SVladimir Oltean struct dsa_bridge bridge) 2205c2e86691STristram Ha { 2206c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2207c2e86691STristram Ha * forwarding state so there is no need to do anything. 2208c2e86691STristram Ha */ 2209c2e86691STristram Ha } 2210c2e86691STristram Ha 22111958eee8SArun Ramadoss static void ksz_port_fast_age(struct dsa_switch *ds, int port) 2212c2e86691STristram Ha { 2213c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2214c2e86691STristram Ha 2215c2e86691STristram Ha dev->dev_ops->flush_dyn_mac_table(dev, port); 2216c2e86691STristram Ha } 2217c2e86691STristram Ha 22182c119d99SArun Ramadoss static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) 22192c119d99SArun Ramadoss { 22202c119d99SArun Ramadoss struct ksz_device *dev = ds->priv; 22212c119d99SArun Ramadoss 22222c119d99SArun Ramadoss if (!dev->dev_ops->set_ageing_time) 22232c119d99SArun Ramadoss return -EOPNOTSUPP; 22242c119d99SArun Ramadoss 22252c119d99SArun Ramadoss return dev->dev_ops->set_ageing_time(dev, msecs); 22262c119d99SArun Ramadoss } 22272c119d99SArun Ramadoss 22281958eee8SArun Ramadoss static int ksz_port_fdb_add(struct dsa_switch *ds, int port, 22291958eee8SArun Ramadoss const unsigned char *addr, u16 vid, 22301958eee8SArun Ramadoss struct dsa_db db) 2231e587be75SArun Ramadoss { 2232e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2233e587be75SArun Ramadoss 2234e587be75SArun Ramadoss if (!dev->dev_ops->fdb_add) 2235e587be75SArun Ramadoss return -EOPNOTSUPP; 2236e587be75SArun Ramadoss 2237e587be75SArun Ramadoss return dev->dev_ops->fdb_add(dev, port, addr, vid, db); 2238e587be75SArun Ramadoss } 2239e587be75SArun Ramadoss 22401958eee8SArun Ramadoss static int ksz_port_fdb_del(struct dsa_switch *ds, int port, 22411958eee8SArun Ramadoss const unsigned char *addr, 22421958eee8SArun Ramadoss u16 vid, struct dsa_db db) 2243e587be75SArun Ramadoss { 2244e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2245e587be75SArun Ramadoss 2246e587be75SArun Ramadoss if (!dev->dev_ops->fdb_del) 2247e587be75SArun Ramadoss return -EOPNOTSUPP; 2248e587be75SArun Ramadoss 2249e587be75SArun Ramadoss return dev->dev_ops->fdb_del(dev, port, addr, vid, db); 2250e587be75SArun Ramadoss } 2251e587be75SArun Ramadoss 22521958eee8SArun Ramadoss static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, 22531958eee8SArun Ramadoss dsa_fdb_dump_cb_t *cb, void *data) 2254b987e98eSWoojung Huh { 2255b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2256b987e98eSWoojung Huh 2257e587be75SArun Ramadoss if (!dev->dev_ops->fdb_dump) 2258e587be75SArun Ramadoss return -EOPNOTSUPP; 2259b987e98eSWoojung Huh 2260e587be75SArun Ramadoss return dev->dev_ops->fdb_dump(dev, port, cb, data); 2261b987e98eSWoojung Huh } 2262b987e98eSWoojung Huh 22631958eee8SArun Ramadoss static int ksz_port_mdb_add(struct dsa_switch *ds, int port, 2264c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2265c2693363SVladimir Oltean struct dsa_db db) 2266b987e98eSWoojung Huh { 2267b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2268b987e98eSWoojung Huh 2269980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_add) 2270980c7d17SArun Ramadoss return -EOPNOTSUPP; 2271b987e98eSWoojung Huh 2272980c7d17SArun Ramadoss return dev->dev_ops->mdb_add(dev, port, mdb, db); 2273c2e86691STristram Ha } 2274c2e86691STristram Ha 22751958eee8SArun Ramadoss static int ksz_port_mdb_del(struct dsa_switch *ds, int port, 2276c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2277c2693363SVladimir Oltean struct dsa_db db) 2278c2e86691STristram Ha { 2279c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2280b987e98eSWoojung Huh 2281980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_del) 2282980c7d17SArun Ramadoss return -EOPNOTSUPP; 2283b987e98eSWoojung Huh 2284980c7d17SArun Ramadoss return dev->dev_ops->mdb_del(dev, port, mdb, db); 2285b987e98eSWoojung Huh } 2286b987e98eSWoojung Huh 22871958eee8SArun Ramadoss static int ksz_enable_port(struct dsa_switch *ds, int port, 22881958eee8SArun Ramadoss struct phy_device *phy) 2289b987e98eSWoojung Huh { 2290b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2291b987e98eSWoojung Huh 229274be4babSVivien Didelot if (!dsa_is_user_port(ds, port)) 229374be4babSVivien Didelot return 0; 229474be4babSVivien Didelot 2295c2e86691STristram Ha /* setup slave port */ 2296c2e86691STristram Ha dev->dev_ops->port_setup(dev, port, false); 2297b987e98eSWoojung Huh 2298c2e86691STristram Ha /* port_stp_state_set() will be called after to enable the port so 2299c2e86691STristram Ha * there is no need to do anything. 2300c2e86691STristram Ha */ 2301b987e98eSWoojung Huh 2302b987e98eSWoojung Huh return 0; 2303b987e98eSWoojung Huh } 2304b987e98eSWoojung Huh 2305e593df51SArun Ramadoss void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) 2306de6dd626SArun Ramadoss { 2307de6dd626SArun Ramadoss struct ksz_device *dev = ds->priv; 2308de6dd626SArun Ramadoss struct ksz_port *p; 23096877102fSArun Ramadoss const u16 *regs; 2310de6dd626SArun Ramadoss u8 data; 2311e593df51SArun Ramadoss 23126877102fSArun Ramadoss regs = dev->info->regs; 2313de6dd626SArun Ramadoss 23146877102fSArun Ramadoss ksz_pread8(dev, port, regs[P_STP_CTRL], &data); 2315de6dd626SArun Ramadoss data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2316de6dd626SArun Ramadoss 231715f7cfaeSVladimir Oltean p = &dev->ports[port]; 231815f7cfaeSVladimir Oltean 2319de6dd626SArun Ramadoss switch (state) { 2320de6dd626SArun Ramadoss case BR_STATE_DISABLED: 2321de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2322de6dd626SArun Ramadoss break; 2323de6dd626SArun Ramadoss case BR_STATE_LISTENING: 2324de6dd626SArun Ramadoss data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2325de6dd626SArun Ramadoss break; 2326de6dd626SArun Ramadoss case BR_STATE_LEARNING: 2327de6dd626SArun Ramadoss data |= PORT_RX_ENABLE; 232815f7cfaeSVladimir Oltean if (!p->learning) 232915f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2330de6dd626SArun Ramadoss break; 2331de6dd626SArun Ramadoss case BR_STATE_FORWARDING: 2332de6dd626SArun Ramadoss data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); 233315f7cfaeSVladimir Oltean if (!p->learning) 233415f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2335de6dd626SArun Ramadoss break; 2336de6dd626SArun Ramadoss case BR_STATE_BLOCKING: 2337de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2338de6dd626SArun Ramadoss break; 2339de6dd626SArun Ramadoss default: 2340de6dd626SArun Ramadoss dev_err(ds->dev, "invalid STP state: %d\n", state); 2341de6dd626SArun Ramadoss return; 2342de6dd626SArun Ramadoss } 2343de6dd626SArun Ramadoss 23446877102fSArun Ramadoss ksz_pwrite8(dev, port, regs[P_STP_CTRL], data); 2345de6dd626SArun Ramadoss 2346de6dd626SArun Ramadoss p->stp_state = state; 2347de6dd626SArun Ramadoss 2348de6dd626SArun Ramadoss ksz_update_port_member(dev, port); 2349de6dd626SArun Ramadoss } 2350de6dd626SArun Ramadoss 235115f7cfaeSVladimir Oltean static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, 235215f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 235315f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 235415f7cfaeSVladimir Oltean { 235515f7cfaeSVladimir Oltean if (flags.mask & ~BR_LEARNING) 235615f7cfaeSVladimir Oltean return -EINVAL; 235715f7cfaeSVladimir Oltean 235815f7cfaeSVladimir Oltean return 0; 235915f7cfaeSVladimir Oltean } 236015f7cfaeSVladimir Oltean 236115f7cfaeSVladimir Oltean static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, 236215f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 236315f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 236415f7cfaeSVladimir Oltean { 236515f7cfaeSVladimir Oltean struct ksz_device *dev = ds->priv; 236615f7cfaeSVladimir Oltean struct ksz_port *p = &dev->ports[port]; 236715f7cfaeSVladimir Oltean 236815f7cfaeSVladimir Oltean if (flags.mask & BR_LEARNING) { 236915f7cfaeSVladimir Oltean p->learning = !!(flags.val & BR_LEARNING); 237015f7cfaeSVladimir Oltean 237115f7cfaeSVladimir Oltean /* Make the change take effect immediately */ 237215f7cfaeSVladimir Oltean ksz_port_stp_state_set(ds, port, p->stp_state); 237315f7cfaeSVladimir Oltean } 237415f7cfaeSVladimir Oltean 237515f7cfaeSVladimir Oltean return 0; 237615f7cfaeSVladimir Oltean } 237715f7cfaeSVladimir Oltean 23781958eee8SArun Ramadoss static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, 23791958eee8SArun Ramadoss int port, 23801958eee8SArun Ramadoss enum dsa_tag_protocol mp) 2381534a0431SArun Ramadoss { 2382534a0431SArun Ramadoss struct ksz_device *dev = ds->priv; 2383534a0431SArun Ramadoss enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; 2384534a0431SArun Ramadoss 2385534a0431SArun Ramadoss if (dev->chip_id == KSZ8795_CHIP_ID || 2386534a0431SArun Ramadoss dev->chip_id == KSZ8794_CHIP_ID || 2387534a0431SArun Ramadoss dev->chip_id == KSZ8765_CHIP_ID) 2388534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ8795; 2389534a0431SArun Ramadoss 2390534a0431SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID || 2391b4490809SOleksij Rempel dev->chip_id == KSZ8563_CHIP_ID || 2392534a0431SArun Ramadoss dev->chip_id == KSZ9893_CHIP_ID) 2393534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9893; 2394534a0431SArun Ramadoss 2395534a0431SArun Ramadoss if (dev->chip_id == KSZ9477_CHIP_ID || 23962eb3ff3cSRomain Naour dev->chip_id == KSZ9896_CHIP_ID || 2397534a0431SArun Ramadoss dev->chip_id == KSZ9897_CHIP_ID || 2398534a0431SArun Ramadoss dev->chip_id == KSZ9567_CHIP_ID) 2399534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9477; 2400534a0431SArun Ramadoss 240199b16df0SArun Ramadoss if (is_lan937x(dev)) 240299b16df0SArun Ramadoss proto = DSA_TAG_PROTO_LAN937X_VALUE; 240399b16df0SArun Ramadoss 2404534a0431SArun Ramadoss return proto; 2405534a0431SArun Ramadoss } 2406534a0431SArun Ramadoss 24071958eee8SArun Ramadoss static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, 2408f0d997e3SArun Ramadoss bool flag, struct netlink_ext_ack *extack) 2409f0d997e3SArun Ramadoss { 2410f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2411f0d997e3SArun Ramadoss 2412f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_filtering) 2413f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2414f0d997e3SArun Ramadoss 2415f0d997e3SArun Ramadoss return dev->dev_ops->vlan_filtering(dev, port, flag, extack); 2416f0d997e3SArun Ramadoss } 2417f0d997e3SArun Ramadoss 24181958eee8SArun Ramadoss static int ksz_port_vlan_add(struct dsa_switch *ds, int port, 2419f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan, 2420f0d997e3SArun Ramadoss struct netlink_ext_ack *extack) 2421f0d997e3SArun Ramadoss { 2422f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2423f0d997e3SArun Ramadoss 2424f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_add) 2425f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2426f0d997e3SArun Ramadoss 2427f0d997e3SArun Ramadoss return dev->dev_ops->vlan_add(dev, port, vlan, extack); 2428f0d997e3SArun Ramadoss } 2429f0d997e3SArun Ramadoss 24301958eee8SArun Ramadoss static int ksz_port_vlan_del(struct dsa_switch *ds, int port, 2431f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan) 2432f0d997e3SArun Ramadoss { 2433f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2434f0d997e3SArun Ramadoss 2435f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_del) 2436f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2437f0d997e3SArun Ramadoss 2438f0d997e3SArun Ramadoss return dev->dev_ops->vlan_del(dev, port, vlan); 2439f0d997e3SArun Ramadoss } 2440f0d997e3SArun Ramadoss 24411958eee8SArun Ramadoss static int ksz_port_mirror_add(struct dsa_switch *ds, int port, 244200a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror, 244300a298bbSArun Ramadoss bool ingress, struct netlink_ext_ack *extack) 244400a298bbSArun Ramadoss { 244500a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 244600a298bbSArun Ramadoss 244700a298bbSArun Ramadoss if (!dev->dev_ops->mirror_add) 244800a298bbSArun Ramadoss return -EOPNOTSUPP; 244900a298bbSArun Ramadoss 245000a298bbSArun Ramadoss return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack); 245100a298bbSArun Ramadoss } 245200a298bbSArun Ramadoss 24531958eee8SArun Ramadoss static void ksz_port_mirror_del(struct dsa_switch *ds, int port, 245400a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror) 245500a298bbSArun Ramadoss { 245600a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 245700a298bbSArun Ramadoss 245800a298bbSArun Ramadoss if (dev->dev_ops->mirror_del) 245900a298bbSArun Ramadoss dev->dev_ops->mirror_del(dev, port, mirror); 246000a298bbSArun Ramadoss } 246100a298bbSArun Ramadoss 24621958eee8SArun Ramadoss static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) 24631fe94f54SArun Ramadoss { 24641fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 24651fe94f54SArun Ramadoss 24661fe94f54SArun Ramadoss if (!dev->dev_ops->change_mtu) 24671fe94f54SArun Ramadoss return -EOPNOTSUPP; 24681fe94f54SArun Ramadoss 24691fe94f54SArun Ramadoss return dev->dev_ops->change_mtu(dev, port, mtu); 24701fe94f54SArun Ramadoss } 24711fe94f54SArun Ramadoss 24721958eee8SArun Ramadoss static int ksz_max_mtu(struct dsa_switch *ds, int port) 24731fe94f54SArun Ramadoss { 24741fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 24751fe94f54SArun Ramadoss 24761fe94f54SArun Ramadoss if (!dev->dev_ops->max_mtu) 24771fe94f54SArun Ramadoss return -EOPNOTSUPP; 24781fe94f54SArun Ramadoss 24791fe94f54SArun Ramadoss return dev->dev_ops->max_mtu(dev, port); 24801fe94f54SArun Ramadoss } 24811fe94f54SArun Ramadoss 2482f3d890f5SArun Ramadoss static void ksz_set_xmii(struct ksz_device *dev, int port, 2483f3d890f5SArun Ramadoss phy_interface_t interface) 2484dc1c596eSArun Ramadoss { 2485dc1c596eSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 2486b19ac41fSArun Ramadoss struct ksz_port *p = &dev->ports[port]; 2487dc1c596eSArun Ramadoss const u16 *regs = dev->info->regs; 2488dc1c596eSArun Ramadoss u8 data8; 2489dc1c596eSArun Ramadoss 2490dc1c596eSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 2491dc1c596eSArun Ramadoss 2492b19ac41fSArun Ramadoss data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE | 2493b19ac41fSArun Ramadoss P_RGMII_ID_EG_ENABLE); 2494dc1c596eSArun Ramadoss 2495dc1c596eSArun Ramadoss switch (interface) { 2496dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_MII: 2497dc1c596eSArun Ramadoss data8 |= bitval[P_MII_SEL]; 2498dc1c596eSArun Ramadoss break; 2499dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RMII: 2500dc1c596eSArun Ramadoss data8 |= bitval[P_RMII_SEL]; 2501dc1c596eSArun Ramadoss break; 2502dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_GMII: 2503dc1c596eSArun Ramadoss data8 |= bitval[P_GMII_SEL]; 2504dc1c596eSArun Ramadoss break; 2505dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII: 2506dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_ID: 2507dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_TXID: 2508dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_RXID: 2509dc1c596eSArun Ramadoss data8 |= bitval[P_RGMII_SEL]; 25100ab7f6bfSArun Ramadoss /* On KSZ9893, disable RGMII in-band status support */ 251132cbac21SOleksij Rempel if (dev->chip_id == KSZ9893_CHIP_ID || 251232cbac21SOleksij Rempel dev->chip_id == KSZ8563_CHIP_ID) 25130ab7f6bfSArun Ramadoss data8 &= ~P_MII_MAC_MODE; 2514dc1c596eSArun Ramadoss break; 2515dc1c596eSArun Ramadoss default: 2516dc1c596eSArun Ramadoss dev_err(dev->dev, "Unsupported interface '%s' for port %d\n", 2517dc1c596eSArun Ramadoss phy_modes(interface), port); 2518dc1c596eSArun Ramadoss return; 2519dc1c596eSArun Ramadoss } 2520dc1c596eSArun Ramadoss 2521b19ac41fSArun Ramadoss if (p->rgmii_tx_val) 2522b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_EG_ENABLE; 2523b19ac41fSArun Ramadoss 2524b19ac41fSArun Ramadoss if (p->rgmii_rx_val) 2525b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_IG_ENABLE; 2526b19ac41fSArun Ramadoss 2527dc1c596eSArun Ramadoss /* Write the updated value */ 2528dc1c596eSArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 2529dc1c596eSArun Ramadoss } 2530dc1c596eSArun Ramadoss 25310ab7f6bfSArun Ramadoss phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) 25320ab7f6bfSArun Ramadoss { 25330ab7f6bfSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 25340ab7f6bfSArun Ramadoss const u16 *regs = dev->info->regs; 25350ab7f6bfSArun Ramadoss phy_interface_t interface; 25360ab7f6bfSArun Ramadoss u8 data8; 25370ab7f6bfSArun Ramadoss u8 val; 25380ab7f6bfSArun Ramadoss 25390ab7f6bfSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 25400ab7f6bfSArun Ramadoss 25410ab7f6bfSArun Ramadoss val = FIELD_GET(P_MII_SEL_M, data8); 25420ab7f6bfSArun Ramadoss 25430ab7f6bfSArun Ramadoss if (val == bitval[P_MII_SEL]) { 25440ab7f6bfSArun Ramadoss if (gbit) 25450ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_GMII; 25460ab7f6bfSArun Ramadoss else 25470ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_MII; 25480ab7f6bfSArun Ramadoss } else if (val == bitval[P_RMII_SEL]) { 25490ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 25500ab7f6bfSArun Ramadoss } else { 25510ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 25520ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 25530ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_TXID; 25540ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_IG_ENABLE) { 25550ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_RXID; 25560ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 25570ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_ID; 25580ab7f6bfSArun Ramadoss } 25590ab7f6bfSArun Ramadoss } 25600ab7f6bfSArun Ramadoss 25610ab7f6bfSArun Ramadoss return interface; 25620ab7f6bfSArun Ramadoss } 25630ab7f6bfSArun Ramadoss 2564a0cb1aa4SArun Ramadoss static void ksz_phylink_mac_config(struct dsa_switch *ds, int port, 2565a0cb1aa4SArun Ramadoss unsigned int mode, 2566a0cb1aa4SArun Ramadoss const struct phylink_link_state *state) 2567a0cb1aa4SArun Ramadoss { 2568a0cb1aa4SArun Ramadoss struct ksz_device *dev = ds->priv; 2569a0cb1aa4SArun Ramadoss 2570f3d890f5SArun Ramadoss if (ksz_is_ksz88x3(dev)) 2571f3d890f5SArun Ramadoss return; 2572f3d890f5SArun Ramadoss 2573f3d890f5SArun Ramadoss /* Internal PHYs */ 2574f3d890f5SArun Ramadoss if (dev->info->internal_phy[port]) 2575f3d890f5SArun Ramadoss return; 2576f3d890f5SArun Ramadoss 2577f3d890f5SArun Ramadoss if (phylink_autoneg_inband(mode)) { 2578f3d890f5SArun Ramadoss dev_err(dev->dev, "In-band AN not supported!\n"); 2579f3d890f5SArun Ramadoss return; 2580f3d890f5SArun Ramadoss } 2581f3d890f5SArun Ramadoss 2582f3d890f5SArun Ramadoss ksz_set_xmii(dev, port, state->interface); 2583f3d890f5SArun Ramadoss 2584a0cb1aa4SArun Ramadoss if (dev->dev_ops->phylink_mac_config) 2585a0cb1aa4SArun Ramadoss dev->dev_ops->phylink_mac_config(dev, port, mode, state); 2586b19ac41fSArun Ramadoss 2587b19ac41fSArun Ramadoss if (dev->dev_ops->setup_rgmii_delay) 2588b19ac41fSArun Ramadoss dev->dev_ops->setup_rgmii_delay(dev, port); 2589a0cb1aa4SArun Ramadoss } 2590a0cb1aa4SArun Ramadoss 259146f80fa8SArun Ramadoss bool ksz_get_gbit(struct ksz_device *dev, int port) 259246f80fa8SArun Ramadoss { 259346f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 259446f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 259546f80fa8SArun Ramadoss bool gbit = false; 259646f80fa8SArun Ramadoss u8 data8; 259746f80fa8SArun Ramadoss bool val; 259846f80fa8SArun Ramadoss 259946f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 260046f80fa8SArun Ramadoss 260146f80fa8SArun Ramadoss val = FIELD_GET(P_GMII_1GBIT_M, data8); 260246f80fa8SArun Ramadoss 260346f80fa8SArun Ramadoss if (val == bitval[P_GMII_1GBIT]) 260446f80fa8SArun Ramadoss gbit = true; 260546f80fa8SArun Ramadoss 260646f80fa8SArun Ramadoss return gbit; 260746f80fa8SArun Ramadoss } 260846f80fa8SArun Ramadoss 26090ab7f6bfSArun Ramadoss static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit) 261046f80fa8SArun Ramadoss { 261146f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 261246f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 261346f80fa8SArun Ramadoss u8 data8; 261446f80fa8SArun Ramadoss 261546f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 261646f80fa8SArun Ramadoss 261746f80fa8SArun Ramadoss data8 &= ~P_GMII_1GBIT_M; 261846f80fa8SArun Ramadoss 261946f80fa8SArun Ramadoss if (gbit) 262046f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); 262146f80fa8SArun Ramadoss else 262246f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); 262346f80fa8SArun Ramadoss 262446f80fa8SArun Ramadoss /* Write the updated value */ 262546f80fa8SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 262646f80fa8SArun Ramadoss } 262746f80fa8SArun Ramadoss 2628aa5b8b73SArun Ramadoss static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed) 2629aa5b8b73SArun Ramadoss { 2630aa5b8b73SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 2631aa5b8b73SArun Ramadoss const u16 *regs = dev->info->regs; 2632aa5b8b73SArun Ramadoss u8 data8; 2633aa5b8b73SArun Ramadoss 2634aa5b8b73SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); 2635aa5b8b73SArun Ramadoss 2636aa5b8b73SArun Ramadoss data8 &= ~P_MII_100MBIT_M; 2637aa5b8b73SArun Ramadoss 2638aa5b8b73SArun Ramadoss if (speed == SPEED_100) 2639aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); 2640aa5b8b73SArun Ramadoss else 2641aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); 2642aa5b8b73SArun Ramadoss 2643aa5b8b73SArun Ramadoss /* Write the updated value */ 2644aa5b8b73SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); 2645aa5b8b73SArun Ramadoss } 2646aa5b8b73SArun Ramadoss 2647da8cd085SArun Ramadoss static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed) 2648aa5b8b73SArun Ramadoss { 2649aa5b8b73SArun Ramadoss if (speed == SPEED_1000) 2650aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, true); 2651aa5b8b73SArun Ramadoss else 2652aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, false); 2653aa5b8b73SArun Ramadoss 2654aa5b8b73SArun Ramadoss if (speed == SPEED_100 || speed == SPEED_10) 2655aa5b8b73SArun Ramadoss ksz_set_100_10mbit(dev, port, speed); 2656aa5b8b73SArun Ramadoss } 2657aa5b8b73SArun Ramadoss 2658da8cd085SArun Ramadoss static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex, 26598560664fSArun Ramadoss bool tx_pause, bool rx_pause) 26608560664fSArun Ramadoss { 26618560664fSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 26628560664fSArun Ramadoss const u32 *masks = dev->info->masks; 26638560664fSArun Ramadoss const u16 *regs = dev->info->regs; 26648560664fSArun Ramadoss u8 mask; 26658560664fSArun Ramadoss u8 val; 26668560664fSArun Ramadoss 26678560664fSArun Ramadoss mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] | 26688560664fSArun Ramadoss masks[P_MII_RX_FLOW_CTRL]; 26698560664fSArun Ramadoss 26708560664fSArun Ramadoss if (duplex == DUPLEX_FULL) 26718560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]); 26728560664fSArun Ramadoss else 26738560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]); 26748560664fSArun Ramadoss 26758560664fSArun Ramadoss if (tx_pause) 26768560664fSArun Ramadoss val |= masks[P_MII_TX_FLOW_CTRL]; 26778560664fSArun Ramadoss 26788560664fSArun Ramadoss if (rx_pause) 26798560664fSArun Ramadoss val |= masks[P_MII_RX_FLOW_CTRL]; 26808560664fSArun Ramadoss 26818560664fSArun Ramadoss ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val); 26828560664fSArun Ramadoss } 26838560664fSArun Ramadoss 26843015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 2685f597d3adSArun Ramadoss unsigned int mode, 2686f597d3adSArun Ramadoss phy_interface_t interface, 2687f597d3adSArun Ramadoss struct phy_device *phydev, int speed, 26883015c503SOleksij Rempel int duplex, bool tx_pause, 26893015c503SOleksij Rempel bool rx_pause) 2690f597d3adSArun Ramadoss { 2691da8cd085SArun Ramadoss struct ksz_port *p; 2692da8cd085SArun Ramadoss 2693da8cd085SArun Ramadoss p = &dev->ports[port]; 2694da8cd085SArun Ramadoss 2695da8cd085SArun Ramadoss /* Internal PHYs */ 2696da8cd085SArun Ramadoss if (dev->info->internal_phy[port]) 2697da8cd085SArun Ramadoss return; 2698da8cd085SArun Ramadoss 2699da8cd085SArun Ramadoss p->phydev.speed = speed; 2700da8cd085SArun Ramadoss 2701da8cd085SArun Ramadoss ksz_port_set_xmii_speed(dev, port, speed); 2702da8cd085SArun Ramadoss 2703da8cd085SArun Ramadoss ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause); 27043015c503SOleksij Rempel } 27053015c503SOleksij Rempel 27063015c503SOleksij Rempel static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port, 27073015c503SOleksij Rempel unsigned int mode, 27083015c503SOleksij Rempel phy_interface_t interface, 27093015c503SOleksij Rempel struct phy_device *phydev, int speed, 27103015c503SOleksij Rempel int duplex, bool tx_pause, bool rx_pause) 27113015c503SOleksij Rempel { 27123015c503SOleksij Rempel struct ksz_device *dev = ds->priv; 2713f597d3adSArun Ramadoss 2714f597d3adSArun Ramadoss if (dev->dev_ops->phylink_mac_link_up) 2715f597d3adSArun Ramadoss dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface, 2716f597d3adSArun Ramadoss phydev, speed, duplex, 2717f597d3adSArun Ramadoss tx_pause, rx_pause); 2718f597d3adSArun Ramadoss } 2719f597d3adSArun Ramadoss 272091a98917SArun Ramadoss static int ksz_switch_detect(struct ksz_device *dev) 272191a98917SArun Ramadoss { 2722b4490809SOleksij Rempel u8 id1, id2, id4; 272391a98917SArun Ramadoss u16 id16; 272491a98917SArun Ramadoss u32 id32; 272591a98917SArun Ramadoss int ret; 272691a98917SArun Ramadoss 272791a98917SArun Ramadoss /* read chip id */ 272891a98917SArun Ramadoss ret = ksz_read16(dev, REG_CHIP_ID0, &id16); 272991a98917SArun Ramadoss if (ret) 273091a98917SArun Ramadoss return ret; 273191a98917SArun Ramadoss 273291a98917SArun Ramadoss id1 = FIELD_GET(SW_FAMILY_ID_M, id16); 273391a98917SArun Ramadoss id2 = FIELD_GET(SW_CHIP_ID_M, id16); 273491a98917SArun Ramadoss 273591a98917SArun Ramadoss switch (id1) { 273691a98917SArun Ramadoss case KSZ87_FAMILY_ID: 273791a98917SArun Ramadoss if (id2 == KSZ87_CHIP_ID_95) { 273891a98917SArun Ramadoss u8 val; 273991a98917SArun Ramadoss 274091a98917SArun Ramadoss dev->chip_id = KSZ8795_CHIP_ID; 274191a98917SArun Ramadoss 274291a98917SArun Ramadoss ksz_read8(dev, KSZ8_PORT_STATUS_0, &val); 274391a98917SArun Ramadoss if (val & KSZ8_PORT_FIBER_MODE) 274491a98917SArun Ramadoss dev->chip_id = KSZ8765_CHIP_ID; 274591a98917SArun Ramadoss } else if (id2 == KSZ87_CHIP_ID_94) { 274691a98917SArun Ramadoss dev->chip_id = KSZ8794_CHIP_ID; 274791a98917SArun Ramadoss } else { 274891a98917SArun Ramadoss return -ENODEV; 274991a98917SArun Ramadoss } 275091a98917SArun Ramadoss break; 275191a98917SArun Ramadoss case KSZ88_FAMILY_ID: 275291a98917SArun Ramadoss if (id2 == KSZ88_CHIP_ID_63) 275391a98917SArun Ramadoss dev->chip_id = KSZ8830_CHIP_ID; 275491a98917SArun Ramadoss else 275591a98917SArun Ramadoss return -ENODEV; 275691a98917SArun Ramadoss break; 275791a98917SArun Ramadoss default: 275891a98917SArun Ramadoss ret = ksz_read32(dev, REG_CHIP_ID0, &id32); 275991a98917SArun Ramadoss if (ret) 276091a98917SArun Ramadoss return ret; 276191a98917SArun Ramadoss 276291a98917SArun Ramadoss dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32); 276391a98917SArun Ramadoss id32 &= ~0xFF; 276491a98917SArun Ramadoss 276591a98917SArun Ramadoss switch (id32) { 276691a98917SArun Ramadoss case KSZ9477_CHIP_ID: 27672eb3ff3cSRomain Naour case KSZ9896_CHIP_ID: 276891a98917SArun Ramadoss case KSZ9897_CHIP_ID: 276991a98917SArun Ramadoss case KSZ9567_CHIP_ID: 277091a98917SArun Ramadoss case LAN9370_CHIP_ID: 277191a98917SArun Ramadoss case LAN9371_CHIP_ID: 277291a98917SArun Ramadoss case LAN9372_CHIP_ID: 277391a98917SArun Ramadoss case LAN9373_CHIP_ID: 277491a98917SArun Ramadoss case LAN9374_CHIP_ID: 277591a98917SArun Ramadoss dev->chip_id = id32; 277691a98917SArun Ramadoss break; 2777b4490809SOleksij Rempel case KSZ9893_CHIP_ID: 2778b4490809SOleksij Rempel ret = ksz_read8(dev, REG_CHIP_ID4, 2779b4490809SOleksij Rempel &id4); 2780b4490809SOleksij Rempel if (ret) 2781b4490809SOleksij Rempel return ret; 2782b4490809SOleksij Rempel 2783b4490809SOleksij Rempel if (id4 == SKU_ID_KSZ8563) 2784b4490809SOleksij Rempel dev->chip_id = KSZ8563_CHIP_ID; 2785b4490809SOleksij Rempel else 2786b4490809SOleksij Rempel dev->chip_id = KSZ9893_CHIP_ID; 2787b4490809SOleksij Rempel 2788b4490809SOleksij Rempel break; 278991a98917SArun Ramadoss default: 279091a98917SArun Ramadoss dev_err(dev->dev, 279191a98917SArun Ramadoss "unsupported switch detected %x)\n", id32); 279291a98917SArun Ramadoss return -ENODEV; 279391a98917SArun Ramadoss } 279491a98917SArun Ramadoss } 279591a98917SArun Ramadoss return 0; 279691a98917SArun Ramadoss } 279791a98917SArun Ramadoss 27981958eee8SArun Ramadoss static const struct dsa_switch_ops ksz_switch_ops = { 27991958eee8SArun Ramadoss .get_tag_protocol = ksz_get_tag_protocol, 28001958eee8SArun Ramadoss .get_phy_flags = ksz_get_phy_flags, 28011958eee8SArun Ramadoss .setup = ksz_setup, 2802c9cd961cSArun Ramadoss .teardown = ksz_teardown, 28031958eee8SArun Ramadoss .phy_read = ksz_phy_read16, 28041958eee8SArun Ramadoss .phy_write = ksz_phy_write16, 28051958eee8SArun Ramadoss .phylink_get_caps = ksz_phylink_get_caps, 2806a0cb1aa4SArun Ramadoss .phylink_mac_config = ksz_phylink_mac_config, 2807f597d3adSArun Ramadoss .phylink_mac_link_up = ksz_phylink_mac_link_up, 28081958eee8SArun Ramadoss .phylink_mac_link_down = ksz_mac_link_down, 28091958eee8SArun Ramadoss .port_enable = ksz_enable_port, 28102c119d99SArun Ramadoss .set_ageing_time = ksz_set_ageing_time, 28111958eee8SArun Ramadoss .get_strings = ksz_get_strings, 28121958eee8SArun Ramadoss .get_ethtool_stats = ksz_get_ethtool_stats, 28131958eee8SArun Ramadoss .get_sset_count = ksz_sset_count, 28141958eee8SArun Ramadoss .port_bridge_join = ksz_port_bridge_join, 28151958eee8SArun Ramadoss .port_bridge_leave = ksz_port_bridge_leave, 28161958eee8SArun Ramadoss .port_stp_state_set = ksz_port_stp_state_set, 281715f7cfaeSVladimir Oltean .port_pre_bridge_flags = ksz_port_pre_bridge_flags, 281815f7cfaeSVladimir Oltean .port_bridge_flags = ksz_port_bridge_flags, 28191958eee8SArun Ramadoss .port_fast_age = ksz_port_fast_age, 28201958eee8SArun Ramadoss .port_vlan_filtering = ksz_port_vlan_filtering, 28211958eee8SArun Ramadoss .port_vlan_add = ksz_port_vlan_add, 28221958eee8SArun Ramadoss .port_vlan_del = ksz_port_vlan_del, 28231958eee8SArun Ramadoss .port_fdb_dump = ksz_port_fdb_dump, 28241958eee8SArun Ramadoss .port_fdb_add = ksz_port_fdb_add, 28251958eee8SArun Ramadoss .port_fdb_del = ksz_port_fdb_del, 28261958eee8SArun Ramadoss .port_mdb_add = ksz_port_mdb_add, 28271958eee8SArun Ramadoss .port_mdb_del = ksz_port_mdb_del, 28281958eee8SArun Ramadoss .port_mirror_add = ksz_port_mirror_add, 28291958eee8SArun Ramadoss .port_mirror_del = ksz_port_mirror_del, 28301958eee8SArun Ramadoss .get_stats64 = ksz_get_stats64, 2831c4748ff6SOleksij Rempel .get_pause_stats = ksz_get_pause_stats, 28321958eee8SArun Ramadoss .port_change_mtu = ksz_change_mtu, 28331958eee8SArun Ramadoss .port_max_mtu = ksz_max_mtu, 28341958eee8SArun Ramadoss }; 28351958eee8SArun Ramadoss 2836ee394feaSMarek Vasut struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) 2837b987e98eSWoojung Huh { 2838b987e98eSWoojung Huh struct dsa_switch *ds; 2839b987e98eSWoojung Huh struct ksz_device *swdev; 2840b987e98eSWoojung Huh 28417e99e347SVivien Didelot ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL); 2842b987e98eSWoojung Huh if (!ds) 2843b987e98eSWoojung Huh return NULL; 2844b987e98eSWoojung Huh 28457e99e347SVivien Didelot ds->dev = base; 28467e99e347SVivien Didelot ds->num_ports = DSA_MAX_PORTS; 28471958eee8SArun Ramadoss ds->ops = &ksz_switch_ops; 28487e99e347SVivien Didelot 2849b987e98eSWoojung Huh swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); 2850b987e98eSWoojung Huh if (!swdev) 2851b987e98eSWoojung Huh return NULL; 2852b987e98eSWoojung Huh 2853b987e98eSWoojung Huh ds->priv = swdev; 2854b987e98eSWoojung Huh swdev->dev = base; 2855b987e98eSWoojung Huh 2856b987e98eSWoojung Huh swdev->ds = ds; 2857b987e98eSWoojung Huh swdev->priv = priv; 2858b987e98eSWoojung Huh 2859b987e98eSWoojung Huh return swdev; 2860b987e98eSWoojung Huh } 2861b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_alloc); 2862b987e98eSWoojung Huh 2863b19ac41fSArun Ramadoss static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num, 2864b19ac41fSArun Ramadoss struct device_node *port_dn) 2865b19ac41fSArun Ramadoss { 2866b19ac41fSArun Ramadoss phy_interface_t phy_mode = dev->ports[port_num].interface; 2867b19ac41fSArun Ramadoss int rx_delay = -1, tx_delay = -1; 2868b19ac41fSArun Ramadoss 2869b19ac41fSArun Ramadoss if (!phy_interface_mode_is_rgmii(phy_mode)) 2870b19ac41fSArun Ramadoss return; 2871b19ac41fSArun Ramadoss 2872b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay); 2873b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay); 2874b19ac41fSArun Ramadoss 2875b19ac41fSArun Ramadoss if (rx_delay == -1 && tx_delay == -1) { 2876b19ac41fSArun Ramadoss dev_warn(dev->dev, 2877b19ac41fSArun Ramadoss "Port %d interpreting RGMII delay settings based on \"phy-mode\" property, " 2878b19ac41fSArun Ramadoss "please update device tree to specify \"rx-internal-delay-ps\" and " 2879b19ac41fSArun Ramadoss "\"tx-internal-delay-ps\"", 2880b19ac41fSArun Ramadoss port_num); 2881b19ac41fSArun Ramadoss 2882b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID || 2883b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 2884b19ac41fSArun Ramadoss rx_delay = 2000; 2885b19ac41fSArun Ramadoss 2886b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID || 2887b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 2888b19ac41fSArun Ramadoss tx_delay = 2000; 2889b19ac41fSArun Ramadoss } 2890b19ac41fSArun Ramadoss 2891b19ac41fSArun Ramadoss if (rx_delay < 0) 2892b19ac41fSArun Ramadoss rx_delay = 0; 2893b19ac41fSArun Ramadoss if (tx_delay < 0) 2894b19ac41fSArun Ramadoss tx_delay = 0; 2895b19ac41fSArun Ramadoss 2896b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_rx_val = rx_delay; 2897b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_tx_val = tx_delay; 2898b19ac41fSArun Ramadoss } 2899b19ac41fSArun Ramadoss 29006ec23aaaSArun Ramadoss int ksz_switch_register(struct ksz_device *dev) 2901b987e98eSWoojung Huh { 2902462d5250SArun Ramadoss const struct ksz_chip_data *info; 2903912aae27SHelmut Grohne struct device_node *port, *ports; 29040c65b2b9SAndrew Lunn phy_interface_t interface; 2905edecfa98SHelmut Grohne unsigned int port_num; 2906b987e98eSWoojung Huh int ret; 2907198b3478SArun Ramadoss int i; 2908b987e98eSWoojung Huh 2909b987e98eSWoojung Huh if (dev->pdata) 2910b987e98eSWoojung Huh dev->chip_id = dev->pdata->chip_id; 2911b987e98eSWoojung Huh 2912924352c3SMarek Vasut dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset", 2913924352c3SMarek Vasut GPIOD_OUT_LOW); 2914924352c3SMarek Vasut if (IS_ERR(dev->reset_gpio)) 2915924352c3SMarek Vasut return PTR_ERR(dev->reset_gpio); 2916924352c3SMarek Vasut 2917924352c3SMarek Vasut if (dev->reset_gpio) { 291822e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 29195b797980SPaul Barker usleep_range(10000, 12000); 292022e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 0); 29211c45ba93SMarek Vasut msleep(100); 2922924352c3SMarek Vasut } 2923924352c3SMarek Vasut 29247049f9b5STristram Ha mutex_init(&dev->dev_mutex); 2925013572a2SMarek Vasut mutex_init(&dev->regmap_mutex); 2926284fb78eSTristram Ha mutex_init(&dev->alu_mutex); 2927284fb78eSTristram Ha mutex_init(&dev->vlan_mutex); 2928284fb78eSTristram Ha 292991a98917SArun Ramadoss ret = ksz_switch_detect(dev); 293091a98917SArun Ramadoss if (ret) 293191a98917SArun Ramadoss return ret; 2932b987e98eSWoojung Huh 2933462d5250SArun Ramadoss info = ksz_lookup_info(dev->chip_id); 2934462d5250SArun Ramadoss if (!info) 2935462d5250SArun Ramadoss return -ENODEV; 2936462d5250SArun Ramadoss 2937462d5250SArun Ramadoss /* Update the compatible info with the probed one */ 2938462d5250SArun Ramadoss dev->info = info; 2939462d5250SArun Ramadoss 294091a98917SArun Ramadoss dev_info(dev->dev, "found switch: %s, rev %i\n", 294191a98917SArun Ramadoss dev->info->dev_name, dev->chip_rev); 294291a98917SArun Ramadoss 2943eee16b14SArun Ramadoss ret = ksz_check_device_id(dev); 2944eee16b14SArun Ramadoss if (ret) 2945eee16b14SArun Ramadoss return ret; 2946eee16b14SArun Ramadoss 29476ec23aaaSArun Ramadoss dev->dev_ops = dev->info->ops; 294891a98917SArun Ramadoss 2949c2e86691STristram Ha ret = dev->dev_ops->init(dev); 2950b987e98eSWoojung Huh if (ret) 2951b987e98eSWoojung Huh return ret; 2952b987e98eSWoojung Huh 2953198b3478SArun Ramadoss dev->ports = devm_kzalloc(dev->dev, 2954198b3478SArun Ramadoss dev->info->port_cnt * sizeof(struct ksz_port), 2955198b3478SArun Ramadoss GFP_KERNEL); 2956198b3478SArun Ramadoss if (!dev->ports) 2957198b3478SArun Ramadoss return -ENOMEM; 2958198b3478SArun Ramadoss 2959198b3478SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 2960198b3478SArun Ramadoss spin_lock_init(&dev->ports[i].mib.stats64_lock); 2961198b3478SArun Ramadoss mutex_init(&dev->ports[i].mib.cnt_mutex); 2962198b3478SArun Ramadoss dev->ports[i].mib.counters = 2963198b3478SArun Ramadoss devm_kzalloc(dev->dev, 2964198b3478SArun Ramadoss sizeof(u64) * (dev->info->mib_cnt + 1), 2965198b3478SArun Ramadoss GFP_KERNEL); 2966198b3478SArun Ramadoss if (!dev->ports[i].mib.counters) 2967198b3478SArun Ramadoss return -ENOMEM; 2968f3c16545SArun Ramadoss 2969f3c16545SArun Ramadoss dev->ports[i].ksz_dev = dev; 2970f3c16545SArun Ramadoss dev->ports[i].num = i; 2971198b3478SArun Ramadoss } 2972198b3478SArun Ramadoss 2973198b3478SArun Ramadoss /* set the real number of ports */ 2974198b3478SArun Ramadoss dev->ds->num_ports = dev->info->port_cnt; 2975198b3478SArun Ramadoss 29768c29bebbSTristram Ha /* Host port interface will be self detected, or specifically set in 29778c29bebbSTristram Ha * device tree. 29788c29bebbSTristram Ha */ 2979462d5250SArun Ramadoss for (port_num = 0; port_num < dev->info->port_cnt; ++port_num) 2980edecfa98SHelmut Grohne dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA; 2981c2e86691STristram Ha if (dev->dev->of_node) { 29820c65b2b9SAndrew Lunn ret = of_get_phy_mode(dev->dev->of_node, &interface); 29830c65b2b9SAndrew Lunn if (ret == 0) 2984edecfa98SHelmut Grohne dev->compat_interface = interface; 298544e53c88SChristian Eggers ports = of_get_child_by_name(dev->dev->of_node, "ethernet-ports"); 298644e53c88SChristian Eggers if (!ports) 2987912aae27SHelmut Grohne ports = of_get_child_by_name(dev->dev->of_node, "ports"); 2988a14bd747SLiang He if (ports) { 2989912aae27SHelmut Grohne for_each_available_child_of_node(ports, port) { 2990912aae27SHelmut Grohne if (of_property_read_u32(port, "reg", 2991912aae27SHelmut Grohne &port_num)) 2992edecfa98SHelmut Grohne continue; 299384f7e0bbSkernel test robot if (!(dev->port_mask & BIT(port_num))) { 299484f7e0bbSkernel test robot of_node_put(port); 2995a14bd747SLiang He of_node_put(ports); 2996edecfa98SHelmut Grohne return -EINVAL; 299784f7e0bbSkernel test robot } 2998912aae27SHelmut Grohne of_get_phy_mode(port, 2999912aae27SHelmut Grohne &dev->ports[port_num].interface); 3000b19ac41fSArun Ramadoss 3001b19ac41fSArun Ramadoss ksz_parse_rgmii_delay(dev, port_num, port); 3002edecfa98SHelmut Grohne } 3003a14bd747SLiang He of_node_put(ports); 3004a14bd747SLiang He } 300579c8bd15SRobert Hancock dev->synclko_125 = of_property_read_bool(dev->dev->of_node, 300679c8bd15SRobert Hancock "microchip,synclko-125"); 300748bf8b8aSRobert Hancock dev->synclko_disable = of_property_read_bool(dev->dev->of_node, 300848bf8b8aSRobert Hancock "microchip,synclko-disable"); 300948bf8b8aSRobert Hancock if (dev->synclko_125 && dev->synclko_disable) { 301048bf8b8aSRobert Hancock dev_err(dev->dev, "inconsistent synclko settings\n"); 301148bf8b8aSRobert Hancock return -EINVAL; 301248bf8b8aSRobert Hancock } 3013c2e86691STristram Ha } 3014c2e86691STristram Ha 3015c2e86691STristram Ha ret = dsa_register_switch(dev->ds); 3016c2e86691STristram Ha if (ret) { 3017c2e86691STristram Ha dev->dev_ops->exit(dev); 3018c2e86691STristram Ha return ret; 3019c2e86691STristram Ha } 3020c2e86691STristram Ha 30218098bd69SChristian Eggers /* Read MIB counters every 30 seconds to avoid overflow. */ 302212c740c8SOleksij Rempel dev->mib_read_interval = msecs_to_jiffies(5000); 30238098bd69SChristian Eggers 30248098bd69SChristian Eggers /* Start the MIB timer. */ 30258098bd69SChristian Eggers schedule_delayed_work(&dev->mib_read, 0); 30268098bd69SChristian Eggers 30277a8988a1SArun Ramadoss return ret; 3028b987e98eSWoojung Huh } 3029b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_register); 3030b987e98eSWoojung Huh 3031b987e98eSWoojung Huh void ksz_switch_remove(struct ksz_device *dev) 3032b987e98eSWoojung Huh { 30337c6ff470STristram Ha /* timer started */ 3034ef1100efSArun Ramadoss if (dev->mib_read_interval) { 3035ef1100efSArun Ramadoss dev->mib_read_interval = 0; 3036469b390eSGeorge McCollister cancel_delayed_work_sync(&dev->mib_read); 3037ef1100efSArun Ramadoss } 30387c6ff470STristram Ha 3039c2e86691STristram Ha dev->dev_ops->exit(dev); 3040b987e98eSWoojung Huh dsa_unregister_switch(dev->ds); 3041924352c3SMarek Vasut 3042924352c3SMarek Vasut if (dev->reset_gpio) 304322e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 3044924352c3SMarek Vasut 3045b987e98eSWoojung Huh } 3046b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_remove); 3047b987e98eSWoojung Huh 3048b987e98eSWoojung Huh MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 3049b987e98eSWoojung Huh MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver"); 3050b987e98eSWoojung Huh MODULE_LICENSE("GPL"); 3051