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