xref: /openbmc/linux/drivers/net/dsa/microchip/ksz_common.h (revision ef912fe443adfa15b88645b3bf58c92e5a364167)
1b31141d3SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */
2b31141d3SNishad Kamdar /* Microchip switch driver common header
3c2e86691STristram Ha  *
47c6ff470STristram Ha  * Copyright (C) 2017-2019 Microchip Technology Inc.
5c2e86691STristram Ha  */
6c2e86691STristram Ha 
7c2e86691STristram Ha #ifndef __KSZ_COMMON_H
8c2e86691STristram Ha #define __KSZ_COMMON_H
9c2e86691STristram Ha 
106a7abc61SMarek Vasut #include <linux/etherdevice.h>
116a7abc61SMarek Vasut #include <linux/kernel.h>
126a7abc61SMarek Vasut #include <linux/mutex.h>
136a7abc61SMarek Vasut #include <linux/phy.h>
14ee394feaSMarek Vasut #include <linux/regmap.h>
156a7abc61SMarek Vasut #include <net/dsa.h>
16c9cd961cSArun Ramadoss #include <linux/irq.h>
176a7abc61SMarek Vasut 
1865ac79e1SArun Ramadoss #define KSZ_MAX_NUM_PORTS 8
1965ac79e1SArun Ramadoss 
20f3c16545SArun Ramadoss struct ksz_device;
21f3c16545SArun Ramadoss 
226a7abc61SMarek Vasut struct vlan_table {
236a7abc61SMarek Vasut 	u32 table[3];
246a7abc61SMarek Vasut };
256a7abc61SMarek Vasut 
266a7abc61SMarek Vasut struct ksz_port_mib {
276a7abc61SMarek Vasut 	struct mutex cnt_mutex;		/* structure access */
286a7abc61SMarek Vasut 	u8 cnt_ptr;
296a7abc61SMarek Vasut 	u64 *counters;
30a7f4f13aSOleksij Rempel 	struct rtnl_link_stats64 stats64;
31c4748ff6SOleksij Rempel 	struct ethtool_pause_stats pause_stats;
32a7f4f13aSOleksij Rempel 	struct spinlock stats64_lock;
336a7abc61SMarek Vasut };
346a7abc61SMarek Vasut 
35a530e6f2SArun Ramadoss struct ksz_mib_names {
36a530e6f2SArun Ramadoss 	int index;
37a530e6f2SArun Ramadoss 	char string[ETH_GSTRING_LEN];
38a530e6f2SArun Ramadoss };
39a530e6f2SArun Ramadoss 
40462d5250SArun Ramadoss struct ksz_chip_data {
41462d5250SArun Ramadoss 	u32 chip_id;
42462d5250SArun Ramadoss 	const char *dev_name;
43462d5250SArun Ramadoss 	int num_vlans;
44462d5250SArun Ramadoss 	int num_alus;
45462d5250SArun Ramadoss 	int num_statics;
46462d5250SArun Ramadoss 	int cpu_ports;
47462d5250SArun Ramadoss 	int port_cnt;
48978f1f72SArun Ramadoss 	u8 port_nirqs;
496ec23aaaSArun Ramadoss 	const struct ksz_dev_ops *ops;
50462d5250SArun Ramadoss 	bool phy_errata_9477;
51462d5250SArun Ramadoss 	bool ksz87xx_eee_link_erratum;
52a530e6f2SArun Ramadoss 	const struct ksz_mib_names *mib_names;
53a530e6f2SArun Ramadoss 	int mib_cnt;
54a530e6f2SArun Ramadoss 	u8 reg_mib_cnt;
55a02579dfSArun Ramadoss 	const u16 *regs;
56d23a5e18SArun Ramadoss 	const u32 *masks;
5734e48383SArun Ramadoss 	const u8 *shifts;
58aa5b8b73SArun Ramadoss 	const u8 *xmii_ctrl0;
5946f80fa8SArun Ramadoss 	const u8 *xmii_ctrl1;
60e593df51SArun Ramadoss 	int stp_ctrl_reg;
611ca6437fSArun Ramadoss 	int broadcast_ctrl_reg;
620abab9f3SArun Ramadoss 	int multicast_ctrl_reg;
63ad08ac18SArun Ramadoss 	int start_ctrl_reg;
6465ac79e1SArun Ramadoss 	bool supports_mii[KSZ_MAX_NUM_PORTS];
6565ac79e1SArun Ramadoss 	bool supports_rmii[KSZ_MAX_NUM_PORTS];
6665ac79e1SArun Ramadoss 	bool supports_rgmii[KSZ_MAX_NUM_PORTS];
6765ac79e1SArun Ramadoss 	bool internal_phy[KSZ_MAX_NUM_PORTS];
68505bf320SOleksij Rempel 	bool gbit_capable[KSZ_MAX_NUM_PORTS];
69ec6ba50cSOleksij Rempel 	const struct regmap_access_table *wr_table;
70ec6ba50cSOleksij Rempel 	const struct regmap_access_table *rd_table;
71462d5250SArun Ramadoss };
72462d5250SArun Ramadoss 
73c9cd961cSArun Ramadoss struct ksz_irq {
74c9cd961cSArun Ramadoss 	u16 masked;
75e1add7ddSArun Ramadoss 	u16 reg_mask;
76e1add7ddSArun Ramadoss 	u16 reg_status;
77c9cd961cSArun Ramadoss 	struct irq_domain *domain;
78c9cd961cSArun Ramadoss 	int nirqs;
79e1add7ddSArun Ramadoss 	int irq_num;
80c9cd961cSArun Ramadoss 	char name[16];
81e1add7ddSArun Ramadoss 	struct ksz_device *dev;
82c9cd961cSArun Ramadoss };
83c9cd961cSArun Ramadoss 
846a7abc61SMarek Vasut struct ksz_port {
858f4f58f8SBen Hutchings 	bool remove_tag;		/* Remove Tag flag set, for ksz8795 only */
8615f7cfaeSVladimir Oltean 	bool learning;
876a7abc61SMarek Vasut 	int stp_state;
886a7abc61SMarek Vasut 	struct phy_device phydev;
896a7abc61SMarek Vasut 
906a7abc61SMarek Vasut 	u32 on:1;			/* port is not disabled by hardware */
916a7abc61SMarek Vasut 	u32 fiber:1;			/* port is fiber */
926a7abc61SMarek Vasut 	u32 force:1;
936a7abc61SMarek Vasut 	u32 read:1;			/* read MIB counters in background */
946a7abc61SMarek Vasut 	u32 freeze:1;			/* MIB counter freeze is enabled */
956a7abc61SMarek Vasut 
966a7abc61SMarek Vasut 	struct ksz_port_mib mib;
97edecfa98SHelmut Grohne 	phy_interface_t interface;
98e18058eaSOleksij Rempel 	u16 max_frame;
99b19ac41fSArun Ramadoss 	u32 rgmii_tx_val;
100b19ac41fSArun Ramadoss 	u32 rgmii_rx_val;
101f3c16545SArun Ramadoss 	struct ksz_device *ksz_dev;
102c9cd961cSArun Ramadoss 	struct ksz_irq pirq;
103f3c16545SArun Ramadoss 	u8 num;
1046a7abc61SMarek Vasut };
1056a7abc61SMarek Vasut 
1066a7abc61SMarek Vasut struct ksz_device {
1076a7abc61SMarek Vasut 	struct dsa_switch *ds;
1086a7abc61SMarek Vasut 	struct ksz_platform_data *pdata;
109462d5250SArun Ramadoss 	const struct ksz_chip_data *info;
1106a7abc61SMarek Vasut 
1116a7abc61SMarek Vasut 	struct mutex dev_mutex;		/* device access */
112013572a2SMarek Vasut 	struct mutex regmap_mutex;	/* regmap access */
1136a7abc61SMarek Vasut 	struct mutex alu_mutex;		/* ALU access */
1146a7abc61SMarek Vasut 	struct mutex vlan_mutex;	/* vlan access */
1156a7abc61SMarek Vasut 	const struct ksz_dev_ops *dev_ops;
1166a7abc61SMarek Vasut 
1176a7abc61SMarek Vasut 	struct device *dev;
1186a7abc61SMarek Vasut 	struct regmap *regmap[3];
1196a7abc61SMarek Vasut 
1206a7abc61SMarek Vasut 	void *priv;
121c9cd961cSArun Ramadoss 	int irq;
1226a7abc61SMarek Vasut 
1236a7abc61SMarek Vasut 	struct gpio_desc *reset_gpio;	/* Optional reset GPIO */
1246a7abc61SMarek Vasut 
1256a7abc61SMarek Vasut 	/* chip specific data */
1266a7abc61SMarek Vasut 	u32 chip_id;
12791a98917SArun Ramadoss 	u8 chip_rev;
1286a7abc61SMarek Vasut 	int cpu_port;			/* port connected to CPU */
1296a7abc61SMarek Vasut 	int phy_port_cnt;
130edecfa98SHelmut Grohne 	phy_interface_t compat_interface;
1316a7abc61SMarek Vasut 	bool synclko_125;
13248bf8b8aSRobert Hancock 	bool synclko_disable;
1336a7abc61SMarek Vasut 
1346a7abc61SMarek Vasut 	struct vlan_table *vlan_cache;
1356a7abc61SMarek Vasut 
1366a7abc61SMarek Vasut 	struct ksz_port *ports;
137469b390eSGeorge McCollister 	struct delayed_work mib_read;
1386a7abc61SMarek Vasut 	unsigned long mib_read_interval;
1396a7abc61SMarek Vasut 	u16 mirror_rx;
1406a7abc61SMarek Vasut 	u16 mirror_tx;
1416a7abc61SMarek Vasut 	u16 port_mask;
142c9cd961cSArun Ramadoss 	struct mutex lock_irq;		/* IRQ Access */
143c9cd961cSArun Ramadoss 	struct ksz_irq girq;
1446a7abc61SMarek Vasut };
1456a7abc61SMarek Vasut 
146462d5250SArun Ramadoss /* List of supported models */
147462d5250SArun Ramadoss enum ksz_model {
148b4490809SOleksij Rempel 	KSZ8563,
149462d5250SArun Ramadoss 	KSZ8795,
150462d5250SArun Ramadoss 	KSZ8794,
151462d5250SArun Ramadoss 	KSZ8765,
152462d5250SArun Ramadoss 	KSZ8830,
153462d5250SArun Ramadoss 	KSZ9477,
1542eb3ff3cSRomain Naour 	KSZ9896,
155462d5250SArun Ramadoss 	KSZ9897,
156462d5250SArun Ramadoss 	KSZ9893,
157*ef912fe4SRakesh Sankaranarayanan 	KSZ9563,
158462d5250SArun Ramadoss 	KSZ9567,
159462d5250SArun Ramadoss 	LAN9370,
160462d5250SArun Ramadoss 	LAN9371,
161462d5250SArun Ramadoss 	LAN9372,
162462d5250SArun Ramadoss 	LAN9373,
163462d5250SArun Ramadoss 	LAN9374,
164462d5250SArun Ramadoss };
165462d5250SArun Ramadoss 
166462d5250SArun Ramadoss enum ksz_chip_id {
167b4490809SOleksij Rempel 	KSZ8563_CHIP_ID = 0x8563,
168462d5250SArun Ramadoss 	KSZ8795_CHIP_ID = 0x8795,
169462d5250SArun Ramadoss 	KSZ8794_CHIP_ID = 0x8794,
170462d5250SArun Ramadoss 	KSZ8765_CHIP_ID = 0x8765,
171462d5250SArun Ramadoss 	KSZ8830_CHIP_ID = 0x8830,
172462d5250SArun Ramadoss 	KSZ9477_CHIP_ID = 0x00947700,
1732eb3ff3cSRomain Naour 	KSZ9896_CHIP_ID = 0x00989600,
174462d5250SArun Ramadoss 	KSZ9897_CHIP_ID = 0x00989700,
175462d5250SArun Ramadoss 	KSZ9893_CHIP_ID = 0x00989300,
176*ef912fe4SRakesh Sankaranarayanan 	KSZ9563_CHIP_ID = 0x00956300,
177462d5250SArun Ramadoss 	KSZ9567_CHIP_ID = 0x00956700,
178462d5250SArun Ramadoss 	LAN9370_CHIP_ID = 0x00937000,
179462d5250SArun Ramadoss 	LAN9371_CHIP_ID = 0x00937100,
180462d5250SArun Ramadoss 	LAN9372_CHIP_ID = 0x00937200,
181462d5250SArun Ramadoss 	LAN9373_CHIP_ID = 0x00937300,
182462d5250SArun Ramadoss 	LAN9374_CHIP_ID = 0x00937400,
183462d5250SArun Ramadoss };
184462d5250SArun Ramadoss 
185486f9ca7SArun Ramadoss enum ksz_regs {
186486f9ca7SArun Ramadoss 	REG_IND_CTRL_0,
187486f9ca7SArun Ramadoss 	REG_IND_DATA_8,
188486f9ca7SArun Ramadoss 	REG_IND_DATA_CHECK,
189486f9ca7SArun Ramadoss 	REG_IND_DATA_HI,
190486f9ca7SArun Ramadoss 	REG_IND_DATA_LO,
191486f9ca7SArun Ramadoss 	REG_IND_MIB_CHECK,
192486f9ca7SArun Ramadoss 	REG_IND_BYTE,
193486f9ca7SArun Ramadoss 	P_FORCE_CTRL,
194486f9ca7SArun Ramadoss 	P_LINK_STATUS,
195486f9ca7SArun Ramadoss 	P_LOCAL_CTRL,
196486f9ca7SArun Ramadoss 	P_NEG_RESTART_CTRL,
197486f9ca7SArun Ramadoss 	P_REMOTE_STATUS,
198486f9ca7SArun Ramadoss 	P_SPEED_STATUS,
199486f9ca7SArun Ramadoss 	S_TAIL_TAG_CTRL,
2006877102fSArun Ramadoss 	P_STP_CTRL,
2019d95329cSArun Ramadoss 	S_START_CTRL,
2029d95329cSArun Ramadoss 	S_BROADCAST_CTRL,
2039d95329cSArun Ramadoss 	S_MULTICAST_CTRL,
204aa5b8b73SArun Ramadoss 	P_XMII_CTRL_0,
20546f80fa8SArun Ramadoss 	P_XMII_CTRL_1,
206486f9ca7SArun Ramadoss };
207486f9ca7SArun Ramadoss 
208d23a5e18SArun Ramadoss enum ksz_masks {
209d23a5e18SArun Ramadoss 	PORT_802_1P_REMAPPING,
210d23a5e18SArun Ramadoss 	SW_TAIL_TAG_ENABLE,
211d23a5e18SArun Ramadoss 	MIB_COUNTER_OVERFLOW,
212d23a5e18SArun Ramadoss 	MIB_COUNTER_VALID,
213d23a5e18SArun Ramadoss 	VLAN_TABLE_FID,
214d23a5e18SArun Ramadoss 	VLAN_TABLE_MEMBERSHIP,
215d23a5e18SArun Ramadoss 	VLAN_TABLE_VALID,
216d23a5e18SArun Ramadoss 	STATIC_MAC_TABLE_VALID,
217d23a5e18SArun Ramadoss 	STATIC_MAC_TABLE_USE_FID,
218d23a5e18SArun Ramadoss 	STATIC_MAC_TABLE_FID,
219d23a5e18SArun Ramadoss 	STATIC_MAC_TABLE_OVERRIDE,
220d23a5e18SArun Ramadoss 	STATIC_MAC_TABLE_FWD_PORTS,
221d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_ENTRIES_H,
222d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_MAC_EMPTY,
223d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_NOT_READY,
224d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_ENTRIES,
225d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_FID,
226d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_SRC_PORT,
227d23a5e18SArun Ramadoss 	DYNAMIC_MAC_TABLE_TIMESTAMP,
228457c182aSArun Ramadoss 	ALU_STAT_WRITE,
229457c182aSArun Ramadoss 	ALU_STAT_READ,
2308560664fSArun Ramadoss 	P_MII_TX_FLOW_CTRL,
2318560664fSArun Ramadoss 	P_MII_RX_FLOW_CTRL,
232d23a5e18SArun Ramadoss };
233d23a5e18SArun Ramadoss 
23434e48383SArun Ramadoss enum ksz_shifts {
23534e48383SArun Ramadoss 	VLAN_TABLE_MEMBERSHIP_S,
23634e48383SArun Ramadoss 	VLAN_TABLE,
23734e48383SArun Ramadoss 	STATIC_MAC_FWD_PORTS,
23834e48383SArun Ramadoss 	STATIC_MAC_FID,
23934e48383SArun Ramadoss 	DYNAMIC_MAC_ENTRIES_H,
24034e48383SArun Ramadoss 	DYNAMIC_MAC_ENTRIES,
24134e48383SArun Ramadoss 	DYNAMIC_MAC_FID,
24234e48383SArun Ramadoss 	DYNAMIC_MAC_TIMESTAMP,
24334e48383SArun Ramadoss 	DYNAMIC_MAC_SRC_PORT,
244457c182aSArun Ramadoss 	ALU_STAT_INDEX,
24534e48383SArun Ramadoss };
24634e48383SArun Ramadoss 
247aa5b8b73SArun Ramadoss enum ksz_xmii_ctrl0 {
248aa5b8b73SArun Ramadoss 	P_MII_100MBIT,
249aa5b8b73SArun Ramadoss 	P_MII_10MBIT,
2508560664fSArun Ramadoss 	P_MII_FULL_DUPLEX,
2518560664fSArun Ramadoss 	P_MII_HALF_DUPLEX,
252aa5b8b73SArun Ramadoss };
253aa5b8b73SArun Ramadoss 
25446f80fa8SArun Ramadoss enum ksz_xmii_ctrl1 {
255dc1c596eSArun Ramadoss 	P_RGMII_SEL,
256dc1c596eSArun Ramadoss 	P_RMII_SEL,
257dc1c596eSArun Ramadoss 	P_GMII_SEL,
258dc1c596eSArun Ramadoss 	P_MII_SEL,
25946f80fa8SArun Ramadoss 	P_GMII_1GBIT,
26046f80fa8SArun Ramadoss 	P_GMII_NOT_1GBIT,
26146f80fa8SArun Ramadoss };
26246f80fa8SArun Ramadoss 
2636a7abc61SMarek Vasut struct alu_struct {
2646a7abc61SMarek Vasut 	/* entry 1 */
2656a7abc61SMarek Vasut 	u8	is_static:1;
2666a7abc61SMarek Vasut 	u8	is_src_filter:1;
2676a7abc61SMarek Vasut 	u8	is_dst_filter:1;
2686a7abc61SMarek Vasut 	u8	prio_age:3;
2696a7abc61SMarek Vasut 	u32	_reserv_0_1:23;
2706a7abc61SMarek Vasut 	u8	mstp:3;
2716a7abc61SMarek Vasut 	/* entry 2 */
2726a7abc61SMarek Vasut 	u8	is_override:1;
2736a7abc61SMarek Vasut 	u8	is_use_fid:1;
2746a7abc61SMarek Vasut 	u32	_reserv_1_1:23;
2756a7abc61SMarek Vasut 	u8	port_forward:7;
2766a7abc61SMarek Vasut 	/* entry 3 & 4*/
2776a7abc61SMarek Vasut 	u32	_reserv_2_1:9;
2786a7abc61SMarek Vasut 	u8	fid:7;
2796a7abc61SMarek Vasut 	u8	mac[ETH_ALEN];
2806a7abc61SMarek Vasut };
2816a7abc61SMarek Vasut 
2826a7abc61SMarek Vasut struct ksz_dev_ops {
283d2822e68SArun Ramadoss 	int (*setup)(struct dsa_switch *ds);
284c9cd961cSArun Ramadoss 	void (*teardown)(struct dsa_switch *ds);
2856a7abc61SMarek Vasut 	u32 (*get_port_addr)(int port, int offset);
2866a7abc61SMarek Vasut 	void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
2876a7abc61SMarek Vasut 	void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
2886a7abc61SMarek Vasut 	void (*port_cleanup)(struct ksz_device *dev, int port);
2896a7abc61SMarek Vasut 	void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
2902c119d99SArun Ramadoss 	int (*set_ageing_time)(struct ksz_device *dev, unsigned int msecs);
2918f420456SOleksij Rempel 	int (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
2928f420456SOleksij Rempel 	int (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
2936a7abc61SMarek Vasut 	void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
2946a7abc61SMarek Vasut 			  u64 *cnt);
2956a7abc61SMarek Vasut 	void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
2966a7abc61SMarek Vasut 			  u64 *dropped, u64 *cnt);
297a7f4f13aSOleksij Rempel 	void (*r_mib_stat64)(struct ksz_device *dev, int port);
298f0d997e3SArun Ramadoss 	int  (*vlan_filtering)(struct ksz_device *dev, int port,
299f0d997e3SArun Ramadoss 			       bool flag, struct netlink_ext_ack *extack);
300f0d997e3SArun Ramadoss 	int  (*vlan_add)(struct ksz_device *dev, int port,
301f0d997e3SArun Ramadoss 			 const struct switchdev_obj_port_vlan *vlan,
302f0d997e3SArun Ramadoss 			 struct netlink_ext_ack *extack);
303f0d997e3SArun Ramadoss 	int  (*vlan_del)(struct ksz_device *dev, int port,
304f0d997e3SArun Ramadoss 			 const struct switchdev_obj_port_vlan *vlan);
30500a298bbSArun Ramadoss 	int (*mirror_add)(struct ksz_device *dev, int port,
30600a298bbSArun Ramadoss 			  struct dsa_mall_mirror_tc_entry *mirror,
30700a298bbSArun Ramadoss 			  bool ingress, struct netlink_ext_ack *extack);
30800a298bbSArun Ramadoss 	void (*mirror_del)(struct ksz_device *dev, int port,
30900a298bbSArun Ramadoss 			   struct dsa_mall_mirror_tc_entry *mirror);
310e587be75SArun Ramadoss 	int (*fdb_add)(struct ksz_device *dev, int port,
311e587be75SArun Ramadoss 		       const unsigned char *addr, u16 vid, struct dsa_db db);
312e587be75SArun Ramadoss 	int (*fdb_del)(struct ksz_device *dev, int port,
313e587be75SArun Ramadoss 		       const unsigned char *addr, u16 vid, struct dsa_db db);
314e587be75SArun Ramadoss 	int (*fdb_dump)(struct ksz_device *dev, int port,
315e587be75SArun Ramadoss 			dsa_fdb_dump_cb_t *cb, void *data);
316980c7d17SArun Ramadoss 	int (*mdb_add)(struct ksz_device *dev, int port,
317980c7d17SArun Ramadoss 		       const struct switchdev_obj_port_mdb *mdb,
318980c7d17SArun Ramadoss 		       struct dsa_db db);
319980c7d17SArun Ramadoss 	int (*mdb_del)(struct ksz_device *dev, int port,
320980c7d17SArun Ramadoss 		       const struct switchdev_obj_port_mdb *mdb,
321980c7d17SArun Ramadoss 		       struct dsa_db db);
3227012033cSArun Ramadoss 	void (*get_caps)(struct ksz_device *dev, int port,
3237012033cSArun Ramadoss 			 struct phylink_config *config);
3241fe94f54SArun Ramadoss 	int (*change_mtu)(struct ksz_device *dev, int port, int mtu);
3251fe94f54SArun Ramadoss 	int (*max_mtu)(struct ksz_device *dev, int port);
3266a7abc61SMarek Vasut 	void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
3276a7abc61SMarek Vasut 	void (*port_init_cnt)(struct ksz_device *dev, int port);
328a0cb1aa4SArun Ramadoss 	void (*phylink_mac_config)(struct ksz_device *dev, int port,
329a0cb1aa4SArun Ramadoss 				   unsigned int mode,
330a0cb1aa4SArun Ramadoss 				   const struct phylink_link_state *state);
331f597d3adSArun Ramadoss 	void (*phylink_mac_link_up)(struct ksz_device *dev, int port,
332f597d3adSArun Ramadoss 				    unsigned int mode,
333f597d3adSArun Ramadoss 				    phy_interface_t interface,
334f597d3adSArun Ramadoss 				    struct phy_device *phydev, int speed,
335f597d3adSArun Ramadoss 				    int duplex, bool tx_pause, bool rx_pause);
336b19ac41fSArun Ramadoss 	void (*setup_rgmii_delay)(struct ksz_device *dev, int port);
337fb9324beSArun Ramadoss 	void (*config_cpu_port)(struct dsa_switch *ds);
338331d64f7SArun Ramadoss 	int (*enable_stp_addr)(struct ksz_device *dev);
339673b196fSArun Ramadoss 	int (*reset)(struct ksz_device *dev);
3406a7abc61SMarek Vasut 	int (*init)(struct ksz_device *dev);
3416a7abc61SMarek Vasut 	void (*exit)(struct ksz_device *dev);
3426a7abc61SMarek Vasut };
3436a7abc61SMarek Vasut 
3446a7abc61SMarek Vasut struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
3456ec23aaaSArun Ramadoss int ksz_switch_register(struct ksz_device *dev);
3466a7abc61SMarek Vasut void ksz_switch_remove(struct ksz_device *dev);
3476a7abc61SMarek Vasut 
3487c6ff470STristram Ha void ksz_init_mib_timer(struct ksz_device *dev);
349c6101dd7SArun Ramadoss void ksz_r_mib_stats64(struct ksz_device *dev, int port);
350e593df51SArun Ramadoss void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
35146f80fa8SArun Ramadoss bool ksz_get_gbit(struct ksz_device *dev, int port);
3520ab7f6bfSArun Ramadoss phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit);
3531958eee8SArun Ramadoss extern const struct ksz_chip_data ksz_switch_chips[];
354c2e86691STristram Ha 
355c2e86691STristram Ha /* Common register access functions */
356c2e86691STristram Ha 
357c2e86691STristram Ha static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
358c2e86691STristram Ha {
359ee394feaSMarek Vasut 	unsigned int value;
360ee394feaSMarek Vasut 	int ret = regmap_read(dev->regmap[0], reg, &value);
361c2e86691STristram Ha 
362ec6ba50cSOleksij Rempel 	if (ret)
363ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg,
364ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
365ec6ba50cSOleksij Rempel 
366ee394feaSMarek Vasut 	*val = value;
367c2e86691STristram Ha 	return ret;
368c2e86691STristram Ha }
369c2e86691STristram Ha 
370c2e86691STristram Ha static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
371c2e86691STristram Ha {
372ee394feaSMarek Vasut 	unsigned int value;
373ee394feaSMarek Vasut 	int ret = regmap_read(dev->regmap[1], reg, &value);
374c2e86691STristram Ha 
375ec6ba50cSOleksij Rempel 	if (ret)
376ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg,
377ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
378ec6ba50cSOleksij Rempel 
379ee394feaSMarek Vasut 	*val = value;
380c2e86691STristram Ha 	return ret;
381c2e86691STristram Ha }
382c2e86691STristram Ha 
383c2e86691STristram Ha static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
384c2e86691STristram Ha {
385ee394feaSMarek Vasut 	unsigned int value;
386ee394feaSMarek Vasut 	int ret = regmap_read(dev->regmap[2], reg, &value);
387c2e86691STristram Ha 
388ec6ba50cSOleksij Rempel 	if (ret)
389ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg,
390ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
391ec6ba50cSOleksij Rempel 
392ee394feaSMarek Vasut 	*val = value;
393c2e86691STristram Ha 	return ret;
394c2e86691STristram Ha }
395c2e86691STristram Ha 
396e66f840cSTristram Ha static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
397e66f840cSTristram Ha {
398e66f840cSTristram Ha 	u32 value[2];
399e66f840cSTristram Ha 	int ret;
400e66f840cSTristram Ha 
401e66f840cSTristram Ha 	ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
402ec6ba50cSOleksij Rempel 	if (ret)
403ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg,
404ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
405ec6ba50cSOleksij Rempel 	else
406c34f674cSBen Hutchings 		*val = (u64)value[0] << 32 | value[1];
407e66f840cSTristram Ha 
408e66f840cSTristram Ha 	return ret;
409e66f840cSTristram Ha }
410e66f840cSTristram Ha 
411c2e86691STristram Ha static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
412c2e86691STristram Ha {
413ec6ba50cSOleksij Rempel 	int ret;
414ec6ba50cSOleksij Rempel 
415ec6ba50cSOleksij Rempel 	ret = regmap_write(dev->regmap[0], reg, value);
416ec6ba50cSOleksij Rempel 	if (ret)
417ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg,
418ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
419ec6ba50cSOleksij Rempel 
420ec6ba50cSOleksij Rempel 	return ret;
421c2e86691STristram Ha }
422c2e86691STristram Ha 
423c2e86691STristram Ha static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
424c2e86691STristram Ha {
425ec6ba50cSOleksij Rempel 	int ret;
426ec6ba50cSOleksij Rempel 
427ec6ba50cSOleksij Rempel 	ret = regmap_write(dev->regmap[1], reg, value);
428ec6ba50cSOleksij Rempel 	if (ret)
429ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg,
430ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
431ec6ba50cSOleksij Rempel 
432ec6ba50cSOleksij Rempel 	return ret;
433c2e86691STristram Ha }
434c2e86691STristram Ha 
435c2e86691STristram Ha static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
436c2e86691STristram Ha {
437ec6ba50cSOleksij Rempel 	int ret;
438ec6ba50cSOleksij Rempel 
439ec6ba50cSOleksij Rempel 	ret = regmap_write(dev->regmap[2], reg, value);
440ec6ba50cSOleksij Rempel 	if (ret)
441ec6ba50cSOleksij Rempel 		dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg,
442ec6ba50cSOleksij Rempel 			ERR_PTR(ret));
443ec6ba50cSOleksij Rempel 
444ec6ba50cSOleksij Rempel 	return ret;
445c2e86691STristram Ha }
446c2e86691STristram Ha 
447e66f840cSTristram Ha static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
448e66f840cSTristram Ha {
449e66f840cSTristram Ha 	u32 val[2];
450e66f840cSTristram Ha 
451e66f840cSTristram Ha 	/* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
452e66f840cSTristram Ha 	value = swab64(value);
453e66f840cSTristram Ha 	val[0] = swab32(value & 0xffffffffULL);
454e66f840cSTristram Ha 	val[1] = swab32(value >> 32ULL);
455e66f840cSTristram Ha 
456e66f840cSTristram Ha 	return regmap_bulk_write(dev->regmap[2], reg, val, 2);
457e66f840cSTristram Ha }
458e66f840cSTristram Ha 
459d38bc3b4SOleksij Rempel static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
460c2e86691STristram Ha 			     u8 *data)
461c2e86691STristram Ha {
462d38bc3b4SOleksij Rempel 	return ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
463c2e86691STristram Ha }
464c2e86691STristram Ha 
465d38bc3b4SOleksij Rempel static inline int ksz_pread16(struct ksz_device *dev, int port, int offset,
466c2e86691STristram Ha 			      u16 *data)
467c2e86691STristram Ha {
468d38bc3b4SOleksij Rempel 	return ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
469c2e86691STristram Ha }
470c2e86691STristram Ha 
471d38bc3b4SOleksij Rempel static inline int ksz_pread32(struct ksz_device *dev, int port, int offset,
472c2e86691STristram Ha 			      u32 *data)
473c2e86691STristram Ha {
474d38bc3b4SOleksij Rempel 	return ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
475c2e86691STristram Ha }
476c2e86691STristram Ha 
477d38bc3b4SOleksij Rempel static inline int ksz_pwrite8(struct ksz_device *dev, int port, int offset,
478c2e86691STristram Ha 			      u8 data)
479c2e86691STristram Ha {
480d38bc3b4SOleksij Rempel 	return ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
481c2e86691STristram Ha }
482c2e86691STristram Ha 
483d38bc3b4SOleksij Rempel static inline int ksz_pwrite16(struct ksz_device *dev, int port, int offset,
484c2e86691STristram Ha 			       u16 data)
485c2e86691STristram Ha {
486d38bc3b4SOleksij Rempel 	return ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset),
487d38bc3b4SOleksij Rempel 			   data);
488c2e86691STristram Ha }
489c2e86691STristram Ha 
490d38bc3b4SOleksij Rempel static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
491c2e86691STristram Ha 			       u32 data)
492c2e86691STristram Ha {
493d38bc3b4SOleksij Rempel 	return ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset),
494d38bc3b4SOleksij Rempel 			   data);
495c2e86691STristram Ha }
496c2e86691STristram Ha 
4978560664fSArun Ramadoss static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
4988560664fSArun Ramadoss 			     u8 mask, u8 val)
4998560664fSArun Ramadoss {
5008560664fSArun Ramadoss 	regmap_update_bits(dev->regmap[0],
5018560664fSArun Ramadoss 			   dev->dev_ops->get_port_addr(port, offset),
5028560664fSArun Ramadoss 			   mask, val);
5038560664fSArun Ramadoss }
5048560664fSArun Ramadoss 
505013572a2SMarek Vasut static inline void ksz_regmap_lock(void *__mtx)
506013572a2SMarek Vasut {
507013572a2SMarek Vasut 	struct mutex *mtx = __mtx;
508013572a2SMarek Vasut 	mutex_lock(mtx);
509013572a2SMarek Vasut }
510013572a2SMarek Vasut 
511013572a2SMarek Vasut static inline void ksz_regmap_unlock(void *__mtx)
512013572a2SMarek Vasut {
513013572a2SMarek Vasut 	struct mutex *mtx = __mtx;
514013572a2SMarek Vasut 	mutex_unlock(mtx);
515013572a2SMarek Vasut }
516013572a2SMarek Vasut 
517f3d890f5SArun Ramadoss static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
518f3d890f5SArun Ramadoss {
519f3d890f5SArun Ramadoss 	return dev->chip_id == KSZ8830_CHIP_ID;
520f3d890f5SArun Ramadoss }
521f3d890f5SArun Ramadoss 
52299b16df0SArun Ramadoss static inline int is_lan937x(struct ksz_device *dev)
52399b16df0SArun Ramadoss {
52499b16df0SArun Ramadoss 	return dev->chip_id == LAN9370_CHIP_ID ||
52599b16df0SArun Ramadoss 		dev->chip_id == LAN9371_CHIP_ID ||
52699b16df0SArun Ramadoss 		dev->chip_id == LAN9372_CHIP_ID ||
52799b16df0SArun Ramadoss 		dev->chip_id == LAN9373_CHIP_ID ||
52899b16df0SArun Ramadoss 		dev->chip_id == LAN9374_CHIP_ID;
52999b16df0SArun Ramadoss }
53099b16df0SArun Ramadoss 
531de6dd626SArun Ramadoss /* STP State Defines */
532de6dd626SArun Ramadoss #define PORT_TX_ENABLE			BIT(2)
533de6dd626SArun Ramadoss #define PORT_RX_ENABLE			BIT(1)
534de6dd626SArun Ramadoss #define PORT_LEARN_DISABLE		BIT(0)
535de6dd626SArun Ramadoss 
53691a98917SArun Ramadoss /* Switch ID Defines */
53791a98917SArun Ramadoss #define REG_CHIP_ID0			0x00
53891a98917SArun Ramadoss 
53991a98917SArun Ramadoss #define SW_FAMILY_ID_M			GENMASK(15, 8)
54091a98917SArun Ramadoss #define KSZ87_FAMILY_ID			0x87
54191a98917SArun Ramadoss #define KSZ88_FAMILY_ID			0x88
54291a98917SArun Ramadoss 
54391a98917SArun Ramadoss #define KSZ8_PORT_STATUS_0		0x08
54491a98917SArun Ramadoss #define KSZ8_PORT_FIBER_MODE		BIT(7)
54591a98917SArun Ramadoss 
54691a98917SArun Ramadoss #define SW_CHIP_ID_M			GENMASK(7, 4)
54791a98917SArun Ramadoss #define KSZ87_CHIP_ID_94		0x6
54891a98917SArun Ramadoss #define KSZ87_CHIP_ID_95		0x9
54991a98917SArun Ramadoss #define KSZ88_CHIP_ID_63		0x3
55091a98917SArun Ramadoss 
55191a98917SArun Ramadoss #define SW_REV_ID_M			GENMASK(7, 4)
55291a98917SArun Ramadoss 
553b4490809SOleksij Rempel /* KSZ9893, KSZ9563, KSZ8563 specific register  */
554b4490809SOleksij Rempel #define REG_CHIP_ID4			0x0f
555b4490809SOleksij Rempel #define SKU_ID_KSZ8563			0x3c
556*ef912fe4SRakesh Sankaranarayanan #define SKU_ID_KSZ9563			0x1c
557b4490809SOleksij Rempel 
5581ca6437fSArun Ramadoss /* Driver set switch broadcast storm protection at 10% rate. */
5591ca6437fSArun Ramadoss #define BROADCAST_STORM_PROT_RATE	10
5601ca6437fSArun Ramadoss 
5611ca6437fSArun Ramadoss /* 148,800 frames * 67 ms / 100 */
5621ca6437fSArun Ramadoss #define BROADCAST_STORM_VALUE		9969
5631ca6437fSArun Ramadoss 
5641ca6437fSArun Ramadoss #define BROADCAST_STORM_RATE_HI		0x07
5651ca6437fSArun Ramadoss #define BROADCAST_STORM_RATE_LO		0xFF
5661ca6437fSArun Ramadoss #define BROADCAST_STORM_RATE		0x07FF
5671ca6437fSArun Ramadoss 
5680abab9f3SArun Ramadoss #define MULTICAST_STORM_DISABLE		BIT(6)
5690abab9f3SArun Ramadoss 
570ad08ac18SArun Ramadoss #define SW_START			0x01
571ad08ac18SArun Ramadoss 
57246f80fa8SArun Ramadoss /* xMII configuration */
5738560664fSArun Ramadoss #define P_MII_DUPLEX_M			BIT(6)
574aa5b8b73SArun Ramadoss #define P_MII_100MBIT_M			BIT(4)
575aa5b8b73SArun Ramadoss 
57646f80fa8SArun Ramadoss #define P_GMII_1GBIT_M			BIT(6)
577dc1c596eSArun Ramadoss #define P_RGMII_ID_IG_ENABLE		BIT(4)
578dc1c596eSArun Ramadoss #define P_RGMII_ID_EG_ENABLE		BIT(3)
5790ab7f6bfSArun Ramadoss #define P_MII_MAC_MODE			BIT(2)
580dc1c596eSArun Ramadoss #define P_MII_SEL_M			0x3
58146f80fa8SArun Ramadoss 
582ff319a64SArun Ramadoss /* Interrupt */
583e1add7ddSArun Ramadoss #define REG_SW_PORT_INT_STATUS__1	0x001B
584e1add7ddSArun Ramadoss #define REG_SW_PORT_INT_MASK__1		0x001F
585ff319a64SArun Ramadoss 
586ff319a64SArun Ramadoss #define REG_PORT_INT_STATUS		0x001B
587ff319a64SArun Ramadoss #define REG_PORT_INT_MASK		0x001F
588ff319a64SArun Ramadoss 
589ff319a64SArun Ramadoss #define PORT_SRC_PHY_INT		1
590ff319a64SArun Ramadoss 
591255b59adSMarek Vasut /* Regmap tables generation */
592255b59adSMarek Vasut #define KSZ_SPI_OP_RD		3
593255b59adSMarek Vasut #define KSZ_SPI_OP_WR		2
594255b59adSMarek Vasut 
59520e03777STristram Ha #define swabnot_used(x)		0
59620e03777STristram Ha 
597255b59adSMarek Vasut #define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad)		\
598255b59adSMarek Vasut 	swab##swp((opcode) << ((regbits) + (regpad)))
599255b59adSMarek Vasut 
600255b59adSMarek Vasut #define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign)		\
601255b59adSMarek Vasut 	{								\
6025f81d545SGeorge McCollister 		.name = #width,						\
603255b59adSMarek Vasut 		.val_bits = (width),					\
604a3aa6e65SMarek Vasut 		.reg_stride = 1,					\
605255b59adSMarek Vasut 		.reg_bits = (regbits) + (regalign),			\
606255b59adSMarek Vasut 		.pad_bits = (regpad),					\
607255b59adSMarek Vasut 		.max_register = BIT(regbits) - 1,			\
608255b59adSMarek Vasut 		.cache_type = REGCACHE_NONE,				\
609255b59adSMarek Vasut 		.read_flag_mask =					\
610255b59adSMarek Vasut 			KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_RD, swp,	\
611255b59adSMarek Vasut 					     regbits, regpad),		\
612255b59adSMarek Vasut 		.write_flag_mask =					\
613255b59adSMarek Vasut 			KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp,	\
614255b59adSMarek Vasut 					     regbits, regpad),		\
615013572a2SMarek Vasut 		.lock = ksz_regmap_lock,				\
616013572a2SMarek Vasut 		.unlock = ksz_regmap_unlock,				\
617255b59adSMarek Vasut 		.reg_format_endian = REGMAP_ENDIAN_BIG,			\
618255b59adSMarek Vasut 		.val_format_endian = REGMAP_ENDIAN_BIG			\
619255b59adSMarek Vasut 	}
620255b59adSMarek Vasut 
621255b59adSMarek Vasut #define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign)		\
622255b59adSMarek Vasut 	static const struct regmap_config ksz##_regmap_config[] = {	\
623255b59adSMarek Vasut 		KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
624255b59adSMarek Vasut 		KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
625255b59adSMarek Vasut 		KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
626255b59adSMarek Vasut 	}
627255b59adSMarek Vasut 
628c2e86691STristram Ha #endif
629