xref: /netbsd-src/sys/arch/x68k/dev/slhci_intio.c (revision 6b664a713479c31d4f17b38b42182a5d5fa21802)
1*6b664a71Sisaki /*	$NetBSD: slhci_intio.c,v 1.16 2024/01/07 07:58:33 isaki Exp $	*/
2dd0e0396Sisaki 
3dd0e0396Sisaki /*
4dd0e0396Sisaki  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5dd0e0396Sisaki  * All rights reserved.
6dd0e0396Sisaki  *
7dd0e0396Sisaki  * This code is derived from software contributed to The NetBSD Foundation
8dd0e0396Sisaki  * by Tetsuya Isaki.
9dd0e0396Sisaki  *
10dd0e0396Sisaki  * Redistribution and use in source and binary forms, with or without
11dd0e0396Sisaki  * modification, are permitted provided that the following conditions
12dd0e0396Sisaki  * are met:
13dd0e0396Sisaki  * 1. Redistributions of source code must retain the above copyright
14dd0e0396Sisaki  *    notice, this list of conditions and the following disclaimer.
15dd0e0396Sisaki  * 2. Redistributions in binary form must reproduce the above copyright
16dd0e0396Sisaki  *    notice, this list of conditions and the following disclaimer in the
17dd0e0396Sisaki  *    documentation and/or other materials provided with the distribution.
18dd0e0396Sisaki  *
19dd0e0396Sisaki  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20dd0e0396Sisaki  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21dd0e0396Sisaki  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22dd0e0396Sisaki  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23dd0e0396Sisaki  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24dd0e0396Sisaki  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25dd0e0396Sisaki  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26dd0e0396Sisaki  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27dd0e0396Sisaki  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28dd0e0396Sisaki  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29dd0e0396Sisaki  * POSSIBILITY OF SUCH DAMAGE.
30dd0e0396Sisaki  */
31dd0e0396Sisaki 
32dd0e0396Sisaki /*
33dd0e0396Sisaki  * USB part of Nereid Ethernet/USB/Memory board
34dd0e0396Sisaki  */
35dd0e0396Sisaki 
36ab48a212Slukem #include <sys/cdefs.h>
37*6b664a71Sisaki __KERNEL_RCSID(0, "$NetBSD: slhci_intio.c,v 1.16 2024/01/07 07:58:33 isaki Exp $");
38ab48a212Slukem 
39dd0e0396Sisaki #include <sys/param.h>
40dd0e0396Sisaki #include <sys/systm.h>
41dd0e0396Sisaki #include <sys/device.h>
42dd0e0396Sisaki 
43dd0e0396Sisaki #include <machine/bus.h>
44dd0e0396Sisaki #include <machine/cpu.h>
45dd0e0396Sisaki 
46dd0e0396Sisaki #include <dev/usb/usb.h>
47dd0e0396Sisaki #include <dev/usb/usbdi.h>
48dd0e0396Sisaki #include <dev/usb/usbdivar.h>
49dd0e0396Sisaki 
50dd0e0396Sisaki #include <dev/ic/sl811hsreg.h>
51dd0e0396Sisaki #include <dev/ic/sl811hsvar.h>
52dd0e0396Sisaki 
53dd0e0396Sisaki #include <arch/x68k/dev/intiovar.h>
54dd0e0396Sisaki 
55dd0e0396Sisaki #include <arch/x68k/dev/slhci_intio_var.h>
56dd0e0396Sisaki 
575fc34baaSisaki static int  slhci_intio_match(device_t, cfdata_t, void *);
585fc34baaSisaki static void slhci_intio_attach(device_t, device_t, void *);
5944c89c76Skiyohara static void slhci_intio_enable_power(void *, enum power_change);
60dd0e0396Sisaki static void slhci_intio_enable_intr(void *, int);
61dd0e0396Sisaki 
625fc34baaSisaki CFATTACH_DECL_NEW(slhci_intio, sizeof(struct slhci_intio_softc),
634bf871a7Sthorpej     slhci_intio_match, slhci_intio_attach, NULL, NULL);
64dd0e0396Sisaki 
6544c89c76Skiyohara #define INTR_ON 	1
6644c89c76Skiyohara #define INTR_OFF	0
6744c89c76Skiyohara 
68dd0e0396Sisaki static int
slhci_intio_match(device_t parent,cfdata_t cf,void * aux)695fc34baaSisaki slhci_intio_match(device_t parent, cfdata_t cf, void *aux)
70dd0e0396Sisaki {
71dd0e0396Sisaki 	struct intio_attach_args *ia = aux;
72dd0e0396Sisaki 	bus_space_tag_t iot = ia->ia_bst;
73dd0e0396Sisaki 	bus_space_handle_t ioh;
74dd0e0396Sisaki 	bus_space_handle_t nch;
75dd0e0396Sisaki 	int nc_addr;
76dd0e0396Sisaki 	int nc_size;
77dd0e0396Sisaki 
78dd0e0396Sisaki 	if (ia->ia_addr == INTIOCF_ADDR_DEFAULT)
79dd0e0396Sisaki 		ia->ia_addr = SLHCI_INTIO_ADDR1;
80dd0e0396Sisaki 	if (ia->ia_intr == INTIOCF_INTR_DEFAULT)
81dd0e0396Sisaki 		ia->ia_intr = SLHCI_INTIO_INTR1;
82dd0e0396Sisaki 
83dd0e0396Sisaki 	/* fixed parameters */
84dd0e0396Sisaki 	if ( !(ia->ia_addr == SLHCI_INTIO_ADDR1 &&
85dd0e0396Sisaki 	       ia->ia_intr == SLHCI_INTIO_INTR1   ) &&
86dd0e0396Sisaki 	     !(ia->ia_addr == SLHCI_INTIO_ADDR2 &&
87dd0e0396Sisaki 	       ia->ia_intr == SLHCI_INTIO_INTR2   ) )
88dd0e0396Sisaki 		return 0;
89dd0e0396Sisaki 
9009e97aa9Sisaki 	/* Whether the SL811 port is accessible or not */
9109e97aa9Sisaki 	if (badaddr((void *)IIOV(ia->ia_addr)))
9209e97aa9Sisaki 		return 0;
9309e97aa9Sisaki 
94dd0e0396Sisaki 	/* Whether the control port is accessible or not */
95dd0e0396Sisaki 	nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET;
96dd0e0396Sisaki 	nc_size = 0x02;
973b878f89Sisaki 	if (badbaddr((void *)IIOV(nc_addr)))
98dd0e0396Sisaki 		return 0;
99dd0e0396Sisaki 
100dd0e0396Sisaki 	/* Map two I/O spaces */
101dd0e0396Sisaki 	ia->ia_size = SL11_PORTSIZE * 2;
102dd0e0396Sisaki 	if (bus_space_map(iot, ia->ia_addr, ia->ia_size,
103dd0e0396Sisaki 			BUS_SPACE_MAP_SHIFTED, &ioh))
104dd0e0396Sisaki 		return 0;
105dd0e0396Sisaki 
106dd0e0396Sisaki 	if (bus_space_map(iot, nc_addr, nc_size,
107dd0e0396Sisaki 			BUS_SPACE_MAP_SHIFTED, &nch))
108dd0e0396Sisaki 		return 0;
109dd0e0396Sisaki 
110dd0e0396Sisaki 	bus_space_unmap(iot, ioh, ia->ia_size);
111dd0e0396Sisaki 	bus_space_unmap(iot, nch, nc_size);
112dd0e0396Sisaki 
113dd0e0396Sisaki 	return 1;
114dd0e0396Sisaki }
115dd0e0396Sisaki 
116dd0e0396Sisaki static void
slhci_intio_attach(device_t parent,device_t self,void * aux)1175fc34baaSisaki slhci_intio_attach(device_t parent, device_t self, void *aux)
118dd0e0396Sisaki {
1195fc34baaSisaki 	struct slhci_intio_softc *isc = device_private(self);
1205fc34baaSisaki 	struct slhci_softc *sc = &isc->sc_sc;
121dd0e0396Sisaki 	struct intio_attach_args *ia = aux;
122dd0e0396Sisaki 	bus_space_tag_t iot = ia->ia_bst;
123dd0e0396Sisaki 	bus_space_handle_t ioh;
124dd0e0396Sisaki 	int nc_addr;
125dd0e0396Sisaki 	int nc_size;
126dd0e0396Sisaki 
1275fc34baaSisaki 	sc->sc_dev = self;
1284e8e6643Sskrll 	sc->sc_bus.ub_hcpriv = sc;
1295fc34baaSisaki 
130dd0e0396Sisaki 	printf(": Nereid USB\n");
131dd0e0396Sisaki 
132dd0e0396Sisaki 	/* Map I/O space */
133dd0e0396Sisaki 	if (bus_space_map(iot, ia->ia_addr, SL11_PORTSIZE * 2,
134dd0e0396Sisaki 			BUS_SPACE_MAP_SHIFTED, &ioh)) {
135dd0e0396Sisaki 		printf("%s: can't map I/O space\n",
1365fc34baaSisaki 			device_xname(self));
137dd0e0396Sisaki 		return;
138dd0e0396Sisaki 	}
139dd0e0396Sisaki 
140dd0e0396Sisaki 	nc_addr = ia->ia_addr + NEREID_ADDR_OFFSET;
141dd0e0396Sisaki 	nc_size = 0x02;
142dd0e0396Sisaki 	if (bus_space_map(iot, nc_addr, nc_size,
1435fc34baaSisaki 			BUS_SPACE_MAP_SHIFTED, &isc->sc_nch)) {
144dd0e0396Sisaki 		printf("%s: can't map I/O control space\n",
1455fc34baaSisaki 			device_xname(self));
146dd0e0396Sisaki 		return;
147dd0e0396Sisaki 	}
148dd0e0396Sisaki 
149dd0e0396Sisaki 	/* Initialize sc */
1505fc34baaSisaki 	slhci_preinit(sc, slhci_intio_enable_power, iot, ioh, 30,
15144c89c76Skiyohara 	    SL11_IDX_DATA);
152dd0e0396Sisaki 
153dd0e0396Sisaki 	/* Establish the interrupt handler */
15444c89c76Skiyohara 	if (intio_intr_establish(ia->ia_intr, "slhci", slhci_intr, sc)) {
155dd0e0396Sisaki 		printf("%s: can't establish interrupt\n",
1565fc34baaSisaki 			device_xname(self));
157dd0e0396Sisaki 		return;
158dd0e0396Sisaki 	}
159dd0e0396Sisaki 
160dd0e0396Sisaki 	/* Reset controller */
1615fc34baaSisaki 	bus_space_write_1(iot, isc->sc_nch, NEREID_CTRL, NEREID_CTRL_RESET);
162dd0e0396Sisaki 	delay(40000);
163dd0e0396Sisaki 
16444c89c76Skiyohara 	slhci_intio_enable_intr(sc, INTR_ON);
16544c89c76Skiyohara 
166dd0e0396Sisaki 	/* Attach SL811HS/T */
1675fc34baaSisaki 	if (slhci_attach(sc))
168dd0e0396Sisaki 		return;
169dd0e0396Sisaki }
170dd0e0396Sisaki 
171dd0e0396Sisaki static void
slhci_intio_enable_power(void * arg,enum power_change mode)17244c89c76Skiyohara slhci_intio_enable_power(void *arg, enum power_change mode)
173dd0e0396Sisaki {
174dd0e0396Sisaki 	struct slhci_intio_softc *sc = arg;
175dd0e0396Sisaki 	bus_space_tag_t iot = sc->sc_sc.sc_iot;
176dd0e0396Sisaki 	u_int8_t r;
177dd0e0396Sisaki 
178dd0e0396Sisaki 	r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL);
179dd0e0396Sisaki 	if (mode == POWER_ON)
180dd0e0396Sisaki 		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
181dd0e0396Sisaki 			r |  NEREID_CTRL_POWER);
182dd0e0396Sisaki 	else
183dd0e0396Sisaki 		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
184dd0e0396Sisaki 			r & ~NEREID_CTRL_POWER);
185dd0e0396Sisaki }
186dd0e0396Sisaki 
187dd0e0396Sisaki static void
slhci_intio_enable_intr(void * arg,int mode)188dd0e0396Sisaki slhci_intio_enable_intr(void *arg, int mode)
189dd0e0396Sisaki {
190dd0e0396Sisaki 	struct slhci_intio_softc *sc = arg;
191dd0e0396Sisaki 	bus_space_tag_t iot = sc->sc_sc.sc_iot;
192dd0e0396Sisaki 	u_int8_t r;
193dd0e0396Sisaki 
194dd0e0396Sisaki 	r = bus_space_read_1(iot, sc->sc_nch, NEREID_CTRL);
195dd0e0396Sisaki 	if (mode == INTR_ON)
196dd0e0396Sisaki 		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
197dd0e0396Sisaki 			r |  NEREID_CTRL_INTR);
198dd0e0396Sisaki 	else
199dd0e0396Sisaki 		bus_space_write_1(iot, sc->sc_nch, NEREID_CTRL,
200dd0e0396Sisaki 			r & ~NEREID_CTRL_INTR);
201dd0e0396Sisaki }
202dd0e0396Sisaki 
203