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> 9ab32f56aSChristian Eggers #include <linux/dsa/ksz_common.h> 10b987e98eSWoojung Huh #include <linux/export.h> 11924352c3SMarek Vasut #include <linux/gpio/consumer.h> 12b987e98eSWoojung Huh #include <linux/kernel.h> 13b987e98eSWoojung Huh #include <linux/module.h> 14b987e98eSWoojung Huh #include <linux/platform_data/microchip-ksz.h> 15b987e98eSWoojung Huh #include <linux/phy.h> 16b987e98eSWoojung Huh #include <linux/etherdevice.h> 17b987e98eSWoojung Huh #include <linux/if_bridge.h> 18838c19f8SOleksij Rempel #include <linux/if_vlan.h> 19ff319a64SArun Ramadoss #include <linux/irq.h> 20ff319a64SArun Ramadoss #include <linux/irqdomain.h> 21ff319a64SArun Ramadoss #include <linux/of_mdio.h> 22eee16b14SArun Ramadoss #include <linux/of_device.h> 23c2e86691STristram Ha #include <linux/of_net.h> 241fe94f54SArun Ramadoss #include <linux/micrel_phy.h> 25b987e98eSWoojung Huh #include <net/dsa.h> 26*71d7920fSArun Ramadoss #include <net/pkt_cls.h> 27b987e98eSWoojung Huh #include <net/switchdev.h> 28b987e98eSWoojung Huh 29ffc60b55SMarek Vasut #include "ksz_common.h" 30eac1ea20SChristian Eggers #include "ksz_ptp.h" 316ec23aaaSArun Ramadoss #include "ksz8.h" 326ec23aaaSArun Ramadoss #include "ksz9477.h" 3355ab6ffaSArun Ramadoss #include "lan937x.h" 347049f9b5STristram Ha 35*71d7920fSArun Ramadoss #define KSZ_CBS_ENABLE ((MTI_SCHEDULE_STRICT_PRIO << MTI_SCHEDULE_MODE_S) | \ 36*71d7920fSArun Ramadoss (MTI_SHAPING_SRP << MTI_SHAPING_S)) 37*71d7920fSArun Ramadoss #define KSZ_CBS_DISABLE ((MTI_SCHEDULE_WRR << MTI_SCHEDULE_MODE_S) |\ 38*71d7920fSArun Ramadoss (MTI_SHAPING_OFF << MTI_SHAPING_S)) 39a530e6f2SArun Ramadoss #define MIB_COUNTER_NUM 0x20 40a530e6f2SArun Ramadoss 41c6101dd7SArun Ramadoss struct ksz_stats_raw { 42c6101dd7SArun Ramadoss u64 rx_hi; 43c6101dd7SArun Ramadoss u64 rx_undersize; 44c6101dd7SArun Ramadoss u64 rx_fragments; 45c6101dd7SArun Ramadoss u64 rx_oversize; 46c6101dd7SArun Ramadoss u64 rx_jabbers; 47c6101dd7SArun Ramadoss u64 rx_symbol_err; 48c6101dd7SArun Ramadoss u64 rx_crc_err; 49c6101dd7SArun Ramadoss u64 rx_align_err; 50c6101dd7SArun Ramadoss u64 rx_mac_ctrl; 51c6101dd7SArun Ramadoss u64 rx_pause; 52c6101dd7SArun Ramadoss u64 rx_bcast; 53c6101dd7SArun Ramadoss u64 rx_mcast; 54c6101dd7SArun Ramadoss u64 rx_ucast; 55c6101dd7SArun Ramadoss u64 rx_64_or_less; 56c6101dd7SArun Ramadoss u64 rx_65_127; 57c6101dd7SArun Ramadoss u64 rx_128_255; 58c6101dd7SArun Ramadoss u64 rx_256_511; 59c6101dd7SArun Ramadoss u64 rx_512_1023; 60c6101dd7SArun Ramadoss u64 rx_1024_1522; 61c6101dd7SArun Ramadoss u64 rx_1523_2000; 62c6101dd7SArun Ramadoss u64 rx_2001; 63c6101dd7SArun Ramadoss u64 tx_hi; 64c6101dd7SArun Ramadoss u64 tx_late_col; 65c6101dd7SArun Ramadoss u64 tx_pause; 66c6101dd7SArun Ramadoss u64 tx_bcast; 67c6101dd7SArun Ramadoss u64 tx_mcast; 68c6101dd7SArun Ramadoss u64 tx_ucast; 69c6101dd7SArun Ramadoss u64 tx_deferred; 70c6101dd7SArun Ramadoss u64 tx_total_col; 71c6101dd7SArun Ramadoss u64 tx_exc_col; 72c6101dd7SArun Ramadoss u64 tx_single_col; 73c6101dd7SArun Ramadoss u64 tx_mult_col; 74c6101dd7SArun Ramadoss u64 rx_total; 75c6101dd7SArun Ramadoss u64 tx_total; 76c6101dd7SArun Ramadoss u64 rx_discards; 77c6101dd7SArun Ramadoss u64 tx_discards; 78c6101dd7SArun Ramadoss }; 79c6101dd7SArun Ramadoss 80bde55dd9SOleksij Rempel struct ksz88xx_stats_raw { 81bde55dd9SOleksij Rempel u64 rx; 82bde55dd9SOleksij Rempel u64 rx_hi; 83bde55dd9SOleksij Rempel u64 rx_undersize; 84bde55dd9SOleksij Rempel u64 rx_fragments; 85bde55dd9SOleksij Rempel u64 rx_oversize; 86bde55dd9SOleksij Rempel u64 rx_jabbers; 87bde55dd9SOleksij Rempel u64 rx_symbol_err; 88bde55dd9SOleksij Rempel u64 rx_crc_err; 89bde55dd9SOleksij Rempel u64 rx_align_err; 90bde55dd9SOleksij Rempel u64 rx_mac_ctrl; 91bde55dd9SOleksij Rempel u64 rx_pause; 92bde55dd9SOleksij Rempel u64 rx_bcast; 93bde55dd9SOleksij Rempel u64 rx_mcast; 94bde55dd9SOleksij Rempel u64 rx_ucast; 95bde55dd9SOleksij Rempel u64 rx_64_or_less; 96bde55dd9SOleksij Rempel u64 rx_65_127; 97bde55dd9SOleksij Rempel u64 rx_128_255; 98bde55dd9SOleksij Rempel u64 rx_256_511; 99bde55dd9SOleksij Rempel u64 rx_512_1023; 100bde55dd9SOleksij Rempel u64 rx_1024_1522; 101bde55dd9SOleksij Rempel u64 tx; 102bde55dd9SOleksij Rempel u64 tx_hi; 103bde55dd9SOleksij Rempel u64 tx_late_col; 104bde55dd9SOleksij Rempel u64 tx_pause; 105bde55dd9SOleksij Rempel u64 tx_bcast; 106bde55dd9SOleksij Rempel u64 tx_mcast; 107bde55dd9SOleksij Rempel u64 tx_ucast; 108bde55dd9SOleksij Rempel u64 tx_deferred; 109bde55dd9SOleksij Rempel u64 tx_total_col; 110bde55dd9SOleksij Rempel u64 tx_exc_col; 111bde55dd9SOleksij Rempel u64 tx_single_col; 112bde55dd9SOleksij Rempel u64 tx_mult_col; 113bde55dd9SOleksij Rempel u64 rx_discards; 114bde55dd9SOleksij Rempel u64 tx_discards; 115bde55dd9SOleksij Rempel }; 116bde55dd9SOleksij Rempel 117a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz88xx_mib_names[] = { 118a530e6f2SArun Ramadoss { 0x00, "rx" }, 119a530e6f2SArun Ramadoss { 0x01, "rx_hi" }, 120a530e6f2SArun Ramadoss { 0x02, "rx_undersize" }, 121a530e6f2SArun Ramadoss { 0x03, "rx_fragments" }, 122a530e6f2SArun Ramadoss { 0x04, "rx_oversize" }, 123a530e6f2SArun Ramadoss { 0x05, "rx_jabbers" }, 124a530e6f2SArun Ramadoss { 0x06, "rx_symbol_err" }, 125a530e6f2SArun Ramadoss { 0x07, "rx_crc_err" }, 126a530e6f2SArun Ramadoss { 0x08, "rx_align_err" }, 127a530e6f2SArun Ramadoss { 0x09, "rx_mac_ctrl" }, 128a530e6f2SArun Ramadoss { 0x0a, "rx_pause" }, 129a530e6f2SArun Ramadoss { 0x0b, "rx_bcast" }, 130a530e6f2SArun Ramadoss { 0x0c, "rx_mcast" }, 131a530e6f2SArun Ramadoss { 0x0d, "rx_ucast" }, 132a530e6f2SArun Ramadoss { 0x0e, "rx_64_or_less" }, 133a530e6f2SArun Ramadoss { 0x0f, "rx_65_127" }, 134a530e6f2SArun Ramadoss { 0x10, "rx_128_255" }, 135a530e6f2SArun Ramadoss { 0x11, "rx_256_511" }, 136a530e6f2SArun Ramadoss { 0x12, "rx_512_1023" }, 137a530e6f2SArun Ramadoss { 0x13, "rx_1024_1522" }, 138a530e6f2SArun Ramadoss { 0x14, "tx" }, 139a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 140a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 141a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 142a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 143a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 144a530e6f2SArun Ramadoss { 0x1a, "tx_ucast" }, 145a530e6f2SArun Ramadoss { 0x1b, "tx_deferred" }, 146a530e6f2SArun Ramadoss { 0x1c, "tx_total_col" }, 147a530e6f2SArun Ramadoss { 0x1d, "tx_exc_col" }, 148a530e6f2SArun Ramadoss { 0x1e, "tx_single_col" }, 149a530e6f2SArun Ramadoss { 0x1f, "tx_mult_col" }, 150a530e6f2SArun Ramadoss { 0x100, "rx_discards" }, 151a530e6f2SArun Ramadoss { 0x101, "tx_discards" }, 152a530e6f2SArun Ramadoss }; 153a530e6f2SArun Ramadoss 154a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz9477_mib_names[] = { 155a530e6f2SArun Ramadoss { 0x00, "rx_hi" }, 156a530e6f2SArun Ramadoss { 0x01, "rx_undersize" }, 157a530e6f2SArun Ramadoss { 0x02, "rx_fragments" }, 158a530e6f2SArun Ramadoss { 0x03, "rx_oversize" }, 159a530e6f2SArun Ramadoss { 0x04, "rx_jabbers" }, 160a530e6f2SArun Ramadoss { 0x05, "rx_symbol_err" }, 161a530e6f2SArun Ramadoss { 0x06, "rx_crc_err" }, 162a530e6f2SArun Ramadoss { 0x07, "rx_align_err" }, 163a530e6f2SArun Ramadoss { 0x08, "rx_mac_ctrl" }, 164a530e6f2SArun Ramadoss { 0x09, "rx_pause" }, 165a530e6f2SArun Ramadoss { 0x0A, "rx_bcast" }, 166a530e6f2SArun Ramadoss { 0x0B, "rx_mcast" }, 167a530e6f2SArun Ramadoss { 0x0C, "rx_ucast" }, 168a530e6f2SArun Ramadoss { 0x0D, "rx_64_or_less" }, 169a530e6f2SArun Ramadoss { 0x0E, "rx_65_127" }, 170a530e6f2SArun Ramadoss { 0x0F, "rx_128_255" }, 171a530e6f2SArun Ramadoss { 0x10, "rx_256_511" }, 172a530e6f2SArun Ramadoss { 0x11, "rx_512_1023" }, 173a530e6f2SArun Ramadoss { 0x12, "rx_1024_1522" }, 174a530e6f2SArun Ramadoss { 0x13, "rx_1523_2000" }, 175a530e6f2SArun Ramadoss { 0x14, "rx_2001" }, 176a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 177a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 178a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 179a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 180a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 181a530e6f2SArun Ramadoss { 0x1A, "tx_ucast" }, 182a530e6f2SArun Ramadoss { 0x1B, "tx_deferred" }, 183a530e6f2SArun Ramadoss { 0x1C, "tx_total_col" }, 184a530e6f2SArun Ramadoss { 0x1D, "tx_exc_col" }, 185a530e6f2SArun Ramadoss { 0x1E, "tx_single_col" }, 186a530e6f2SArun Ramadoss { 0x1F, "tx_mult_col" }, 187a530e6f2SArun Ramadoss { 0x80, "rx_total" }, 188a530e6f2SArun Ramadoss { 0x81, "tx_total" }, 189a530e6f2SArun Ramadoss { 0x82, "rx_discards" }, 190a530e6f2SArun Ramadoss { 0x83, "tx_discards" }, 191a530e6f2SArun Ramadoss }; 192a530e6f2SArun Ramadoss 1936ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz8_dev_ops = { 1946ec23aaaSArun Ramadoss .setup = ksz8_setup, 1956ec23aaaSArun Ramadoss .get_port_addr = ksz8_get_port_addr, 1966ec23aaaSArun Ramadoss .cfg_port_member = ksz8_cfg_port_member, 1976ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, 1986ec23aaaSArun Ramadoss .port_setup = ksz8_port_setup, 1996ec23aaaSArun Ramadoss .r_phy = ksz8_r_phy, 2006ec23aaaSArun Ramadoss .w_phy = ksz8_w_phy, 201769e2695SArun Ramadoss .r_mib_cnt = ksz8_r_mib_cnt, 2026ec23aaaSArun Ramadoss .r_mib_pkt = ksz8_r_mib_pkt, 203bde55dd9SOleksij Rempel .r_mib_stat64 = ksz88xx_r_mib_stats64, 2046ec23aaaSArun Ramadoss .freeze_mib = ksz8_freeze_mib, 2056ec23aaaSArun Ramadoss .port_init_cnt = ksz8_port_init_cnt, 2066ec23aaaSArun Ramadoss .fdb_dump = ksz8_fdb_dump, 2076ec23aaaSArun Ramadoss .mdb_add = ksz8_mdb_add, 2086ec23aaaSArun Ramadoss .mdb_del = ksz8_mdb_del, 2096ec23aaaSArun Ramadoss .vlan_filtering = ksz8_port_vlan_filtering, 2106ec23aaaSArun Ramadoss .vlan_add = ksz8_port_vlan_add, 2116ec23aaaSArun Ramadoss .vlan_del = ksz8_port_vlan_del, 2126ec23aaaSArun Ramadoss .mirror_add = ksz8_port_mirror_add, 2136ec23aaaSArun Ramadoss .mirror_del = ksz8_port_mirror_del, 2146ec23aaaSArun Ramadoss .get_caps = ksz8_get_caps, 2156ec23aaaSArun Ramadoss .config_cpu_port = ksz8_config_cpu_port, 2166ec23aaaSArun Ramadoss .enable_stp_addr = ksz8_enable_stp_addr, 2176ec23aaaSArun Ramadoss .reset = ksz8_reset_switch, 2186ec23aaaSArun Ramadoss .init = ksz8_switch_init, 2196ec23aaaSArun Ramadoss .exit = ksz8_switch_exit, 22029d1e85fSOleksij Rempel .change_mtu = ksz8_change_mtu, 2216ec23aaaSArun Ramadoss }; 2226ec23aaaSArun Ramadoss 2233015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 2243015c503SOleksij Rempel unsigned int mode, 2253015c503SOleksij Rempel phy_interface_t interface, 2263015c503SOleksij Rempel struct phy_device *phydev, int speed, 2273015c503SOleksij Rempel int duplex, bool tx_pause, 2283015c503SOleksij Rempel bool rx_pause); 2293015c503SOleksij Rempel 2306ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz9477_dev_ops = { 2316ec23aaaSArun Ramadoss .setup = ksz9477_setup, 2326ec23aaaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 2336ec23aaaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 2346ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 2356ec23aaaSArun Ramadoss .port_setup = ksz9477_port_setup, 2362c119d99SArun Ramadoss .set_ageing_time = ksz9477_set_ageing_time, 2376ec23aaaSArun Ramadoss .r_phy = ksz9477_r_phy, 2386ec23aaaSArun Ramadoss .w_phy = ksz9477_w_phy, 2396ec23aaaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 2406ec23aaaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 2416ec23aaaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 2426ec23aaaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 2436ec23aaaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 2446ec23aaaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 2456ec23aaaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 2466ec23aaaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 2476ec23aaaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 2486ec23aaaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 2496ec23aaaSArun Ramadoss .get_caps = ksz9477_get_caps, 2506ec23aaaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 2516ec23aaaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 2526ec23aaaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 2536ec23aaaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 2546ec23aaaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 2556ec23aaaSArun Ramadoss .change_mtu = ksz9477_change_mtu, 2563015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 2576ec23aaaSArun Ramadoss .config_cpu_port = ksz9477_config_cpu_port, 258*71d7920fSArun Ramadoss .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc, 2596ec23aaaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 2606ec23aaaSArun Ramadoss .reset = ksz9477_reset_switch, 2616ec23aaaSArun Ramadoss .init = ksz9477_switch_init, 2626ec23aaaSArun Ramadoss .exit = ksz9477_switch_exit, 2636ec23aaaSArun Ramadoss }; 2646ec23aaaSArun Ramadoss 26555ab6ffaSArun Ramadoss static const struct ksz_dev_ops lan937x_dev_ops = { 26655ab6ffaSArun Ramadoss .setup = lan937x_setup, 267c9cd961cSArun Ramadoss .teardown = lan937x_teardown, 26855ab6ffaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 26955ab6ffaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 270ab882368SArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 27155ab6ffaSArun Ramadoss .port_setup = lan937x_port_setup, 2722c119d99SArun Ramadoss .set_ageing_time = lan937x_set_ageing_time, 273ffaf1de2SArun Ramadoss .r_phy = lan937x_r_phy, 274ffaf1de2SArun Ramadoss .w_phy = lan937x_w_phy, 27555ab6ffaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 27655ab6ffaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 27755ab6ffaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 27855ab6ffaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 27955ab6ffaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 28055ab6ffaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 28155ab6ffaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 28255ab6ffaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 28355ab6ffaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 28455ab6ffaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 285c14e878dSArun Ramadoss .get_caps = lan937x_phylink_get_caps, 286b19ac41fSArun Ramadoss .setup_rgmii_delay = lan937x_setup_rgmii_delay, 28755ab6ffaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 28855ab6ffaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 28955ab6ffaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 29055ab6ffaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 29155ab6ffaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 292ab882368SArun Ramadoss .change_mtu = lan937x_change_mtu, 2933015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 29455ab6ffaSArun Ramadoss .config_cpu_port = lan937x_config_cpu_port, 295*71d7920fSArun Ramadoss .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc, 29655ab6ffaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 29755ab6ffaSArun Ramadoss .reset = lan937x_reset_switch, 29855ab6ffaSArun Ramadoss .init = lan937x_switch_init, 29955ab6ffaSArun Ramadoss .exit = lan937x_switch_exit, 30055ab6ffaSArun Ramadoss }; 30155ab6ffaSArun Ramadoss 302a02579dfSArun Ramadoss static const u16 ksz8795_regs[] = { 303486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x6E, 304486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x70, 305486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x72, 306486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x71, 307486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x75, 308486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x74, 309486f9ca7SArun Ramadoss [REG_IND_BYTE] = 0xA0, 310486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 311486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 312486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x07, 313486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 314486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x08, 315486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x09, 316486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x0C, 3176877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3189d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3199d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3209d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 321aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x06, 32246f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x56, 323486f9ca7SArun Ramadoss }; 324486f9ca7SArun Ramadoss 325d23a5e18SArun Ramadoss static const u32 ksz8795_masks[] = { 326d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(7), 327d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(1), 328d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(6), 329d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(5), 330d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(6, 0), 331d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), 332d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(12), 333d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(21), 334d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(23), 335d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), 336d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(26), 337d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(24, 20), 338d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), 339d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(8), 340d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 341d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), 342d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(26, 20), 343d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), 344d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), 3458560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 3468560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(5), 347d23a5e18SArun Ramadoss }; 348d23a5e18SArun Ramadoss 349aa5b8b73SArun Ramadoss static const u8 ksz8795_xmii_ctrl0[] = { 350aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 0, 351aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 1, 3528560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 0, 3538560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 1, 354aa5b8b73SArun Ramadoss }; 355aa5b8b73SArun Ramadoss 35646f80fa8SArun Ramadoss static const u8 ksz8795_xmii_ctrl1[] = { 357dc1c596eSArun Ramadoss [P_RGMII_SEL] = 3, 358dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 359dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 360dc1c596eSArun Ramadoss [P_MII_SEL] = 0, 36146f80fa8SArun Ramadoss [P_GMII_1GBIT] = 1, 36246f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 0, 36346f80fa8SArun Ramadoss }; 36446f80fa8SArun Ramadoss 36534e48383SArun Ramadoss static const u8 ksz8795_shifts[] = { 36634e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 7, 36734e48383SArun Ramadoss [VLAN_TABLE] = 16, 36834e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 36934e48383SArun Ramadoss [STATIC_MAC_FID] = 24, 37034e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 37134e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 29, 37234e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 37334e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 27, 37434e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 24, 37534e48383SArun Ramadoss }; 37634e48383SArun Ramadoss 377a02579dfSArun Ramadoss static const u16 ksz8863_regs[] = { 378486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x79, 379486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x7B, 380486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x7B, 381486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x7C, 382486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x80, 383486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x80, 384486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 385486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 386486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x0C, 387486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 388486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x0E, 389486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x0F, 390486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x03, 3916877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3929d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3939d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3949d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 395486f9ca7SArun Ramadoss }; 396486f9ca7SArun Ramadoss 397d23a5e18SArun Ramadoss static const u32 ksz8863_masks[] = { 398d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(3), 399d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(6), 400d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(7), 401d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(6), 402d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(15, 12), 403d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16), 404d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(19), 405d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(19), 406d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(21), 407d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(29, 26), 408d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(20), 409d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16), 410d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(5, 0), 411d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), 412d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 413d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 28), 414d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16), 415d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20), 416d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22), 417d23a5e18SArun Ramadoss }; 418d23a5e18SArun Ramadoss 41934e48383SArun Ramadoss static u8 ksz8863_shifts[] = { 42034e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 16, 42134e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 42234e48383SArun Ramadoss [STATIC_MAC_FID] = 22, 42334e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 42434e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 24, 42534e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 42634e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 24, 42734e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 20, 42834e48383SArun Ramadoss }; 42934e48383SArun Ramadoss 4306877102fSArun Ramadoss static const u16 ksz9477_regs[] = { 4316877102fSArun Ramadoss [P_STP_CTRL] = 0x0B04, 4329d95329cSArun Ramadoss [S_START_CTRL] = 0x0300, 4339d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x0332, 4349d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x0331, 435aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x0300, 43646f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x0301, 437457c182aSArun Ramadoss }; 4386877102fSArun Ramadoss 439457c182aSArun Ramadoss static const u32 ksz9477_masks[] = { 440457c182aSArun Ramadoss [ALU_STAT_WRITE] = 0, 441457c182aSArun Ramadoss [ALU_STAT_READ] = 1, 4428560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 4438560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 444457c182aSArun Ramadoss }; 445457c182aSArun Ramadoss 446457c182aSArun Ramadoss static const u8 ksz9477_shifts[] = { 447457c182aSArun Ramadoss [ALU_STAT_INDEX] = 16, 448457c182aSArun Ramadoss }; 449457c182aSArun Ramadoss 450aa5b8b73SArun Ramadoss static const u8 ksz9477_xmii_ctrl0[] = { 451aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 1, 452aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 0, 4538560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 1, 4548560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 0, 455aa5b8b73SArun Ramadoss }; 456aa5b8b73SArun Ramadoss 45746f80fa8SArun Ramadoss static const u8 ksz9477_xmii_ctrl1[] = { 458dc1c596eSArun Ramadoss [P_RGMII_SEL] = 0, 459dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 460dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 461dc1c596eSArun Ramadoss [P_MII_SEL] = 3, 46246f80fa8SArun Ramadoss [P_GMII_1GBIT] = 0, 46346f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 1, 46446f80fa8SArun Ramadoss }; 46546f80fa8SArun Ramadoss 466457c182aSArun Ramadoss static const u32 lan937x_masks[] = { 467457c182aSArun Ramadoss [ALU_STAT_WRITE] = 1, 468457c182aSArun Ramadoss [ALU_STAT_READ] = 2, 4698560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 4708560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 471457c182aSArun Ramadoss }; 472457c182aSArun Ramadoss 473457c182aSArun Ramadoss static const u8 lan937x_shifts[] = { 474457c182aSArun Ramadoss [ALU_STAT_INDEX] = 8, 4756877102fSArun Ramadoss }; 4766877102fSArun Ramadoss 47741131bacSOleksij Rempel static const struct regmap_range ksz8563_valid_regs[] = { 47841131bacSOleksij Rempel regmap_reg_range(0x0000, 0x0003), 47941131bacSOleksij Rempel regmap_reg_range(0x0006, 0x0006), 48041131bacSOleksij Rempel regmap_reg_range(0x000f, 0x001f), 48141131bacSOleksij Rempel regmap_reg_range(0x0100, 0x0100), 48241131bacSOleksij Rempel regmap_reg_range(0x0104, 0x0107), 48341131bacSOleksij Rempel regmap_reg_range(0x010d, 0x010d), 48441131bacSOleksij Rempel regmap_reg_range(0x0110, 0x0113), 48541131bacSOleksij Rempel regmap_reg_range(0x0120, 0x012b), 48641131bacSOleksij Rempel regmap_reg_range(0x0201, 0x0201), 48741131bacSOleksij Rempel regmap_reg_range(0x0210, 0x0213), 48841131bacSOleksij Rempel regmap_reg_range(0x0300, 0x0300), 48941131bacSOleksij Rempel regmap_reg_range(0x0302, 0x031b), 49041131bacSOleksij Rempel regmap_reg_range(0x0320, 0x032b), 49141131bacSOleksij Rempel regmap_reg_range(0x0330, 0x0336), 49241131bacSOleksij Rempel regmap_reg_range(0x0338, 0x033e), 49341131bacSOleksij Rempel regmap_reg_range(0x0340, 0x035f), 49441131bacSOleksij Rempel regmap_reg_range(0x0370, 0x0370), 49541131bacSOleksij Rempel regmap_reg_range(0x0378, 0x0378), 49641131bacSOleksij Rempel regmap_reg_range(0x037c, 0x037d), 49741131bacSOleksij Rempel regmap_reg_range(0x0390, 0x0393), 49841131bacSOleksij Rempel regmap_reg_range(0x0400, 0x040e), 49941131bacSOleksij Rempel regmap_reg_range(0x0410, 0x042f), 50041131bacSOleksij Rempel regmap_reg_range(0x0500, 0x0519), 50141131bacSOleksij Rempel regmap_reg_range(0x0520, 0x054b), 50241131bacSOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 50341131bacSOleksij Rempel 50441131bacSOleksij Rempel /* port 1 */ 50541131bacSOleksij Rempel regmap_reg_range(0x1000, 0x1001), 50641131bacSOleksij Rempel regmap_reg_range(0x1004, 0x100b), 50741131bacSOleksij Rempel regmap_reg_range(0x1013, 0x1013), 50841131bacSOleksij Rempel regmap_reg_range(0x1017, 0x1017), 50941131bacSOleksij Rempel regmap_reg_range(0x101b, 0x101b), 51041131bacSOleksij Rempel regmap_reg_range(0x101f, 0x1021), 51141131bacSOleksij Rempel regmap_reg_range(0x1030, 0x1030), 51241131bacSOleksij Rempel regmap_reg_range(0x1100, 0x1111), 51341131bacSOleksij Rempel regmap_reg_range(0x111a, 0x111d), 51441131bacSOleksij Rempel regmap_reg_range(0x1122, 0x1127), 51541131bacSOleksij Rempel regmap_reg_range(0x112a, 0x112b), 51641131bacSOleksij Rempel regmap_reg_range(0x1136, 0x1139), 51741131bacSOleksij Rempel regmap_reg_range(0x113e, 0x113f), 51841131bacSOleksij Rempel regmap_reg_range(0x1400, 0x1401), 51941131bacSOleksij Rempel regmap_reg_range(0x1403, 0x1403), 52041131bacSOleksij Rempel regmap_reg_range(0x1410, 0x1417), 52141131bacSOleksij Rempel regmap_reg_range(0x1420, 0x1423), 52241131bacSOleksij Rempel regmap_reg_range(0x1500, 0x1507), 52341131bacSOleksij Rempel regmap_reg_range(0x1600, 0x1612), 52441131bacSOleksij Rempel regmap_reg_range(0x1800, 0x180f), 52541131bacSOleksij Rempel regmap_reg_range(0x1900, 0x1907), 52641131bacSOleksij Rempel regmap_reg_range(0x1914, 0x191b), 52741131bacSOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 52841131bacSOleksij Rempel regmap_reg_range(0x1a04, 0x1a08), 52941131bacSOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 53041131bacSOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 53141131bacSOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 53241131bacSOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 53341131bacSOleksij Rempel 53441131bacSOleksij Rempel /* port 2 */ 53541131bacSOleksij Rempel regmap_reg_range(0x2000, 0x2001), 53641131bacSOleksij Rempel regmap_reg_range(0x2004, 0x200b), 53741131bacSOleksij Rempel regmap_reg_range(0x2013, 0x2013), 53841131bacSOleksij Rempel regmap_reg_range(0x2017, 0x2017), 53941131bacSOleksij Rempel regmap_reg_range(0x201b, 0x201b), 54041131bacSOleksij Rempel regmap_reg_range(0x201f, 0x2021), 54141131bacSOleksij Rempel regmap_reg_range(0x2030, 0x2030), 54241131bacSOleksij Rempel regmap_reg_range(0x2100, 0x2111), 54341131bacSOleksij Rempel regmap_reg_range(0x211a, 0x211d), 54441131bacSOleksij Rempel regmap_reg_range(0x2122, 0x2127), 54541131bacSOleksij Rempel regmap_reg_range(0x212a, 0x212b), 54641131bacSOleksij Rempel regmap_reg_range(0x2136, 0x2139), 54741131bacSOleksij Rempel regmap_reg_range(0x213e, 0x213f), 54841131bacSOleksij Rempel regmap_reg_range(0x2400, 0x2401), 54941131bacSOleksij Rempel regmap_reg_range(0x2403, 0x2403), 55041131bacSOleksij Rempel regmap_reg_range(0x2410, 0x2417), 55141131bacSOleksij Rempel regmap_reg_range(0x2420, 0x2423), 55241131bacSOleksij Rempel regmap_reg_range(0x2500, 0x2507), 55341131bacSOleksij Rempel regmap_reg_range(0x2600, 0x2612), 55441131bacSOleksij Rempel regmap_reg_range(0x2800, 0x280f), 55541131bacSOleksij Rempel regmap_reg_range(0x2900, 0x2907), 55641131bacSOleksij Rempel regmap_reg_range(0x2914, 0x291b), 55741131bacSOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 55841131bacSOleksij Rempel regmap_reg_range(0x2a04, 0x2a08), 55941131bacSOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 56041131bacSOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 56141131bacSOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 56241131bacSOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 56341131bacSOleksij Rempel 56441131bacSOleksij Rempel /* port 3 */ 56541131bacSOleksij Rempel regmap_reg_range(0x3000, 0x3001), 56641131bacSOleksij Rempel regmap_reg_range(0x3004, 0x300b), 56741131bacSOleksij Rempel regmap_reg_range(0x3013, 0x3013), 56841131bacSOleksij Rempel regmap_reg_range(0x3017, 0x3017), 56941131bacSOleksij Rempel regmap_reg_range(0x301b, 0x301b), 57041131bacSOleksij Rempel regmap_reg_range(0x301f, 0x3021), 57141131bacSOleksij Rempel regmap_reg_range(0x3030, 0x3030), 57241131bacSOleksij Rempel regmap_reg_range(0x3300, 0x3301), 57341131bacSOleksij Rempel regmap_reg_range(0x3303, 0x3303), 57441131bacSOleksij Rempel regmap_reg_range(0x3400, 0x3401), 57541131bacSOleksij Rempel regmap_reg_range(0x3403, 0x3403), 57641131bacSOleksij Rempel regmap_reg_range(0x3410, 0x3417), 57741131bacSOleksij Rempel regmap_reg_range(0x3420, 0x3423), 57841131bacSOleksij Rempel regmap_reg_range(0x3500, 0x3507), 57941131bacSOleksij Rempel regmap_reg_range(0x3600, 0x3612), 58041131bacSOleksij Rempel regmap_reg_range(0x3800, 0x380f), 58141131bacSOleksij Rempel regmap_reg_range(0x3900, 0x3907), 58241131bacSOleksij Rempel regmap_reg_range(0x3914, 0x391b), 58341131bacSOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 58441131bacSOleksij Rempel regmap_reg_range(0x3a04, 0x3a08), 58541131bacSOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 58641131bacSOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 58741131bacSOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 58841131bacSOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 58941131bacSOleksij Rempel }; 59041131bacSOleksij Rempel 59141131bacSOleksij Rempel static const struct regmap_access_table ksz8563_register_set = { 59241131bacSOleksij Rempel .yes_ranges = ksz8563_valid_regs, 59341131bacSOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs), 59441131bacSOleksij Rempel }; 59541131bacSOleksij Rempel 59674e792b5SOleksij Rempel static const struct regmap_range ksz9477_valid_regs[] = { 59774e792b5SOleksij Rempel regmap_reg_range(0x0000, 0x0003), 59874e792b5SOleksij Rempel regmap_reg_range(0x0006, 0x0006), 59974e792b5SOleksij Rempel regmap_reg_range(0x0010, 0x001f), 60074e792b5SOleksij Rempel regmap_reg_range(0x0100, 0x0100), 60174e792b5SOleksij Rempel regmap_reg_range(0x0103, 0x0107), 60274e792b5SOleksij Rempel regmap_reg_range(0x010d, 0x010d), 60374e792b5SOleksij Rempel regmap_reg_range(0x0110, 0x0113), 60474e792b5SOleksij Rempel regmap_reg_range(0x0120, 0x012b), 60574e792b5SOleksij Rempel regmap_reg_range(0x0201, 0x0201), 60674e792b5SOleksij Rempel regmap_reg_range(0x0210, 0x0213), 60774e792b5SOleksij Rempel regmap_reg_range(0x0300, 0x0300), 60874e792b5SOleksij Rempel regmap_reg_range(0x0302, 0x031b), 60974e792b5SOleksij Rempel regmap_reg_range(0x0320, 0x032b), 61074e792b5SOleksij Rempel regmap_reg_range(0x0330, 0x0336), 6113a8b8ea6SRomain Naour regmap_reg_range(0x0338, 0x033b), 6123a8b8ea6SRomain Naour regmap_reg_range(0x033e, 0x033e), 61374e792b5SOleksij Rempel regmap_reg_range(0x0340, 0x035f), 61474e792b5SOleksij Rempel regmap_reg_range(0x0370, 0x0370), 61574e792b5SOleksij Rempel regmap_reg_range(0x0378, 0x0378), 61674e792b5SOleksij Rempel regmap_reg_range(0x037c, 0x037d), 61774e792b5SOleksij Rempel regmap_reg_range(0x0390, 0x0393), 61874e792b5SOleksij Rempel regmap_reg_range(0x0400, 0x040e), 61974e792b5SOleksij Rempel regmap_reg_range(0x0410, 0x042f), 62074e792b5SOleksij Rempel regmap_reg_range(0x0444, 0x044b), 62174e792b5SOleksij Rempel regmap_reg_range(0x0450, 0x046f), 62274e792b5SOleksij Rempel regmap_reg_range(0x0500, 0x0519), 62374e792b5SOleksij Rempel regmap_reg_range(0x0520, 0x054b), 62474e792b5SOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 62574e792b5SOleksij Rempel regmap_reg_range(0x0604, 0x060b), 62674e792b5SOleksij Rempel regmap_reg_range(0x0610, 0x0612), 62774e792b5SOleksij Rempel regmap_reg_range(0x0614, 0x062c), 62874e792b5SOleksij Rempel regmap_reg_range(0x0640, 0x0645), 62974e792b5SOleksij Rempel regmap_reg_range(0x0648, 0x064d), 63074e792b5SOleksij Rempel 63174e792b5SOleksij Rempel /* port 1 */ 63274e792b5SOleksij Rempel regmap_reg_range(0x1000, 0x1001), 63374e792b5SOleksij Rempel regmap_reg_range(0x1013, 0x1013), 63474e792b5SOleksij Rempel regmap_reg_range(0x1017, 0x1017), 63574e792b5SOleksij Rempel regmap_reg_range(0x101b, 0x101b), 63674e792b5SOleksij Rempel regmap_reg_range(0x101f, 0x1020), 63774e792b5SOleksij Rempel regmap_reg_range(0x1030, 0x1030), 63874e792b5SOleksij Rempel regmap_reg_range(0x1100, 0x1115), 63974e792b5SOleksij Rempel regmap_reg_range(0x111a, 0x111f), 64074e792b5SOleksij Rempel regmap_reg_range(0x1122, 0x1127), 64174e792b5SOleksij Rempel regmap_reg_range(0x112a, 0x112b), 64274e792b5SOleksij Rempel regmap_reg_range(0x1136, 0x1139), 64374e792b5SOleksij Rempel regmap_reg_range(0x113e, 0x113f), 64474e792b5SOleksij Rempel regmap_reg_range(0x1400, 0x1401), 64574e792b5SOleksij Rempel regmap_reg_range(0x1403, 0x1403), 64674e792b5SOleksij Rempel regmap_reg_range(0x1410, 0x1417), 64774e792b5SOleksij Rempel regmap_reg_range(0x1420, 0x1423), 64874e792b5SOleksij Rempel regmap_reg_range(0x1500, 0x1507), 64974e792b5SOleksij Rempel regmap_reg_range(0x1600, 0x1613), 65074e792b5SOleksij Rempel regmap_reg_range(0x1800, 0x180f), 65174e792b5SOleksij Rempel regmap_reg_range(0x1820, 0x1827), 65274e792b5SOleksij Rempel regmap_reg_range(0x1830, 0x1837), 65374e792b5SOleksij Rempel regmap_reg_range(0x1840, 0x184b), 65474e792b5SOleksij Rempel regmap_reg_range(0x1900, 0x1907), 65574e792b5SOleksij Rempel regmap_reg_range(0x1914, 0x191b), 65674e792b5SOleksij Rempel regmap_reg_range(0x1920, 0x1920), 65774e792b5SOleksij Rempel regmap_reg_range(0x1923, 0x1927), 65874e792b5SOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 65974e792b5SOleksij Rempel regmap_reg_range(0x1a04, 0x1a07), 66074e792b5SOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 66174e792b5SOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 66274e792b5SOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 66374e792b5SOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 66474e792b5SOleksij Rempel 66574e792b5SOleksij Rempel /* port 2 */ 66674e792b5SOleksij Rempel regmap_reg_range(0x2000, 0x2001), 66774e792b5SOleksij Rempel regmap_reg_range(0x2013, 0x2013), 66874e792b5SOleksij Rempel regmap_reg_range(0x2017, 0x2017), 66974e792b5SOleksij Rempel regmap_reg_range(0x201b, 0x201b), 67074e792b5SOleksij Rempel regmap_reg_range(0x201f, 0x2020), 67174e792b5SOleksij Rempel regmap_reg_range(0x2030, 0x2030), 67274e792b5SOleksij Rempel regmap_reg_range(0x2100, 0x2115), 67374e792b5SOleksij Rempel regmap_reg_range(0x211a, 0x211f), 67474e792b5SOleksij Rempel regmap_reg_range(0x2122, 0x2127), 67574e792b5SOleksij Rempel regmap_reg_range(0x212a, 0x212b), 67674e792b5SOleksij Rempel regmap_reg_range(0x2136, 0x2139), 67774e792b5SOleksij Rempel regmap_reg_range(0x213e, 0x213f), 67874e792b5SOleksij Rempel regmap_reg_range(0x2400, 0x2401), 67974e792b5SOleksij Rempel regmap_reg_range(0x2403, 0x2403), 68074e792b5SOleksij Rempel regmap_reg_range(0x2410, 0x2417), 68174e792b5SOleksij Rempel regmap_reg_range(0x2420, 0x2423), 68274e792b5SOleksij Rempel regmap_reg_range(0x2500, 0x2507), 68374e792b5SOleksij Rempel regmap_reg_range(0x2600, 0x2613), 68474e792b5SOleksij Rempel regmap_reg_range(0x2800, 0x280f), 68574e792b5SOleksij Rempel regmap_reg_range(0x2820, 0x2827), 68674e792b5SOleksij Rempel regmap_reg_range(0x2830, 0x2837), 68774e792b5SOleksij Rempel regmap_reg_range(0x2840, 0x284b), 68874e792b5SOleksij Rempel regmap_reg_range(0x2900, 0x2907), 68974e792b5SOleksij Rempel regmap_reg_range(0x2914, 0x291b), 69074e792b5SOleksij Rempel regmap_reg_range(0x2920, 0x2920), 69174e792b5SOleksij Rempel regmap_reg_range(0x2923, 0x2927), 69274e792b5SOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 69374e792b5SOleksij Rempel regmap_reg_range(0x2a04, 0x2a07), 69474e792b5SOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 69574e792b5SOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 69674e792b5SOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 69774e792b5SOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 69874e792b5SOleksij Rempel 69974e792b5SOleksij Rempel /* port 3 */ 70074e792b5SOleksij Rempel regmap_reg_range(0x3000, 0x3001), 70174e792b5SOleksij Rempel regmap_reg_range(0x3013, 0x3013), 70274e792b5SOleksij Rempel regmap_reg_range(0x3017, 0x3017), 70374e792b5SOleksij Rempel regmap_reg_range(0x301b, 0x301b), 70474e792b5SOleksij Rempel regmap_reg_range(0x301f, 0x3020), 70574e792b5SOleksij Rempel regmap_reg_range(0x3030, 0x3030), 70674e792b5SOleksij Rempel regmap_reg_range(0x3100, 0x3115), 70774e792b5SOleksij Rempel regmap_reg_range(0x311a, 0x311f), 70874e792b5SOleksij Rempel regmap_reg_range(0x3122, 0x3127), 70974e792b5SOleksij Rempel regmap_reg_range(0x312a, 0x312b), 71074e792b5SOleksij Rempel regmap_reg_range(0x3136, 0x3139), 71174e792b5SOleksij Rempel regmap_reg_range(0x313e, 0x313f), 71274e792b5SOleksij Rempel regmap_reg_range(0x3400, 0x3401), 71374e792b5SOleksij Rempel regmap_reg_range(0x3403, 0x3403), 71474e792b5SOleksij Rempel regmap_reg_range(0x3410, 0x3417), 71574e792b5SOleksij Rempel regmap_reg_range(0x3420, 0x3423), 71674e792b5SOleksij Rempel regmap_reg_range(0x3500, 0x3507), 71774e792b5SOleksij Rempel regmap_reg_range(0x3600, 0x3613), 71874e792b5SOleksij Rempel regmap_reg_range(0x3800, 0x380f), 71974e792b5SOleksij Rempel regmap_reg_range(0x3820, 0x3827), 72074e792b5SOleksij Rempel regmap_reg_range(0x3830, 0x3837), 72174e792b5SOleksij Rempel regmap_reg_range(0x3840, 0x384b), 72274e792b5SOleksij Rempel regmap_reg_range(0x3900, 0x3907), 72374e792b5SOleksij Rempel regmap_reg_range(0x3914, 0x391b), 72474e792b5SOleksij Rempel regmap_reg_range(0x3920, 0x3920), 72574e792b5SOleksij Rempel regmap_reg_range(0x3923, 0x3927), 72674e792b5SOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 72774e792b5SOleksij Rempel regmap_reg_range(0x3a04, 0x3a07), 72874e792b5SOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 72974e792b5SOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 73074e792b5SOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 73174e792b5SOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 73274e792b5SOleksij Rempel 73374e792b5SOleksij Rempel /* port 4 */ 73474e792b5SOleksij Rempel regmap_reg_range(0x4000, 0x4001), 73574e792b5SOleksij Rempel regmap_reg_range(0x4013, 0x4013), 73674e792b5SOleksij Rempel regmap_reg_range(0x4017, 0x4017), 73774e792b5SOleksij Rempel regmap_reg_range(0x401b, 0x401b), 73874e792b5SOleksij Rempel regmap_reg_range(0x401f, 0x4020), 73974e792b5SOleksij Rempel regmap_reg_range(0x4030, 0x4030), 74074e792b5SOleksij Rempel regmap_reg_range(0x4100, 0x4115), 74174e792b5SOleksij Rempel regmap_reg_range(0x411a, 0x411f), 74274e792b5SOleksij Rempel regmap_reg_range(0x4122, 0x4127), 74374e792b5SOleksij Rempel regmap_reg_range(0x412a, 0x412b), 74474e792b5SOleksij Rempel regmap_reg_range(0x4136, 0x4139), 74574e792b5SOleksij Rempel regmap_reg_range(0x413e, 0x413f), 74674e792b5SOleksij Rempel regmap_reg_range(0x4400, 0x4401), 74774e792b5SOleksij Rempel regmap_reg_range(0x4403, 0x4403), 74874e792b5SOleksij Rempel regmap_reg_range(0x4410, 0x4417), 74974e792b5SOleksij Rempel regmap_reg_range(0x4420, 0x4423), 75074e792b5SOleksij Rempel regmap_reg_range(0x4500, 0x4507), 75174e792b5SOleksij Rempel regmap_reg_range(0x4600, 0x4613), 75274e792b5SOleksij Rempel regmap_reg_range(0x4800, 0x480f), 75374e792b5SOleksij Rempel regmap_reg_range(0x4820, 0x4827), 75474e792b5SOleksij Rempel regmap_reg_range(0x4830, 0x4837), 75574e792b5SOleksij Rempel regmap_reg_range(0x4840, 0x484b), 75674e792b5SOleksij Rempel regmap_reg_range(0x4900, 0x4907), 75774e792b5SOleksij Rempel regmap_reg_range(0x4914, 0x491b), 75874e792b5SOleksij Rempel regmap_reg_range(0x4920, 0x4920), 75974e792b5SOleksij Rempel regmap_reg_range(0x4923, 0x4927), 76074e792b5SOleksij Rempel regmap_reg_range(0x4a00, 0x4a03), 76174e792b5SOleksij Rempel regmap_reg_range(0x4a04, 0x4a07), 76274e792b5SOleksij Rempel regmap_reg_range(0x4b00, 0x4b01), 76374e792b5SOleksij Rempel regmap_reg_range(0x4b04, 0x4b04), 76474e792b5SOleksij Rempel regmap_reg_range(0x4c00, 0x4c05), 76574e792b5SOleksij Rempel regmap_reg_range(0x4c08, 0x4c1b), 76674e792b5SOleksij Rempel 76774e792b5SOleksij Rempel /* port 5 */ 76874e792b5SOleksij Rempel regmap_reg_range(0x5000, 0x5001), 76974e792b5SOleksij Rempel regmap_reg_range(0x5013, 0x5013), 77074e792b5SOleksij Rempel regmap_reg_range(0x5017, 0x5017), 77174e792b5SOleksij Rempel regmap_reg_range(0x501b, 0x501b), 77274e792b5SOleksij Rempel regmap_reg_range(0x501f, 0x5020), 77374e792b5SOleksij Rempel regmap_reg_range(0x5030, 0x5030), 77474e792b5SOleksij Rempel regmap_reg_range(0x5100, 0x5115), 77574e792b5SOleksij Rempel regmap_reg_range(0x511a, 0x511f), 77674e792b5SOleksij Rempel regmap_reg_range(0x5122, 0x5127), 77774e792b5SOleksij Rempel regmap_reg_range(0x512a, 0x512b), 77874e792b5SOleksij Rempel regmap_reg_range(0x5136, 0x5139), 77974e792b5SOleksij Rempel regmap_reg_range(0x513e, 0x513f), 78074e792b5SOleksij Rempel regmap_reg_range(0x5400, 0x5401), 78174e792b5SOleksij Rempel regmap_reg_range(0x5403, 0x5403), 78274e792b5SOleksij Rempel regmap_reg_range(0x5410, 0x5417), 78374e792b5SOleksij Rempel regmap_reg_range(0x5420, 0x5423), 78474e792b5SOleksij Rempel regmap_reg_range(0x5500, 0x5507), 78574e792b5SOleksij Rempel regmap_reg_range(0x5600, 0x5613), 78674e792b5SOleksij Rempel regmap_reg_range(0x5800, 0x580f), 78774e792b5SOleksij Rempel regmap_reg_range(0x5820, 0x5827), 78874e792b5SOleksij Rempel regmap_reg_range(0x5830, 0x5837), 78974e792b5SOleksij Rempel regmap_reg_range(0x5840, 0x584b), 79074e792b5SOleksij Rempel regmap_reg_range(0x5900, 0x5907), 79174e792b5SOleksij Rempel regmap_reg_range(0x5914, 0x591b), 79274e792b5SOleksij Rempel regmap_reg_range(0x5920, 0x5920), 79374e792b5SOleksij Rempel regmap_reg_range(0x5923, 0x5927), 79474e792b5SOleksij Rempel regmap_reg_range(0x5a00, 0x5a03), 79574e792b5SOleksij Rempel regmap_reg_range(0x5a04, 0x5a07), 79674e792b5SOleksij Rempel regmap_reg_range(0x5b00, 0x5b01), 79774e792b5SOleksij Rempel regmap_reg_range(0x5b04, 0x5b04), 79874e792b5SOleksij Rempel regmap_reg_range(0x5c00, 0x5c05), 79974e792b5SOleksij Rempel regmap_reg_range(0x5c08, 0x5c1b), 80074e792b5SOleksij Rempel 80174e792b5SOleksij Rempel /* port 6 */ 80274e792b5SOleksij Rempel regmap_reg_range(0x6000, 0x6001), 80374e792b5SOleksij Rempel regmap_reg_range(0x6013, 0x6013), 80474e792b5SOleksij Rempel regmap_reg_range(0x6017, 0x6017), 80574e792b5SOleksij Rempel regmap_reg_range(0x601b, 0x601b), 80674e792b5SOleksij Rempel regmap_reg_range(0x601f, 0x6020), 80774e792b5SOleksij Rempel regmap_reg_range(0x6030, 0x6030), 80874e792b5SOleksij Rempel regmap_reg_range(0x6300, 0x6301), 80974e792b5SOleksij Rempel regmap_reg_range(0x6400, 0x6401), 81074e792b5SOleksij Rempel regmap_reg_range(0x6403, 0x6403), 81174e792b5SOleksij Rempel regmap_reg_range(0x6410, 0x6417), 81274e792b5SOleksij Rempel regmap_reg_range(0x6420, 0x6423), 81374e792b5SOleksij Rempel regmap_reg_range(0x6500, 0x6507), 81474e792b5SOleksij Rempel regmap_reg_range(0x6600, 0x6613), 81574e792b5SOleksij Rempel regmap_reg_range(0x6800, 0x680f), 81674e792b5SOleksij Rempel regmap_reg_range(0x6820, 0x6827), 81774e792b5SOleksij Rempel regmap_reg_range(0x6830, 0x6837), 81874e792b5SOleksij Rempel regmap_reg_range(0x6840, 0x684b), 81974e792b5SOleksij Rempel regmap_reg_range(0x6900, 0x6907), 82074e792b5SOleksij Rempel regmap_reg_range(0x6914, 0x691b), 82174e792b5SOleksij Rempel regmap_reg_range(0x6920, 0x6920), 82274e792b5SOleksij Rempel regmap_reg_range(0x6923, 0x6927), 82374e792b5SOleksij Rempel regmap_reg_range(0x6a00, 0x6a03), 82474e792b5SOleksij Rempel regmap_reg_range(0x6a04, 0x6a07), 82574e792b5SOleksij Rempel regmap_reg_range(0x6b00, 0x6b01), 82674e792b5SOleksij Rempel regmap_reg_range(0x6b04, 0x6b04), 82774e792b5SOleksij Rempel regmap_reg_range(0x6c00, 0x6c05), 82874e792b5SOleksij Rempel regmap_reg_range(0x6c08, 0x6c1b), 82974e792b5SOleksij Rempel 83074e792b5SOleksij Rempel /* port 7 */ 83174e792b5SOleksij Rempel regmap_reg_range(0x7000, 0x7001), 83274e792b5SOleksij Rempel regmap_reg_range(0x7013, 0x7013), 83374e792b5SOleksij Rempel regmap_reg_range(0x7017, 0x7017), 83474e792b5SOleksij Rempel regmap_reg_range(0x701b, 0x701b), 83574e792b5SOleksij Rempel regmap_reg_range(0x701f, 0x7020), 83674e792b5SOleksij Rempel regmap_reg_range(0x7030, 0x7030), 83774e792b5SOleksij Rempel regmap_reg_range(0x7200, 0x7203), 83874e792b5SOleksij Rempel regmap_reg_range(0x7206, 0x7207), 83974e792b5SOleksij Rempel regmap_reg_range(0x7300, 0x7301), 84074e792b5SOleksij Rempel regmap_reg_range(0x7400, 0x7401), 84174e792b5SOleksij Rempel regmap_reg_range(0x7403, 0x7403), 84274e792b5SOleksij Rempel regmap_reg_range(0x7410, 0x7417), 84374e792b5SOleksij Rempel regmap_reg_range(0x7420, 0x7423), 84474e792b5SOleksij Rempel regmap_reg_range(0x7500, 0x7507), 84574e792b5SOleksij Rempel regmap_reg_range(0x7600, 0x7613), 84674e792b5SOleksij Rempel regmap_reg_range(0x7800, 0x780f), 84774e792b5SOleksij Rempel regmap_reg_range(0x7820, 0x7827), 84874e792b5SOleksij Rempel regmap_reg_range(0x7830, 0x7837), 84974e792b5SOleksij Rempel regmap_reg_range(0x7840, 0x784b), 85074e792b5SOleksij Rempel regmap_reg_range(0x7900, 0x7907), 85174e792b5SOleksij Rempel regmap_reg_range(0x7914, 0x791b), 85274e792b5SOleksij Rempel regmap_reg_range(0x7920, 0x7920), 85374e792b5SOleksij Rempel regmap_reg_range(0x7923, 0x7927), 85474e792b5SOleksij Rempel regmap_reg_range(0x7a00, 0x7a03), 85574e792b5SOleksij Rempel regmap_reg_range(0x7a04, 0x7a07), 85674e792b5SOleksij Rempel regmap_reg_range(0x7b00, 0x7b01), 85774e792b5SOleksij Rempel regmap_reg_range(0x7b04, 0x7b04), 85874e792b5SOleksij Rempel regmap_reg_range(0x7c00, 0x7c05), 85974e792b5SOleksij Rempel regmap_reg_range(0x7c08, 0x7c1b), 86074e792b5SOleksij Rempel }; 86174e792b5SOleksij Rempel 86274e792b5SOleksij Rempel static const struct regmap_access_table ksz9477_register_set = { 86374e792b5SOleksij Rempel .yes_ranges = ksz9477_valid_regs, 86474e792b5SOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs), 86574e792b5SOleksij Rempel }; 86674e792b5SOleksij Rempel 8676674e7fdSRomain Naour static const struct regmap_range ksz9896_valid_regs[] = { 8686674e7fdSRomain Naour regmap_reg_range(0x0000, 0x0003), 8696674e7fdSRomain Naour regmap_reg_range(0x0006, 0x0006), 8706674e7fdSRomain Naour regmap_reg_range(0x0010, 0x001f), 8716674e7fdSRomain Naour regmap_reg_range(0x0100, 0x0100), 8726674e7fdSRomain Naour regmap_reg_range(0x0103, 0x0107), 8736674e7fdSRomain Naour regmap_reg_range(0x010d, 0x010d), 8746674e7fdSRomain Naour regmap_reg_range(0x0110, 0x0113), 8756674e7fdSRomain Naour regmap_reg_range(0x0120, 0x0127), 8766674e7fdSRomain Naour regmap_reg_range(0x0201, 0x0201), 8776674e7fdSRomain Naour regmap_reg_range(0x0210, 0x0213), 8786674e7fdSRomain Naour regmap_reg_range(0x0300, 0x0300), 8796674e7fdSRomain Naour regmap_reg_range(0x0302, 0x030b), 8806674e7fdSRomain Naour regmap_reg_range(0x0310, 0x031b), 8816674e7fdSRomain Naour regmap_reg_range(0x0320, 0x032b), 8826674e7fdSRomain Naour regmap_reg_range(0x0330, 0x0336), 8836674e7fdSRomain Naour regmap_reg_range(0x0338, 0x033b), 8846674e7fdSRomain Naour regmap_reg_range(0x033e, 0x033e), 8856674e7fdSRomain Naour regmap_reg_range(0x0340, 0x035f), 8866674e7fdSRomain Naour regmap_reg_range(0x0370, 0x0370), 8876674e7fdSRomain Naour regmap_reg_range(0x0378, 0x0378), 8886674e7fdSRomain Naour regmap_reg_range(0x037c, 0x037d), 8896674e7fdSRomain Naour regmap_reg_range(0x0390, 0x0393), 8906674e7fdSRomain Naour regmap_reg_range(0x0400, 0x040e), 8916674e7fdSRomain Naour regmap_reg_range(0x0410, 0x042f), 8926674e7fdSRomain Naour 8936674e7fdSRomain Naour /* port 1 */ 8946674e7fdSRomain Naour regmap_reg_range(0x1000, 0x1001), 8956674e7fdSRomain Naour regmap_reg_range(0x1013, 0x1013), 8966674e7fdSRomain Naour regmap_reg_range(0x1017, 0x1017), 8976674e7fdSRomain Naour regmap_reg_range(0x101b, 0x101b), 8986674e7fdSRomain Naour regmap_reg_range(0x101f, 0x1020), 8996674e7fdSRomain Naour regmap_reg_range(0x1030, 0x1030), 9006674e7fdSRomain Naour regmap_reg_range(0x1100, 0x1115), 9016674e7fdSRomain Naour regmap_reg_range(0x111a, 0x111f), 9026674e7fdSRomain Naour regmap_reg_range(0x1122, 0x1127), 9036674e7fdSRomain Naour regmap_reg_range(0x112a, 0x112b), 9046674e7fdSRomain Naour regmap_reg_range(0x1136, 0x1139), 9056674e7fdSRomain Naour regmap_reg_range(0x113e, 0x113f), 9066674e7fdSRomain Naour regmap_reg_range(0x1400, 0x1401), 9076674e7fdSRomain Naour regmap_reg_range(0x1403, 0x1403), 9086674e7fdSRomain Naour regmap_reg_range(0x1410, 0x1417), 9096674e7fdSRomain Naour regmap_reg_range(0x1420, 0x1423), 9106674e7fdSRomain Naour regmap_reg_range(0x1500, 0x1507), 9116674e7fdSRomain Naour regmap_reg_range(0x1600, 0x1612), 9126674e7fdSRomain Naour regmap_reg_range(0x1800, 0x180f), 9136674e7fdSRomain Naour regmap_reg_range(0x1820, 0x1827), 9146674e7fdSRomain Naour regmap_reg_range(0x1830, 0x1837), 9156674e7fdSRomain Naour regmap_reg_range(0x1840, 0x184b), 9166674e7fdSRomain Naour regmap_reg_range(0x1900, 0x1907), 9176674e7fdSRomain Naour regmap_reg_range(0x1914, 0x1915), 9186674e7fdSRomain Naour regmap_reg_range(0x1a00, 0x1a03), 9196674e7fdSRomain Naour regmap_reg_range(0x1a04, 0x1a07), 9206674e7fdSRomain Naour regmap_reg_range(0x1b00, 0x1b01), 9216674e7fdSRomain Naour regmap_reg_range(0x1b04, 0x1b04), 9226674e7fdSRomain Naour 9236674e7fdSRomain Naour /* port 2 */ 9246674e7fdSRomain Naour regmap_reg_range(0x2000, 0x2001), 9256674e7fdSRomain Naour regmap_reg_range(0x2013, 0x2013), 9266674e7fdSRomain Naour regmap_reg_range(0x2017, 0x2017), 9276674e7fdSRomain Naour regmap_reg_range(0x201b, 0x201b), 9286674e7fdSRomain Naour regmap_reg_range(0x201f, 0x2020), 9296674e7fdSRomain Naour regmap_reg_range(0x2030, 0x2030), 9306674e7fdSRomain Naour regmap_reg_range(0x2100, 0x2115), 9316674e7fdSRomain Naour regmap_reg_range(0x211a, 0x211f), 9326674e7fdSRomain Naour regmap_reg_range(0x2122, 0x2127), 9336674e7fdSRomain Naour regmap_reg_range(0x212a, 0x212b), 9346674e7fdSRomain Naour regmap_reg_range(0x2136, 0x2139), 9356674e7fdSRomain Naour regmap_reg_range(0x213e, 0x213f), 9366674e7fdSRomain Naour regmap_reg_range(0x2400, 0x2401), 9376674e7fdSRomain Naour regmap_reg_range(0x2403, 0x2403), 9386674e7fdSRomain Naour regmap_reg_range(0x2410, 0x2417), 9396674e7fdSRomain Naour regmap_reg_range(0x2420, 0x2423), 9406674e7fdSRomain Naour regmap_reg_range(0x2500, 0x2507), 9416674e7fdSRomain Naour regmap_reg_range(0x2600, 0x2612), 9426674e7fdSRomain Naour regmap_reg_range(0x2800, 0x280f), 9436674e7fdSRomain Naour regmap_reg_range(0x2820, 0x2827), 9446674e7fdSRomain Naour regmap_reg_range(0x2830, 0x2837), 9456674e7fdSRomain Naour regmap_reg_range(0x2840, 0x284b), 9466674e7fdSRomain Naour regmap_reg_range(0x2900, 0x2907), 9476674e7fdSRomain Naour regmap_reg_range(0x2914, 0x2915), 9486674e7fdSRomain Naour regmap_reg_range(0x2a00, 0x2a03), 9496674e7fdSRomain Naour regmap_reg_range(0x2a04, 0x2a07), 9506674e7fdSRomain Naour regmap_reg_range(0x2b00, 0x2b01), 9516674e7fdSRomain Naour regmap_reg_range(0x2b04, 0x2b04), 9526674e7fdSRomain Naour 9536674e7fdSRomain Naour /* port 3 */ 9546674e7fdSRomain Naour regmap_reg_range(0x3000, 0x3001), 9556674e7fdSRomain Naour regmap_reg_range(0x3013, 0x3013), 9566674e7fdSRomain Naour regmap_reg_range(0x3017, 0x3017), 9576674e7fdSRomain Naour regmap_reg_range(0x301b, 0x301b), 9586674e7fdSRomain Naour regmap_reg_range(0x301f, 0x3020), 9596674e7fdSRomain Naour regmap_reg_range(0x3030, 0x3030), 9606674e7fdSRomain Naour regmap_reg_range(0x3100, 0x3115), 9616674e7fdSRomain Naour regmap_reg_range(0x311a, 0x311f), 9626674e7fdSRomain Naour regmap_reg_range(0x3122, 0x3127), 9636674e7fdSRomain Naour regmap_reg_range(0x312a, 0x312b), 9646674e7fdSRomain Naour regmap_reg_range(0x3136, 0x3139), 9656674e7fdSRomain Naour regmap_reg_range(0x313e, 0x313f), 9666674e7fdSRomain Naour regmap_reg_range(0x3400, 0x3401), 9676674e7fdSRomain Naour regmap_reg_range(0x3403, 0x3403), 9686674e7fdSRomain Naour regmap_reg_range(0x3410, 0x3417), 9696674e7fdSRomain Naour regmap_reg_range(0x3420, 0x3423), 9706674e7fdSRomain Naour regmap_reg_range(0x3500, 0x3507), 9716674e7fdSRomain Naour regmap_reg_range(0x3600, 0x3612), 9726674e7fdSRomain Naour regmap_reg_range(0x3800, 0x380f), 9736674e7fdSRomain Naour regmap_reg_range(0x3820, 0x3827), 9746674e7fdSRomain Naour regmap_reg_range(0x3830, 0x3837), 9756674e7fdSRomain Naour regmap_reg_range(0x3840, 0x384b), 9766674e7fdSRomain Naour regmap_reg_range(0x3900, 0x3907), 9776674e7fdSRomain Naour regmap_reg_range(0x3914, 0x3915), 9786674e7fdSRomain Naour regmap_reg_range(0x3a00, 0x3a03), 9796674e7fdSRomain Naour regmap_reg_range(0x3a04, 0x3a07), 9806674e7fdSRomain Naour regmap_reg_range(0x3b00, 0x3b01), 9816674e7fdSRomain Naour regmap_reg_range(0x3b04, 0x3b04), 9826674e7fdSRomain Naour 9836674e7fdSRomain Naour /* port 4 */ 9846674e7fdSRomain Naour regmap_reg_range(0x4000, 0x4001), 9856674e7fdSRomain Naour regmap_reg_range(0x4013, 0x4013), 9866674e7fdSRomain Naour regmap_reg_range(0x4017, 0x4017), 9876674e7fdSRomain Naour regmap_reg_range(0x401b, 0x401b), 9886674e7fdSRomain Naour regmap_reg_range(0x401f, 0x4020), 9896674e7fdSRomain Naour regmap_reg_range(0x4030, 0x4030), 9906674e7fdSRomain Naour regmap_reg_range(0x4100, 0x4115), 9916674e7fdSRomain Naour regmap_reg_range(0x411a, 0x411f), 9926674e7fdSRomain Naour regmap_reg_range(0x4122, 0x4127), 9936674e7fdSRomain Naour regmap_reg_range(0x412a, 0x412b), 9946674e7fdSRomain Naour regmap_reg_range(0x4136, 0x4139), 9956674e7fdSRomain Naour regmap_reg_range(0x413e, 0x413f), 9966674e7fdSRomain Naour regmap_reg_range(0x4400, 0x4401), 9976674e7fdSRomain Naour regmap_reg_range(0x4403, 0x4403), 9986674e7fdSRomain Naour regmap_reg_range(0x4410, 0x4417), 9996674e7fdSRomain Naour regmap_reg_range(0x4420, 0x4423), 10006674e7fdSRomain Naour regmap_reg_range(0x4500, 0x4507), 10016674e7fdSRomain Naour regmap_reg_range(0x4600, 0x4612), 10026674e7fdSRomain Naour regmap_reg_range(0x4800, 0x480f), 10036674e7fdSRomain Naour regmap_reg_range(0x4820, 0x4827), 10046674e7fdSRomain Naour regmap_reg_range(0x4830, 0x4837), 10056674e7fdSRomain Naour regmap_reg_range(0x4840, 0x484b), 10066674e7fdSRomain Naour regmap_reg_range(0x4900, 0x4907), 10076674e7fdSRomain Naour regmap_reg_range(0x4914, 0x4915), 10086674e7fdSRomain Naour regmap_reg_range(0x4a00, 0x4a03), 10096674e7fdSRomain Naour regmap_reg_range(0x4a04, 0x4a07), 10106674e7fdSRomain Naour regmap_reg_range(0x4b00, 0x4b01), 10116674e7fdSRomain Naour regmap_reg_range(0x4b04, 0x4b04), 10126674e7fdSRomain Naour 10136674e7fdSRomain Naour /* port 5 */ 10146674e7fdSRomain Naour regmap_reg_range(0x5000, 0x5001), 10156674e7fdSRomain Naour regmap_reg_range(0x5013, 0x5013), 10166674e7fdSRomain Naour regmap_reg_range(0x5017, 0x5017), 10176674e7fdSRomain Naour regmap_reg_range(0x501b, 0x501b), 10186674e7fdSRomain Naour regmap_reg_range(0x501f, 0x5020), 10196674e7fdSRomain Naour regmap_reg_range(0x5030, 0x5030), 10206674e7fdSRomain Naour regmap_reg_range(0x5100, 0x5115), 10216674e7fdSRomain Naour regmap_reg_range(0x511a, 0x511f), 10226674e7fdSRomain Naour regmap_reg_range(0x5122, 0x5127), 10236674e7fdSRomain Naour regmap_reg_range(0x512a, 0x512b), 10246674e7fdSRomain Naour regmap_reg_range(0x5136, 0x5139), 10256674e7fdSRomain Naour regmap_reg_range(0x513e, 0x513f), 10266674e7fdSRomain Naour regmap_reg_range(0x5400, 0x5401), 10276674e7fdSRomain Naour regmap_reg_range(0x5403, 0x5403), 10286674e7fdSRomain Naour regmap_reg_range(0x5410, 0x5417), 10296674e7fdSRomain Naour regmap_reg_range(0x5420, 0x5423), 10306674e7fdSRomain Naour regmap_reg_range(0x5500, 0x5507), 10316674e7fdSRomain Naour regmap_reg_range(0x5600, 0x5612), 10326674e7fdSRomain Naour regmap_reg_range(0x5800, 0x580f), 10336674e7fdSRomain Naour regmap_reg_range(0x5820, 0x5827), 10346674e7fdSRomain Naour regmap_reg_range(0x5830, 0x5837), 10356674e7fdSRomain Naour regmap_reg_range(0x5840, 0x584b), 10366674e7fdSRomain Naour regmap_reg_range(0x5900, 0x5907), 10376674e7fdSRomain Naour regmap_reg_range(0x5914, 0x5915), 10386674e7fdSRomain Naour regmap_reg_range(0x5a00, 0x5a03), 10396674e7fdSRomain Naour regmap_reg_range(0x5a04, 0x5a07), 10406674e7fdSRomain Naour regmap_reg_range(0x5b00, 0x5b01), 10416674e7fdSRomain Naour regmap_reg_range(0x5b04, 0x5b04), 10426674e7fdSRomain Naour 10436674e7fdSRomain Naour /* port 6 */ 10446674e7fdSRomain Naour regmap_reg_range(0x6000, 0x6001), 10456674e7fdSRomain Naour regmap_reg_range(0x6013, 0x6013), 10466674e7fdSRomain Naour regmap_reg_range(0x6017, 0x6017), 10476674e7fdSRomain Naour regmap_reg_range(0x601b, 0x601b), 10486674e7fdSRomain Naour regmap_reg_range(0x601f, 0x6020), 10496674e7fdSRomain Naour regmap_reg_range(0x6030, 0x6030), 10506674e7fdSRomain Naour regmap_reg_range(0x6100, 0x6115), 10516674e7fdSRomain Naour regmap_reg_range(0x611a, 0x611f), 10526674e7fdSRomain Naour regmap_reg_range(0x6122, 0x6127), 10536674e7fdSRomain Naour regmap_reg_range(0x612a, 0x612b), 10546674e7fdSRomain Naour regmap_reg_range(0x6136, 0x6139), 10556674e7fdSRomain Naour regmap_reg_range(0x613e, 0x613f), 10566674e7fdSRomain Naour regmap_reg_range(0x6300, 0x6301), 10576674e7fdSRomain Naour regmap_reg_range(0x6400, 0x6401), 10586674e7fdSRomain Naour regmap_reg_range(0x6403, 0x6403), 10596674e7fdSRomain Naour regmap_reg_range(0x6410, 0x6417), 10606674e7fdSRomain Naour regmap_reg_range(0x6420, 0x6423), 10616674e7fdSRomain Naour regmap_reg_range(0x6500, 0x6507), 10626674e7fdSRomain Naour regmap_reg_range(0x6600, 0x6612), 10636674e7fdSRomain Naour regmap_reg_range(0x6800, 0x680f), 10646674e7fdSRomain Naour regmap_reg_range(0x6820, 0x6827), 10656674e7fdSRomain Naour regmap_reg_range(0x6830, 0x6837), 10666674e7fdSRomain Naour regmap_reg_range(0x6840, 0x684b), 10676674e7fdSRomain Naour regmap_reg_range(0x6900, 0x6907), 10686674e7fdSRomain Naour regmap_reg_range(0x6914, 0x6915), 10696674e7fdSRomain Naour regmap_reg_range(0x6a00, 0x6a03), 10706674e7fdSRomain Naour regmap_reg_range(0x6a04, 0x6a07), 10716674e7fdSRomain Naour regmap_reg_range(0x6b00, 0x6b01), 10726674e7fdSRomain Naour regmap_reg_range(0x6b04, 0x6b04), 10736674e7fdSRomain Naour }; 10746674e7fdSRomain Naour 10756674e7fdSRomain Naour static const struct regmap_access_table ksz9896_register_set = { 10766674e7fdSRomain Naour .yes_ranges = ksz9896_valid_regs, 10776674e7fdSRomain Naour .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs), 10786674e7fdSRomain Naour }; 10796674e7fdSRomain Naour 1080eee16b14SArun Ramadoss const struct ksz_chip_data ksz_switch_chips[] = { 1081b4490809SOleksij Rempel [KSZ8563] = { 1082b4490809SOleksij Rempel .chip_id = KSZ8563_CHIP_ID, 1083b4490809SOleksij Rempel .dev_name = "KSZ8563", 1084b4490809SOleksij Rempel .num_vlans = 4096, 1085b4490809SOleksij Rempel .num_alus = 4096, 1086b4490809SOleksij Rempel .num_statics = 16, 1087b4490809SOleksij Rempel .cpu_ports = 0x07, /* can be configured as cpu port */ 1088b4490809SOleksij Rempel .port_cnt = 3, /* total port count */ 10894630d142SRakesh Sankaranarayanan .port_nirqs = 3, 1090e30f33a5SArun Ramadoss .num_tx_queues = 4, 1091*71d7920fSArun Ramadoss .tc_cbs_supported = true, 1092b4490809SOleksij Rempel .ops = &ksz9477_dev_ops, 1093b4490809SOleksij Rempel .mib_names = ksz9477_mib_names, 1094b4490809SOleksij Rempel .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1095b4490809SOleksij Rempel .reg_mib_cnt = MIB_COUNTER_NUM, 1096b4490809SOleksij Rempel .regs = ksz9477_regs, 1097b4490809SOleksij Rempel .masks = ksz9477_masks, 1098b4490809SOleksij Rempel .shifts = ksz9477_shifts, 1099b4490809SOleksij Rempel .xmii_ctrl0 = ksz9477_xmii_ctrl0, 1100b4490809SOleksij Rempel .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 1101b4490809SOleksij Rempel .supports_mii = {false, false, true}, 1102b4490809SOleksij Rempel .supports_rmii = {false, false, true}, 1103b4490809SOleksij Rempel .supports_rgmii = {false, false, true}, 1104b4490809SOleksij Rempel .internal_phy = {true, true, false}, 1105505bf320SOleksij Rempel .gbit_capable = {false, false, true}, 110641131bacSOleksij Rempel .wr_table = &ksz8563_register_set, 110741131bacSOleksij Rempel .rd_table = &ksz8563_register_set, 1108b4490809SOleksij Rempel }, 1109b4490809SOleksij Rempel 1110462d5250SArun Ramadoss [KSZ8795] = { 1111462d5250SArun Ramadoss .chip_id = KSZ8795_CHIP_ID, 1112462d5250SArun Ramadoss .dev_name = "KSZ8795", 1113462d5250SArun Ramadoss .num_vlans = 4096, 1114462d5250SArun Ramadoss .num_alus = 0, 1115462d5250SArun Ramadoss .num_statics = 8, 1116462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1117462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1118e30f33a5SArun Ramadoss .num_tx_queues = 4, 11196ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1120462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1121a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1122a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1123a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1124486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1125d23a5e18SArun Ramadoss .masks = ksz8795_masks, 112634e48383SArun Ramadoss .shifts = ksz8795_shifts, 1127aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 112846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 112965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 113065ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 113165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 113265ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1133462d5250SArun Ramadoss }, 1134462d5250SArun Ramadoss 1135462d5250SArun Ramadoss [KSZ8794] = { 1136462d5250SArun Ramadoss /* WARNING 1137462d5250SArun Ramadoss * ======= 1138462d5250SArun Ramadoss * KSZ8794 is similar to KSZ8795, except the port map 1139462d5250SArun Ramadoss * contains a gap between external and CPU ports, the 1140462d5250SArun Ramadoss * port map is NOT continuous. The per-port register 1141462d5250SArun Ramadoss * map is shifted accordingly too, i.e. registers at 1142462d5250SArun Ramadoss * offset 0x40 are NOT used on KSZ8794 and they ARE 1143462d5250SArun Ramadoss * used on KSZ8795 for external port 3. 1144462d5250SArun Ramadoss * external cpu 1145462d5250SArun Ramadoss * KSZ8794 0,1,2 4 1146462d5250SArun Ramadoss * KSZ8795 0,1,2,3 4 1147462d5250SArun Ramadoss * KSZ8765 0,1,2,3 4 1148462d5250SArun Ramadoss * port_cnt is configured as 5, even though it is 4 1149462d5250SArun Ramadoss */ 1150462d5250SArun Ramadoss .chip_id = KSZ8794_CHIP_ID, 1151462d5250SArun Ramadoss .dev_name = "KSZ8794", 1152462d5250SArun Ramadoss .num_vlans = 4096, 1153462d5250SArun Ramadoss .num_alus = 0, 1154462d5250SArun Ramadoss .num_statics = 8, 1155462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1156462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1157e30f33a5SArun Ramadoss .num_tx_queues = 4, 11586ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1159462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1160a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1161a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1162a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1163486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1164d23a5e18SArun Ramadoss .masks = ksz8795_masks, 116534e48383SArun Ramadoss .shifts = ksz8795_shifts, 1166aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 116746f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 116865ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 116965ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 117065ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 117165ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, false}, 1172462d5250SArun Ramadoss }, 1173462d5250SArun Ramadoss 1174462d5250SArun Ramadoss [KSZ8765] = { 1175462d5250SArun Ramadoss .chip_id = KSZ8765_CHIP_ID, 1176462d5250SArun Ramadoss .dev_name = "KSZ8765", 1177462d5250SArun Ramadoss .num_vlans = 4096, 1178462d5250SArun Ramadoss .num_alus = 0, 1179462d5250SArun Ramadoss .num_statics = 8, 1180462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1181462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1182e30f33a5SArun Ramadoss .num_tx_queues = 4, 11836ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1184462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1185a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1186a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1187a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1188486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1189d23a5e18SArun Ramadoss .masks = ksz8795_masks, 119034e48383SArun Ramadoss .shifts = ksz8795_shifts, 1191aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 119246f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 119365ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 119465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 119565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 119665ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1197462d5250SArun Ramadoss }, 1198462d5250SArun Ramadoss 1199462d5250SArun Ramadoss [KSZ8830] = { 1200462d5250SArun Ramadoss .chip_id = KSZ8830_CHIP_ID, 1201462d5250SArun Ramadoss .dev_name = "KSZ8863/KSZ8873", 1202462d5250SArun Ramadoss .num_vlans = 16, 1203462d5250SArun Ramadoss .num_alus = 0, 1204462d5250SArun Ramadoss .num_statics = 8, 1205462d5250SArun Ramadoss .cpu_ports = 0x4, /* can be configured as cpu port */ 1206462d5250SArun Ramadoss .port_cnt = 3, 1207e30f33a5SArun Ramadoss .num_tx_queues = 4, 12086ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1209a530e6f2SArun Ramadoss .mib_names = ksz88xx_mib_names, 1210a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), 1211a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1212486f9ca7SArun Ramadoss .regs = ksz8863_regs, 1213d23a5e18SArun Ramadoss .masks = ksz8863_masks, 121434e48383SArun Ramadoss .shifts = ksz8863_shifts, 121565ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 121665ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 121765ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1218462d5250SArun Ramadoss }, 1219462d5250SArun Ramadoss 1220462d5250SArun Ramadoss [KSZ9477] = { 1221462d5250SArun Ramadoss .chip_id = KSZ9477_CHIP_ID, 1222462d5250SArun Ramadoss .dev_name = "KSZ9477", 1223462d5250SArun Ramadoss .num_vlans = 4096, 1224462d5250SArun Ramadoss .num_alus = 4096, 1225462d5250SArun Ramadoss .num_statics = 16, 1226462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1227462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1228978f1f72SArun Ramadoss .port_nirqs = 4, 1229e30f33a5SArun Ramadoss .num_tx_queues = 4, 1230*71d7920fSArun Ramadoss .tc_cbs_supported = true, 12316ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1232462d5250SArun Ramadoss .phy_errata_9477 = true, 1233a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1234a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1235a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 12366877102fSArun Ramadoss .regs = ksz9477_regs, 1237457c182aSArun Ramadoss .masks = ksz9477_masks, 1238457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1239aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 124046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 124165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 124265ac79e1SArun Ramadoss false, true, false}, 124365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 124465ac79e1SArun Ramadoss false, true, false}, 124565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 124665ac79e1SArun Ramadoss false, true, false}, 124765ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 124865ac79e1SArun Ramadoss true, false, false}, 1249505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 125074e792b5SOleksij Rempel .wr_table = &ksz9477_register_set, 125174e792b5SOleksij Rempel .rd_table = &ksz9477_register_set, 1252462d5250SArun Ramadoss }, 1253462d5250SArun Ramadoss 12542eb3ff3cSRomain Naour [KSZ9896] = { 12552eb3ff3cSRomain Naour .chip_id = KSZ9896_CHIP_ID, 12562eb3ff3cSRomain Naour .dev_name = "KSZ9896", 12572eb3ff3cSRomain Naour .num_vlans = 4096, 12582eb3ff3cSRomain Naour .num_alus = 4096, 12592eb3ff3cSRomain Naour .num_statics = 16, 12602eb3ff3cSRomain Naour .cpu_ports = 0x3F, /* can be configured as cpu port */ 12612eb3ff3cSRomain Naour .port_cnt = 6, /* total physical port count */ 1262978f1f72SArun Ramadoss .port_nirqs = 2, 1263e30f33a5SArun Ramadoss .num_tx_queues = 4, 12642eb3ff3cSRomain Naour .ops = &ksz9477_dev_ops, 12652eb3ff3cSRomain Naour .phy_errata_9477 = true, 12662eb3ff3cSRomain Naour .mib_names = ksz9477_mib_names, 12672eb3ff3cSRomain Naour .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 12682eb3ff3cSRomain Naour .reg_mib_cnt = MIB_COUNTER_NUM, 12692eb3ff3cSRomain Naour .regs = ksz9477_regs, 12702eb3ff3cSRomain Naour .masks = ksz9477_masks, 12712eb3ff3cSRomain Naour .shifts = ksz9477_shifts, 12722eb3ff3cSRomain Naour .xmii_ctrl0 = ksz9477_xmii_ctrl0, 12732eb3ff3cSRomain Naour .xmii_ctrl1 = ksz9477_xmii_ctrl1, 12742eb3ff3cSRomain Naour .supports_mii = {false, false, false, false, 12752eb3ff3cSRomain Naour false, true}, 12762eb3ff3cSRomain Naour .supports_rmii = {false, false, false, false, 12772eb3ff3cSRomain Naour false, true}, 12782eb3ff3cSRomain Naour .supports_rgmii = {false, false, false, false, 12792eb3ff3cSRomain Naour false, true}, 12802eb3ff3cSRomain Naour .internal_phy = {true, true, true, true, 12812eb3ff3cSRomain Naour true, false}, 12822eb3ff3cSRomain Naour .gbit_capable = {true, true, true, true, true, true}, 12836674e7fdSRomain Naour .wr_table = &ksz9896_register_set, 12846674e7fdSRomain Naour .rd_table = &ksz9896_register_set, 12852eb3ff3cSRomain Naour }, 12862eb3ff3cSRomain Naour 1287462d5250SArun Ramadoss [KSZ9897] = { 1288462d5250SArun Ramadoss .chip_id = KSZ9897_CHIP_ID, 1289462d5250SArun Ramadoss .dev_name = "KSZ9897", 1290462d5250SArun Ramadoss .num_vlans = 4096, 1291462d5250SArun Ramadoss .num_alus = 4096, 1292462d5250SArun Ramadoss .num_statics = 16, 1293462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1294462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1295978f1f72SArun Ramadoss .port_nirqs = 2, 1296e30f33a5SArun Ramadoss .num_tx_queues = 4, 12976ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1298462d5250SArun Ramadoss .phy_errata_9477 = true, 1299a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1300a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1301a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13026877102fSArun Ramadoss .regs = ksz9477_regs, 1303457c182aSArun Ramadoss .masks = ksz9477_masks, 1304457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1305aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 130646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 130765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 130865ac79e1SArun Ramadoss false, true, true}, 130965ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 131065ac79e1SArun Ramadoss false, true, true}, 131165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 131265ac79e1SArun Ramadoss false, true, true}, 131365ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 131465ac79e1SArun Ramadoss true, false, false}, 1315505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1316462d5250SArun Ramadoss }, 1317462d5250SArun Ramadoss 1318462d5250SArun Ramadoss [KSZ9893] = { 1319462d5250SArun Ramadoss .chip_id = KSZ9893_CHIP_ID, 1320462d5250SArun Ramadoss .dev_name = "KSZ9893", 1321462d5250SArun Ramadoss .num_vlans = 4096, 1322462d5250SArun Ramadoss .num_alus = 4096, 1323462d5250SArun Ramadoss .num_statics = 16, 1324462d5250SArun Ramadoss .cpu_ports = 0x07, /* can be configured as cpu port */ 1325462d5250SArun Ramadoss .port_cnt = 3, /* total port count */ 1326978f1f72SArun Ramadoss .port_nirqs = 2, 1327e30f33a5SArun Ramadoss .num_tx_queues = 4, 13286ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1329a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1330a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1331a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13326877102fSArun Ramadoss .regs = ksz9477_regs, 1333457c182aSArun Ramadoss .masks = ksz9477_masks, 1334457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1335aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 133646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 133765ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 133865ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 133965ac79e1SArun Ramadoss .supports_rgmii = {false, false, true}, 134065ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1341505bf320SOleksij Rempel .gbit_capable = {true, true, true}, 1342462d5250SArun Ramadoss }, 1343462d5250SArun Ramadoss 1344ef912fe4SRakesh Sankaranarayanan [KSZ9563] = { 1345ef912fe4SRakesh Sankaranarayanan .chip_id = KSZ9563_CHIP_ID, 1346ef912fe4SRakesh Sankaranarayanan .dev_name = "KSZ9563", 1347ef912fe4SRakesh Sankaranarayanan .num_vlans = 4096, 1348ef912fe4SRakesh Sankaranarayanan .num_alus = 4096, 1349ef912fe4SRakesh Sankaranarayanan .num_statics = 16, 1350ef912fe4SRakesh Sankaranarayanan .cpu_ports = 0x07, /* can be configured as cpu port */ 1351ef912fe4SRakesh Sankaranarayanan .port_cnt = 3, /* total port count */ 1352ef912fe4SRakesh Sankaranarayanan .port_nirqs = 3, 1353e30f33a5SArun Ramadoss .num_tx_queues = 4, 1354*71d7920fSArun Ramadoss .tc_cbs_supported = true, 1355ef912fe4SRakesh Sankaranarayanan .ops = &ksz9477_dev_ops, 1356ef912fe4SRakesh Sankaranarayanan .mib_names = ksz9477_mib_names, 1357ef912fe4SRakesh Sankaranarayanan .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1358ef912fe4SRakesh Sankaranarayanan .reg_mib_cnt = MIB_COUNTER_NUM, 1359ef912fe4SRakesh Sankaranarayanan .regs = ksz9477_regs, 1360ef912fe4SRakesh Sankaranarayanan .masks = ksz9477_masks, 1361ef912fe4SRakesh Sankaranarayanan .shifts = ksz9477_shifts, 1362ef912fe4SRakesh Sankaranarayanan .xmii_ctrl0 = ksz9477_xmii_ctrl0, 1363ef912fe4SRakesh Sankaranarayanan .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 1364ef912fe4SRakesh Sankaranarayanan .supports_mii = {false, false, true}, 1365ef912fe4SRakesh Sankaranarayanan .supports_rmii = {false, false, true}, 1366ef912fe4SRakesh Sankaranarayanan .supports_rgmii = {false, false, true}, 1367ef912fe4SRakesh Sankaranarayanan .internal_phy = {true, true, false}, 1368ef912fe4SRakesh Sankaranarayanan .gbit_capable = {true, true, true}, 1369ef912fe4SRakesh Sankaranarayanan }, 1370ef912fe4SRakesh Sankaranarayanan 1371462d5250SArun Ramadoss [KSZ9567] = { 1372462d5250SArun Ramadoss .chip_id = KSZ9567_CHIP_ID, 1373462d5250SArun Ramadoss .dev_name = "KSZ9567", 1374462d5250SArun Ramadoss .num_vlans = 4096, 1375462d5250SArun Ramadoss .num_alus = 4096, 1376462d5250SArun Ramadoss .num_statics = 16, 1377462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1378462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1379978f1f72SArun Ramadoss .port_nirqs = 3, 1380e30f33a5SArun Ramadoss .num_tx_queues = 4, 1381*71d7920fSArun Ramadoss .tc_cbs_supported = true, 13826ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1383462d5250SArun Ramadoss .phy_errata_9477 = true, 1384a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1385a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1386a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13876877102fSArun Ramadoss .regs = ksz9477_regs, 1388457c182aSArun Ramadoss .masks = ksz9477_masks, 1389457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1390aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 139146f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 139265ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 139365ac79e1SArun Ramadoss false, true, true}, 139465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 139565ac79e1SArun Ramadoss false, true, true}, 139665ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 139765ac79e1SArun Ramadoss false, true, true}, 139865ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 139965ac79e1SArun Ramadoss true, false, false}, 1400505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1401462d5250SArun Ramadoss }, 1402462d5250SArun Ramadoss 1403462d5250SArun Ramadoss [LAN9370] = { 1404462d5250SArun Ramadoss .chip_id = LAN9370_CHIP_ID, 1405462d5250SArun Ramadoss .dev_name = "LAN9370", 1406462d5250SArun Ramadoss .num_vlans = 4096, 1407462d5250SArun Ramadoss .num_alus = 1024, 1408462d5250SArun Ramadoss .num_statics = 256, 1409462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1410462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1411978f1f72SArun Ramadoss .port_nirqs = 6, 1412e30f33a5SArun Ramadoss .num_tx_queues = 8, 1413*71d7920fSArun Ramadoss .tc_cbs_supported = true, 141455ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1415a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1416a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1417a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14186877102fSArun Ramadoss .regs = ksz9477_regs, 1419457c182aSArun Ramadoss .masks = lan937x_masks, 1420457c182aSArun Ramadoss .shifts = lan937x_shifts, 1421aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 142246f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 142365ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 142465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 142565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 142665ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1427462d5250SArun Ramadoss }, 1428462d5250SArun Ramadoss 1429462d5250SArun Ramadoss [LAN9371] = { 1430462d5250SArun Ramadoss .chip_id = LAN9371_CHIP_ID, 1431462d5250SArun Ramadoss .dev_name = "LAN9371", 1432462d5250SArun Ramadoss .num_vlans = 4096, 1433462d5250SArun Ramadoss .num_alus = 1024, 1434462d5250SArun Ramadoss .num_statics = 256, 1435462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1436462d5250SArun Ramadoss .port_cnt = 6, /* total physical port count */ 1437978f1f72SArun Ramadoss .port_nirqs = 6, 1438e30f33a5SArun Ramadoss .num_tx_queues = 8, 1439*71d7920fSArun Ramadoss .tc_cbs_supported = true, 144055ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1441a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1442a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1443a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14446877102fSArun Ramadoss .regs = ksz9477_regs, 1445457c182aSArun Ramadoss .masks = lan937x_masks, 1446457c182aSArun Ramadoss .shifts = lan937x_shifts, 1447aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 144846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 144965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true, true}, 145065ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true, true}, 145165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true, true}, 145265ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false, false}, 1453462d5250SArun Ramadoss }, 1454462d5250SArun Ramadoss 1455462d5250SArun Ramadoss [LAN9372] = { 1456462d5250SArun Ramadoss .chip_id = LAN9372_CHIP_ID, 1457462d5250SArun Ramadoss .dev_name = "LAN9372", 1458462d5250SArun Ramadoss .num_vlans = 4096, 1459462d5250SArun Ramadoss .num_alus = 1024, 1460462d5250SArun Ramadoss .num_statics = 256, 1461462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1462462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1463978f1f72SArun Ramadoss .port_nirqs = 6, 1464e30f33a5SArun Ramadoss .num_tx_queues = 8, 1465*71d7920fSArun Ramadoss .tc_cbs_supported = true, 146655ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1467a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1468a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1469a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14706877102fSArun Ramadoss .regs = ksz9477_regs, 1471457c182aSArun Ramadoss .masks = lan937x_masks, 1472457c182aSArun Ramadoss .shifts = lan937x_shifts, 1473aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 147446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 147565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 147665ac79e1SArun Ramadoss true, true, false, false}, 147765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 147865ac79e1SArun Ramadoss true, true, false, false}, 147965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 148065ac79e1SArun Ramadoss true, true, false, false}, 148165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 148265ac79e1SArun Ramadoss false, false, true, true}, 1483462d5250SArun Ramadoss }, 1484462d5250SArun Ramadoss 1485462d5250SArun Ramadoss [LAN9373] = { 1486462d5250SArun Ramadoss .chip_id = LAN9373_CHIP_ID, 1487462d5250SArun Ramadoss .dev_name = "LAN9373", 1488462d5250SArun Ramadoss .num_vlans = 4096, 1489462d5250SArun Ramadoss .num_alus = 1024, 1490462d5250SArun Ramadoss .num_statics = 256, 1491462d5250SArun Ramadoss .cpu_ports = 0x38, /* can be configured as cpu port */ 1492462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1493978f1f72SArun Ramadoss .port_nirqs = 6, 1494e30f33a5SArun Ramadoss .num_tx_queues = 8, 1495*71d7920fSArun Ramadoss .tc_cbs_supported = true, 149655ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1497a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1498a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1499a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 15006877102fSArun Ramadoss .regs = ksz9477_regs, 1501457c182aSArun Ramadoss .masks = lan937x_masks, 1502457c182aSArun Ramadoss .shifts = lan937x_shifts, 1503aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 150446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 150565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 150665ac79e1SArun Ramadoss true, true, false, false}, 150765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 150865ac79e1SArun Ramadoss true, true, false, false}, 150965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 151065ac79e1SArun Ramadoss true, true, false, false}, 151165ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, 151265ac79e1SArun Ramadoss false, false, true, true}, 1513462d5250SArun Ramadoss }, 1514462d5250SArun Ramadoss 1515462d5250SArun Ramadoss [LAN9374] = { 1516462d5250SArun Ramadoss .chip_id = LAN9374_CHIP_ID, 1517462d5250SArun Ramadoss .dev_name = "LAN9374", 1518462d5250SArun Ramadoss .num_vlans = 4096, 1519462d5250SArun Ramadoss .num_alus = 1024, 1520462d5250SArun Ramadoss .num_statics = 256, 1521462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1522462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1523978f1f72SArun Ramadoss .port_nirqs = 6, 1524e30f33a5SArun Ramadoss .num_tx_queues = 8, 1525*71d7920fSArun Ramadoss .tc_cbs_supported = true, 152655ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1527a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1528a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1529a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 15306877102fSArun Ramadoss .regs = ksz9477_regs, 1531457c182aSArun Ramadoss .masks = lan937x_masks, 1532457c182aSArun Ramadoss .shifts = lan937x_shifts, 1533aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 153446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 153565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 153665ac79e1SArun Ramadoss true, true, false, false}, 153765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 153865ac79e1SArun Ramadoss true, true, false, false}, 153965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 154065ac79e1SArun Ramadoss true, true, false, false}, 154165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 154265ac79e1SArun Ramadoss false, false, true, true}, 1543462d5250SArun Ramadoss }, 1544462d5250SArun Ramadoss }; 1545eee16b14SArun Ramadoss EXPORT_SYMBOL_GPL(ksz_switch_chips); 1546462d5250SArun Ramadoss 1547462d5250SArun Ramadoss static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num) 1548462d5250SArun Ramadoss { 1549462d5250SArun Ramadoss int i; 1550462d5250SArun Ramadoss 1551462d5250SArun Ramadoss for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) { 1552462d5250SArun Ramadoss const struct ksz_chip_data *chip = &ksz_switch_chips[i]; 1553462d5250SArun Ramadoss 1554462d5250SArun Ramadoss if (chip->chip_id == prod_num) 1555462d5250SArun Ramadoss return chip; 1556462d5250SArun Ramadoss } 1557462d5250SArun Ramadoss 1558462d5250SArun Ramadoss return NULL; 1559462d5250SArun Ramadoss } 1560462d5250SArun Ramadoss 1561eee16b14SArun Ramadoss static int ksz_check_device_id(struct ksz_device *dev) 1562eee16b14SArun Ramadoss { 1563eee16b14SArun Ramadoss const struct ksz_chip_data *dt_chip_data; 1564eee16b14SArun Ramadoss 1565eee16b14SArun Ramadoss dt_chip_data = of_device_get_match_data(dev->dev); 1566eee16b14SArun Ramadoss 1567eee16b14SArun Ramadoss /* Check for Device Tree and Chip ID */ 1568eee16b14SArun Ramadoss if (dt_chip_data->chip_id != dev->chip_id) { 1569eee16b14SArun Ramadoss dev_err(dev->dev, 1570eee16b14SArun Ramadoss "Device tree specifies chip %s but found %s, please fix it!\n", 1571eee16b14SArun Ramadoss dt_chip_data->dev_name, dev->info->dev_name); 1572eee16b14SArun Ramadoss return -ENODEV; 1573eee16b14SArun Ramadoss } 1574eee16b14SArun Ramadoss 1575eee16b14SArun Ramadoss return 0; 1576eee16b14SArun Ramadoss } 1577eee16b14SArun Ramadoss 15781958eee8SArun Ramadoss static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, 157965ac79e1SArun Ramadoss struct phylink_config *config) 158065ac79e1SArun Ramadoss { 158165ac79e1SArun Ramadoss struct ksz_device *dev = ds->priv; 158265ac79e1SArun Ramadoss 158365ac79e1SArun Ramadoss config->legacy_pre_march2020 = false; 158465ac79e1SArun Ramadoss 158565ac79e1SArun Ramadoss if (dev->info->supports_mii[port]) 158665ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); 158765ac79e1SArun Ramadoss 158865ac79e1SArun Ramadoss if (dev->info->supports_rmii[port]) 158965ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_RMII, 159065ac79e1SArun Ramadoss config->supported_interfaces); 159165ac79e1SArun Ramadoss 159265ac79e1SArun Ramadoss if (dev->info->supports_rgmii[port]) 159365ac79e1SArun Ramadoss phy_interface_set_rgmii(config->supported_interfaces); 159465ac79e1SArun Ramadoss 15955fbb08ebSVladimir Oltean if (dev->info->internal_phy[port]) { 159665ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_INTERNAL, 159765ac79e1SArun Ramadoss config->supported_interfaces); 15985fbb08ebSVladimir Oltean /* Compatibility for phylib's default interface type when the 15995fbb08ebSVladimir Oltean * phy-mode property is absent 16005fbb08ebSVladimir Oltean */ 16015fbb08ebSVladimir Oltean __set_bit(PHY_INTERFACE_MODE_GMII, 16025fbb08ebSVladimir Oltean config->supported_interfaces); 16035fbb08ebSVladimir Oltean } 16047012033cSArun Ramadoss 16057012033cSArun Ramadoss if (dev->dev_ops->get_caps) 16067012033cSArun Ramadoss dev->dev_ops->get_caps(dev, port, config); 160765ac79e1SArun Ramadoss } 160865ac79e1SArun Ramadoss 1609c6101dd7SArun Ramadoss void ksz_r_mib_stats64(struct ksz_device *dev, int port) 1610c6101dd7SArun Ramadoss { 1611c4748ff6SOleksij Rempel struct ethtool_pause_stats *pstats; 1612c6101dd7SArun Ramadoss struct rtnl_link_stats64 *stats; 1613c6101dd7SArun Ramadoss struct ksz_stats_raw *raw; 1614c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1615c6101dd7SArun Ramadoss 1616c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1617c6101dd7SArun Ramadoss stats = &mib->stats64; 1618c4748ff6SOleksij Rempel pstats = &mib->pause_stats; 1619c6101dd7SArun Ramadoss raw = (struct ksz_stats_raw *)mib->counters; 1620c6101dd7SArun Ramadoss 1621c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1622c6101dd7SArun Ramadoss 1623961d6c70SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 1624961d6c70SOleksij Rempel raw->rx_pause; 1625961d6c70SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 1626961d6c70SOleksij Rempel raw->tx_pause; 1627c6101dd7SArun Ramadoss 1628c6101dd7SArun Ramadoss /* HW counters are counting bytes + FCS which is not acceptable 1629c6101dd7SArun Ramadoss * for rtnl_link_stats64 interface 1630c6101dd7SArun Ramadoss */ 1631c6101dd7SArun Ramadoss stats->rx_bytes = raw->rx_total - stats->rx_packets * ETH_FCS_LEN; 1632c6101dd7SArun Ramadoss stats->tx_bytes = raw->tx_total - stats->tx_packets * ETH_FCS_LEN; 1633c6101dd7SArun Ramadoss 1634c6101dd7SArun Ramadoss stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 1635c6101dd7SArun Ramadoss raw->rx_oversize; 1636c6101dd7SArun Ramadoss 1637c6101dd7SArun Ramadoss stats->rx_crc_errors = raw->rx_crc_err; 1638c6101dd7SArun Ramadoss stats->rx_frame_errors = raw->rx_align_err; 1639c6101dd7SArun Ramadoss stats->rx_dropped = raw->rx_discards; 1640c6101dd7SArun Ramadoss stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 1641c6101dd7SArun Ramadoss stats->rx_frame_errors + stats->rx_dropped; 1642c6101dd7SArun Ramadoss 1643c6101dd7SArun Ramadoss stats->tx_window_errors = raw->tx_late_col; 1644c6101dd7SArun Ramadoss stats->tx_fifo_errors = raw->tx_discards; 1645c6101dd7SArun Ramadoss stats->tx_aborted_errors = raw->tx_exc_col; 1646c6101dd7SArun Ramadoss stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 1647c6101dd7SArun Ramadoss stats->tx_aborted_errors; 1648c6101dd7SArun Ramadoss 1649c6101dd7SArun Ramadoss stats->multicast = raw->rx_mcast; 1650c6101dd7SArun Ramadoss stats->collisions = raw->tx_total_col; 1651c6101dd7SArun Ramadoss 1652c4748ff6SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 1653c4748ff6SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 1654c4748ff6SOleksij Rempel 1655c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1656c6101dd7SArun Ramadoss } 1657c6101dd7SArun Ramadoss 1658bde55dd9SOleksij Rempel void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port) 1659bde55dd9SOleksij Rempel { 1660bde55dd9SOleksij Rempel struct ethtool_pause_stats *pstats; 1661bde55dd9SOleksij Rempel struct rtnl_link_stats64 *stats; 1662bde55dd9SOleksij Rempel struct ksz88xx_stats_raw *raw; 1663bde55dd9SOleksij Rempel struct ksz_port_mib *mib; 1664bde55dd9SOleksij Rempel 1665bde55dd9SOleksij Rempel mib = &dev->ports[port].mib; 1666bde55dd9SOleksij Rempel stats = &mib->stats64; 1667bde55dd9SOleksij Rempel pstats = &mib->pause_stats; 1668bde55dd9SOleksij Rempel raw = (struct ksz88xx_stats_raw *)mib->counters; 1669bde55dd9SOleksij Rempel 1670bde55dd9SOleksij Rempel spin_lock(&mib->stats64_lock); 1671bde55dd9SOleksij Rempel 1672bde55dd9SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 1673bde55dd9SOleksij Rempel raw->rx_pause; 1674bde55dd9SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 1675bde55dd9SOleksij Rempel raw->tx_pause; 1676bde55dd9SOleksij Rempel 1677bde55dd9SOleksij Rempel /* HW counters are counting bytes + FCS which is not acceptable 1678bde55dd9SOleksij Rempel * for rtnl_link_stats64 interface 1679bde55dd9SOleksij Rempel */ 1680bde55dd9SOleksij Rempel stats->rx_bytes = raw->rx + raw->rx_hi - stats->rx_packets * ETH_FCS_LEN; 1681bde55dd9SOleksij Rempel stats->tx_bytes = raw->tx + raw->tx_hi - stats->tx_packets * ETH_FCS_LEN; 1682bde55dd9SOleksij Rempel 1683bde55dd9SOleksij Rempel stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 1684bde55dd9SOleksij Rempel raw->rx_oversize; 1685bde55dd9SOleksij Rempel 1686bde55dd9SOleksij Rempel stats->rx_crc_errors = raw->rx_crc_err; 1687bde55dd9SOleksij Rempel stats->rx_frame_errors = raw->rx_align_err; 1688bde55dd9SOleksij Rempel stats->rx_dropped = raw->rx_discards; 1689bde55dd9SOleksij Rempel stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 1690bde55dd9SOleksij Rempel stats->rx_frame_errors + stats->rx_dropped; 1691bde55dd9SOleksij Rempel 1692bde55dd9SOleksij Rempel stats->tx_window_errors = raw->tx_late_col; 1693bde55dd9SOleksij Rempel stats->tx_fifo_errors = raw->tx_discards; 1694bde55dd9SOleksij Rempel stats->tx_aborted_errors = raw->tx_exc_col; 1695bde55dd9SOleksij Rempel stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 1696bde55dd9SOleksij Rempel stats->tx_aborted_errors; 1697bde55dd9SOleksij Rempel 1698bde55dd9SOleksij Rempel stats->multicast = raw->rx_mcast; 1699bde55dd9SOleksij Rempel stats->collisions = raw->tx_total_col; 1700bde55dd9SOleksij Rempel 1701bde55dd9SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 1702bde55dd9SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 1703bde55dd9SOleksij Rempel 1704bde55dd9SOleksij Rempel spin_unlock(&mib->stats64_lock); 1705bde55dd9SOleksij Rempel } 1706bde55dd9SOleksij Rempel 17071958eee8SArun Ramadoss static void ksz_get_stats64(struct dsa_switch *ds, int port, 1708c6101dd7SArun Ramadoss struct rtnl_link_stats64 *s) 1709c6101dd7SArun Ramadoss { 1710c6101dd7SArun Ramadoss struct ksz_device *dev = ds->priv; 1711c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1712c6101dd7SArun Ramadoss 1713c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1714c6101dd7SArun Ramadoss 1715c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1716c6101dd7SArun Ramadoss memcpy(s, &mib->stats64, sizeof(*s)); 1717c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1718c6101dd7SArun Ramadoss } 1719c6101dd7SArun Ramadoss 1720c4748ff6SOleksij Rempel static void ksz_get_pause_stats(struct dsa_switch *ds, int port, 1721c4748ff6SOleksij Rempel struct ethtool_pause_stats *pause_stats) 1722c4748ff6SOleksij Rempel { 1723c4748ff6SOleksij Rempel struct ksz_device *dev = ds->priv; 1724c4748ff6SOleksij Rempel struct ksz_port_mib *mib; 1725c4748ff6SOleksij Rempel 1726c4748ff6SOleksij Rempel mib = &dev->ports[port].mib; 1727c4748ff6SOleksij Rempel 1728c4748ff6SOleksij Rempel spin_lock(&mib->stats64_lock); 1729c4748ff6SOleksij Rempel memcpy(pause_stats, &mib->pause_stats, sizeof(*pause_stats)); 1730c4748ff6SOleksij Rempel spin_unlock(&mib->stats64_lock); 1731c4748ff6SOleksij Rempel } 1732c4748ff6SOleksij Rempel 17331958eee8SArun Ramadoss static void ksz_get_strings(struct dsa_switch *ds, int port, 1734997d2126SArun Ramadoss u32 stringset, uint8_t *buf) 1735997d2126SArun Ramadoss { 1736997d2126SArun Ramadoss struct ksz_device *dev = ds->priv; 1737997d2126SArun Ramadoss int i; 1738997d2126SArun Ramadoss 1739997d2126SArun Ramadoss if (stringset != ETH_SS_STATS) 1740997d2126SArun Ramadoss return; 1741997d2126SArun Ramadoss 1742997d2126SArun Ramadoss for (i = 0; i < dev->info->mib_cnt; i++) { 1743997d2126SArun Ramadoss memcpy(buf + i * ETH_GSTRING_LEN, 1744997d2126SArun Ramadoss dev->info->mib_names[i].string, ETH_GSTRING_LEN); 1745997d2126SArun Ramadoss } 1746997d2126SArun Ramadoss } 1747997d2126SArun Ramadoss 1748e593df51SArun Ramadoss static void ksz_update_port_member(struct ksz_device *dev, int port) 1749b987e98eSWoojung Huh { 1750b3612ccdSOleksij Rempel struct ksz_port *p = &dev->ports[port]; 1751b3612ccdSOleksij Rempel struct dsa_switch *ds = dev->ds; 1752b3612ccdSOleksij Rempel u8 port_member = 0, cpu_port; 1753b3612ccdSOleksij Rempel const struct dsa_port *dp; 17543d00827aSSvenning Sørensen int i, j; 1755b987e98eSWoojung Huh 1756b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, port)) 1757b3612ccdSOleksij Rempel return; 1758b3612ccdSOleksij Rempel 1759b3612ccdSOleksij Rempel dp = dsa_to_port(ds, port); 1760b3612ccdSOleksij Rempel cpu_port = BIT(dsa_upstream_port(ds, port)); 1761b3612ccdSOleksij Rempel 1762b3612ccdSOleksij Rempel for (i = 0; i < ds->num_ports; i++) { 1763b3612ccdSOleksij Rempel const struct dsa_port *other_dp = dsa_to_port(ds, i); 1764b3612ccdSOleksij Rempel struct ksz_port *other_p = &dev->ports[i]; 1765b3612ccdSOleksij Rempel u8 val = 0; 1766b3612ccdSOleksij Rempel 1767b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, i)) 1768c2e86691STristram Ha continue; 1769b3612ccdSOleksij Rempel if (port == i) 1770b3612ccdSOleksij Rempel continue; 177141fb0cf1SVladimir Oltean if (!dsa_port_bridge_same(dp, other_dp)) 1772c2e86691STristram Ha continue; 17733d00827aSSvenning Sørensen if (other_p->stp_state != BR_STATE_FORWARDING) 17743d00827aSSvenning Sørensen continue; 1775b987e98eSWoojung Huh 17763d00827aSSvenning Sørensen if (p->stp_state == BR_STATE_FORWARDING) { 1777b3612ccdSOleksij Rempel val |= BIT(port); 1778b3612ccdSOleksij Rempel port_member |= BIT(i); 1779b987e98eSWoojung Huh } 1780b3612ccdSOleksij Rempel 17813d00827aSSvenning Sørensen /* Retain port [i]'s relationship to other ports than [port] */ 17823d00827aSSvenning Sørensen for (j = 0; j < ds->num_ports; j++) { 17833d00827aSSvenning Sørensen const struct dsa_port *third_dp; 17843d00827aSSvenning Sørensen struct ksz_port *third_p; 17853d00827aSSvenning Sørensen 17863d00827aSSvenning Sørensen if (j == i) 17873d00827aSSvenning Sørensen continue; 17883d00827aSSvenning Sørensen if (j == port) 17893d00827aSSvenning Sørensen continue; 17903d00827aSSvenning Sørensen if (!dsa_is_user_port(ds, j)) 17913d00827aSSvenning Sørensen continue; 17923d00827aSSvenning Sørensen third_p = &dev->ports[j]; 17933d00827aSSvenning Sørensen if (third_p->stp_state != BR_STATE_FORWARDING) 17943d00827aSSvenning Sørensen continue; 17953d00827aSSvenning Sørensen third_dp = dsa_to_port(ds, j); 17963d00827aSSvenning Sørensen if (dsa_port_bridge_same(other_dp, third_dp)) 17973d00827aSSvenning Sørensen val |= BIT(j); 17983d00827aSSvenning Sørensen } 17993d00827aSSvenning Sørensen 1800b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); 1801b3612ccdSOleksij Rempel } 1802b3612ccdSOleksij Rempel 1803b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); 1804b987e98eSWoojung Huh } 1805b987e98eSWoojung Huh 1806ff319a64SArun Ramadoss static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum) 1807ff319a64SArun Ramadoss { 1808ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1809ff319a64SArun Ramadoss u16 val; 1810ff319a64SArun Ramadoss int ret; 1811ff319a64SArun Ramadoss 1812ff319a64SArun Ramadoss ret = dev->dev_ops->r_phy(dev, addr, regnum, &val); 1813ff319a64SArun Ramadoss if (ret < 0) 1814ff319a64SArun Ramadoss return ret; 1815ff319a64SArun Ramadoss 1816ff319a64SArun Ramadoss return val; 1817ff319a64SArun Ramadoss } 1818ff319a64SArun Ramadoss 1819ff319a64SArun Ramadoss static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, 1820ff319a64SArun Ramadoss u16 val) 1821ff319a64SArun Ramadoss { 1822ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1823ff319a64SArun Ramadoss 1824ff319a64SArun Ramadoss return dev->dev_ops->w_phy(dev, addr, regnum, val); 1825ff319a64SArun Ramadoss } 1826ff319a64SArun Ramadoss 1827ff319a64SArun Ramadoss static int ksz_irq_phy_setup(struct ksz_device *dev) 1828ff319a64SArun Ramadoss { 1829ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1830ff319a64SArun Ramadoss int phy; 1831ff319a64SArun Ramadoss int irq; 1832ff319a64SArun Ramadoss int ret; 1833ff319a64SArun Ramadoss 1834ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) { 1835ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) { 1836ff319a64SArun Ramadoss irq = irq_find_mapping(dev->ports[phy].pirq.domain, 1837ff319a64SArun Ramadoss PORT_SRC_PHY_INT); 1838ff319a64SArun Ramadoss if (irq < 0) { 1839ff319a64SArun Ramadoss ret = irq; 1840ff319a64SArun Ramadoss goto out; 1841ff319a64SArun Ramadoss } 1842ff319a64SArun Ramadoss ds->slave_mii_bus->irq[phy] = irq; 1843ff319a64SArun Ramadoss } 1844ff319a64SArun Ramadoss } 1845ff319a64SArun Ramadoss return 0; 1846ff319a64SArun Ramadoss out: 1847ff319a64SArun Ramadoss while (phy--) 1848ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1849ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1850ff319a64SArun Ramadoss 1851ff319a64SArun Ramadoss return ret; 1852ff319a64SArun Ramadoss } 1853ff319a64SArun Ramadoss 1854ff319a64SArun Ramadoss static void ksz_irq_phy_free(struct ksz_device *dev) 1855ff319a64SArun Ramadoss { 1856ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1857ff319a64SArun Ramadoss int phy; 1858ff319a64SArun Ramadoss 1859ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) 1860ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1861ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1862ff319a64SArun Ramadoss } 1863ff319a64SArun Ramadoss 1864ff319a64SArun Ramadoss static int ksz_mdio_register(struct ksz_device *dev) 1865ff319a64SArun Ramadoss { 1866ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1867ff319a64SArun Ramadoss struct device_node *mdio_np; 1868ff319a64SArun Ramadoss struct mii_bus *bus; 1869ff319a64SArun Ramadoss int ret; 1870ff319a64SArun Ramadoss 1871ff319a64SArun Ramadoss mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio"); 1872ff319a64SArun Ramadoss if (!mdio_np) 1873ff319a64SArun Ramadoss return 0; 1874ff319a64SArun Ramadoss 1875ff319a64SArun Ramadoss bus = devm_mdiobus_alloc(ds->dev); 1876ff319a64SArun Ramadoss if (!bus) { 1877ff319a64SArun Ramadoss of_node_put(mdio_np); 1878ff319a64SArun Ramadoss return -ENOMEM; 1879ff319a64SArun Ramadoss } 1880ff319a64SArun Ramadoss 1881ff319a64SArun Ramadoss bus->priv = dev; 1882ff319a64SArun Ramadoss bus->read = ksz_sw_mdio_read; 1883ff319a64SArun Ramadoss bus->write = ksz_sw_mdio_write; 1884ff319a64SArun Ramadoss bus->name = "ksz slave smi"; 1885ff319a64SArun Ramadoss snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index); 1886ff319a64SArun Ramadoss bus->parent = ds->dev; 1887ff319a64SArun Ramadoss bus->phy_mask = ~ds->phys_mii_mask; 1888ff319a64SArun Ramadoss 1889ff319a64SArun Ramadoss ds->slave_mii_bus = bus; 1890ff319a64SArun Ramadoss 1891ff319a64SArun Ramadoss if (dev->irq > 0) { 1892ff319a64SArun Ramadoss ret = ksz_irq_phy_setup(dev); 1893ff319a64SArun Ramadoss if (ret) { 1894ff319a64SArun Ramadoss of_node_put(mdio_np); 1895ff319a64SArun Ramadoss return ret; 1896ff319a64SArun Ramadoss } 1897ff319a64SArun Ramadoss } 1898ff319a64SArun Ramadoss 1899ff319a64SArun Ramadoss ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np); 1900ff319a64SArun Ramadoss if (ret) { 1901ff319a64SArun Ramadoss dev_err(ds->dev, "unable to register MDIO bus %s\n", 1902ff319a64SArun Ramadoss bus->id); 1903ff319a64SArun Ramadoss if (dev->irq > 0) 1904ff319a64SArun Ramadoss ksz_irq_phy_free(dev); 1905ff319a64SArun Ramadoss } 1906ff319a64SArun Ramadoss 1907ff319a64SArun Ramadoss of_node_put(mdio_np); 1908ff319a64SArun Ramadoss 1909ff319a64SArun Ramadoss return ret; 1910ff319a64SArun Ramadoss } 1911ff319a64SArun Ramadoss 1912e1add7ddSArun Ramadoss static void ksz_irq_mask(struct irq_data *d) 1913ff319a64SArun Ramadoss { 1914e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1915ff319a64SArun Ramadoss 1916e1add7ddSArun Ramadoss kirq->masked |= BIT(d->hwirq); 1917ff319a64SArun Ramadoss } 1918ff319a64SArun Ramadoss 1919e1add7ddSArun Ramadoss static void ksz_irq_unmask(struct irq_data *d) 1920ff319a64SArun Ramadoss { 1921e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1922ff319a64SArun Ramadoss 1923e1add7ddSArun Ramadoss kirq->masked &= ~BIT(d->hwirq); 1924ff319a64SArun Ramadoss } 1925ff319a64SArun Ramadoss 1926e1add7ddSArun Ramadoss static void ksz_irq_bus_lock(struct irq_data *d) 1927ff319a64SArun Ramadoss { 1928e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1929ff319a64SArun Ramadoss 1930e1add7ddSArun Ramadoss mutex_lock(&kirq->dev->lock_irq); 1931ff319a64SArun Ramadoss } 1932ff319a64SArun Ramadoss 1933e1add7ddSArun Ramadoss static void ksz_irq_bus_sync_unlock(struct irq_data *d) 1934ff319a64SArun Ramadoss { 1935e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1936e1add7ddSArun Ramadoss struct ksz_device *dev = kirq->dev; 1937ff319a64SArun Ramadoss int ret; 1938ff319a64SArun Ramadoss 1939e1add7ddSArun Ramadoss ret = ksz_write32(dev, kirq->reg_mask, kirq->masked); 1940ff319a64SArun Ramadoss if (ret) 1941ff319a64SArun Ramadoss dev_err(dev->dev, "failed to change IRQ mask\n"); 1942ff319a64SArun Ramadoss 1943ff319a64SArun Ramadoss mutex_unlock(&dev->lock_irq); 1944ff319a64SArun Ramadoss } 1945ff319a64SArun Ramadoss 1946e1add7ddSArun Ramadoss static const struct irq_chip ksz_irq_chip = { 1947e1add7ddSArun Ramadoss .name = "ksz-irq", 1948e1add7ddSArun Ramadoss .irq_mask = ksz_irq_mask, 1949e1add7ddSArun Ramadoss .irq_unmask = ksz_irq_unmask, 1950e1add7ddSArun Ramadoss .irq_bus_lock = ksz_irq_bus_lock, 1951e1add7ddSArun Ramadoss .irq_bus_sync_unlock = ksz_irq_bus_sync_unlock, 1952ff319a64SArun Ramadoss }; 1953ff319a64SArun Ramadoss 1954e1add7ddSArun Ramadoss static int ksz_irq_domain_map(struct irq_domain *d, 1955ff319a64SArun Ramadoss unsigned int irq, irq_hw_number_t hwirq) 1956ff319a64SArun Ramadoss { 1957ff319a64SArun Ramadoss irq_set_chip_data(irq, d->host_data); 1958e1add7ddSArun Ramadoss irq_set_chip_and_handler(irq, &ksz_irq_chip, handle_level_irq); 1959ff319a64SArun Ramadoss irq_set_noprobe(irq); 1960ff319a64SArun Ramadoss 1961ff319a64SArun Ramadoss return 0; 1962ff319a64SArun Ramadoss } 1963ff319a64SArun Ramadoss 1964e1add7ddSArun Ramadoss static const struct irq_domain_ops ksz_irq_domain_ops = { 1965e1add7ddSArun Ramadoss .map = ksz_irq_domain_map, 1966ff319a64SArun Ramadoss .xlate = irq_domain_xlate_twocell, 1967ff319a64SArun Ramadoss }; 1968ff319a64SArun Ramadoss 1969e1add7ddSArun Ramadoss static void ksz_irq_free(struct ksz_irq *kirq) 1970ff319a64SArun Ramadoss { 1971ff319a64SArun Ramadoss int irq, virq; 1972ff319a64SArun Ramadoss 1973e1add7ddSArun Ramadoss free_irq(kirq->irq_num, kirq); 1974ff319a64SArun Ramadoss 1975e1add7ddSArun Ramadoss for (irq = 0; irq < kirq->nirqs; irq++) { 1976e1add7ddSArun Ramadoss virq = irq_find_mapping(kirq->domain, irq); 1977ff319a64SArun Ramadoss irq_dispose_mapping(virq); 1978ff319a64SArun Ramadoss } 1979ff319a64SArun Ramadoss 1980e1add7ddSArun Ramadoss irq_domain_remove(kirq->domain); 1981ff319a64SArun Ramadoss } 1982ff319a64SArun Ramadoss 1983e1add7ddSArun Ramadoss static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id) 1984ff319a64SArun Ramadoss { 1985e1add7ddSArun Ramadoss struct ksz_irq *kirq = dev_id; 1986ff319a64SArun Ramadoss unsigned int nhandled = 0; 1987e1add7ddSArun Ramadoss struct ksz_device *dev; 1988ff319a64SArun Ramadoss unsigned int sub_irq; 1989e1add7ddSArun Ramadoss u8 data; 1990ff319a64SArun Ramadoss int ret; 1991e1add7ddSArun Ramadoss u8 n; 1992ff319a64SArun Ramadoss 1993e1add7ddSArun Ramadoss dev = kirq->dev; 1994e1add7ddSArun Ramadoss 1995e1add7ddSArun Ramadoss /* Read interrupt status register */ 1996e1add7ddSArun Ramadoss ret = ksz_read8(dev, kirq->reg_status, &data); 1997ff319a64SArun Ramadoss if (ret) 1998ff319a64SArun Ramadoss goto out; 1999ff319a64SArun Ramadoss 2000e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; ++n) { 2001e1add7ddSArun Ramadoss if (data & BIT(n)) { 2002e1add7ddSArun Ramadoss sub_irq = irq_find_mapping(kirq->domain, n); 2003ff319a64SArun Ramadoss handle_nested_irq(sub_irq); 2004ff319a64SArun Ramadoss ++nhandled; 2005ff319a64SArun Ramadoss } 2006ff319a64SArun Ramadoss } 2007ff319a64SArun Ramadoss out: 2008ff319a64SArun Ramadoss return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 2009ff319a64SArun Ramadoss } 2010ff319a64SArun Ramadoss 2011e1add7ddSArun Ramadoss static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq) 2012e1add7ddSArun Ramadoss { 2013e1add7ddSArun Ramadoss int ret, n; 2014e1add7ddSArun Ramadoss 2015e1add7ddSArun Ramadoss kirq->dev = dev; 2016e1add7ddSArun Ramadoss kirq->masked = ~0; 2017e1add7ddSArun Ramadoss 2018e1add7ddSArun Ramadoss kirq->domain = irq_domain_add_simple(dev->dev->of_node, kirq->nirqs, 0, 2019e1add7ddSArun Ramadoss &ksz_irq_domain_ops, kirq); 2020e1add7ddSArun Ramadoss if (!kirq->domain) 2021e1add7ddSArun Ramadoss return -ENOMEM; 2022e1add7ddSArun Ramadoss 2023e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; n++) 2024e1add7ddSArun Ramadoss irq_create_mapping(kirq->domain, n); 2025e1add7ddSArun Ramadoss 2026e1add7ddSArun Ramadoss ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn, 202762e027fbSArun Ramadoss IRQF_ONESHOT, kirq->name, kirq); 2028e1add7ddSArun Ramadoss if (ret) 2029e1add7ddSArun Ramadoss goto out; 2030e1add7ddSArun Ramadoss 2031e1add7ddSArun Ramadoss return 0; 2032e1add7ddSArun Ramadoss 2033e1add7ddSArun Ramadoss out: 2034e1add7ddSArun Ramadoss ksz_irq_free(kirq); 2035e1add7ddSArun Ramadoss 2036e1add7ddSArun Ramadoss return ret; 2037e1add7ddSArun Ramadoss } 2038e1add7ddSArun Ramadoss 2039ff319a64SArun Ramadoss static int ksz_girq_setup(struct ksz_device *dev) 2040ff319a64SArun Ramadoss { 2041e1add7ddSArun Ramadoss struct ksz_irq *girq = &dev->girq; 2042ff319a64SArun Ramadoss 2043e1add7ddSArun Ramadoss girq->nirqs = dev->info->port_cnt; 2044e1add7ddSArun Ramadoss girq->reg_mask = REG_SW_PORT_INT_MASK__1; 2045e1add7ddSArun Ramadoss girq->reg_status = REG_SW_PORT_INT_STATUS__1; 2046e1add7ddSArun Ramadoss snprintf(girq->name, sizeof(girq->name), "global_port_irq"); 2047ff319a64SArun Ramadoss 2048e1add7ddSArun Ramadoss girq->irq_num = dev->irq; 2049ff319a64SArun Ramadoss 2050e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, girq); 2051ff319a64SArun Ramadoss } 2052ff319a64SArun Ramadoss 2053ff319a64SArun Ramadoss static int ksz_pirq_setup(struct ksz_device *dev, u8 p) 2054ff319a64SArun Ramadoss { 2055e1add7ddSArun Ramadoss struct ksz_irq *pirq = &dev->ports[p].pirq; 2056ff319a64SArun Ramadoss 2057e1add7ddSArun Ramadoss pirq->nirqs = dev->info->port_nirqs; 2058e1add7ddSArun Ramadoss pirq->reg_mask = dev->dev_ops->get_port_addr(p, REG_PORT_INT_MASK); 2059e1add7ddSArun Ramadoss pirq->reg_status = dev->dev_ops->get_port_addr(p, REG_PORT_INT_STATUS); 2060e1add7ddSArun Ramadoss snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p); 2061ff319a64SArun Ramadoss 2062e1add7ddSArun Ramadoss pirq->irq_num = irq_find_mapping(dev->girq.domain, p); 2063e1add7ddSArun Ramadoss if (pirq->irq_num < 0) 2064e1add7ddSArun Ramadoss return pirq->irq_num; 2065ff319a64SArun Ramadoss 2066e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, pirq); 2067ff319a64SArun Ramadoss } 2068ff319a64SArun Ramadoss 20691958eee8SArun Ramadoss static int ksz_setup(struct dsa_switch *ds) 2070d2822e68SArun Ramadoss { 2071d2822e68SArun Ramadoss struct ksz_device *dev = ds->priv; 2072ff319a64SArun Ramadoss struct dsa_port *dp; 207315f7cfaeSVladimir Oltean struct ksz_port *p; 20749d95329cSArun Ramadoss const u16 *regs; 2075d2822e68SArun Ramadoss int ret; 2076d2822e68SArun Ramadoss 20779d95329cSArun Ramadoss regs = dev->info->regs; 20789d95329cSArun Ramadoss 2079d2822e68SArun Ramadoss dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), 2080d2822e68SArun Ramadoss dev->info->num_vlans, GFP_KERNEL); 2081d2822e68SArun Ramadoss if (!dev->vlan_cache) 2082d2822e68SArun Ramadoss return -ENOMEM; 2083d2822e68SArun Ramadoss 2084d2822e68SArun Ramadoss ret = dev->dev_ops->reset(dev); 2085d2822e68SArun Ramadoss if (ret) { 2086d2822e68SArun Ramadoss dev_err(ds->dev, "failed to reset switch\n"); 2087d2822e68SArun Ramadoss return ret; 2088d2822e68SArun Ramadoss } 2089d2822e68SArun Ramadoss 20901ca6437fSArun Ramadoss /* set broadcast storm protection 10% rate */ 20919d95329cSArun Ramadoss regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL], 20921ca6437fSArun Ramadoss BROADCAST_STORM_RATE, 20931ca6437fSArun Ramadoss (BROADCAST_STORM_VALUE * 20941ca6437fSArun Ramadoss BROADCAST_STORM_PROT_RATE) / 100); 20951ca6437fSArun Ramadoss 2096d2822e68SArun Ramadoss dev->dev_ops->config_cpu_port(ds); 2097d2822e68SArun Ramadoss 2098d2822e68SArun Ramadoss dev->dev_ops->enable_stp_addr(dev); 2099d2822e68SArun Ramadoss 2100e30f33a5SArun Ramadoss ds->num_tx_queues = dev->info->num_tx_queues; 2101e30f33a5SArun Ramadoss 21029d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], 21030abab9f3SArun Ramadoss MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); 21040abab9f3SArun Ramadoss 2105d2822e68SArun Ramadoss ksz_init_mib_timer(dev); 2106d2822e68SArun Ramadoss 2107d2822e68SArun Ramadoss ds->configure_vlan_while_not_filtering = false; 2108d2822e68SArun Ramadoss 2109d2822e68SArun Ramadoss if (dev->dev_ops->setup) { 2110d2822e68SArun Ramadoss ret = dev->dev_ops->setup(ds); 2111d2822e68SArun Ramadoss if (ret) 2112d2822e68SArun Ramadoss return ret; 2113d2822e68SArun Ramadoss } 2114d2822e68SArun Ramadoss 211515f7cfaeSVladimir Oltean /* Start with learning disabled on standalone user ports, and enabled 211615f7cfaeSVladimir Oltean * on the CPU port. In lack of other finer mechanisms, learning on the 211715f7cfaeSVladimir Oltean * CPU port will avoid flooding bridge local addresses on the network 211815f7cfaeSVladimir Oltean * in some cases. 211915f7cfaeSVladimir Oltean */ 212015f7cfaeSVladimir Oltean p = &dev->ports[dev->cpu_port]; 212115f7cfaeSVladimir Oltean p->learning = true; 212215f7cfaeSVladimir Oltean 2123ff319a64SArun Ramadoss if (dev->irq > 0) { 2124ff319a64SArun Ramadoss ret = ksz_girq_setup(dev); 2125ff319a64SArun Ramadoss if (ret) 2126ff319a64SArun Ramadoss return ret; 2127ff319a64SArun Ramadoss 2128ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) { 2129ff319a64SArun Ramadoss ret = ksz_pirq_setup(dev, dp->index); 2130ff319a64SArun Ramadoss if (ret) 2131ff319a64SArun Ramadoss goto out_girq; 2132cc13ab18SArun Ramadoss 2133cc13ab18SArun Ramadoss ret = ksz_ptp_irq_setup(ds, dp->index); 2134cc13ab18SArun Ramadoss if (ret) 2135cc13ab18SArun Ramadoss goto out_pirq; 2136ff319a64SArun Ramadoss } 2137ff319a64SArun Ramadoss } 2138ff319a64SArun Ramadoss 2139eac1ea20SChristian Eggers ret = ksz_ptp_clock_register(ds); 2140eac1ea20SChristian Eggers if (ret) { 2141eac1ea20SChristian Eggers dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret); 2142cc13ab18SArun Ramadoss goto out_ptpirq; 2143eac1ea20SChristian Eggers } 2144eac1ea20SChristian Eggers 2145ff319a64SArun Ramadoss ret = ksz_mdio_register(dev); 2146ff319a64SArun Ramadoss if (ret < 0) { 2147ff319a64SArun Ramadoss dev_err(dev->dev, "failed to register the mdio"); 2148eac1ea20SChristian Eggers goto out_ptp_clock_unregister; 2149ff319a64SArun Ramadoss } 2150ff319a64SArun Ramadoss 2151ad08ac18SArun Ramadoss /* start switch */ 21529d95329cSArun Ramadoss regmap_update_bits(dev->regmap[0], regs[S_START_CTRL], 2153ad08ac18SArun Ramadoss SW_START, SW_START); 2154ad08ac18SArun Ramadoss 2155d2822e68SArun Ramadoss return 0; 2156ff319a64SArun Ramadoss 2157eac1ea20SChristian Eggers out_ptp_clock_unregister: 2158eac1ea20SChristian Eggers ksz_ptp_clock_unregister(ds); 2159cc13ab18SArun Ramadoss out_ptpirq: 2160cc13ab18SArun Ramadoss if (dev->irq > 0) 2161cc13ab18SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2162cc13ab18SArun Ramadoss ksz_ptp_irq_free(ds, dp->index); 2163ff319a64SArun Ramadoss out_pirq: 2164ff319a64SArun Ramadoss if (dev->irq > 0) 2165ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2166e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2167ff319a64SArun Ramadoss out_girq: 2168ff319a64SArun Ramadoss if (dev->irq > 0) 2169e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2170ff319a64SArun Ramadoss 2171ff319a64SArun Ramadoss return ret; 2172d2822e68SArun Ramadoss } 2173d2822e68SArun Ramadoss 2174c9cd961cSArun Ramadoss static void ksz_teardown(struct dsa_switch *ds) 2175c9cd961cSArun Ramadoss { 2176c9cd961cSArun Ramadoss struct ksz_device *dev = ds->priv; 2177ff319a64SArun Ramadoss struct dsa_port *dp; 2178ff319a64SArun Ramadoss 2179eac1ea20SChristian Eggers ksz_ptp_clock_unregister(ds); 2180eac1ea20SChristian Eggers 2181ff319a64SArun Ramadoss if (dev->irq > 0) { 2182cc13ab18SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) { 2183cc13ab18SArun Ramadoss ksz_ptp_irq_free(ds, dp->index); 2184cc13ab18SArun Ramadoss 2185e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2186cc13ab18SArun Ramadoss } 2187ff319a64SArun Ramadoss 2188e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2189ff319a64SArun Ramadoss } 2190c9cd961cSArun Ramadoss 2191c9cd961cSArun Ramadoss if (dev->dev_ops->teardown) 2192c9cd961cSArun Ramadoss dev->dev_ops->teardown(ds); 2193c9cd961cSArun Ramadoss } 2194c9cd961cSArun Ramadoss 21957c6ff470STristram Ha static void port_r_cnt(struct ksz_device *dev, int port) 21967c6ff470STristram Ha { 21977c6ff470STristram Ha struct ksz_port_mib *mib = &dev->ports[port].mib; 21987c6ff470STristram Ha u64 *dropped; 21997c6ff470STristram Ha 22007c6ff470STristram Ha /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ 2201a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->reg_mib_cnt) { 22027c6ff470STristram Ha dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, 22037c6ff470STristram Ha &mib->counters[mib->cnt_ptr]); 22047c6ff470STristram Ha ++mib->cnt_ptr; 22057c6ff470STristram Ha } 22067c6ff470STristram Ha 22077c6ff470STristram Ha /* last one in storage */ 2208a530e6f2SArun Ramadoss dropped = &mib->counters[dev->info->mib_cnt]; 22097c6ff470STristram Ha 22107c6ff470STristram Ha /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ 2211a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->mib_cnt) { 22127c6ff470STristram Ha dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, 22137c6ff470STristram Ha dropped, &mib->counters[mib->cnt_ptr]); 22147c6ff470STristram Ha ++mib->cnt_ptr; 22157c6ff470STristram Ha } 22167c6ff470STristram Ha mib->cnt_ptr = 0; 22177c6ff470STristram Ha } 22187c6ff470STristram Ha 22197c6ff470STristram Ha static void ksz_mib_read_work(struct work_struct *work) 22207c6ff470STristram Ha { 22217c6ff470STristram Ha struct ksz_device *dev = container_of(work, struct ksz_device, 2222469b390eSGeorge McCollister mib_read.work); 22237c6ff470STristram Ha struct ksz_port_mib *mib; 22247c6ff470STristram Ha struct ksz_port *p; 22257c6ff470STristram Ha int i; 22267c6ff470STristram Ha 2227462d5250SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 22286bb9e376SRobert Hancock if (dsa_is_unused_port(dev->ds, i)) 22296bb9e376SRobert Hancock continue; 22306bb9e376SRobert Hancock 22317c6ff470STristram Ha p = &dev->ports[i]; 22327c6ff470STristram Ha mib = &p->mib; 22337c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 22347c6ff470STristram Ha 22357c6ff470STristram Ha /* Only read MIB counters when the port is told to do. 22367c6ff470STristram Ha * If not, read only dropped counters when link is not up. 22377c6ff470STristram Ha */ 22387c6ff470STristram Ha if (!p->read) { 22397c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(dev->ds, i); 22407c6ff470STristram Ha 22417c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2242a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 22437c6ff470STristram Ha } 22447c6ff470STristram Ha port_r_cnt(dev, i); 22457c6ff470STristram Ha p->read = false; 2246a7f4f13aSOleksij Rempel 2247a7f4f13aSOleksij Rempel if (dev->dev_ops->r_mib_stat64) 2248a7f4f13aSOleksij Rempel dev->dev_ops->r_mib_stat64(dev, i); 2249a7f4f13aSOleksij Rempel 22507c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 22517c6ff470STristram Ha } 22527c6ff470STristram Ha 2253469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, dev->mib_read_interval); 22547c6ff470STristram Ha } 22557c6ff470STristram Ha 22567c6ff470STristram Ha void ksz_init_mib_timer(struct ksz_device *dev) 22577c6ff470STristram Ha { 22587c6ff470STristram Ha int i; 22597c6ff470STristram Ha 2260469b390eSGeorge McCollister INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work); 2261469b390eSGeorge McCollister 2262b094c679SPrasanna Vengateshan for (i = 0; i < dev->info->port_cnt; i++) { 2263b094c679SPrasanna Vengateshan struct ksz_port_mib *mib = &dev->ports[i].mib; 2264b094c679SPrasanna Vengateshan 22657c6ff470STristram Ha dev->dev_ops->port_init_cnt(dev, i); 2266b094c679SPrasanna Vengateshan 2267b094c679SPrasanna Vengateshan mib->cnt_ptr = 0; 2268b094c679SPrasanna Vengateshan memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64)); 2269b094c679SPrasanna Vengateshan } 22707c6ff470STristram Ha } 22717c6ff470STristram Ha 22721958eee8SArun Ramadoss static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) 2273b987e98eSWoojung Huh { 2274b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2275c2e86691STristram Ha u16 val = 0xffff; 22768f420456SOleksij Rempel int ret; 2277b987e98eSWoojung Huh 22788f420456SOleksij Rempel ret = dev->dev_ops->r_phy(dev, addr, reg, &val); 22798f420456SOleksij Rempel if (ret) 22808f420456SOleksij Rempel return ret; 2281b987e98eSWoojung Huh 2282b987e98eSWoojung Huh return val; 2283b987e98eSWoojung Huh } 2284b987e98eSWoojung Huh 22851958eee8SArun Ramadoss static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) 2286b987e98eSWoojung Huh { 2287b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 22888f420456SOleksij Rempel int ret; 2289b987e98eSWoojung Huh 22908f420456SOleksij Rempel ret = dev->dev_ops->w_phy(dev, addr, reg, val); 22918f420456SOleksij Rempel if (ret) 22928f420456SOleksij Rempel return ret; 2293b987e98eSWoojung Huh 2294b987e98eSWoojung Huh return 0; 2295b987e98eSWoojung Huh } 2296b987e98eSWoojung Huh 22971958eee8SArun Ramadoss static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) 22981fe94f54SArun Ramadoss { 22991fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 23001fe94f54SArun Ramadoss 23011fe94f54SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID) { 23021fe94f54SArun Ramadoss /* Silicon Errata Sheet (DS80000830A): 23031fe94f54SArun Ramadoss * Port 1 does not work with LinkMD Cable-Testing. 23041fe94f54SArun Ramadoss * Port 1 does not respond to received PAUSE control frames. 23051fe94f54SArun Ramadoss */ 23061fe94f54SArun Ramadoss if (!port) 23071fe94f54SArun Ramadoss return MICREL_KSZ8_P1_ERRATA; 23081fe94f54SArun Ramadoss } 23091fe94f54SArun Ramadoss 23101fe94f54SArun Ramadoss return 0; 23111fe94f54SArun Ramadoss } 23121fe94f54SArun Ramadoss 23131958eee8SArun Ramadoss static void ksz_mac_link_down(struct dsa_switch *ds, int port, 23141958eee8SArun Ramadoss unsigned int mode, phy_interface_t interface) 2315c30d894bSTristram Ha { 2316c30d894bSTristram Ha struct ksz_device *dev = ds->priv; 2317c30d894bSTristram Ha struct ksz_port *p = &dev->ports[port]; 2318c30d894bSTristram Ha 2319c30d894bSTristram Ha /* Read all MIB counters when the link is going down. */ 2320c30d894bSTristram Ha p->read = true; 23218098bd69SChristian Eggers /* timer started */ 23228098bd69SChristian Eggers if (dev->mib_read_interval) 2323469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, 0); 2324143a102eSCodrin Ciubotariu } 2325143a102eSCodrin Ciubotariu 23261958eee8SArun Ramadoss static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) 2327b987e98eSWoojung Huh { 2328b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2329b987e98eSWoojung Huh 233089f09048SFlorian Fainelli if (sset != ETH_SS_STATS) 233189f09048SFlorian Fainelli return 0; 233289f09048SFlorian Fainelli 2333a530e6f2SArun Ramadoss return dev->info->mib_cnt; 2334b987e98eSWoojung Huh } 2335b987e98eSWoojung Huh 23361958eee8SArun Ramadoss static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, 23371958eee8SArun Ramadoss uint64_t *buf) 23387c6ff470STristram Ha { 23397c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(ds, port); 23407c6ff470STristram Ha struct ksz_device *dev = ds->priv; 23417c6ff470STristram Ha struct ksz_port_mib *mib; 23427c6ff470STristram Ha 23437c6ff470STristram Ha mib = &dev->ports[port].mib; 23447c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 23457c6ff470STristram Ha 23467c6ff470STristram Ha /* Only read dropped counters if no link. */ 23477c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2348a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 23497c6ff470STristram Ha port_r_cnt(dev, port); 2350a530e6f2SArun Ramadoss memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64)); 23517c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 23527c6ff470STristram Ha } 23537c6ff470STristram Ha 23541958eee8SArun Ramadoss static int ksz_port_bridge_join(struct dsa_switch *ds, int port, 2355b079922bSVladimir Oltean struct dsa_bridge bridge, 235606b9cce4SVladimir Oltean bool *tx_fwd_offload, 235706b9cce4SVladimir Oltean struct netlink_ext_ack *extack) 2358b987e98eSWoojung Huh { 2359c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2360c2e86691STristram Ha * appropriate state so there is no need to do anything. 2361c2e86691STristram Ha */ 2362b987e98eSWoojung Huh 2363b987e98eSWoojung Huh return 0; 2364b987e98eSWoojung Huh } 2365b987e98eSWoojung Huh 23661958eee8SArun Ramadoss static void ksz_port_bridge_leave(struct dsa_switch *ds, int port, 2367d3eed0e5SVladimir Oltean struct dsa_bridge bridge) 2368c2e86691STristram Ha { 2369c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2370c2e86691STristram Ha * forwarding state so there is no need to do anything. 2371c2e86691STristram Ha */ 2372c2e86691STristram Ha } 2373c2e86691STristram Ha 23741958eee8SArun Ramadoss static void ksz_port_fast_age(struct dsa_switch *ds, int port) 2375c2e86691STristram Ha { 2376c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2377c2e86691STristram Ha 2378c2e86691STristram Ha dev->dev_ops->flush_dyn_mac_table(dev, port); 2379c2e86691STristram Ha } 2380c2e86691STristram Ha 23812c119d99SArun Ramadoss static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) 23822c119d99SArun Ramadoss { 23832c119d99SArun Ramadoss struct ksz_device *dev = ds->priv; 23842c119d99SArun Ramadoss 23852c119d99SArun Ramadoss if (!dev->dev_ops->set_ageing_time) 23862c119d99SArun Ramadoss return -EOPNOTSUPP; 23872c119d99SArun Ramadoss 23882c119d99SArun Ramadoss return dev->dev_ops->set_ageing_time(dev, msecs); 23892c119d99SArun Ramadoss } 23902c119d99SArun Ramadoss 23911958eee8SArun Ramadoss static int ksz_port_fdb_add(struct dsa_switch *ds, int port, 23921958eee8SArun Ramadoss const unsigned char *addr, u16 vid, 23931958eee8SArun Ramadoss struct dsa_db db) 2394e587be75SArun Ramadoss { 2395e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2396e587be75SArun Ramadoss 2397e587be75SArun Ramadoss if (!dev->dev_ops->fdb_add) 2398e587be75SArun Ramadoss return -EOPNOTSUPP; 2399e587be75SArun Ramadoss 2400e587be75SArun Ramadoss return dev->dev_ops->fdb_add(dev, port, addr, vid, db); 2401e587be75SArun Ramadoss } 2402e587be75SArun Ramadoss 24031958eee8SArun Ramadoss static int ksz_port_fdb_del(struct dsa_switch *ds, int port, 24041958eee8SArun Ramadoss const unsigned char *addr, 24051958eee8SArun Ramadoss u16 vid, struct dsa_db db) 2406e587be75SArun Ramadoss { 2407e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2408e587be75SArun Ramadoss 2409e587be75SArun Ramadoss if (!dev->dev_ops->fdb_del) 2410e587be75SArun Ramadoss return -EOPNOTSUPP; 2411e587be75SArun Ramadoss 2412e587be75SArun Ramadoss return dev->dev_ops->fdb_del(dev, port, addr, vid, db); 2413e587be75SArun Ramadoss } 2414e587be75SArun Ramadoss 24151958eee8SArun Ramadoss static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, 24161958eee8SArun Ramadoss dsa_fdb_dump_cb_t *cb, void *data) 2417b987e98eSWoojung Huh { 2418b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2419b987e98eSWoojung Huh 2420e587be75SArun Ramadoss if (!dev->dev_ops->fdb_dump) 2421e587be75SArun Ramadoss return -EOPNOTSUPP; 2422b987e98eSWoojung Huh 2423e587be75SArun Ramadoss return dev->dev_ops->fdb_dump(dev, port, cb, data); 2424b987e98eSWoojung Huh } 2425b987e98eSWoojung Huh 24261958eee8SArun Ramadoss static int ksz_port_mdb_add(struct dsa_switch *ds, int port, 2427c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2428c2693363SVladimir Oltean struct dsa_db db) 2429b987e98eSWoojung Huh { 2430b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2431b987e98eSWoojung Huh 2432980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_add) 2433980c7d17SArun Ramadoss return -EOPNOTSUPP; 2434b987e98eSWoojung Huh 2435980c7d17SArun Ramadoss return dev->dev_ops->mdb_add(dev, port, mdb, db); 2436c2e86691STristram Ha } 2437c2e86691STristram Ha 24381958eee8SArun Ramadoss static int ksz_port_mdb_del(struct dsa_switch *ds, int port, 2439c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2440c2693363SVladimir Oltean struct dsa_db db) 2441c2e86691STristram Ha { 2442c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2443b987e98eSWoojung Huh 2444980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_del) 2445980c7d17SArun Ramadoss return -EOPNOTSUPP; 2446b987e98eSWoojung Huh 2447980c7d17SArun Ramadoss return dev->dev_ops->mdb_del(dev, port, mdb, db); 2448b987e98eSWoojung Huh } 2449b987e98eSWoojung Huh 24501958eee8SArun Ramadoss static int ksz_enable_port(struct dsa_switch *ds, int port, 24511958eee8SArun Ramadoss struct phy_device *phy) 2452b987e98eSWoojung Huh { 2453b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2454b987e98eSWoojung Huh 245574be4babSVivien Didelot if (!dsa_is_user_port(ds, port)) 245674be4babSVivien Didelot return 0; 245774be4babSVivien Didelot 2458c2e86691STristram Ha /* setup slave port */ 2459c2e86691STristram Ha dev->dev_ops->port_setup(dev, port, false); 2460b987e98eSWoojung Huh 2461c2e86691STristram Ha /* port_stp_state_set() will be called after to enable the port so 2462c2e86691STristram Ha * there is no need to do anything. 2463c2e86691STristram Ha */ 2464b987e98eSWoojung Huh 2465b987e98eSWoojung Huh return 0; 2466b987e98eSWoojung Huh } 2467b987e98eSWoojung Huh 2468e593df51SArun Ramadoss void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) 2469de6dd626SArun Ramadoss { 2470de6dd626SArun Ramadoss struct ksz_device *dev = ds->priv; 2471de6dd626SArun Ramadoss struct ksz_port *p; 24726877102fSArun Ramadoss const u16 *regs; 2473de6dd626SArun Ramadoss u8 data; 2474e593df51SArun Ramadoss 24756877102fSArun Ramadoss regs = dev->info->regs; 2476de6dd626SArun Ramadoss 24776877102fSArun Ramadoss ksz_pread8(dev, port, regs[P_STP_CTRL], &data); 2478de6dd626SArun Ramadoss data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2479de6dd626SArun Ramadoss 248015f7cfaeSVladimir Oltean p = &dev->ports[port]; 248115f7cfaeSVladimir Oltean 2482de6dd626SArun Ramadoss switch (state) { 2483de6dd626SArun Ramadoss case BR_STATE_DISABLED: 2484de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2485de6dd626SArun Ramadoss break; 2486de6dd626SArun Ramadoss case BR_STATE_LISTENING: 2487de6dd626SArun Ramadoss data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2488de6dd626SArun Ramadoss break; 2489de6dd626SArun Ramadoss case BR_STATE_LEARNING: 2490de6dd626SArun Ramadoss data |= PORT_RX_ENABLE; 249115f7cfaeSVladimir Oltean if (!p->learning) 249215f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2493de6dd626SArun Ramadoss break; 2494de6dd626SArun Ramadoss case BR_STATE_FORWARDING: 2495de6dd626SArun Ramadoss data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); 249615f7cfaeSVladimir Oltean if (!p->learning) 249715f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2498de6dd626SArun Ramadoss break; 2499de6dd626SArun Ramadoss case BR_STATE_BLOCKING: 2500de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2501de6dd626SArun Ramadoss break; 2502de6dd626SArun Ramadoss default: 2503de6dd626SArun Ramadoss dev_err(ds->dev, "invalid STP state: %d\n", state); 2504de6dd626SArun Ramadoss return; 2505de6dd626SArun Ramadoss } 2506de6dd626SArun Ramadoss 25076877102fSArun Ramadoss ksz_pwrite8(dev, port, regs[P_STP_CTRL], data); 2508de6dd626SArun Ramadoss 2509de6dd626SArun Ramadoss p->stp_state = state; 2510de6dd626SArun Ramadoss 2511de6dd626SArun Ramadoss ksz_update_port_member(dev, port); 2512de6dd626SArun Ramadoss } 2513de6dd626SArun Ramadoss 251415f7cfaeSVladimir Oltean static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, 251515f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 251615f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 251715f7cfaeSVladimir Oltean { 251815f7cfaeSVladimir Oltean if (flags.mask & ~BR_LEARNING) 251915f7cfaeSVladimir Oltean return -EINVAL; 252015f7cfaeSVladimir Oltean 252115f7cfaeSVladimir Oltean return 0; 252215f7cfaeSVladimir Oltean } 252315f7cfaeSVladimir Oltean 252415f7cfaeSVladimir Oltean static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, 252515f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 252615f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 252715f7cfaeSVladimir Oltean { 252815f7cfaeSVladimir Oltean struct ksz_device *dev = ds->priv; 252915f7cfaeSVladimir Oltean struct ksz_port *p = &dev->ports[port]; 253015f7cfaeSVladimir Oltean 253115f7cfaeSVladimir Oltean if (flags.mask & BR_LEARNING) { 253215f7cfaeSVladimir Oltean p->learning = !!(flags.val & BR_LEARNING); 253315f7cfaeSVladimir Oltean 253415f7cfaeSVladimir Oltean /* Make the change take effect immediately */ 253515f7cfaeSVladimir Oltean ksz_port_stp_state_set(ds, port, p->stp_state); 253615f7cfaeSVladimir Oltean } 253715f7cfaeSVladimir Oltean 253815f7cfaeSVladimir Oltean return 0; 253915f7cfaeSVladimir Oltean } 254015f7cfaeSVladimir Oltean 25411958eee8SArun Ramadoss static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, 25421958eee8SArun Ramadoss int port, 25431958eee8SArun Ramadoss enum dsa_tag_protocol mp) 2544534a0431SArun Ramadoss { 2545534a0431SArun Ramadoss struct ksz_device *dev = ds->priv; 2546534a0431SArun Ramadoss enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; 2547534a0431SArun Ramadoss 2548534a0431SArun Ramadoss if (dev->chip_id == KSZ8795_CHIP_ID || 2549534a0431SArun Ramadoss dev->chip_id == KSZ8794_CHIP_ID || 2550534a0431SArun Ramadoss dev->chip_id == KSZ8765_CHIP_ID) 2551534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ8795; 2552534a0431SArun Ramadoss 2553534a0431SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID || 2554b4490809SOleksij Rempel dev->chip_id == KSZ8563_CHIP_ID || 2555ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9893_CHIP_ID || 2556ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9563_CHIP_ID) 2557534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9893; 2558534a0431SArun Ramadoss 2559534a0431SArun Ramadoss if (dev->chip_id == KSZ9477_CHIP_ID || 25602eb3ff3cSRomain Naour dev->chip_id == KSZ9896_CHIP_ID || 2561534a0431SArun Ramadoss dev->chip_id == KSZ9897_CHIP_ID || 2562534a0431SArun Ramadoss dev->chip_id == KSZ9567_CHIP_ID) 2563534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9477; 2564534a0431SArun Ramadoss 256599b16df0SArun Ramadoss if (is_lan937x(dev)) 256699b16df0SArun Ramadoss proto = DSA_TAG_PROTO_LAN937X_VALUE; 256799b16df0SArun Ramadoss 2568534a0431SArun Ramadoss return proto; 2569534a0431SArun Ramadoss } 2570534a0431SArun Ramadoss 2571ab32f56aSChristian Eggers static int ksz_connect_tag_protocol(struct dsa_switch *ds, 2572ab32f56aSChristian Eggers enum dsa_tag_protocol proto) 2573ab32f56aSChristian Eggers { 2574ab32f56aSChristian Eggers struct ksz_tagger_data *tagger_data; 2575ab32f56aSChristian Eggers 2576ab32f56aSChristian Eggers tagger_data = ksz_tagger_data(ds); 2577ab32f56aSChristian Eggers tagger_data->xmit_work_fn = ksz_port_deferred_xmit; 2578ab32f56aSChristian Eggers 2579ab32f56aSChristian Eggers return 0; 2580ab32f56aSChristian Eggers } 2581ab32f56aSChristian Eggers 25821958eee8SArun Ramadoss static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, 2583f0d997e3SArun Ramadoss bool flag, struct netlink_ext_ack *extack) 2584f0d997e3SArun Ramadoss { 2585f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2586f0d997e3SArun Ramadoss 2587f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_filtering) 2588f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2589f0d997e3SArun Ramadoss 2590f0d997e3SArun Ramadoss return dev->dev_ops->vlan_filtering(dev, port, flag, extack); 2591f0d997e3SArun Ramadoss } 2592f0d997e3SArun Ramadoss 25931958eee8SArun Ramadoss static int ksz_port_vlan_add(struct dsa_switch *ds, int port, 2594f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan, 2595f0d997e3SArun Ramadoss struct netlink_ext_ack *extack) 2596f0d997e3SArun Ramadoss { 2597f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2598f0d997e3SArun Ramadoss 2599f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_add) 2600f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2601f0d997e3SArun Ramadoss 2602f0d997e3SArun Ramadoss return dev->dev_ops->vlan_add(dev, port, vlan, extack); 2603f0d997e3SArun Ramadoss } 2604f0d997e3SArun Ramadoss 26051958eee8SArun Ramadoss static int ksz_port_vlan_del(struct dsa_switch *ds, int port, 2606f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan) 2607f0d997e3SArun Ramadoss { 2608f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2609f0d997e3SArun Ramadoss 2610f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_del) 2611f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2612f0d997e3SArun Ramadoss 2613f0d997e3SArun Ramadoss return dev->dev_ops->vlan_del(dev, port, vlan); 2614f0d997e3SArun Ramadoss } 2615f0d997e3SArun Ramadoss 26161958eee8SArun Ramadoss static int ksz_port_mirror_add(struct dsa_switch *ds, int port, 261700a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror, 261800a298bbSArun Ramadoss bool ingress, struct netlink_ext_ack *extack) 261900a298bbSArun Ramadoss { 262000a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 262100a298bbSArun Ramadoss 262200a298bbSArun Ramadoss if (!dev->dev_ops->mirror_add) 262300a298bbSArun Ramadoss return -EOPNOTSUPP; 262400a298bbSArun Ramadoss 262500a298bbSArun Ramadoss return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack); 262600a298bbSArun Ramadoss } 262700a298bbSArun Ramadoss 26281958eee8SArun Ramadoss static void ksz_port_mirror_del(struct dsa_switch *ds, int port, 262900a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror) 263000a298bbSArun Ramadoss { 263100a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 263200a298bbSArun Ramadoss 263300a298bbSArun Ramadoss if (dev->dev_ops->mirror_del) 263400a298bbSArun Ramadoss dev->dev_ops->mirror_del(dev, port, mirror); 263500a298bbSArun Ramadoss } 263600a298bbSArun Ramadoss 26371958eee8SArun Ramadoss static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) 26381fe94f54SArun Ramadoss { 26391fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 26401fe94f54SArun Ramadoss 26411fe94f54SArun Ramadoss if (!dev->dev_ops->change_mtu) 26421fe94f54SArun Ramadoss return -EOPNOTSUPP; 26431fe94f54SArun Ramadoss 26441fe94f54SArun Ramadoss return dev->dev_ops->change_mtu(dev, port, mtu); 26451fe94f54SArun Ramadoss } 26461fe94f54SArun Ramadoss 26471958eee8SArun Ramadoss static int ksz_max_mtu(struct dsa_switch *ds, int port) 26481fe94f54SArun Ramadoss { 26491fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 26501fe94f54SArun Ramadoss 2651838c19f8SOleksij Rempel switch (dev->chip_id) { 265229d1e85fSOleksij Rempel case KSZ8795_CHIP_ID: 265329d1e85fSOleksij Rempel case KSZ8794_CHIP_ID: 265429d1e85fSOleksij Rempel case KSZ8765_CHIP_ID: 265529d1e85fSOleksij Rempel return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 265629d1e85fSOleksij Rempel case KSZ8830_CHIP_ID: 265729d1e85fSOleksij Rempel return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 2658838c19f8SOleksij Rempel case KSZ8563_CHIP_ID: 2659838c19f8SOleksij Rempel case KSZ9477_CHIP_ID: 2660838c19f8SOleksij Rempel case KSZ9563_CHIP_ID: 2661838c19f8SOleksij Rempel case KSZ9567_CHIP_ID: 2662838c19f8SOleksij Rempel case KSZ9893_CHIP_ID: 2663838c19f8SOleksij Rempel case KSZ9896_CHIP_ID: 2664838c19f8SOleksij Rempel case KSZ9897_CHIP_ID: 2665838c19f8SOleksij Rempel case LAN9370_CHIP_ID: 2666838c19f8SOleksij Rempel case LAN9371_CHIP_ID: 2667838c19f8SOleksij Rempel case LAN9372_CHIP_ID: 2668838c19f8SOleksij Rempel case LAN9373_CHIP_ID: 2669838c19f8SOleksij Rempel case LAN9374_CHIP_ID: 2670838c19f8SOleksij Rempel return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 2671838c19f8SOleksij Rempel } 26721fe94f54SArun Ramadoss 2673838c19f8SOleksij Rempel return -EOPNOTSUPP; 26741fe94f54SArun Ramadoss } 26751fe94f54SArun Ramadoss 2676f3d890f5SArun Ramadoss static void ksz_set_xmii(struct ksz_device *dev, int port, 2677f3d890f5SArun Ramadoss phy_interface_t interface) 2678dc1c596eSArun Ramadoss { 2679dc1c596eSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 2680b19ac41fSArun Ramadoss struct ksz_port *p = &dev->ports[port]; 2681dc1c596eSArun Ramadoss const u16 *regs = dev->info->regs; 2682dc1c596eSArun Ramadoss u8 data8; 2683dc1c596eSArun Ramadoss 2684dc1c596eSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 2685dc1c596eSArun Ramadoss 2686b19ac41fSArun Ramadoss data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE | 2687b19ac41fSArun Ramadoss P_RGMII_ID_EG_ENABLE); 2688dc1c596eSArun Ramadoss 2689dc1c596eSArun Ramadoss switch (interface) { 2690dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_MII: 2691dc1c596eSArun Ramadoss data8 |= bitval[P_MII_SEL]; 2692dc1c596eSArun Ramadoss break; 2693dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RMII: 2694dc1c596eSArun Ramadoss data8 |= bitval[P_RMII_SEL]; 2695dc1c596eSArun Ramadoss break; 2696dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_GMII: 2697dc1c596eSArun Ramadoss data8 |= bitval[P_GMII_SEL]; 2698dc1c596eSArun Ramadoss break; 2699dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII: 2700dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_ID: 2701dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_TXID: 2702dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_RXID: 2703dc1c596eSArun Ramadoss data8 |= bitval[P_RGMII_SEL]; 27040ab7f6bfSArun Ramadoss /* On KSZ9893, disable RGMII in-band status support */ 270532cbac21SOleksij Rempel if (dev->chip_id == KSZ9893_CHIP_ID || 2706ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ8563_CHIP_ID || 2707ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9563_CHIP_ID) 27080ab7f6bfSArun Ramadoss data8 &= ~P_MII_MAC_MODE; 2709dc1c596eSArun Ramadoss break; 2710dc1c596eSArun Ramadoss default: 2711dc1c596eSArun Ramadoss dev_err(dev->dev, "Unsupported interface '%s' for port %d\n", 2712dc1c596eSArun Ramadoss phy_modes(interface), port); 2713dc1c596eSArun Ramadoss return; 2714dc1c596eSArun Ramadoss } 2715dc1c596eSArun Ramadoss 2716b19ac41fSArun Ramadoss if (p->rgmii_tx_val) 2717b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_EG_ENABLE; 2718b19ac41fSArun Ramadoss 2719b19ac41fSArun Ramadoss if (p->rgmii_rx_val) 2720b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_IG_ENABLE; 2721b19ac41fSArun Ramadoss 2722dc1c596eSArun Ramadoss /* Write the updated value */ 2723dc1c596eSArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 2724dc1c596eSArun Ramadoss } 2725dc1c596eSArun Ramadoss 27260ab7f6bfSArun Ramadoss phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) 27270ab7f6bfSArun Ramadoss { 27280ab7f6bfSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 27290ab7f6bfSArun Ramadoss const u16 *regs = dev->info->regs; 27300ab7f6bfSArun Ramadoss phy_interface_t interface; 27310ab7f6bfSArun Ramadoss u8 data8; 27320ab7f6bfSArun Ramadoss u8 val; 27330ab7f6bfSArun Ramadoss 27340ab7f6bfSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 27350ab7f6bfSArun Ramadoss 27360ab7f6bfSArun Ramadoss val = FIELD_GET(P_MII_SEL_M, data8); 27370ab7f6bfSArun Ramadoss 27380ab7f6bfSArun Ramadoss if (val == bitval[P_MII_SEL]) { 27390ab7f6bfSArun Ramadoss if (gbit) 27400ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_GMII; 27410ab7f6bfSArun Ramadoss else 27420ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_MII; 27430ab7f6bfSArun Ramadoss } else if (val == bitval[P_RMII_SEL]) { 27440ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 27450ab7f6bfSArun Ramadoss } else { 27460ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 27470ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 27480ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_TXID; 27490ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_IG_ENABLE) { 27500ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_RXID; 27510ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 27520ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_ID; 27530ab7f6bfSArun Ramadoss } 27540ab7f6bfSArun Ramadoss } 27550ab7f6bfSArun Ramadoss 27560ab7f6bfSArun Ramadoss return interface; 27570ab7f6bfSArun Ramadoss } 27580ab7f6bfSArun Ramadoss 2759a0cb1aa4SArun Ramadoss static void ksz_phylink_mac_config(struct dsa_switch *ds, int port, 2760a0cb1aa4SArun Ramadoss unsigned int mode, 2761a0cb1aa4SArun Ramadoss const struct phylink_link_state *state) 2762a0cb1aa4SArun Ramadoss { 2763a0cb1aa4SArun Ramadoss struct ksz_device *dev = ds->priv; 2764a0cb1aa4SArun Ramadoss 2765f3d890f5SArun Ramadoss if (ksz_is_ksz88x3(dev)) 2766f3d890f5SArun Ramadoss return; 2767f3d890f5SArun Ramadoss 2768f3d890f5SArun Ramadoss /* Internal PHYs */ 2769f3d890f5SArun Ramadoss if (dev->info->internal_phy[port]) 2770f3d890f5SArun Ramadoss return; 2771f3d890f5SArun Ramadoss 2772f3d890f5SArun Ramadoss if (phylink_autoneg_inband(mode)) { 2773f3d890f5SArun Ramadoss dev_err(dev->dev, "In-band AN not supported!\n"); 2774f3d890f5SArun Ramadoss return; 2775f3d890f5SArun Ramadoss } 2776f3d890f5SArun Ramadoss 2777f3d890f5SArun Ramadoss ksz_set_xmii(dev, port, state->interface); 2778f3d890f5SArun Ramadoss 2779a0cb1aa4SArun Ramadoss if (dev->dev_ops->phylink_mac_config) 2780a0cb1aa4SArun Ramadoss dev->dev_ops->phylink_mac_config(dev, port, mode, state); 2781b19ac41fSArun Ramadoss 2782b19ac41fSArun Ramadoss if (dev->dev_ops->setup_rgmii_delay) 2783b19ac41fSArun Ramadoss dev->dev_ops->setup_rgmii_delay(dev, port); 2784a0cb1aa4SArun Ramadoss } 2785a0cb1aa4SArun Ramadoss 278646f80fa8SArun Ramadoss bool ksz_get_gbit(struct ksz_device *dev, int port) 278746f80fa8SArun Ramadoss { 278846f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 278946f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 279046f80fa8SArun Ramadoss bool gbit = false; 279146f80fa8SArun Ramadoss u8 data8; 279246f80fa8SArun Ramadoss bool val; 279346f80fa8SArun Ramadoss 279446f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 279546f80fa8SArun Ramadoss 279646f80fa8SArun Ramadoss val = FIELD_GET(P_GMII_1GBIT_M, data8); 279746f80fa8SArun Ramadoss 279846f80fa8SArun Ramadoss if (val == bitval[P_GMII_1GBIT]) 279946f80fa8SArun Ramadoss gbit = true; 280046f80fa8SArun Ramadoss 280146f80fa8SArun Ramadoss return gbit; 280246f80fa8SArun Ramadoss } 280346f80fa8SArun Ramadoss 28040ab7f6bfSArun Ramadoss static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit) 280546f80fa8SArun Ramadoss { 280646f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 280746f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 280846f80fa8SArun Ramadoss u8 data8; 280946f80fa8SArun Ramadoss 281046f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 281146f80fa8SArun Ramadoss 281246f80fa8SArun Ramadoss data8 &= ~P_GMII_1GBIT_M; 281346f80fa8SArun Ramadoss 281446f80fa8SArun Ramadoss if (gbit) 281546f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); 281646f80fa8SArun Ramadoss else 281746f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); 281846f80fa8SArun Ramadoss 281946f80fa8SArun Ramadoss /* Write the updated value */ 282046f80fa8SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 282146f80fa8SArun Ramadoss } 282246f80fa8SArun Ramadoss 2823aa5b8b73SArun Ramadoss static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed) 2824aa5b8b73SArun Ramadoss { 2825aa5b8b73SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 2826aa5b8b73SArun Ramadoss const u16 *regs = dev->info->regs; 2827aa5b8b73SArun Ramadoss u8 data8; 2828aa5b8b73SArun Ramadoss 2829aa5b8b73SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); 2830aa5b8b73SArun Ramadoss 2831aa5b8b73SArun Ramadoss data8 &= ~P_MII_100MBIT_M; 2832aa5b8b73SArun Ramadoss 2833aa5b8b73SArun Ramadoss if (speed == SPEED_100) 2834aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); 2835aa5b8b73SArun Ramadoss else 2836aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); 2837aa5b8b73SArun Ramadoss 2838aa5b8b73SArun Ramadoss /* Write the updated value */ 2839aa5b8b73SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); 2840aa5b8b73SArun Ramadoss } 2841aa5b8b73SArun Ramadoss 2842da8cd085SArun Ramadoss static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed) 2843aa5b8b73SArun Ramadoss { 2844aa5b8b73SArun Ramadoss if (speed == SPEED_1000) 2845aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, true); 2846aa5b8b73SArun Ramadoss else 2847aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, false); 2848aa5b8b73SArun Ramadoss 2849aa5b8b73SArun Ramadoss if (speed == SPEED_100 || speed == SPEED_10) 2850aa5b8b73SArun Ramadoss ksz_set_100_10mbit(dev, port, speed); 2851aa5b8b73SArun Ramadoss } 2852aa5b8b73SArun Ramadoss 2853da8cd085SArun Ramadoss static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex, 28548560664fSArun Ramadoss bool tx_pause, bool rx_pause) 28558560664fSArun Ramadoss { 28568560664fSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 28578560664fSArun Ramadoss const u32 *masks = dev->info->masks; 28588560664fSArun Ramadoss const u16 *regs = dev->info->regs; 28598560664fSArun Ramadoss u8 mask; 28608560664fSArun Ramadoss u8 val; 28618560664fSArun Ramadoss 28628560664fSArun Ramadoss mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] | 28638560664fSArun Ramadoss masks[P_MII_RX_FLOW_CTRL]; 28648560664fSArun Ramadoss 28658560664fSArun Ramadoss if (duplex == DUPLEX_FULL) 28668560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]); 28678560664fSArun Ramadoss else 28688560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]); 28698560664fSArun Ramadoss 28708560664fSArun Ramadoss if (tx_pause) 28718560664fSArun Ramadoss val |= masks[P_MII_TX_FLOW_CTRL]; 28728560664fSArun Ramadoss 28738560664fSArun Ramadoss if (rx_pause) 28748560664fSArun Ramadoss val |= masks[P_MII_RX_FLOW_CTRL]; 28758560664fSArun Ramadoss 28768560664fSArun Ramadoss ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val); 28778560664fSArun Ramadoss } 28788560664fSArun Ramadoss 28793015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 2880f597d3adSArun Ramadoss unsigned int mode, 2881f597d3adSArun Ramadoss phy_interface_t interface, 2882f597d3adSArun Ramadoss struct phy_device *phydev, int speed, 28833015c503SOleksij Rempel int duplex, bool tx_pause, 28843015c503SOleksij Rempel bool rx_pause) 2885f597d3adSArun Ramadoss { 2886da8cd085SArun Ramadoss struct ksz_port *p; 2887da8cd085SArun Ramadoss 2888da8cd085SArun Ramadoss p = &dev->ports[port]; 2889da8cd085SArun Ramadoss 2890da8cd085SArun Ramadoss /* Internal PHYs */ 2891da8cd085SArun Ramadoss if (dev->info->internal_phy[port]) 2892da8cd085SArun Ramadoss return; 2893da8cd085SArun Ramadoss 2894da8cd085SArun Ramadoss p->phydev.speed = speed; 2895da8cd085SArun Ramadoss 2896da8cd085SArun Ramadoss ksz_port_set_xmii_speed(dev, port, speed); 2897da8cd085SArun Ramadoss 2898da8cd085SArun Ramadoss ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause); 28993015c503SOleksij Rempel } 29003015c503SOleksij Rempel 29013015c503SOleksij Rempel static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port, 29023015c503SOleksij Rempel unsigned int mode, 29033015c503SOleksij Rempel phy_interface_t interface, 29043015c503SOleksij Rempel struct phy_device *phydev, int speed, 29053015c503SOleksij Rempel int duplex, bool tx_pause, bool rx_pause) 29063015c503SOleksij Rempel { 29073015c503SOleksij Rempel struct ksz_device *dev = ds->priv; 2908f597d3adSArun Ramadoss 2909f597d3adSArun Ramadoss if (dev->dev_ops->phylink_mac_link_up) 2910f597d3adSArun Ramadoss dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface, 2911f597d3adSArun Ramadoss phydev, speed, duplex, 2912f597d3adSArun Ramadoss tx_pause, rx_pause); 2913f597d3adSArun Ramadoss } 2914f597d3adSArun Ramadoss 291591a98917SArun Ramadoss static int ksz_switch_detect(struct ksz_device *dev) 291691a98917SArun Ramadoss { 2917b4490809SOleksij Rempel u8 id1, id2, id4; 291891a98917SArun Ramadoss u16 id16; 291991a98917SArun Ramadoss u32 id32; 292091a98917SArun Ramadoss int ret; 292191a98917SArun Ramadoss 292291a98917SArun Ramadoss /* read chip id */ 292391a98917SArun Ramadoss ret = ksz_read16(dev, REG_CHIP_ID0, &id16); 292491a98917SArun Ramadoss if (ret) 292591a98917SArun Ramadoss return ret; 292691a98917SArun Ramadoss 292791a98917SArun Ramadoss id1 = FIELD_GET(SW_FAMILY_ID_M, id16); 292891a98917SArun Ramadoss id2 = FIELD_GET(SW_CHIP_ID_M, id16); 292991a98917SArun Ramadoss 293091a98917SArun Ramadoss switch (id1) { 293191a98917SArun Ramadoss case KSZ87_FAMILY_ID: 293291a98917SArun Ramadoss if (id2 == KSZ87_CHIP_ID_95) { 293391a98917SArun Ramadoss u8 val; 293491a98917SArun Ramadoss 293591a98917SArun Ramadoss dev->chip_id = KSZ8795_CHIP_ID; 293691a98917SArun Ramadoss 293791a98917SArun Ramadoss ksz_read8(dev, KSZ8_PORT_STATUS_0, &val); 293891a98917SArun Ramadoss if (val & KSZ8_PORT_FIBER_MODE) 293991a98917SArun Ramadoss dev->chip_id = KSZ8765_CHIP_ID; 294091a98917SArun Ramadoss } else if (id2 == KSZ87_CHIP_ID_94) { 294191a98917SArun Ramadoss dev->chip_id = KSZ8794_CHIP_ID; 294291a98917SArun Ramadoss } else { 294391a98917SArun Ramadoss return -ENODEV; 294491a98917SArun Ramadoss } 294591a98917SArun Ramadoss break; 294691a98917SArun Ramadoss case KSZ88_FAMILY_ID: 294791a98917SArun Ramadoss if (id2 == KSZ88_CHIP_ID_63) 294891a98917SArun Ramadoss dev->chip_id = KSZ8830_CHIP_ID; 294991a98917SArun Ramadoss else 295091a98917SArun Ramadoss return -ENODEV; 295191a98917SArun Ramadoss break; 295291a98917SArun Ramadoss default: 295391a98917SArun Ramadoss ret = ksz_read32(dev, REG_CHIP_ID0, &id32); 295491a98917SArun Ramadoss if (ret) 295591a98917SArun Ramadoss return ret; 295691a98917SArun Ramadoss 295791a98917SArun Ramadoss dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32); 295891a98917SArun Ramadoss id32 &= ~0xFF; 295991a98917SArun Ramadoss 296091a98917SArun Ramadoss switch (id32) { 296191a98917SArun Ramadoss case KSZ9477_CHIP_ID: 29622eb3ff3cSRomain Naour case KSZ9896_CHIP_ID: 296391a98917SArun Ramadoss case KSZ9897_CHIP_ID: 296491a98917SArun Ramadoss case KSZ9567_CHIP_ID: 296591a98917SArun Ramadoss case LAN9370_CHIP_ID: 296691a98917SArun Ramadoss case LAN9371_CHIP_ID: 296791a98917SArun Ramadoss case LAN9372_CHIP_ID: 296891a98917SArun Ramadoss case LAN9373_CHIP_ID: 296991a98917SArun Ramadoss case LAN9374_CHIP_ID: 297091a98917SArun Ramadoss dev->chip_id = id32; 297191a98917SArun Ramadoss break; 2972b4490809SOleksij Rempel case KSZ9893_CHIP_ID: 2973b4490809SOleksij Rempel ret = ksz_read8(dev, REG_CHIP_ID4, 2974b4490809SOleksij Rempel &id4); 2975b4490809SOleksij Rempel if (ret) 2976b4490809SOleksij Rempel return ret; 2977b4490809SOleksij Rempel 2978b4490809SOleksij Rempel if (id4 == SKU_ID_KSZ8563) 2979b4490809SOleksij Rempel dev->chip_id = KSZ8563_CHIP_ID; 2980ef912fe4SRakesh Sankaranarayanan else if (id4 == SKU_ID_KSZ9563) 2981ef912fe4SRakesh Sankaranarayanan dev->chip_id = KSZ9563_CHIP_ID; 2982b4490809SOleksij Rempel else 2983b4490809SOleksij Rempel dev->chip_id = KSZ9893_CHIP_ID; 2984b4490809SOleksij Rempel 2985b4490809SOleksij Rempel break; 298691a98917SArun Ramadoss default: 298791a98917SArun Ramadoss dev_err(dev->dev, 298891a98917SArun Ramadoss "unsupported switch detected %x)\n", id32); 298991a98917SArun Ramadoss return -ENODEV; 299091a98917SArun Ramadoss } 299191a98917SArun Ramadoss } 299291a98917SArun Ramadoss return 0; 299391a98917SArun Ramadoss } 299491a98917SArun Ramadoss 2995*71d7920fSArun Ramadoss /* Bandwidth is calculated by idle slope/transmission speed. Then the Bandwidth 2996*71d7920fSArun Ramadoss * is converted to Hex-decimal using the successive multiplication method. On 2997*71d7920fSArun Ramadoss * every step, integer part is taken and decimal part is carry forwarded. 2998*71d7920fSArun Ramadoss */ 2999*71d7920fSArun Ramadoss static int cinc_cal(s32 idle_slope, s32 send_slope, u32 *bw) 3000*71d7920fSArun Ramadoss { 3001*71d7920fSArun Ramadoss u32 cinc = 0; 3002*71d7920fSArun Ramadoss u32 txrate; 3003*71d7920fSArun Ramadoss u32 rate; 3004*71d7920fSArun Ramadoss u8 temp; 3005*71d7920fSArun Ramadoss u8 i; 3006*71d7920fSArun Ramadoss 3007*71d7920fSArun Ramadoss txrate = idle_slope - send_slope; 3008*71d7920fSArun Ramadoss 3009*71d7920fSArun Ramadoss if (!txrate) 3010*71d7920fSArun Ramadoss return -EINVAL; 3011*71d7920fSArun Ramadoss 3012*71d7920fSArun Ramadoss rate = idle_slope; 3013*71d7920fSArun Ramadoss 3014*71d7920fSArun Ramadoss /* 24 bit register */ 3015*71d7920fSArun Ramadoss for (i = 0; i < 6; i++) { 3016*71d7920fSArun Ramadoss rate = rate * 16; 3017*71d7920fSArun Ramadoss 3018*71d7920fSArun Ramadoss temp = rate / txrate; 3019*71d7920fSArun Ramadoss 3020*71d7920fSArun Ramadoss rate %= txrate; 3021*71d7920fSArun Ramadoss 3022*71d7920fSArun Ramadoss cinc = ((cinc << 4) | temp); 3023*71d7920fSArun Ramadoss } 3024*71d7920fSArun Ramadoss 3025*71d7920fSArun Ramadoss *bw = cinc; 3026*71d7920fSArun Ramadoss 3027*71d7920fSArun Ramadoss return 0; 3028*71d7920fSArun Ramadoss } 3029*71d7920fSArun Ramadoss 3030*71d7920fSArun Ramadoss static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port, 3031*71d7920fSArun Ramadoss struct tc_cbs_qopt_offload *qopt) 3032*71d7920fSArun Ramadoss { 3033*71d7920fSArun Ramadoss struct ksz_device *dev = ds->priv; 3034*71d7920fSArun Ramadoss int ret; 3035*71d7920fSArun Ramadoss u32 bw; 3036*71d7920fSArun Ramadoss 3037*71d7920fSArun Ramadoss if (!dev->info->tc_cbs_supported) 3038*71d7920fSArun Ramadoss return -EOPNOTSUPP; 3039*71d7920fSArun Ramadoss 3040*71d7920fSArun Ramadoss if (qopt->queue > dev->info->num_tx_queues) 3041*71d7920fSArun Ramadoss return -EINVAL; 3042*71d7920fSArun Ramadoss 3043*71d7920fSArun Ramadoss /* Queue Selection */ 3044*71d7920fSArun Ramadoss ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, qopt->queue); 3045*71d7920fSArun Ramadoss if (ret) 3046*71d7920fSArun Ramadoss return ret; 3047*71d7920fSArun Ramadoss 3048*71d7920fSArun Ramadoss if (!qopt->enable) 3049*71d7920fSArun Ramadoss return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0, 3050*71d7920fSArun Ramadoss KSZ_CBS_DISABLE); 3051*71d7920fSArun Ramadoss 3052*71d7920fSArun Ramadoss /* High Credit */ 3053*71d7920fSArun Ramadoss ret = ksz_pwrite16(dev, port, REG_PORT_MTI_HI_WATER_MARK, 3054*71d7920fSArun Ramadoss qopt->hicredit); 3055*71d7920fSArun Ramadoss if (ret) 3056*71d7920fSArun Ramadoss return ret; 3057*71d7920fSArun Ramadoss 3058*71d7920fSArun Ramadoss /* Low Credit */ 3059*71d7920fSArun Ramadoss ret = ksz_pwrite16(dev, port, REG_PORT_MTI_LO_WATER_MARK, 3060*71d7920fSArun Ramadoss qopt->locredit); 3061*71d7920fSArun Ramadoss if (ret) 3062*71d7920fSArun Ramadoss return ret; 3063*71d7920fSArun Ramadoss 3064*71d7920fSArun Ramadoss /* Credit Increment Register */ 3065*71d7920fSArun Ramadoss ret = cinc_cal(qopt->idleslope, qopt->sendslope, &bw); 3066*71d7920fSArun Ramadoss if (ret) 3067*71d7920fSArun Ramadoss return ret; 3068*71d7920fSArun Ramadoss 3069*71d7920fSArun Ramadoss if (dev->dev_ops->tc_cbs_set_cinc) { 3070*71d7920fSArun Ramadoss ret = dev->dev_ops->tc_cbs_set_cinc(dev, port, bw); 3071*71d7920fSArun Ramadoss if (ret) 3072*71d7920fSArun Ramadoss return ret; 3073*71d7920fSArun Ramadoss } 3074*71d7920fSArun Ramadoss 3075*71d7920fSArun Ramadoss return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0, 3076*71d7920fSArun Ramadoss KSZ_CBS_ENABLE); 3077*71d7920fSArun Ramadoss } 3078*71d7920fSArun Ramadoss 3079*71d7920fSArun Ramadoss static int ksz_setup_tc(struct dsa_switch *ds, int port, 3080*71d7920fSArun Ramadoss enum tc_setup_type type, void *type_data) 3081*71d7920fSArun Ramadoss { 3082*71d7920fSArun Ramadoss switch (type) { 3083*71d7920fSArun Ramadoss case TC_SETUP_QDISC_CBS: 3084*71d7920fSArun Ramadoss return ksz_setup_tc_cbs(ds, port, type_data); 3085*71d7920fSArun Ramadoss default: 3086*71d7920fSArun Ramadoss return -EOPNOTSUPP; 3087*71d7920fSArun Ramadoss } 3088*71d7920fSArun Ramadoss } 3089*71d7920fSArun Ramadoss 30901958eee8SArun Ramadoss static const struct dsa_switch_ops ksz_switch_ops = { 30911958eee8SArun Ramadoss .get_tag_protocol = ksz_get_tag_protocol, 3092ab32f56aSChristian Eggers .connect_tag_protocol = ksz_connect_tag_protocol, 30931958eee8SArun Ramadoss .get_phy_flags = ksz_get_phy_flags, 30941958eee8SArun Ramadoss .setup = ksz_setup, 3095c9cd961cSArun Ramadoss .teardown = ksz_teardown, 30961958eee8SArun Ramadoss .phy_read = ksz_phy_read16, 30971958eee8SArun Ramadoss .phy_write = ksz_phy_write16, 30981958eee8SArun Ramadoss .phylink_get_caps = ksz_phylink_get_caps, 3099a0cb1aa4SArun Ramadoss .phylink_mac_config = ksz_phylink_mac_config, 3100f597d3adSArun Ramadoss .phylink_mac_link_up = ksz_phylink_mac_link_up, 31011958eee8SArun Ramadoss .phylink_mac_link_down = ksz_mac_link_down, 31021958eee8SArun Ramadoss .port_enable = ksz_enable_port, 31032c119d99SArun Ramadoss .set_ageing_time = ksz_set_ageing_time, 31041958eee8SArun Ramadoss .get_strings = ksz_get_strings, 31051958eee8SArun Ramadoss .get_ethtool_stats = ksz_get_ethtool_stats, 31061958eee8SArun Ramadoss .get_sset_count = ksz_sset_count, 31071958eee8SArun Ramadoss .port_bridge_join = ksz_port_bridge_join, 31081958eee8SArun Ramadoss .port_bridge_leave = ksz_port_bridge_leave, 31091958eee8SArun Ramadoss .port_stp_state_set = ksz_port_stp_state_set, 311015f7cfaeSVladimir Oltean .port_pre_bridge_flags = ksz_port_pre_bridge_flags, 311115f7cfaeSVladimir Oltean .port_bridge_flags = ksz_port_bridge_flags, 31121958eee8SArun Ramadoss .port_fast_age = ksz_port_fast_age, 31131958eee8SArun Ramadoss .port_vlan_filtering = ksz_port_vlan_filtering, 31141958eee8SArun Ramadoss .port_vlan_add = ksz_port_vlan_add, 31151958eee8SArun Ramadoss .port_vlan_del = ksz_port_vlan_del, 31161958eee8SArun Ramadoss .port_fdb_dump = ksz_port_fdb_dump, 31171958eee8SArun Ramadoss .port_fdb_add = ksz_port_fdb_add, 31181958eee8SArun Ramadoss .port_fdb_del = ksz_port_fdb_del, 31191958eee8SArun Ramadoss .port_mdb_add = ksz_port_mdb_add, 31201958eee8SArun Ramadoss .port_mdb_del = ksz_port_mdb_del, 31211958eee8SArun Ramadoss .port_mirror_add = ksz_port_mirror_add, 31221958eee8SArun Ramadoss .port_mirror_del = ksz_port_mirror_del, 31231958eee8SArun Ramadoss .get_stats64 = ksz_get_stats64, 3124c4748ff6SOleksij Rempel .get_pause_stats = ksz_get_pause_stats, 31251958eee8SArun Ramadoss .port_change_mtu = ksz_change_mtu, 31261958eee8SArun Ramadoss .port_max_mtu = ksz_max_mtu, 3127c59e12a1SChristian Eggers .get_ts_info = ksz_get_ts_info, 3128c59e12a1SChristian Eggers .port_hwtstamp_get = ksz_hwtstamp_get, 3129c59e12a1SChristian Eggers .port_hwtstamp_set = ksz_hwtstamp_set, 3130ab32f56aSChristian Eggers .port_txtstamp = ksz_port_txtstamp, 313190188fffSChristian Eggers .port_rxtstamp = ksz_port_rxtstamp, 3132*71d7920fSArun Ramadoss .port_setup_tc = ksz_setup_tc, 31331958eee8SArun Ramadoss }; 31341958eee8SArun Ramadoss 3135ee394feaSMarek Vasut struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) 3136b987e98eSWoojung Huh { 3137b987e98eSWoojung Huh struct dsa_switch *ds; 3138b987e98eSWoojung Huh struct ksz_device *swdev; 3139b987e98eSWoojung Huh 31407e99e347SVivien Didelot ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL); 3141b987e98eSWoojung Huh if (!ds) 3142b987e98eSWoojung Huh return NULL; 3143b987e98eSWoojung Huh 31447e99e347SVivien Didelot ds->dev = base; 31457e99e347SVivien Didelot ds->num_ports = DSA_MAX_PORTS; 31461958eee8SArun Ramadoss ds->ops = &ksz_switch_ops; 31477e99e347SVivien Didelot 3148b987e98eSWoojung Huh swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); 3149b987e98eSWoojung Huh if (!swdev) 3150b987e98eSWoojung Huh return NULL; 3151b987e98eSWoojung Huh 3152b987e98eSWoojung Huh ds->priv = swdev; 3153b987e98eSWoojung Huh swdev->dev = base; 3154b987e98eSWoojung Huh 3155b987e98eSWoojung Huh swdev->ds = ds; 3156b987e98eSWoojung Huh swdev->priv = priv; 3157b987e98eSWoojung Huh 3158b987e98eSWoojung Huh return swdev; 3159b987e98eSWoojung Huh } 3160b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_alloc); 3161b987e98eSWoojung Huh 3162b19ac41fSArun Ramadoss static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num, 3163b19ac41fSArun Ramadoss struct device_node *port_dn) 3164b19ac41fSArun Ramadoss { 3165b19ac41fSArun Ramadoss phy_interface_t phy_mode = dev->ports[port_num].interface; 3166b19ac41fSArun Ramadoss int rx_delay = -1, tx_delay = -1; 3167b19ac41fSArun Ramadoss 3168b19ac41fSArun Ramadoss if (!phy_interface_mode_is_rgmii(phy_mode)) 3169b19ac41fSArun Ramadoss return; 3170b19ac41fSArun Ramadoss 3171b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay); 3172b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay); 3173b19ac41fSArun Ramadoss 3174b19ac41fSArun Ramadoss if (rx_delay == -1 && tx_delay == -1) { 3175b19ac41fSArun Ramadoss dev_warn(dev->dev, 3176b19ac41fSArun Ramadoss "Port %d interpreting RGMII delay settings based on \"phy-mode\" property, " 3177b19ac41fSArun Ramadoss "please update device tree to specify \"rx-internal-delay-ps\" and " 3178b19ac41fSArun Ramadoss "\"tx-internal-delay-ps\"", 3179b19ac41fSArun Ramadoss port_num); 3180b19ac41fSArun Ramadoss 3181b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID || 3182b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 3183b19ac41fSArun Ramadoss rx_delay = 2000; 3184b19ac41fSArun Ramadoss 3185b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID || 3186b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 3187b19ac41fSArun Ramadoss tx_delay = 2000; 3188b19ac41fSArun Ramadoss } 3189b19ac41fSArun Ramadoss 3190b19ac41fSArun Ramadoss if (rx_delay < 0) 3191b19ac41fSArun Ramadoss rx_delay = 0; 3192b19ac41fSArun Ramadoss if (tx_delay < 0) 3193b19ac41fSArun Ramadoss tx_delay = 0; 3194b19ac41fSArun Ramadoss 3195b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_rx_val = rx_delay; 3196b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_tx_val = tx_delay; 3197b19ac41fSArun Ramadoss } 3198b19ac41fSArun Ramadoss 31996ec23aaaSArun Ramadoss int ksz_switch_register(struct ksz_device *dev) 3200b987e98eSWoojung Huh { 3201462d5250SArun Ramadoss const struct ksz_chip_data *info; 3202912aae27SHelmut Grohne struct device_node *port, *ports; 32030c65b2b9SAndrew Lunn phy_interface_t interface; 3204edecfa98SHelmut Grohne unsigned int port_num; 3205b987e98eSWoojung Huh int ret; 3206198b3478SArun Ramadoss int i; 3207b987e98eSWoojung Huh 3208b987e98eSWoojung Huh if (dev->pdata) 3209b987e98eSWoojung Huh dev->chip_id = dev->pdata->chip_id; 3210b987e98eSWoojung Huh 3211924352c3SMarek Vasut dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset", 3212924352c3SMarek Vasut GPIOD_OUT_LOW); 3213924352c3SMarek Vasut if (IS_ERR(dev->reset_gpio)) 3214924352c3SMarek Vasut return PTR_ERR(dev->reset_gpio); 3215924352c3SMarek Vasut 3216924352c3SMarek Vasut if (dev->reset_gpio) { 321722e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 32185b797980SPaul Barker usleep_range(10000, 12000); 321922e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 0); 32201c45ba93SMarek Vasut msleep(100); 3221924352c3SMarek Vasut } 3222924352c3SMarek Vasut 32237049f9b5STristram Ha mutex_init(&dev->dev_mutex); 3224013572a2SMarek Vasut mutex_init(&dev->regmap_mutex); 3225284fb78eSTristram Ha mutex_init(&dev->alu_mutex); 3226284fb78eSTristram Ha mutex_init(&dev->vlan_mutex); 3227284fb78eSTristram Ha 322891a98917SArun Ramadoss ret = ksz_switch_detect(dev); 322991a98917SArun Ramadoss if (ret) 323091a98917SArun Ramadoss return ret; 3231b987e98eSWoojung Huh 3232462d5250SArun Ramadoss info = ksz_lookup_info(dev->chip_id); 3233462d5250SArun Ramadoss if (!info) 3234462d5250SArun Ramadoss return -ENODEV; 3235462d5250SArun Ramadoss 3236462d5250SArun Ramadoss /* Update the compatible info with the probed one */ 3237462d5250SArun Ramadoss dev->info = info; 3238462d5250SArun Ramadoss 323991a98917SArun Ramadoss dev_info(dev->dev, "found switch: %s, rev %i\n", 324091a98917SArun Ramadoss dev->info->dev_name, dev->chip_rev); 324191a98917SArun Ramadoss 3242eee16b14SArun Ramadoss ret = ksz_check_device_id(dev); 3243eee16b14SArun Ramadoss if (ret) 3244eee16b14SArun Ramadoss return ret; 3245eee16b14SArun Ramadoss 32466ec23aaaSArun Ramadoss dev->dev_ops = dev->info->ops; 324791a98917SArun Ramadoss 3248c2e86691STristram Ha ret = dev->dev_ops->init(dev); 3249b987e98eSWoojung Huh if (ret) 3250b987e98eSWoojung Huh return ret; 3251b987e98eSWoojung Huh 3252198b3478SArun Ramadoss dev->ports = devm_kzalloc(dev->dev, 3253198b3478SArun Ramadoss dev->info->port_cnt * sizeof(struct ksz_port), 3254198b3478SArun Ramadoss GFP_KERNEL); 3255198b3478SArun Ramadoss if (!dev->ports) 3256198b3478SArun Ramadoss return -ENOMEM; 3257198b3478SArun Ramadoss 3258198b3478SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 3259198b3478SArun Ramadoss spin_lock_init(&dev->ports[i].mib.stats64_lock); 3260198b3478SArun Ramadoss mutex_init(&dev->ports[i].mib.cnt_mutex); 3261198b3478SArun Ramadoss dev->ports[i].mib.counters = 3262198b3478SArun Ramadoss devm_kzalloc(dev->dev, 3263198b3478SArun Ramadoss sizeof(u64) * (dev->info->mib_cnt + 1), 3264198b3478SArun Ramadoss GFP_KERNEL); 3265198b3478SArun Ramadoss if (!dev->ports[i].mib.counters) 3266198b3478SArun Ramadoss return -ENOMEM; 3267f3c16545SArun Ramadoss 3268f3c16545SArun Ramadoss dev->ports[i].ksz_dev = dev; 3269f3c16545SArun Ramadoss dev->ports[i].num = i; 3270198b3478SArun Ramadoss } 3271198b3478SArun Ramadoss 3272198b3478SArun Ramadoss /* set the real number of ports */ 3273198b3478SArun Ramadoss dev->ds->num_ports = dev->info->port_cnt; 3274198b3478SArun Ramadoss 32758c29bebbSTristram Ha /* Host port interface will be self detected, or specifically set in 32768c29bebbSTristram Ha * device tree. 32778c29bebbSTristram Ha */ 3278462d5250SArun Ramadoss for (port_num = 0; port_num < dev->info->port_cnt; ++port_num) 3279edecfa98SHelmut Grohne dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA; 3280c2e86691STristram Ha if (dev->dev->of_node) { 32810c65b2b9SAndrew Lunn ret = of_get_phy_mode(dev->dev->of_node, &interface); 32820c65b2b9SAndrew Lunn if (ret == 0) 3283edecfa98SHelmut Grohne dev->compat_interface = interface; 328444e53c88SChristian Eggers ports = of_get_child_by_name(dev->dev->of_node, "ethernet-ports"); 328544e53c88SChristian Eggers if (!ports) 3286912aae27SHelmut Grohne ports = of_get_child_by_name(dev->dev->of_node, "ports"); 3287a14bd747SLiang He if (ports) { 3288912aae27SHelmut Grohne for_each_available_child_of_node(ports, port) { 3289912aae27SHelmut Grohne if (of_property_read_u32(port, "reg", 3290912aae27SHelmut Grohne &port_num)) 3291edecfa98SHelmut Grohne continue; 329284f7e0bbSkernel test robot if (!(dev->port_mask & BIT(port_num))) { 329384f7e0bbSkernel test robot of_node_put(port); 3294a14bd747SLiang He of_node_put(ports); 3295edecfa98SHelmut Grohne return -EINVAL; 329684f7e0bbSkernel test robot } 3297912aae27SHelmut Grohne of_get_phy_mode(port, 3298912aae27SHelmut Grohne &dev->ports[port_num].interface); 3299b19ac41fSArun Ramadoss 3300b19ac41fSArun Ramadoss ksz_parse_rgmii_delay(dev, port_num, port); 3301edecfa98SHelmut Grohne } 3302a14bd747SLiang He of_node_put(ports); 3303a14bd747SLiang He } 330479c8bd15SRobert Hancock dev->synclko_125 = of_property_read_bool(dev->dev->of_node, 330579c8bd15SRobert Hancock "microchip,synclko-125"); 330648bf8b8aSRobert Hancock dev->synclko_disable = of_property_read_bool(dev->dev->of_node, 330748bf8b8aSRobert Hancock "microchip,synclko-disable"); 330848bf8b8aSRobert Hancock if (dev->synclko_125 && dev->synclko_disable) { 330948bf8b8aSRobert Hancock dev_err(dev->dev, "inconsistent synclko settings\n"); 331048bf8b8aSRobert Hancock return -EINVAL; 331148bf8b8aSRobert Hancock } 3312c2e86691STristram Ha } 3313c2e86691STristram Ha 3314c2e86691STristram Ha ret = dsa_register_switch(dev->ds); 3315c2e86691STristram Ha if (ret) { 3316c2e86691STristram Ha dev->dev_ops->exit(dev); 3317c2e86691STristram Ha return ret; 3318c2e86691STristram Ha } 3319c2e86691STristram Ha 33208098bd69SChristian Eggers /* Read MIB counters every 30 seconds to avoid overflow. */ 332112c740c8SOleksij Rempel dev->mib_read_interval = msecs_to_jiffies(5000); 33228098bd69SChristian Eggers 33238098bd69SChristian Eggers /* Start the MIB timer. */ 33248098bd69SChristian Eggers schedule_delayed_work(&dev->mib_read, 0); 33258098bd69SChristian Eggers 33267a8988a1SArun Ramadoss return ret; 3327b987e98eSWoojung Huh } 3328b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_register); 3329b987e98eSWoojung Huh 3330b987e98eSWoojung Huh void ksz_switch_remove(struct ksz_device *dev) 3331b987e98eSWoojung Huh { 33327c6ff470STristram Ha /* timer started */ 3333ef1100efSArun Ramadoss if (dev->mib_read_interval) { 3334ef1100efSArun Ramadoss dev->mib_read_interval = 0; 3335469b390eSGeorge McCollister cancel_delayed_work_sync(&dev->mib_read); 3336ef1100efSArun Ramadoss } 33377c6ff470STristram Ha 3338c2e86691STristram Ha dev->dev_ops->exit(dev); 3339b987e98eSWoojung Huh dsa_unregister_switch(dev->ds); 3340924352c3SMarek Vasut 3341924352c3SMarek Vasut if (dev->reset_gpio) 334222e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 3343924352c3SMarek Vasut 3344b987e98eSWoojung Huh } 3345b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_remove); 3346b987e98eSWoojung Huh 3347b987e98eSWoojung Huh MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 3348b987e98eSWoojung Huh MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver"); 3349b987e98eSWoojung Huh MODULE_LICENSE("GPL"); 3350