xref: /netbsd-src/sys/arch/evbarm/gumstix/if_sm_gxio.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
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