xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch_8327.c (revision 7431dfd4580e850375fe5478d92ec770344db098)
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/etherswitch/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_8327.h>
61 
62 #include "mdio_if.h"
63 #include "miibus_if.h"
64 #include "etherswitch_if.h"
65 
66 static void
67 ar8327_phy_fixup(struct arswitch_softc *sc, int phy)
68 {
69 
70 	switch (sc->chip_rev) {
71 	case 1:
72 		/* For 100M waveform */
73 		arswitch_writedbg(sc->sc_dev, phy, 0, 0x02ea);
74 		/* Turn on Gigabit clock */
75 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x68a0);
76 		break;
77 
78 	case 2:
79 		arswitch_writemmd(sc->sc_dev, phy, 0x7, 0x3c);
80 		arswitch_writemmd(sc->sc_dev, phy, 0x4007, 0x0);
81 		/* fallthrough */
82 	case 4:
83 		arswitch_writemmd(sc->sc_dev, phy, 0x3, 0x800d);
84 		arswitch_writemmd(sc->sc_dev, phy, 0x4003, 0x803f);
85 
86 		arswitch_writedbg(sc->sc_dev, phy, 0x3d, 0x6860);
87 		arswitch_writedbg(sc->sc_dev, phy, 0x5, 0x2c46);
88 		arswitch_writedbg(sc->sc_dev, phy, 0x3c, 0x6000);
89 		break;
90 	}
91 }
92 
93 static uint32_t
94 ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
95 {
96 	uint32_t t;
97 
98 	if (!cfg)
99 		return (0);
100 
101 	t = 0;
102 	switch (cfg->mode) {
103 	case AR8327_PAD_NC:
104 		break;
105 
106 	case AR8327_PAD_MAC2MAC_MII:
107 		t = AR8327_PAD_MAC_MII_EN;
108 		if (cfg->rxclk_sel)
109 			t |= AR8327_PAD_MAC_MII_RXCLK_SEL;
110 		if (cfg->txclk_sel)
111 			t |= AR8327_PAD_MAC_MII_TXCLK_SEL;
112 		break;
113 
114 	case AR8327_PAD_MAC2MAC_GMII:
115 		t = AR8327_PAD_MAC_GMII_EN;
116 		if (cfg->rxclk_sel)
117 			t |= AR8327_PAD_MAC_GMII_RXCLK_SEL;
118 		if (cfg->txclk_sel)
119 			t |= AR8327_PAD_MAC_GMII_TXCLK_SEL;
120 		break;
121 
122 	case AR8327_PAD_MAC_SGMII:
123 		t = AR8327_PAD_SGMII_EN;
124 
125 		/*
126 		 * WAR for the Qualcomm Atheros AP136 board.
127 		 * It seems that RGMII TX/RX delay settings needs to be
128 		 * applied for SGMII mode as well, The ethernet is not
129 		 * reliable without this.
130 		 */
131 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
132 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
133 		if (cfg->rxclk_delay_en)
134 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
135 		if (cfg->txclk_delay_en)
136 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
137 
138 		if (cfg->sgmii_delay_en)
139 			t |= AR8327_PAD_SGMII_DELAY_EN;
140 
141 		break;
142 
143 	case AR8327_PAD_MAC2PHY_MII:
144 		t = AR8327_PAD_PHY_MII_EN;
145 		if (cfg->rxclk_sel)
146 			t |= AR8327_PAD_PHY_MII_RXCLK_SEL;
147 		if (cfg->txclk_sel)
148 			t |= AR8327_PAD_PHY_MII_TXCLK_SEL;
149 		break;
150 
151 	case AR8327_PAD_MAC2PHY_GMII:
152 		t = AR8327_PAD_PHY_GMII_EN;
153 		if (cfg->pipe_rxclk_sel)
154 			t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL;
155 		if (cfg->rxclk_sel)
156 			t |= AR8327_PAD_PHY_GMII_RXCLK_SEL;
157 		if (cfg->txclk_sel)
158 			t |= AR8327_PAD_PHY_GMII_TXCLK_SEL;
159 		break;
160 
161 	case AR8327_PAD_MAC_RGMII:
162 		t = AR8327_PAD_RGMII_EN;
163 		t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S;
164 		t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S;
165 		if (cfg->rxclk_delay_en)
166 			t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN;
167 		if (cfg->txclk_delay_en)
168 			t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN;
169 		break;
170 
171 	case AR8327_PAD_PHY_GMII:
172 		t = AR8327_PAD_PHYX_GMII_EN;
173 		break;
174 
175 	case AR8327_PAD_PHY_RGMII:
176 		t = AR8327_PAD_PHYX_RGMII_EN;
177 		break;
178 
179 	case AR8327_PAD_PHY_MII:
180 		t = AR8327_PAD_PHYX_MII_EN;
181 		break;
182 	}
183 
184 	return (t);
185 }
186 
187 /*
188  * Map the hard-coded port config from the switch setup to
189  * the chipset port config (status, duplex, flow, etc.)
190  */
191 static uint32_t
192 ar8327_get_port_init_status(struct ar8327_port_cfg *cfg)
193 {
194 	uint32_t t;
195 
196 	if (!cfg->force_link)
197 		return (AR8X16_PORT_STS_LINK_AUTO);
198 
199 	t = AR8X16_PORT_STS_TXMAC | AR8X16_PORT_STS_RXMAC;
200 	t |= cfg->duplex ? AR8X16_PORT_STS_DUPLEX : 0;
201 	t |= cfg->rxpause ? AR8X16_PORT_STS_RXFLOW : 0;
202 	t |= cfg->txpause ? AR8X16_PORT_STS_TXFLOW : 0;
203 
204 	switch (cfg->speed) {
205 	case AR8327_PORT_SPEED_10:
206 		t |= AR8X16_PORT_STS_SPEED_10;
207 		break;
208 	case AR8327_PORT_SPEED_100:
209 		t |= AR8X16_PORT_STS_SPEED_100;
210 		break;
211 	case AR8327_PORT_SPEED_1000:
212 		t |= AR8X16_PORT_STS_SPEED_1000;
213 		break;
214 	}
215 
216 	return (t);
217 }
218 
219 /*
220  * Fetch the port data for the given port.
221  *
222  * This goes and does dirty things with the hints space
223  * to determine what the configuration parameters should be.
224  *
225  * Returns 1 if the structure was successfully parsed and
226  * the contents are valid; 0 otherwise.
227  */
228 static int
229 ar8327_fetch_pdata_port(struct arswitch_softc *sc,
230     struct ar8327_port_cfg *pcfg,
231     int port)
232 {
233 	int val;
234 	char sbuf[128];
235 
236 	/* Check if force_link exists */
237 	val = 0;
238 	snprintf(sbuf, 128, "port.%d.force_link", port);
239 	(void) resource_int_value(device_get_name(sc->sc_dev),
240 	    device_get_unit(sc->sc_dev),
241 	    sbuf, &val);
242 	if (val != 1)
243 		return (0);
244 	pcfg->force_link = 1;
245 
246 	/* force_link is set; let's parse the rest of the fields */
247 	snprintf(sbuf, 128, "port.%d.speed", port);
248 	if (resource_int_value(device_get_name(sc->sc_dev),
249 	    device_get_unit(sc->sc_dev),
250 	    sbuf, &val) == 0) {
251 		switch (val) {
252 		case 10:
253 			pcfg->speed = AR8327_PORT_SPEED_10;
254 			break;
255 		case 100:
256 			pcfg->speed = AR8327_PORT_SPEED_100;
257 			break;
258 		case 1000:
259 			pcfg->speed = AR8327_PORT_SPEED_1000;
260 			break;
261 		default:
262 			device_printf(sc->sc_dev,
263 			    "%s: invalid port %d duplex value (%d)\n",
264 			    __func__,
265 			    port,
266 			    val);
267 			return (0);
268 		}
269 	}
270 
271 	snprintf(sbuf, 128, "port.%d.duplex", port);
272 	if (resource_int_value(device_get_name(sc->sc_dev),
273 	    device_get_unit(sc->sc_dev),
274 	    sbuf, &val) == 0)
275 		pcfg->duplex = val;
276 
277 	snprintf(sbuf, 128, "port.%d.txpause", port);
278 	if (resource_int_value(device_get_name(sc->sc_dev),
279 	    device_get_unit(sc->sc_dev),
280 	    sbuf, &val) == 0)
281 		pcfg->txpause = val;
282 
283 	snprintf(sbuf, 128, "port.%d.rxpause", port);
284 	if (resource_int_value(device_get_name(sc->sc_dev),
285 	    device_get_unit(sc->sc_dev),
286 	    sbuf, &val) == 0)
287 		pcfg->rxpause = val;
288 
289 #if 0
290 	device_printf(sc->sc_dev,
291 	    "%s: port %d: speed=%d, duplex=%d, txpause=%d, rxpause=%d\n",
292 	    __func__,
293 	    port,
294 	    pcfg->speed,
295 	    pcfg->duplex,
296 	    pcfg->txpause,
297 	    pcfg->rxpause);
298 #endif
299 
300 	return (1);
301 }
302 
303 /*
304  * Parse the pad configuration from the boot hints.
305  *
306  * The (mostly optional) fields are:
307  *
308  * uint32_t mode;
309  * uint32_t rxclk_sel;
310  * uint32_t txclk_sel;
311  * uint32_t txclk_delay_sel;
312  * uint32_t rxclk_delay_sel;
313  * uint32_t txclk_delay_en;
314  * uint32_t rxclk_delay_en;
315  * uint32_t sgmii_delay_en;
316  * uint32_t pipe_rxclk_sel;
317  *
318  * If mode isn't in the hints, 0 is returned.
319  * Else the structure is fleshed out and 1 is returned.
320  */
321 static int
322 ar8327_fetch_pdata_pad(struct arswitch_softc *sc,
323     struct ar8327_pad_cfg *pc,
324     int pad)
325 {
326 	int val;
327 	char sbuf[128];
328 
329 	/* Check if mode exists */
330 	val = 0;
331 	snprintf(sbuf, 128, "pad.%d.mode", pad);
332 	if (resource_int_value(device_get_name(sc->sc_dev),
333 	    device_get_unit(sc->sc_dev),
334 	    sbuf, &val) != 0)
335 		return (0);
336 
337 	/* assume that 'mode' exists and was found */
338 	pc->mode = val;
339 
340 	snprintf(sbuf, 128, "pad.%d.rxclk_sel", pad);
341 	if (resource_int_value(device_get_name(sc->sc_dev),
342 	    device_get_unit(sc->sc_dev),
343 	    sbuf, &val) == 0)
344 		pc->rxclk_sel = val;
345 
346 	snprintf(sbuf, 128, "pad.%d.txclk_sel", pad);
347 	if (resource_int_value(device_get_name(sc->sc_dev),
348 	    device_get_unit(sc->sc_dev),
349 	    sbuf, &val) == 0)
350 		pc->txclk_sel = val;
351 
352 	snprintf(sbuf, 128, "pad.%d.txclk_delay_sel", pad);
353 	if (resource_int_value(device_get_name(sc->sc_dev),
354 	    device_get_unit(sc->sc_dev),
355 	    sbuf, &val) == 0)
356 		pc->txclk_delay_sel = val;
357 
358 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_sel", pad);
359 	if (resource_int_value(device_get_name(sc->sc_dev),
360 	    device_get_unit(sc->sc_dev),
361 	    sbuf, &val) == 0)
362 		pc->rxclk_delay_sel = val;
363 
364 	snprintf(sbuf, 128, "pad.%d.txclk_delay_en", pad);
365 	if (resource_int_value(device_get_name(sc->sc_dev),
366 	    device_get_unit(sc->sc_dev),
367 	    sbuf, &val) == 0)
368 		pc->txclk_delay_en = val;
369 
370 	snprintf(sbuf, 128, "pad.%d.rxclk_delay_en", pad);
371 	if (resource_int_value(device_get_name(sc->sc_dev),
372 	    device_get_unit(sc->sc_dev),
373 	    sbuf, &val) == 0)
374 		pc->rxclk_delay_en = val;
375 
376 	snprintf(sbuf, 128, "pad.%d.sgmii_delay_en", pad);
377 	if (resource_int_value(device_get_name(sc->sc_dev),
378 	    device_get_unit(sc->sc_dev),
379 	    sbuf, &val) == 0)
380 		pc->sgmii_delay_en = val;
381 
382 	snprintf(sbuf, 128, "pad.%d.pipe_rxclk_sel", pad);
383 	if (resource_int_value(device_get_name(sc->sc_dev),
384 	    device_get_unit(sc->sc_dev),
385 	    sbuf, &val) == 0)
386 		pc->pipe_rxclk_sel = val;
387 
388 #if 0
389 	device_printf(sc->sc_dev,
390 	    "%s: pad %d: mode=%d, rxclk_sel=%d, txclk_sel=%d, "
391 	    "txclk_delay_sel=%d, rxclk_delay_sel=%d, txclk_delay_en=%d, "
392 	    "rxclk_enable_en=%d, sgmii_delay_en=%d, pipe_rxclk_sel=%d\n",
393 	    __func__,
394 	    pad,
395 	    pc->mode,
396 	    pc->rxclk_sel,
397 	    pc->txclk_sel,
398 	    pc->txclk_delay_sel,
399 	    pc->rxclk_delay_sel,
400 	    pc->txclk_delay_en,
401 	    pc->rxclk_delay_en,
402 	    pc->sgmii_delay_en,
403 	    pc->pipe_rxclk_sel);
404 #endif
405 
406 	return (1);
407 }
408 
409 /*
410  * Fetch the SGMII configuration block from the boot hints.
411  */
412 static int
413 ar8327_fetch_pdata_sgmii(struct arswitch_softc *sc,
414     struct ar8327_sgmii_cfg *scfg)
415 {
416 	int val;
417 
418 	/* sgmii_ctrl */
419 	val = 0;
420 	if (resource_int_value(device_get_name(sc->sc_dev),
421 	    device_get_unit(sc->sc_dev),
422 	    "sgmii.ctrl", &val) != 0)
423 		return (0);
424 	scfg->sgmii_ctrl = val;
425 
426 	/* serdes_aen */
427 	val = 0;
428 	if (resource_int_value(device_get_name(sc->sc_dev),
429 	    device_get_unit(sc->sc_dev),
430 	    "sgmii.serdes_aen", &val) != 0)
431 		return (0);
432 	scfg->serdes_aen = val;
433 
434 	return (1);
435 }
436 
437 /*
438  * Fetch the LED configuration from the boot hints.
439  */
440 static int
441 ar8327_fetch_pdata_led(struct arswitch_softc *sc,
442     struct ar8327_led_cfg *lcfg)
443 {
444 	int val;
445 
446 	val = 0;
447 	if (resource_int_value(device_get_name(sc->sc_dev),
448 	    device_get_unit(sc->sc_dev),
449 	    "led.ctrl0", &val) != 0)
450 		return (0);
451 	lcfg->led_ctrl0 = val;
452 
453 	val = 0;
454 	if (resource_int_value(device_get_name(sc->sc_dev),
455 	    device_get_unit(sc->sc_dev),
456 	    "led.ctrl1", &val) != 0)
457 		return (0);
458 	lcfg->led_ctrl1 = val;
459 
460 	val = 0;
461 	if (resource_int_value(device_get_name(sc->sc_dev),
462 	    device_get_unit(sc->sc_dev),
463 	    "led.ctrl2", &val) != 0)
464 		return (0);
465 	lcfg->led_ctrl2 = val;
466 
467 	val = 0;
468 	if (resource_int_value(device_get_name(sc->sc_dev),
469 	    device_get_unit(sc->sc_dev),
470 	    "led.ctrl3", &val) != 0)
471 		return (0);
472 	lcfg->led_ctrl3 = val;
473 
474 	val = 0;
475 	if (resource_int_value(device_get_name(sc->sc_dev),
476 	    device_get_unit(sc->sc_dev),
477 	    "led.open_drain", &val) != 0)
478 		return (0);
479 	lcfg->open_drain = val;
480 
481 	return (1);
482 }
483 
484 /*
485  * Initialise the ar8327 specific hardware features from
486  * the hints provided in the boot environment.
487  */
488 static int
489 ar8327_init_pdata(struct arswitch_softc *sc)
490 {
491 	struct ar8327_pad_cfg pc;
492 	struct ar8327_port_cfg port_cfg;
493 	struct ar8327_sgmii_cfg scfg;
494 	struct ar8327_led_cfg lcfg;
495 	uint32_t t, new_pos, pos;
496 
497 	/* Port 0 */
498 	bzero(&port_cfg, sizeof(port_cfg));
499 	sc->ar8327.port0_status = 0;
500 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 0))
501 		sc->ar8327.port0_status = ar8327_get_port_init_status(&port_cfg);
502 
503 	/* Port 6 */
504 	bzero(&port_cfg, sizeof(port_cfg));
505 	sc->ar8327.port6_status = 0;
506 	if (ar8327_fetch_pdata_port(sc, &port_cfg, 6))
507 		sc->ar8327.port6_status = ar8327_get_port_init_status(&port_cfg);
508 
509 	/* Pad 0 */
510 	bzero(&pc, sizeof(pc));
511 	t = 0;
512 	if (ar8327_fetch_pdata_pad(sc, &pc, 0))
513 		t = ar8327_get_pad_cfg(&pc);
514 #if 0
515 		if (AR8X16_IS_SWITCH(sc, AR8337))
516 			t |= AR8337_PAD_MAC06_EXCHANGE_EN;
517 #endif
518 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD0_MODE, t);
519 
520 	/* Pad 5 */
521 	bzero(&pc, sizeof(pc));
522 	t = 0;
523 	if (ar8327_fetch_pdata_pad(sc, &pc, 5))
524 		t = ar8327_get_pad_cfg(&pc);
525 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD5_MODE, t);
526 
527 	/* Pad 6 */
528 	bzero(&pc, sizeof(pc));
529 	t = 0;
530 	if (ar8327_fetch_pdata_pad(sc, &pc, 6))
531 		t = ar8327_get_pad_cfg(&pc);
532 	arswitch_writereg(sc->sc_dev, AR8327_REG_PAD6_MODE, t);
533 
534 	pos = arswitch_readreg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP);
535 	new_pos = pos;
536 
537 	/* XXX LED config */
538 	bzero(&lcfg, sizeof(lcfg));
539 	if (ar8327_fetch_pdata_led(sc, &lcfg)) {
540 		if (lcfg.open_drain)
541 			new_pos |= AR8327_POWER_ON_STRIP_LED_OPEN_EN;
542 		else
543 			new_pos &= ~AR8327_POWER_ON_STRIP_LED_OPEN_EN;
544 
545 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL0,
546 		    lcfg.led_ctrl0);
547 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL1,
548 		    lcfg.led_ctrl1);
549 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL2,
550 		    lcfg.led_ctrl2);
551 		arswitch_writereg(sc->sc_dev, AR8327_REG_LED_CTRL3,
552 		    lcfg.led_ctrl3);
553 
554 		if (new_pos != pos)
555 			new_pos |= AR8327_POWER_ON_STRIP_POWER_ON_SEL;
556 	}
557 
558 	/* SGMII config */
559 	bzero(&scfg, sizeof(scfg));
560 	if (ar8327_fetch_pdata_sgmii(sc, &scfg)) {
561 		t = scfg.sgmii_ctrl;
562 		if (sc->chip_rev == 1)
563 			t |= AR8327_SGMII_CTRL_EN_PLL |
564 			    AR8327_SGMII_CTRL_EN_RX |
565 			    AR8327_SGMII_CTRL_EN_TX;
566 		else
567 			t &= ~(AR8327_SGMII_CTRL_EN_PLL |
568 			    AR8327_SGMII_CTRL_EN_RX |
569 			    AR8327_SGMII_CTRL_EN_TX);
570 
571 		arswitch_writereg(sc->sc_dev, AR8327_REG_SGMII_CTRL, t);
572 
573 		if (scfg.serdes_aen)
574 			new_pos &= ~AR8327_POWER_ON_STRIP_SERDES_AEN;
575 		else
576 			new_pos |= AR8327_POWER_ON_STRIP_SERDES_AEN;
577 	}
578 
579 	arswitch_writereg(sc->sc_dev, AR8327_REG_POWER_ON_STRIP, new_pos);
580 
581 	return (0);
582 }
583 
584 static int
585 ar8327_hw_setup(struct arswitch_softc *sc)
586 {
587 	int i;
588 	int err;
589 
590 	/* pdata fetch and setup */
591 	err = ar8327_init_pdata(sc);
592 	if (err != 0)
593 		return (err);
594 
595 	/* XXX init leds */
596 
597 	for (i = 0; i < AR8327_NUM_PHYS; i++) {
598 		/* phy fixup */
599 		ar8327_phy_fixup(sc, i);
600 
601 		/* start PHY autonegotiation? */
602 		/* XXX is this done as part of the normal PHY setup? */
603 
604 	};
605 
606 	/* Let things settle */
607 	DELAY(1000);
608 
609 	return (0);
610 }
611 
612 /*
613  * Initialise other global values, for the AR8327.
614  */
615 static int
616 ar8327_hw_global_setup(struct arswitch_softc *sc)
617 {
618 	uint32_t t;
619 
620 	/* enable CPU port and disable mirror port */
621 	t = AR8327_FWD_CTRL0_CPU_PORT_EN |
622 	    AR8327_FWD_CTRL0_MIRROR_PORT;
623 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL0, t);
624 
625 	/* forward multicast and broadcast frames to CPU */
626 	t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) |
627 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) |
628 	    (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S);
629 	arswitch_writereg(sc->sc_dev, AR8327_REG_FWD_CTRL1, t);
630 
631 	/* enable jumbo frames */
632 	/* XXX need to macro-shift the value! */
633 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MAX_FRAME_SIZE,
634 	    AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2);
635 
636 	/* Enable MIB counters */
637 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_MODULE_EN,
638 	    AR8327_MODULE_EN_MIB, AR8327_MODULE_EN_MIB);
639 
640 	/* Set the right number of ports */
641 	sc->info.es_nports = 6;
642 
643 	return (0);
644 }
645 
646 /*
647  * Port setup.
648  */
649 static void
650 ar8327_port_init(struct arswitch_softc *sc, int port)
651 {
652 	uint32_t t;
653 
654 	if (port == AR8X16_PORT_CPU)
655 		t = sc->ar8327.port0_status;
656 	else if (port == 6)
657 		t = sc->ar8327.port6_status;
658         else
659 		t = AR8X16_PORT_STS_LINK_AUTO;
660 
661 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_STATUS(port), t);
662 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_HEADER(port), 0);
663 
664 	/*
665 	 * Default to 1 port group.
666 	 */
667 	t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
668 	t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
669 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(port), t);
670 
671 	t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S;
672 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(port), t);
673 
674 	/*
675 	 * This doesn't configure any ports which this port can "see".
676 	 * bits 0-6 control which ports a frame coming into this port
677 	 * can be sent out to.
678 	 *
679 	 * So by doing this, we're making it impossible to send frames out
680 	 * to that port.
681 	 */
682 	t = AR8327_PORT_LOOKUP_LEARN;
683 	t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
684 
685 	/* So this allows traffic to any port except ourselves */
686 	t |= (0x3f & ~(1 << port));
687 	arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(port), t);
688 }
689 
690 static int
691 ar8327_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
692 {
693 
694 	/* XXX stub for now */
695 	device_printf(sc->sc_dev, "%s: called\n", __func__);
696 	return (0);
697 }
698 
699 static int
700 ar8327_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
701 {
702 
703 	/* XXX stub for now */
704 	device_printf(sc->sc_dev, "%s: called\n", __func__);
705 	return (0);
706 }
707 
708 static void
709 ar8327_reset_vlans(struct arswitch_softc *sc)
710 {
711 	int i;
712 	uint32_t mode, t;
713 
714 	/*
715 	 * Disable mirroring.
716 	 */
717 	arswitch_modifyreg(sc->sc_dev, AR8327_REG_FWD_CTRL0,
718 	    AR8327_FWD_CTRL0_MIRROR_PORT,
719 	    (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S));
720 
721 	/*
722 	 * For now, let's default to one portgroup, just so traffic
723 	 * flows.  All ports can see other ports.
724 	 */
725 	for (i = 0; i < AR8327_NUM_PORTS; i++) {
726 		/* set pvid = 1; there's only one vlangroup */
727 		t = 1 << AR8327_PORT_VLAN0_DEF_SVID_S;
728 		t |= 1 << AR8327_PORT_VLAN0_DEF_CVID_S;
729 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN0(i), t);
730 
731 		/* set egress == out_keep */
732 		mode = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH;
733 
734 		t = AR8327_PORT_VLAN1_PORT_VLAN_PROP;
735 		t |= mode << AR8327_PORT_VLAN1_OUT_MODE_S;
736 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_VLAN1(i), t);
737 
738 		/* Ports can see other ports */
739 		t = (0x3f & ~(1 << i));	/* all ports besides us */
740 		t |= AR8327_PORT_LOOKUP_LEARN;
741 
742 		/* in_port_only, forward */
743 		t |= AR8X16_PORT_VLAN_MODE_PORT_ONLY << AR8327_PORT_LOOKUP_IN_MODE_S;
744 		t |= AR8X16_PORT_CTRL_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S;
745 		arswitch_writereg(sc->sc_dev, AR8327_REG_PORT_LOOKUP(i), t);
746 
747 		/*
748 		 * Disable port mirroring entirely.
749 		 */
750 		arswitch_modifyreg(sc->sc_dev,
751 		    AR8327_REG_PORT_LOOKUP(i),
752 		    AR8327_PORT_LOOKUP_ING_MIRROR_EN,
753 		    0);
754 		arswitch_modifyreg(sc->sc_dev,
755 		    AR8327_REG_PORT_HOL_CTRL1(i),
756 		    AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN,
757 		    0);
758 	}
759 }
760 
761 static int
762 ar8327_vlan_getvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
763 {
764 	device_printf(sc->sc_dev, "%s: called\n", __func__);
765 	return (0);
766 }
767 
768 static int
769 ar8327_vlan_setvgroup(struct arswitch_softc *sc, etherswitch_vlangroup_t *vg)
770 {
771 
772 	device_printf(sc->sc_dev, "%s: called\n", __func__);
773 	return (0);
774 }
775 
776 static int
777 ar8327_get_pvid(struct arswitch_softc *sc, int port, int *pvid)
778 {
779 
780 	device_printf(sc->sc_dev, "%s: called\n", __func__);
781 	return (0);
782 }
783 
784 static int
785 ar8327_set_pvid(struct arswitch_softc *sc, int port, int pvid)
786 {
787 
788 	device_printf(sc->sc_dev, "%s: called\n", __func__);
789 	return (0);
790 }
791 
792 static int
793 ar8327_atu_flush(struct arswitch_softc *sc)
794 {
795 
796 	int ret;
797 
798 	ret = arswitch_waitreg(sc->sc_dev,
799 	    AR8327_REG_ATU_FUNC,
800 	    AR8327_ATU_FUNC_BUSY,
801 	    0,
802 	    1000);
803 
804 	if (ret)
805 		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
806 
807 	if (!ret)
808 		arswitch_writereg(sc->sc_dev,
809 		    AR8327_REG_ATU_FUNC,
810 		    AR8327_ATU_FUNC_OP_FLUSH);
811 	return (ret);
812 }
813 
814 void
815 ar8327_attach(struct arswitch_softc *sc)
816 {
817 
818 	sc->hal.arswitch_hw_setup = ar8327_hw_setup;
819 	sc->hal.arswitch_hw_global_setup = ar8327_hw_global_setup;
820 
821 	sc->hal.arswitch_port_init = ar8327_port_init;
822 	sc->hal.arswitch_port_vlan_setup = ar8327_port_vlan_setup;
823 	sc->hal.arswitch_port_vlan_get = ar8327_port_vlan_get;
824 
825 	sc->hal.arswitch_vlan_init_hw = ar8327_reset_vlans;
826 	sc->hal.arswitch_vlan_getvgroup = ar8327_vlan_getvgroup;
827 	sc->hal.arswitch_vlan_setvgroup = ar8327_vlan_setvgroup;
828 	sc->hal.arswitch_vlan_get_pvid = ar8327_get_pvid;
829 	sc->hal.arswitch_vlan_set_pvid = ar8327_set_pvid;
830 
831 	sc->hal.arswitch_atu_flush = ar8327_atu_flush;
832 
833 	/* Set the switch vlan capabilities. */
834 	sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q |
835 	    ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOUBLE_TAG;
836 	sc->info.es_nvlangroups = AR8X16_MAX_VLANS;
837 }
838