1*cbab9cadSchs /* $NetBSD: if_sm_gxio.c,v 1.11 2012/10/27 17:17:47 chs Exp $ */
260e982e8Skiyohara /*
360e982e8Skiyohara * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation.
460e982e8Skiyohara * All rights reserved.
560e982e8Skiyohara *
660e982e8Skiyohara * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM
760e982e8Skiyohara * Corporation.
860e982e8Skiyohara *
960e982e8Skiyohara * Redistribution and use in source and binary forms, with or without
1060e982e8Skiyohara * modification, are permitted provided that the following conditions
1160e982e8Skiyohara * are met:
1260e982e8Skiyohara * 1. Redistributions of source code must retain the above copyright
1360e982e8Skiyohara * notice, this list of conditions and the following disclaimer.
1460e982e8Skiyohara * 2. Redistributions in binary form must reproduce the above copyright
1560e982e8Skiyohara * notice, this list of conditions and the following disclaimer in the
1660e982e8Skiyohara * documentation and/or other materials provided with the distribution.
1760e982e8Skiyohara * 3. Neither the name of the project nor the name of SOUM Corporation
1860e982e8Skiyohara * may be used to endorse or promote products derived from this software
1960e982e8Skiyohara * without specific prior written permission.
2060e982e8Skiyohara *
2160e982e8Skiyohara * THIS SOFTWARE IS PROVIDED BY THE PROJECT and SOUM CORPORATION ``AS IS''
2260e982e8Skiyohara * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2360e982e8Skiyohara * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2460e982e8Skiyohara * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT AND SOUM CORPORATION
2560e982e8Skiyohara * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2660e982e8Skiyohara * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2760e982e8Skiyohara * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2860e982e8Skiyohara * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2960e982e8Skiyohara * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3060e982e8Skiyohara * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3160e982e8Skiyohara * POSSIBILITY OF SUCH DAMAGE.
3260e982e8Skiyohara */
3360e982e8Skiyohara /*-
3460e982e8Skiyohara * Copyright (c) 1997 The NetBSD Foundation, Inc.
3560e982e8Skiyohara * All rights reserved.
3660e982e8Skiyohara *
3760e982e8Skiyohara * This code is derived from software contributed to The NetBSD Foundation
3860e982e8Skiyohara * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
3960e982e8Skiyohara * NASA Ames Research Center.
4060e982e8Skiyohara *
4160e982e8Skiyohara * Redistribution and use in source and binary forms, with or without
4260e982e8Skiyohara * modification, are permitted provided that the following conditions
4360e982e8Skiyohara * are met:
4460e982e8Skiyohara * 1. Redistributions of source code must retain the above copyright
4560e982e8Skiyohara * notice, this list of conditions and the following disclaimer.
4660e982e8Skiyohara * 2. Redistributions in binary form must reproduce the above copyright
4760e982e8Skiyohara * notice, this list of conditions and the following disclaimer in the
4860e982e8Skiyohara * documentation and/or other materials provided with the distribution.
4960e982e8Skiyohara *
5060e982e8Skiyohara * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
5160e982e8Skiyohara * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
5260e982e8Skiyohara * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5360e982e8Skiyohara * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
5460e982e8Skiyohara * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5560e982e8Skiyohara * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5660e982e8Skiyohara * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5760e982e8Skiyohara * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5860e982e8Skiyohara * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5960e982e8Skiyohara * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6060e982e8Skiyohara * POSSIBILITY OF SUCH DAMAGE.
6160e982e8Skiyohara */
6260e982e8Skiyohara
6360e982e8Skiyohara #include <sys/cdefs.h>
64*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: if_sm_gxio.c,v 1.11 2012/10/27 17:17:47 chs Exp $");
6560e982e8Skiyohara
6660e982e8Skiyohara #include <sys/param.h>
6760e982e8Skiyohara #include <sys/device.h>
6860e982e8Skiyohara #include <sys/errno.h>
6960e982e8Skiyohara
7060e982e8Skiyohara #include <sys/systm.h>
7160e982e8Skiyohara #include <sys/mbuf.h>
7260e982e8Skiyohara #include <sys/socket.h>
7360e982e8Skiyohara #include <sys/ioctl.h>
7460e982e8Skiyohara #include <sys/syslog.h>
7560e982e8Skiyohara #include <sys/select.h>
7660e982e8Skiyohara
7760e982e8Skiyohara #include <net/if.h>
7860e982e8Skiyohara #include <net/if_dl.h>
7960e982e8Skiyohara #include <net/if_ether.h>
8060e982e8Skiyohara #include <net/if_media.h>
8160e982e8Skiyohara
8260e982e8Skiyohara #include <machine/intr.h>
83fea15f47Sdyoung #include <sys/bus.h>
8460e982e8Skiyohara
8560e982e8Skiyohara #include <dev/mii/mii.h>
8660e982e8Skiyohara #include <dev/mii/miivar.h>
8760e982e8Skiyohara
8860e982e8Skiyohara #include <dev/ic/smc91cxxreg.h>
8960e982e8Skiyohara #include <dev/ic/smc91cxxvar.h>
9060e982e8Skiyohara
9160e982e8Skiyohara #include <evbarm/gumstix/gumstixvar.h>
9260e982e8Skiyohara
9360e982e8Skiyohara #include "locators.h"
9460e982e8Skiyohara
9560e982e8Skiyohara
962438bca8Skiyohara static int sm_gxio_match(device_t, struct cfdata *, void *);
972438bca8Skiyohara static void sm_gxio_attach(device_t, device_t, void *);
9860e982e8Skiyohara
9960e982e8Skiyohara static int ether_serial_digit = 1;
10060e982e8Skiyohara
10160e982e8Skiyohara struct sm_gxio_softc {
10260e982e8Skiyohara struct smc91cxx_softc sc_smc;
10360e982e8Skiyohara void *sc_ih;
10460e982e8Skiyohara };
10560e982e8Skiyohara
106*cbab9cadSchs CFATTACH_DECL_NEW(sm_gxio, sizeof(struct sm_gxio_softc),
10760e982e8Skiyohara sm_gxio_match, sm_gxio_attach, NULL, NULL);
10860e982e8Skiyohara
10960e982e8Skiyohara
1105d6dcf3dSkiyohara /* ARGSUSED */
11160e982e8Skiyohara static int
sm_gxio_match(device_t parent,struct cfdata * match,void * aux)1122438bca8Skiyohara sm_gxio_match(device_t parent, struct cfdata *match, void *aux)
11360e982e8Skiyohara {
11460e982e8Skiyohara struct gxio_attach_args *gxa = aux;
11560e982e8Skiyohara bus_space_tag_t iot = gxa->gxa_iot;
11660e982e8Skiyohara bus_space_handle_t ioh;
1171c10f508Skiyohara uint16_t tmp;
11860e982e8Skiyohara int rv = 0;
11960e982e8Skiyohara extern const char *smc91cxx_idstrs[];
12060e982e8Skiyohara
12160e982e8Skiyohara /* Disallow wildcarded values. */
12260e982e8Skiyohara if (gxa->gxa_addr == GXIOCF_ADDR_DEFAULT)
1231c10f508Skiyohara return 0;
12460e982e8Skiyohara if (gxa->gxa_gpirq == GXIOCF_GPIRQ_DEFAULT)
1251c10f508Skiyohara return 0;
12660e982e8Skiyohara
12760e982e8Skiyohara if (bus_space_map(iot, gxa->gxa_addr, SMC_IOSIZE, 0, &ioh) != 0)
1281c10f508Skiyohara return 0;
12960e982e8Skiyohara
13060e982e8Skiyohara /* Check that high byte of BANK_SELECT is what we expect. */
13160e982e8Skiyohara tmp = bus_space_read_2(iot, ioh, BANK_SELECT_REG_W);
13260e982e8Skiyohara if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE)
13360e982e8Skiyohara goto out;
13460e982e8Skiyohara
13560e982e8Skiyohara /*
13660e982e8Skiyohara * Switch to bank 0 and perform the test again.
13760e982e8Skiyohara * XXX INVASIVE!
13860e982e8Skiyohara */
1390d23f6e0Skiyohara bus_space_write_2(iot, ioh, BANK_SELECT_REG_W, 0);
14060e982e8Skiyohara tmp = bus_space_read_2(iot, ioh, BANK_SELECT_REG_W);
14160e982e8Skiyohara if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE)
14260e982e8Skiyohara goto out;
14360e982e8Skiyohara
14460e982e8Skiyohara /*
14560e982e8Skiyohara * Check for a recognized chip id.
14660e982e8Skiyohara * XXX INVASIVE!
14760e982e8Skiyohara */
1480d23f6e0Skiyohara bus_space_write_2(iot, ioh, BANK_SELECT_REG_W, 3);
14960e982e8Skiyohara tmp = bus_space_read_2(iot, ioh, REVISION_REG_W);
15060e982e8Skiyohara if (smc91cxx_idstrs[RR_ID(tmp)] == NULL)
15160e982e8Skiyohara goto out;
15260e982e8Skiyohara
15360e982e8Skiyohara if (ether_serial_digit > 15)
15460e982e8Skiyohara goto out;
15560e982e8Skiyohara /*
15660e982e8Skiyohara * Assume we have an SMC91Cxx.
15760e982e8Skiyohara */
15860e982e8Skiyohara
15960e982e8Skiyohara rv = 1;
16060e982e8Skiyohara
16160e982e8Skiyohara out:
16260e982e8Skiyohara bus_space_unmap(iot, ioh, SMC_IOSIZE);
1631c10f508Skiyohara return rv;
16460e982e8Skiyohara }
16560e982e8Skiyohara
1665d6dcf3dSkiyohara /* ARGSUSED */
1671c10f508Skiyohara static void
sm_gxio_attach(device_t parent,device_t self,void * aux)1682438bca8Skiyohara sm_gxio_attach(device_t parent, device_t self, void *aux)
16960e982e8Skiyohara {
1707dbdf011Skiyohara struct sm_gxio_softc *gsc = device_private(self);
17160e982e8Skiyohara struct smc91cxx_softc *sc = &gsc->sc_smc;
17260e982e8Skiyohara struct gxio_attach_args *gxa = aux;
17360e982e8Skiyohara bus_space_handle_t ioh;
1741c10f508Skiyohara uint8_t myea[ETHER_ADDR_LEN];
17560e982e8Skiyohara
1767dbdf011Skiyohara aprint_normal("\n");
1777dbdf011Skiyohara aprint_naive("\n");
17860e982e8Skiyohara
1791c10f508Skiyohara KASSERT(system_serial_high != 0 || system_serial_low != 0);
1801c10f508Skiyohara
18160e982e8Skiyohara /* Map i/o space. */
18260e982e8Skiyohara if (bus_space_map(gxa->gxa_iot, gxa->gxa_addr, SMC_IOSIZE, 0, &ioh))
18360e982e8Skiyohara panic("sm_gxio_attach: can't map i/o space");
18460e982e8Skiyohara
185*cbab9cadSchs sc->sc_dev = self;
18660e982e8Skiyohara sc->sc_bst = gxa->gxa_iot;
18760e982e8Skiyohara sc->sc_bsh = ioh;
18860e982e8Skiyohara
18960e982e8Skiyohara /* should always be enabled */
19060e982e8Skiyohara sc->sc_flags |= SMC_FLAGS_ENABLED;
19160e982e8Skiyohara
19260e982e8Skiyohara myea[0] = ((system_serial_high >> 8) & 0xfe) | 0x02;
19360e982e8Skiyohara myea[1] = system_serial_high;
19460e982e8Skiyohara myea[2] = system_serial_low >> 24;
19560e982e8Skiyohara myea[3] = system_serial_low >> 16;
19660e982e8Skiyohara myea[4] = system_serial_low >> 8;
19760e982e8Skiyohara myea[5] = (system_serial_low & 0xc0) |
19860e982e8Skiyohara (1 << 4) | ((ether_serial_digit++) & 0x0f);
19960e982e8Skiyohara smc91cxx_attach(sc, myea);
20060e982e8Skiyohara
20160e982e8Skiyohara /* Establish the interrupt handler. */
20260e982e8Skiyohara gsc->sc_ih = gxio_intr_establish(gxa->gxa_sc,
20360e982e8Skiyohara gxa->gxa_gpirq, IST_EDGE_RISING, IPL_NET, smc91cxx_intr, sc);
20460e982e8Skiyohara
20560e982e8Skiyohara if (gsc->sc_ih == NULL)
2062438bca8Skiyohara aprint_error_dev(self,
2072438bca8Skiyohara "couldn't establish interrupt handler\n");
20860e982e8Skiyohara }
209