auxio.c revision 136301
1136301Syongari/*-
2136301Syongari * Copyright (c) 2004 Pyun YongHyeon
3136301Syongari * All rights reserved.
4136301Syongari *
5136301Syongari * Redistribution and use in source and binary forms, with or without
6136301Syongari * modification, are permitted provided that the following conditions
7136301Syongari * are met:
8136301Syongari * 1. Redistributions of source code must retain the above copyright
9136301Syongari *    notice, this list of conditions and the following disclaimer.
10136301Syongari * 2. Redistributions in binary form must reproduce the above copyright
11136301Syongari *    notice, this list of conditions and the following disclaimer in the
12136301Syongari *    documentation and/or other materials provided with the distribution.
13136301Syongari *
14136301Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15136301Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16136301Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17136301Syongari * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18136301Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19136301Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20136301Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21136301Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22136301Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23136301Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24136301Syongari * SUCH DAMAGE.
25136301Syongari *
26136301Syongari */
27136301Syongari
28136301Syongari/*	$NetBSD: auxio.c,v 1.11 2003/07/15 03:36:04 lukem Exp $	*/
29136301Syongari
30136301Syongari/*
31136301Syongari * Copyright (c) 2000, 2001 Matthew R. Green
32136301Syongari * All rights reserved.
33136301Syongari *
34136301Syongari * Redistribution and use in source and binary forms, with or without
35136301Syongari * modification, are permitted provided that the following conditions
36136301Syongari * are met:
37136301Syongari * 1. Redistributions of source code must retain the above copyright
38136301Syongari *    notice, this list of conditions and the following disclaimer.
39136301Syongari * 2. Redistributions in binary form must reproduce the above copyright
40136301Syongari *    notice, this list of conditions and the following disclaimer in the
41136301Syongari *    documentation and/or other materials provided with the distribution.
42136301Syongari * 3. The name of the author may not be used to endorse or promote products
43136301Syongari *    derived from this software without specific prior written permission.
44136301Syongari *
45136301Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46136301Syongari * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47136301Syongari * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48136301Syongari * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49136301Syongari * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
50136301Syongari * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51136301Syongari * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
52136301Syongari * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
53136301Syongari * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54136301Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55136301Syongari * SUCH DAMAGE.
56136301Syongari */
57136301Syongari
58136301Syongari/*
59136301Syongari * AUXIO registers support on the sbus & ebus2, used for the floppy driver
60136301Syongari * and to control the system LED, for the BLINK option.
61136301Syongari */
62136301Syongari
63136301Syongari#include <sys/cdefs.h>
64136301Syongari__FBSDID("$FreeBSD: head/sys/dev/auxio/auxio.c 136301 2004-10-09 07:31:03Z yongari $");
65136301Syongari
66136301Syongari#include <sys/param.h>
67136301Syongari#include <sys/systm.h>
68136301Syongari#include <sys/bus.h>
69136301Syongari#include <sys/kernel.h>
70136301Syongari#include <sys/lock.h>
71136301Syongari#include <sys/module.h>
72136301Syongari#include <sys/mutex.h>
73136301Syongari#include <sys/resource.h>
74136301Syongari#include <sys/rman.h>
75136301Syongari
76136301Syongari#include <dev/led/led.h>
77136301Syongari#include <dev/ofw/ofw_bus.h>
78136301Syongari#include <dev/ofw/openfirm.h>
79136301Syongari
80136301Syongari#include <machine/bus.h>
81136301Syongari#include <machine/ofw_machdep.h>
82136301Syongari#include <machine/resource.h>
83136301Syongari
84136301Syongari#include <sparc64/sbus/sbusvar.h>
85136301Syongari#include <dev/auxio/auxioreg.h>
86136301Syongari
87136301Syongari/*
88136301Syongari * on sun4u, auxio exists with one register (LED) on the sbus, and 5
89136301Syongari * registers on the ebus2 (pci) (LED, PCIMODE, FREQUENCY, SCSI
90136301Syongari * OSCILLATOR, and TEMP SENSE.
91136301Syongari */
92136301Syongari
93136301Syongari#define AUXIO_PCIO_LED	0
94136301Syongari#define AUXIO_PCIO_PCI	1
95136301Syongari#define AUXIO_PCIO_FREQ	2
96136301Syongari#define AUXIO_PCIO_OSC	3
97136301Syongari#define AUXIO_PCIO_TEMP	4
98136301Syongari#define AUXIO_PCIO_MAX	8
99136301Syongari
100136301Syongaristruct auxio_softc {
101136301Syongari	struct device		*sc_dev;
102136301Syongari
103136301Syongari	int			sc_nauxio;
104136301Syongari	struct resource		*sc_res[AUXIO_PCIO_MAX];
105136301Syongari	int			sc_rid[AUXIO_PCIO_MAX];
106136301Syongari	bus_space_tag_t		sc_regt[AUXIO_PCIO_MAX];
107136301Syongari	bus_space_handle_t	sc_regh[AUXIO_PCIO_MAX];
108136301Syongari	struct cdev		*sc_led_dev;
109136301Syongari	u_int32_t		sc_led_stat;
110136301Syongari
111136301Syongari	int			sc_flags;
112136301Syongari#define	AUXIO_LEDONLY		0x1
113136301Syongari#define	AUXIO_EBUS		0x2
114136301Syongari#define	AUXIO_SBUS		0x4
115136301Syongari
116136301Syongari	struct mtx		sc_lock;
117136301Syongari};
118136301Syongari
119136301Syongaristatic void	auxio_led_func(void *arg, int onoff);
120136301Syongaristatic void	auxio_attach_common(struct auxio_softc *);
121136301Syongaristatic int	auxio_bus_probe(device_t);
122136301Syongaristatic int	auxio_sbus_attach(device_t);
123136301Syongaristatic int	auxio_ebus_attach(device_t);
124136301Syongaristatic int	auxio_bus_detach(device_t);
125136301Syongaristatic void	auxio_free_resource(struct auxio_softc *);
126136301Syongaristatic __inline u_int32_t auxio_led_read(struct auxio_softc *);
127136301Syongaristatic __inline void auxio_led_write(struct auxio_softc *, u_int32_t);
128136301Syongari
129136301Syongari/* SBus */
130136301Syongaristatic device_method_t auxio_sbus_methods[] = {
131136301Syongari	DEVMETHOD(device_probe,		auxio_bus_probe),
132136301Syongari	DEVMETHOD(device_attach,	auxio_sbus_attach),
133136301Syongari	DEVMETHOD(device_detach,	auxio_bus_detach),
134136301Syongari	{0, 0}
135136301Syongari};
136136301Syongari
137136301Syongaristatic driver_t auxio_sbus_driver = {
138136301Syongari	"auxio",
139136301Syongari	auxio_sbus_methods,
140136301Syongari	sizeof(struct auxio_softc)
141136301Syongari};
142136301Syongari
143136301Syongaristatic devclass_t	auxio_devclass;
144136301SyongariDRIVER_MODULE(auxio, sbus, auxio_sbus_driver, auxio_devclass, 0, 0);
145136301Syongari
146136301Syongari/* EBus */
147136301Syongaristatic device_method_t auxio_ebus_methods[] = {
148136301Syongari	DEVMETHOD(device_probe,		auxio_bus_probe),
149136301Syongari	DEVMETHOD(device_attach,	auxio_ebus_attach),
150136301Syongari	DEVMETHOD(device_detach,	auxio_bus_detach),
151136301Syongari	{0, 0}
152136301Syongari};
153136301Syongari
154136301Syongaristatic driver_t auxio_ebus_driver = {
155136301Syongari	"auxio",
156136301Syongari	auxio_ebus_methods,
157136301Syongari	sizeof(struct auxio_softc)
158136301Syongari};
159136301Syongari
160136301SyongariDRIVER_MODULE(auxio, ebus, auxio_ebus_driver, auxio_devclass, 0, 0);
161136301SyongariMODULE_VERSION(auxio, 1);
162136301Syongari
163136301Syongari#define AUXIO_LOCK_INIT(sc)	\
164136301Syongari	mtx_init(&sc->sc_lock, "auxio mtx", NULL, MTX_DEF)
165136301Syongari#define AUXIO_LOCK(sc)		mtx_lock(&sc->sc_lock)
166136301Syongari#define AUXIO_UNLOCK(sc)	mtx_unlock(&sc->sc_lock)
167136301Syongari#define AUXIO_LOCK_DESTROY(sc)	mtx_destroy(&sc->sc_lock)
168136301Syongari
169136301Syongaristatic __inline void
170136301Syongariauxio_led_write(struct auxio_softc *sc, u_int32_t v)
171136301Syongari{
172136301Syongari	if (sc->sc_flags & AUXIO_EBUS)
173136301Syongari		bus_space_write_4(sc->sc_regt[AUXIO_PCIO_LED],
174136301Syongari		    sc->sc_regh[AUXIO_PCIO_LED], 0, v);
175136301Syongari	else
176136301Syongari		bus_space_write_1(sc->sc_regt[AUXIO_PCIO_LED],
177136301Syongari		    sc->sc_regh[AUXIO_PCIO_LED], 0, v);
178136301Syongari}
179136301Syongari
180136301Syongaristatic __inline u_int32_t
181136301Syongariauxio_led_read(struct auxio_softc *sc)
182136301Syongari{
183136301Syongari	u_int32_t led;
184136301Syongari
185136301Syongari	if (sc->sc_flags & AUXIO_EBUS)
186136301Syongari		led = bus_space_read_4(sc->sc_regt[AUXIO_PCIO_LED],
187136301Syongari		    sc->sc_regh[AUXIO_PCIO_LED], 0);
188136301Syongari	else
189136301Syongari		led = bus_space_read_1(sc->sc_regt[AUXIO_PCIO_LED],
190136301Syongari		    sc->sc_regh[AUXIO_PCIO_LED], 0);
191136301Syongari
192136301Syongari	return (led);
193136301Syongari}
194136301Syongari
195136301Syongaristatic void
196136301Syongariauxio_led_func(void *arg, int onoff)
197136301Syongari{
198136301Syongari	struct auxio_softc *sc;
199136301Syongari	u_int32_t led;
200136301Syongari
201136301Syongari	sc = (struct auxio_softc *)arg;
202136301Syongari
203136301Syongari	led = onoff ? AUXIO_LED_LED : 0;
204136301Syongari	AUXIO_LOCK(sc);
205136301Syongari	auxio_led_write(sc, led);
206136301Syongari	AUXIO_UNLOCK(sc);
207136301Syongari}
208136301Syongari
209136301Syongaristatic int
210136301Syongariauxio_bus_probe(device_t dev)
211136301Syongari{
212136301Syongari	const char *name;
213136301Syongari
214136301Syongari	name = ofw_bus_get_name(dev);
215136301Syongari	if (strcmp("auxio", name) == 0) {
216136301Syongari		device_set_desc(dev, "Sun Auxiliary I/O");
217136301Syongari		return (0);
218136301Syongari	}
219136301Syongari
220136301Syongari	return (ENXIO);
221136301Syongari}
222136301Syongari
223136301Syongaristatic int
224136301Syongariauxio_ebus_attach(device_t dev)
225136301Syongari{
226136301Syongari	struct auxio_softc *sc;
227136301Syongari	struct resource *res;
228136301Syongari	u_long start, count;
229136301Syongari	int i;
230136301Syongari
231136301Syongari	sc = device_get_softc(dev);
232136301Syongari	bzero(sc, sizeof(*sc));
233136301Syongari	sc->sc_dev = dev;
234136301Syongari
235136301Syongari	AUXIO_LOCK_INIT(sc);
236136301Syongari	sc->sc_nauxio = AUXIO_PCIO_MAX;
237136301Syongari	sc->sc_flags = AUXIO_LEDONLY | AUXIO_EBUS;
238136301Syongari	for (i = 0;
239136301Syongari	    i < AUXIO_PCIO_MAX &&
240136301Syongari	    bus_get_resource(dev, SYS_RES_IOPORT, i, &start, &count) == 0;
241136301Syongari             i++) {
242136301Syongari		sc->sc_rid[i] = i;
243136301Syongari		if (bootverbose)
244136301Syongari			device_printf(sc->sc_dev,
245136301Syongari			    "Got rid %d, start %#lx, count %#lx\n",
246136301Syongari			    i, start, count);
247136301Syongari		res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
248136301Syongari		    &sc->sc_rid[i], RF_ACTIVE);
249136301Syongari		if (res == NULL) {
250136301Syongari			device_printf(sc->sc_dev,
251136301Syongari			    "could not allocate resources\n");
252136301Syongari			goto attach_fail;
253136301Syongari		}
254136301Syongari		sc->sc_res[i] = res;
255136301Syongari		sc->sc_regt[i] = rman_get_bustag(res);
256136301Syongari		sc->sc_regh[i] = rman_get_bushandle(res);
257136301Syongari	}
258136301Syongari	sc->sc_nauxio = i;
259136301Syongari	auxio_attach_common(sc);
260136301Syongari
261136301Syongari	return (0);
262136301Syongari
263136301Syongariattach_fail:
264136301Syongari	auxio_free_resource(sc);
265136301Syongari
266136301Syongari	return (ENXIO);
267136301Syongari}
268136301Syongari
269136301Syongaristatic void
270136301Syongariauxio_attach_common(struct auxio_softc *sc)
271136301Syongari{
272136301Syongari	sc->sc_led_stat = auxio_led_read(sc);
273136301Syongari	sc->sc_led_dev = led_create(auxio_led_func, sc, "auxioled");
274136301Syongari	/* turn on the LED */
275136301Syongari	auxio_led_func(sc, 1);
276136301Syongari}
277136301Syongari
278136301Syongaristatic int
279136301Syongariauxio_bus_detach(device_t dev)
280136301Syongari{
281136301Syongari	struct auxio_softc *sc;
282136301Syongari
283136301Syongari	sc = device_get_softc(dev);
284136301Syongari	led_destroy(sc->sc_led_dev);
285136301Syongari	auxio_led_func(sc, sc->sc_led_stat);
286136301Syongari	auxio_free_resource(sc);
287136301Syongari
288136301Syongari	return (0);
289136301Syongari}
290136301Syongari
291136301Syongaristatic void
292136301Syongariauxio_free_resource(struct auxio_softc *sc)
293136301Syongari{
294136301Syongari	int i, n;
295136301Syongari
296136301Syongari	n = sc->sc_nauxio;
297136301Syongari	for (i = 0; i < n; i++)
298136301Syongari		if (sc->sc_res[i])
299136301Syongari			bus_release_resource(sc->sc_dev,
300136301Syongari			    (sc->sc_flags & AUXIO_SBUS) ? SYS_RES_MEMORY :
301136301Syongari			    SYS_RES_IOPORT, sc->sc_rid[i], sc->sc_res[i]);
302136301Syongari	AUXIO_LOCK_DESTROY(sc);
303136301Syongari}
304136301Syongari
305136301Syongaristatic int
306136301Syongariauxio_sbus_attach(device_t dev)
307136301Syongari{
308136301Syongari	struct auxio_softc *sc;
309136301Syongari	struct resource *res;
310136301Syongari
311136301Syongari	sc = device_get_softc(dev);
312136301Syongari	bzero(sc, sizeof(*sc));
313136301Syongari	sc->sc_dev = dev;
314136301Syongari
315136301Syongari	AUXIO_LOCK_INIT(sc);
316136301Syongari	sc->sc_nauxio = 1;
317136301Syongari	sc->sc_flags = AUXIO_LEDONLY | AUXIO_SBUS;
318136301Syongari	sc->sc_rid[AUXIO_PCIO_LED] = 0;
319136301Syongari	res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
320136301Syongari	    &sc->sc_rid[AUXIO_PCIO_LED], RF_ACTIVE);
321136301Syongari	if (res == NULL) {
322136301Syongari		device_printf(sc->sc_dev, "could not allocate resources\n");
323136301Syongari		goto attach_fail;
324136301Syongari	}
325136301Syongari	sc->sc_res[AUXIO_PCIO_LED] = res;
326136301Syongari	sc->sc_regt[AUXIO_PCIO_LED] = rman_get_bustag(res);
327136301Syongari	sc->sc_regh[AUXIO_PCIO_LED] = rman_get_bushandle(res);
328136301Syongari	auxio_attach_common(sc);
329136301Syongari	return (0);
330136301Syongari
331136301Syongariattach_fail:
332136301Syongari	auxio_free_resource(sc);
333136301Syongari
334136301Syongari	return (ENXIO);
335136301Syongari}
336