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> 2671d7920fSArun 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 35a530e6f2SArun Ramadoss #define MIB_COUNTER_NUM 0x20 36a530e6f2SArun Ramadoss 37c6101dd7SArun Ramadoss struct ksz_stats_raw { 38c6101dd7SArun Ramadoss u64 rx_hi; 39c6101dd7SArun Ramadoss u64 rx_undersize; 40c6101dd7SArun Ramadoss u64 rx_fragments; 41c6101dd7SArun Ramadoss u64 rx_oversize; 42c6101dd7SArun Ramadoss u64 rx_jabbers; 43c6101dd7SArun Ramadoss u64 rx_symbol_err; 44c6101dd7SArun Ramadoss u64 rx_crc_err; 45c6101dd7SArun Ramadoss u64 rx_align_err; 46c6101dd7SArun Ramadoss u64 rx_mac_ctrl; 47c6101dd7SArun Ramadoss u64 rx_pause; 48c6101dd7SArun Ramadoss u64 rx_bcast; 49c6101dd7SArun Ramadoss u64 rx_mcast; 50c6101dd7SArun Ramadoss u64 rx_ucast; 51c6101dd7SArun Ramadoss u64 rx_64_or_less; 52c6101dd7SArun Ramadoss u64 rx_65_127; 53c6101dd7SArun Ramadoss u64 rx_128_255; 54c6101dd7SArun Ramadoss u64 rx_256_511; 55c6101dd7SArun Ramadoss u64 rx_512_1023; 56c6101dd7SArun Ramadoss u64 rx_1024_1522; 57c6101dd7SArun Ramadoss u64 rx_1523_2000; 58c6101dd7SArun Ramadoss u64 rx_2001; 59c6101dd7SArun Ramadoss u64 tx_hi; 60c6101dd7SArun Ramadoss u64 tx_late_col; 61c6101dd7SArun Ramadoss u64 tx_pause; 62c6101dd7SArun Ramadoss u64 tx_bcast; 63c6101dd7SArun Ramadoss u64 tx_mcast; 64c6101dd7SArun Ramadoss u64 tx_ucast; 65c6101dd7SArun Ramadoss u64 tx_deferred; 66c6101dd7SArun Ramadoss u64 tx_total_col; 67c6101dd7SArun Ramadoss u64 tx_exc_col; 68c6101dd7SArun Ramadoss u64 tx_single_col; 69c6101dd7SArun Ramadoss u64 tx_mult_col; 70c6101dd7SArun Ramadoss u64 rx_total; 71c6101dd7SArun Ramadoss u64 tx_total; 72c6101dd7SArun Ramadoss u64 rx_discards; 73c6101dd7SArun Ramadoss u64 tx_discards; 74c6101dd7SArun Ramadoss }; 75c6101dd7SArun Ramadoss 76bde55dd9SOleksij Rempel struct ksz88xx_stats_raw { 77bde55dd9SOleksij Rempel u64 rx; 78bde55dd9SOleksij Rempel u64 rx_hi; 79bde55dd9SOleksij Rempel u64 rx_undersize; 80bde55dd9SOleksij Rempel u64 rx_fragments; 81bde55dd9SOleksij Rempel u64 rx_oversize; 82bde55dd9SOleksij Rempel u64 rx_jabbers; 83bde55dd9SOleksij Rempel u64 rx_symbol_err; 84bde55dd9SOleksij Rempel u64 rx_crc_err; 85bde55dd9SOleksij Rempel u64 rx_align_err; 86bde55dd9SOleksij Rempel u64 rx_mac_ctrl; 87bde55dd9SOleksij Rempel u64 rx_pause; 88bde55dd9SOleksij Rempel u64 rx_bcast; 89bde55dd9SOleksij Rempel u64 rx_mcast; 90bde55dd9SOleksij Rempel u64 rx_ucast; 91bde55dd9SOleksij Rempel u64 rx_64_or_less; 92bde55dd9SOleksij Rempel u64 rx_65_127; 93bde55dd9SOleksij Rempel u64 rx_128_255; 94bde55dd9SOleksij Rempel u64 rx_256_511; 95bde55dd9SOleksij Rempel u64 rx_512_1023; 96bde55dd9SOleksij Rempel u64 rx_1024_1522; 97bde55dd9SOleksij Rempel u64 tx; 98bde55dd9SOleksij Rempel u64 tx_hi; 99bde55dd9SOleksij Rempel u64 tx_late_col; 100bde55dd9SOleksij Rempel u64 tx_pause; 101bde55dd9SOleksij Rempel u64 tx_bcast; 102bde55dd9SOleksij Rempel u64 tx_mcast; 103bde55dd9SOleksij Rempel u64 tx_ucast; 104bde55dd9SOleksij Rempel u64 tx_deferred; 105bde55dd9SOleksij Rempel u64 tx_total_col; 106bde55dd9SOleksij Rempel u64 tx_exc_col; 107bde55dd9SOleksij Rempel u64 tx_single_col; 108bde55dd9SOleksij Rempel u64 tx_mult_col; 109bde55dd9SOleksij Rempel u64 rx_discards; 110bde55dd9SOleksij Rempel u64 tx_discards; 111bde55dd9SOleksij Rempel }; 112bde55dd9SOleksij Rempel 113a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz88xx_mib_names[] = { 114a530e6f2SArun Ramadoss { 0x00, "rx" }, 115a530e6f2SArun Ramadoss { 0x01, "rx_hi" }, 116a530e6f2SArun Ramadoss { 0x02, "rx_undersize" }, 117a530e6f2SArun Ramadoss { 0x03, "rx_fragments" }, 118a530e6f2SArun Ramadoss { 0x04, "rx_oversize" }, 119a530e6f2SArun Ramadoss { 0x05, "rx_jabbers" }, 120a530e6f2SArun Ramadoss { 0x06, "rx_symbol_err" }, 121a530e6f2SArun Ramadoss { 0x07, "rx_crc_err" }, 122a530e6f2SArun Ramadoss { 0x08, "rx_align_err" }, 123a530e6f2SArun Ramadoss { 0x09, "rx_mac_ctrl" }, 124a530e6f2SArun Ramadoss { 0x0a, "rx_pause" }, 125a530e6f2SArun Ramadoss { 0x0b, "rx_bcast" }, 126a530e6f2SArun Ramadoss { 0x0c, "rx_mcast" }, 127a530e6f2SArun Ramadoss { 0x0d, "rx_ucast" }, 128a530e6f2SArun Ramadoss { 0x0e, "rx_64_or_less" }, 129a530e6f2SArun Ramadoss { 0x0f, "rx_65_127" }, 130a530e6f2SArun Ramadoss { 0x10, "rx_128_255" }, 131a530e6f2SArun Ramadoss { 0x11, "rx_256_511" }, 132a530e6f2SArun Ramadoss { 0x12, "rx_512_1023" }, 133a530e6f2SArun Ramadoss { 0x13, "rx_1024_1522" }, 134a530e6f2SArun Ramadoss { 0x14, "tx" }, 135a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 136a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 137a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 138a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 139a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 140a530e6f2SArun Ramadoss { 0x1a, "tx_ucast" }, 141a530e6f2SArun Ramadoss { 0x1b, "tx_deferred" }, 142a530e6f2SArun Ramadoss { 0x1c, "tx_total_col" }, 143a530e6f2SArun Ramadoss { 0x1d, "tx_exc_col" }, 144a530e6f2SArun Ramadoss { 0x1e, "tx_single_col" }, 145a530e6f2SArun Ramadoss { 0x1f, "tx_mult_col" }, 146a530e6f2SArun Ramadoss { 0x100, "rx_discards" }, 147a530e6f2SArun Ramadoss { 0x101, "tx_discards" }, 148a530e6f2SArun Ramadoss }; 149a530e6f2SArun Ramadoss 150a530e6f2SArun Ramadoss static const struct ksz_mib_names ksz9477_mib_names[] = { 151a530e6f2SArun Ramadoss { 0x00, "rx_hi" }, 152a530e6f2SArun Ramadoss { 0x01, "rx_undersize" }, 153a530e6f2SArun Ramadoss { 0x02, "rx_fragments" }, 154a530e6f2SArun Ramadoss { 0x03, "rx_oversize" }, 155a530e6f2SArun Ramadoss { 0x04, "rx_jabbers" }, 156a530e6f2SArun Ramadoss { 0x05, "rx_symbol_err" }, 157a530e6f2SArun Ramadoss { 0x06, "rx_crc_err" }, 158a530e6f2SArun Ramadoss { 0x07, "rx_align_err" }, 159a530e6f2SArun Ramadoss { 0x08, "rx_mac_ctrl" }, 160a530e6f2SArun Ramadoss { 0x09, "rx_pause" }, 161a530e6f2SArun Ramadoss { 0x0A, "rx_bcast" }, 162a530e6f2SArun Ramadoss { 0x0B, "rx_mcast" }, 163a530e6f2SArun Ramadoss { 0x0C, "rx_ucast" }, 164a530e6f2SArun Ramadoss { 0x0D, "rx_64_or_less" }, 165a530e6f2SArun Ramadoss { 0x0E, "rx_65_127" }, 166a530e6f2SArun Ramadoss { 0x0F, "rx_128_255" }, 167a530e6f2SArun Ramadoss { 0x10, "rx_256_511" }, 168a530e6f2SArun Ramadoss { 0x11, "rx_512_1023" }, 169a530e6f2SArun Ramadoss { 0x12, "rx_1024_1522" }, 170a530e6f2SArun Ramadoss { 0x13, "rx_1523_2000" }, 171a530e6f2SArun Ramadoss { 0x14, "rx_2001" }, 172a530e6f2SArun Ramadoss { 0x15, "tx_hi" }, 173a530e6f2SArun Ramadoss { 0x16, "tx_late_col" }, 174a530e6f2SArun Ramadoss { 0x17, "tx_pause" }, 175a530e6f2SArun Ramadoss { 0x18, "tx_bcast" }, 176a530e6f2SArun Ramadoss { 0x19, "tx_mcast" }, 177a530e6f2SArun Ramadoss { 0x1A, "tx_ucast" }, 178a530e6f2SArun Ramadoss { 0x1B, "tx_deferred" }, 179a530e6f2SArun Ramadoss { 0x1C, "tx_total_col" }, 180a530e6f2SArun Ramadoss { 0x1D, "tx_exc_col" }, 181a530e6f2SArun Ramadoss { 0x1E, "tx_single_col" }, 182a530e6f2SArun Ramadoss { 0x1F, "tx_mult_col" }, 183a530e6f2SArun Ramadoss { 0x80, "rx_total" }, 184a530e6f2SArun Ramadoss { 0x81, "tx_total" }, 185a530e6f2SArun Ramadoss { 0x82, "rx_discards" }, 186a530e6f2SArun Ramadoss { 0x83, "tx_discards" }, 187a530e6f2SArun Ramadoss }; 188a530e6f2SArun Ramadoss 1896ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz8_dev_ops = { 1906ec23aaaSArun Ramadoss .setup = ksz8_setup, 1916ec23aaaSArun Ramadoss .get_port_addr = ksz8_get_port_addr, 1926ec23aaaSArun Ramadoss .cfg_port_member = ksz8_cfg_port_member, 1936ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz8_flush_dyn_mac_table, 1946ec23aaaSArun Ramadoss .port_setup = ksz8_port_setup, 1956ec23aaaSArun Ramadoss .r_phy = ksz8_r_phy, 1966ec23aaaSArun Ramadoss .w_phy = ksz8_w_phy, 197769e2695SArun Ramadoss .r_mib_cnt = ksz8_r_mib_cnt, 1986ec23aaaSArun Ramadoss .r_mib_pkt = ksz8_r_mib_pkt, 199bde55dd9SOleksij Rempel .r_mib_stat64 = ksz88xx_r_mib_stats64, 2006ec23aaaSArun Ramadoss .freeze_mib = ksz8_freeze_mib, 2016ec23aaaSArun Ramadoss .port_init_cnt = ksz8_port_init_cnt, 2026ec23aaaSArun Ramadoss .fdb_dump = ksz8_fdb_dump, 20357795412SOleksij Rempel .fdb_add = ksz8_fdb_add, 20457795412SOleksij Rempel .fdb_del = ksz8_fdb_del, 2056ec23aaaSArun Ramadoss .mdb_add = ksz8_mdb_add, 2066ec23aaaSArun Ramadoss .mdb_del = ksz8_mdb_del, 2076ec23aaaSArun Ramadoss .vlan_filtering = ksz8_port_vlan_filtering, 2086ec23aaaSArun Ramadoss .vlan_add = ksz8_port_vlan_add, 2096ec23aaaSArun Ramadoss .vlan_del = ksz8_port_vlan_del, 2106ec23aaaSArun Ramadoss .mirror_add = ksz8_port_mirror_add, 2116ec23aaaSArun Ramadoss .mirror_del = ksz8_port_mirror_del, 2126ec23aaaSArun Ramadoss .get_caps = ksz8_get_caps, 2136ec23aaaSArun Ramadoss .config_cpu_port = ksz8_config_cpu_port, 2146ec23aaaSArun Ramadoss .enable_stp_addr = ksz8_enable_stp_addr, 2156ec23aaaSArun Ramadoss .reset = ksz8_reset_switch, 2166ec23aaaSArun Ramadoss .init = ksz8_switch_init, 2176ec23aaaSArun Ramadoss .exit = ksz8_switch_exit, 21829d1e85fSOleksij Rempel .change_mtu = ksz8_change_mtu, 2196ec23aaaSArun Ramadoss }; 2206ec23aaaSArun Ramadoss 2213015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 2223015c503SOleksij Rempel unsigned int mode, 2233015c503SOleksij Rempel phy_interface_t interface, 2243015c503SOleksij Rempel struct phy_device *phydev, int speed, 2253015c503SOleksij Rempel int duplex, bool tx_pause, 2263015c503SOleksij Rempel bool rx_pause); 2273015c503SOleksij Rempel 2286ec23aaaSArun Ramadoss static const struct ksz_dev_ops ksz9477_dev_ops = { 2296ec23aaaSArun Ramadoss .setup = ksz9477_setup, 2306ec23aaaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 2316ec23aaaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 2326ec23aaaSArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 2336ec23aaaSArun Ramadoss .port_setup = ksz9477_port_setup, 2342c119d99SArun Ramadoss .set_ageing_time = ksz9477_set_ageing_time, 2356ec23aaaSArun Ramadoss .r_phy = ksz9477_r_phy, 2366ec23aaaSArun Ramadoss .w_phy = ksz9477_w_phy, 2376ec23aaaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 2386ec23aaaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 2396ec23aaaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 2406ec23aaaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 2416ec23aaaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 2426ec23aaaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 2436ec23aaaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 2446ec23aaaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 2456ec23aaaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 2466ec23aaaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 2476ec23aaaSArun Ramadoss .get_caps = ksz9477_get_caps, 2486ec23aaaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 2496ec23aaaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 2506ec23aaaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 2516ec23aaaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 2526ec23aaaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 2536ec23aaaSArun Ramadoss .change_mtu = ksz9477_change_mtu, 2543015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 2556ec23aaaSArun Ramadoss .config_cpu_port = ksz9477_config_cpu_port, 25671d7920fSArun Ramadoss .tc_cbs_set_cinc = ksz9477_tc_cbs_set_cinc, 2576ec23aaaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 2586ec23aaaSArun Ramadoss .reset = ksz9477_reset_switch, 2596ec23aaaSArun Ramadoss .init = ksz9477_switch_init, 2606ec23aaaSArun Ramadoss .exit = ksz9477_switch_exit, 2616ec23aaaSArun Ramadoss }; 2626ec23aaaSArun Ramadoss 26355ab6ffaSArun Ramadoss static const struct ksz_dev_ops lan937x_dev_ops = { 26455ab6ffaSArun Ramadoss .setup = lan937x_setup, 265c9cd961cSArun Ramadoss .teardown = lan937x_teardown, 26655ab6ffaSArun Ramadoss .get_port_addr = ksz9477_get_port_addr, 26755ab6ffaSArun Ramadoss .cfg_port_member = ksz9477_cfg_port_member, 268ab882368SArun Ramadoss .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, 26955ab6ffaSArun Ramadoss .port_setup = lan937x_port_setup, 2702c119d99SArun Ramadoss .set_ageing_time = lan937x_set_ageing_time, 271ffaf1de2SArun Ramadoss .r_phy = lan937x_r_phy, 272ffaf1de2SArun Ramadoss .w_phy = lan937x_w_phy, 27355ab6ffaSArun Ramadoss .r_mib_cnt = ksz9477_r_mib_cnt, 27455ab6ffaSArun Ramadoss .r_mib_pkt = ksz9477_r_mib_pkt, 27555ab6ffaSArun Ramadoss .r_mib_stat64 = ksz_r_mib_stats64, 27655ab6ffaSArun Ramadoss .freeze_mib = ksz9477_freeze_mib, 27755ab6ffaSArun Ramadoss .port_init_cnt = ksz9477_port_init_cnt, 27855ab6ffaSArun Ramadoss .vlan_filtering = ksz9477_port_vlan_filtering, 27955ab6ffaSArun Ramadoss .vlan_add = ksz9477_port_vlan_add, 28055ab6ffaSArun Ramadoss .vlan_del = ksz9477_port_vlan_del, 28155ab6ffaSArun Ramadoss .mirror_add = ksz9477_port_mirror_add, 28255ab6ffaSArun Ramadoss .mirror_del = ksz9477_port_mirror_del, 283c14e878dSArun Ramadoss .get_caps = lan937x_phylink_get_caps, 284b19ac41fSArun Ramadoss .setup_rgmii_delay = lan937x_setup_rgmii_delay, 28555ab6ffaSArun Ramadoss .fdb_dump = ksz9477_fdb_dump, 28655ab6ffaSArun Ramadoss .fdb_add = ksz9477_fdb_add, 28755ab6ffaSArun Ramadoss .fdb_del = ksz9477_fdb_del, 28855ab6ffaSArun Ramadoss .mdb_add = ksz9477_mdb_add, 28955ab6ffaSArun Ramadoss .mdb_del = ksz9477_mdb_del, 290ab882368SArun Ramadoss .change_mtu = lan937x_change_mtu, 2913015c503SOleksij Rempel .phylink_mac_link_up = ksz9477_phylink_mac_link_up, 29255ab6ffaSArun Ramadoss .config_cpu_port = lan937x_config_cpu_port, 29371d7920fSArun Ramadoss .tc_cbs_set_cinc = lan937x_tc_cbs_set_cinc, 29455ab6ffaSArun Ramadoss .enable_stp_addr = ksz9477_enable_stp_addr, 29555ab6ffaSArun Ramadoss .reset = lan937x_reset_switch, 29655ab6ffaSArun Ramadoss .init = lan937x_switch_init, 29755ab6ffaSArun Ramadoss .exit = lan937x_switch_exit, 29855ab6ffaSArun Ramadoss }; 29955ab6ffaSArun Ramadoss 300a02579dfSArun Ramadoss static const u16 ksz8795_regs[] = { 301486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x6E, 302486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x70, 303486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x72, 304486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x71, 305486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x75, 306486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x74, 307486f9ca7SArun Ramadoss [REG_IND_BYTE] = 0xA0, 308486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 309486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 310486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x07, 311486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 312486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x08, 313486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x09, 314486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x0C, 3156877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3169d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3179d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3189d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 319aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x06, 3205ae06327SMarek Vasut [P_XMII_CTRL_1] = 0x06, 321486f9ca7SArun Ramadoss }; 322486f9ca7SArun Ramadoss 323d23a5e18SArun Ramadoss static const u32 ksz8795_masks[] = { 324d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(7), 325d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(1), 326d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(6), 327d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(5), 328d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(6, 0), 329d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(11, 7), 330d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(12), 331d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(21), 332d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(23), 333d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FID] = GENMASK(30, 24), 334*4bdf79d6STristram Ha [STATIC_MAC_TABLE_OVERRIDE] = BIT(22), 335*4bdf79d6STristram Ha [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(20, 16), 336d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(6, 0), 337*4bdf79d6STristram Ha [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(7), 338d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 339d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 29), 340*4bdf79d6STristram Ha [DYNAMIC_MAC_TABLE_FID] = GENMASK(22, 16), 341d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(26, 24), 342d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(28, 27), 3438560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 3448560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(5), 345d23a5e18SArun Ramadoss }; 346d23a5e18SArun Ramadoss 347aa5b8b73SArun Ramadoss static const u8 ksz8795_xmii_ctrl0[] = { 348aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 0, 349aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 1, 3508560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 0, 3518560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 1, 352aa5b8b73SArun Ramadoss }; 353aa5b8b73SArun Ramadoss 35446f80fa8SArun Ramadoss static const u8 ksz8795_xmii_ctrl1[] = { 355dc1c596eSArun Ramadoss [P_RGMII_SEL] = 3, 356dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 357dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 358dc1c596eSArun Ramadoss [P_MII_SEL] = 0, 35946f80fa8SArun Ramadoss [P_GMII_1GBIT] = 1, 36046f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 0, 36146f80fa8SArun Ramadoss }; 36246f80fa8SArun Ramadoss 36334e48383SArun Ramadoss static const u8 ksz8795_shifts[] = { 36434e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 7, 36534e48383SArun Ramadoss [VLAN_TABLE] = 16, 36634e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 36734e48383SArun Ramadoss [STATIC_MAC_FID] = 24, 36834e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES_H] = 3, 36934e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 29, 37034e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 37134e48383SArun Ramadoss [DYNAMIC_MAC_TIMESTAMP] = 27, 37234e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 24, 37334e48383SArun Ramadoss }; 37434e48383SArun Ramadoss 375a02579dfSArun Ramadoss static const u16 ksz8863_regs[] = { 376486f9ca7SArun Ramadoss [REG_IND_CTRL_0] = 0x79, 377486f9ca7SArun Ramadoss [REG_IND_DATA_8] = 0x7B, 378486f9ca7SArun Ramadoss [REG_IND_DATA_CHECK] = 0x7B, 379486f9ca7SArun Ramadoss [REG_IND_DATA_HI] = 0x7C, 380486f9ca7SArun Ramadoss [REG_IND_DATA_LO] = 0x80, 381486f9ca7SArun Ramadoss [REG_IND_MIB_CHECK] = 0x80, 382486f9ca7SArun Ramadoss [P_FORCE_CTRL] = 0x0C, 383486f9ca7SArun Ramadoss [P_LINK_STATUS] = 0x0E, 384486f9ca7SArun Ramadoss [P_LOCAL_CTRL] = 0x0C, 385486f9ca7SArun Ramadoss [P_NEG_RESTART_CTRL] = 0x0D, 386486f9ca7SArun Ramadoss [P_REMOTE_STATUS] = 0x0E, 387486f9ca7SArun Ramadoss [P_SPEED_STATUS] = 0x0F, 388486f9ca7SArun Ramadoss [S_TAIL_TAG_CTRL] = 0x03, 3896877102fSArun Ramadoss [P_STP_CTRL] = 0x02, 3909d95329cSArun Ramadoss [S_START_CTRL] = 0x01, 3919d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x06, 3929d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x04, 393486f9ca7SArun Ramadoss }; 394486f9ca7SArun Ramadoss 395d23a5e18SArun Ramadoss static const u32 ksz8863_masks[] = { 396d23a5e18SArun Ramadoss [PORT_802_1P_REMAPPING] = BIT(3), 397d23a5e18SArun Ramadoss [SW_TAIL_TAG_ENABLE] = BIT(6), 398d23a5e18SArun Ramadoss [MIB_COUNTER_OVERFLOW] = BIT(7), 399d23a5e18SArun Ramadoss [MIB_COUNTER_VALID] = BIT(6), 400d23a5e18SArun Ramadoss [VLAN_TABLE_FID] = GENMASK(15, 12), 401d23a5e18SArun Ramadoss [VLAN_TABLE_MEMBERSHIP] = GENMASK(18, 16), 402d23a5e18SArun Ramadoss [VLAN_TABLE_VALID] = BIT(19), 403d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_VALID] = BIT(19), 404d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_USE_FID] = BIT(21), 4059aa5757eSOleksij Rempel [STATIC_MAC_TABLE_FID] = GENMASK(25, 22), 406d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_OVERRIDE] = BIT(20), 407d23a5e18SArun Ramadoss [STATIC_MAC_TABLE_FWD_PORTS] = GENMASK(18, 16), 4085d90492dSOleksij Rempel [DYNAMIC_MAC_TABLE_ENTRIES_H] = GENMASK(1, 0), 409492606cdSOleksij Rempel [DYNAMIC_MAC_TABLE_MAC_EMPTY] = BIT(2), 410d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_NOT_READY] = BIT(7), 4115d90492dSOleksij Rempel [DYNAMIC_MAC_TABLE_ENTRIES] = GENMASK(31, 24), 412d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_FID] = GENMASK(19, 16), 413d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_SRC_PORT] = GENMASK(21, 20), 414d23a5e18SArun Ramadoss [DYNAMIC_MAC_TABLE_TIMESTAMP] = GENMASK(23, 22), 415d23a5e18SArun Ramadoss }; 416d23a5e18SArun Ramadoss 41734e48383SArun Ramadoss static u8 ksz8863_shifts[] = { 41834e48383SArun Ramadoss [VLAN_TABLE_MEMBERSHIP_S] = 16, 41934e48383SArun Ramadoss [STATIC_MAC_FWD_PORTS] = 16, 42034e48383SArun Ramadoss [STATIC_MAC_FID] = 22, 4215d90492dSOleksij Rempel [DYNAMIC_MAC_ENTRIES_H] = 8, 42234e48383SArun Ramadoss [DYNAMIC_MAC_ENTRIES] = 24, 42334e48383SArun Ramadoss [DYNAMIC_MAC_FID] = 16, 424b3177aabSOleksij Rempel [DYNAMIC_MAC_TIMESTAMP] = 22, 42534e48383SArun Ramadoss [DYNAMIC_MAC_SRC_PORT] = 20, 42634e48383SArun Ramadoss }; 42734e48383SArun Ramadoss 4286877102fSArun Ramadoss static const u16 ksz9477_regs[] = { 4296877102fSArun Ramadoss [P_STP_CTRL] = 0x0B04, 4309d95329cSArun Ramadoss [S_START_CTRL] = 0x0300, 4319d95329cSArun Ramadoss [S_BROADCAST_CTRL] = 0x0332, 4329d95329cSArun Ramadoss [S_MULTICAST_CTRL] = 0x0331, 433aa5b8b73SArun Ramadoss [P_XMII_CTRL_0] = 0x0300, 43446f80fa8SArun Ramadoss [P_XMII_CTRL_1] = 0x0301, 435457c182aSArun Ramadoss }; 4366877102fSArun Ramadoss 437457c182aSArun Ramadoss static const u32 ksz9477_masks[] = { 438457c182aSArun Ramadoss [ALU_STAT_WRITE] = 0, 439457c182aSArun Ramadoss [ALU_STAT_READ] = 1, 4408560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 4418560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 442457c182aSArun Ramadoss }; 443457c182aSArun Ramadoss 444457c182aSArun Ramadoss static const u8 ksz9477_shifts[] = { 445457c182aSArun Ramadoss [ALU_STAT_INDEX] = 16, 446457c182aSArun Ramadoss }; 447457c182aSArun Ramadoss 448aa5b8b73SArun Ramadoss static const u8 ksz9477_xmii_ctrl0[] = { 449aa5b8b73SArun Ramadoss [P_MII_100MBIT] = 1, 450aa5b8b73SArun Ramadoss [P_MII_10MBIT] = 0, 4518560664fSArun Ramadoss [P_MII_FULL_DUPLEX] = 1, 4528560664fSArun Ramadoss [P_MII_HALF_DUPLEX] = 0, 453aa5b8b73SArun Ramadoss }; 454aa5b8b73SArun Ramadoss 45546f80fa8SArun Ramadoss static const u8 ksz9477_xmii_ctrl1[] = { 456dc1c596eSArun Ramadoss [P_RGMII_SEL] = 0, 457dc1c596eSArun Ramadoss [P_RMII_SEL] = 1, 458dc1c596eSArun Ramadoss [P_GMII_SEL] = 2, 459dc1c596eSArun Ramadoss [P_MII_SEL] = 3, 46046f80fa8SArun Ramadoss [P_GMII_1GBIT] = 0, 46146f80fa8SArun Ramadoss [P_GMII_NOT_1GBIT] = 1, 46246f80fa8SArun Ramadoss }; 46346f80fa8SArun Ramadoss 464457c182aSArun Ramadoss static const u32 lan937x_masks[] = { 465457c182aSArun Ramadoss [ALU_STAT_WRITE] = 1, 466457c182aSArun Ramadoss [ALU_STAT_READ] = 2, 4678560664fSArun Ramadoss [P_MII_TX_FLOW_CTRL] = BIT(5), 4688560664fSArun Ramadoss [P_MII_RX_FLOW_CTRL] = BIT(3), 469457c182aSArun Ramadoss }; 470457c182aSArun Ramadoss 471457c182aSArun Ramadoss static const u8 lan937x_shifts[] = { 472457c182aSArun Ramadoss [ALU_STAT_INDEX] = 8, 4736877102fSArun Ramadoss }; 4746877102fSArun Ramadoss 47541131bacSOleksij Rempel static const struct regmap_range ksz8563_valid_regs[] = { 47641131bacSOleksij Rempel regmap_reg_range(0x0000, 0x0003), 47741131bacSOleksij Rempel regmap_reg_range(0x0006, 0x0006), 47841131bacSOleksij Rempel regmap_reg_range(0x000f, 0x001f), 47941131bacSOleksij Rempel regmap_reg_range(0x0100, 0x0100), 48041131bacSOleksij Rempel regmap_reg_range(0x0104, 0x0107), 48141131bacSOleksij Rempel regmap_reg_range(0x010d, 0x010d), 48241131bacSOleksij Rempel regmap_reg_range(0x0110, 0x0113), 48341131bacSOleksij Rempel regmap_reg_range(0x0120, 0x012b), 48441131bacSOleksij Rempel regmap_reg_range(0x0201, 0x0201), 48541131bacSOleksij Rempel regmap_reg_range(0x0210, 0x0213), 48641131bacSOleksij Rempel regmap_reg_range(0x0300, 0x0300), 48741131bacSOleksij Rempel regmap_reg_range(0x0302, 0x031b), 48841131bacSOleksij Rempel regmap_reg_range(0x0320, 0x032b), 48941131bacSOleksij Rempel regmap_reg_range(0x0330, 0x0336), 49041131bacSOleksij Rempel regmap_reg_range(0x0338, 0x033e), 49141131bacSOleksij Rempel regmap_reg_range(0x0340, 0x035f), 49241131bacSOleksij Rempel regmap_reg_range(0x0370, 0x0370), 49341131bacSOleksij Rempel regmap_reg_range(0x0378, 0x0378), 49441131bacSOleksij Rempel regmap_reg_range(0x037c, 0x037d), 49541131bacSOleksij Rempel regmap_reg_range(0x0390, 0x0393), 49641131bacSOleksij Rempel regmap_reg_range(0x0400, 0x040e), 49741131bacSOleksij Rempel regmap_reg_range(0x0410, 0x042f), 49841131bacSOleksij Rempel regmap_reg_range(0x0500, 0x0519), 49941131bacSOleksij Rempel regmap_reg_range(0x0520, 0x054b), 50041131bacSOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 50141131bacSOleksij Rempel 50241131bacSOleksij Rempel /* port 1 */ 50341131bacSOleksij Rempel regmap_reg_range(0x1000, 0x1001), 50441131bacSOleksij Rempel regmap_reg_range(0x1004, 0x100b), 50541131bacSOleksij Rempel regmap_reg_range(0x1013, 0x1013), 50641131bacSOleksij Rempel regmap_reg_range(0x1017, 0x1017), 50741131bacSOleksij Rempel regmap_reg_range(0x101b, 0x101b), 50841131bacSOleksij Rempel regmap_reg_range(0x101f, 0x1021), 50941131bacSOleksij Rempel regmap_reg_range(0x1030, 0x1030), 51041131bacSOleksij Rempel regmap_reg_range(0x1100, 0x1111), 51141131bacSOleksij Rempel regmap_reg_range(0x111a, 0x111d), 51241131bacSOleksij Rempel regmap_reg_range(0x1122, 0x1127), 51341131bacSOleksij Rempel regmap_reg_range(0x112a, 0x112b), 51441131bacSOleksij Rempel regmap_reg_range(0x1136, 0x1139), 51541131bacSOleksij Rempel regmap_reg_range(0x113e, 0x113f), 51641131bacSOleksij Rempel regmap_reg_range(0x1400, 0x1401), 51741131bacSOleksij Rempel regmap_reg_range(0x1403, 0x1403), 51841131bacSOleksij Rempel regmap_reg_range(0x1410, 0x1417), 51941131bacSOleksij Rempel regmap_reg_range(0x1420, 0x1423), 52041131bacSOleksij Rempel regmap_reg_range(0x1500, 0x1507), 52141131bacSOleksij Rempel regmap_reg_range(0x1600, 0x1612), 52241131bacSOleksij Rempel regmap_reg_range(0x1800, 0x180f), 52341131bacSOleksij Rempel regmap_reg_range(0x1900, 0x1907), 52441131bacSOleksij Rempel regmap_reg_range(0x1914, 0x191b), 52541131bacSOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 52641131bacSOleksij Rempel regmap_reg_range(0x1a04, 0x1a08), 52741131bacSOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 52841131bacSOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 52941131bacSOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 53041131bacSOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 53141131bacSOleksij Rempel 53241131bacSOleksij Rempel /* port 2 */ 53341131bacSOleksij Rempel regmap_reg_range(0x2000, 0x2001), 53441131bacSOleksij Rempel regmap_reg_range(0x2004, 0x200b), 53541131bacSOleksij Rempel regmap_reg_range(0x2013, 0x2013), 53641131bacSOleksij Rempel regmap_reg_range(0x2017, 0x2017), 53741131bacSOleksij Rempel regmap_reg_range(0x201b, 0x201b), 53841131bacSOleksij Rempel regmap_reg_range(0x201f, 0x2021), 53941131bacSOleksij Rempel regmap_reg_range(0x2030, 0x2030), 54041131bacSOleksij Rempel regmap_reg_range(0x2100, 0x2111), 54141131bacSOleksij Rempel regmap_reg_range(0x211a, 0x211d), 54241131bacSOleksij Rempel regmap_reg_range(0x2122, 0x2127), 54341131bacSOleksij Rempel regmap_reg_range(0x212a, 0x212b), 54441131bacSOleksij Rempel regmap_reg_range(0x2136, 0x2139), 54541131bacSOleksij Rempel regmap_reg_range(0x213e, 0x213f), 54641131bacSOleksij Rempel regmap_reg_range(0x2400, 0x2401), 54741131bacSOleksij Rempel regmap_reg_range(0x2403, 0x2403), 54841131bacSOleksij Rempel regmap_reg_range(0x2410, 0x2417), 54941131bacSOleksij Rempel regmap_reg_range(0x2420, 0x2423), 55041131bacSOleksij Rempel regmap_reg_range(0x2500, 0x2507), 55141131bacSOleksij Rempel regmap_reg_range(0x2600, 0x2612), 55241131bacSOleksij Rempel regmap_reg_range(0x2800, 0x280f), 55341131bacSOleksij Rempel regmap_reg_range(0x2900, 0x2907), 55441131bacSOleksij Rempel regmap_reg_range(0x2914, 0x291b), 55541131bacSOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 55641131bacSOleksij Rempel regmap_reg_range(0x2a04, 0x2a08), 55741131bacSOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 55841131bacSOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 55941131bacSOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 56041131bacSOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 56141131bacSOleksij Rempel 56241131bacSOleksij Rempel /* port 3 */ 56341131bacSOleksij Rempel regmap_reg_range(0x3000, 0x3001), 56441131bacSOleksij Rempel regmap_reg_range(0x3004, 0x300b), 56541131bacSOleksij Rempel regmap_reg_range(0x3013, 0x3013), 56641131bacSOleksij Rempel regmap_reg_range(0x3017, 0x3017), 56741131bacSOleksij Rempel regmap_reg_range(0x301b, 0x301b), 56841131bacSOleksij Rempel regmap_reg_range(0x301f, 0x3021), 56941131bacSOleksij Rempel regmap_reg_range(0x3030, 0x3030), 57041131bacSOleksij Rempel regmap_reg_range(0x3300, 0x3301), 57141131bacSOleksij Rempel regmap_reg_range(0x3303, 0x3303), 57241131bacSOleksij Rempel regmap_reg_range(0x3400, 0x3401), 57341131bacSOleksij Rempel regmap_reg_range(0x3403, 0x3403), 57441131bacSOleksij Rempel regmap_reg_range(0x3410, 0x3417), 57541131bacSOleksij Rempel regmap_reg_range(0x3420, 0x3423), 57641131bacSOleksij Rempel regmap_reg_range(0x3500, 0x3507), 57741131bacSOleksij Rempel regmap_reg_range(0x3600, 0x3612), 57841131bacSOleksij Rempel regmap_reg_range(0x3800, 0x380f), 57941131bacSOleksij Rempel regmap_reg_range(0x3900, 0x3907), 58041131bacSOleksij Rempel regmap_reg_range(0x3914, 0x391b), 58141131bacSOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 58241131bacSOleksij Rempel regmap_reg_range(0x3a04, 0x3a08), 58341131bacSOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 58441131bacSOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 58541131bacSOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 58641131bacSOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 58741131bacSOleksij Rempel }; 58841131bacSOleksij Rempel 58941131bacSOleksij Rempel static const struct regmap_access_table ksz8563_register_set = { 59041131bacSOleksij Rempel .yes_ranges = ksz8563_valid_regs, 59141131bacSOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs), 59241131bacSOleksij Rempel }; 59341131bacSOleksij Rempel 59474e792b5SOleksij Rempel static const struct regmap_range ksz9477_valid_regs[] = { 59574e792b5SOleksij Rempel regmap_reg_range(0x0000, 0x0003), 59674e792b5SOleksij Rempel regmap_reg_range(0x0006, 0x0006), 59774e792b5SOleksij Rempel regmap_reg_range(0x0010, 0x001f), 59874e792b5SOleksij Rempel regmap_reg_range(0x0100, 0x0100), 59974e792b5SOleksij Rempel regmap_reg_range(0x0103, 0x0107), 60074e792b5SOleksij Rempel regmap_reg_range(0x010d, 0x010d), 60174e792b5SOleksij Rempel regmap_reg_range(0x0110, 0x0113), 60274e792b5SOleksij Rempel regmap_reg_range(0x0120, 0x012b), 60374e792b5SOleksij Rempel regmap_reg_range(0x0201, 0x0201), 60474e792b5SOleksij Rempel regmap_reg_range(0x0210, 0x0213), 60574e792b5SOleksij Rempel regmap_reg_range(0x0300, 0x0300), 60674e792b5SOleksij Rempel regmap_reg_range(0x0302, 0x031b), 60774e792b5SOleksij Rempel regmap_reg_range(0x0320, 0x032b), 60874e792b5SOleksij Rempel regmap_reg_range(0x0330, 0x0336), 6093a8b8ea6SRomain Naour regmap_reg_range(0x0338, 0x033b), 6103a8b8ea6SRomain Naour regmap_reg_range(0x033e, 0x033e), 61174e792b5SOleksij Rempel regmap_reg_range(0x0340, 0x035f), 61274e792b5SOleksij Rempel regmap_reg_range(0x0370, 0x0370), 61374e792b5SOleksij Rempel regmap_reg_range(0x0378, 0x0378), 61474e792b5SOleksij Rempel regmap_reg_range(0x037c, 0x037d), 61574e792b5SOleksij Rempel regmap_reg_range(0x0390, 0x0393), 61674e792b5SOleksij Rempel regmap_reg_range(0x0400, 0x040e), 61774e792b5SOleksij Rempel regmap_reg_range(0x0410, 0x042f), 61874e792b5SOleksij Rempel regmap_reg_range(0x0444, 0x044b), 61974e792b5SOleksij Rempel regmap_reg_range(0x0450, 0x046f), 62074e792b5SOleksij Rempel regmap_reg_range(0x0500, 0x0519), 62174e792b5SOleksij Rempel regmap_reg_range(0x0520, 0x054b), 62274e792b5SOleksij Rempel regmap_reg_range(0x0550, 0x05b3), 62374e792b5SOleksij Rempel regmap_reg_range(0x0604, 0x060b), 62474e792b5SOleksij Rempel regmap_reg_range(0x0610, 0x0612), 62574e792b5SOleksij Rempel regmap_reg_range(0x0614, 0x062c), 62674e792b5SOleksij Rempel regmap_reg_range(0x0640, 0x0645), 62774e792b5SOleksij Rempel regmap_reg_range(0x0648, 0x064d), 62874e792b5SOleksij Rempel 62974e792b5SOleksij Rempel /* port 1 */ 63074e792b5SOleksij Rempel regmap_reg_range(0x1000, 0x1001), 63174e792b5SOleksij Rempel regmap_reg_range(0x1013, 0x1013), 63274e792b5SOleksij Rempel regmap_reg_range(0x1017, 0x1017), 63374e792b5SOleksij Rempel regmap_reg_range(0x101b, 0x101b), 63474e792b5SOleksij Rempel regmap_reg_range(0x101f, 0x1020), 63574e792b5SOleksij Rempel regmap_reg_range(0x1030, 0x1030), 63674e792b5SOleksij Rempel regmap_reg_range(0x1100, 0x1115), 63774e792b5SOleksij Rempel regmap_reg_range(0x111a, 0x111f), 63874e792b5SOleksij Rempel regmap_reg_range(0x1122, 0x1127), 63974e792b5SOleksij Rempel regmap_reg_range(0x112a, 0x112b), 64074e792b5SOleksij Rempel regmap_reg_range(0x1136, 0x1139), 64174e792b5SOleksij Rempel regmap_reg_range(0x113e, 0x113f), 64274e792b5SOleksij Rempel regmap_reg_range(0x1400, 0x1401), 64374e792b5SOleksij Rempel regmap_reg_range(0x1403, 0x1403), 64474e792b5SOleksij Rempel regmap_reg_range(0x1410, 0x1417), 64574e792b5SOleksij Rempel regmap_reg_range(0x1420, 0x1423), 64674e792b5SOleksij Rempel regmap_reg_range(0x1500, 0x1507), 64774e792b5SOleksij Rempel regmap_reg_range(0x1600, 0x1613), 64874e792b5SOleksij Rempel regmap_reg_range(0x1800, 0x180f), 64974e792b5SOleksij Rempel regmap_reg_range(0x1820, 0x1827), 65074e792b5SOleksij Rempel regmap_reg_range(0x1830, 0x1837), 65174e792b5SOleksij Rempel regmap_reg_range(0x1840, 0x184b), 65274e792b5SOleksij Rempel regmap_reg_range(0x1900, 0x1907), 65374e792b5SOleksij Rempel regmap_reg_range(0x1914, 0x191b), 65474e792b5SOleksij Rempel regmap_reg_range(0x1920, 0x1920), 65574e792b5SOleksij Rempel regmap_reg_range(0x1923, 0x1927), 65674e792b5SOleksij Rempel regmap_reg_range(0x1a00, 0x1a03), 65774e792b5SOleksij Rempel regmap_reg_range(0x1a04, 0x1a07), 65874e792b5SOleksij Rempel regmap_reg_range(0x1b00, 0x1b01), 65974e792b5SOleksij Rempel regmap_reg_range(0x1b04, 0x1b04), 66074e792b5SOleksij Rempel regmap_reg_range(0x1c00, 0x1c05), 66174e792b5SOleksij Rempel regmap_reg_range(0x1c08, 0x1c1b), 66274e792b5SOleksij Rempel 66374e792b5SOleksij Rempel /* port 2 */ 66474e792b5SOleksij Rempel regmap_reg_range(0x2000, 0x2001), 66574e792b5SOleksij Rempel regmap_reg_range(0x2013, 0x2013), 66674e792b5SOleksij Rempel regmap_reg_range(0x2017, 0x2017), 66774e792b5SOleksij Rempel regmap_reg_range(0x201b, 0x201b), 66874e792b5SOleksij Rempel regmap_reg_range(0x201f, 0x2020), 66974e792b5SOleksij Rempel regmap_reg_range(0x2030, 0x2030), 67074e792b5SOleksij Rempel regmap_reg_range(0x2100, 0x2115), 67174e792b5SOleksij Rempel regmap_reg_range(0x211a, 0x211f), 67274e792b5SOleksij Rempel regmap_reg_range(0x2122, 0x2127), 67374e792b5SOleksij Rempel regmap_reg_range(0x212a, 0x212b), 67474e792b5SOleksij Rempel regmap_reg_range(0x2136, 0x2139), 67574e792b5SOleksij Rempel regmap_reg_range(0x213e, 0x213f), 67674e792b5SOleksij Rempel regmap_reg_range(0x2400, 0x2401), 67774e792b5SOleksij Rempel regmap_reg_range(0x2403, 0x2403), 67874e792b5SOleksij Rempel regmap_reg_range(0x2410, 0x2417), 67974e792b5SOleksij Rempel regmap_reg_range(0x2420, 0x2423), 68074e792b5SOleksij Rempel regmap_reg_range(0x2500, 0x2507), 68174e792b5SOleksij Rempel regmap_reg_range(0x2600, 0x2613), 68274e792b5SOleksij Rempel regmap_reg_range(0x2800, 0x280f), 68374e792b5SOleksij Rempel regmap_reg_range(0x2820, 0x2827), 68474e792b5SOleksij Rempel regmap_reg_range(0x2830, 0x2837), 68574e792b5SOleksij Rempel regmap_reg_range(0x2840, 0x284b), 68674e792b5SOleksij Rempel regmap_reg_range(0x2900, 0x2907), 68774e792b5SOleksij Rempel regmap_reg_range(0x2914, 0x291b), 68874e792b5SOleksij Rempel regmap_reg_range(0x2920, 0x2920), 68974e792b5SOleksij Rempel regmap_reg_range(0x2923, 0x2927), 69074e792b5SOleksij Rempel regmap_reg_range(0x2a00, 0x2a03), 69174e792b5SOleksij Rempel regmap_reg_range(0x2a04, 0x2a07), 69274e792b5SOleksij Rempel regmap_reg_range(0x2b00, 0x2b01), 69374e792b5SOleksij Rempel regmap_reg_range(0x2b04, 0x2b04), 69474e792b5SOleksij Rempel regmap_reg_range(0x2c00, 0x2c05), 69574e792b5SOleksij Rempel regmap_reg_range(0x2c08, 0x2c1b), 69674e792b5SOleksij Rempel 69774e792b5SOleksij Rempel /* port 3 */ 69874e792b5SOleksij Rempel regmap_reg_range(0x3000, 0x3001), 69974e792b5SOleksij Rempel regmap_reg_range(0x3013, 0x3013), 70074e792b5SOleksij Rempel regmap_reg_range(0x3017, 0x3017), 70174e792b5SOleksij Rempel regmap_reg_range(0x301b, 0x301b), 70274e792b5SOleksij Rempel regmap_reg_range(0x301f, 0x3020), 70374e792b5SOleksij Rempel regmap_reg_range(0x3030, 0x3030), 70474e792b5SOleksij Rempel regmap_reg_range(0x3100, 0x3115), 70574e792b5SOleksij Rempel regmap_reg_range(0x311a, 0x311f), 70674e792b5SOleksij Rempel regmap_reg_range(0x3122, 0x3127), 70774e792b5SOleksij Rempel regmap_reg_range(0x312a, 0x312b), 70874e792b5SOleksij Rempel regmap_reg_range(0x3136, 0x3139), 70974e792b5SOleksij Rempel regmap_reg_range(0x313e, 0x313f), 71074e792b5SOleksij Rempel regmap_reg_range(0x3400, 0x3401), 71174e792b5SOleksij Rempel regmap_reg_range(0x3403, 0x3403), 71274e792b5SOleksij Rempel regmap_reg_range(0x3410, 0x3417), 71374e792b5SOleksij Rempel regmap_reg_range(0x3420, 0x3423), 71474e792b5SOleksij Rempel regmap_reg_range(0x3500, 0x3507), 71574e792b5SOleksij Rempel regmap_reg_range(0x3600, 0x3613), 71674e792b5SOleksij Rempel regmap_reg_range(0x3800, 0x380f), 71774e792b5SOleksij Rempel regmap_reg_range(0x3820, 0x3827), 71874e792b5SOleksij Rempel regmap_reg_range(0x3830, 0x3837), 71974e792b5SOleksij Rempel regmap_reg_range(0x3840, 0x384b), 72074e792b5SOleksij Rempel regmap_reg_range(0x3900, 0x3907), 72174e792b5SOleksij Rempel regmap_reg_range(0x3914, 0x391b), 72274e792b5SOleksij Rempel regmap_reg_range(0x3920, 0x3920), 72374e792b5SOleksij Rempel regmap_reg_range(0x3923, 0x3927), 72474e792b5SOleksij Rempel regmap_reg_range(0x3a00, 0x3a03), 72574e792b5SOleksij Rempel regmap_reg_range(0x3a04, 0x3a07), 72674e792b5SOleksij Rempel regmap_reg_range(0x3b00, 0x3b01), 72774e792b5SOleksij Rempel regmap_reg_range(0x3b04, 0x3b04), 72874e792b5SOleksij Rempel regmap_reg_range(0x3c00, 0x3c05), 72974e792b5SOleksij Rempel regmap_reg_range(0x3c08, 0x3c1b), 73074e792b5SOleksij Rempel 73174e792b5SOleksij Rempel /* port 4 */ 73274e792b5SOleksij Rempel regmap_reg_range(0x4000, 0x4001), 73374e792b5SOleksij Rempel regmap_reg_range(0x4013, 0x4013), 73474e792b5SOleksij Rempel regmap_reg_range(0x4017, 0x4017), 73574e792b5SOleksij Rempel regmap_reg_range(0x401b, 0x401b), 73674e792b5SOleksij Rempel regmap_reg_range(0x401f, 0x4020), 73774e792b5SOleksij Rempel regmap_reg_range(0x4030, 0x4030), 73874e792b5SOleksij Rempel regmap_reg_range(0x4100, 0x4115), 73974e792b5SOleksij Rempel regmap_reg_range(0x411a, 0x411f), 74074e792b5SOleksij Rempel regmap_reg_range(0x4122, 0x4127), 74174e792b5SOleksij Rempel regmap_reg_range(0x412a, 0x412b), 74274e792b5SOleksij Rempel regmap_reg_range(0x4136, 0x4139), 74374e792b5SOleksij Rempel regmap_reg_range(0x413e, 0x413f), 74474e792b5SOleksij Rempel regmap_reg_range(0x4400, 0x4401), 74574e792b5SOleksij Rempel regmap_reg_range(0x4403, 0x4403), 74674e792b5SOleksij Rempel regmap_reg_range(0x4410, 0x4417), 74774e792b5SOleksij Rempel regmap_reg_range(0x4420, 0x4423), 74874e792b5SOleksij Rempel regmap_reg_range(0x4500, 0x4507), 74974e792b5SOleksij Rempel regmap_reg_range(0x4600, 0x4613), 75074e792b5SOleksij Rempel regmap_reg_range(0x4800, 0x480f), 75174e792b5SOleksij Rempel regmap_reg_range(0x4820, 0x4827), 75274e792b5SOleksij Rempel regmap_reg_range(0x4830, 0x4837), 75374e792b5SOleksij Rempel regmap_reg_range(0x4840, 0x484b), 75474e792b5SOleksij Rempel regmap_reg_range(0x4900, 0x4907), 75574e792b5SOleksij Rempel regmap_reg_range(0x4914, 0x491b), 75674e792b5SOleksij Rempel regmap_reg_range(0x4920, 0x4920), 75774e792b5SOleksij Rempel regmap_reg_range(0x4923, 0x4927), 75874e792b5SOleksij Rempel regmap_reg_range(0x4a00, 0x4a03), 75974e792b5SOleksij Rempel regmap_reg_range(0x4a04, 0x4a07), 76074e792b5SOleksij Rempel regmap_reg_range(0x4b00, 0x4b01), 76174e792b5SOleksij Rempel regmap_reg_range(0x4b04, 0x4b04), 76274e792b5SOleksij Rempel regmap_reg_range(0x4c00, 0x4c05), 76374e792b5SOleksij Rempel regmap_reg_range(0x4c08, 0x4c1b), 76474e792b5SOleksij Rempel 76574e792b5SOleksij Rempel /* port 5 */ 76674e792b5SOleksij Rempel regmap_reg_range(0x5000, 0x5001), 76774e792b5SOleksij Rempel regmap_reg_range(0x5013, 0x5013), 76874e792b5SOleksij Rempel regmap_reg_range(0x5017, 0x5017), 76974e792b5SOleksij Rempel regmap_reg_range(0x501b, 0x501b), 77074e792b5SOleksij Rempel regmap_reg_range(0x501f, 0x5020), 77174e792b5SOleksij Rempel regmap_reg_range(0x5030, 0x5030), 77274e792b5SOleksij Rempel regmap_reg_range(0x5100, 0x5115), 77374e792b5SOleksij Rempel regmap_reg_range(0x511a, 0x511f), 77474e792b5SOleksij Rempel regmap_reg_range(0x5122, 0x5127), 77574e792b5SOleksij Rempel regmap_reg_range(0x512a, 0x512b), 77674e792b5SOleksij Rempel regmap_reg_range(0x5136, 0x5139), 77774e792b5SOleksij Rempel regmap_reg_range(0x513e, 0x513f), 77874e792b5SOleksij Rempel regmap_reg_range(0x5400, 0x5401), 77974e792b5SOleksij Rempel regmap_reg_range(0x5403, 0x5403), 78074e792b5SOleksij Rempel regmap_reg_range(0x5410, 0x5417), 78174e792b5SOleksij Rempel regmap_reg_range(0x5420, 0x5423), 78274e792b5SOleksij Rempel regmap_reg_range(0x5500, 0x5507), 78374e792b5SOleksij Rempel regmap_reg_range(0x5600, 0x5613), 78474e792b5SOleksij Rempel regmap_reg_range(0x5800, 0x580f), 78574e792b5SOleksij Rempel regmap_reg_range(0x5820, 0x5827), 78674e792b5SOleksij Rempel regmap_reg_range(0x5830, 0x5837), 78774e792b5SOleksij Rempel regmap_reg_range(0x5840, 0x584b), 78874e792b5SOleksij Rempel regmap_reg_range(0x5900, 0x5907), 78974e792b5SOleksij Rempel regmap_reg_range(0x5914, 0x591b), 79074e792b5SOleksij Rempel regmap_reg_range(0x5920, 0x5920), 79174e792b5SOleksij Rempel regmap_reg_range(0x5923, 0x5927), 79274e792b5SOleksij Rempel regmap_reg_range(0x5a00, 0x5a03), 79374e792b5SOleksij Rempel regmap_reg_range(0x5a04, 0x5a07), 79474e792b5SOleksij Rempel regmap_reg_range(0x5b00, 0x5b01), 79574e792b5SOleksij Rempel regmap_reg_range(0x5b04, 0x5b04), 79674e792b5SOleksij Rempel regmap_reg_range(0x5c00, 0x5c05), 79774e792b5SOleksij Rempel regmap_reg_range(0x5c08, 0x5c1b), 79874e792b5SOleksij Rempel 79974e792b5SOleksij Rempel /* port 6 */ 80074e792b5SOleksij Rempel regmap_reg_range(0x6000, 0x6001), 80174e792b5SOleksij Rempel regmap_reg_range(0x6013, 0x6013), 80274e792b5SOleksij Rempel regmap_reg_range(0x6017, 0x6017), 80374e792b5SOleksij Rempel regmap_reg_range(0x601b, 0x601b), 80474e792b5SOleksij Rempel regmap_reg_range(0x601f, 0x6020), 80574e792b5SOleksij Rempel regmap_reg_range(0x6030, 0x6030), 80674e792b5SOleksij Rempel regmap_reg_range(0x6300, 0x6301), 80774e792b5SOleksij Rempel regmap_reg_range(0x6400, 0x6401), 80874e792b5SOleksij Rempel regmap_reg_range(0x6403, 0x6403), 80974e792b5SOleksij Rempel regmap_reg_range(0x6410, 0x6417), 81074e792b5SOleksij Rempel regmap_reg_range(0x6420, 0x6423), 81174e792b5SOleksij Rempel regmap_reg_range(0x6500, 0x6507), 81274e792b5SOleksij Rempel regmap_reg_range(0x6600, 0x6613), 81374e792b5SOleksij Rempel regmap_reg_range(0x6800, 0x680f), 81474e792b5SOleksij Rempel regmap_reg_range(0x6820, 0x6827), 81574e792b5SOleksij Rempel regmap_reg_range(0x6830, 0x6837), 81674e792b5SOleksij Rempel regmap_reg_range(0x6840, 0x684b), 81774e792b5SOleksij Rempel regmap_reg_range(0x6900, 0x6907), 81874e792b5SOleksij Rempel regmap_reg_range(0x6914, 0x691b), 81974e792b5SOleksij Rempel regmap_reg_range(0x6920, 0x6920), 82074e792b5SOleksij Rempel regmap_reg_range(0x6923, 0x6927), 82174e792b5SOleksij Rempel regmap_reg_range(0x6a00, 0x6a03), 82274e792b5SOleksij Rempel regmap_reg_range(0x6a04, 0x6a07), 82374e792b5SOleksij Rempel regmap_reg_range(0x6b00, 0x6b01), 82474e792b5SOleksij Rempel regmap_reg_range(0x6b04, 0x6b04), 82574e792b5SOleksij Rempel regmap_reg_range(0x6c00, 0x6c05), 82674e792b5SOleksij Rempel regmap_reg_range(0x6c08, 0x6c1b), 82774e792b5SOleksij Rempel 82874e792b5SOleksij Rempel /* port 7 */ 82974e792b5SOleksij Rempel regmap_reg_range(0x7000, 0x7001), 83074e792b5SOleksij Rempel regmap_reg_range(0x7013, 0x7013), 83174e792b5SOleksij Rempel regmap_reg_range(0x7017, 0x7017), 83274e792b5SOleksij Rempel regmap_reg_range(0x701b, 0x701b), 83374e792b5SOleksij Rempel regmap_reg_range(0x701f, 0x7020), 83474e792b5SOleksij Rempel regmap_reg_range(0x7030, 0x7030), 83574e792b5SOleksij Rempel regmap_reg_range(0x7200, 0x7203), 83674e792b5SOleksij Rempel regmap_reg_range(0x7206, 0x7207), 83774e792b5SOleksij Rempel regmap_reg_range(0x7300, 0x7301), 83874e792b5SOleksij Rempel regmap_reg_range(0x7400, 0x7401), 83974e792b5SOleksij Rempel regmap_reg_range(0x7403, 0x7403), 84074e792b5SOleksij Rempel regmap_reg_range(0x7410, 0x7417), 84174e792b5SOleksij Rempel regmap_reg_range(0x7420, 0x7423), 84274e792b5SOleksij Rempel regmap_reg_range(0x7500, 0x7507), 84374e792b5SOleksij Rempel regmap_reg_range(0x7600, 0x7613), 84474e792b5SOleksij Rempel regmap_reg_range(0x7800, 0x780f), 84574e792b5SOleksij Rempel regmap_reg_range(0x7820, 0x7827), 84674e792b5SOleksij Rempel regmap_reg_range(0x7830, 0x7837), 84774e792b5SOleksij Rempel regmap_reg_range(0x7840, 0x784b), 84874e792b5SOleksij Rempel regmap_reg_range(0x7900, 0x7907), 84974e792b5SOleksij Rempel regmap_reg_range(0x7914, 0x791b), 85074e792b5SOleksij Rempel regmap_reg_range(0x7920, 0x7920), 85174e792b5SOleksij Rempel regmap_reg_range(0x7923, 0x7927), 85274e792b5SOleksij Rempel regmap_reg_range(0x7a00, 0x7a03), 85374e792b5SOleksij Rempel regmap_reg_range(0x7a04, 0x7a07), 85474e792b5SOleksij Rempel regmap_reg_range(0x7b00, 0x7b01), 85574e792b5SOleksij Rempel regmap_reg_range(0x7b04, 0x7b04), 85674e792b5SOleksij Rempel regmap_reg_range(0x7c00, 0x7c05), 85774e792b5SOleksij Rempel regmap_reg_range(0x7c08, 0x7c1b), 85874e792b5SOleksij Rempel }; 85974e792b5SOleksij Rempel 86074e792b5SOleksij Rempel static const struct regmap_access_table ksz9477_register_set = { 86174e792b5SOleksij Rempel .yes_ranges = ksz9477_valid_regs, 86274e792b5SOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs), 86374e792b5SOleksij Rempel }; 86474e792b5SOleksij Rempel 8656674e7fdSRomain Naour static const struct regmap_range ksz9896_valid_regs[] = { 8666674e7fdSRomain Naour regmap_reg_range(0x0000, 0x0003), 8676674e7fdSRomain Naour regmap_reg_range(0x0006, 0x0006), 8686674e7fdSRomain Naour regmap_reg_range(0x0010, 0x001f), 8696674e7fdSRomain Naour regmap_reg_range(0x0100, 0x0100), 8706674e7fdSRomain Naour regmap_reg_range(0x0103, 0x0107), 8716674e7fdSRomain Naour regmap_reg_range(0x010d, 0x010d), 8726674e7fdSRomain Naour regmap_reg_range(0x0110, 0x0113), 8736674e7fdSRomain Naour regmap_reg_range(0x0120, 0x0127), 8746674e7fdSRomain Naour regmap_reg_range(0x0201, 0x0201), 8756674e7fdSRomain Naour regmap_reg_range(0x0210, 0x0213), 8766674e7fdSRomain Naour regmap_reg_range(0x0300, 0x0300), 8776674e7fdSRomain Naour regmap_reg_range(0x0302, 0x030b), 8786674e7fdSRomain Naour regmap_reg_range(0x0310, 0x031b), 8796674e7fdSRomain Naour regmap_reg_range(0x0320, 0x032b), 8806674e7fdSRomain Naour regmap_reg_range(0x0330, 0x0336), 8816674e7fdSRomain Naour regmap_reg_range(0x0338, 0x033b), 8826674e7fdSRomain Naour regmap_reg_range(0x033e, 0x033e), 8836674e7fdSRomain Naour regmap_reg_range(0x0340, 0x035f), 8846674e7fdSRomain Naour regmap_reg_range(0x0370, 0x0370), 8856674e7fdSRomain Naour regmap_reg_range(0x0378, 0x0378), 8866674e7fdSRomain Naour regmap_reg_range(0x037c, 0x037d), 8876674e7fdSRomain Naour regmap_reg_range(0x0390, 0x0393), 8886674e7fdSRomain Naour regmap_reg_range(0x0400, 0x040e), 8896674e7fdSRomain Naour regmap_reg_range(0x0410, 0x042f), 8906674e7fdSRomain Naour 8916674e7fdSRomain Naour /* port 1 */ 8926674e7fdSRomain Naour regmap_reg_range(0x1000, 0x1001), 8936674e7fdSRomain Naour regmap_reg_range(0x1013, 0x1013), 8946674e7fdSRomain Naour regmap_reg_range(0x1017, 0x1017), 8956674e7fdSRomain Naour regmap_reg_range(0x101b, 0x101b), 8966674e7fdSRomain Naour regmap_reg_range(0x101f, 0x1020), 8976674e7fdSRomain Naour regmap_reg_range(0x1030, 0x1030), 8986674e7fdSRomain Naour regmap_reg_range(0x1100, 0x1115), 8996674e7fdSRomain Naour regmap_reg_range(0x111a, 0x111f), 9006674e7fdSRomain Naour regmap_reg_range(0x1122, 0x1127), 9016674e7fdSRomain Naour regmap_reg_range(0x112a, 0x112b), 9026674e7fdSRomain Naour regmap_reg_range(0x1136, 0x1139), 9036674e7fdSRomain Naour regmap_reg_range(0x113e, 0x113f), 9046674e7fdSRomain Naour regmap_reg_range(0x1400, 0x1401), 9056674e7fdSRomain Naour regmap_reg_range(0x1403, 0x1403), 9066674e7fdSRomain Naour regmap_reg_range(0x1410, 0x1417), 9076674e7fdSRomain Naour regmap_reg_range(0x1420, 0x1423), 9086674e7fdSRomain Naour regmap_reg_range(0x1500, 0x1507), 9096674e7fdSRomain Naour regmap_reg_range(0x1600, 0x1612), 9106674e7fdSRomain Naour regmap_reg_range(0x1800, 0x180f), 9116674e7fdSRomain Naour regmap_reg_range(0x1820, 0x1827), 9126674e7fdSRomain Naour regmap_reg_range(0x1830, 0x1837), 9136674e7fdSRomain Naour regmap_reg_range(0x1840, 0x184b), 9146674e7fdSRomain Naour regmap_reg_range(0x1900, 0x1907), 9156674e7fdSRomain Naour regmap_reg_range(0x1914, 0x1915), 9166674e7fdSRomain Naour regmap_reg_range(0x1a00, 0x1a03), 9176674e7fdSRomain Naour regmap_reg_range(0x1a04, 0x1a07), 9186674e7fdSRomain Naour regmap_reg_range(0x1b00, 0x1b01), 9196674e7fdSRomain Naour regmap_reg_range(0x1b04, 0x1b04), 9206674e7fdSRomain Naour 9216674e7fdSRomain Naour /* port 2 */ 9226674e7fdSRomain Naour regmap_reg_range(0x2000, 0x2001), 9236674e7fdSRomain Naour regmap_reg_range(0x2013, 0x2013), 9246674e7fdSRomain Naour regmap_reg_range(0x2017, 0x2017), 9256674e7fdSRomain Naour regmap_reg_range(0x201b, 0x201b), 9266674e7fdSRomain Naour regmap_reg_range(0x201f, 0x2020), 9276674e7fdSRomain Naour regmap_reg_range(0x2030, 0x2030), 9286674e7fdSRomain Naour regmap_reg_range(0x2100, 0x2115), 9296674e7fdSRomain Naour regmap_reg_range(0x211a, 0x211f), 9306674e7fdSRomain Naour regmap_reg_range(0x2122, 0x2127), 9316674e7fdSRomain Naour regmap_reg_range(0x212a, 0x212b), 9326674e7fdSRomain Naour regmap_reg_range(0x2136, 0x2139), 9336674e7fdSRomain Naour regmap_reg_range(0x213e, 0x213f), 9346674e7fdSRomain Naour regmap_reg_range(0x2400, 0x2401), 9356674e7fdSRomain Naour regmap_reg_range(0x2403, 0x2403), 9366674e7fdSRomain Naour regmap_reg_range(0x2410, 0x2417), 9376674e7fdSRomain Naour regmap_reg_range(0x2420, 0x2423), 9386674e7fdSRomain Naour regmap_reg_range(0x2500, 0x2507), 9396674e7fdSRomain Naour regmap_reg_range(0x2600, 0x2612), 9406674e7fdSRomain Naour regmap_reg_range(0x2800, 0x280f), 9416674e7fdSRomain Naour regmap_reg_range(0x2820, 0x2827), 9426674e7fdSRomain Naour regmap_reg_range(0x2830, 0x2837), 9436674e7fdSRomain Naour regmap_reg_range(0x2840, 0x284b), 9446674e7fdSRomain Naour regmap_reg_range(0x2900, 0x2907), 9456674e7fdSRomain Naour regmap_reg_range(0x2914, 0x2915), 9466674e7fdSRomain Naour regmap_reg_range(0x2a00, 0x2a03), 9476674e7fdSRomain Naour regmap_reg_range(0x2a04, 0x2a07), 9486674e7fdSRomain Naour regmap_reg_range(0x2b00, 0x2b01), 9496674e7fdSRomain Naour regmap_reg_range(0x2b04, 0x2b04), 9506674e7fdSRomain Naour 9516674e7fdSRomain Naour /* port 3 */ 9526674e7fdSRomain Naour regmap_reg_range(0x3000, 0x3001), 9536674e7fdSRomain Naour regmap_reg_range(0x3013, 0x3013), 9546674e7fdSRomain Naour regmap_reg_range(0x3017, 0x3017), 9556674e7fdSRomain Naour regmap_reg_range(0x301b, 0x301b), 9566674e7fdSRomain Naour regmap_reg_range(0x301f, 0x3020), 9576674e7fdSRomain Naour regmap_reg_range(0x3030, 0x3030), 9586674e7fdSRomain Naour regmap_reg_range(0x3100, 0x3115), 9596674e7fdSRomain Naour regmap_reg_range(0x311a, 0x311f), 9606674e7fdSRomain Naour regmap_reg_range(0x3122, 0x3127), 9616674e7fdSRomain Naour regmap_reg_range(0x312a, 0x312b), 9626674e7fdSRomain Naour regmap_reg_range(0x3136, 0x3139), 9636674e7fdSRomain Naour regmap_reg_range(0x313e, 0x313f), 9646674e7fdSRomain Naour regmap_reg_range(0x3400, 0x3401), 9656674e7fdSRomain Naour regmap_reg_range(0x3403, 0x3403), 9666674e7fdSRomain Naour regmap_reg_range(0x3410, 0x3417), 9676674e7fdSRomain Naour regmap_reg_range(0x3420, 0x3423), 9686674e7fdSRomain Naour regmap_reg_range(0x3500, 0x3507), 9696674e7fdSRomain Naour regmap_reg_range(0x3600, 0x3612), 9706674e7fdSRomain Naour regmap_reg_range(0x3800, 0x380f), 9716674e7fdSRomain Naour regmap_reg_range(0x3820, 0x3827), 9726674e7fdSRomain Naour regmap_reg_range(0x3830, 0x3837), 9736674e7fdSRomain Naour regmap_reg_range(0x3840, 0x384b), 9746674e7fdSRomain Naour regmap_reg_range(0x3900, 0x3907), 9756674e7fdSRomain Naour regmap_reg_range(0x3914, 0x3915), 9766674e7fdSRomain Naour regmap_reg_range(0x3a00, 0x3a03), 9776674e7fdSRomain Naour regmap_reg_range(0x3a04, 0x3a07), 9786674e7fdSRomain Naour regmap_reg_range(0x3b00, 0x3b01), 9796674e7fdSRomain Naour regmap_reg_range(0x3b04, 0x3b04), 9806674e7fdSRomain Naour 9816674e7fdSRomain Naour /* port 4 */ 9826674e7fdSRomain Naour regmap_reg_range(0x4000, 0x4001), 9836674e7fdSRomain Naour regmap_reg_range(0x4013, 0x4013), 9846674e7fdSRomain Naour regmap_reg_range(0x4017, 0x4017), 9856674e7fdSRomain Naour regmap_reg_range(0x401b, 0x401b), 9866674e7fdSRomain Naour regmap_reg_range(0x401f, 0x4020), 9876674e7fdSRomain Naour regmap_reg_range(0x4030, 0x4030), 9886674e7fdSRomain Naour regmap_reg_range(0x4100, 0x4115), 9896674e7fdSRomain Naour regmap_reg_range(0x411a, 0x411f), 9906674e7fdSRomain Naour regmap_reg_range(0x4122, 0x4127), 9916674e7fdSRomain Naour regmap_reg_range(0x412a, 0x412b), 9926674e7fdSRomain Naour regmap_reg_range(0x4136, 0x4139), 9936674e7fdSRomain Naour regmap_reg_range(0x413e, 0x413f), 9946674e7fdSRomain Naour regmap_reg_range(0x4400, 0x4401), 9956674e7fdSRomain Naour regmap_reg_range(0x4403, 0x4403), 9966674e7fdSRomain Naour regmap_reg_range(0x4410, 0x4417), 9976674e7fdSRomain Naour regmap_reg_range(0x4420, 0x4423), 9986674e7fdSRomain Naour regmap_reg_range(0x4500, 0x4507), 9996674e7fdSRomain Naour regmap_reg_range(0x4600, 0x4612), 10006674e7fdSRomain Naour regmap_reg_range(0x4800, 0x480f), 10016674e7fdSRomain Naour regmap_reg_range(0x4820, 0x4827), 10026674e7fdSRomain Naour regmap_reg_range(0x4830, 0x4837), 10036674e7fdSRomain Naour regmap_reg_range(0x4840, 0x484b), 10046674e7fdSRomain Naour regmap_reg_range(0x4900, 0x4907), 10056674e7fdSRomain Naour regmap_reg_range(0x4914, 0x4915), 10066674e7fdSRomain Naour regmap_reg_range(0x4a00, 0x4a03), 10076674e7fdSRomain Naour regmap_reg_range(0x4a04, 0x4a07), 10086674e7fdSRomain Naour regmap_reg_range(0x4b00, 0x4b01), 10096674e7fdSRomain Naour regmap_reg_range(0x4b04, 0x4b04), 10106674e7fdSRomain Naour 10116674e7fdSRomain Naour /* port 5 */ 10126674e7fdSRomain Naour regmap_reg_range(0x5000, 0x5001), 10136674e7fdSRomain Naour regmap_reg_range(0x5013, 0x5013), 10146674e7fdSRomain Naour regmap_reg_range(0x5017, 0x5017), 10156674e7fdSRomain Naour regmap_reg_range(0x501b, 0x501b), 10166674e7fdSRomain Naour regmap_reg_range(0x501f, 0x5020), 10176674e7fdSRomain Naour regmap_reg_range(0x5030, 0x5030), 10186674e7fdSRomain Naour regmap_reg_range(0x5100, 0x5115), 10196674e7fdSRomain Naour regmap_reg_range(0x511a, 0x511f), 10206674e7fdSRomain Naour regmap_reg_range(0x5122, 0x5127), 10216674e7fdSRomain Naour regmap_reg_range(0x512a, 0x512b), 10226674e7fdSRomain Naour regmap_reg_range(0x5136, 0x5139), 10236674e7fdSRomain Naour regmap_reg_range(0x513e, 0x513f), 10246674e7fdSRomain Naour regmap_reg_range(0x5400, 0x5401), 10256674e7fdSRomain Naour regmap_reg_range(0x5403, 0x5403), 10266674e7fdSRomain Naour regmap_reg_range(0x5410, 0x5417), 10276674e7fdSRomain Naour regmap_reg_range(0x5420, 0x5423), 10286674e7fdSRomain Naour regmap_reg_range(0x5500, 0x5507), 10296674e7fdSRomain Naour regmap_reg_range(0x5600, 0x5612), 10306674e7fdSRomain Naour regmap_reg_range(0x5800, 0x580f), 10316674e7fdSRomain Naour regmap_reg_range(0x5820, 0x5827), 10326674e7fdSRomain Naour regmap_reg_range(0x5830, 0x5837), 10336674e7fdSRomain Naour regmap_reg_range(0x5840, 0x584b), 10346674e7fdSRomain Naour regmap_reg_range(0x5900, 0x5907), 10356674e7fdSRomain Naour regmap_reg_range(0x5914, 0x5915), 10366674e7fdSRomain Naour regmap_reg_range(0x5a00, 0x5a03), 10376674e7fdSRomain Naour regmap_reg_range(0x5a04, 0x5a07), 10386674e7fdSRomain Naour regmap_reg_range(0x5b00, 0x5b01), 10396674e7fdSRomain Naour regmap_reg_range(0x5b04, 0x5b04), 10406674e7fdSRomain Naour 10416674e7fdSRomain Naour /* port 6 */ 10426674e7fdSRomain Naour regmap_reg_range(0x6000, 0x6001), 10436674e7fdSRomain Naour regmap_reg_range(0x6013, 0x6013), 10446674e7fdSRomain Naour regmap_reg_range(0x6017, 0x6017), 10456674e7fdSRomain Naour regmap_reg_range(0x601b, 0x601b), 10466674e7fdSRomain Naour regmap_reg_range(0x601f, 0x6020), 10476674e7fdSRomain Naour regmap_reg_range(0x6030, 0x6030), 10486674e7fdSRomain Naour regmap_reg_range(0x6100, 0x6115), 10496674e7fdSRomain Naour regmap_reg_range(0x611a, 0x611f), 10506674e7fdSRomain Naour regmap_reg_range(0x6122, 0x6127), 10516674e7fdSRomain Naour regmap_reg_range(0x612a, 0x612b), 10526674e7fdSRomain Naour regmap_reg_range(0x6136, 0x6139), 10536674e7fdSRomain Naour regmap_reg_range(0x613e, 0x613f), 10546674e7fdSRomain Naour regmap_reg_range(0x6300, 0x6301), 10556674e7fdSRomain Naour regmap_reg_range(0x6400, 0x6401), 10566674e7fdSRomain Naour regmap_reg_range(0x6403, 0x6403), 10576674e7fdSRomain Naour regmap_reg_range(0x6410, 0x6417), 10586674e7fdSRomain Naour regmap_reg_range(0x6420, 0x6423), 10596674e7fdSRomain Naour regmap_reg_range(0x6500, 0x6507), 10606674e7fdSRomain Naour regmap_reg_range(0x6600, 0x6612), 10616674e7fdSRomain Naour regmap_reg_range(0x6800, 0x680f), 10626674e7fdSRomain Naour regmap_reg_range(0x6820, 0x6827), 10636674e7fdSRomain Naour regmap_reg_range(0x6830, 0x6837), 10646674e7fdSRomain Naour regmap_reg_range(0x6840, 0x684b), 10656674e7fdSRomain Naour regmap_reg_range(0x6900, 0x6907), 10666674e7fdSRomain Naour regmap_reg_range(0x6914, 0x6915), 10676674e7fdSRomain Naour regmap_reg_range(0x6a00, 0x6a03), 10686674e7fdSRomain Naour regmap_reg_range(0x6a04, 0x6a07), 10696674e7fdSRomain Naour regmap_reg_range(0x6b00, 0x6b01), 10706674e7fdSRomain Naour regmap_reg_range(0x6b04, 0x6b04), 10716674e7fdSRomain Naour }; 10726674e7fdSRomain Naour 10736674e7fdSRomain Naour static const struct regmap_access_table ksz9896_register_set = { 10746674e7fdSRomain Naour .yes_ranges = ksz9896_valid_regs, 10756674e7fdSRomain Naour .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs), 10766674e7fdSRomain Naour }; 10776674e7fdSRomain Naour 1078d0dec333SOleksij Rempel static const struct regmap_range ksz8873_valid_regs[] = { 1079d0dec333SOleksij Rempel regmap_reg_range(0x00, 0x01), 1080d0dec333SOleksij Rempel /* global control register */ 1081d0dec333SOleksij Rempel regmap_reg_range(0x02, 0x0f), 1082d0dec333SOleksij Rempel 1083d0dec333SOleksij Rempel /* port registers */ 1084d0dec333SOleksij Rempel regmap_reg_range(0x10, 0x1d), 1085d0dec333SOleksij Rempel regmap_reg_range(0x1e, 0x1f), 1086d0dec333SOleksij Rempel regmap_reg_range(0x20, 0x2d), 1087d0dec333SOleksij Rempel regmap_reg_range(0x2e, 0x2f), 1088d0dec333SOleksij Rempel regmap_reg_range(0x30, 0x39), 1089d0dec333SOleksij Rempel regmap_reg_range(0x3f, 0x3f), 1090d0dec333SOleksij Rempel 1091d0dec333SOleksij Rempel /* advanced control registers */ 1092d0dec333SOleksij Rempel regmap_reg_range(0x60, 0x6f), 1093d0dec333SOleksij Rempel regmap_reg_range(0x70, 0x75), 1094d0dec333SOleksij Rempel regmap_reg_range(0x76, 0x78), 1095d0dec333SOleksij Rempel regmap_reg_range(0x79, 0x7a), 1096d0dec333SOleksij Rempel regmap_reg_range(0x7b, 0x83), 1097d0dec333SOleksij Rempel regmap_reg_range(0x8e, 0x99), 1098d0dec333SOleksij Rempel regmap_reg_range(0x9a, 0xa5), 1099d0dec333SOleksij Rempel regmap_reg_range(0xa6, 0xa6), 1100d0dec333SOleksij Rempel regmap_reg_range(0xa7, 0xaa), 1101d0dec333SOleksij Rempel regmap_reg_range(0xab, 0xae), 1102d0dec333SOleksij Rempel regmap_reg_range(0xaf, 0xba), 1103d0dec333SOleksij Rempel regmap_reg_range(0xbb, 0xbc), 1104d0dec333SOleksij Rempel regmap_reg_range(0xbd, 0xbd), 1105d0dec333SOleksij Rempel regmap_reg_range(0xc0, 0xc0), 1106d0dec333SOleksij Rempel regmap_reg_range(0xc2, 0xc2), 1107d0dec333SOleksij Rempel regmap_reg_range(0xc3, 0xc3), 1108d0dec333SOleksij Rempel regmap_reg_range(0xc4, 0xc4), 1109d0dec333SOleksij Rempel regmap_reg_range(0xc6, 0xc6), 1110d0dec333SOleksij Rempel }; 1111d0dec333SOleksij Rempel 1112d0dec333SOleksij Rempel static const struct regmap_access_table ksz8873_register_set = { 1113d0dec333SOleksij Rempel .yes_ranges = ksz8873_valid_regs, 1114d0dec333SOleksij Rempel .n_yes_ranges = ARRAY_SIZE(ksz8873_valid_regs), 1115d0dec333SOleksij Rempel }; 1116d0dec333SOleksij Rempel 1117eee16b14SArun Ramadoss const struct ksz_chip_data ksz_switch_chips[] = { 1118b4490809SOleksij Rempel [KSZ8563] = { 1119b4490809SOleksij Rempel .chip_id = KSZ8563_CHIP_ID, 1120b4490809SOleksij Rempel .dev_name = "KSZ8563", 1121b4490809SOleksij Rempel .num_vlans = 4096, 1122b4490809SOleksij Rempel .num_alus = 4096, 1123b4490809SOleksij Rempel .num_statics = 16, 1124b4490809SOleksij Rempel .cpu_ports = 0x07, /* can be configured as cpu port */ 1125b4490809SOleksij Rempel .port_cnt = 3, /* total port count */ 11264630d142SRakesh Sankaranarayanan .port_nirqs = 3, 1127e30f33a5SArun Ramadoss .num_tx_queues = 4, 112871d7920fSArun Ramadoss .tc_cbs_supported = true, 1129c570f861SOleksij Rempel .tc_ets_supported = true, 1130b4490809SOleksij Rempel .ops = &ksz9477_dev_ops, 1131b4490809SOleksij Rempel .mib_names = ksz9477_mib_names, 1132b4490809SOleksij Rempel .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1133b4490809SOleksij Rempel .reg_mib_cnt = MIB_COUNTER_NUM, 1134b4490809SOleksij Rempel .regs = ksz9477_regs, 1135b4490809SOleksij Rempel .masks = ksz9477_masks, 1136b4490809SOleksij Rempel .shifts = ksz9477_shifts, 1137b4490809SOleksij Rempel .xmii_ctrl0 = ksz9477_xmii_ctrl0, 1138b4490809SOleksij Rempel .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 1139b4490809SOleksij Rempel .supports_mii = {false, false, true}, 1140b4490809SOleksij Rempel .supports_rmii = {false, false, true}, 1141b4490809SOleksij Rempel .supports_rgmii = {false, false, true}, 1142b4490809SOleksij Rempel .internal_phy = {true, true, false}, 1143505bf320SOleksij Rempel .gbit_capable = {false, false, true}, 114441131bacSOleksij Rempel .wr_table = &ksz8563_register_set, 114541131bacSOleksij Rempel .rd_table = &ksz8563_register_set, 1146b4490809SOleksij Rempel }, 1147b4490809SOleksij Rempel 1148462d5250SArun Ramadoss [KSZ8795] = { 1149462d5250SArun Ramadoss .chip_id = KSZ8795_CHIP_ID, 1150462d5250SArun Ramadoss .dev_name = "KSZ8795", 1151462d5250SArun Ramadoss .num_vlans = 4096, 1152462d5250SArun Ramadoss .num_alus = 0, 1153462d5250SArun Ramadoss .num_statics = 8, 1154462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1155462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1156e30f33a5SArun Ramadoss .num_tx_queues = 4, 11576ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1158462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1159a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1160a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1161a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1162486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1163d23a5e18SArun Ramadoss .masks = ksz8795_masks, 116434e48383SArun Ramadoss .shifts = ksz8795_shifts, 1165aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 116646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 116765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 116865ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 116965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 117065ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1171462d5250SArun Ramadoss }, 1172462d5250SArun Ramadoss 1173462d5250SArun Ramadoss [KSZ8794] = { 1174462d5250SArun Ramadoss /* WARNING 1175462d5250SArun Ramadoss * ======= 1176462d5250SArun Ramadoss * KSZ8794 is similar to KSZ8795, except the port map 1177462d5250SArun Ramadoss * contains a gap between external and CPU ports, the 1178462d5250SArun Ramadoss * port map is NOT continuous. The per-port register 1179462d5250SArun Ramadoss * map is shifted accordingly too, i.e. registers at 1180462d5250SArun Ramadoss * offset 0x40 are NOT used on KSZ8794 and they ARE 1181462d5250SArun Ramadoss * used on KSZ8795 for external port 3. 1182462d5250SArun Ramadoss * external cpu 1183462d5250SArun Ramadoss * KSZ8794 0,1,2 4 1184462d5250SArun Ramadoss * KSZ8795 0,1,2,3 4 1185462d5250SArun Ramadoss * KSZ8765 0,1,2,3 4 1186462d5250SArun Ramadoss * port_cnt is configured as 5, even though it is 4 1187462d5250SArun Ramadoss */ 1188462d5250SArun Ramadoss .chip_id = KSZ8794_CHIP_ID, 1189462d5250SArun Ramadoss .dev_name = "KSZ8794", 1190462d5250SArun Ramadoss .num_vlans = 4096, 1191462d5250SArun Ramadoss .num_alus = 0, 1192462d5250SArun Ramadoss .num_statics = 8, 1193462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1194462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1195e30f33a5SArun Ramadoss .num_tx_queues = 4, 11966ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1197462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1198a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1199a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1200a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1201486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1202d23a5e18SArun Ramadoss .masks = ksz8795_masks, 120334e48383SArun Ramadoss .shifts = ksz8795_shifts, 1204aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 120546f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 120665ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 120765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 120865ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 120965ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, false}, 1210462d5250SArun Ramadoss }, 1211462d5250SArun Ramadoss 1212462d5250SArun Ramadoss [KSZ8765] = { 1213462d5250SArun Ramadoss .chip_id = KSZ8765_CHIP_ID, 1214462d5250SArun Ramadoss .dev_name = "KSZ8765", 1215462d5250SArun Ramadoss .num_vlans = 4096, 1216462d5250SArun Ramadoss .num_alus = 0, 1217462d5250SArun Ramadoss .num_statics = 8, 1218462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1219462d5250SArun Ramadoss .port_cnt = 5, /* total cpu and user ports */ 1220e30f33a5SArun Ramadoss .num_tx_queues = 4, 12216ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1222462d5250SArun Ramadoss .ksz87xx_eee_link_erratum = true, 1223a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1224a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1225a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1226486f9ca7SArun Ramadoss .regs = ksz8795_regs, 1227d23a5e18SArun Ramadoss .masks = ksz8795_masks, 122834e48383SArun Ramadoss .shifts = ksz8795_shifts, 1229aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz8795_xmii_ctrl0, 123046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, 123165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 123265ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 123365ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 123465ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1235462d5250SArun Ramadoss }, 1236462d5250SArun Ramadoss 1237462d5250SArun Ramadoss [KSZ8830] = { 1238462d5250SArun Ramadoss .chip_id = KSZ8830_CHIP_ID, 1239462d5250SArun Ramadoss .dev_name = "KSZ8863/KSZ8873", 1240462d5250SArun Ramadoss .num_vlans = 16, 1241462d5250SArun Ramadoss .num_alus = 0, 1242462d5250SArun Ramadoss .num_statics = 8, 1243462d5250SArun Ramadoss .cpu_ports = 0x4, /* can be configured as cpu port */ 1244462d5250SArun Ramadoss .port_cnt = 3, 1245e30f33a5SArun Ramadoss .num_tx_queues = 4, 12466ec23aaaSArun Ramadoss .ops = &ksz8_dev_ops, 1247a530e6f2SArun Ramadoss .mib_names = ksz88xx_mib_names, 1248a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz88xx_mib_names), 1249a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 1250486f9ca7SArun Ramadoss .regs = ksz8863_regs, 1251d23a5e18SArun Ramadoss .masks = ksz8863_masks, 125234e48383SArun Ramadoss .shifts = ksz8863_shifts, 125365ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 125465ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 125565ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1256d0dec333SOleksij Rempel .wr_table = &ksz8873_register_set, 1257d0dec333SOleksij Rempel .rd_table = &ksz8873_register_set, 1258462d5250SArun Ramadoss }, 1259462d5250SArun Ramadoss 1260462d5250SArun Ramadoss [KSZ9477] = { 1261462d5250SArun Ramadoss .chip_id = KSZ9477_CHIP_ID, 1262462d5250SArun Ramadoss .dev_name = "KSZ9477", 1263462d5250SArun Ramadoss .num_vlans = 4096, 1264462d5250SArun Ramadoss .num_alus = 4096, 1265462d5250SArun Ramadoss .num_statics = 16, 1266462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1267462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1268978f1f72SArun Ramadoss .port_nirqs = 4, 1269e30f33a5SArun Ramadoss .num_tx_queues = 4, 127071d7920fSArun Ramadoss .tc_cbs_supported = true, 1271c570f861SOleksij Rempel .tc_ets_supported = true, 12726ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1273a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1274a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1275a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 12766877102fSArun Ramadoss .regs = ksz9477_regs, 1277457c182aSArun Ramadoss .masks = ksz9477_masks, 1278457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1279aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 128046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 128165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 128265ac79e1SArun Ramadoss false, true, false}, 128365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 128465ac79e1SArun Ramadoss false, true, false}, 128565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 128665ac79e1SArun Ramadoss false, true, false}, 128765ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 128865ac79e1SArun Ramadoss true, false, false}, 1289505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 129074e792b5SOleksij Rempel .wr_table = &ksz9477_register_set, 129174e792b5SOleksij Rempel .rd_table = &ksz9477_register_set, 1292462d5250SArun Ramadoss }, 1293462d5250SArun Ramadoss 12942eb3ff3cSRomain Naour [KSZ9896] = { 12952eb3ff3cSRomain Naour .chip_id = KSZ9896_CHIP_ID, 12962eb3ff3cSRomain Naour .dev_name = "KSZ9896", 12972eb3ff3cSRomain Naour .num_vlans = 4096, 12982eb3ff3cSRomain Naour .num_alus = 4096, 12992eb3ff3cSRomain Naour .num_statics = 16, 13002eb3ff3cSRomain Naour .cpu_ports = 0x3F, /* can be configured as cpu port */ 13012eb3ff3cSRomain Naour .port_cnt = 6, /* total physical port count */ 1302978f1f72SArun Ramadoss .port_nirqs = 2, 1303e30f33a5SArun Ramadoss .num_tx_queues = 4, 13042eb3ff3cSRomain Naour .ops = &ksz9477_dev_ops, 13052eb3ff3cSRomain Naour .mib_names = ksz9477_mib_names, 13062eb3ff3cSRomain Naour .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 13072eb3ff3cSRomain Naour .reg_mib_cnt = MIB_COUNTER_NUM, 13082eb3ff3cSRomain Naour .regs = ksz9477_regs, 13092eb3ff3cSRomain Naour .masks = ksz9477_masks, 13102eb3ff3cSRomain Naour .shifts = ksz9477_shifts, 13112eb3ff3cSRomain Naour .xmii_ctrl0 = ksz9477_xmii_ctrl0, 13122eb3ff3cSRomain Naour .xmii_ctrl1 = ksz9477_xmii_ctrl1, 13132eb3ff3cSRomain Naour .supports_mii = {false, false, false, false, 13142eb3ff3cSRomain Naour false, true}, 13152eb3ff3cSRomain Naour .supports_rmii = {false, false, false, false, 13162eb3ff3cSRomain Naour false, true}, 13172eb3ff3cSRomain Naour .supports_rgmii = {false, false, false, false, 13182eb3ff3cSRomain Naour false, true}, 13192eb3ff3cSRomain Naour .internal_phy = {true, true, true, true, 13202eb3ff3cSRomain Naour true, false}, 13212eb3ff3cSRomain Naour .gbit_capable = {true, true, true, true, true, true}, 13226674e7fdSRomain Naour .wr_table = &ksz9896_register_set, 13236674e7fdSRomain Naour .rd_table = &ksz9896_register_set, 13242eb3ff3cSRomain Naour }, 13252eb3ff3cSRomain Naour 1326462d5250SArun Ramadoss [KSZ9897] = { 1327462d5250SArun Ramadoss .chip_id = KSZ9897_CHIP_ID, 1328462d5250SArun Ramadoss .dev_name = "KSZ9897", 1329462d5250SArun Ramadoss .num_vlans = 4096, 1330462d5250SArun Ramadoss .num_alus = 4096, 1331462d5250SArun Ramadoss .num_statics = 16, 1332462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1333462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1334978f1f72SArun Ramadoss .port_nirqs = 2, 1335e30f33a5SArun Ramadoss .num_tx_queues = 4, 13366ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1337a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1338a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1339a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13406877102fSArun Ramadoss .regs = ksz9477_regs, 1341457c182aSArun Ramadoss .masks = ksz9477_masks, 1342457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1343aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 134446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 134565ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 134665ac79e1SArun Ramadoss false, true, true}, 134765ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 134865ac79e1SArun Ramadoss false, true, true}, 134965ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 135065ac79e1SArun Ramadoss false, true, true}, 135165ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 135265ac79e1SArun Ramadoss true, false, false}, 1353505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1354462d5250SArun Ramadoss }, 1355462d5250SArun Ramadoss 1356462d5250SArun Ramadoss [KSZ9893] = { 1357462d5250SArun Ramadoss .chip_id = KSZ9893_CHIP_ID, 1358462d5250SArun Ramadoss .dev_name = "KSZ9893", 1359462d5250SArun Ramadoss .num_vlans = 4096, 1360462d5250SArun Ramadoss .num_alus = 4096, 1361462d5250SArun Ramadoss .num_statics = 16, 1362462d5250SArun Ramadoss .cpu_ports = 0x07, /* can be configured as cpu port */ 1363462d5250SArun Ramadoss .port_cnt = 3, /* total port count */ 1364978f1f72SArun Ramadoss .port_nirqs = 2, 1365e30f33a5SArun Ramadoss .num_tx_queues = 4, 13666ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1367a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1368a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1369a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 13706877102fSArun Ramadoss .regs = ksz9477_regs, 1371457c182aSArun Ramadoss .masks = ksz9477_masks, 1372457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1373aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 137446f80fa8SArun Ramadoss .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 137565ac79e1SArun Ramadoss .supports_mii = {false, false, true}, 137665ac79e1SArun Ramadoss .supports_rmii = {false, false, true}, 137765ac79e1SArun Ramadoss .supports_rgmii = {false, false, true}, 137865ac79e1SArun Ramadoss .internal_phy = {true, true, false}, 1379505bf320SOleksij Rempel .gbit_capable = {true, true, true}, 1380462d5250SArun Ramadoss }, 1381462d5250SArun Ramadoss 1382ef912fe4SRakesh Sankaranarayanan [KSZ9563] = { 1383ef912fe4SRakesh Sankaranarayanan .chip_id = KSZ9563_CHIP_ID, 1384ef912fe4SRakesh Sankaranarayanan .dev_name = "KSZ9563", 1385ef912fe4SRakesh Sankaranarayanan .num_vlans = 4096, 1386ef912fe4SRakesh Sankaranarayanan .num_alus = 4096, 1387ef912fe4SRakesh Sankaranarayanan .num_statics = 16, 1388ef912fe4SRakesh Sankaranarayanan .cpu_ports = 0x07, /* can be configured as cpu port */ 1389ef912fe4SRakesh Sankaranarayanan .port_cnt = 3, /* total port count */ 1390ef912fe4SRakesh Sankaranarayanan .port_nirqs = 3, 1391e30f33a5SArun Ramadoss .num_tx_queues = 4, 139271d7920fSArun Ramadoss .tc_cbs_supported = true, 1393c570f861SOleksij Rempel .tc_ets_supported = true, 1394ef912fe4SRakesh Sankaranarayanan .ops = &ksz9477_dev_ops, 1395ef912fe4SRakesh Sankaranarayanan .mib_names = ksz9477_mib_names, 1396ef912fe4SRakesh Sankaranarayanan .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1397ef912fe4SRakesh Sankaranarayanan .reg_mib_cnt = MIB_COUNTER_NUM, 1398ef912fe4SRakesh Sankaranarayanan .regs = ksz9477_regs, 1399ef912fe4SRakesh Sankaranarayanan .masks = ksz9477_masks, 1400ef912fe4SRakesh Sankaranarayanan .shifts = ksz9477_shifts, 1401ef912fe4SRakesh Sankaranarayanan .xmii_ctrl0 = ksz9477_xmii_ctrl0, 1402ef912fe4SRakesh Sankaranarayanan .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */ 1403ef912fe4SRakesh Sankaranarayanan .supports_mii = {false, false, true}, 1404ef912fe4SRakesh Sankaranarayanan .supports_rmii = {false, false, true}, 1405ef912fe4SRakesh Sankaranarayanan .supports_rgmii = {false, false, true}, 1406ef912fe4SRakesh Sankaranarayanan .internal_phy = {true, true, false}, 1407ef912fe4SRakesh Sankaranarayanan .gbit_capable = {true, true, true}, 1408ef912fe4SRakesh Sankaranarayanan }, 1409ef912fe4SRakesh Sankaranarayanan 1410462d5250SArun Ramadoss [KSZ9567] = { 1411462d5250SArun Ramadoss .chip_id = KSZ9567_CHIP_ID, 1412462d5250SArun Ramadoss .dev_name = "KSZ9567", 1413462d5250SArun Ramadoss .num_vlans = 4096, 1414462d5250SArun Ramadoss .num_alus = 4096, 1415462d5250SArun Ramadoss .num_statics = 16, 1416462d5250SArun Ramadoss .cpu_ports = 0x7F, /* can be configured as cpu port */ 1417462d5250SArun Ramadoss .port_cnt = 7, /* total physical port count */ 1418978f1f72SArun Ramadoss .port_nirqs = 3, 1419e30f33a5SArun Ramadoss .num_tx_queues = 4, 142071d7920fSArun Ramadoss .tc_cbs_supported = true, 1421c570f861SOleksij Rempel .tc_ets_supported = true, 14226ec23aaaSArun Ramadoss .ops = &ksz9477_dev_ops, 1423a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1424a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1425a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14266877102fSArun Ramadoss .regs = ksz9477_regs, 1427457c182aSArun Ramadoss .masks = ksz9477_masks, 1428457c182aSArun Ramadoss .shifts = ksz9477_shifts, 1429aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 143046f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 143165ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 143265ac79e1SArun Ramadoss false, true, true}, 143365ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 143465ac79e1SArun Ramadoss false, true, true}, 143565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 143665ac79e1SArun Ramadoss false, true, true}, 143765ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 143865ac79e1SArun Ramadoss true, false, false}, 1439505bf320SOleksij Rempel .gbit_capable = {true, true, true, true, true, true, true}, 1440462d5250SArun Ramadoss }, 1441462d5250SArun Ramadoss 1442462d5250SArun Ramadoss [LAN9370] = { 1443462d5250SArun Ramadoss .chip_id = LAN9370_CHIP_ID, 1444462d5250SArun Ramadoss .dev_name = "LAN9370", 1445462d5250SArun Ramadoss .num_vlans = 4096, 1446462d5250SArun Ramadoss .num_alus = 1024, 1447462d5250SArun Ramadoss .num_statics = 256, 1448462d5250SArun Ramadoss .cpu_ports = 0x10, /* can be configured as cpu port */ 1449462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1450978f1f72SArun Ramadoss .port_nirqs = 6, 1451e30f33a5SArun Ramadoss .num_tx_queues = 8, 145271d7920fSArun Ramadoss .tc_cbs_supported = true, 1453c570f861SOleksij Rempel .tc_ets_supported = true, 145455ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1455a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1456a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1457a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14586877102fSArun Ramadoss .regs = ksz9477_regs, 1459457c182aSArun Ramadoss .masks = lan937x_masks, 1460457c182aSArun Ramadoss .shifts = lan937x_shifts, 1461aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 146246f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 146365ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true}, 146465ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true}, 146565ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true}, 146665ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false}, 1467462d5250SArun Ramadoss }, 1468462d5250SArun Ramadoss 1469462d5250SArun Ramadoss [LAN9371] = { 1470462d5250SArun Ramadoss .chip_id = LAN9371_CHIP_ID, 1471462d5250SArun Ramadoss .dev_name = "LAN9371", 1472462d5250SArun Ramadoss .num_vlans = 4096, 1473462d5250SArun Ramadoss .num_alus = 1024, 1474462d5250SArun Ramadoss .num_statics = 256, 1475462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1476462d5250SArun Ramadoss .port_cnt = 6, /* total physical port count */ 1477978f1f72SArun Ramadoss .port_nirqs = 6, 1478e30f33a5SArun Ramadoss .num_tx_queues = 8, 147971d7920fSArun Ramadoss .tc_cbs_supported = true, 1480c570f861SOleksij Rempel .tc_ets_supported = true, 148155ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1482a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1483a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1484a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 14856877102fSArun Ramadoss .regs = ksz9477_regs, 1486457c182aSArun Ramadoss .masks = lan937x_masks, 1487457c182aSArun Ramadoss .shifts = lan937x_shifts, 1488aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 148946f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 149065ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, true, true}, 149165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, true, true}, 149265ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, true, true}, 149365ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, false, false}, 1494462d5250SArun Ramadoss }, 1495462d5250SArun Ramadoss 1496462d5250SArun Ramadoss [LAN9372] = { 1497462d5250SArun Ramadoss .chip_id = LAN9372_CHIP_ID, 1498462d5250SArun Ramadoss .dev_name = "LAN9372", 1499462d5250SArun Ramadoss .num_vlans = 4096, 1500462d5250SArun Ramadoss .num_alus = 1024, 1501462d5250SArun Ramadoss .num_statics = 256, 1502462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1503462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1504978f1f72SArun Ramadoss .port_nirqs = 6, 1505e30f33a5SArun Ramadoss .num_tx_queues = 8, 150671d7920fSArun Ramadoss .tc_cbs_supported = true, 1507c570f861SOleksij Rempel .tc_ets_supported = true, 150855ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1509a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1510a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1511a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 15126877102fSArun Ramadoss .regs = ksz9477_regs, 1513457c182aSArun Ramadoss .masks = lan937x_masks, 1514457c182aSArun Ramadoss .shifts = lan937x_shifts, 1515aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 151646f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 151765ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 151865ac79e1SArun Ramadoss true, true, false, false}, 151965ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 152065ac79e1SArun Ramadoss true, true, false, false}, 152165ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 152265ac79e1SArun Ramadoss true, true, false, false}, 152365ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 152465ac79e1SArun Ramadoss false, false, true, true}, 1525462d5250SArun Ramadoss }, 1526462d5250SArun Ramadoss 1527462d5250SArun Ramadoss [LAN9373] = { 1528462d5250SArun Ramadoss .chip_id = LAN9373_CHIP_ID, 1529462d5250SArun Ramadoss .dev_name = "LAN9373", 1530462d5250SArun Ramadoss .num_vlans = 4096, 1531462d5250SArun Ramadoss .num_alus = 1024, 1532462d5250SArun Ramadoss .num_statics = 256, 1533462d5250SArun Ramadoss .cpu_ports = 0x38, /* can be configured as cpu port */ 1534462d5250SArun Ramadoss .port_cnt = 5, /* total physical port count */ 1535978f1f72SArun Ramadoss .port_nirqs = 6, 1536e30f33a5SArun Ramadoss .num_tx_queues = 8, 153771d7920fSArun Ramadoss .tc_cbs_supported = true, 1538c570f861SOleksij Rempel .tc_ets_supported = true, 153955ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1540a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1541a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1542a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 15436877102fSArun Ramadoss .regs = ksz9477_regs, 1544457c182aSArun Ramadoss .masks = lan937x_masks, 1545457c182aSArun Ramadoss .shifts = lan937x_shifts, 1546aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 154746f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 154865ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 154965ac79e1SArun Ramadoss true, true, false, false}, 155065ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 155165ac79e1SArun Ramadoss true, true, false, false}, 155265ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 155365ac79e1SArun Ramadoss true, true, false, false}, 155465ac79e1SArun Ramadoss .internal_phy = {true, true, true, false, 155565ac79e1SArun Ramadoss false, false, true, true}, 1556462d5250SArun Ramadoss }, 1557462d5250SArun Ramadoss 1558462d5250SArun Ramadoss [LAN9374] = { 1559462d5250SArun Ramadoss .chip_id = LAN9374_CHIP_ID, 1560462d5250SArun Ramadoss .dev_name = "LAN9374", 1561462d5250SArun Ramadoss .num_vlans = 4096, 1562462d5250SArun Ramadoss .num_alus = 1024, 1563462d5250SArun Ramadoss .num_statics = 256, 1564462d5250SArun Ramadoss .cpu_ports = 0x30, /* can be configured as cpu port */ 1565462d5250SArun Ramadoss .port_cnt = 8, /* total physical port count */ 1566978f1f72SArun Ramadoss .port_nirqs = 6, 1567e30f33a5SArun Ramadoss .num_tx_queues = 8, 156871d7920fSArun Ramadoss .tc_cbs_supported = true, 1569c570f861SOleksij Rempel .tc_ets_supported = true, 157055ab6ffaSArun Ramadoss .ops = &lan937x_dev_ops, 1571a530e6f2SArun Ramadoss .mib_names = ksz9477_mib_names, 1572a530e6f2SArun Ramadoss .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), 1573a530e6f2SArun Ramadoss .reg_mib_cnt = MIB_COUNTER_NUM, 15746877102fSArun Ramadoss .regs = ksz9477_regs, 1575457c182aSArun Ramadoss .masks = lan937x_masks, 1576457c182aSArun Ramadoss .shifts = lan937x_shifts, 1577aa5b8b73SArun Ramadoss .xmii_ctrl0 = ksz9477_xmii_ctrl0, 157846f80fa8SArun Ramadoss .xmii_ctrl1 = ksz9477_xmii_ctrl1, 157965ac79e1SArun Ramadoss .supports_mii = {false, false, false, false, 158065ac79e1SArun Ramadoss true, true, false, false}, 158165ac79e1SArun Ramadoss .supports_rmii = {false, false, false, false, 158265ac79e1SArun Ramadoss true, true, false, false}, 158365ac79e1SArun Ramadoss .supports_rgmii = {false, false, false, false, 158465ac79e1SArun Ramadoss true, true, false, false}, 158565ac79e1SArun Ramadoss .internal_phy = {true, true, true, true, 158665ac79e1SArun Ramadoss false, false, true, true}, 1587462d5250SArun Ramadoss }, 1588462d5250SArun Ramadoss }; 1589eee16b14SArun Ramadoss EXPORT_SYMBOL_GPL(ksz_switch_chips); 1590462d5250SArun Ramadoss 1591462d5250SArun Ramadoss static const struct ksz_chip_data *ksz_lookup_info(unsigned int prod_num) 1592462d5250SArun Ramadoss { 1593462d5250SArun Ramadoss int i; 1594462d5250SArun Ramadoss 1595462d5250SArun Ramadoss for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) { 1596462d5250SArun Ramadoss const struct ksz_chip_data *chip = &ksz_switch_chips[i]; 1597462d5250SArun Ramadoss 1598462d5250SArun Ramadoss if (chip->chip_id == prod_num) 1599462d5250SArun Ramadoss return chip; 1600462d5250SArun Ramadoss } 1601462d5250SArun Ramadoss 1602462d5250SArun Ramadoss return NULL; 1603462d5250SArun Ramadoss } 1604462d5250SArun Ramadoss 1605eee16b14SArun Ramadoss static int ksz_check_device_id(struct ksz_device *dev) 1606eee16b14SArun Ramadoss { 1607eee16b14SArun Ramadoss const struct ksz_chip_data *dt_chip_data; 1608eee16b14SArun Ramadoss 1609eee16b14SArun Ramadoss dt_chip_data = of_device_get_match_data(dev->dev); 1610eee16b14SArun Ramadoss 1611eee16b14SArun Ramadoss /* Check for Device Tree and Chip ID */ 1612eee16b14SArun Ramadoss if (dt_chip_data->chip_id != dev->chip_id) { 1613eee16b14SArun Ramadoss dev_err(dev->dev, 1614eee16b14SArun Ramadoss "Device tree specifies chip %s but found %s, please fix it!\n", 1615eee16b14SArun Ramadoss dt_chip_data->dev_name, dev->info->dev_name); 1616eee16b14SArun Ramadoss return -ENODEV; 1617eee16b14SArun Ramadoss } 1618eee16b14SArun Ramadoss 1619eee16b14SArun Ramadoss return 0; 1620eee16b14SArun Ramadoss } 1621eee16b14SArun Ramadoss 16221958eee8SArun Ramadoss static void ksz_phylink_get_caps(struct dsa_switch *ds, int port, 162365ac79e1SArun Ramadoss struct phylink_config *config) 162465ac79e1SArun Ramadoss { 162565ac79e1SArun Ramadoss struct ksz_device *dev = ds->priv; 162665ac79e1SArun Ramadoss 162765ac79e1SArun Ramadoss config->legacy_pre_march2020 = false; 162865ac79e1SArun Ramadoss 162965ac79e1SArun Ramadoss if (dev->info->supports_mii[port]) 163065ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); 163165ac79e1SArun Ramadoss 163265ac79e1SArun Ramadoss if (dev->info->supports_rmii[port]) 163365ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_RMII, 163465ac79e1SArun Ramadoss config->supported_interfaces); 163565ac79e1SArun Ramadoss 163665ac79e1SArun Ramadoss if (dev->info->supports_rgmii[port]) 163765ac79e1SArun Ramadoss phy_interface_set_rgmii(config->supported_interfaces); 163865ac79e1SArun Ramadoss 16395fbb08ebSVladimir Oltean if (dev->info->internal_phy[port]) { 164065ac79e1SArun Ramadoss __set_bit(PHY_INTERFACE_MODE_INTERNAL, 164165ac79e1SArun Ramadoss config->supported_interfaces); 16425fbb08ebSVladimir Oltean /* Compatibility for phylib's default interface type when the 16435fbb08ebSVladimir Oltean * phy-mode property is absent 16445fbb08ebSVladimir Oltean */ 16455fbb08ebSVladimir Oltean __set_bit(PHY_INTERFACE_MODE_GMII, 16465fbb08ebSVladimir Oltean config->supported_interfaces); 16475fbb08ebSVladimir Oltean } 16487012033cSArun Ramadoss 16497012033cSArun Ramadoss if (dev->dev_ops->get_caps) 16507012033cSArun Ramadoss dev->dev_ops->get_caps(dev, port, config); 165165ac79e1SArun Ramadoss } 165265ac79e1SArun Ramadoss 1653c6101dd7SArun Ramadoss void ksz_r_mib_stats64(struct ksz_device *dev, int port) 1654c6101dd7SArun Ramadoss { 1655c4748ff6SOleksij Rempel struct ethtool_pause_stats *pstats; 1656c6101dd7SArun Ramadoss struct rtnl_link_stats64 *stats; 1657c6101dd7SArun Ramadoss struct ksz_stats_raw *raw; 1658c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1659c6101dd7SArun Ramadoss 1660c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1661c6101dd7SArun Ramadoss stats = &mib->stats64; 1662c4748ff6SOleksij Rempel pstats = &mib->pause_stats; 1663c6101dd7SArun Ramadoss raw = (struct ksz_stats_raw *)mib->counters; 1664c6101dd7SArun Ramadoss 1665c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1666c6101dd7SArun Ramadoss 1667961d6c70SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 1668961d6c70SOleksij Rempel raw->rx_pause; 1669961d6c70SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 1670961d6c70SOleksij Rempel raw->tx_pause; 1671c6101dd7SArun Ramadoss 1672c6101dd7SArun Ramadoss /* HW counters are counting bytes + FCS which is not acceptable 1673c6101dd7SArun Ramadoss * for rtnl_link_stats64 interface 1674c6101dd7SArun Ramadoss */ 1675c6101dd7SArun Ramadoss stats->rx_bytes = raw->rx_total - stats->rx_packets * ETH_FCS_LEN; 1676c6101dd7SArun Ramadoss stats->tx_bytes = raw->tx_total - stats->tx_packets * ETH_FCS_LEN; 1677c6101dd7SArun Ramadoss 1678c6101dd7SArun Ramadoss stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 1679c6101dd7SArun Ramadoss raw->rx_oversize; 1680c6101dd7SArun Ramadoss 1681c6101dd7SArun Ramadoss stats->rx_crc_errors = raw->rx_crc_err; 1682c6101dd7SArun Ramadoss stats->rx_frame_errors = raw->rx_align_err; 1683c6101dd7SArun Ramadoss stats->rx_dropped = raw->rx_discards; 1684c6101dd7SArun Ramadoss stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 1685c6101dd7SArun Ramadoss stats->rx_frame_errors + stats->rx_dropped; 1686c6101dd7SArun Ramadoss 1687c6101dd7SArun Ramadoss stats->tx_window_errors = raw->tx_late_col; 1688c6101dd7SArun Ramadoss stats->tx_fifo_errors = raw->tx_discards; 1689c6101dd7SArun Ramadoss stats->tx_aborted_errors = raw->tx_exc_col; 1690c6101dd7SArun Ramadoss stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 1691c6101dd7SArun Ramadoss stats->tx_aborted_errors; 1692c6101dd7SArun Ramadoss 1693c6101dd7SArun Ramadoss stats->multicast = raw->rx_mcast; 1694c6101dd7SArun Ramadoss stats->collisions = raw->tx_total_col; 1695c6101dd7SArun Ramadoss 1696c4748ff6SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 1697c4748ff6SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 1698c4748ff6SOleksij Rempel 1699c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1700c6101dd7SArun Ramadoss } 1701c6101dd7SArun Ramadoss 1702bde55dd9SOleksij Rempel void ksz88xx_r_mib_stats64(struct ksz_device *dev, int port) 1703bde55dd9SOleksij Rempel { 1704bde55dd9SOleksij Rempel struct ethtool_pause_stats *pstats; 1705bde55dd9SOleksij Rempel struct rtnl_link_stats64 *stats; 1706bde55dd9SOleksij Rempel struct ksz88xx_stats_raw *raw; 1707bde55dd9SOleksij Rempel struct ksz_port_mib *mib; 1708bde55dd9SOleksij Rempel 1709bde55dd9SOleksij Rempel mib = &dev->ports[port].mib; 1710bde55dd9SOleksij Rempel stats = &mib->stats64; 1711bde55dd9SOleksij Rempel pstats = &mib->pause_stats; 1712bde55dd9SOleksij Rempel raw = (struct ksz88xx_stats_raw *)mib->counters; 1713bde55dd9SOleksij Rempel 1714bde55dd9SOleksij Rempel spin_lock(&mib->stats64_lock); 1715bde55dd9SOleksij Rempel 1716bde55dd9SOleksij Rempel stats->rx_packets = raw->rx_bcast + raw->rx_mcast + raw->rx_ucast + 1717bde55dd9SOleksij Rempel raw->rx_pause; 1718bde55dd9SOleksij Rempel stats->tx_packets = raw->tx_bcast + raw->tx_mcast + raw->tx_ucast + 1719bde55dd9SOleksij Rempel raw->tx_pause; 1720bde55dd9SOleksij Rempel 1721bde55dd9SOleksij Rempel /* HW counters are counting bytes + FCS which is not acceptable 1722bde55dd9SOleksij Rempel * for rtnl_link_stats64 interface 1723bde55dd9SOleksij Rempel */ 1724bde55dd9SOleksij Rempel stats->rx_bytes = raw->rx + raw->rx_hi - stats->rx_packets * ETH_FCS_LEN; 1725bde55dd9SOleksij Rempel stats->tx_bytes = raw->tx + raw->tx_hi - stats->tx_packets * ETH_FCS_LEN; 1726bde55dd9SOleksij Rempel 1727bde55dd9SOleksij Rempel stats->rx_length_errors = raw->rx_undersize + raw->rx_fragments + 1728bde55dd9SOleksij Rempel raw->rx_oversize; 1729bde55dd9SOleksij Rempel 1730bde55dd9SOleksij Rempel stats->rx_crc_errors = raw->rx_crc_err; 1731bde55dd9SOleksij Rempel stats->rx_frame_errors = raw->rx_align_err; 1732bde55dd9SOleksij Rempel stats->rx_dropped = raw->rx_discards; 1733bde55dd9SOleksij Rempel stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors + 1734bde55dd9SOleksij Rempel stats->rx_frame_errors + stats->rx_dropped; 1735bde55dd9SOleksij Rempel 1736bde55dd9SOleksij Rempel stats->tx_window_errors = raw->tx_late_col; 1737bde55dd9SOleksij Rempel stats->tx_fifo_errors = raw->tx_discards; 1738bde55dd9SOleksij Rempel stats->tx_aborted_errors = raw->tx_exc_col; 1739bde55dd9SOleksij Rempel stats->tx_errors = stats->tx_window_errors + stats->tx_fifo_errors + 1740bde55dd9SOleksij Rempel stats->tx_aborted_errors; 1741bde55dd9SOleksij Rempel 1742bde55dd9SOleksij Rempel stats->multicast = raw->rx_mcast; 1743bde55dd9SOleksij Rempel stats->collisions = raw->tx_total_col; 1744bde55dd9SOleksij Rempel 1745bde55dd9SOleksij Rempel pstats->tx_pause_frames = raw->tx_pause; 1746bde55dd9SOleksij Rempel pstats->rx_pause_frames = raw->rx_pause; 1747bde55dd9SOleksij Rempel 1748bde55dd9SOleksij Rempel spin_unlock(&mib->stats64_lock); 1749bde55dd9SOleksij Rempel } 1750bde55dd9SOleksij Rempel 17511958eee8SArun Ramadoss static void ksz_get_stats64(struct dsa_switch *ds, int port, 1752c6101dd7SArun Ramadoss struct rtnl_link_stats64 *s) 1753c6101dd7SArun Ramadoss { 1754c6101dd7SArun Ramadoss struct ksz_device *dev = ds->priv; 1755c6101dd7SArun Ramadoss struct ksz_port_mib *mib; 1756c6101dd7SArun Ramadoss 1757c6101dd7SArun Ramadoss mib = &dev->ports[port].mib; 1758c6101dd7SArun Ramadoss 1759c6101dd7SArun Ramadoss spin_lock(&mib->stats64_lock); 1760c6101dd7SArun Ramadoss memcpy(s, &mib->stats64, sizeof(*s)); 1761c6101dd7SArun Ramadoss spin_unlock(&mib->stats64_lock); 1762c6101dd7SArun Ramadoss } 1763c6101dd7SArun Ramadoss 1764c4748ff6SOleksij Rempel static void ksz_get_pause_stats(struct dsa_switch *ds, int port, 1765c4748ff6SOleksij Rempel struct ethtool_pause_stats *pause_stats) 1766c4748ff6SOleksij Rempel { 1767c4748ff6SOleksij Rempel struct ksz_device *dev = ds->priv; 1768c4748ff6SOleksij Rempel struct ksz_port_mib *mib; 1769c4748ff6SOleksij Rempel 1770c4748ff6SOleksij Rempel mib = &dev->ports[port].mib; 1771c4748ff6SOleksij Rempel 1772c4748ff6SOleksij Rempel spin_lock(&mib->stats64_lock); 1773c4748ff6SOleksij Rempel memcpy(pause_stats, &mib->pause_stats, sizeof(*pause_stats)); 1774c4748ff6SOleksij Rempel spin_unlock(&mib->stats64_lock); 1775c4748ff6SOleksij Rempel } 1776c4748ff6SOleksij Rempel 17771958eee8SArun Ramadoss static void ksz_get_strings(struct dsa_switch *ds, int port, 1778997d2126SArun Ramadoss u32 stringset, uint8_t *buf) 1779997d2126SArun Ramadoss { 1780997d2126SArun Ramadoss struct ksz_device *dev = ds->priv; 1781997d2126SArun Ramadoss int i; 1782997d2126SArun Ramadoss 1783997d2126SArun Ramadoss if (stringset != ETH_SS_STATS) 1784997d2126SArun Ramadoss return; 1785997d2126SArun Ramadoss 1786997d2126SArun Ramadoss for (i = 0; i < dev->info->mib_cnt; i++) { 1787997d2126SArun Ramadoss memcpy(buf + i * ETH_GSTRING_LEN, 1788997d2126SArun Ramadoss dev->info->mib_names[i].string, ETH_GSTRING_LEN); 1789997d2126SArun Ramadoss } 1790997d2126SArun Ramadoss } 1791997d2126SArun Ramadoss 1792e593df51SArun Ramadoss static void ksz_update_port_member(struct ksz_device *dev, int port) 1793b987e98eSWoojung Huh { 1794b3612ccdSOleksij Rempel struct ksz_port *p = &dev->ports[port]; 1795b3612ccdSOleksij Rempel struct dsa_switch *ds = dev->ds; 1796b3612ccdSOleksij Rempel u8 port_member = 0, cpu_port; 1797b3612ccdSOleksij Rempel const struct dsa_port *dp; 17983d00827aSSvenning Sørensen int i, j; 1799b987e98eSWoojung Huh 1800b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, port)) 1801b3612ccdSOleksij Rempel return; 1802b3612ccdSOleksij Rempel 1803b3612ccdSOleksij Rempel dp = dsa_to_port(ds, port); 1804b3612ccdSOleksij Rempel cpu_port = BIT(dsa_upstream_port(ds, port)); 1805b3612ccdSOleksij Rempel 1806b3612ccdSOleksij Rempel for (i = 0; i < ds->num_ports; i++) { 1807b3612ccdSOleksij Rempel const struct dsa_port *other_dp = dsa_to_port(ds, i); 1808b3612ccdSOleksij Rempel struct ksz_port *other_p = &dev->ports[i]; 1809b3612ccdSOleksij Rempel u8 val = 0; 1810b3612ccdSOleksij Rempel 1811b3612ccdSOleksij Rempel if (!dsa_is_user_port(ds, i)) 1812c2e86691STristram Ha continue; 1813b3612ccdSOleksij Rempel if (port == i) 1814b3612ccdSOleksij Rempel continue; 181541fb0cf1SVladimir Oltean if (!dsa_port_bridge_same(dp, other_dp)) 1816c2e86691STristram Ha continue; 18173d00827aSSvenning Sørensen if (other_p->stp_state != BR_STATE_FORWARDING) 18183d00827aSSvenning Sørensen continue; 1819b987e98eSWoojung Huh 18203d00827aSSvenning Sørensen if (p->stp_state == BR_STATE_FORWARDING) { 1821b3612ccdSOleksij Rempel val |= BIT(port); 1822b3612ccdSOleksij Rempel port_member |= BIT(i); 1823b987e98eSWoojung Huh } 1824b3612ccdSOleksij Rempel 18253d00827aSSvenning Sørensen /* Retain port [i]'s relationship to other ports than [port] */ 18263d00827aSSvenning Sørensen for (j = 0; j < ds->num_ports; j++) { 18273d00827aSSvenning Sørensen const struct dsa_port *third_dp; 18283d00827aSSvenning Sørensen struct ksz_port *third_p; 18293d00827aSSvenning Sørensen 18303d00827aSSvenning Sørensen if (j == i) 18313d00827aSSvenning Sørensen continue; 18323d00827aSSvenning Sørensen if (j == port) 18333d00827aSSvenning Sørensen continue; 18343d00827aSSvenning Sørensen if (!dsa_is_user_port(ds, j)) 18353d00827aSSvenning Sørensen continue; 18363d00827aSSvenning Sørensen third_p = &dev->ports[j]; 18373d00827aSSvenning Sørensen if (third_p->stp_state != BR_STATE_FORWARDING) 18383d00827aSSvenning Sørensen continue; 18393d00827aSSvenning Sørensen third_dp = dsa_to_port(ds, j); 18403d00827aSSvenning Sørensen if (dsa_port_bridge_same(other_dp, third_dp)) 18413d00827aSSvenning Sørensen val |= BIT(j); 18423d00827aSSvenning Sørensen } 18433d00827aSSvenning Sørensen 1844b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); 1845b3612ccdSOleksij Rempel } 1846b3612ccdSOleksij Rempel 1847b3612ccdSOleksij Rempel dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); 1848b987e98eSWoojung Huh } 1849b987e98eSWoojung Huh 1850ff319a64SArun Ramadoss static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum) 1851ff319a64SArun Ramadoss { 1852ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1853ff319a64SArun Ramadoss u16 val; 1854ff319a64SArun Ramadoss int ret; 1855ff319a64SArun Ramadoss 1856ff319a64SArun Ramadoss ret = dev->dev_ops->r_phy(dev, addr, regnum, &val); 1857ff319a64SArun Ramadoss if (ret < 0) 1858ff319a64SArun Ramadoss return ret; 1859ff319a64SArun Ramadoss 1860ff319a64SArun Ramadoss return val; 1861ff319a64SArun Ramadoss } 1862ff319a64SArun Ramadoss 1863ff319a64SArun Ramadoss static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, 1864ff319a64SArun Ramadoss u16 val) 1865ff319a64SArun Ramadoss { 1866ff319a64SArun Ramadoss struct ksz_device *dev = bus->priv; 1867ff319a64SArun Ramadoss 1868ff319a64SArun Ramadoss return dev->dev_ops->w_phy(dev, addr, regnum, val); 1869ff319a64SArun Ramadoss } 1870ff319a64SArun Ramadoss 1871ff319a64SArun Ramadoss static int ksz_irq_phy_setup(struct ksz_device *dev) 1872ff319a64SArun Ramadoss { 1873ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1874ff319a64SArun Ramadoss int phy; 1875ff319a64SArun Ramadoss int irq; 1876ff319a64SArun Ramadoss int ret; 1877ff319a64SArun Ramadoss 1878ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) { 1879ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) { 1880ff319a64SArun Ramadoss irq = irq_find_mapping(dev->ports[phy].pirq.domain, 1881ff319a64SArun Ramadoss PORT_SRC_PHY_INT); 1882ff319a64SArun Ramadoss if (irq < 0) { 1883ff319a64SArun Ramadoss ret = irq; 1884ff319a64SArun Ramadoss goto out; 1885ff319a64SArun Ramadoss } 1886ff319a64SArun Ramadoss ds->slave_mii_bus->irq[phy] = irq; 1887ff319a64SArun Ramadoss } 1888ff319a64SArun Ramadoss } 1889ff319a64SArun Ramadoss return 0; 1890ff319a64SArun Ramadoss out: 1891ff319a64SArun Ramadoss while (phy--) 1892ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1893ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1894ff319a64SArun Ramadoss 1895ff319a64SArun Ramadoss return ret; 1896ff319a64SArun Ramadoss } 1897ff319a64SArun Ramadoss 1898ff319a64SArun Ramadoss static void ksz_irq_phy_free(struct ksz_device *dev) 1899ff319a64SArun Ramadoss { 1900ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1901ff319a64SArun Ramadoss int phy; 1902ff319a64SArun Ramadoss 1903ff319a64SArun Ramadoss for (phy = 0; phy < KSZ_MAX_NUM_PORTS; phy++) 1904ff319a64SArun Ramadoss if (BIT(phy) & ds->phys_mii_mask) 1905ff319a64SArun Ramadoss irq_dispose_mapping(ds->slave_mii_bus->irq[phy]); 1906ff319a64SArun Ramadoss } 1907ff319a64SArun Ramadoss 1908ff319a64SArun Ramadoss static int ksz_mdio_register(struct ksz_device *dev) 1909ff319a64SArun Ramadoss { 1910ff319a64SArun Ramadoss struct dsa_switch *ds = dev->ds; 1911ff319a64SArun Ramadoss struct device_node *mdio_np; 1912ff319a64SArun Ramadoss struct mii_bus *bus; 1913ff319a64SArun Ramadoss int ret; 1914ff319a64SArun Ramadoss 1915ff319a64SArun Ramadoss mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio"); 1916ff319a64SArun Ramadoss if (!mdio_np) 1917ff319a64SArun Ramadoss return 0; 1918ff319a64SArun Ramadoss 1919ff319a64SArun Ramadoss bus = devm_mdiobus_alloc(ds->dev); 1920ff319a64SArun Ramadoss if (!bus) { 1921ff319a64SArun Ramadoss of_node_put(mdio_np); 1922ff319a64SArun Ramadoss return -ENOMEM; 1923ff319a64SArun Ramadoss } 1924ff319a64SArun Ramadoss 1925ff319a64SArun Ramadoss bus->priv = dev; 1926ff319a64SArun Ramadoss bus->read = ksz_sw_mdio_read; 1927ff319a64SArun Ramadoss bus->write = ksz_sw_mdio_write; 1928ff319a64SArun Ramadoss bus->name = "ksz slave smi"; 1929ff319a64SArun Ramadoss snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index); 1930ff319a64SArun Ramadoss bus->parent = ds->dev; 1931ff319a64SArun Ramadoss bus->phy_mask = ~ds->phys_mii_mask; 1932ff319a64SArun Ramadoss 1933ff319a64SArun Ramadoss ds->slave_mii_bus = bus; 1934ff319a64SArun Ramadoss 1935ff319a64SArun Ramadoss if (dev->irq > 0) { 1936ff319a64SArun Ramadoss ret = ksz_irq_phy_setup(dev); 1937ff319a64SArun Ramadoss if (ret) { 1938ff319a64SArun Ramadoss of_node_put(mdio_np); 1939ff319a64SArun Ramadoss return ret; 1940ff319a64SArun Ramadoss } 1941ff319a64SArun Ramadoss } 1942ff319a64SArun Ramadoss 1943ff319a64SArun Ramadoss ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np); 1944ff319a64SArun Ramadoss if (ret) { 1945ff319a64SArun Ramadoss dev_err(ds->dev, "unable to register MDIO bus %s\n", 1946ff319a64SArun Ramadoss bus->id); 1947ff319a64SArun Ramadoss if (dev->irq > 0) 1948ff319a64SArun Ramadoss ksz_irq_phy_free(dev); 1949ff319a64SArun Ramadoss } 1950ff319a64SArun Ramadoss 1951ff319a64SArun Ramadoss of_node_put(mdio_np); 1952ff319a64SArun Ramadoss 1953ff319a64SArun Ramadoss return ret; 1954ff319a64SArun Ramadoss } 1955ff319a64SArun Ramadoss 1956e1add7ddSArun Ramadoss static void ksz_irq_mask(struct irq_data *d) 1957ff319a64SArun Ramadoss { 1958e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1959ff319a64SArun Ramadoss 1960e1add7ddSArun Ramadoss kirq->masked |= BIT(d->hwirq); 1961ff319a64SArun Ramadoss } 1962ff319a64SArun Ramadoss 1963e1add7ddSArun Ramadoss static void ksz_irq_unmask(struct irq_data *d) 1964ff319a64SArun Ramadoss { 1965e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1966ff319a64SArun Ramadoss 1967e1add7ddSArun Ramadoss kirq->masked &= ~BIT(d->hwirq); 1968ff319a64SArun Ramadoss } 1969ff319a64SArun Ramadoss 1970e1add7ddSArun Ramadoss static void ksz_irq_bus_lock(struct irq_data *d) 1971ff319a64SArun Ramadoss { 1972e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1973ff319a64SArun Ramadoss 1974e1add7ddSArun Ramadoss mutex_lock(&kirq->dev->lock_irq); 1975ff319a64SArun Ramadoss } 1976ff319a64SArun Ramadoss 1977e1add7ddSArun Ramadoss static void ksz_irq_bus_sync_unlock(struct irq_data *d) 1978ff319a64SArun Ramadoss { 1979e1add7ddSArun Ramadoss struct ksz_irq *kirq = irq_data_get_irq_chip_data(d); 1980e1add7ddSArun Ramadoss struct ksz_device *dev = kirq->dev; 1981ff319a64SArun Ramadoss int ret; 1982ff319a64SArun Ramadoss 1983e1add7ddSArun Ramadoss ret = ksz_write32(dev, kirq->reg_mask, kirq->masked); 1984ff319a64SArun Ramadoss if (ret) 1985ff319a64SArun Ramadoss dev_err(dev->dev, "failed to change IRQ mask\n"); 1986ff319a64SArun Ramadoss 1987ff319a64SArun Ramadoss mutex_unlock(&dev->lock_irq); 1988ff319a64SArun Ramadoss } 1989ff319a64SArun Ramadoss 1990e1add7ddSArun Ramadoss static const struct irq_chip ksz_irq_chip = { 1991e1add7ddSArun Ramadoss .name = "ksz-irq", 1992e1add7ddSArun Ramadoss .irq_mask = ksz_irq_mask, 1993e1add7ddSArun Ramadoss .irq_unmask = ksz_irq_unmask, 1994e1add7ddSArun Ramadoss .irq_bus_lock = ksz_irq_bus_lock, 1995e1add7ddSArun Ramadoss .irq_bus_sync_unlock = ksz_irq_bus_sync_unlock, 1996ff319a64SArun Ramadoss }; 1997ff319a64SArun Ramadoss 1998e1add7ddSArun Ramadoss static int ksz_irq_domain_map(struct irq_domain *d, 1999ff319a64SArun Ramadoss unsigned int irq, irq_hw_number_t hwirq) 2000ff319a64SArun Ramadoss { 2001ff319a64SArun Ramadoss irq_set_chip_data(irq, d->host_data); 2002e1add7ddSArun Ramadoss irq_set_chip_and_handler(irq, &ksz_irq_chip, handle_level_irq); 2003ff319a64SArun Ramadoss irq_set_noprobe(irq); 2004ff319a64SArun Ramadoss 2005ff319a64SArun Ramadoss return 0; 2006ff319a64SArun Ramadoss } 2007ff319a64SArun Ramadoss 2008e1add7ddSArun Ramadoss static const struct irq_domain_ops ksz_irq_domain_ops = { 2009e1add7ddSArun Ramadoss .map = ksz_irq_domain_map, 2010ff319a64SArun Ramadoss .xlate = irq_domain_xlate_twocell, 2011ff319a64SArun Ramadoss }; 2012ff319a64SArun Ramadoss 2013e1add7ddSArun Ramadoss static void ksz_irq_free(struct ksz_irq *kirq) 2014ff319a64SArun Ramadoss { 2015ff319a64SArun Ramadoss int irq, virq; 2016ff319a64SArun Ramadoss 2017e1add7ddSArun Ramadoss free_irq(kirq->irq_num, kirq); 2018ff319a64SArun Ramadoss 2019e1add7ddSArun Ramadoss for (irq = 0; irq < kirq->nirqs; irq++) { 2020e1add7ddSArun Ramadoss virq = irq_find_mapping(kirq->domain, irq); 2021ff319a64SArun Ramadoss irq_dispose_mapping(virq); 2022ff319a64SArun Ramadoss } 2023ff319a64SArun Ramadoss 2024e1add7ddSArun Ramadoss irq_domain_remove(kirq->domain); 2025ff319a64SArun Ramadoss } 2026ff319a64SArun Ramadoss 2027e1add7ddSArun Ramadoss static irqreturn_t ksz_irq_thread_fn(int irq, void *dev_id) 2028ff319a64SArun Ramadoss { 2029e1add7ddSArun Ramadoss struct ksz_irq *kirq = dev_id; 2030ff319a64SArun Ramadoss unsigned int nhandled = 0; 2031e1add7ddSArun Ramadoss struct ksz_device *dev; 2032ff319a64SArun Ramadoss unsigned int sub_irq; 2033e1add7ddSArun Ramadoss u8 data; 2034ff319a64SArun Ramadoss int ret; 2035e1add7ddSArun Ramadoss u8 n; 2036ff319a64SArun Ramadoss 2037e1add7ddSArun Ramadoss dev = kirq->dev; 2038e1add7ddSArun Ramadoss 2039e1add7ddSArun Ramadoss /* Read interrupt status register */ 2040e1add7ddSArun Ramadoss ret = ksz_read8(dev, kirq->reg_status, &data); 2041ff319a64SArun Ramadoss if (ret) 2042ff319a64SArun Ramadoss goto out; 2043ff319a64SArun Ramadoss 2044e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; ++n) { 2045e1add7ddSArun Ramadoss if (data & BIT(n)) { 2046e1add7ddSArun Ramadoss sub_irq = irq_find_mapping(kirq->domain, n); 2047ff319a64SArun Ramadoss handle_nested_irq(sub_irq); 2048ff319a64SArun Ramadoss ++nhandled; 2049ff319a64SArun Ramadoss } 2050ff319a64SArun Ramadoss } 2051ff319a64SArun Ramadoss out: 2052ff319a64SArun Ramadoss return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); 2053ff319a64SArun Ramadoss } 2054ff319a64SArun Ramadoss 2055e1add7ddSArun Ramadoss static int ksz_irq_common_setup(struct ksz_device *dev, struct ksz_irq *kirq) 2056e1add7ddSArun Ramadoss { 2057e1add7ddSArun Ramadoss int ret, n; 2058e1add7ddSArun Ramadoss 2059e1add7ddSArun Ramadoss kirq->dev = dev; 2060e1add7ddSArun Ramadoss kirq->masked = ~0; 2061e1add7ddSArun Ramadoss 2062e1add7ddSArun Ramadoss kirq->domain = irq_domain_add_simple(dev->dev->of_node, kirq->nirqs, 0, 2063e1add7ddSArun Ramadoss &ksz_irq_domain_ops, kirq); 2064e1add7ddSArun Ramadoss if (!kirq->domain) 2065e1add7ddSArun Ramadoss return -ENOMEM; 2066e1add7ddSArun Ramadoss 2067e1add7ddSArun Ramadoss for (n = 0; n < kirq->nirqs; n++) 2068e1add7ddSArun Ramadoss irq_create_mapping(kirq->domain, n); 2069e1add7ddSArun Ramadoss 2070e1add7ddSArun Ramadoss ret = request_threaded_irq(kirq->irq_num, NULL, ksz_irq_thread_fn, 207162e027fbSArun Ramadoss IRQF_ONESHOT, kirq->name, kirq); 2072e1add7ddSArun Ramadoss if (ret) 2073e1add7ddSArun Ramadoss goto out; 2074e1add7ddSArun Ramadoss 2075e1add7ddSArun Ramadoss return 0; 2076e1add7ddSArun Ramadoss 2077e1add7ddSArun Ramadoss out: 2078e1add7ddSArun Ramadoss ksz_irq_free(kirq); 2079e1add7ddSArun Ramadoss 2080e1add7ddSArun Ramadoss return ret; 2081e1add7ddSArun Ramadoss } 2082e1add7ddSArun Ramadoss 2083ff319a64SArun Ramadoss static int ksz_girq_setup(struct ksz_device *dev) 2084ff319a64SArun Ramadoss { 2085e1add7ddSArun Ramadoss struct ksz_irq *girq = &dev->girq; 2086ff319a64SArun Ramadoss 2087e1add7ddSArun Ramadoss girq->nirqs = dev->info->port_cnt; 2088e1add7ddSArun Ramadoss girq->reg_mask = REG_SW_PORT_INT_MASK__1; 2089e1add7ddSArun Ramadoss girq->reg_status = REG_SW_PORT_INT_STATUS__1; 2090e1add7ddSArun Ramadoss snprintf(girq->name, sizeof(girq->name), "global_port_irq"); 2091ff319a64SArun Ramadoss 2092e1add7ddSArun Ramadoss girq->irq_num = dev->irq; 2093ff319a64SArun Ramadoss 2094e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, girq); 2095ff319a64SArun Ramadoss } 2096ff319a64SArun Ramadoss 2097ff319a64SArun Ramadoss static int ksz_pirq_setup(struct ksz_device *dev, u8 p) 2098ff319a64SArun Ramadoss { 2099e1add7ddSArun Ramadoss struct ksz_irq *pirq = &dev->ports[p].pirq; 2100ff319a64SArun Ramadoss 2101e1add7ddSArun Ramadoss pirq->nirqs = dev->info->port_nirqs; 2102e1add7ddSArun Ramadoss pirq->reg_mask = dev->dev_ops->get_port_addr(p, REG_PORT_INT_MASK); 2103e1add7ddSArun Ramadoss pirq->reg_status = dev->dev_ops->get_port_addr(p, REG_PORT_INT_STATUS); 2104e1add7ddSArun Ramadoss snprintf(pirq->name, sizeof(pirq->name), "port_irq-%d", p); 2105ff319a64SArun Ramadoss 2106e1add7ddSArun Ramadoss pirq->irq_num = irq_find_mapping(dev->girq.domain, p); 2107e1add7ddSArun Ramadoss if (pirq->irq_num < 0) 2108e1add7ddSArun Ramadoss return pirq->irq_num; 2109ff319a64SArun Ramadoss 2110e1add7ddSArun Ramadoss return ksz_irq_common_setup(dev, pirq); 2111ff319a64SArun Ramadoss } 2112ff319a64SArun Ramadoss 21131958eee8SArun Ramadoss static int ksz_setup(struct dsa_switch *ds) 2114d2822e68SArun Ramadoss { 2115d2822e68SArun Ramadoss struct ksz_device *dev = ds->priv; 2116ff319a64SArun Ramadoss struct dsa_port *dp; 211715f7cfaeSVladimir Oltean struct ksz_port *p; 21189d95329cSArun Ramadoss const u16 *regs; 2119d2822e68SArun Ramadoss int ret; 2120d2822e68SArun Ramadoss 21219d95329cSArun Ramadoss regs = dev->info->regs; 21229d95329cSArun Ramadoss 2123d2822e68SArun Ramadoss dev->vlan_cache = devm_kcalloc(dev->dev, sizeof(struct vlan_table), 2124d2822e68SArun Ramadoss dev->info->num_vlans, GFP_KERNEL); 2125d2822e68SArun Ramadoss if (!dev->vlan_cache) 2126d2822e68SArun Ramadoss return -ENOMEM; 2127d2822e68SArun Ramadoss 2128d2822e68SArun Ramadoss ret = dev->dev_ops->reset(dev); 2129d2822e68SArun Ramadoss if (ret) { 2130d2822e68SArun Ramadoss dev_err(ds->dev, "failed to reset switch\n"); 2131d2822e68SArun Ramadoss return ret; 2132d2822e68SArun Ramadoss } 2133d2822e68SArun Ramadoss 21341ca6437fSArun Ramadoss /* set broadcast storm protection 10% rate */ 2135b8311f46SVladimir Oltean regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], 21361ca6437fSArun Ramadoss BROADCAST_STORM_RATE, 21371ca6437fSArun Ramadoss (BROADCAST_STORM_VALUE * 21381ca6437fSArun Ramadoss BROADCAST_STORM_PROT_RATE) / 100); 21391ca6437fSArun Ramadoss 2140d2822e68SArun Ramadoss dev->dev_ops->config_cpu_port(ds); 2141d2822e68SArun Ramadoss 2142d2822e68SArun Ramadoss dev->dev_ops->enable_stp_addr(dev); 2143d2822e68SArun Ramadoss 2144e30f33a5SArun Ramadoss ds->num_tx_queues = dev->info->num_tx_queues; 2145e30f33a5SArun Ramadoss 2146b8311f46SVladimir Oltean regmap_update_bits(ksz_regmap_8(dev), regs[S_MULTICAST_CTRL], 21470abab9f3SArun Ramadoss MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); 21480abab9f3SArun Ramadoss 2149d2822e68SArun Ramadoss ksz_init_mib_timer(dev); 2150d2822e68SArun Ramadoss 2151d2822e68SArun Ramadoss ds->configure_vlan_while_not_filtering = false; 2152d2822e68SArun Ramadoss 2153d2822e68SArun Ramadoss if (dev->dev_ops->setup) { 2154d2822e68SArun Ramadoss ret = dev->dev_ops->setup(ds); 2155d2822e68SArun Ramadoss if (ret) 2156d2822e68SArun Ramadoss return ret; 2157d2822e68SArun Ramadoss } 2158d2822e68SArun Ramadoss 215915f7cfaeSVladimir Oltean /* Start with learning disabled on standalone user ports, and enabled 216015f7cfaeSVladimir Oltean * on the CPU port. In lack of other finer mechanisms, learning on the 216115f7cfaeSVladimir Oltean * CPU port will avoid flooding bridge local addresses on the network 216215f7cfaeSVladimir Oltean * in some cases. 216315f7cfaeSVladimir Oltean */ 216415f7cfaeSVladimir Oltean p = &dev->ports[dev->cpu_port]; 216515f7cfaeSVladimir Oltean p->learning = true; 216615f7cfaeSVladimir Oltean 2167ff319a64SArun Ramadoss if (dev->irq > 0) { 2168ff319a64SArun Ramadoss ret = ksz_girq_setup(dev); 2169ff319a64SArun Ramadoss if (ret) 2170ff319a64SArun Ramadoss return ret; 2171ff319a64SArun Ramadoss 2172ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) { 2173ff319a64SArun Ramadoss ret = ksz_pirq_setup(dev, dp->index); 2174ff319a64SArun Ramadoss if (ret) 2175ff319a64SArun Ramadoss goto out_girq; 2176cc13ab18SArun Ramadoss 2177cc13ab18SArun Ramadoss ret = ksz_ptp_irq_setup(ds, dp->index); 2178cc13ab18SArun Ramadoss if (ret) 2179cc13ab18SArun Ramadoss goto out_pirq; 2180ff319a64SArun Ramadoss } 2181ff319a64SArun Ramadoss } 2182ff319a64SArun Ramadoss 2183eac1ea20SChristian Eggers ret = ksz_ptp_clock_register(ds); 2184eac1ea20SChristian Eggers if (ret) { 2185eac1ea20SChristian Eggers dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret); 2186cc13ab18SArun Ramadoss goto out_ptpirq; 2187eac1ea20SChristian Eggers } 2188eac1ea20SChristian Eggers 2189ff319a64SArun Ramadoss ret = ksz_mdio_register(dev); 2190ff319a64SArun Ramadoss if (ret < 0) { 2191ff319a64SArun Ramadoss dev_err(dev->dev, "failed to register the mdio"); 2192eac1ea20SChristian Eggers goto out_ptp_clock_unregister; 2193ff319a64SArun Ramadoss } 2194ff319a64SArun Ramadoss 2195ad08ac18SArun Ramadoss /* start switch */ 2196b8311f46SVladimir Oltean regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL], 2197ad08ac18SArun Ramadoss SW_START, SW_START); 2198ad08ac18SArun Ramadoss 2199d2822e68SArun Ramadoss return 0; 2200ff319a64SArun Ramadoss 2201eac1ea20SChristian Eggers out_ptp_clock_unregister: 2202eac1ea20SChristian Eggers ksz_ptp_clock_unregister(ds); 2203cc13ab18SArun Ramadoss out_ptpirq: 2204cc13ab18SArun Ramadoss if (dev->irq > 0) 2205cc13ab18SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2206cc13ab18SArun Ramadoss ksz_ptp_irq_free(ds, dp->index); 2207ff319a64SArun Ramadoss out_pirq: 2208ff319a64SArun Ramadoss if (dev->irq > 0) 2209ff319a64SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) 2210e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2211ff319a64SArun Ramadoss out_girq: 2212ff319a64SArun Ramadoss if (dev->irq > 0) 2213e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2214ff319a64SArun Ramadoss 2215ff319a64SArun Ramadoss return ret; 2216d2822e68SArun Ramadoss } 2217d2822e68SArun Ramadoss 2218c9cd961cSArun Ramadoss static void ksz_teardown(struct dsa_switch *ds) 2219c9cd961cSArun Ramadoss { 2220c9cd961cSArun Ramadoss struct ksz_device *dev = ds->priv; 2221ff319a64SArun Ramadoss struct dsa_port *dp; 2222ff319a64SArun Ramadoss 2223eac1ea20SChristian Eggers ksz_ptp_clock_unregister(ds); 2224eac1ea20SChristian Eggers 2225ff319a64SArun Ramadoss if (dev->irq > 0) { 2226cc13ab18SArun Ramadoss dsa_switch_for_each_user_port(dp, dev->ds) { 2227cc13ab18SArun Ramadoss ksz_ptp_irq_free(ds, dp->index); 2228cc13ab18SArun Ramadoss 2229e1add7ddSArun Ramadoss ksz_irq_free(&dev->ports[dp->index].pirq); 2230cc13ab18SArun Ramadoss } 2231ff319a64SArun Ramadoss 2232e1add7ddSArun Ramadoss ksz_irq_free(&dev->girq); 2233ff319a64SArun Ramadoss } 2234c9cd961cSArun Ramadoss 2235c9cd961cSArun Ramadoss if (dev->dev_ops->teardown) 2236c9cd961cSArun Ramadoss dev->dev_ops->teardown(ds); 2237c9cd961cSArun Ramadoss } 2238c9cd961cSArun Ramadoss 22397c6ff470STristram Ha static void port_r_cnt(struct ksz_device *dev, int port) 22407c6ff470STristram Ha { 22417c6ff470STristram Ha struct ksz_port_mib *mib = &dev->ports[port].mib; 22427c6ff470STristram Ha u64 *dropped; 22437c6ff470STristram Ha 22447c6ff470STristram Ha /* Some ports may not have MIB counters before SWITCH_COUNTER_NUM. */ 2245a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->reg_mib_cnt) { 22467c6ff470STristram Ha dev->dev_ops->r_mib_cnt(dev, port, mib->cnt_ptr, 22477c6ff470STristram Ha &mib->counters[mib->cnt_ptr]); 22487c6ff470STristram Ha ++mib->cnt_ptr; 22497c6ff470STristram Ha } 22507c6ff470STristram Ha 22517c6ff470STristram Ha /* last one in storage */ 2252a530e6f2SArun Ramadoss dropped = &mib->counters[dev->info->mib_cnt]; 22537c6ff470STristram Ha 22547c6ff470STristram Ha /* Some ports may not have MIB counters after SWITCH_COUNTER_NUM. */ 2255a530e6f2SArun Ramadoss while (mib->cnt_ptr < dev->info->mib_cnt) { 22567c6ff470STristram Ha dev->dev_ops->r_mib_pkt(dev, port, mib->cnt_ptr, 22577c6ff470STristram Ha dropped, &mib->counters[mib->cnt_ptr]); 22587c6ff470STristram Ha ++mib->cnt_ptr; 22597c6ff470STristram Ha } 22607c6ff470STristram Ha mib->cnt_ptr = 0; 22617c6ff470STristram Ha } 22627c6ff470STristram Ha 22637c6ff470STristram Ha static void ksz_mib_read_work(struct work_struct *work) 22647c6ff470STristram Ha { 22657c6ff470STristram Ha struct ksz_device *dev = container_of(work, struct ksz_device, 2266469b390eSGeorge McCollister mib_read.work); 22677c6ff470STristram Ha struct ksz_port_mib *mib; 22687c6ff470STristram Ha struct ksz_port *p; 22697c6ff470STristram Ha int i; 22707c6ff470STristram Ha 2271462d5250SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 22726bb9e376SRobert Hancock if (dsa_is_unused_port(dev->ds, i)) 22736bb9e376SRobert Hancock continue; 22746bb9e376SRobert Hancock 22757c6ff470STristram Ha p = &dev->ports[i]; 22767c6ff470STristram Ha mib = &p->mib; 22777c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 22787c6ff470STristram Ha 22797c6ff470STristram Ha /* Only read MIB counters when the port is told to do. 22807c6ff470STristram Ha * If not, read only dropped counters when link is not up. 22817c6ff470STristram Ha */ 22827c6ff470STristram Ha if (!p->read) { 22837c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(dev->ds, i); 22847c6ff470STristram Ha 22857c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2286a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 22877c6ff470STristram Ha } 22887c6ff470STristram Ha port_r_cnt(dev, i); 22897c6ff470STristram Ha p->read = false; 2290a7f4f13aSOleksij Rempel 2291a7f4f13aSOleksij Rempel if (dev->dev_ops->r_mib_stat64) 2292a7f4f13aSOleksij Rempel dev->dev_ops->r_mib_stat64(dev, i); 2293a7f4f13aSOleksij Rempel 22947c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 22957c6ff470STristram Ha } 22967c6ff470STristram Ha 2297469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, dev->mib_read_interval); 22987c6ff470STristram Ha } 22997c6ff470STristram Ha 23007c6ff470STristram Ha void ksz_init_mib_timer(struct ksz_device *dev) 23017c6ff470STristram Ha { 23027c6ff470STristram Ha int i; 23037c6ff470STristram Ha 2304469b390eSGeorge McCollister INIT_DELAYED_WORK(&dev->mib_read, ksz_mib_read_work); 2305469b390eSGeorge McCollister 2306b094c679SPrasanna Vengateshan for (i = 0; i < dev->info->port_cnt; i++) { 2307b094c679SPrasanna Vengateshan struct ksz_port_mib *mib = &dev->ports[i].mib; 2308b094c679SPrasanna Vengateshan 23097c6ff470STristram Ha dev->dev_ops->port_init_cnt(dev, i); 2310b094c679SPrasanna Vengateshan 2311b094c679SPrasanna Vengateshan mib->cnt_ptr = 0; 2312b094c679SPrasanna Vengateshan memset(mib->counters, 0, dev->info->mib_cnt * sizeof(u64)); 2313b094c679SPrasanna Vengateshan } 23147c6ff470STristram Ha } 23157c6ff470STristram Ha 23161958eee8SArun Ramadoss static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg) 2317b987e98eSWoojung Huh { 2318b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2319c2e86691STristram Ha u16 val = 0xffff; 23208f420456SOleksij Rempel int ret; 2321b987e98eSWoojung Huh 23228f420456SOleksij Rempel ret = dev->dev_ops->r_phy(dev, addr, reg, &val); 23238f420456SOleksij Rempel if (ret) 23248f420456SOleksij Rempel return ret; 2325b987e98eSWoojung Huh 2326b987e98eSWoojung Huh return val; 2327b987e98eSWoojung Huh } 2328b987e98eSWoojung Huh 23291958eee8SArun Ramadoss static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val) 2330b987e98eSWoojung Huh { 2331b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 23328f420456SOleksij Rempel int ret; 2333b987e98eSWoojung Huh 23348f420456SOleksij Rempel ret = dev->dev_ops->w_phy(dev, addr, reg, val); 23358f420456SOleksij Rempel if (ret) 23368f420456SOleksij Rempel return ret; 2337b987e98eSWoojung Huh 2338b987e98eSWoojung Huh return 0; 2339b987e98eSWoojung Huh } 2340b987e98eSWoojung Huh 23411958eee8SArun Ramadoss static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port) 23421fe94f54SArun Ramadoss { 23431fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 23441fe94f54SArun Ramadoss 23451fe94f54SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID) { 23461fe94f54SArun Ramadoss /* Silicon Errata Sheet (DS80000830A): 23471fe94f54SArun Ramadoss * Port 1 does not work with LinkMD Cable-Testing. 23481fe94f54SArun Ramadoss * Port 1 does not respond to received PAUSE control frames. 23491fe94f54SArun Ramadoss */ 23501fe94f54SArun Ramadoss if (!port) 23511fe94f54SArun Ramadoss return MICREL_KSZ8_P1_ERRATA; 23521fe94f54SArun Ramadoss } 23531fe94f54SArun Ramadoss 23541fe94f54SArun Ramadoss return 0; 23551fe94f54SArun Ramadoss } 23561fe94f54SArun Ramadoss 23571958eee8SArun Ramadoss static void ksz_mac_link_down(struct dsa_switch *ds, int port, 23581958eee8SArun Ramadoss unsigned int mode, phy_interface_t interface) 2359c30d894bSTristram Ha { 2360c30d894bSTristram Ha struct ksz_device *dev = ds->priv; 2361c30d894bSTristram Ha struct ksz_port *p = &dev->ports[port]; 2362c30d894bSTristram Ha 2363c30d894bSTristram Ha /* Read all MIB counters when the link is going down. */ 2364c30d894bSTristram Ha p->read = true; 23658098bd69SChristian Eggers /* timer started */ 23668098bd69SChristian Eggers if (dev->mib_read_interval) 2367469b390eSGeorge McCollister schedule_delayed_work(&dev->mib_read, 0); 2368143a102eSCodrin Ciubotariu } 2369143a102eSCodrin Ciubotariu 23701958eee8SArun Ramadoss static int ksz_sset_count(struct dsa_switch *ds, int port, int sset) 2371b987e98eSWoojung Huh { 2372b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2373b987e98eSWoojung Huh 237489f09048SFlorian Fainelli if (sset != ETH_SS_STATS) 237589f09048SFlorian Fainelli return 0; 237689f09048SFlorian Fainelli 2377a530e6f2SArun Ramadoss return dev->info->mib_cnt; 2378b987e98eSWoojung Huh } 2379b987e98eSWoojung Huh 23801958eee8SArun Ramadoss static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, 23811958eee8SArun Ramadoss uint64_t *buf) 23827c6ff470STristram Ha { 23837c6ff470STristram Ha const struct dsa_port *dp = dsa_to_port(ds, port); 23847c6ff470STristram Ha struct ksz_device *dev = ds->priv; 23857c6ff470STristram Ha struct ksz_port_mib *mib; 23867c6ff470STristram Ha 23877c6ff470STristram Ha mib = &dev->ports[port].mib; 23887c6ff470STristram Ha mutex_lock(&mib->cnt_mutex); 23897c6ff470STristram Ha 23907c6ff470STristram Ha /* Only read dropped counters if no link. */ 23917c6ff470STristram Ha if (!netif_carrier_ok(dp->slave)) 2392a530e6f2SArun Ramadoss mib->cnt_ptr = dev->info->reg_mib_cnt; 23937c6ff470STristram Ha port_r_cnt(dev, port); 2394a530e6f2SArun Ramadoss memcpy(buf, mib->counters, dev->info->mib_cnt * sizeof(u64)); 23957c6ff470STristram Ha mutex_unlock(&mib->cnt_mutex); 23967c6ff470STristram Ha } 23977c6ff470STristram Ha 23981958eee8SArun Ramadoss static int ksz_port_bridge_join(struct dsa_switch *ds, int port, 2399b079922bSVladimir Oltean struct dsa_bridge bridge, 240006b9cce4SVladimir Oltean bool *tx_fwd_offload, 240106b9cce4SVladimir Oltean struct netlink_ext_ack *extack) 2402b987e98eSWoojung Huh { 2403c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2404c2e86691STristram Ha * appropriate state so there is no need to do anything. 2405c2e86691STristram Ha */ 2406b987e98eSWoojung Huh 2407b987e98eSWoojung Huh return 0; 2408b987e98eSWoojung Huh } 2409b987e98eSWoojung Huh 24101958eee8SArun Ramadoss static void ksz_port_bridge_leave(struct dsa_switch *ds, int port, 2411d3eed0e5SVladimir Oltean struct dsa_bridge bridge) 2412c2e86691STristram Ha { 2413c2e86691STristram Ha /* port_stp_state_set() will be called after to put the port in 2414c2e86691STristram Ha * forwarding state so there is no need to do anything. 2415c2e86691STristram Ha */ 2416c2e86691STristram Ha } 2417c2e86691STristram Ha 24181958eee8SArun Ramadoss static void ksz_port_fast_age(struct dsa_switch *ds, int port) 2419c2e86691STristram Ha { 2420c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2421c2e86691STristram Ha 2422c2e86691STristram Ha dev->dev_ops->flush_dyn_mac_table(dev, port); 2423c2e86691STristram Ha } 2424c2e86691STristram Ha 24252c119d99SArun Ramadoss static int ksz_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) 24262c119d99SArun Ramadoss { 24272c119d99SArun Ramadoss struct ksz_device *dev = ds->priv; 24282c119d99SArun Ramadoss 24292c119d99SArun Ramadoss if (!dev->dev_ops->set_ageing_time) 24302c119d99SArun Ramadoss return -EOPNOTSUPP; 24312c119d99SArun Ramadoss 24322c119d99SArun Ramadoss return dev->dev_ops->set_ageing_time(dev, msecs); 24332c119d99SArun Ramadoss } 24342c119d99SArun Ramadoss 24351958eee8SArun Ramadoss static int ksz_port_fdb_add(struct dsa_switch *ds, int port, 24361958eee8SArun Ramadoss const unsigned char *addr, u16 vid, 24371958eee8SArun Ramadoss struct dsa_db db) 2438e587be75SArun Ramadoss { 2439e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2440e587be75SArun Ramadoss 2441e587be75SArun Ramadoss if (!dev->dev_ops->fdb_add) 2442e587be75SArun Ramadoss return -EOPNOTSUPP; 2443e587be75SArun Ramadoss 2444e587be75SArun Ramadoss return dev->dev_ops->fdb_add(dev, port, addr, vid, db); 2445e587be75SArun Ramadoss } 2446e587be75SArun Ramadoss 24471958eee8SArun Ramadoss static int ksz_port_fdb_del(struct dsa_switch *ds, int port, 24481958eee8SArun Ramadoss const unsigned char *addr, 24491958eee8SArun Ramadoss u16 vid, struct dsa_db db) 2450e587be75SArun Ramadoss { 2451e587be75SArun Ramadoss struct ksz_device *dev = ds->priv; 2452e587be75SArun Ramadoss 2453e587be75SArun Ramadoss if (!dev->dev_ops->fdb_del) 2454e587be75SArun Ramadoss return -EOPNOTSUPP; 2455e587be75SArun Ramadoss 2456e587be75SArun Ramadoss return dev->dev_ops->fdb_del(dev, port, addr, vid, db); 2457e587be75SArun Ramadoss } 2458e587be75SArun Ramadoss 24591958eee8SArun Ramadoss static int ksz_port_fdb_dump(struct dsa_switch *ds, int port, 24601958eee8SArun Ramadoss dsa_fdb_dump_cb_t *cb, void *data) 2461b987e98eSWoojung Huh { 2462b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2463b987e98eSWoojung Huh 2464e587be75SArun Ramadoss if (!dev->dev_ops->fdb_dump) 2465e587be75SArun Ramadoss return -EOPNOTSUPP; 2466b987e98eSWoojung Huh 2467e587be75SArun Ramadoss return dev->dev_ops->fdb_dump(dev, port, cb, data); 2468b987e98eSWoojung Huh } 2469b987e98eSWoojung Huh 24701958eee8SArun Ramadoss static int ksz_port_mdb_add(struct dsa_switch *ds, int port, 2471c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2472c2693363SVladimir Oltean struct dsa_db db) 2473b987e98eSWoojung Huh { 2474b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2475b987e98eSWoojung Huh 2476980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_add) 2477980c7d17SArun Ramadoss return -EOPNOTSUPP; 2478b987e98eSWoojung Huh 2479980c7d17SArun Ramadoss return dev->dev_ops->mdb_add(dev, port, mdb, db); 2480c2e86691STristram Ha } 2481c2e86691STristram Ha 24821958eee8SArun Ramadoss static int ksz_port_mdb_del(struct dsa_switch *ds, int port, 2483c2693363SVladimir Oltean const struct switchdev_obj_port_mdb *mdb, 2484c2693363SVladimir Oltean struct dsa_db db) 2485c2e86691STristram Ha { 2486c2e86691STristram Ha struct ksz_device *dev = ds->priv; 2487b987e98eSWoojung Huh 2488980c7d17SArun Ramadoss if (!dev->dev_ops->mdb_del) 2489980c7d17SArun Ramadoss return -EOPNOTSUPP; 2490b987e98eSWoojung Huh 2491980c7d17SArun Ramadoss return dev->dev_ops->mdb_del(dev, port, mdb, db); 2492b987e98eSWoojung Huh } 2493b987e98eSWoojung Huh 24941958eee8SArun Ramadoss static int ksz_enable_port(struct dsa_switch *ds, int port, 24951958eee8SArun Ramadoss struct phy_device *phy) 2496b987e98eSWoojung Huh { 2497b987e98eSWoojung Huh struct ksz_device *dev = ds->priv; 2498b987e98eSWoojung Huh 249974be4babSVivien Didelot if (!dsa_is_user_port(ds, port)) 250074be4babSVivien Didelot return 0; 250174be4babSVivien Didelot 2502c2e86691STristram Ha /* setup slave port */ 2503c2e86691STristram Ha dev->dev_ops->port_setup(dev, port, false); 2504b987e98eSWoojung Huh 2505c2e86691STristram Ha /* port_stp_state_set() will be called after to enable the port so 2506c2e86691STristram Ha * there is no need to do anything. 2507c2e86691STristram Ha */ 2508b987e98eSWoojung Huh 2509b987e98eSWoojung Huh return 0; 2510b987e98eSWoojung Huh } 2511b987e98eSWoojung Huh 2512e593df51SArun Ramadoss void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) 2513de6dd626SArun Ramadoss { 2514de6dd626SArun Ramadoss struct ksz_device *dev = ds->priv; 2515de6dd626SArun Ramadoss struct ksz_port *p; 25166877102fSArun Ramadoss const u16 *regs; 2517de6dd626SArun Ramadoss u8 data; 2518e593df51SArun Ramadoss 25196877102fSArun Ramadoss regs = dev->info->regs; 2520de6dd626SArun Ramadoss 25216877102fSArun Ramadoss ksz_pread8(dev, port, regs[P_STP_CTRL], &data); 2522de6dd626SArun Ramadoss data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2523de6dd626SArun Ramadoss 252415f7cfaeSVladimir Oltean p = &dev->ports[port]; 252515f7cfaeSVladimir Oltean 2526de6dd626SArun Ramadoss switch (state) { 2527de6dd626SArun Ramadoss case BR_STATE_DISABLED: 2528de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2529de6dd626SArun Ramadoss break; 2530de6dd626SArun Ramadoss case BR_STATE_LISTENING: 2531de6dd626SArun Ramadoss data |= (PORT_RX_ENABLE | PORT_LEARN_DISABLE); 2532de6dd626SArun Ramadoss break; 2533de6dd626SArun Ramadoss case BR_STATE_LEARNING: 2534de6dd626SArun Ramadoss data |= PORT_RX_ENABLE; 253515f7cfaeSVladimir Oltean if (!p->learning) 253615f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2537de6dd626SArun Ramadoss break; 2538de6dd626SArun Ramadoss case BR_STATE_FORWARDING: 2539de6dd626SArun Ramadoss data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); 254015f7cfaeSVladimir Oltean if (!p->learning) 254115f7cfaeSVladimir Oltean data |= PORT_LEARN_DISABLE; 2542de6dd626SArun Ramadoss break; 2543de6dd626SArun Ramadoss case BR_STATE_BLOCKING: 2544de6dd626SArun Ramadoss data |= PORT_LEARN_DISABLE; 2545de6dd626SArun Ramadoss break; 2546de6dd626SArun Ramadoss default: 2547de6dd626SArun Ramadoss dev_err(ds->dev, "invalid STP state: %d\n", state); 2548de6dd626SArun Ramadoss return; 2549de6dd626SArun Ramadoss } 2550de6dd626SArun Ramadoss 25516877102fSArun Ramadoss ksz_pwrite8(dev, port, regs[P_STP_CTRL], data); 2552de6dd626SArun Ramadoss 2553de6dd626SArun Ramadoss p->stp_state = state; 2554de6dd626SArun Ramadoss 2555de6dd626SArun Ramadoss ksz_update_port_member(dev, port); 2556de6dd626SArun Ramadoss } 2557de6dd626SArun Ramadoss 255815f7cfaeSVladimir Oltean static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port, 255915f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 256015f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 256115f7cfaeSVladimir Oltean { 256215f7cfaeSVladimir Oltean if (flags.mask & ~BR_LEARNING) 256315f7cfaeSVladimir Oltean return -EINVAL; 256415f7cfaeSVladimir Oltean 256515f7cfaeSVladimir Oltean return 0; 256615f7cfaeSVladimir Oltean } 256715f7cfaeSVladimir Oltean 256815f7cfaeSVladimir Oltean static int ksz_port_bridge_flags(struct dsa_switch *ds, int port, 256915f7cfaeSVladimir Oltean struct switchdev_brport_flags flags, 257015f7cfaeSVladimir Oltean struct netlink_ext_ack *extack) 257115f7cfaeSVladimir Oltean { 257215f7cfaeSVladimir Oltean struct ksz_device *dev = ds->priv; 257315f7cfaeSVladimir Oltean struct ksz_port *p = &dev->ports[port]; 257415f7cfaeSVladimir Oltean 257515f7cfaeSVladimir Oltean if (flags.mask & BR_LEARNING) { 257615f7cfaeSVladimir Oltean p->learning = !!(flags.val & BR_LEARNING); 257715f7cfaeSVladimir Oltean 257815f7cfaeSVladimir Oltean /* Make the change take effect immediately */ 257915f7cfaeSVladimir Oltean ksz_port_stp_state_set(ds, port, p->stp_state); 258015f7cfaeSVladimir Oltean } 258115f7cfaeSVladimir Oltean 258215f7cfaeSVladimir Oltean return 0; 258315f7cfaeSVladimir Oltean } 258415f7cfaeSVladimir Oltean 25851958eee8SArun Ramadoss static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds, 25861958eee8SArun Ramadoss int port, 25871958eee8SArun Ramadoss enum dsa_tag_protocol mp) 2588534a0431SArun Ramadoss { 2589534a0431SArun Ramadoss struct ksz_device *dev = ds->priv; 2590534a0431SArun Ramadoss enum dsa_tag_protocol proto = DSA_TAG_PROTO_NONE; 2591534a0431SArun Ramadoss 2592534a0431SArun Ramadoss if (dev->chip_id == KSZ8795_CHIP_ID || 2593534a0431SArun Ramadoss dev->chip_id == KSZ8794_CHIP_ID || 2594534a0431SArun Ramadoss dev->chip_id == KSZ8765_CHIP_ID) 2595534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ8795; 2596534a0431SArun Ramadoss 2597534a0431SArun Ramadoss if (dev->chip_id == KSZ8830_CHIP_ID || 2598b4490809SOleksij Rempel dev->chip_id == KSZ8563_CHIP_ID || 2599ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9893_CHIP_ID || 2600ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9563_CHIP_ID) 2601534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9893; 2602534a0431SArun Ramadoss 2603534a0431SArun Ramadoss if (dev->chip_id == KSZ9477_CHIP_ID || 26042eb3ff3cSRomain Naour dev->chip_id == KSZ9896_CHIP_ID || 2605534a0431SArun Ramadoss dev->chip_id == KSZ9897_CHIP_ID || 2606534a0431SArun Ramadoss dev->chip_id == KSZ9567_CHIP_ID) 2607534a0431SArun Ramadoss proto = DSA_TAG_PROTO_KSZ9477; 2608534a0431SArun Ramadoss 260999b16df0SArun Ramadoss if (is_lan937x(dev)) 261099b16df0SArun Ramadoss proto = DSA_TAG_PROTO_LAN937X_VALUE; 261199b16df0SArun Ramadoss 2612534a0431SArun Ramadoss return proto; 2613534a0431SArun Ramadoss } 2614534a0431SArun Ramadoss 2615ab32f56aSChristian Eggers static int ksz_connect_tag_protocol(struct dsa_switch *ds, 2616ab32f56aSChristian Eggers enum dsa_tag_protocol proto) 2617ab32f56aSChristian Eggers { 2618ab32f56aSChristian Eggers struct ksz_tagger_data *tagger_data; 2619ab32f56aSChristian Eggers 2620ab32f56aSChristian Eggers tagger_data = ksz_tagger_data(ds); 2621ab32f56aSChristian Eggers tagger_data->xmit_work_fn = ksz_port_deferred_xmit; 2622ab32f56aSChristian Eggers 2623ab32f56aSChristian Eggers return 0; 2624ab32f56aSChristian Eggers } 2625ab32f56aSChristian Eggers 26261958eee8SArun Ramadoss static int ksz_port_vlan_filtering(struct dsa_switch *ds, int port, 2627f0d997e3SArun Ramadoss bool flag, struct netlink_ext_ack *extack) 2628f0d997e3SArun Ramadoss { 2629f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2630f0d997e3SArun Ramadoss 2631f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_filtering) 2632f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2633f0d997e3SArun Ramadoss 2634f0d997e3SArun Ramadoss return dev->dev_ops->vlan_filtering(dev, port, flag, extack); 2635f0d997e3SArun Ramadoss } 2636f0d997e3SArun Ramadoss 26371958eee8SArun Ramadoss static int ksz_port_vlan_add(struct dsa_switch *ds, int port, 2638f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan, 2639f0d997e3SArun Ramadoss struct netlink_ext_ack *extack) 2640f0d997e3SArun Ramadoss { 2641f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2642f0d997e3SArun Ramadoss 2643f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_add) 2644f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2645f0d997e3SArun Ramadoss 2646f0d997e3SArun Ramadoss return dev->dev_ops->vlan_add(dev, port, vlan, extack); 2647f0d997e3SArun Ramadoss } 2648f0d997e3SArun Ramadoss 26491958eee8SArun Ramadoss static int ksz_port_vlan_del(struct dsa_switch *ds, int port, 2650f0d997e3SArun Ramadoss const struct switchdev_obj_port_vlan *vlan) 2651f0d997e3SArun Ramadoss { 2652f0d997e3SArun Ramadoss struct ksz_device *dev = ds->priv; 2653f0d997e3SArun Ramadoss 2654f0d997e3SArun Ramadoss if (!dev->dev_ops->vlan_del) 2655f0d997e3SArun Ramadoss return -EOPNOTSUPP; 2656f0d997e3SArun Ramadoss 2657f0d997e3SArun Ramadoss return dev->dev_ops->vlan_del(dev, port, vlan); 2658f0d997e3SArun Ramadoss } 2659f0d997e3SArun Ramadoss 26601958eee8SArun Ramadoss static int ksz_port_mirror_add(struct dsa_switch *ds, int port, 266100a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror, 266200a298bbSArun Ramadoss bool ingress, struct netlink_ext_ack *extack) 266300a298bbSArun Ramadoss { 266400a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 266500a298bbSArun Ramadoss 266600a298bbSArun Ramadoss if (!dev->dev_ops->mirror_add) 266700a298bbSArun Ramadoss return -EOPNOTSUPP; 266800a298bbSArun Ramadoss 266900a298bbSArun Ramadoss return dev->dev_ops->mirror_add(dev, port, mirror, ingress, extack); 267000a298bbSArun Ramadoss } 267100a298bbSArun Ramadoss 26721958eee8SArun Ramadoss static void ksz_port_mirror_del(struct dsa_switch *ds, int port, 267300a298bbSArun Ramadoss struct dsa_mall_mirror_tc_entry *mirror) 267400a298bbSArun Ramadoss { 267500a298bbSArun Ramadoss struct ksz_device *dev = ds->priv; 267600a298bbSArun Ramadoss 267700a298bbSArun Ramadoss if (dev->dev_ops->mirror_del) 267800a298bbSArun Ramadoss dev->dev_ops->mirror_del(dev, port, mirror); 267900a298bbSArun Ramadoss } 268000a298bbSArun Ramadoss 26811958eee8SArun Ramadoss static int ksz_change_mtu(struct dsa_switch *ds, int port, int mtu) 26821fe94f54SArun Ramadoss { 26831fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 26841fe94f54SArun Ramadoss 26851fe94f54SArun Ramadoss if (!dev->dev_ops->change_mtu) 26861fe94f54SArun Ramadoss return -EOPNOTSUPP; 26871fe94f54SArun Ramadoss 26881fe94f54SArun Ramadoss return dev->dev_ops->change_mtu(dev, port, mtu); 26891fe94f54SArun Ramadoss } 26901fe94f54SArun Ramadoss 26911958eee8SArun Ramadoss static int ksz_max_mtu(struct dsa_switch *ds, int port) 26921fe94f54SArun Ramadoss { 26931fe94f54SArun Ramadoss struct ksz_device *dev = ds->priv; 26941fe94f54SArun Ramadoss 2695838c19f8SOleksij Rempel switch (dev->chip_id) { 269629d1e85fSOleksij Rempel case KSZ8795_CHIP_ID: 269729d1e85fSOleksij Rempel case KSZ8794_CHIP_ID: 269829d1e85fSOleksij Rempel case KSZ8765_CHIP_ID: 269929d1e85fSOleksij Rempel return KSZ8795_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 270029d1e85fSOleksij Rempel case KSZ8830_CHIP_ID: 270129d1e85fSOleksij Rempel return KSZ8863_HUGE_PACKET_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 2702838c19f8SOleksij Rempel case KSZ8563_CHIP_ID: 2703838c19f8SOleksij Rempel case KSZ9477_CHIP_ID: 2704838c19f8SOleksij Rempel case KSZ9563_CHIP_ID: 2705838c19f8SOleksij Rempel case KSZ9567_CHIP_ID: 2706838c19f8SOleksij Rempel case KSZ9893_CHIP_ID: 2707838c19f8SOleksij Rempel case KSZ9896_CHIP_ID: 2708838c19f8SOleksij Rempel case KSZ9897_CHIP_ID: 2709838c19f8SOleksij Rempel case LAN9370_CHIP_ID: 2710838c19f8SOleksij Rempel case LAN9371_CHIP_ID: 2711838c19f8SOleksij Rempel case LAN9372_CHIP_ID: 2712838c19f8SOleksij Rempel case LAN9373_CHIP_ID: 2713838c19f8SOleksij Rempel case LAN9374_CHIP_ID: 2714838c19f8SOleksij Rempel return KSZ9477_MAX_FRAME_SIZE - VLAN_ETH_HLEN - ETH_FCS_LEN; 2715838c19f8SOleksij Rempel } 27161fe94f54SArun Ramadoss 2717838c19f8SOleksij Rempel return -EOPNOTSUPP; 27181fe94f54SArun Ramadoss } 27191fe94f54SArun Ramadoss 272069d3b36cSOleksij Rempel static int ksz_validate_eee(struct dsa_switch *ds, int port) 272169d3b36cSOleksij Rempel { 272269d3b36cSOleksij Rempel struct ksz_device *dev = ds->priv; 272369d3b36cSOleksij Rempel 272469d3b36cSOleksij Rempel if (!dev->info->internal_phy[port]) 272569d3b36cSOleksij Rempel return -EOPNOTSUPP; 272669d3b36cSOleksij Rempel 272769d3b36cSOleksij Rempel switch (dev->chip_id) { 272869d3b36cSOleksij Rempel case KSZ8563_CHIP_ID: 272969d3b36cSOleksij Rempel case KSZ9477_CHIP_ID: 273069d3b36cSOleksij Rempel case KSZ9563_CHIP_ID: 273169d3b36cSOleksij Rempel case KSZ9567_CHIP_ID: 273269d3b36cSOleksij Rempel case KSZ9893_CHIP_ID: 273369d3b36cSOleksij Rempel case KSZ9896_CHIP_ID: 273469d3b36cSOleksij Rempel case KSZ9897_CHIP_ID: 273569d3b36cSOleksij Rempel return 0; 273669d3b36cSOleksij Rempel } 273769d3b36cSOleksij Rempel 273869d3b36cSOleksij Rempel return -EOPNOTSUPP; 273969d3b36cSOleksij Rempel } 274069d3b36cSOleksij Rempel 274169d3b36cSOleksij Rempel static int ksz_get_mac_eee(struct dsa_switch *ds, int port, 274269d3b36cSOleksij Rempel struct ethtool_eee *e) 274369d3b36cSOleksij Rempel { 274469d3b36cSOleksij Rempel int ret; 274569d3b36cSOleksij Rempel 274669d3b36cSOleksij Rempel ret = ksz_validate_eee(ds, port); 274769d3b36cSOleksij Rempel if (ret) 274869d3b36cSOleksij Rempel return ret; 274969d3b36cSOleksij Rempel 275069d3b36cSOleksij Rempel /* There is no documented control of Tx LPI configuration. */ 275169d3b36cSOleksij Rempel e->tx_lpi_enabled = true; 275269d3b36cSOleksij Rempel 275369d3b36cSOleksij Rempel /* There is no documented control of Tx LPI timer. According to tests 275469d3b36cSOleksij Rempel * Tx LPI timer seems to be set by default to minimal value. 275569d3b36cSOleksij Rempel */ 275669d3b36cSOleksij Rempel e->tx_lpi_timer = 0; 275769d3b36cSOleksij Rempel 275869d3b36cSOleksij Rempel return 0; 275969d3b36cSOleksij Rempel } 276069d3b36cSOleksij Rempel 276169d3b36cSOleksij Rempel static int ksz_set_mac_eee(struct dsa_switch *ds, int port, 276269d3b36cSOleksij Rempel struct ethtool_eee *e) 276369d3b36cSOleksij Rempel { 276469d3b36cSOleksij Rempel struct ksz_device *dev = ds->priv; 276569d3b36cSOleksij Rempel int ret; 276669d3b36cSOleksij Rempel 276769d3b36cSOleksij Rempel ret = ksz_validate_eee(ds, port); 276869d3b36cSOleksij Rempel if (ret) 276969d3b36cSOleksij Rempel return ret; 277069d3b36cSOleksij Rempel 277169d3b36cSOleksij Rempel if (!e->tx_lpi_enabled) { 277269d3b36cSOleksij Rempel dev_err(dev->dev, "Disabling EEE Tx LPI is not supported\n"); 277369d3b36cSOleksij Rempel return -EINVAL; 277469d3b36cSOleksij Rempel } 277569d3b36cSOleksij Rempel 277669d3b36cSOleksij Rempel if (e->tx_lpi_timer) { 277769d3b36cSOleksij Rempel dev_err(dev->dev, "Setting EEE Tx LPI timer is not supported\n"); 277869d3b36cSOleksij Rempel return -EINVAL; 277969d3b36cSOleksij Rempel } 278069d3b36cSOleksij Rempel 278169d3b36cSOleksij Rempel return 0; 278269d3b36cSOleksij Rempel } 278369d3b36cSOleksij Rempel 2784f3d890f5SArun Ramadoss static void ksz_set_xmii(struct ksz_device *dev, int port, 2785f3d890f5SArun Ramadoss phy_interface_t interface) 2786dc1c596eSArun Ramadoss { 2787dc1c596eSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 2788b19ac41fSArun Ramadoss struct ksz_port *p = &dev->ports[port]; 2789dc1c596eSArun Ramadoss const u16 *regs = dev->info->regs; 2790dc1c596eSArun Ramadoss u8 data8; 2791dc1c596eSArun Ramadoss 2792dc1c596eSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 2793dc1c596eSArun Ramadoss 2794b19ac41fSArun Ramadoss data8 &= ~(P_MII_SEL_M | P_RGMII_ID_IG_ENABLE | 2795b19ac41fSArun Ramadoss P_RGMII_ID_EG_ENABLE); 2796dc1c596eSArun Ramadoss 2797dc1c596eSArun Ramadoss switch (interface) { 2798dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_MII: 2799dc1c596eSArun Ramadoss data8 |= bitval[P_MII_SEL]; 2800dc1c596eSArun Ramadoss break; 2801dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RMII: 2802dc1c596eSArun Ramadoss data8 |= bitval[P_RMII_SEL]; 2803dc1c596eSArun Ramadoss break; 2804dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_GMII: 2805dc1c596eSArun Ramadoss data8 |= bitval[P_GMII_SEL]; 2806dc1c596eSArun Ramadoss break; 2807dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII: 2808dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_ID: 2809dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_TXID: 2810dc1c596eSArun Ramadoss case PHY_INTERFACE_MODE_RGMII_RXID: 2811dc1c596eSArun Ramadoss data8 |= bitval[P_RGMII_SEL]; 28120ab7f6bfSArun Ramadoss /* On KSZ9893, disable RGMII in-band status support */ 281332cbac21SOleksij Rempel if (dev->chip_id == KSZ9893_CHIP_ID || 2814ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ8563_CHIP_ID || 2815ef912fe4SRakesh Sankaranarayanan dev->chip_id == KSZ9563_CHIP_ID) 28160ab7f6bfSArun Ramadoss data8 &= ~P_MII_MAC_MODE; 2817dc1c596eSArun Ramadoss break; 2818dc1c596eSArun Ramadoss default: 2819dc1c596eSArun Ramadoss dev_err(dev->dev, "Unsupported interface '%s' for port %d\n", 2820dc1c596eSArun Ramadoss phy_modes(interface), port); 2821dc1c596eSArun Ramadoss return; 2822dc1c596eSArun Ramadoss } 2823dc1c596eSArun Ramadoss 2824b19ac41fSArun Ramadoss if (p->rgmii_tx_val) 2825b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_EG_ENABLE; 2826b19ac41fSArun Ramadoss 2827b19ac41fSArun Ramadoss if (p->rgmii_rx_val) 2828b19ac41fSArun Ramadoss data8 |= P_RGMII_ID_IG_ENABLE; 2829b19ac41fSArun Ramadoss 2830dc1c596eSArun Ramadoss /* Write the updated value */ 2831dc1c596eSArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 2832dc1c596eSArun Ramadoss } 2833dc1c596eSArun Ramadoss 28340ab7f6bfSArun Ramadoss phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit) 28350ab7f6bfSArun Ramadoss { 28360ab7f6bfSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 28370ab7f6bfSArun Ramadoss const u16 *regs = dev->info->regs; 28380ab7f6bfSArun Ramadoss phy_interface_t interface; 28390ab7f6bfSArun Ramadoss u8 data8; 28400ab7f6bfSArun Ramadoss u8 val; 28410ab7f6bfSArun Ramadoss 28420ab7f6bfSArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 28430ab7f6bfSArun Ramadoss 28440ab7f6bfSArun Ramadoss val = FIELD_GET(P_MII_SEL_M, data8); 28450ab7f6bfSArun Ramadoss 28460ab7f6bfSArun Ramadoss if (val == bitval[P_MII_SEL]) { 28470ab7f6bfSArun Ramadoss if (gbit) 28480ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_GMII; 28490ab7f6bfSArun Ramadoss else 28500ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_MII; 28510ab7f6bfSArun Ramadoss } else if (val == bitval[P_RMII_SEL]) { 28520ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 28530ab7f6bfSArun Ramadoss } else { 28540ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII; 28550ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 28560ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_TXID; 28570ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_IG_ENABLE) { 28580ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_RXID; 28590ab7f6bfSArun Ramadoss if (data8 & P_RGMII_ID_EG_ENABLE) 28600ab7f6bfSArun Ramadoss interface = PHY_INTERFACE_MODE_RGMII_ID; 28610ab7f6bfSArun Ramadoss } 28620ab7f6bfSArun Ramadoss } 28630ab7f6bfSArun Ramadoss 28640ab7f6bfSArun Ramadoss return interface; 28650ab7f6bfSArun Ramadoss } 28660ab7f6bfSArun Ramadoss 2867a0cb1aa4SArun Ramadoss static void ksz_phylink_mac_config(struct dsa_switch *ds, int port, 2868a0cb1aa4SArun Ramadoss unsigned int mode, 2869a0cb1aa4SArun Ramadoss const struct phylink_link_state *state) 2870a0cb1aa4SArun Ramadoss { 2871a0cb1aa4SArun Ramadoss struct ksz_device *dev = ds->priv; 2872a0cb1aa4SArun Ramadoss 2873f3d890f5SArun Ramadoss if (ksz_is_ksz88x3(dev)) 2874f3d890f5SArun Ramadoss return; 2875f3d890f5SArun Ramadoss 2876f3d890f5SArun Ramadoss /* Internal PHYs */ 2877f3d890f5SArun Ramadoss if (dev->info->internal_phy[port]) 2878f3d890f5SArun Ramadoss return; 2879f3d890f5SArun Ramadoss 2880f3d890f5SArun Ramadoss if (phylink_autoneg_inband(mode)) { 2881f3d890f5SArun Ramadoss dev_err(dev->dev, "In-band AN not supported!\n"); 2882f3d890f5SArun Ramadoss return; 2883f3d890f5SArun Ramadoss } 2884f3d890f5SArun Ramadoss 2885f3d890f5SArun Ramadoss ksz_set_xmii(dev, port, state->interface); 2886f3d890f5SArun Ramadoss 2887a0cb1aa4SArun Ramadoss if (dev->dev_ops->phylink_mac_config) 2888a0cb1aa4SArun Ramadoss dev->dev_ops->phylink_mac_config(dev, port, mode, state); 2889b19ac41fSArun Ramadoss 2890b19ac41fSArun Ramadoss if (dev->dev_ops->setup_rgmii_delay) 2891b19ac41fSArun Ramadoss dev->dev_ops->setup_rgmii_delay(dev, port); 2892a0cb1aa4SArun Ramadoss } 2893a0cb1aa4SArun Ramadoss 289446f80fa8SArun Ramadoss bool ksz_get_gbit(struct ksz_device *dev, int port) 289546f80fa8SArun Ramadoss { 289646f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 289746f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 289846f80fa8SArun Ramadoss bool gbit = false; 289946f80fa8SArun Ramadoss u8 data8; 290046f80fa8SArun Ramadoss bool val; 290146f80fa8SArun Ramadoss 290246f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 290346f80fa8SArun Ramadoss 290446f80fa8SArun Ramadoss val = FIELD_GET(P_GMII_1GBIT_M, data8); 290546f80fa8SArun Ramadoss 290646f80fa8SArun Ramadoss if (val == bitval[P_GMII_1GBIT]) 290746f80fa8SArun Ramadoss gbit = true; 290846f80fa8SArun Ramadoss 290946f80fa8SArun Ramadoss return gbit; 291046f80fa8SArun Ramadoss } 291146f80fa8SArun Ramadoss 29120ab7f6bfSArun Ramadoss static void ksz_set_gbit(struct ksz_device *dev, int port, bool gbit) 291346f80fa8SArun Ramadoss { 291446f80fa8SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl1; 291546f80fa8SArun Ramadoss const u16 *regs = dev->info->regs; 291646f80fa8SArun Ramadoss u8 data8; 291746f80fa8SArun Ramadoss 291846f80fa8SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_1], &data8); 291946f80fa8SArun Ramadoss 292046f80fa8SArun Ramadoss data8 &= ~P_GMII_1GBIT_M; 292146f80fa8SArun Ramadoss 292246f80fa8SArun Ramadoss if (gbit) 292346f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_1GBIT]); 292446f80fa8SArun Ramadoss else 292546f80fa8SArun Ramadoss data8 |= FIELD_PREP(P_GMII_1GBIT_M, bitval[P_GMII_NOT_1GBIT]); 292646f80fa8SArun Ramadoss 292746f80fa8SArun Ramadoss /* Write the updated value */ 292846f80fa8SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_1], data8); 292946f80fa8SArun Ramadoss } 293046f80fa8SArun Ramadoss 2931aa5b8b73SArun Ramadoss static void ksz_set_100_10mbit(struct ksz_device *dev, int port, int speed) 2932aa5b8b73SArun Ramadoss { 2933aa5b8b73SArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 2934aa5b8b73SArun Ramadoss const u16 *regs = dev->info->regs; 2935aa5b8b73SArun Ramadoss u8 data8; 2936aa5b8b73SArun Ramadoss 2937aa5b8b73SArun Ramadoss ksz_pread8(dev, port, regs[P_XMII_CTRL_0], &data8); 2938aa5b8b73SArun Ramadoss 2939aa5b8b73SArun Ramadoss data8 &= ~P_MII_100MBIT_M; 2940aa5b8b73SArun Ramadoss 2941aa5b8b73SArun Ramadoss if (speed == SPEED_100) 2942aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_100MBIT]); 2943aa5b8b73SArun Ramadoss else 2944aa5b8b73SArun Ramadoss data8 |= FIELD_PREP(P_MII_100MBIT_M, bitval[P_MII_10MBIT]); 2945aa5b8b73SArun Ramadoss 2946aa5b8b73SArun Ramadoss /* Write the updated value */ 2947aa5b8b73SArun Ramadoss ksz_pwrite8(dev, port, regs[P_XMII_CTRL_0], data8); 2948aa5b8b73SArun Ramadoss } 2949aa5b8b73SArun Ramadoss 2950da8cd085SArun Ramadoss static void ksz_port_set_xmii_speed(struct ksz_device *dev, int port, int speed) 2951aa5b8b73SArun Ramadoss { 2952aa5b8b73SArun Ramadoss if (speed == SPEED_1000) 2953aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, true); 2954aa5b8b73SArun Ramadoss else 2955aa5b8b73SArun Ramadoss ksz_set_gbit(dev, port, false); 2956aa5b8b73SArun Ramadoss 2957aa5b8b73SArun Ramadoss if (speed == SPEED_100 || speed == SPEED_10) 2958aa5b8b73SArun Ramadoss ksz_set_100_10mbit(dev, port, speed); 2959aa5b8b73SArun Ramadoss } 2960aa5b8b73SArun Ramadoss 2961da8cd085SArun Ramadoss static void ksz_duplex_flowctrl(struct ksz_device *dev, int port, int duplex, 29628560664fSArun Ramadoss bool tx_pause, bool rx_pause) 29638560664fSArun Ramadoss { 29648560664fSArun Ramadoss const u8 *bitval = dev->info->xmii_ctrl0; 29658560664fSArun Ramadoss const u32 *masks = dev->info->masks; 29668560664fSArun Ramadoss const u16 *regs = dev->info->regs; 29678560664fSArun Ramadoss u8 mask; 29688560664fSArun Ramadoss u8 val; 29698560664fSArun Ramadoss 29708560664fSArun Ramadoss mask = P_MII_DUPLEX_M | masks[P_MII_TX_FLOW_CTRL] | 29718560664fSArun Ramadoss masks[P_MII_RX_FLOW_CTRL]; 29728560664fSArun Ramadoss 29738560664fSArun Ramadoss if (duplex == DUPLEX_FULL) 29748560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_FULL_DUPLEX]); 29758560664fSArun Ramadoss else 29768560664fSArun Ramadoss val = FIELD_PREP(P_MII_DUPLEX_M, bitval[P_MII_HALF_DUPLEX]); 29778560664fSArun Ramadoss 29788560664fSArun Ramadoss if (tx_pause) 29798560664fSArun Ramadoss val |= masks[P_MII_TX_FLOW_CTRL]; 29808560664fSArun Ramadoss 29818560664fSArun Ramadoss if (rx_pause) 29828560664fSArun Ramadoss val |= masks[P_MII_RX_FLOW_CTRL]; 29838560664fSArun Ramadoss 29848560664fSArun Ramadoss ksz_prmw8(dev, port, regs[P_XMII_CTRL_0], mask, val); 29858560664fSArun Ramadoss } 29868560664fSArun Ramadoss 29873015c503SOleksij Rempel static void ksz9477_phylink_mac_link_up(struct ksz_device *dev, int port, 2988f597d3adSArun Ramadoss unsigned int mode, 2989f597d3adSArun Ramadoss phy_interface_t interface, 2990f597d3adSArun Ramadoss struct phy_device *phydev, int speed, 29913015c503SOleksij Rempel int duplex, bool tx_pause, 29923015c503SOleksij Rempel bool rx_pause) 2993f597d3adSArun Ramadoss { 2994da8cd085SArun Ramadoss struct ksz_port *p; 2995da8cd085SArun Ramadoss 2996da8cd085SArun Ramadoss p = &dev->ports[port]; 2997da8cd085SArun Ramadoss 2998da8cd085SArun Ramadoss /* Internal PHYs */ 2999da8cd085SArun Ramadoss if (dev->info->internal_phy[port]) 3000da8cd085SArun Ramadoss return; 3001da8cd085SArun Ramadoss 3002da8cd085SArun Ramadoss p->phydev.speed = speed; 3003da8cd085SArun Ramadoss 3004da8cd085SArun Ramadoss ksz_port_set_xmii_speed(dev, port, speed); 3005da8cd085SArun Ramadoss 3006da8cd085SArun Ramadoss ksz_duplex_flowctrl(dev, port, duplex, tx_pause, rx_pause); 30073015c503SOleksij Rempel } 30083015c503SOleksij Rempel 30093015c503SOleksij Rempel static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port, 30103015c503SOleksij Rempel unsigned int mode, 30113015c503SOleksij Rempel phy_interface_t interface, 30123015c503SOleksij Rempel struct phy_device *phydev, int speed, 30133015c503SOleksij Rempel int duplex, bool tx_pause, bool rx_pause) 30143015c503SOleksij Rempel { 30153015c503SOleksij Rempel struct ksz_device *dev = ds->priv; 3016f597d3adSArun Ramadoss 3017f597d3adSArun Ramadoss if (dev->dev_ops->phylink_mac_link_up) 3018f597d3adSArun Ramadoss dev->dev_ops->phylink_mac_link_up(dev, port, mode, interface, 3019f597d3adSArun Ramadoss phydev, speed, duplex, 3020f597d3adSArun Ramadoss tx_pause, rx_pause); 3021f597d3adSArun Ramadoss } 3022f597d3adSArun Ramadoss 302391a98917SArun Ramadoss static int ksz_switch_detect(struct ksz_device *dev) 302491a98917SArun Ramadoss { 3025b4490809SOleksij Rempel u8 id1, id2, id4; 302691a98917SArun Ramadoss u16 id16; 302791a98917SArun Ramadoss u32 id32; 302891a98917SArun Ramadoss int ret; 302991a98917SArun Ramadoss 303091a98917SArun Ramadoss /* read chip id */ 303191a98917SArun Ramadoss ret = ksz_read16(dev, REG_CHIP_ID0, &id16); 303291a98917SArun Ramadoss if (ret) 303391a98917SArun Ramadoss return ret; 303491a98917SArun Ramadoss 303591a98917SArun Ramadoss id1 = FIELD_GET(SW_FAMILY_ID_M, id16); 303691a98917SArun Ramadoss id2 = FIELD_GET(SW_CHIP_ID_M, id16); 303791a98917SArun Ramadoss 303891a98917SArun Ramadoss switch (id1) { 303991a98917SArun Ramadoss case KSZ87_FAMILY_ID: 304091a98917SArun Ramadoss if (id2 == KSZ87_CHIP_ID_95) { 304191a98917SArun Ramadoss u8 val; 304291a98917SArun Ramadoss 304391a98917SArun Ramadoss dev->chip_id = KSZ8795_CHIP_ID; 304491a98917SArun Ramadoss 304591a98917SArun Ramadoss ksz_read8(dev, KSZ8_PORT_STATUS_0, &val); 304691a98917SArun Ramadoss if (val & KSZ8_PORT_FIBER_MODE) 304791a98917SArun Ramadoss dev->chip_id = KSZ8765_CHIP_ID; 304891a98917SArun Ramadoss } else if (id2 == KSZ87_CHIP_ID_94) { 304991a98917SArun Ramadoss dev->chip_id = KSZ8794_CHIP_ID; 305091a98917SArun Ramadoss } else { 305191a98917SArun Ramadoss return -ENODEV; 305291a98917SArun Ramadoss } 305391a98917SArun Ramadoss break; 305491a98917SArun Ramadoss case KSZ88_FAMILY_ID: 305591a98917SArun Ramadoss if (id2 == KSZ88_CHIP_ID_63) 305691a98917SArun Ramadoss dev->chip_id = KSZ8830_CHIP_ID; 305791a98917SArun Ramadoss else 305891a98917SArun Ramadoss return -ENODEV; 305991a98917SArun Ramadoss break; 306091a98917SArun Ramadoss default: 306191a98917SArun Ramadoss ret = ksz_read32(dev, REG_CHIP_ID0, &id32); 306291a98917SArun Ramadoss if (ret) 306391a98917SArun Ramadoss return ret; 306491a98917SArun Ramadoss 306591a98917SArun Ramadoss dev->chip_rev = FIELD_GET(SW_REV_ID_M, id32); 306691a98917SArun Ramadoss id32 &= ~0xFF; 306791a98917SArun Ramadoss 306891a98917SArun Ramadoss switch (id32) { 306991a98917SArun Ramadoss case KSZ9477_CHIP_ID: 30702eb3ff3cSRomain Naour case KSZ9896_CHIP_ID: 307191a98917SArun Ramadoss case KSZ9897_CHIP_ID: 307291a98917SArun Ramadoss case KSZ9567_CHIP_ID: 307391a98917SArun Ramadoss case LAN9370_CHIP_ID: 307491a98917SArun Ramadoss case LAN9371_CHIP_ID: 307591a98917SArun Ramadoss case LAN9372_CHIP_ID: 307691a98917SArun Ramadoss case LAN9373_CHIP_ID: 307791a98917SArun Ramadoss case LAN9374_CHIP_ID: 307891a98917SArun Ramadoss dev->chip_id = id32; 307991a98917SArun Ramadoss break; 3080b4490809SOleksij Rempel case KSZ9893_CHIP_ID: 3081b4490809SOleksij Rempel ret = ksz_read8(dev, REG_CHIP_ID4, 3082b4490809SOleksij Rempel &id4); 3083b4490809SOleksij Rempel if (ret) 3084b4490809SOleksij Rempel return ret; 3085b4490809SOleksij Rempel 3086b4490809SOleksij Rempel if (id4 == SKU_ID_KSZ8563) 3087b4490809SOleksij Rempel dev->chip_id = KSZ8563_CHIP_ID; 3088ef912fe4SRakesh Sankaranarayanan else if (id4 == SKU_ID_KSZ9563) 3089ef912fe4SRakesh Sankaranarayanan dev->chip_id = KSZ9563_CHIP_ID; 3090b4490809SOleksij Rempel else 3091b4490809SOleksij Rempel dev->chip_id = KSZ9893_CHIP_ID; 3092b4490809SOleksij Rempel 3093b4490809SOleksij Rempel break; 309491a98917SArun Ramadoss default: 309591a98917SArun Ramadoss dev_err(dev->dev, 309691a98917SArun Ramadoss "unsupported switch detected %x)\n", id32); 309791a98917SArun Ramadoss return -ENODEV; 309891a98917SArun Ramadoss } 309991a98917SArun Ramadoss } 310091a98917SArun Ramadoss return 0; 310191a98917SArun Ramadoss } 310291a98917SArun Ramadoss 310371d7920fSArun Ramadoss /* Bandwidth is calculated by idle slope/transmission speed. Then the Bandwidth 310471d7920fSArun Ramadoss * is converted to Hex-decimal using the successive multiplication method. On 310571d7920fSArun Ramadoss * every step, integer part is taken and decimal part is carry forwarded. 310671d7920fSArun Ramadoss */ 310771d7920fSArun Ramadoss static int cinc_cal(s32 idle_slope, s32 send_slope, u32 *bw) 310871d7920fSArun Ramadoss { 310971d7920fSArun Ramadoss u32 cinc = 0; 311071d7920fSArun Ramadoss u32 txrate; 311171d7920fSArun Ramadoss u32 rate; 311271d7920fSArun Ramadoss u8 temp; 311371d7920fSArun Ramadoss u8 i; 311471d7920fSArun Ramadoss 311571d7920fSArun Ramadoss txrate = idle_slope - send_slope; 311671d7920fSArun Ramadoss 311771d7920fSArun Ramadoss if (!txrate) 311871d7920fSArun Ramadoss return -EINVAL; 311971d7920fSArun Ramadoss 312071d7920fSArun Ramadoss rate = idle_slope; 312171d7920fSArun Ramadoss 312271d7920fSArun Ramadoss /* 24 bit register */ 312371d7920fSArun Ramadoss for (i = 0; i < 6; i++) { 312471d7920fSArun Ramadoss rate = rate * 16; 312571d7920fSArun Ramadoss 312671d7920fSArun Ramadoss temp = rate / txrate; 312771d7920fSArun Ramadoss 312871d7920fSArun Ramadoss rate %= txrate; 312971d7920fSArun Ramadoss 313071d7920fSArun Ramadoss cinc = ((cinc << 4) | temp); 313171d7920fSArun Ramadoss } 313271d7920fSArun Ramadoss 313371d7920fSArun Ramadoss *bw = cinc; 313471d7920fSArun Ramadoss 313571d7920fSArun Ramadoss return 0; 313671d7920fSArun Ramadoss } 313771d7920fSArun Ramadoss 313869444581SOleksij Rempel static int ksz_setup_tc_mode(struct ksz_device *dev, int port, u8 scheduler, 313969444581SOleksij Rempel u8 shaper) 314069444581SOleksij Rempel { 314169444581SOleksij Rempel return ksz_pwrite8(dev, port, REG_PORT_MTI_QUEUE_CTRL_0, 314269444581SOleksij Rempel FIELD_PREP(MTI_SCHEDULE_MODE_M, scheduler) | 314369444581SOleksij Rempel FIELD_PREP(MTI_SHAPING_M, shaper)); 314469444581SOleksij Rempel } 314569444581SOleksij Rempel 314671d7920fSArun Ramadoss static int ksz_setup_tc_cbs(struct dsa_switch *ds, int port, 314771d7920fSArun Ramadoss struct tc_cbs_qopt_offload *qopt) 314871d7920fSArun Ramadoss { 314971d7920fSArun Ramadoss struct ksz_device *dev = ds->priv; 315071d7920fSArun Ramadoss int ret; 315171d7920fSArun Ramadoss u32 bw; 315271d7920fSArun Ramadoss 315371d7920fSArun Ramadoss if (!dev->info->tc_cbs_supported) 315471d7920fSArun Ramadoss return -EOPNOTSUPP; 315571d7920fSArun Ramadoss 315671d7920fSArun Ramadoss if (qopt->queue > dev->info->num_tx_queues) 315771d7920fSArun Ramadoss return -EINVAL; 315871d7920fSArun Ramadoss 315971d7920fSArun Ramadoss /* Queue Selection */ 316071d7920fSArun Ramadoss ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, qopt->queue); 316171d7920fSArun Ramadoss if (ret) 316271d7920fSArun Ramadoss return ret; 316371d7920fSArun Ramadoss 316471d7920fSArun Ramadoss if (!qopt->enable) 316569444581SOleksij Rempel return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_WRR, 316669444581SOleksij Rempel MTI_SHAPING_OFF); 316771d7920fSArun Ramadoss 316871d7920fSArun Ramadoss /* High Credit */ 316971d7920fSArun Ramadoss ret = ksz_pwrite16(dev, port, REG_PORT_MTI_HI_WATER_MARK, 317071d7920fSArun Ramadoss qopt->hicredit); 317171d7920fSArun Ramadoss if (ret) 317271d7920fSArun Ramadoss return ret; 317371d7920fSArun Ramadoss 317471d7920fSArun Ramadoss /* Low Credit */ 317571d7920fSArun Ramadoss ret = ksz_pwrite16(dev, port, REG_PORT_MTI_LO_WATER_MARK, 317671d7920fSArun Ramadoss qopt->locredit); 317771d7920fSArun Ramadoss if (ret) 317871d7920fSArun Ramadoss return ret; 317971d7920fSArun Ramadoss 318071d7920fSArun Ramadoss /* Credit Increment Register */ 318171d7920fSArun Ramadoss ret = cinc_cal(qopt->idleslope, qopt->sendslope, &bw); 318271d7920fSArun Ramadoss if (ret) 318371d7920fSArun Ramadoss return ret; 318471d7920fSArun Ramadoss 318571d7920fSArun Ramadoss if (dev->dev_ops->tc_cbs_set_cinc) { 318671d7920fSArun Ramadoss ret = dev->dev_ops->tc_cbs_set_cinc(dev, port, bw); 318771d7920fSArun Ramadoss if (ret) 318871d7920fSArun Ramadoss return ret; 318971d7920fSArun Ramadoss } 319071d7920fSArun Ramadoss 319169444581SOleksij Rempel return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_STRICT_PRIO, 319269444581SOleksij Rempel MTI_SHAPING_SRP); 319371d7920fSArun Ramadoss } 319471d7920fSArun Ramadoss 3195c570f861SOleksij Rempel static int ksz_disable_egress_rate_limit(struct ksz_device *dev, int port) 3196c570f861SOleksij Rempel { 3197c570f861SOleksij Rempel int queue, ret; 3198c570f861SOleksij Rempel 3199c570f861SOleksij Rempel /* Configuration will not take effect until the last Port Queue X 3200c570f861SOleksij Rempel * Egress Limit Control Register is written. 3201c570f861SOleksij Rempel */ 3202c570f861SOleksij Rempel for (queue = 0; queue < dev->info->num_tx_queues; queue++) { 3203c570f861SOleksij Rempel ret = ksz_pwrite8(dev, port, KSZ9477_REG_PORT_OUT_RATE_0 + queue, 3204c570f861SOleksij Rempel KSZ9477_OUT_RATE_NO_LIMIT); 3205c570f861SOleksij Rempel if (ret) 3206c570f861SOleksij Rempel return ret; 3207c570f861SOleksij Rempel } 3208c570f861SOleksij Rempel 3209c570f861SOleksij Rempel return 0; 3210c570f861SOleksij Rempel } 3211c570f861SOleksij Rempel 3212c570f861SOleksij Rempel static int ksz_ets_band_to_queue(struct tc_ets_qopt_offload_replace_params *p, 3213c570f861SOleksij Rempel int band) 3214c570f861SOleksij Rempel { 3215c570f861SOleksij Rempel /* Compared to queues, bands prioritize packets differently. In strict 3216c570f861SOleksij Rempel * priority mode, the lowest priority is assigned to Queue 0 while the 3217c570f861SOleksij Rempel * highest priority is given to Band 0. 3218c570f861SOleksij Rempel */ 3219c570f861SOleksij Rempel return p->bands - 1 - band; 3220c570f861SOleksij Rempel } 3221c570f861SOleksij Rempel 3222c570f861SOleksij Rempel static int ksz_queue_set_strict(struct ksz_device *dev, int port, int queue) 3223c570f861SOleksij Rempel { 3224c570f861SOleksij Rempel int ret; 3225c570f861SOleksij Rempel 3226c570f861SOleksij Rempel ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, queue); 3227c570f861SOleksij Rempel if (ret) 3228c570f861SOleksij Rempel return ret; 3229c570f861SOleksij Rempel 3230c570f861SOleksij Rempel return ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_STRICT_PRIO, 3231c570f861SOleksij Rempel MTI_SHAPING_OFF); 3232c570f861SOleksij Rempel } 3233c570f861SOleksij Rempel 3234c570f861SOleksij Rempel static int ksz_queue_set_wrr(struct ksz_device *dev, int port, int queue, 3235c570f861SOleksij Rempel int weight) 3236c570f861SOleksij Rempel { 3237c570f861SOleksij Rempel int ret; 3238c570f861SOleksij Rempel 3239c570f861SOleksij Rempel ret = ksz_pwrite32(dev, port, REG_PORT_MTI_QUEUE_INDEX__4, queue); 3240c570f861SOleksij Rempel if (ret) 3241c570f861SOleksij Rempel return ret; 3242c570f861SOleksij Rempel 3243c570f861SOleksij Rempel ret = ksz_setup_tc_mode(dev, port, MTI_SCHEDULE_WRR, 3244c570f861SOleksij Rempel MTI_SHAPING_OFF); 3245c570f861SOleksij Rempel if (ret) 3246c570f861SOleksij Rempel return ret; 3247c570f861SOleksij Rempel 3248c570f861SOleksij Rempel return ksz_pwrite8(dev, port, KSZ9477_PORT_MTI_QUEUE_CTRL_1, weight); 3249c570f861SOleksij Rempel } 3250c570f861SOleksij Rempel 3251c570f861SOleksij Rempel static int ksz_tc_ets_add(struct ksz_device *dev, int port, 3252c570f861SOleksij Rempel struct tc_ets_qopt_offload_replace_params *p) 3253c570f861SOleksij Rempel { 3254c570f861SOleksij Rempel int ret, band, tc_prio; 3255c570f861SOleksij Rempel u32 queue_map = 0; 3256c570f861SOleksij Rempel 3257c570f861SOleksij Rempel /* In order to ensure proper prioritization, it is necessary to set the 3258c570f861SOleksij Rempel * rate limit for the related queue to zero. Otherwise strict priority 3259c570f861SOleksij Rempel * or WRR mode will not work. This is a hardware limitation. 3260c570f861SOleksij Rempel */ 3261c570f861SOleksij Rempel ret = ksz_disable_egress_rate_limit(dev, port); 3262c570f861SOleksij Rempel if (ret) 3263c570f861SOleksij Rempel return ret; 3264c570f861SOleksij Rempel 3265c570f861SOleksij Rempel /* Configure queue scheduling mode for all bands. Currently only strict 3266c570f861SOleksij Rempel * prio mode is supported. 3267c570f861SOleksij Rempel */ 3268c570f861SOleksij Rempel for (band = 0; band < p->bands; band++) { 3269c570f861SOleksij Rempel int queue = ksz_ets_band_to_queue(p, band); 3270c570f861SOleksij Rempel 3271c570f861SOleksij Rempel ret = ksz_queue_set_strict(dev, port, queue); 3272c570f861SOleksij Rempel if (ret) 3273c570f861SOleksij Rempel return ret; 3274c570f861SOleksij Rempel } 3275c570f861SOleksij Rempel 3276c570f861SOleksij Rempel /* Configure the mapping between traffic classes and queues. Note: 3277c570f861SOleksij Rempel * priomap variable support 16 traffic classes, but the chip can handle 3278c570f861SOleksij Rempel * only 8 classes. 3279c570f861SOleksij Rempel */ 3280c570f861SOleksij Rempel for (tc_prio = 0; tc_prio < ARRAY_SIZE(p->priomap); tc_prio++) { 3281c570f861SOleksij Rempel int queue; 3282c570f861SOleksij Rempel 3283c570f861SOleksij Rempel if (tc_prio > KSZ9477_MAX_TC_PRIO) 3284c570f861SOleksij Rempel break; 3285c570f861SOleksij Rempel 3286c570f861SOleksij Rempel queue = ksz_ets_band_to_queue(p, p->priomap[tc_prio]); 3287c570f861SOleksij Rempel queue_map |= queue << (tc_prio * KSZ9477_PORT_TC_MAP_S); 3288c570f861SOleksij Rempel } 3289c570f861SOleksij Rempel 3290c570f861SOleksij Rempel return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map); 3291c570f861SOleksij Rempel } 3292c570f861SOleksij Rempel 3293c570f861SOleksij Rempel static int ksz_tc_ets_del(struct ksz_device *dev, int port) 3294c570f861SOleksij Rempel { 3295c570f861SOleksij Rempel int ret, queue, tc_prio, s; 3296c570f861SOleksij Rempel u32 queue_map = 0; 3297c570f861SOleksij Rempel 3298c570f861SOleksij Rempel /* To restore the default chip configuration, set all queues to use the 3299c570f861SOleksij Rempel * WRR scheduler with a weight of 1. 3300c570f861SOleksij Rempel */ 3301c570f861SOleksij Rempel for (queue = 0; queue < dev->info->num_tx_queues; queue++) { 3302c570f861SOleksij Rempel ret = ksz_queue_set_wrr(dev, port, queue, 3303c570f861SOleksij Rempel KSZ9477_DEFAULT_WRR_WEIGHT); 3304c570f861SOleksij Rempel if (ret) 3305c570f861SOleksij Rempel return ret; 3306c570f861SOleksij Rempel } 3307c570f861SOleksij Rempel 3308c570f861SOleksij Rempel switch (dev->info->num_tx_queues) { 3309c570f861SOleksij Rempel case 2: 3310c570f861SOleksij Rempel s = 2; 3311c570f861SOleksij Rempel break; 3312c570f861SOleksij Rempel case 4: 3313c570f861SOleksij Rempel s = 1; 3314c570f861SOleksij Rempel break; 3315c570f861SOleksij Rempel case 8: 3316c570f861SOleksij Rempel s = 0; 3317c570f861SOleksij Rempel break; 3318c570f861SOleksij Rempel default: 3319c570f861SOleksij Rempel return -EINVAL; 3320c570f861SOleksij Rempel } 3321c570f861SOleksij Rempel 3322c570f861SOleksij Rempel /* Revert the queue mapping for TC-priority to its default setting on 3323c570f861SOleksij Rempel * the chip. 3324c570f861SOleksij Rempel */ 3325c570f861SOleksij Rempel for (tc_prio = 0; tc_prio <= KSZ9477_MAX_TC_PRIO; tc_prio++) { 3326c570f861SOleksij Rempel int queue; 3327c570f861SOleksij Rempel 3328c570f861SOleksij Rempel queue = tc_prio >> s; 3329c570f861SOleksij Rempel queue_map |= queue << (tc_prio * KSZ9477_PORT_TC_MAP_S); 3330c570f861SOleksij Rempel } 3331c570f861SOleksij Rempel 3332c570f861SOleksij Rempel return ksz_pwrite32(dev, port, KSZ9477_PORT_MRI_TC_MAP__4, queue_map); 3333c570f861SOleksij Rempel } 3334c570f861SOleksij Rempel 3335c570f861SOleksij Rempel static int ksz_tc_ets_validate(struct ksz_device *dev, int port, 3336c570f861SOleksij Rempel struct tc_ets_qopt_offload_replace_params *p) 3337c570f861SOleksij Rempel { 3338c570f861SOleksij Rempel int band; 3339c570f861SOleksij Rempel 3340c570f861SOleksij Rempel /* Since it is not feasible to share one port among multiple qdisc, 3341c570f861SOleksij Rempel * the user must configure all available queues appropriately. 3342c570f861SOleksij Rempel */ 3343c570f861SOleksij Rempel if (p->bands != dev->info->num_tx_queues) { 3344c570f861SOleksij Rempel dev_err(dev->dev, "Not supported amount of bands. It should be %d\n", 3345c570f861SOleksij Rempel dev->info->num_tx_queues); 3346c570f861SOleksij Rempel return -EOPNOTSUPP; 3347c570f861SOleksij Rempel } 3348c570f861SOleksij Rempel 3349c570f861SOleksij Rempel for (band = 0; band < p->bands; ++band) { 3350c570f861SOleksij Rempel /* The KSZ switches utilize a weighted round robin configuration 3351c570f861SOleksij Rempel * where a certain number of packets can be transmitted from a 3352c570f861SOleksij Rempel * queue before the next queue is serviced. For more information 3353c570f861SOleksij Rempel * on this, refer to section 5.2.8.4 of the KSZ8565R 3354c570f861SOleksij Rempel * documentation on the Port Transmit Queue Control 1 Register. 3355c570f861SOleksij Rempel * However, the current ETS Qdisc implementation (as of February 3356c570f861SOleksij Rempel * 2023) assigns a weight to each queue based on the number of 3357c570f861SOleksij Rempel * bytes or extrapolated bandwidth in percentages. Since this 3358c570f861SOleksij Rempel * differs from the KSZ switches' method and we don't want to 3359c570f861SOleksij Rempel * fake support by converting bytes to packets, it is better to 3360c570f861SOleksij Rempel * return an error instead. 3361c570f861SOleksij Rempel */ 3362c570f861SOleksij Rempel if (p->quanta[band]) { 3363c570f861SOleksij Rempel dev_err(dev->dev, "Quanta/weights configuration is not supported.\n"); 3364c570f861SOleksij Rempel return -EOPNOTSUPP; 3365c570f861SOleksij Rempel } 3366c570f861SOleksij Rempel } 3367c570f861SOleksij Rempel 3368c570f861SOleksij Rempel return 0; 3369c570f861SOleksij Rempel } 3370c570f861SOleksij Rempel 3371c570f861SOleksij Rempel static int ksz_tc_setup_qdisc_ets(struct dsa_switch *ds, int port, 3372c570f861SOleksij Rempel struct tc_ets_qopt_offload *qopt) 3373c570f861SOleksij Rempel { 3374c570f861SOleksij Rempel struct ksz_device *dev = ds->priv; 3375c570f861SOleksij Rempel int ret; 3376c570f861SOleksij Rempel 3377c570f861SOleksij Rempel if (!dev->info->tc_ets_supported) 3378c570f861SOleksij Rempel return -EOPNOTSUPP; 3379c570f861SOleksij Rempel 3380c570f861SOleksij Rempel if (qopt->parent != TC_H_ROOT) { 3381c570f861SOleksij Rempel dev_err(dev->dev, "Parent should be \"root\"\n"); 3382c570f861SOleksij Rempel return -EOPNOTSUPP; 3383c570f861SOleksij Rempel } 3384c570f861SOleksij Rempel 3385c570f861SOleksij Rempel switch (qopt->command) { 3386c570f861SOleksij Rempel case TC_ETS_REPLACE: 3387c570f861SOleksij Rempel ret = ksz_tc_ets_validate(dev, port, &qopt->replace_params); 3388c570f861SOleksij Rempel if (ret) 3389c570f861SOleksij Rempel return ret; 3390c570f861SOleksij Rempel 3391c570f861SOleksij Rempel return ksz_tc_ets_add(dev, port, &qopt->replace_params); 3392c570f861SOleksij Rempel case TC_ETS_DESTROY: 3393c570f861SOleksij Rempel return ksz_tc_ets_del(dev, port); 3394c570f861SOleksij Rempel case TC_ETS_STATS: 3395c570f861SOleksij Rempel case TC_ETS_GRAFT: 3396c570f861SOleksij Rempel return -EOPNOTSUPP; 3397c570f861SOleksij Rempel } 3398c570f861SOleksij Rempel 3399c570f861SOleksij Rempel return -EOPNOTSUPP; 3400c570f861SOleksij Rempel } 3401c570f861SOleksij Rempel 340271d7920fSArun Ramadoss static int ksz_setup_tc(struct dsa_switch *ds, int port, 340371d7920fSArun Ramadoss enum tc_setup_type type, void *type_data) 340471d7920fSArun Ramadoss { 340571d7920fSArun Ramadoss switch (type) { 340671d7920fSArun Ramadoss case TC_SETUP_QDISC_CBS: 340771d7920fSArun Ramadoss return ksz_setup_tc_cbs(ds, port, type_data); 3408c570f861SOleksij Rempel case TC_SETUP_QDISC_ETS: 3409c570f861SOleksij Rempel return ksz_tc_setup_qdisc_ets(ds, port, type_data); 341071d7920fSArun Ramadoss default: 341171d7920fSArun Ramadoss return -EOPNOTSUPP; 341271d7920fSArun Ramadoss } 341371d7920fSArun Ramadoss } 341471d7920fSArun Ramadoss 34151958eee8SArun Ramadoss static const struct dsa_switch_ops ksz_switch_ops = { 34161958eee8SArun Ramadoss .get_tag_protocol = ksz_get_tag_protocol, 3417ab32f56aSChristian Eggers .connect_tag_protocol = ksz_connect_tag_protocol, 34181958eee8SArun Ramadoss .get_phy_flags = ksz_get_phy_flags, 34191958eee8SArun Ramadoss .setup = ksz_setup, 3420c9cd961cSArun Ramadoss .teardown = ksz_teardown, 34211958eee8SArun Ramadoss .phy_read = ksz_phy_read16, 34221958eee8SArun Ramadoss .phy_write = ksz_phy_write16, 34231958eee8SArun Ramadoss .phylink_get_caps = ksz_phylink_get_caps, 3424a0cb1aa4SArun Ramadoss .phylink_mac_config = ksz_phylink_mac_config, 3425f597d3adSArun Ramadoss .phylink_mac_link_up = ksz_phylink_mac_link_up, 34261958eee8SArun Ramadoss .phylink_mac_link_down = ksz_mac_link_down, 34271958eee8SArun Ramadoss .port_enable = ksz_enable_port, 34282c119d99SArun Ramadoss .set_ageing_time = ksz_set_ageing_time, 34291958eee8SArun Ramadoss .get_strings = ksz_get_strings, 34301958eee8SArun Ramadoss .get_ethtool_stats = ksz_get_ethtool_stats, 34311958eee8SArun Ramadoss .get_sset_count = ksz_sset_count, 34321958eee8SArun Ramadoss .port_bridge_join = ksz_port_bridge_join, 34331958eee8SArun Ramadoss .port_bridge_leave = ksz_port_bridge_leave, 34341958eee8SArun Ramadoss .port_stp_state_set = ksz_port_stp_state_set, 343515f7cfaeSVladimir Oltean .port_pre_bridge_flags = ksz_port_pre_bridge_flags, 343615f7cfaeSVladimir Oltean .port_bridge_flags = ksz_port_bridge_flags, 34371958eee8SArun Ramadoss .port_fast_age = ksz_port_fast_age, 34381958eee8SArun Ramadoss .port_vlan_filtering = ksz_port_vlan_filtering, 34391958eee8SArun Ramadoss .port_vlan_add = ksz_port_vlan_add, 34401958eee8SArun Ramadoss .port_vlan_del = ksz_port_vlan_del, 34411958eee8SArun Ramadoss .port_fdb_dump = ksz_port_fdb_dump, 34421958eee8SArun Ramadoss .port_fdb_add = ksz_port_fdb_add, 34431958eee8SArun Ramadoss .port_fdb_del = ksz_port_fdb_del, 34441958eee8SArun Ramadoss .port_mdb_add = ksz_port_mdb_add, 34451958eee8SArun Ramadoss .port_mdb_del = ksz_port_mdb_del, 34461958eee8SArun Ramadoss .port_mirror_add = ksz_port_mirror_add, 34471958eee8SArun Ramadoss .port_mirror_del = ksz_port_mirror_del, 34481958eee8SArun Ramadoss .get_stats64 = ksz_get_stats64, 3449c4748ff6SOleksij Rempel .get_pause_stats = ksz_get_pause_stats, 34501958eee8SArun Ramadoss .port_change_mtu = ksz_change_mtu, 34511958eee8SArun Ramadoss .port_max_mtu = ksz_max_mtu, 3452c59e12a1SChristian Eggers .get_ts_info = ksz_get_ts_info, 3453c59e12a1SChristian Eggers .port_hwtstamp_get = ksz_hwtstamp_get, 3454c59e12a1SChristian Eggers .port_hwtstamp_set = ksz_hwtstamp_set, 3455ab32f56aSChristian Eggers .port_txtstamp = ksz_port_txtstamp, 345690188fffSChristian Eggers .port_rxtstamp = ksz_port_rxtstamp, 345771d7920fSArun Ramadoss .port_setup_tc = ksz_setup_tc, 345869d3b36cSOleksij Rempel .get_mac_eee = ksz_get_mac_eee, 345969d3b36cSOleksij Rempel .set_mac_eee = ksz_set_mac_eee, 34601958eee8SArun Ramadoss }; 34611958eee8SArun Ramadoss 3462ee394feaSMarek Vasut struct ksz_device *ksz_switch_alloc(struct device *base, void *priv) 3463b987e98eSWoojung Huh { 3464b987e98eSWoojung Huh struct dsa_switch *ds; 3465b987e98eSWoojung Huh struct ksz_device *swdev; 3466b987e98eSWoojung Huh 34677e99e347SVivien Didelot ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL); 3468b987e98eSWoojung Huh if (!ds) 3469b987e98eSWoojung Huh return NULL; 3470b987e98eSWoojung Huh 34717e99e347SVivien Didelot ds->dev = base; 34727e99e347SVivien Didelot ds->num_ports = DSA_MAX_PORTS; 34731958eee8SArun Ramadoss ds->ops = &ksz_switch_ops; 34747e99e347SVivien Didelot 3475b987e98eSWoojung Huh swdev = devm_kzalloc(base, sizeof(*swdev), GFP_KERNEL); 3476b987e98eSWoojung Huh if (!swdev) 3477b987e98eSWoojung Huh return NULL; 3478b987e98eSWoojung Huh 3479b987e98eSWoojung Huh ds->priv = swdev; 3480b987e98eSWoojung Huh swdev->dev = base; 3481b987e98eSWoojung Huh 3482b987e98eSWoojung Huh swdev->ds = ds; 3483b987e98eSWoojung Huh swdev->priv = priv; 3484b987e98eSWoojung Huh 3485b987e98eSWoojung Huh return swdev; 3486b987e98eSWoojung Huh } 3487b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_alloc); 3488b987e98eSWoojung Huh 3489b19ac41fSArun Ramadoss static void ksz_parse_rgmii_delay(struct ksz_device *dev, int port_num, 3490b19ac41fSArun Ramadoss struct device_node *port_dn) 3491b19ac41fSArun Ramadoss { 3492b19ac41fSArun Ramadoss phy_interface_t phy_mode = dev->ports[port_num].interface; 3493b19ac41fSArun Ramadoss int rx_delay = -1, tx_delay = -1; 3494b19ac41fSArun Ramadoss 3495b19ac41fSArun Ramadoss if (!phy_interface_mode_is_rgmii(phy_mode)) 3496b19ac41fSArun Ramadoss return; 3497b19ac41fSArun Ramadoss 3498b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay); 3499b19ac41fSArun Ramadoss of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay); 3500b19ac41fSArun Ramadoss 3501b19ac41fSArun Ramadoss if (rx_delay == -1 && tx_delay == -1) { 3502b19ac41fSArun Ramadoss dev_warn(dev->dev, 3503b19ac41fSArun Ramadoss "Port %d interpreting RGMII delay settings based on \"phy-mode\" property, " 3504b19ac41fSArun Ramadoss "please update device tree to specify \"rx-internal-delay-ps\" and " 3505b19ac41fSArun Ramadoss "\"tx-internal-delay-ps\"", 3506b19ac41fSArun Ramadoss port_num); 3507b19ac41fSArun Ramadoss 3508b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID || 3509b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 3510b19ac41fSArun Ramadoss rx_delay = 2000; 3511b19ac41fSArun Ramadoss 3512b19ac41fSArun Ramadoss if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID || 3513b19ac41fSArun Ramadoss phy_mode == PHY_INTERFACE_MODE_RGMII_ID) 3514b19ac41fSArun Ramadoss tx_delay = 2000; 3515b19ac41fSArun Ramadoss } 3516b19ac41fSArun Ramadoss 3517b19ac41fSArun Ramadoss if (rx_delay < 0) 3518b19ac41fSArun Ramadoss rx_delay = 0; 3519b19ac41fSArun Ramadoss if (tx_delay < 0) 3520b19ac41fSArun Ramadoss tx_delay = 0; 3521b19ac41fSArun Ramadoss 3522b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_rx_val = rx_delay; 3523b19ac41fSArun Ramadoss dev->ports[port_num].rgmii_tx_val = tx_delay; 3524b19ac41fSArun Ramadoss } 3525b19ac41fSArun Ramadoss 35266ec23aaaSArun Ramadoss int ksz_switch_register(struct ksz_device *dev) 3527b987e98eSWoojung Huh { 3528462d5250SArun Ramadoss const struct ksz_chip_data *info; 3529912aae27SHelmut Grohne struct device_node *port, *ports; 35300c65b2b9SAndrew Lunn phy_interface_t interface; 3531edecfa98SHelmut Grohne unsigned int port_num; 3532b987e98eSWoojung Huh int ret; 3533198b3478SArun Ramadoss int i; 3534b987e98eSWoojung Huh 3535b987e98eSWoojung Huh if (dev->pdata) 3536b987e98eSWoojung Huh dev->chip_id = dev->pdata->chip_id; 3537b987e98eSWoojung Huh 3538924352c3SMarek Vasut dev->reset_gpio = devm_gpiod_get_optional(dev->dev, "reset", 3539924352c3SMarek Vasut GPIOD_OUT_LOW); 3540924352c3SMarek Vasut if (IS_ERR(dev->reset_gpio)) 3541924352c3SMarek Vasut return PTR_ERR(dev->reset_gpio); 3542924352c3SMarek Vasut 3543924352c3SMarek Vasut if (dev->reset_gpio) { 354422e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 35455b797980SPaul Barker usleep_range(10000, 12000); 354622e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 0); 35471c45ba93SMarek Vasut msleep(100); 3548924352c3SMarek Vasut } 3549924352c3SMarek Vasut 35507049f9b5STristram Ha mutex_init(&dev->dev_mutex); 3551013572a2SMarek Vasut mutex_init(&dev->regmap_mutex); 3552284fb78eSTristram Ha mutex_init(&dev->alu_mutex); 3553284fb78eSTristram Ha mutex_init(&dev->vlan_mutex); 3554284fb78eSTristram Ha 355591a98917SArun Ramadoss ret = ksz_switch_detect(dev); 355691a98917SArun Ramadoss if (ret) 355791a98917SArun Ramadoss return ret; 3558b987e98eSWoojung Huh 3559462d5250SArun Ramadoss info = ksz_lookup_info(dev->chip_id); 3560462d5250SArun Ramadoss if (!info) 3561462d5250SArun Ramadoss return -ENODEV; 3562462d5250SArun Ramadoss 3563462d5250SArun Ramadoss /* Update the compatible info with the probed one */ 3564462d5250SArun Ramadoss dev->info = info; 3565462d5250SArun Ramadoss 356691a98917SArun Ramadoss dev_info(dev->dev, "found switch: %s, rev %i\n", 356791a98917SArun Ramadoss dev->info->dev_name, dev->chip_rev); 356891a98917SArun Ramadoss 3569eee16b14SArun Ramadoss ret = ksz_check_device_id(dev); 3570eee16b14SArun Ramadoss if (ret) 3571eee16b14SArun Ramadoss return ret; 3572eee16b14SArun Ramadoss 35736ec23aaaSArun Ramadoss dev->dev_ops = dev->info->ops; 357491a98917SArun Ramadoss 3575c2e86691STristram Ha ret = dev->dev_ops->init(dev); 3576b987e98eSWoojung Huh if (ret) 3577b987e98eSWoojung Huh return ret; 3578b987e98eSWoojung Huh 3579198b3478SArun Ramadoss dev->ports = devm_kzalloc(dev->dev, 3580198b3478SArun Ramadoss dev->info->port_cnt * sizeof(struct ksz_port), 3581198b3478SArun Ramadoss GFP_KERNEL); 3582198b3478SArun Ramadoss if (!dev->ports) 3583198b3478SArun Ramadoss return -ENOMEM; 3584198b3478SArun Ramadoss 3585198b3478SArun Ramadoss for (i = 0; i < dev->info->port_cnt; i++) { 3586198b3478SArun Ramadoss spin_lock_init(&dev->ports[i].mib.stats64_lock); 3587198b3478SArun Ramadoss mutex_init(&dev->ports[i].mib.cnt_mutex); 3588198b3478SArun Ramadoss dev->ports[i].mib.counters = 3589198b3478SArun Ramadoss devm_kzalloc(dev->dev, 3590198b3478SArun Ramadoss sizeof(u64) * (dev->info->mib_cnt + 1), 3591198b3478SArun Ramadoss GFP_KERNEL); 3592198b3478SArun Ramadoss if (!dev->ports[i].mib.counters) 3593198b3478SArun Ramadoss return -ENOMEM; 3594f3c16545SArun Ramadoss 3595f3c16545SArun Ramadoss dev->ports[i].ksz_dev = dev; 3596f3c16545SArun Ramadoss dev->ports[i].num = i; 3597198b3478SArun Ramadoss } 3598198b3478SArun Ramadoss 3599198b3478SArun Ramadoss /* set the real number of ports */ 3600198b3478SArun Ramadoss dev->ds->num_ports = dev->info->port_cnt; 3601198b3478SArun Ramadoss 36028c29bebbSTristram Ha /* Host port interface will be self detected, or specifically set in 36038c29bebbSTristram Ha * device tree. 36048c29bebbSTristram Ha */ 3605462d5250SArun Ramadoss for (port_num = 0; port_num < dev->info->port_cnt; ++port_num) 3606edecfa98SHelmut Grohne dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA; 3607c2e86691STristram Ha if (dev->dev->of_node) { 36080c65b2b9SAndrew Lunn ret = of_get_phy_mode(dev->dev->of_node, &interface); 36090c65b2b9SAndrew Lunn if (ret == 0) 3610edecfa98SHelmut Grohne dev->compat_interface = interface; 361144e53c88SChristian Eggers ports = of_get_child_by_name(dev->dev->of_node, "ethernet-ports"); 361244e53c88SChristian Eggers if (!ports) 3613912aae27SHelmut Grohne ports = of_get_child_by_name(dev->dev->of_node, "ports"); 3614a14bd747SLiang He if (ports) { 3615912aae27SHelmut Grohne for_each_available_child_of_node(ports, port) { 3616912aae27SHelmut Grohne if (of_property_read_u32(port, "reg", 3617912aae27SHelmut Grohne &port_num)) 3618edecfa98SHelmut Grohne continue; 361984f7e0bbSkernel test robot if (!(dev->port_mask & BIT(port_num))) { 362084f7e0bbSkernel test robot of_node_put(port); 3621a14bd747SLiang He of_node_put(ports); 3622edecfa98SHelmut Grohne return -EINVAL; 362384f7e0bbSkernel test robot } 3624912aae27SHelmut Grohne of_get_phy_mode(port, 3625912aae27SHelmut Grohne &dev->ports[port_num].interface); 3626b19ac41fSArun Ramadoss 3627b19ac41fSArun Ramadoss ksz_parse_rgmii_delay(dev, port_num, port); 3628edecfa98SHelmut Grohne } 3629a14bd747SLiang He of_node_put(ports); 3630a14bd747SLiang He } 363179c8bd15SRobert Hancock dev->synclko_125 = of_property_read_bool(dev->dev->of_node, 363279c8bd15SRobert Hancock "microchip,synclko-125"); 363348bf8b8aSRobert Hancock dev->synclko_disable = of_property_read_bool(dev->dev->of_node, 363448bf8b8aSRobert Hancock "microchip,synclko-disable"); 363548bf8b8aSRobert Hancock if (dev->synclko_125 && dev->synclko_disable) { 363648bf8b8aSRobert Hancock dev_err(dev->dev, "inconsistent synclko settings\n"); 363748bf8b8aSRobert Hancock return -EINVAL; 363848bf8b8aSRobert Hancock } 3639c2e86691STristram Ha } 3640c2e86691STristram Ha 3641c2e86691STristram Ha ret = dsa_register_switch(dev->ds); 3642c2e86691STristram Ha if (ret) { 3643c2e86691STristram Ha dev->dev_ops->exit(dev); 3644c2e86691STristram Ha return ret; 3645c2e86691STristram Ha } 3646c2e86691STristram Ha 36478098bd69SChristian Eggers /* Read MIB counters every 30 seconds to avoid overflow. */ 364812c740c8SOleksij Rempel dev->mib_read_interval = msecs_to_jiffies(5000); 36498098bd69SChristian Eggers 36508098bd69SChristian Eggers /* Start the MIB timer. */ 36518098bd69SChristian Eggers schedule_delayed_work(&dev->mib_read, 0); 36528098bd69SChristian Eggers 36537a8988a1SArun Ramadoss return ret; 3654b987e98eSWoojung Huh } 3655b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_register); 3656b987e98eSWoojung Huh 3657b987e98eSWoojung Huh void ksz_switch_remove(struct ksz_device *dev) 3658b987e98eSWoojung Huh { 36597c6ff470STristram Ha /* timer started */ 3660ef1100efSArun Ramadoss if (dev->mib_read_interval) { 3661ef1100efSArun Ramadoss dev->mib_read_interval = 0; 3662469b390eSGeorge McCollister cancel_delayed_work_sync(&dev->mib_read); 3663ef1100efSArun Ramadoss } 36647c6ff470STristram Ha 3665c2e86691STristram Ha dev->dev_ops->exit(dev); 3666b987e98eSWoojung Huh dsa_unregister_switch(dev->ds); 3667924352c3SMarek Vasut 3668924352c3SMarek Vasut if (dev->reset_gpio) 366922e72b5eSMarek Vasut gpiod_set_value_cansleep(dev->reset_gpio, 1); 3670924352c3SMarek Vasut 3671b987e98eSWoojung Huh } 3672b987e98eSWoojung Huh EXPORT_SYMBOL(ksz_switch_remove); 3673b987e98eSWoojung Huh 3674b987e98eSWoojung Huh MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>"); 3675b987e98eSWoojung Huh MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver"); 3676b987e98eSWoojung Huh MODULE_LICENSE("GPL"); 3677