1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /* Microchip switch driver common header
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2017-2019 Microchip Technology Inc.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #ifndef __KSZ_COMMON_H
8*4882a593Smuzhiyun #define __KSZ_COMMON_H
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/etherdevice.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/mutex.h>
13*4882a593Smuzhiyun #include <linux/phy.h>
14*4882a593Smuzhiyun #include <linux/regmap.h>
15*4882a593Smuzhiyun #include <net/dsa.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun struct vlan_table {
18*4882a593Smuzhiyun u32 table[3];
19*4882a593Smuzhiyun };
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun struct ksz_port_mib {
22*4882a593Smuzhiyun struct mutex cnt_mutex; /* structure access */
23*4882a593Smuzhiyun u8 cnt_ptr;
24*4882a593Smuzhiyun u64 *counters;
25*4882a593Smuzhiyun };
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct ksz_port {
28*4882a593Smuzhiyun u16 member;
29*4882a593Smuzhiyun u16 vid_member;
30*4882a593Smuzhiyun bool remove_tag; /* Remove Tag flag set, for ksz8795 only */
31*4882a593Smuzhiyun int stp_state;
32*4882a593Smuzhiyun struct phy_device phydev;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun u32 on:1; /* port is not disabled by hardware */
35*4882a593Smuzhiyun u32 phy:1; /* port has a PHY */
36*4882a593Smuzhiyun u32 fiber:1; /* port is fiber */
37*4882a593Smuzhiyun u32 sgmii:1; /* port is SGMII */
38*4882a593Smuzhiyun u32 force:1;
39*4882a593Smuzhiyun u32 read:1; /* read MIB counters in background */
40*4882a593Smuzhiyun u32 freeze:1; /* MIB counter freeze is enabled */
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun struct ksz_port_mib mib;
43*4882a593Smuzhiyun phy_interface_t interface;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun struct ksz_device {
47*4882a593Smuzhiyun struct dsa_switch *ds;
48*4882a593Smuzhiyun struct ksz_platform_data *pdata;
49*4882a593Smuzhiyun const char *name;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun struct mutex dev_mutex; /* device access */
52*4882a593Smuzhiyun struct mutex regmap_mutex; /* regmap access */
53*4882a593Smuzhiyun struct mutex alu_mutex; /* ALU access */
54*4882a593Smuzhiyun struct mutex vlan_mutex; /* vlan access */
55*4882a593Smuzhiyun const struct ksz_dev_ops *dev_ops;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun struct device *dev;
58*4882a593Smuzhiyun struct regmap *regmap[3];
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun void *priv;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun struct gpio_desc *reset_gpio; /* Optional reset GPIO */
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* chip specific data */
65*4882a593Smuzhiyun u32 chip_id;
66*4882a593Smuzhiyun int num_vlans;
67*4882a593Smuzhiyun int num_alus;
68*4882a593Smuzhiyun int num_statics;
69*4882a593Smuzhiyun int cpu_port; /* port connected to CPU */
70*4882a593Smuzhiyun int cpu_ports; /* port bitmap can be cpu port */
71*4882a593Smuzhiyun int phy_port_cnt;
72*4882a593Smuzhiyun int port_cnt;
73*4882a593Smuzhiyun int reg_mib_cnt;
74*4882a593Smuzhiyun int mib_cnt;
75*4882a593Smuzhiyun int mib_port_cnt;
76*4882a593Smuzhiyun int last_port; /* ports after that not used */
77*4882a593Smuzhiyun phy_interface_t compat_interface;
78*4882a593Smuzhiyun u32 regs_size;
79*4882a593Smuzhiyun bool phy_errata_9477;
80*4882a593Smuzhiyun bool synclko_125;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun struct vlan_table *vlan_cache;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun struct ksz_port *ports;
85*4882a593Smuzhiyun struct delayed_work mib_read;
86*4882a593Smuzhiyun unsigned long mib_read_interval;
87*4882a593Smuzhiyun u16 br_member;
88*4882a593Smuzhiyun u16 member;
89*4882a593Smuzhiyun u16 mirror_rx;
90*4882a593Smuzhiyun u16 mirror_tx;
91*4882a593Smuzhiyun u32 features; /* chip specific features */
92*4882a593Smuzhiyun u32 overrides; /* chip functions set by user */
93*4882a593Smuzhiyun u16 host_mask;
94*4882a593Smuzhiyun u16 port_mask;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun struct alu_struct {
98*4882a593Smuzhiyun /* entry 1 */
99*4882a593Smuzhiyun u8 is_static:1;
100*4882a593Smuzhiyun u8 is_src_filter:1;
101*4882a593Smuzhiyun u8 is_dst_filter:1;
102*4882a593Smuzhiyun u8 prio_age:3;
103*4882a593Smuzhiyun u32 _reserv_0_1:23;
104*4882a593Smuzhiyun u8 mstp:3;
105*4882a593Smuzhiyun /* entry 2 */
106*4882a593Smuzhiyun u8 is_override:1;
107*4882a593Smuzhiyun u8 is_use_fid:1;
108*4882a593Smuzhiyun u32 _reserv_1_1:23;
109*4882a593Smuzhiyun u8 port_forward:7;
110*4882a593Smuzhiyun /* entry 3 & 4*/
111*4882a593Smuzhiyun u32 _reserv_2_1:9;
112*4882a593Smuzhiyun u8 fid:7;
113*4882a593Smuzhiyun u8 mac[ETH_ALEN];
114*4882a593Smuzhiyun };
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun struct ksz_dev_ops {
117*4882a593Smuzhiyun u32 (*get_port_addr)(int port, int offset);
118*4882a593Smuzhiyun void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
119*4882a593Smuzhiyun void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
120*4882a593Smuzhiyun void (*port_cleanup)(struct ksz_device *dev, int port);
121*4882a593Smuzhiyun void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
122*4882a593Smuzhiyun void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
123*4882a593Smuzhiyun void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
124*4882a593Smuzhiyun int (*r_dyn_mac_table)(struct ksz_device *dev, u16 addr, u8 *mac_addr,
125*4882a593Smuzhiyun u8 *fid, u8 *src_port, u8 *timestamp,
126*4882a593Smuzhiyun u16 *entries);
127*4882a593Smuzhiyun int (*r_sta_mac_table)(struct ksz_device *dev, u16 addr,
128*4882a593Smuzhiyun struct alu_struct *alu);
129*4882a593Smuzhiyun void (*w_sta_mac_table)(struct ksz_device *dev, u16 addr,
130*4882a593Smuzhiyun struct alu_struct *alu);
131*4882a593Smuzhiyun void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
132*4882a593Smuzhiyun u64 *cnt);
133*4882a593Smuzhiyun void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
134*4882a593Smuzhiyun u64 *dropped, u64 *cnt);
135*4882a593Smuzhiyun void (*freeze_mib)(struct ksz_device *dev, int port, bool freeze);
136*4882a593Smuzhiyun void (*port_init_cnt)(struct ksz_device *dev, int port);
137*4882a593Smuzhiyun int (*shutdown)(struct ksz_device *dev);
138*4882a593Smuzhiyun int (*detect)(struct ksz_device *dev);
139*4882a593Smuzhiyun int (*init)(struct ksz_device *dev);
140*4882a593Smuzhiyun void (*exit)(struct ksz_device *dev);
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
144*4882a593Smuzhiyun int ksz_switch_register(struct ksz_device *dev,
145*4882a593Smuzhiyun const struct ksz_dev_ops *ops);
146*4882a593Smuzhiyun void ksz_switch_remove(struct ksz_device *dev);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun int ksz8795_switch_register(struct ksz_device *dev);
149*4882a593Smuzhiyun int ksz9477_switch_register(struct ksz_device *dev);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun void ksz_update_port_member(struct ksz_device *dev, int port);
152*4882a593Smuzhiyun void ksz_init_mib_timer(struct ksz_device *dev);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* Common DSA access functions */
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg);
157*4882a593Smuzhiyun int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val);
158*4882a593Smuzhiyun void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
159*4882a593Smuzhiyun phy_interface_t interface);
160*4882a593Smuzhiyun int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
161*4882a593Smuzhiyun void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
162*4882a593Smuzhiyun int ksz_port_bridge_join(struct dsa_switch *ds, int port,
163*4882a593Smuzhiyun struct net_device *br);
164*4882a593Smuzhiyun void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
165*4882a593Smuzhiyun struct net_device *br);
166*4882a593Smuzhiyun void ksz_port_fast_age(struct dsa_switch *ds, int port);
167*4882a593Smuzhiyun int ksz_port_vlan_prepare(struct dsa_switch *ds, int port,
168*4882a593Smuzhiyun const struct switchdev_obj_port_vlan *vlan);
169*4882a593Smuzhiyun int ksz_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb,
170*4882a593Smuzhiyun void *data);
171*4882a593Smuzhiyun int ksz_port_mdb_prepare(struct dsa_switch *ds, int port,
172*4882a593Smuzhiyun const struct switchdev_obj_port_mdb *mdb);
173*4882a593Smuzhiyun void ksz_port_mdb_add(struct dsa_switch *ds, int port,
174*4882a593Smuzhiyun const struct switchdev_obj_port_mdb *mdb);
175*4882a593Smuzhiyun int ksz_port_mdb_del(struct dsa_switch *ds, int port,
176*4882a593Smuzhiyun const struct switchdev_obj_port_mdb *mdb);
177*4882a593Smuzhiyun int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /* Common register access functions */
180*4882a593Smuzhiyun
ksz_read8(struct ksz_device * dev,u32 reg,u8 * val)181*4882a593Smuzhiyun static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun unsigned int value;
184*4882a593Smuzhiyun int ret = regmap_read(dev->regmap[0], reg, &value);
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun *val = value;
187*4882a593Smuzhiyun return ret;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
ksz_read16(struct ksz_device * dev,u32 reg,u16 * val)190*4882a593Smuzhiyun static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun unsigned int value;
193*4882a593Smuzhiyun int ret = regmap_read(dev->regmap[1], reg, &value);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun *val = value;
196*4882a593Smuzhiyun return ret;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
ksz_read32(struct ksz_device * dev,u32 reg,u32 * val)199*4882a593Smuzhiyun static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun unsigned int value;
202*4882a593Smuzhiyun int ret = regmap_read(dev->regmap[2], reg, &value);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun *val = value;
205*4882a593Smuzhiyun return ret;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
ksz_read64(struct ksz_device * dev,u32 reg,u64 * val)208*4882a593Smuzhiyun static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun u32 value[2];
211*4882a593Smuzhiyun int ret;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
214*4882a593Smuzhiyun if (!ret)
215*4882a593Smuzhiyun *val = (u64)value[0] << 32 | value[1];
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return ret;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
ksz_write8(struct ksz_device * dev,u32 reg,u8 value)220*4882a593Smuzhiyun static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun return regmap_write(dev->regmap[0], reg, value);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
ksz_write16(struct ksz_device * dev,u32 reg,u16 value)225*4882a593Smuzhiyun static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun return regmap_write(dev->regmap[1], reg, value);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
ksz_write32(struct ksz_device * dev,u32 reg,u32 value)230*4882a593Smuzhiyun static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun return regmap_write(dev->regmap[2], reg, value);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun
ksz_write64(struct ksz_device * dev,u32 reg,u64 value)235*4882a593Smuzhiyun static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun u32 val[2];
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
240*4882a593Smuzhiyun value = swab64(value);
241*4882a593Smuzhiyun val[0] = swab32(value & 0xffffffffULL);
242*4882a593Smuzhiyun val[1] = swab32(value >> 32ULL);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return regmap_bulk_write(dev->regmap[2], reg, val, 2);
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
ksz_pread8(struct ksz_device * dev,int port,int offset,u8 * data)247*4882a593Smuzhiyun static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
248*4882a593Smuzhiyun u8 *data)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
ksz_pread16(struct ksz_device * dev,int port,int offset,u16 * data)253*4882a593Smuzhiyun static inline void ksz_pread16(struct ksz_device *dev, int port, int offset,
254*4882a593Smuzhiyun u16 *data)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
ksz_pread32(struct ksz_device * dev,int port,int offset,u32 * data)259*4882a593Smuzhiyun static inline void ksz_pread32(struct ksz_device *dev, int port, int offset,
260*4882a593Smuzhiyun u32 *data)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
ksz_pwrite8(struct ksz_device * dev,int port,int offset,u8 data)265*4882a593Smuzhiyun static inline void ksz_pwrite8(struct ksz_device *dev, int port, int offset,
266*4882a593Smuzhiyun u8 data)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
ksz_pwrite16(struct ksz_device * dev,int port,int offset,u16 data)271*4882a593Smuzhiyun static inline void ksz_pwrite16(struct ksz_device *dev, int port, int offset,
272*4882a593Smuzhiyun u16 data)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset), data);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
ksz_pwrite32(struct ksz_device * dev,int port,int offset,u32 data)277*4882a593Smuzhiyun static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
278*4882a593Smuzhiyun u32 data)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun
ksz_regmap_lock(void * __mtx)283*4882a593Smuzhiyun static inline void ksz_regmap_lock(void *__mtx)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun struct mutex *mtx = __mtx;
286*4882a593Smuzhiyun mutex_lock(mtx);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
ksz_regmap_unlock(void * __mtx)289*4882a593Smuzhiyun static inline void ksz_regmap_unlock(void *__mtx)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun struct mutex *mtx = __mtx;
292*4882a593Smuzhiyun mutex_unlock(mtx);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /* Regmap tables generation */
296*4882a593Smuzhiyun #define KSZ_SPI_OP_RD 3
297*4882a593Smuzhiyun #define KSZ_SPI_OP_WR 2
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun #define swabnot_used(x) 0
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun #define KSZ_SPI_OP_FLAG_MASK(opcode, swp, regbits, regpad) \
302*4882a593Smuzhiyun swab##swp((opcode) << ((regbits) + (regpad)))
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun #define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \
305*4882a593Smuzhiyun { \
306*4882a593Smuzhiyun .name = #width, \
307*4882a593Smuzhiyun .val_bits = (width), \
308*4882a593Smuzhiyun .reg_stride = 1, \
309*4882a593Smuzhiyun .reg_bits = (regbits) + (regalign), \
310*4882a593Smuzhiyun .pad_bits = (regpad), \
311*4882a593Smuzhiyun .max_register = BIT(regbits) - 1, \
312*4882a593Smuzhiyun .cache_type = REGCACHE_NONE, \
313*4882a593Smuzhiyun .read_flag_mask = \
314*4882a593Smuzhiyun KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_RD, swp, \
315*4882a593Smuzhiyun regbits, regpad), \
316*4882a593Smuzhiyun .write_flag_mask = \
317*4882a593Smuzhiyun KSZ_SPI_OP_FLAG_MASK(KSZ_SPI_OP_WR, swp, \
318*4882a593Smuzhiyun regbits, regpad), \
319*4882a593Smuzhiyun .lock = ksz_regmap_lock, \
320*4882a593Smuzhiyun .unlock = ksz_regmap_unlock, \
321*4882a593Smuzhiyun .reg_format_endian = REGMAP_ENDIAN_BIG, \
322*4882a593Smuzhiyun .val_format_endian = REGMAP_ENDIAN_BIG \
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun #define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \
326*4882a593Smuzhiyun static const struct regmap_config ksz##_regmap_config[] = { \
327*4882a593Smuzhiyun KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \
328*4882a593Smuzhiyun KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \
329*4882a593Smuzhiyun KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun #endif
333