1183234Ssimon/*	$NetBSD: if_gem_sbus.c,v 1.12 2009/08/04 09:26:26 martin Exp $	*/
2280297Sjkim
3280297Sjkim/*-
4183234Ssimon * Copyright (c) 2006 The NetBSD Foundation, Inc.
5183234Ssimon * All rights reserved.
6183234Ssimon *
7183234Ssimon * This code is derived from software contributed to The NetBSD Foundation
8183234Ssimon * by Martin Husemann.
9183234Ssimon *
10183234Ssimon * Redistribution and use in source and binary forms, with or without
11183234Ssimon * modification, are permitted provided that the following conditions
12183234Ssimon * are met:
13183234Ssimon * 1. Redistributions of source code must retain the above copyright
14280297Sjkim *    notice, this list of conditions and the following disclaimer.
15183234Ssimon * 2. Redistributions in binary form must reproduce the above copyright
16183234Ssimon *    notice, this list of conditions and the following disclaimer in the
17183234Ssimon *    documentation and/or other materials provided with the distribution.
18183234Ssimon *
19183234Ssimon * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20183234Ssimon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21183234Ssimon * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22183234Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23183234Ssimon * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24183234Ssimon * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25183234Ssimon * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26183234Ssimon * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27183234Ssimon * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28183234Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29183234Ssimon * POSSIBILITY OF SUCH DAMAGE.
30183234Ssimon */
31183234Ssimon
32183234Ssimon/*
33183234Ssimon * SBus front-end for the GEM network driver
34183234Ssimon */
35183234Ssimon
36183234Ssimon#include <sys/cdefs.h>
37183234Ssimon__KERNEL_RCSID(0, "$NetBSD: if_gem_sbus.c,v 1.12 2009/08/04 09:26:26 martin Exp $");
38183234Ssimon
39183234Ssimon#include <sys/param.h>
40183234Ssimon#include <sys/systm.h>
41183234Ssimon#include <sys/syslog.h>
42183234Ssimon#include <sys/device.h>
43183234Ssimon#include <sys/malloc.h>
44183234Ssimon#include <sys/socket.h>
45183234Ssimon
46183234Ssimon#include <net/if.h>
47183234Ssimon#include <net/if_dl.h>
48183234Ssimon#include <net/if_ether.h>
49183234Ssimon#include <net/if_media.h>
50183234Ssimon
51183234Ssimon#include <dev/mii/mii.h>
52183234Ssimon#include <dev/mii/miivar.h>
53183234Ssimon
54183234Ssimon#include <sys/bus.h>
55183234Ssimon#include <sys/intr.h>
56183234Ssimon#include <machine/autoconf.h>
57183234Ssimon
58183234Ssimon#include <dev/sbus/sbusvar.h>
59183234Ssimon
60183234Ssimon#include <dev/ic/gemreg.h>
61183234Ssimon#include <dev/ic/gemvar.h>
62183234Ssimon
63238405Sjkimstruct gem_sbus_softc {
64183234Ssimon	struct	gem_softc	gsc_gem;	/* GEM device */
65280297Sjkim	void			*gsc_ih;
66280297Sjkim	bus_space_handle_t	gsc_sbus_regs_h;
67280297Sjkim};
68183234Ssimon
69183234Ssimonint	gemmatch_sbus(device_t, cfdata_t, void *);
70280297Sjkimvoid	gemattach_sbus(device_t, device_t, void *);
71280297Sjkim
72280297SjkimCFATTACH_DECL3_NEW(gem_sbus, sizeof(struct gem_sbus_softc),
73183234Ssimon    gemmatch_sbus, gemattach_sbus, NULL, NULL, NULL, NULL, 0);
74183234Ssimon
75183234Ssimonint
76280297Sjkimgemmatch_sbus(device_t parent, cfdata_t cf, void *aux)
77280297Sjkim{
78183234Ssimon	struct sbus_attach_args *sa = aux;
79183234Ssimon
80183234Ssimon	return (strcmp("network", sa->sa_name) == 0);
81183234Ssimon}
82183234Ssimon
83183234Ssimonvoid
84280297Sjkimgemattach_sbus(device_t parent, device_t self, void *aux)
85280297Sjkim{
86280297Sjkim	struct sbus_attach_args *sa = aux;
87183234Ssimon	struct gem_sbus_softc *gsc = device_private(self);
88183234Ssimon	struct gem_softc *sc = &gsc->gsc_gem;
89183234Ssimon	uint8_t enaddr[ETHER_ADDR_LEN];
90183234Ssimon
91183234Ssimon	sc->sc_dev = self;
92238405Sjkim
93280297Sjkim	/* Pass on the bus tags */
94280297Sjkim	sc->sc_bustag = sa->sa_bustag;
95280297Sjkim	sc->sc_dmatag = sa->sa_dmatag;
96280297Sjkim
97183234Ssimon	if (sa->sa_nreg < 2) {
98183234Ssimon		printf("%s: only %d register sets\n",
99183234Ssimon			device_xname(self), sa->sa_nreg);
100280297Sjkim		return;
101280297Sjkim	}
102280297Sjkim
103280297Sjkim	/*
104183234Ssimon	 * Map two register banks:
105183234Ssimon	 *
106183234Ssimon	 *	bank 0: status, config, reset
107183234Ssimon	 *	bank 1: various gem parts
108183234Ssimon	 *
109183234Ssimon	 */
110183234Ssimon	if (sbus_bus_map(sa->sa_bustag,
111183234Ssimon			 sa->sa_reg[0].oa_space,
112183234Ssimon			 sa->sa_reg[0].oa_base,
113280297Sjkim			 (bus_size_t)sa->sa_reg[0].oa_size,
114183234Ssimon			 0, &sc->sc_h2) != 0) {
115238405Sjkim		aprint_error_dev(self, "cannot map registers\n");
116238405Sjkim		return;
117238405Sjkim	}
118280297Sjkim	if (sbus_bus_map(sa->sa_bustag,
119280297Sjkim			 sa->sa_reg[1].oa_space,
120280297Sjkim			 sa->sa_reg[1].oa_base,
121280297Sjkim			 (bus_size_t)sa->sa_reg[1].oa_size,
122280297Sjkim			 0, &sc->sc_h1) != 0) {
123280297Sjkim		aprint_error_dev(self, "cannot map registers\n");
124280297Sjkim		return;
125280297Sjkim	}
126280297Sjkim	prom_getether(sa->sa_node, enaddr);
127280297Sjkim
128280297Sjkim	if (!strcmp("serdes", prom_getpropstring(sa->sa_node, "shared-pins")))
129280297Sjkim		sc->sc_flags |= GEM_SERDES;
130280297Sjkim	sc->sc_variant = GEM_SUN_GEM;
131280297Sjkim	sc->sc_flags &= ~GEM_PCI;
132280297Sjkim
133280297Sjkim	/*
134280297Sjkim	 * SBUS config
135280297Sjkim	 */
136280297Sjkim	(void) bus_space_read_4(sa->sa_bustag, sc->sc_h2, GEM_SBUS_RESET);
137280297Sjkim	delay(100);
138280297Sjkim	bus_space_write_4(sa->sa_bustag, sc->sc_h2, GEM_SBUS_CONFIG,
139280297Sjkim	    GEM_SBUS_CFG_BSIZE128|GEM_SBUS_CFG_PARITY|GEM_SBUS_CFG_BMODE64);
140280297Sjkim	sc->sc_chiprev = bus_space_read_4(sa->sa_bustag, sc->sc_h2,
141280297Sjkim	    GEM_SBUS_REVISION);
142280297Sjkim
143280297Sjkim	printf(": GEM Ethernet controller (%s), version %s (rev 0x%02x)\n",
144280297Sjkim	    sa->sa_name, prom_getpropstring(sa->sa_node, "version"),
145238405Sjkim	    sc->sc_chiprev);
146183234Ssimon
147183234Ssimon	gem_attach(sc, enaddr);
148183234Ssimon
149280297Sjkim	/* Establish interrupt handler */
150280297Sjkim	if (sa->sa_nintr != 0)
151280297Sjkim		gsc->gsc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET,
152280297Sjkim					gem_intr, sc);
153280297Sjkim}
154280297Sjkim