slhci_intio.c revision 1.2
1/*	$NetBSD: slhci_intio.c,v 1.2 2002/09/27 20:37:20 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tetsuya Isaki.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *      This product includes software developed by the NetBSD
21 *      Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 *    contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * USB part of Nereid Ethernet/USB/Memory board
41 */
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/device.h>
46
47#include <machine/bus.h>
48#include <machine/cpu.h>
49
50#include <dev/usb/usb.h>
51#include <dev/usb/usbdi.h>
52#include <dev/usb/usbdivar.h>
53
54#include <dev/ic/sl811hsreg.h>
55#include <dev/ic/sl811hsvar.h>
56
57#include <arch/x68k/dev/intiovar.h>
58
59#include <arch/x68k/dev/slhci_intio_var.h>
60
61static int  slhci_intio_match(struct device *, struct cfdata *, void *);
62static void slhci_intio_attach(struct device *, struct device *, void *);
63static void slhci_intio_enable_power(void *, int);
64static void slhci_intio_enable_intr(void *, int);
65static int  slhci_intio_intr(void *);
66
67const struct cfattach slhci_intio_ca = {
68	sizeof(struct slhci_intio_softc), slhci_intio_match, slhci_intio_attach
69};
70
71static int
72slhci_intio_match(struct device *parent, struct cfdata *cf, void *aux)
73{
74	struct intio_attach_args *ia = aux;
75	bus_space_tag_t iot = ia->ia_bst;
76	bus_space_handle_t ioh;
77	bus_space_handle_t nch;
78	int nc_addr;
79	int nc_size;
80
81	if (ia->ia_addr == INTIOCF_ADDR_DEFAULT)
82		ia->ia_addr = SLHCI_INTIO_ADDR1;
83	if (ia->ia_intr == INTIOCF_INTR_DEFAULT)
84		ia->ia_intr = SLHCI_INTIO_INTR1;
85
86	/* fixed parameters */
87	if ( !(ia->ia_addr == SLHCI_INTIO_ADDR1 &&
88	       ia->ia_intr == SLHCI_INTIO_INTR1   ) &&
89	     !(ia->ia_addr == SLHCI_INTIO_ADDR2 &&
90	       ia->ia_intr == SLHCI_INTIO_INTR2   ) )
91		return 0;
92
93	/* Whether the control port is accessible or not */
94	nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET;
95	nc_size = 0x02;
96	if (badbaddr((caddr_t)INTIO_ADDR(nc_addr)))
97		return 0;
98
99	/* Map two I/O spaces */
100	ia->ia_size = SL11_PORTSIZE * 2;
101	if (bus_space_map(iot, ia->ia_addr, ia->ia_size,
102			BUS_SPACE_MAP_SHIFTED, &ioh))
103		return 0;
104
105	if (bus_space_map(iot, nc_addr, nc_size,
106			BUS_SPACE_MAP_SHIFTED, &nch))
107		return 0;
108
109	bus_space_unmap(iot, ioh, ia->ia_size);
110	bus_space_unmap(iot, nch, nc_size);
111
112	return 1;
113}
114
115static void
116slhci_intio_attach(struct device *parent, struct device *self, void *aux)
117{
118	struct slhci_intio_softc *sc = (struct slhci_intio_softc *)self;
119	struct intio_attach_args *ia = aux;
120	bus_space_tag_t iot = ia->ia_bst;
121	bus_space_handle_t ioh;
122	int nc_addr;
123	int nc_size;
124
125	printf(": Nereid USB\n");
126
127	/* Map I/O space */
128	if (bus_space_map(iot, ia->ia_addr, SL11_PORTSIZE * 2,
129			BUS_SPACE_MAP_SHIFTED, &ioh)) {
130		printf("%s: can't map I/O space\n",
131			sc->sc_sc.sc_bus.bdev.dv_xname);
132		return;
133	}
134
135	nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET;
136	nc_size = 0x02;
137	if (bus_space_map(iot, nc_addr, nc_size,
138			BUS_SPACE_MAP_SHIFTED, &sc->sc_nch)) {
139		printf("%s: can't map I/O control space\n",
140			sc->sc_sc.sc_bus.bdev.dv_xname);
141		return;
142	}
143
144	/* Initialize sc */
145	sc->sc_sc.sc_iot = iot;
146	sc->sc_sc.sc_ioh = ioh;
147	sc->sc_sc.sc_dmat = ia->ia_dmat;
148	sc->sc_sc.sc_enable_power = slhci_intio_enable_power;
149	sc->sc_sc.sc_enable_intr  = slhci_intio_enable_intr;
150	sc->sc_sc.sc_arg = sc;
151
152	/* Establish the interrupt handler */
153	if (intio_intr_establish(ia->ia_intr, "slhci", slhci_intio_intr, sc)) {
154		printf("%s: can't establish interrupt\n",
155			sc->sc_sc.sc_bus.bdev.dv_xname);
156		return;
157	}
158
159	/* Reset controller */
160	bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL, NEREID_CTRL_RESET);
161	delay(40000);
162
163	/* Attach SL811HS/T */
164	if (slhci_attach(&sc->sc_sc, self))
165		return;
166}
167
168static void
169slhci_intio_enable_power(void *arg, int mode)
170{
171	struct slhci_intio_softc *sc = arg;
172	bus_space_tag_t iot = sc->sc_sc.sc_iot;
173	u_int8_t r;
174
175	r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL);
176	if (mode == POWER_ON)
177		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
178			r |  NEREID_CTRL_POWER);
179	else
180		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
181			r & ~NEREID_CTRL_POWER);
182}
183
184static void
185slhci_intio_enable_intr(void *arg, int mode)
186{
187	struct slhci_intio_softc *sc = arg;
188	bus_space_tag_t iot = sc->sc_sc.sc_iot;
189	u_int8_t r;
190
191	r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL);
192	if (mode == INTR_ON)
193		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
194			r |  NEREID_CTRL_INTR);
195	else
196		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
197			r & ~NEREID_CTRL_INTR);
198}
199
200static int
201slhci_intio_intr(void *arg)
202{
203	struct slhci_intio_softc *sc = arg;
204
205	return slhci_intr(&sc->sc_sc);
206}
207