xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch_8327.c (revision b5864e6de2f3aa8eb9bb269ec86282598b5201b1)
1 /*-
2  * Copyright (c) 2011-2012 Stefan Bethke.
3  * Copyright (c) 2014 Adrian Chadd.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29 
30 #include <sys/param.h>
31 #include <sys/bus.h>
32 #include <sys/errno.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/socket.h>
36 #include <sys/sockio.h>
37 #include <sys/sysctl.h>
38 #include <sys/systm.h>
39 
40 #include <net/if.h>
41 #include <net/if_arp.h>
42 #include <net/ethernet.h>
43 #include <net/if_dl.h>
44 #include <net/if_media.h>
45 #include <net/if_types.h>
46 
47 #include <machine/bus.h>
48 #include <dev/iicbus/iic.h>
49 #include <dev/iicbus/iiconf.h>
50 #include <dev/iicbus/iicbus.h>
51 #include <dev/mii/mii.h>
52 #include <dev/mii/miivar.h>
53 #include <dev/mdio/mdio.h>
54 
55 #include <dev/etherswitch/etherswitch.h>
56 
57 #include <dev/etherswitch/arswitch/arswitchreg.h>
58 #include <dev/etherswitch/arswitch/arswitchvar.h>
59 #include <dev/etherswitch/arswitch/arswitch_reg.h>
60 #include <dev/etherswitch/arswitch/arswitch_phy.h>
61 #include <dev/etherswitch/arswitch/arswitch_vlans.h>
62 
63 #include <dev/etherswitch/arswitch/arswitch_8327.h>
64 
65 #include "mdio_if.h"
66 #include "miibus_if.h"
67 #include "etherswitch_if.h"
68 
69 /*
70  * AR8327 TODO:
71  *
72  * There should be a default hardware setup hint set for the default
73  * switch config.  Otherwise the default is "all ports in one vlangroup",
74  * which means both CPU ports can see each other and that will quickly
75  * lead to traffic storms/loops.
76  */
77 
78 /* Map port+led to register+shift */
79 struct ar8327_led_mapping ar8327_led_mapping[AR8327_NUM_PHYS][ETHERSWITCH_PORT_MAX_LEDS] =
80 {
81 	{	/* PHY0 */
82 		{AR8327_REG_LED_CTRL0, 14 },
83 		{AR8327_REG_LED_CTRL1, 14 },
84 		{AR8327_REG_LED_CTRL2, 14 }
85 	},
86 	{	/* PHY1 */
87 		{AR8327_REG_LED_CTRL3, 8  },
88 		{AR8327_REG_LED_CTRL3, 10 },
89 		{AR8327_REG_LED_CTRL3, 12 }
90 	},
91 	{	/* PHY2 */
92 		{AR8327_REG_LED_CTRL3, 14 },
93 		{AR8327_REG_LED_CTRL3, 16 },
94 		{AR8327_REG_LED_CTRL3, 18 }
95 	},
96 	{	/* PHY3 */
97 		{AR8327_REG_LED_CTRL3, 20 },
98 		{AR8327_REG_LED_CTRL3, 22 },
99 		{AR8327_REG_LED_CTRL3, 24 }
100 	},
101 	{	/* PHY4 */
102 		{AR8327_REG_LED_CTRL0, 30 },
103 		{AR8327_REG_LED_CTRL1, 30 },
104 		{AR8327_REG_LED_CTRL2, 30 }
105 	}
106 };
107 
108 static int
109 ar8327_vlan_op(struct arswitch_softc *sc, uint32_t op, uint32_t vid,
110     uint32_t data)
111 {
112 	int err;
113 
114 	/*
115 	 * Wait for the "done" bit to finish.
116 	 */
117 	if (arswitch_waitreg(sc->sc_dev, AR8327_REG_VTU_FUNC1,
118 	    AR8327_VTU_FUNC1_BUSY, 0, 5))
119 		return (EBUSY);
120 
121 	/*
122 	 * If it's a "load" operation, then ensure 'data' is loaded
123 	 * in first.
124 	 */
125 	if ((op & AR8327_VTU_FUNC1_OP) == AR8327_VTU_FUNC1_OP_LOAD) {
126 		err = arswitch_writereg(sc->sc_dev, AR8327_REG_VTU_FUNC0, data);
127 		if (err)
128 			return (err);
129 	}
130 
131 	/*
132 	 * Set the VID.
133 	 */
134 	op |= ((vid & 0xfff) << AR8327_VTU_FUNC1_VID_S);
135 
136 	/*
137 	 * Set busy bit to start loading in the command.
138 	 */
139 	op |= AR8327_VTU_FUNC1_BUSY;
140 	arswitch_writereg(sc->sc_dev, AR8327_REG_VTU_FUNC1, op);
141 
142 	/*
143 	 * Finally - wait for it to load.
144 	 */
145 	if (arswitch_waitreg(sc->sc_dev, AR8327_REG_VTU_FUNC1,
146 	    AR8327_VTU_FUNC1_BUSY, 0, 5))
147 		return (EBUSY);
148 
149 	return (0);
150 }
151 
152 static void
153 ar8327_phy_fixup(struct arswitch_softc *sc, int phy)
154 {
155 	if (bootverbose)
156 		device_printf(sc->sc_dev,
157 		    "%s: called; phy=%d; chiprev=%d\n", __func__,
158 		    phy,
159 		    sc->chip_rev);
160 	switch (sc->chip_rev) {
161 	case 1:
162 		/* For 100M waveform */
163 		arswitch_writedbg(sc->sc_dev, phy, 0, 0x02ea);
164 		/* Turn on Gigabit clock */
165 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x68a0);
166 		break;
167 
168 	case 2:
169 		arswitch_writemmd(sc->sc_dev, phy, 0x7, 0x3c);
170 		arswitch_writemmd(sc->sc_dev, phy, 0x4007, 0x0);
171 		/* fallthrough */
172 	case 4:
173 		arswitch_writemmd(sc->sc_dev, phy, 0x3, 0x800d);
174 		arswitch_writemmd(sc->sc_dev, phy, 0x4003, 0x803f);
175 
176 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x6860);
177 		arswitch_writedbg(sc->sc_dev, phy, 0x5, 0x2c46);
178 		arswitch_writedbg(sc->sc_dev, phy, 0x3c, 0x6000);
179 		break;
180 	}
181 }
182 
183 static uint32_t
184 ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
185 {
186 	uint32_t t;
187 
188 	if (!cfg)
189 		return (0);
190 
191 	t = 0;
192 	switch (cfg->mode) {
193 	case AR8327_PAD_NC:
194 		break;
195 
196 	case AR8327_PAD_MAC2MAC_MII:
197 		t = AR8327_PAD_MAC_MII_EN;
198 		if (cfg->rxclk_sel)
199 			t |= AR8327_PAD_MAC_MII_RXCLK_SEL;
200 		if (cfg->txclk_sel)
201 			t |= AR8327_PAD_MAC_MII_TXCLK_SEL;
202 		break;
203 
204 	case AR8327_PAD_MAC2MAC_GMII:
205 		t = AR8327_PAD_MAC_GMII_EN;
206 		if (cfg->rxclk_sel)
207 			t |= AR8327_PAD_MAC_GMII_RXCLK_SEL;
208 		if (cfg->txclk_sel)
209 			t |= AR8327_PAD_MAC_GMII_TXCLK_SEL;
210 		break;
211 
212 	case AR8327_PAD_MAC_SGMII:
213 		t = AR8327_PAD_SGMII_EN;
214 
215 		/*
216 		 * WAR for the Qualcomm Atheros AP136 board.
217 		 * It seems that RGMII TX/RX delay settings needs to be
218 		 * applied for SGMII mode as well, The ethernet is not
219 		 * reliable without this.
220 		 */
221 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
222 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
223 		if (cfg->rxclk_delay_en)
224 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
225 		if (cfg->txclk_delay_en)
226 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
227 
228 		if (cfg->sgmii_delay_en)
229 			t |= AR8327_PAD_SGMII_DELAY_EN;
230 
231 		break;
232 
233 	case AR8327_PAD_MAC2PHY_MII:
234 		t = AR8327_PAD_PHY_MII_EN;
235 		if (cfg->rxclk_sel)
236 			t |= AR8327_PAD_PHY_MII_RXCLK_SEL;
237 		if (cfg->txclk_sel)
238 			t |= AR8327_PAD_PHY_MII_TXCLK_SEL;
239 		break;
240 
241 	case AR8327_PAD_MAC2PHY_GMII:
242 		t = AR8327_PAD_PHY_GMII_EN;
243 		if (cfg->pipe_rxclk_sel)
244 			t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL;
245 		if (cfg->rxclk_sel)
246 			t |= AR8327_PAD_PHY_GMII_RXCLK_SEL;
247 		if (cfg->txclk_sel)
248 			t |= AR8327_PAD_PHY_GMII_TXCLK_SEL;
249 		break;
250 
251 	case AR8327_PAD_MAC_RGMII:
252 		t = AR8327_PAD_RGMII_EN;
253 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
254 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
255 		if (cfg->rxclk_delay_en)
256 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
257 		if (cfg->txclk_delay_en)
258 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
259 		break;
260 
261 	case AR8327_PAD_PHY_GMII:
262 		t = AR8327_PAD_PHYX_GMII_EN;
263 		break;
264 
265 	case AR8327_PAD_PHY_RGMII:
266 		t = AR8327_PAD_PHYX_RGMII_EN;
267 		break;
268 
269 	case AR8327_PAD_PHY_MII:
270 		t = AR8327_PAD_PHYX_MII_EN;
271 		break;
272 	}
273 
274 	return (t);
275 }
276 
277 /*
278  * Map the hard-coded port config from the switch setup to
279  * the chipset port config (status, duplex, flow, etc.)
280  */
281 static uint32_t
282 ar8327_get_port_init_status(struct ar8327_port_cfg *cfg)
283 {
284 	uint32_t t;
285 
286 	if (!cfg->force_link)
287 		return (AR8X16_PORT_STS_LINK_AUTO);
288 
289 	t = AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC;
290 	t |= cfg->duplex ? AR8X16_PORT_STS_DUPLEX : 0;
291 	t |= cfg->rxpause ? AR8X16_PORT_STS_RXFLOW : 0;
292 	t |= cfg->txpause ? AR8X16_PORT_STS_TXFLOW : 0;
293 
294 	switch (cfg->speed) {
295 	case AR8327_PORT_SPEED_10:
296 		t |= AR8X16_PORT_STS_SPEED_10;
297 		break;
298 	case AR8327_PORT_SPEED_100:
299 		t |= AR8X16_PORT_STS_SPEED_100;
300 		break;
301 	case AR8327_PORT_SPEED_1000:
302 		t |= AR8X16_PORT_STS_SPEED_1000;
303 		break;
304 	}
305 
306 	return (t);
307 }
308 
309 /*
310  * Fetch the port data for the given port.
311  *
312  * This goes and does dirty things with the hints space
313  * to determine what the configuration parameters should be.
314  *
315  * Returns 1 if the structure was successfully parsed and
316  * the contents are valid; 0 otherwise.
317  */
318 static int
319 ar8327_fetch_pdata_port(struct arswitch_softc *sc,
320     struct ar8327_port_cfg *pcfg,
321     int port)
322 {
323 	int val;
324 	char sbuf[128];
325 
326 	/* Check if force_link exists */
327 	val = 0;
328 	snprintf(sbuf, 128, "port.%d.force_link", port);
329 	(void) resource_int_value(device_get_name(sc->sc_dev),
330 	    device_get_unit(sc->sc_dev),
331 	    sbuf, &val);
332 	if (val != 1)
333 		return (0);
334 	pcfg->force_link = 1;
335 
336 	/* force_link is set; let's parse the rest of the fields */
337 	snprintf(sbuf, 128, "port.%d.speed", port);
338 	if (resource_int_value(device_get_name(sc->sc_dev),
339 	    device_get_unit(sc->sc_dev),
340 	    sbuf, &val) == 0) {
341 		switch (val) {
342 		case 10:
343 			pcfg->speed = AR8327_PORT_SPEED_10;
344 			break;
345 		case 100:
346 			pcfg->speed = AR8327_PORT_SPEED_100;
347 			break;
348 		case 1000:
349 			pcfg->speed = AR8327_PORT_SPEED_1000;
350 			break;
351 		default:
352 			device_printf(sc->sc_dev,
353 			    "%s: invalid port %d duplex value (%d)\n",
354 			    __func__,
355 			    port,
356 			    val);
357 			return (0);
358 		}
359 	}
360 
361 	snprintf(sbuf, 128, "port.%d.duplex", port);
362 	if (resource_int_value(device_get_name(sc->sc_dev),
363 	    device_get_unit(sc->sc_dev),
364 	    sbuf, &val) == 0)
365 		pcfg->duplex = val;
366 
367 	snprintf(sbuf, 128, "port.%d.txpause", port);
368 	if (resource_int_value(device_get_name(sc->sc_dev),
369 	    device_get_unit(sc->sc_dev),
370 	    sbuf, &val) == 0)
371 		pcfg->txpause = val;
372 
373 	snprintf(sbuf, 128, "port.%d.rxpause", port);
374 	if (resource_int_value(device_get_name(sc->sc_dev),
375 	    device_get_unit(sc->sc_dev),
376 	    sbuf, &val) == 0)
377 		pcfg->rxpause = val;
378 
379 #if 1
380 	device_printf(sc->sc_dev,
381 	    "%s: port %d: speed=%d, duplex=%d, txpause=%d, rxpause=%d\n",
382 	    __func__,
383 	    port,
384 	    pcfg->speed,
385 	    pcfg->duplex,
386 	    pcfg->txpause,
387 	    pcfg->rxpause);
388 #endif
389 
390 	return (1);
391 }
392 
393 /*
394  * Parse the pad configuration from the boot hints.
395  *
396  * The (mostly optional) fields are:
397  *
398  * uint32_t mode;
399  * uint32_t rxclk_sel;
400  * uint32_t txclk_sel;
401  * uint32_t txclk_delay_sel;
402  * uint32_t rxclk_delay_sel;
403  * uint32_t txclk_delay_en;
404  * uint32_t rxclk_delay_en;
405  * uint32_t sgmii_delay_en;
406  * uint32_t pipe_rxclk_sel;
407  *
408  * If mode isn't in the hints, 0 is returned.
409  * Else the structure is fleshed out and 1 is returned.
410  */
411 static int
412 ar8327_fetch_pdata_pad(struct arswitch_softc *sc,
413     struct ar8327_pad_cfg *pc,
414     int pad)
415 {
416 	int val;
417 	char sbuf[128];
418 
419 	/* Check if mode exists */
420 	val = 0;
421 	snprintf(sbuf, 128, "pad.%d.mode", pad);
422 	if (resource_int_value(device_get_name(sc->sc_dev),
423 	    device_get_unit(sc->sc_dev),
424 	    sbuf, &val) != 0)
425 		return (0);
426 
427 	/* assume that 'mode' exists and was found */
428 	pc->mode = val;
429 
430 	snprintf(sbuf, 128, "pad.%d.rxclk_sel", pad);
431 	if (resource_int_value(device_get_name(sc->sc_dev),
432 	    device_get_unit(sc->sc_dev),
433 	    sbuf, &val) == 0)
434 		pc->rxclk_sel = val;
435 
436 	snprintf(sbuf, 128, "pad.%d.txclk_sel", pad);
437 	if (resource_int_value(device_get_name(sc->sc_dev),
438 	    device_get_unit(sc->sc_dev),
439 	    sbuf, &val) == 0)
440 		pc->txclk_sel = val;
441 
442 	snprintf(sbuf, 128, "pad.%d.txclk_delay_sel", pad);
443 	if (resource_int_value(device_get_name(sc->sc_dev),
444 	    device_get_unit(sc->sc_dev),
445 	    sbuf, &val) == 0)
446 		pc->txclk_delay_sel = val;
447 
448 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_sel", pad);
449 	if (resource_int_value(device_get_name(sc->sc_dev),
450 	    device_get_unit(sc->sc_dev),
451 	    sbuf, &val) == 0)
452 		pc->rxclk_delay_sel = val;
453 
454 	snprintf(sbuf, 128, "pad.%d.txclk_delay_en", pad);
455 	if (resource_int_value(device_get_name(sc->sc_dev),
456 	    device_get_unit(sc->sc_dev),
457 	    sbuf, &val) == 0)
458 		pc->txclk_delay_en = val;
459 
460 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_en", pad);
461 	if (resource_int_value(device_get_name(sc->sc_dev),
462 	    device_get_unit(sc->sc_dev),
463 	    sbuf, &val) == 0)
464 		pc->rxclk_delay_en = val;
465 
466 	snprintf(sbuf, 128, "pad.%d.sgmii_delay_en", pad);
467 	if (resource_int_value(device_get_name(sc->sc_dev),
468 	    device_get_unit(sc->sc_dev),
469 	    sbuf, &val) == 0)
470 		pc->sgmii_delay_en = val;
471 
472 	snprintf(sbuf, 128, "pad.%d.pipe_rxclk_sel", pad);
473 	if (resource_int_value(device_get_name(sc->sc_dev),
474 	    device_get_unit(sc->sc_dev),
475 	    sbuf, &val) == 0)
476 		pc->pipe_rxclk_sel = val;
477 
478 	if (bootverbose) {
479 		device_printf(sc->sc_dev,
480 		    "%s: pad %d: mode=%d, rxclk_sel=%d, txclk_sel=%d, "
481 		    "txclk_delay_sel=%d, rxclk_delay_sel=%d, txclk_delay_en=%d, "
482 		    "rxclk_enable_en=%d, sgmii_delay_en=%d, pipe_rxclk_sel=%d\n",
483 		    __func__,
484 		    pad,
485 		    pc->mode,
486 		    pc->rxclk_sel,
487 		    pc->txclk_sel,
488 		    pc->txclk_delay_sel,
489 		    pc->rxclk_delay_sel,
490 		    pc->txclk_delay_en,
491 		    pc->rxclk_delay_en,
492 		    pc->sgmii_delay_en,
493 		    pc->pipe_rxclk_sel);
494 	}
495 
496 	return (1);
497 }
498 
499 /*
500  * Fetch the SGMII configuration block from the boot hints.
501  */
502 static int
503 ar8327_fetch_pdata_sgmii(struct arswitch_softc *sc,
504     struct ar8327_sgmii_cfg *scfg)
505 {
506 	int val;
507 
508 	/* sgmii_ctrl */
509 	val = 0;
510 	if (resource_int_value(device_get_name(sc->sc_dev),
511 	    device_get_unit(sc->sc_dev),
512 	    "sgmii.ctrl", &val) != 0)
513 		return (0);
514 	scfg->sgmii_ctrl = val;
515 
516 	/* serdes_aen */
517 	val = 0;
518 	if (resource_int_value(device_get_name(sc->sc_dev),
519 	    device_get_unit(sc->sc_dev),
520 	    "sgmii.serdes_aen", &val) != 0)
521 		return (0);
522 	scfg->serdes_aen = val;
523 
524 	return (1);
525 }
526 
527 /*
528  * Fetch the LED configuration from the boot hints.
529  */
530 static int
531 ar8327_fetch_pdata_led(struct arswitch_softc *sc,
532     struct ar8327_led_cfg *lcfg)
533 {
534 	int val;
535 
536 	val = 0;
537 	if (resource_int_value(device_get_name(sc->sc_dev),
538 	    device_get_unit(sc->sc_dev),
539 	    "led.ctrl0", &val) != 0)
540 		return (0);
541 	lcfg->led_ctrl0 = val;
542 
543 	val = 0;
544 	if (resource_int_value(device_get_name(sc->sc_dev),
545 	    device_get_unit(sc->sc_dev),
546 	    "led.ctrl1", &val) != 0)
547 		return (0);
548 	lcfg->led_ctrl1 = val;
549 
550 	val = 0;
551 	if (resource_int_value(device_get_name(sc->sc_dev),
552 	    device_get_unit(sc->sc_dev),
553 	    "led.ctrl2", &val) != 0)
554 		return (0);
555 	lcfg->led_ctrl2 = val;
556 
557 	val = 0;
558 	if (resource_int_value(device_get_name(sc->sc_dev),
559 	    device_get_unit(sc->sc_dev),
560 	    "led.ctrl3", &val) != 0)
561 		return (0);
562 	lcfg->led_ctrl3 = val;
563 
564 	val = 0;
565 	if (resource_int_value(device_get_name(sc->sc_dev),
566 	    device_get_unit(sc->sc_dev),
567 	    "led.open_drain", &val) != 0)
568 		return (0);
569 	lcfg->open_drain = val;
570 
571 	return (1);
572 }
573 
574 /*
575  * Initialise the ar8327 specific hardware features from
576  * the hints provided in the boot environment.
577  */
578 static int
579 ar8327_init_pdata(struct arswitch_softc *sc)
580 {
581 	struct ar8327_pad_cfg pc;
582 	struct ar8327_port_cfg port_cfg;
583 	struct ar8327_sgmii_cfg scfg;
584 	struct ar8327_led_cfg lcfg;
585 	uint32_t t, new_pos, pos;
586 
587 	/* Port 0 */
588 	bzero(&port_cfg, sizeof(port_cfg));
589 	sc->ar8327.port0_status = 0;
590 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 0))
591 		sc->ar8327.port0_status = ar8327_get_port_init_status(&port_cfg);
592 
593 	/* Port 6 */
594 	bzero(&port_cfg, sizeof(port_cfg));
595 	sc->ar8327.port6_status = 0;
596 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 6))
597 		sc->ar8327.port6_status = ar8327_get_port_init_status(&port_cfg);
598 
599 	/* Pad 0 */
600 	bzero(&pc, sizeof(pc));
601 	t = 0;
602 	if (ar8327_fetch_pdata_pad(sc, &pc, 0))
603 		t = ar8327_get_pad_cfg(&pc);
604 #if 0
605 		if (AR8X16_IS_SWITCH(sc, AR8337))
606 			t |= AR8337_PAD_MAC06_EXCHANGE_EN;
607 #endif
608 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD0_MODE, t);
609 
610 	/* Pad 5 */
611 	bzero(&pc, sizeof(pc));
612 	t = 0;
613 	if (ar8327_fetch_pdata_pad(sc, &pc, 5))
614 		t = ar8327_get_pad_cfg(&pc);
615 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD5_MODE, t);
616 
617 	/* Pad 6 */
618 	bzero(&pc, sizeof(pc));
619 	t = 0;
620 	if (ar8327_fetch_pdata_pad(sc, &pc, 6))
621 		t = ar8327_get_pad_cfg(&pc);
622 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD6_MODE, t);
623 
624 	pos = arswitch_readreg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP);
625 	new_pos = pos;
626 
627 	/* XXX LED config */
628 	bzero(&lcfg, sizeof(lcfg));
629 	if (ar8327_fetch_pdata_led(sc, &lcfg)) {
630 		if (lcfg.open_drain)
631 			new_pos |= AR8327_POWER_ON_STRIP_LED_OPEN_EN;
632 		else
633 			new_pos &= ~AR8327_POWER_ON_STRIP_LED_OPEN_EN;
634 
635 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL0,
636 		    lcfg.led_ctrl0);
637 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL1,
638 		    lcfg.led_ctrl1);
639 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL2,
640 		    lcfg.led_ctrl2);
641 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL3,
642 		    lcfg.led_ctrl3);
643 
644 		if (new_pos != pos)
645 			new_pos |= AR8327_POWER_ON_STRIP_POWER_ON_SEL;
646 	}
647 
648 	/* SGMII config */
649 	bzero(&scfg, sizeof(scfg));
650 	if (ar8327_fetch_pdata_sgmii(sc, &scfg)) {
651 		device_printf(sc->sc_dev, "%s: SGMII cfg?\n", __func__);
652 		t = scfg.sgmii_ctrl;
653 		if (sc->chip_rev == 1)
654 			t |= AR8327_SGMII_CTRL_EN_PLL |
655 			    AR8327_SGMII_CTRL_EN_RX |
656 			    AR8327_SGMII_CTRL_EN_TX;
657 		else
658 			t &= ~(AR8327_SGMII_CTRL_EN_PLL |
659 			    AR8327_SGMII_CTRL_EN_RX |
660 			    AR8327_SGMII_CTRL_EN_TX);
661 
662 		arswitch_writereg(sc->sc_dev, AR8327_REG_SGMII_CTRL, t);
663 
664 		if (scfg.serdes_aen)
665 			new_pos &= ~AR8327_POWER_ON_STRIP_SERDES_AEN;
666 		else
667 			new_pos |= AR8327_POWER_ON_STRIP_SERDES_AEN;
668 	}
669 
670 	arswitch_writereg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP, new_pos);
671 
672 	return (0);
673 }
674 
675 static int
676 ar8327_hw_setup(struct arswitch_softc *sc)
677 {
678 	int i;
679 	int err;
680 
681 	/* pdata fetch and setup */
682 	err = ar8327_init_pdata(sc);
683 	if (err != 0)
684 		return (err);
685 
686 	/* XXX init leds */
687 
688 	for (i = 0; i < AR8327_NUM_PHYS; i++) {
689 		/* phy fixup */
690 		ar8327_phy_fixup(sc, i);
691 
692 		/* start PHY autonegotiation? */
693 		/* XXX is this done as part of the normal PHY setup? */
694 
695 	}
696 
697 	/* Let things settle */
698 	DELAY(1000);
699 
700 	return (0);
701 }
702 
703 /*
704  * Initialise other global values, for the AR8327.
705  */
706 static int
707 ar8327_hw_global_setup(struct arswitch_softc *sc)
708 {
709 	uint32_t t;
710 
711 	/* enable CPU port and disable mirror port */
712 	t = AR8327_FWD_CTRL0_CPU_PORT_EN |
713 	    AR8327_FWD_CTRL0_MIRROR_PORT;
714 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t);
715 
716 	/* forward multicast and broadcast frames to CPU */
717 	t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
718 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) |
719 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
720 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t);
721 
722 	/* enable jumbo frames */
723 	/* XXX need to macro-shift the value! */
724 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE,
725 	    AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2);
726 
727 	/* Enable MIB counters */
728 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN,
729 	    AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB);
730 
731 	/* Disable EEE on all ports due to stability issues */
732 	t = arswitch_readreg(sc->sc_dev, AR8327_REG_EEE_CTRL);
733 	t |= AR8327_EEE_CTRL_DISABLE_PHY(0) |
734 	    AR8327_EEE_CTRL_DISABLE_PHY(1) |
735 	    AR8327_EEE_CTRL_DISABLE_PHY(2) |
736 	    AR8327_EEE_CTRL_DISABLE_PHY(3) |
737 	    AR8327_EEE_CTRL_DISABLE_PHY(4);
738 	arswitch_writereg(sc->sc_dev, AR8327_REG_EEE_CTRL, t);
739 
740 	/* Set the right number of ports */
741 	/* GMAC0 (CPU), GMAC1..5 (PHYs), GMAC6 (CPU) */
742 	sc->info.es_nports = 7;
743 
744 	return (0);
745 }
746 
747 /*
748  * Port setup.  Called at attach time.
749  */
750 static void
751 ar8327_port_init(struct arswitch_softc *sc, int port)
752 {
753 	uint32_t t;
754 	int ports;
755 
756 	/* For now, port can see all other ports */
757 	ports = 0x7f;
758 
759 	if (port == AR8X16_PORT_CPU)
760 		t = sc->ar8327.port0_status;
761 	else if (port == 6)
762 		t = sc->ar8327.port6_status;
763         else
764 		t = AR8X16_PORT_STS_LINK_AUTO;
765 
766 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t);
767 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0);
768 
769 	/*
770 	 * Default to 1 port group.
771 	 */
772 	t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
773 	t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
774 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);
775 
776 	t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
777 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t);
778 
779 	/*
780 	 * This doesn't configure any ports which this port can "see".
781 	 * bits 0-6 control which ports a frame coming into this port
782 	 * can be sent out to.
783 	 *
784 	 * So by doing this, we're making it impossible to send frames out
785 	 * to that port.
786 	 */
787 	t = AR8327_PORT_LOOKUP_LEARN;
788 	t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
789 
790 	/* So this allows traffic to any port except ourselves */
791 	t |= (ports & ~(1 << port));
792 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t);
793 }
794 
795 static int
796 ar8327_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
797 {
798 
799 	/* Check: ADDTAG/STRIPTAG - exclusive */
800 
801 	ARSWITCH_LOCK(sc);
802 
803 	/* Set the PVID. */
804 	if (p->es_pvid != 0)
805 		sc->hal.arswitch_vlan_set_pvid(sc, p->es_port, p->es_pvid);
806 
807 	/*
808 	 * DOUBLE_TAG
809 	 * VLAN_MODE_ADD
810 	 * VLAN_MODE_STRIP
811 	 */
812 	ARSWITCH_UNLOCK(sc);
813 	return (0);
814 }
815 
816 /*
817  * Get the port VLAN configuration.
818  */
819 static int
820 ar8327_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
821 {
822 
823 	ARSWITCH_LOCK(sc);
824 
825 	/* Retrieve the PVID */
826 	sc->hal.arswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
827 
828 	/* Retrieve the current port configuration from the VTU */
829 	/*
830 	 * DOUBLE_TAG
831 	 * VLAN_MODE_ADD
832 	 * VLAN_MODE_STRIP
833 	 */
834 
835 	ARSWITCH_UNLOCK(sc);
836 	return (0);
837 }
838 
839 static void
840 ar8327_port_disable_mirror(struct arswitch_softc *sc, int port)
841 {
842 
843 	arswitch_modifyreg(sc->sc_dev,
844 	    AR8327_REG_PORT_LOOKUP(port),
845 	    AR8327_PORT_LOOKUP_ING_MIRROR_EN,
846 	    0);
847 	arswitch_modifyreg(sc->sc_dev,
848 	    AR8327_REG_PORT_HOL_CTRL1(port),
849 	    AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN,
850 	    0);
851 }
852 
853 static void
854 ar8327_reset_vlans(struct arswitch_softc *sc)
855 {
856 	int i;
857 	uint32_t t;
858 	int ports;
859 
860 	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
861 	ARSWITCH_LOCK(sc);
862 
863 	/* Clear the existing VLAN configuration */
864 	memset(sc->vid, 0, sizeof(sc->vid));
865 
866 	/*
867 	 * Disable mirroring.
868 	 */
869 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0,
870 	    AR8327_FWD_CTRL0_MIRROR_PORT,
871 	    (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S));
872 
873 	/*
874 	 * XXX TODO: disable any Q-in-Q port configuration,
875 	 * tagging, egress filters, etc.
876 	 */
877 
878 	/*
879 	 * For now, let's default to one portgroup, just so traffic
880 	 * flows.  All ports can see other ports. There are two CPU GMACs
881 	 * (GMAC0, GMAC6), GMAC1..GMAC5 are external PHYs.
882 	 *
883 	 * (ETHERSWITCH_VLAN_PORT)
884 	 */
885 	ports = 0x7f;
886 
887 	/*
888 	 * XXX TODO: set things up correctly for vlans!
889 	 */
890 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
891 		int egress, ingress;
892 
893 		if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) {
894 			sc->vid[i] = i | ETHERSWITCH_VID_VALID;
895 			/* set egress == out_keep */
896 			ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY;
897 			/* in_port_only, forward */
898 			egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
899 		} else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
900 			ingress = AR8X16_PORT_VLAN_MODE_SECURE;
901 			egress = AR8327_PORT_VLAN1_OUT_MODE_UNMOD;
902 		} else {
903 			/* set egress == out_keep */
904 			ingress = AR8X16_PORT_VLAN_MODE_PORT_ONLY;
905 			/* in_port_only, forward */
906 			egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
907 		}
908 
909 		/* set pvid = 1; there's only one vlangroup to start with */
910 		t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
911 		t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
912 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);
913 
914 		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
915 		t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S;
916 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);
917 
918 		/* Ports can see other ports */
919 		/* XXX not entirely true for dot1q? */
920 		t = (ports & ~(1 << i));	/* all ports besides us */
921 		t |= AR8327_PORT_LOOKUP_LEARN;
922 
923 		t |= ingress << AR8327_PORT_LOOKUP_IN_MODE_S;
924 		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
925 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);
926 	}
927 
928 	/*
929 	 * Disable port mirroring entirely.
930 	 */
931 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
932 		ar8327_port_disable_mirror(sc, i);
933 	}
934 
935 	/*
936 	 * If dot1q - set pvid; dot1q, etc.
937 	 */
938 	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
939 		sc->vid[0] = 1;
940 		for (i = 0; i < AR8327_NUM_PORTS; i++) {
941 			/* Each port - pvid 1 */
942 			sc->hal.arswitch_vlan_set_pvid(sc, i, sc->vid[0]);
943 		}
944 		/* Initialise vlan1 - all ports, untagged */
945 		sc->hal.arswitch_set_dot1q_vlan(sc, ports, ports, sc->vid[0]);
946 		sc->vid[0] |= ETHERSWITCH_VID_VALID;
947 	}
948 
949 	ARSWITCH_UNLOCK(sc);
950 }
951 
952 static int
953 ar8327_vlan_get_port(struct arswitch_softc *sc, uint32_t *ports, int vid)
954 {
955 	int port;
956 	uint32_t reg;
957 
958 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
959 
960 	/* For port based vlans the vlanid is the same as the port index. */
961 	port = vid & ETHERSWITCH_VID_MASK;
962 	reg = arswitch_readreg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port));
963 	*ports = reg & 0x7f;
964 	return (0);
965 }
966 
967 static int
968 ar8327_vlan_set_port(struct arswitch_softc *sc, uint32_t ports, int vid)
969 {
970 	int err, port;
971 
972 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
973 
974 	/* For port based vlans the vlanid is the same as the port index. */
975 	port = vid & ETHERSWITCH_VID_MASK;
976 
977 	err = arswitch_modifyreg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port),
978 	    0x7f, /* vlan membership mask */
979 	    (ports & 0x7f));
980 
981 	if (err)
982 		return (err);
983 	return (0);
984 }
985 
986 static int
987 ar8327_vlan_getvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
988 {
989 
990 	return (ar8xxx_getvgroup(sc, vg));
991 }
992 
993 static int
994 ar8327_vlan_setvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
995 {
996 
997 	return (ar8xxx_setvgroup(sc, vg));
998 }
999 
1000 static int
1001 ar8327_get_pvid(struct arswitch_softc *sc, int port, int *pvid)
1002 {
1003 	uint32_t reg;
1004 
1005 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
1006 
1007 	/*
1008 	 * XXX for now, assuming it's CVID; likely very wrong!
1009 	 */
1010 	port = port & ETHERSWITCH_VID_MASK;
1011 	reg = arswitch_readreg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port));
1012 	reg = reg >> AR8327_PORT_VLAN0_DEF_CVID_S;
1013 	reg = reg & 0xfff;
1014 
1015 	*pvid = reg;
1016 	return (0);
1017 }
1018 
1019 static int
1020 ar8327_set_pvid(struct arswitch_softc *sc, int port, int pvid)
1021 {
1022 	uint32_t t;
1023 
1024 	/* Limit pvid to valid values */
1025 	pvid &= 0x7f;
1026 
1027 	t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S;
1028 	t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S;
1029 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);
1030 
1031 	return (0);
1032 }
1033 
1034 static int
1035 ar8327_atu_flush(struct arswitch_softc *sc)
1036 {
1037 
1038 	int ret;
1039 
1040 	ret = arswitch_waitreg(sc->sc_dev,
1041 	    AR8327_REG_ATU_FUNC,
1042 	    AR8327_ATU_FUNC_BUSY,
1043 	    0,
1044 	    1000);
1045 
1046 	if (ret)
1047 		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
1048 
1049 	if (!ret)
1050 		arswitch_writereg(sc->sc_dev,
1051 		    AR8327_REG_ATU_FUNC,
1052 		    AR8327_ATU_FUNC_OP_FLUSH);
1053 	return (ret);
1054 }
1055 
1056 static int
1057 ar8327_flush_dot1q_vlan(struct arswitch_softc *sc)
1058 {
1059 
1060 	return (ar8327_vlan_op(sc, AR8327_VTU_FUNC1_OP_FLUSH, 0, 0));
1061 }
1062 
1063 static int
1064 ar8327_purge_dot1q_vlan(struct arswitch_softc *sc, int vid)
1065 {
1066 
1067 	return (ar8327_vlan_op(sc, AR8327_VTU_FUNC1_OP_PURGE, vid, 0));
1068 }
1069 
1070 static int
1071 ar8327_get_dot1q_vlan(struct arswitch_softc *sc, uint32_t *ports,
1072     uint32_t *untagged_ports, int vid)
1073 {
1074 	int i, r;
1075 	uint32_t op, reg, val;
1076 
1077 	op = AR8327_VTU_FUNC1_OP_GET_ONE;
1078 
1079 	/* Filter out the vid flags; only grab the VLAN ID */
1080 	vid &= 0xfff;
1081 
1082 	/* XXX TODO: the VTU here stores egress mode - keep, tag, untagged, none */
1083 	r = ar8327_vlan_op(sc, op, vid, 0);
1084 	if (r != 0) {
1085 		device_printf(sc->sc_dev, "%s: %d: op failed\n", __func__, vid);
1086 	}
1087 
1088 	reg = arswitch_readreg(sc->sc_dev, AR8327_REG_VTU_FUNC0);
1089 	DPRINTF(sc, ARSWITCH_DBG_REGIO, "%s: %d: reg=0x%08x\n", __func__, vid, reg);
1090 
1091 	/*
1092 	 * If any of the bits are set, update the port mask.
1093 	 * Worry about the port config itself when getport() is called.
1094 	 */
1095 	*ports = 0;
1096 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
1097 		val = reg >> AR8327_VTU_FUNC0_EG_MODE_S(i);
1098 		val = val & 0x3;
1099 		/* XXX KEEP (unmodified?) */
1100 		if (val == AR8327_VTU_FUNC0_EG_MODE_TAG) {
1101 			*ports |= (1 << i);
1102 		} else if (val == AR8327_VTU_FUNC0_EG_MODE_UNTAG) {
1103 			*ports |= (1 << i);
1104 			*untagged_ports |= (1 << i);
1105 		}
1106 	}
1107 
1108 	return (0);
1109 }
1110 
1111 static int
1112 ar8327_set_dot1q_vlan(struct arswitch_softc *sc, uint32_t ports,
1113     uint32_t untagged_ports, int vid)
1114 {
1115 	int i;
1116 	uint32_t op, val, mode;
1117 
1118 	op = AR8327_VTU_FUNC1_OP_LOAD;
1119 	vid &= 0xfff;
1120 
1121 	DPRINTF(sc, ARSWITCH_DBG_VLAN,
1122 	    "%s: vid: %d, ports=0x%08x, untagged_ports=0x%08x\n",
1123 	    __func__,
1124 	    vid,
1125 	    ports,
1126 	    untagged_ports);
1127 
1128 	/*
1129 	 * Mark it as valid; and that it should use per-VLAN MAC table,
1130 	 * not VID=0 when doing MAC lookups
1131 	 */
1132 	val = AR8327_VTU_FUNC0_VALID | AR8327_VTU_FUNC0_IVL;
1133 
1134 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
1135 		if ((ports & BIT(i)) == 0)
1136 			mode = AR8327_VTU_FUNC0_EG_MODE_NOT;
1137 		else if (untagged_ports & BIT(i))
1138 			mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG;
1139 		else
1140 			mode = AR8327_VTU_FUNC0_EG_MODE_TAG;
1141 
1142 		val |= mode << AR8327_VTU_FUNC0_EG_MODE_S(i);
1143 	}
1144 
1145 	return (ar8327_vlan_op(sc, op, vid, val));
1146 }
1147 
1148 void
1149 ar8327_attach(struct arswitch_softc *sc)
1150 {
1151 
1152 	sc->hal.arswitch_hw_setup = ar8327_hw_setup;
1153 	sc->hal.arswitch_hw_global_setup = ar8327_hw_global_setup;
1154 
1155 	sc->hal.arswitch_port_init = ar8327_port_init;
1156 
1157 	sc->hal.arswitch_vlan_getvgroup = ar8327_vlan_getvgroup;
1158 	sc->hal.arswitch_vlan_setvgroup = ar8327_vlan_setvgroup;
1159 	sc->hal.arswitch_port_vlan_setup = ar8327_port_vlan_setup;
1160 	sc->hal.arswitch_port_vlan_get = ar8327_port_vlan_get;
1161 	sc->hal.arswitch_flush_dot1q_vlan = ar8327_flush_dot1q_vlan;
1162 	sc->hal.arswitch_purge_dot1q_vlan = ar8327_purge_dot1q_vlan;
1163 	sc->hal.arswitch_set_dot1q_vlan = ar8327_set_dot1q_vlan;
1164 	sc->hal.arswitch_get_dot1q_vlan = ar8327_get_dot1q_vlan;
1165 
1166 	sc->hal.arswitch_vlan_init_hw = ar8327_reset_vlans;
1167 	sc->hal.arswitch_vlan_get_pvid = ar8327_get_pvid;
1168 	sc->hal.arswitch_vlan_set_pvid = ar8327_set_pvid;
1169 
1170 	sc->hal.arswitch_get_port_vlan = ar8327_vlan_get_port;
1171 	sc->hal.arswitch_set_port_vlan = ar8327_vlan_set_port;
1172 
1173 	sc->hal.arswitch_atu_flush = ar8327_atu_flush;
1174 
1175 	/*
1176 	 * Reading the PHY via the MDIO interface currently doesn't
1177 	 * work correctly.
1178 	 *
1179 	 * So for now, just go direct to the PHY registers themselves.
1180 	 * This has always worked  on external devices, but not internal
1181 	 * devices (AR934x, AR724x, AR933x.)
1182 	 */
1183 	sc->hal.arswitch_phy_read = arswitch_readphy_external;
1184 	sc->hal.arswitch_phy_write = arswitch_writephy_external;
1185 
1186 	/* Set the switch vlan capabilities. */
1187 	sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q |
1188 	    ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG;
1189 	sc->info.es_nvlangroups = AR8X16_MAX_VLANS;
1190 }
1191