1 /*-
2  * Copyright (c) 1999 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by Paul Kranenburg.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  *	from: NetBSD: if_hme_sbus.c,v 1.19 2004/03/17 17:04:58 pk Exp
30  */
31 
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: stable/9/sys/dev/hme/if_hme_sbus.c 229093 2011-12-31 14:12:12Z hselasky $");
34 
35 /*
36  * SBus front-end device driver for the HME ethernet device.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/bus.h>
42 #include <sys/kernel.h>
43 #include <sys/module.h>
44 #include <sys/resource.h>
45 #include <sys/socket.h>
46 
47 #include <dev/ofw/ofw_bus.h>
48 
49 #include <machine/bus.h>
50 #include <machine/ofw_machdep.h>
51 #include <machine/resource.h>
52 
53 #include <sys/rman.h>
54 
55 #include <net/ethernet.h>
56 #include <net/if.h>
57 #include <net/if_arp.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 
61 #include <dev/mii/mii.h>
62 #include <dev/mii/miivar.h>
63 
64 #include <sparc64/sbus/sbusvar.h>
65 
66 #include <dev/hme/if_hmereg.h>
67 #include <dev/hme/if_hmevar.h>
68 
69 #include "miibus_if.h"
70 
71 struct hme_sbus_softc {
72 	struct	hme_softc	hsc_hme;	/* HME device */
73 	struct	resource	*hsc_seb_res;
74 	struct	resource	*hsc_etx_res;
75 	struct	resource	*hsc_erx_res;
76 	struct	resource	*hsc_mac_res;
77 	struct	resource	*hsc_mif_res;
78 	struct	resource	*hsc_ires;
79 	void			*hsc_ih;
80 };
81 
82 static int hme_sbus_probe(device_t);
83 static int hme_sbus_attach(device_t);
84 static int hme_sbus_detach(device_t);
85 static int hme_sbus_suspend(device_t);
86 static int hme_sbus_resume(device_t);
87 
88 static device_method_t hme_sbus_methods[] = {
89 	/* Device interface */
90 	DEVMETHOD(device_probe,		hme_sbus_probe),
91 	DEVMETHOD(device_attach,	hme_sbus_attach),
92 	DEVMETHOD(device_detach,	hme_sbus_detach),
93 	DEVMETHOD(device_suspend,	hme_sbus_suspend),
94 	DEVMETHOD(device_resume,	hme_sbus_resume),
95 	/* Can just use the suspend method here. */
96 	DEVMETHOD(device_shutdown,	hme_sbus_suspend),
97 
98 	/* MII interface */
99 	DEVMETHOD(miibus_readreg,	hme_mii_readreg),
100 	DEVMETHOD(miibus_writereg,	hme_mii_writereg),
101 	DEVMETHOD(miibus_statchg,	hme_mii_statchg),
102 
103 	DEVMETHOD_END
104 };
105 
106 static driver_t hme_sbus_driver = {
107 	"hme",
108 	hme_sbus_methods,
109 	sizeof(struct hme_sbus_softc)
110 };
111 
112 DRIVER_MODULE(hme, sbus, hme_sbus_driver, hme_devclass, 0, 0);
113 MODULE_DEPEND(hme, sbus, 1, 1, 1);
114 MODULE_DEPEND(hme, ether, 1, 1, 1);
115 
116 static int
hme_sbus_probe(device_t dev)117 hme_sbus_probe(device_t dev)
118 {
119 	const char *name;
120 
121 	name = ofw_bus_get_name(dev);
122 	if (strcmp(name, "SUNW,qfe") == 0 ||
123 	    strcmp(name, "SUNW,hme") == 0) {
124 		device_set_desc(dev, "Sun HME 10/100 Ethernet");
125 		return (0);
126 	}
127 	return (ENXIO);
128 }
129 
130 static int
hme_sbus_attach(device_t dev)131 hme_sbus_attach(device_t dev)
132 {
133 	struct hme_sbus_softc *hsc;
134 	struct hme_softc *sc;
135 	u_long start, count;
136 	uint32_t burst;
137 	int i, error = 0;
138 
139 	hsc = device_get_softc(dev);
140 	sc = &hsc->hsc_hme;
141 	mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
142 	    MTX_DEF);
143 	/*
144 	 * Map five register banks:
145 	 *
146 	 *	bank 0: HME SEB registers
147 	 *	bank 1: HME ETX registers
148 	 *	bank 2: HME ERX registers
149 	 *	bank 3: HME MAC registers
150 	 *	bank 4: HME MIF registers
151 	 *
152 	 */
153 	i = 0;
154 	hsc->hsc_seb_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
155 	    &i, RF_ACTIVE);
156 	if (hsc->hsc_seb_res == NULL) {
157 		device_printf(dev, "cannot map SEB registers\n");
158 		error = ENXIO;
159 		goto fail_mtx_res;
160 	}
161 	sc->sc_sebt = rman_get_bustag(hsc->hsc_seb_res);
162 	sc->sc_sebh = rman_get_bushandle(hsc->hsc_seb_res);
163 
164 	i = 1;
165 	hsc->hsc_etx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
166 	    &i, RF_ACTIVE);
167 	if (hsc->hsc_etx_res == NULL) {
168 		device_printf(dev, "cannot map ETX registers\n");
169 		error = ENXIO;
170 		goto fail_seb_res;
171 	}
172 	sc->sc_etxt = rman_get_bustag(hsc->hsc_etx_res);
173 	sc->sc_etxh = rman_get_bushandle(hsc->hsc_etx_res);
174 
175 	i = 2;
176 	hsc->hsc_erx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
177 	    &i, RF_ACTIVE);
178 	if (hsc->hsc_erx_res == NULL) {
179 		device_printf(dev, "cannot map ERX registers\n");
180 		error = ENXIO;
181 		goto fail_etx_res;
182 	}
183 	sc->sc_erxt = rman_get_bustag(hsc->hsc_erx_res);
184 	sc->sc_erxh = rman_get_bushandle(hsc->hsc_erx_res);
185 
186 	i = 3;
187 	hsc->hsc_mac_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
188 	    &i, RF_ACTIVE);
189 	if (hsc->hsc_mac_res == NULL) {
190 		device_printf(dev, "cannot map MAC registers\n");
191 		error = ENXIO;
192 		goto fail_erx_res;
193 	}
194 	sc->sc_mact = rman_get_bustag(hsc->hsc_mac_res);
195 	sc->sc_mach = rman_get_bushandle(hsc->hsc_mac_res);
196 
197 	/*
198 	 * At least on some HMEs, the MIF registers seem to be inside the MAC
199 	 * range, so try to kludge around it.
200 	 */
201 	i = 4;
202 	hsc->hsc_mif_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
203 	    &i, RF_ACTIVE);
204 	if (hsc->hsc_mif_res == NULL) {
205 		if (bus_get_resource(dev, SYS_RES_MEMORY, i,
206 		    &start, &count) != 0) {
207 			device_printf(dev, "cannot get MIF registers\n");
208 			error = ENXIO;
209 			goto fail_mac_res;
210 		}
211 		if (start < rman_get_start(hsc->hsc_mac_res) ||
212 		    start + count - 1 > rman_get_end(hsc->hsc_mac_res)) {
213 			device_printf(dev, "cannot move MIF registers to MAC "
214 			    "bank\n");
215 			error = ENXIO;
216 			goto fail_mac_res;
217 		}
218 		sc->sc_mift = sc->sc_mact;
219 		bus_space_subregion(sc->sc_mact, sc->sc_mach,
220 		    start - rman_get_start(hsc->hsc_mac_res), count,
221 		    &sc->sc_mifh);
222 	} else {
223 		sc->sc_mift = rman_get_bustag(hsc->hsc_mif_res);
224 		sc->sc_mifh = rman_get_bushandle(hsc->hsc_mif_res);
225 	}
226 
227 	i = 0;
228 	hsc->hsc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
229 	    &i, RF_SHAREABLE | RF_ACTIVE);
230 	if (hsc->hsc_ires == NULL) {
231 		device_printf(dev, "could not allocate interrupt\n");
232 		error = ENXIO;
233 		goto fail_mif_res;
234 	}
235 
236 	OF_getetheraddr(dev, sc->sc_enaddr);
237 
238 	burst = sbus_get_burstsz(dev);
239 	/* Translate into plain numerical format */
240 	if ((burst & SBUS_BURST_64))
241 		sc->sc_burst = 64;
242 	else if ((burst & SBUS_BURST_32))
243 		sc->sc_burst = 32;
244 	else if ((burst & SBUS_BURST_16))
245 		sc->sc_burst = 16;
246 	else
247 		 sc->sc_burst = 0;
248 
249 	sc->sc_dev = dev;
250 	sc->sc_flags = 0;
251 
252 	if ((error = hme_config(sc)) != 0) {
253 		device_printf(dev, "could not be configured\n");
254 		goto fail_ires;
255 	}
256 
257 	if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET |
258 	    INTR_MPSAFE, NULL, hme_intr, sc, &hsc->hsc_ih)) != 0) {
259 		device_printf(dev, "couldn't establish interrupt\n");
260 		hme_detach(sc);
261 		goto fail_ires;
262 	}
263 	return (0);
264 
265 fail_ires:
266 	bus_release_resource(dev, SYS_RES_IRQ,
267 	    rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
268 fail_mif_res:
269 	if (hsc->hsc_mif_res != NULL) {
270 		bus_release_resource(dev, SYS_RES_MEMORY,
271 		    rman_get_rid(hsc->hsc_mif_res), hsc->hsc_mif_res);
272 	}
273 fail_mac_res:
274 	bus_release_resource(dev, SYS_RES_MEMORY,
275 	    rman_get_rid(hsc->hsc_mac_res), hsc->hsc_mac_res);
276 fail_erx_res:
277 	bus_release_resource(dev, SYS_RES_MEMORY,
278 	    rman_get_rid(hsc->hsc_erx_res), hsc->hsc_erx_res);
279 fail_etx_res:
280 	bus_release_resource(dev, SYS_RES_MEMORY,
281 	    rman_get_rid(hsc->hsc_etx_res), hsc->hsc_etx_res);
282 fail_seb_res:
283 	bus_release_resource(dev, SYS_RES_MEMORY,
284 	    rman_get_rid(hsc->hsc_seb_res), hsc->hsc_seb_res);
285 fail_mtx_res:
286 	mtx_destroy(&sc->sc_lock);
287 	return (error);
288 }
289 
290 static int
hme_sbus_detach(device_t dev)291 hme_sbus_detach(device_t dev)
292 {
293 	struct hme_sbus_softc *hsc;
294 	struct hme_softc *sc;
295 
296 	hsc = device_get_softc(dev);
297 	sc = &hsc->hsc_hme;
298 	bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih);
299 	hme_detach(sc);
300 	bus_release_resource(dev, SYS_RES_IRQ,
301 	    rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
302 	if (hsc->hsc_mif_res != NULL) {
303 		bus_release_resource(dev, SYS_RES_MEMORY,
304 		    rman_get_rid(hsc->hsc_mif_res), hsc->hsc_mif_res);
305 	}
306 	bus_release_resource(dev, SYS_RES_MEMORY,
307 	    rman_get_rid(hsc->hsc_mac_res), hsc->hsc_mac_res);
308 	bus_release_resource(dev, SYS_RES_MEMORY,
309 	    rman_get_rid(hsc->hsc_erx_res), hsc->hsc_erx_res);
310 	bus_release_resource(dev, SYS_RES_MEMORY,
311 	    rman_get_rid(hsc->hsc_etx_res), hsc->hsc_etx_res);
312 	bus_release_resource(dev, SYS_RES_MEMORY,
313 	    rman_get_rid(hsc->hsc_seb_res), hsc->hsc_seb_res);
314 	mtx_destroy(&sc->sc_lock);
315 	return (0);
316 }
317 
318 static int
hme_sbus_suspend(device_t dev)319 hme_sbus_suspend(device_t dev)
320 {
321 	struct hme_sbus_softc *hsc;
322 
323 	hsc = device_get_softc(dev);
324 	hme_suspend(&hsc->hsc_hme);
325 	return (0);
326 }
327 
328 static int
hme_sbus_resume(device_t dev)329 hme_sbus_resume(device_t dev)
330 {
331 	struct hme_sbus_softc *hsc;
332 
333 	hsc = device_get_softc(dev);
334 	hme_resume(&hsc->hsc_hme);
335 	return (0);
336 }
337