xref: /freebsd/sys/dev/etherswitch/mtkswitch/mtkswitch_mt7620.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
1 /*-
2  * Copyright (c) 2016 Stanislav Galabov.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 
29 #include <sys/param.h>
30 #include <sys/bus.h>
31 #include <sys/errno.h>
32 #include <sys/kernel.h>
33 #include <sys/lock.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/rman.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42 
43 #include <net/if.h>
44 #include <net/if_var.h>
45 #include <net/ethernet.h>
46 #include <net/if_media.h>
47 #include <net/if_types.h>
48 
49 #include <machine/bus.h>
50 #include <dev/mii/mii.h>
51 #include <dev/mii/miivar.h>
52 #include <dev/mdio/mdio.h>
53 
54 #include <dev/etherswitch/etherswitch.h>
55 #include <dev/etherswitch/mtkswitch/mtkswitchvar.h>
56 #include <dev/etherswitch/mtkswitch/mtkswitch_mt7620.h>
57 
58 static int
59 mtkswitch_phy_read_locked(struct mtkswitch_softc *sc, int phy, int reg)
60 {
61 	uint32_t data;
62 
63 	MTKSWITCH_WRITE(sc, MTKSWITCH_PIAC, PIAC_PHY_ACS_ST | PIAC_MDIO_ST |
64 	    (reg << PIAC_MDIO_REG_ADDR_OFF) | (phy << PIAC_MDIO_PHY_ADDR_OFF) |
65 	    PIAC_MDIO_CMD_READ);
66 	while ((data = MTKSWITCH_READ(sc, MTKSWITCH_PIAC)) & PIAC_PHY_ACS_ST);
67 
68 	return ((int)(data & PIAC_MDIO_RW_DATA_MASK));
69 }
70 
71 static int
72 mtkswitch_phy_read(device_t dev, int phy, int reg)
73 {
74 	struct mtkswitch_softc *sc = device_get_softc(dev);
75 	int data;
76 
77 	if ((phy < 0 || phy >= 32) || (reg < 0 || reg >= 32))
78 		return (ENXIO);
79 
80 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
81 	MTKSWITCH_LOCK(sc);
82 	data = mtkswitch_phy_read_locked(sc, phy, reg);
83 	MTKSWITCH_UNLOCK(sc);
84 
85 	return (data);
86 }
87 
88 static int
89 mtkswitch_phy_write_locked(struct mtkswitch_softc *sc, int phy, int reg,
90     int val)
91 {
92 
93 	MTKSWITCH_WRITE(sc, MTKSWITCH_PIAC, PIAC_PHY_ACS_ST | PIAC_MDIO_ST |
94 	    (reg << PIAC_MDIO_REG_ADDR_OFF) | (phy << PIAC_MDIO_PHY_ADDR_OFF) |
95 	    (val & PIAC_MDIO_RW_DATA_MASK) | PIAC_MDIO_CMD_WRITE);
96 	while (MTKSWITCH_READ(sc, MTKSWITCH_PIAC) & PIAC_PHY_ACS_ST);
97 
98 	return (0);
99 }
100 
101 static int
102 mtkswitch_phy_write(device_t dev, int phy, int reg, int val)
103 {
104 	struct mtkswitch_softc *sc = device_get_softc(dev);
105 	int res;
106 
107 	if ((phy < 0 || phy >= 32) || (reg < 0 || reg >= 32))
108 		return (ENXIO);
109 
110 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
111 	MTKSWITCH_LOCK(sc);
112 	res = mtkswitch_phy_write_locked(sc, phy, reg, val);
113 	MTKSWITCH_UNLOCK(sc);
114 
115 	return (res);
116 }
117 
118 static uint32_t
119 mtkswitch_reg_read32(struct mtkswitch_softc *sc, int reg)
120 {
121 
122 	return (MTKSWITCH_READ(sc, reg));
123 }
124 
125 static uint32_t
126 mtkswitch_reg_write32(struct mtkswitch_softc *sc, int reg, uint32_t val)
127 {
128 
129 	MTKSWITCH_WRITE(sc, reg, val);
130 	return (0);
131 }
132 
133 static uint32_t
134 mtkswitch_reg_read32_mt7621(struct mtkswitch_softc *sc, int reg)
135 {
136 	uint32_t low, hi;
137 
138 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
139 	mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
140 	    MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg));
141 	low = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY,
142 	    MTKSWITCH_REG_LO(reg));
143 	hi = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY,
144 	    MTKSWITCH_REG_HI(reg));;
145 	return (low | (hi << 16));
146 }
147 
148 static uint32_t
149 mtkswitch_reg_write32_mt7621(struct mtkswitch_softc *sc, int reg, uint32_t val)
150 {
151 
152 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
153 	mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
154 	    MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg));
155 	mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
156 	    MTKSWITCH_REG_LO(reg), MTKSWITCH_VAL_LO(val));
157 	mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
158 	    MTKSWITCH_REG_HI(reg), MTKSWITCH_VAL_HI(val));
159 	return (0);
160 }
161 
162 static int
163 mtkswitch_reg_read(device_t dev, int reg)
164 {
165 	struct mtkswitch_softc *sc = device_get_softc(dev);
166 	uint32_t val;
167 
168 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg));
169 	if (MTKSWITCH_IS_HI16(reg))
170 		return (MTKSWITCH_HI16(val));
171 	return (MTKSWITCH_LO16(val));
172 }
173 
174 static int
175 mtkswitch_reg_write(device_t dev, int reg, int val)
176 {
177 	struct mtkswitch_softc *sc = device_get_softc(dev);
178 	uint32_t tmp;
179 
180 	tmp = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg));
181 	if (MTKSWITCH_IS_HI16(reg)) {
182 		tmp &= MTKSWITCH_LO16_MSK;
183 		tmp |= MTKSWITCH_TO_HI16(val);
184 	} else {
185 		tmp &= MTKSWITCH_HI16_MSK;
186 		tmp |= MTKSWITCH_TO_LO16(val);
187 	}
188 	sc->hal.mtkswitch_write(sc, MTKSWITCH_REG32(reg), tmp);
189 
190 	return (0);
191 }
192 
193 static int
194 mtkswitch_reset(struct mtkswitch_softc *sc)
195 {
196 
197 	/* We don't reset the switch for now */
198 	return (0);
199 }
200 
201 static int
202 mtkswitch_hw_setup(struct mtkswitch_softc *sc)
203 {
204 
205 	/*
206 	 * TODO: parse the device tree and see if we need to configure
207 	 *       ports, etc. differently. For now we fallback to defaults.
208 	 */
209 
210 	/* Called early and hence unlocked */
211 	return (0);
212 }
213 
214 static int
215 mtkswitch_hw_global_setup(struct mtkswitch_softc *sc)
216 {
217 	/* Currently does nothing */
218 
219 	/* Called early and hence unlocked */
220 	return (0);
221 }
222 
223 static void
224 mtkswitch_port_init(struct mtkswitch_softc *sc, int port)
225 {
226 	uint32_t val;
227 
228 	/* Called early and hence unlocked */
229 
230 	/* Set the port to secure mode */
231 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PCR(port));
232 	val |= PCR_PORT_VLAN_SECURE;
233 	sc->hal.mtkswitch_write(sc, MTKSWITCH_PCR(port), val);
234 
235 	/* Set port's vlan_attr to user port */
236 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PVC(port));
237 	val &= ~PVC_VLAN_ATTR_MASK;
238 	sc->hal.mtkswitch_write(sc, MTKSWITCH_PVC(port), val);
239 
240 	val = PMCR_CFG_DEFAULT;
241 	if (port == sc->cpuport)
242 		val |= PMCR_FORCE_LINK | PMCR_FORCE_DPX | PMCR_FORCE_SPD_1000 |
243 		    PMCR_FORCE_MODE;
244 	/* Set port's MAC to default settings */
245 	sc->hal.mtkswitch_write(sc, MTKSWITCH_PMCR(port), val);
246 }
247 
248 static uint32_t
249 mtkswitch_get_port_status(struct mtkswitch_softc *sc, int port)
250 {
251 	uint32_t val, res, tmp;
252 
253 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
254 	res = 0;
255 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PMSR(port));
256 
257 	if (val & PMSR_MAC_LINK_STS)
258 		res |= MTKSWITCH_LINK_UP;
259 	if (val & PMSR_MAC_DPX_STS)
260 		res |= MTKSWITCH_DUPLEX;
261 	tmp = PMSR_MAC_SPD(val);
262 	if (tmp == 0)
263 		res |= MTKSWITCH_SPEED_10;
264 	else if (tmp == 1)
265 		res |= MTKSWITCH_SPEED_100;
266 	else if (tmp == 2)
267 		res |= MTKSWITCH_SPEED_1000;
268 	if (val & PMSR_TX_FC_STS)
269 		res |= MTKSWITCH_TXFLOW;
270 	if (val & PMSR_RX_FC_STS)
271 		res |= MTKSWITCH_RXFLOW;
272 
273 	return (res);
274 }
275 
276 static int
277 mtkswitch_atu_flush(struct mtkswitch_softc *sc)
278 {
279 
280 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
281 
282 	/* Flush all non-static MAC addresses */
283 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY);
284 	sc->hal.mtkswitch_write(sc, MTKSWITCH_ATC, ATC_BUSY |
285 	    ATC_AC_MAT_NON_STATIC_MACS | ATC_AC_CMD_CLEAN);
286 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY);
287 
288 	return (0);
289 }
290 
291 static int
292 mtkswitch_port_vlan_setup(struct mtkswitch_softc *sc, etherswitch_port_t *p)
293 {
294 	int err;
295 
296 	/*
297 	 * Port behaviour wrt tag/untag/stack is currently defined per-VLAN.
298 	 * So we say we don't support it here.
299 	 */
300 	if ((p->es_flags & (ETHERSWITCH_PORT_DOUBLE_TAG |
301 	    ETHERSWITCH_PORT_ADDTAG | ETHERSWITCH_PORT_STRIPTAG)) != 0)
302 		return (ENOTSUP);
303 
304 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
305 	MTKSWITCH_LOCK(sc);
306 
307 	/* Set the PVID */
308 	if (p->es_pvid != 0) {
309 		err = sc->hal.mtkswitch_vlan_set_pvid(sc, p->es_port,
310 		    p->es_pvid);
311 		if (err != 0) {
312 			MTKSWITCH_UNLOCK(sc);
313 			return (err);
314 		}
315 	}
316 
317 	MTKSWITCH_UNLOCK(sc);
318 
319 	return (0);
320 }
321 
322 static int
323 mtkswitch_port_vlan_get(struct mtkswitch_softc *sc, etherswitch_port_t *p)
324 {
325 
326 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
327 	MTKSWITCH_LOCK(sc);
328 
329 	/* Retrieve the PVID */
330 	sc->hal.mtkswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
331 
332 	/*
333 	 * Port flags are not supported at the moment.
334 	 * Port's tag/untag/stack behaviour is defined per-VLAN.
335 	 */
336 	p->es_flags = 0;
337 
338 	MTKSWITCH_UNLOCK(sc);
339 
340 	return (0);
341 }
342 
343 static void
344 mtkswitch_invalidate_vlan(struct mtkswitch_softc *sc, uint32_t vid)
345 {
346 
347 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
348 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
349 	    VTCR_FUNC_VID_INVALID | (vid & VTCR_VID_MASK));
350 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
351 }
352 
353 static void
354 mtkswitch_vlan_init_hw(struct mtkswitch_softc *sc)
355 {
356 	uint32_t val, vid, i;
357 
358 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
359 	MTKSWITCH_LOCK(sc);
360 	/* Reset all VLANs to defaults first */
361 	for (i = 0; i < sc->info.es_nvlangroups; i++) {
362 		mtkswitch_invalidate_vlan(sc, i);
363 		if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
364 			val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTIM(i));
365 			val &= ~(VTIM_MASK << VTIM_OFF(i));
366 			val |= ((i + 1) << VTIM_OFF(i));
367 			sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(i), val);
368 		}
369 	}
370 
371 	/* Now, add all ports as untagged members of VLAN 1 */
372 	if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
373 		/* MT7620 uses vid index instead of actual vid */
374 		vid = 0;
375 	} else {
376 		/* MT7621 uses the vid itself */
377 		vid = 1;
378 	}
379 	val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID;
380 	for (i = 0; i < sc->info.es_nports; i++)
381 		val |= VAWD1_PORT_MEMBER(i);
382 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val);
383 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, 0);
384 	val = VTCR_BUSY | VTCR_FUNC_VID_WRITE | vid;
385 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, val);
386 
387 	/* Set all port PVIDs to 1 */
388 	for (i = 0; i < sc->info.es_nports; i++) {
389 		sc->hal.mtkswitch_vlan_set_pvid(sc, i, 1);
390 	}
391 
392 	MTKSWITCH_UNLOCK(sc);
393 }
394 
395 static int
396 mtkswitch_vlan_getvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v)
397 {
398 	uint32_t val, i;
399 
400 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
401 
402 	if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) ||
403 	    (v->es_vlangroup > sc->info.es_nvlangroups))
404 		return (EINVAL);
405 
406 	/* Reset the member ports. */
407 	v->es_untagged_ports = 0;
408 	v->es_member_ports = 0;
409 
410 	/* Not supported for now */
411 	v->es_fid = 0;
412 
413 	MTKSWITCH_LOCK(sc);
414 	if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
415 		v->es_vid = (sc->hal.mtkswitch_read(sc,
416 		    MTKSWITCH_VTIM(v->es_vlangroup)) >>
417 		    VTIM_OFF(v->es_vlangroup)) & VTIM_MASK;
418 	} else {
419 		v->es_vid = v->es_vlangroup;
420 	}
421 
422 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
423 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
424 	    VTCR_FUNC_VID_READ | (v->es_vlangroup & VTCR_VID_MASK));
425 	while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY);
426 	if (val & VTCR_IDX_INVALID) {
427 		MTKSWITCH_UNLOCK(sc);
428 		return (0);
429 	}
430 
431 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD1);
432 	if (val & VAWD1_VALID)
433 		v->es_vid |= ETHERSWITCH_VID_VALID;
434 	else {
435 		MTKSWITCH_UNLOCK(sc);
436 		return (0);
437 	}
438 	v->es_member_ports = (val >> VAWD1_MEMBER_OFF) & VAWD1_MEMBER_MASK;
439 
440 	val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD2);
441 	for (i = 0; i < sc->info.es_nports; i++) {
442 		if ((val & VAWD2_PORT_MASK(i)) == VAWD2_PORT_UNTAGGED(i))
443 			v->es_untagged_ports |= (1<<i);
444 	}
445 
446 	MTKSWITCH_UNLOCK(sc);
447 	return (0);
448 }
449 
450 static int
451 mtkswitch_vlan_setvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v)
452 {
453 	uint32_t val, i, vid;
454 
455 	MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
456 
457 	if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) ||
458 	    (v->es_vlangroup > sc->info.es_nvlangroups))
459 		return (EINVAL);
460 
461 	/* We currently don't support FID */
462 	if (v->es_fid != 0)
463 		return (EINVAL);
464 
465 	MTKSWITCH_LOCK(sc);
466 	while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
467 	if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
468 		val = sc->hal.mtkswitch_read(sc,
469 		    MTKSWITCH_VTIM(v->es_vlangroup));
470 		val &= ~(VTIM_MASK << VTIM_OFF(v->es_vlangroup));
471 		val |= ((v->es_vid & VTIM_MASK) << VTIM_OFF(v->es_vlangroup));
472 		sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(v->es_vlangroup),
473 		    val);
474 		vid = v->es_vlangroup;
475 	} else
476 		vid = v->es_vid;
477 
478 	/* We use FID 0 */
479 	val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID;
480 	val |= ((v->es_member_ports & VAWD1_MEMBER_MASK) << VAWD1_MEMBER_OFF);
481 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val);
482 
483 	/* Set tagged ports */
484 	val = 0;
485 	for (i = 0; i < sc->info.es_nports; i++)
486 		if (((1<<i) & v->es_untagged_ports) == 0)
487 			val |= VAWD2_PORT_TAGGED(i);
488 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, val);
489 
490 	/* Write the VLAN entry */
491 	sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
492 	    VTCR_FUNC_VID_WRITE | (vid & VTCR_VID_MASK));
493 	while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY);
494 
495 	MTKSWITCH_UNLOCK(sc);
496 
497 	if (val & VTCR_IDX_INVALID)
498 		return (EINVAL);
499 
500 	return (0);
501 }
502 
503 static int
504 mtkswitch_vlan_get_pvid(struct mtkswitch_softc *sc, int port, int *pvid)
505 {
506 
507 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
508 
509 	*pvid = sc->hal.mtkswitch_read(sc, MTKSWITCH_PPBV1(port));
510 	*pvid = PPBV_VID_FROM_REG(*pvid);
511 
512 	return (0);
513 }
514 
515 static int
516 mtkswitch_vlan_set_pvid(struct mtkswitch_softc *sc, int port, int pvid)
517 {
518 	uint32_t val;
519 
520 	MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
521 	val = PPBV_VID(pvid & PPBV_VID_MASK);
522 	sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV1(port), val);
523 	sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV2(port), val);
524 
525 	return (0);
526 }
527 
528 extern void
529 mtk_attach_switch_mt7620(struct mtkswitch_softc *sc)
530 {
531 
532 	sc->portmap = 0x7f;
533 	sc->phymap = 0x1f;
534 
535 	sc->info.es_nports = 7;
536 	sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
537 	sc->info.es_nvlangroups = 16;
538 	sprintf(sc->info.es_name, "Mediatek GSW");
539 
540 	if (sc->sc_switchtype == MTK_SWITCH_MT7621) {
541 		sc->hal.mtkswitch_read = mtkswitch_reg_read32_mt7621;
542 		sc->hal.mtkswitch_write = mtkswitch_reg_write32_mt7621;
543 		sc->info.es_nvlangroups = 4096;
544 	} else {
545 		sc->hal.mtkswitch_read = mtkswitch_reg_read32;
546 		sc->hal.mtkswitch_write = mtkswitch_reg_write32;
547 	}
548 
549 	sc->hal.mtkswitch_reset = mtkswitch_reset;
550 	sc->hal.mtkswitch_hw_setup = mtkswitch_hw_setup;
551 	sc->hal.mtkswitch_hw_global_setup = mtkswitch_hw_global_setup;
552 	sc->hal.mtkswitch_port_init = mtkswitch_port_init;
553 	sc->hal.mtkswitch_get_port_status = mtkswitch_get_port_status;
554 	sc->hal.mtkswitch_atu_flush = mtkswitch_atu_flush;
555 	sc->hal.mtkswitch_port_vlan_setup = mtkswitch_port_vlan_setup;
556 	sc->hal.mtkswitch_port_vlan_get = mtkswitch_port_vlan_get;
557 	sc->hal.mtkswitch_vlan_init_hw = mtkswitch_vlan_init_hw;
558 	sc->hal.mtkswitch_vlan_getvgroup = mtkswitch_vlan_getvgroup;
559 	sc->hal.mtkswitch_vlan_setvgroup = mtkswitch_vlan_setvgroup;
560 	sc->hal.mtkswitch_vlan_get_pvid = mtkswitch_vlan_get_pvid;
561 	sc->hal.mtkswitch_vlan_set_pvid = mtkswitch_vlan_set_pvid;
562 	sc->hal.mtkswitch_phy_read = mtkswitch_phy_read;
563 	sc->hal.mtkswitch_phy_write = mtkswitch_phy_write;
564 	sc->hal.mtkswitch_reg_read = mtkswitch_reg_read;
565 	sc->hal.mtkswitch_reg_write = mtkswitch_reg_write;
566 }
567