]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/etherswitch/arswitch/arswitch_8327.c
Import byacc 20141005 from vendor
[FreeBSD/FreeBSD.git] / sys / dev / etherswitch / arswitch / arswitch_8327.c
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 }