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