xref: /netbsd-src/sys/arch/arm/at91/at91ohci.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$Id: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $	*/
2*c7fb772bSthorpej /*	$NetBSD: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $	*/
3c62a0ac4Smatt 
4c62a0ac4Smatt /*-
5c62a0ac4Smatt  * Copyright (c) 2007 Embedtronics Oy.
6c62a0ac4Smatt  * All rights reserved.
7c62a0ac4Smatt  *
8c62a0ac4Smatt  * Based on arch/arm/ep93xx/epohci.c,
9c62a0ac4Smatt  * Copyright (c) 2004 Jesse Off
10c62a0ac4Smatt  * All rights reserved.
11c62a0ac4Smatt  *
12c62a0ac4Smatt  * Redistribution and use in source and binary forms, with or without
13c62a0ac4Smatt  * modification, are permitted provided that the following conditions
14c62a0ac4Smatt  * are met:
15c62a0ac4Smatt  * 1. Redistributions of source code must retain the above copyright
16c62a0ac4Smatt  *    notice, this list of conditions and the following disclaimer.
17c62a0ac4Smatt  * 2. Redistributions in binary form must reproduce the above copyright
18c62a0ac4Smatt  *    notice, this list of conditions and the following disclaimer in the
19c62a0ac4Smatt  *    documentation and/or other materials provided with the distribution.
20c62a0ac4Smatt  *
21c62a0ac4Smatt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22c62a0ac4Smatt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c62a0ac4Smatt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c62a0ac4Smatt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25c62a0ac4Smatt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c62a0ac4Smatt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c62a0ac4Smatt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c62a0ac4Smatt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c62a0ac4Smatt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c62a0ac4Smatt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c62a0ac4Smatt  * SUCH DAMAGE.
32c62a0ac4Smatt  */
33c62a0ac4Smatt 
34c62a0ac4Smatt /*
35c62a0ac4Smatt  * USB Open Host Controller driver.
36c62a0ac4Smatt  *
37c62a0ac4Smatt  * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe
38c62a0ac4Smatt  * USB spec: http://www.usb.org/developers/data/usb11.pdf
39c62a0ac4Smatt  */
40c62a0ac4Smatt 
41c62a0ac4Smatt #include <sys/cdefs.h>
42*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: at91ohci.c,v 1.9 2021/08/07 16:18:43 thorpej Exp $");
43c62a0ac4Smatt 
44c62a0ac4Smatt #include <sys/param.h>
45c62a0ac4Smatt #include <sys/systm.h>
46c62a0ac4Smatt #include <sys/kernel.h>
47c62a0ac4Smatt #include <sys/device.h>
48c62a0ac4Smatt #include <sys/proc.h>
49c62a0ac4Smatt #include <sys/queue.h>
50c62a0ac4Smatt 
51c62a0ac4Smatt /* busdma */
52c62a0ac4Smatt #include <sys/mbuf.h>
53c62a0ac4Smatt #include <uvm/uvm_extern.h>
54c62a0ac4Smatt 
55cf10107dSdyoung #include <sys/bus.h>
56c62a0ac4Smatt 
57c62a0ac4Smatt #include <dev/usb/usb.h>
58c62a0ac4Smatt #include <dev/usb/usbdi.h>
59c62a0ac4Smatt #include <dev/usb/usbdivar.h>
60c62a0ac4Smatt #include <dev/usb/usb_mem.h>
61c62a0ac4Smatt 
62c62a0ac4Smatt #include <dev/usb/ohcireg.h>
63c62a0ac4Smatt #include <dev/usb/ohcivar.h>
64c62a0ac4Smatt 
65c62a0ac4Smatt #include <arm/at91/at91reg.h>
66c62a0ac4Smatt #include <arm/at91/at91var.h>
67c62a0ac4Smatt 
68c62a0ac4Smatt int at91ohci_match(device_t, cfdata_t, void *);
69c62a0ac4Smatt void at91ohci_attach(device_t, device_t, void *);
70c62a0ac4Smatt void at91ohci_callback(device_t );
71c62a0ac4Smatt 
72c62a0ac4Smatt struct at91ohci_softc {
73c62a0ac4Smatt 	struct ohci_softc sc;
74c62a0ac4Smatt 	void	*sc_ih;
75c62a0ac4Smatt 	int	sc_pid;
76c62a0ac4Smatt };
77c62a0ac4Smatt 
78b3352941Saymeric CFATTACH_DECL_NEW(at91ohci, sizeof(struct at91ohci_softc),
79c62a0ac4Smatt     at91ohci_match, at91ohci_attach, NULL, NULL);
80c62a0ac4Smatt 
81c62a0ac4Smatt int
at91ohci_match(device_t parent,cfdata_t match,void * aux)82c62a0ac4Smatt at91ohci_match(device_t parent, cfdata_t match, void *aux)
83c62a0ac4Smatt {
84c62a0ac4Smatt 	/* AT91X builtin OHCI module */
85c62a0ac4Smatt 	if (strcmp(match->cf_name, "ohci") == 0 && strcmp(match->cf_atname, "at91ohci") == 0)
864e8e6643Sskrll 		return 2;
87c62a0ac4Smatt 	return(0);
88c62a0ac4Smatt }
89c62a0ac4Smatt 
90c62a0ac4Smatt void
at91ohci_attach(device_t parent,device_t self,void * aux)91c62a0ac4Smatt at91ohci_attach(device_t parent, device_t self, void *aux)
92c62a0ac4Smatt {
93b3352941Saymeric 	struct at91ohci_softc *sc = device_private(self);
94c62a0ac4Smatt 	struct at91bus_attach_args *sa = aux;
95c62a0ac4Smatt 
96b3352941Saymeric 	sc->sc.sc_dev = self;
974e8e6643Sskrll 	sc->sc.sc_bus.ub_hcpriv = sc;
984e8e6643Sskrll 	sc->sc.sc_bus.ub_dmatag = sa->sa_dmat;
99b3352941Saymeric 	sc->sc.iot = sa->sa_iot;
100c62a0ac4Smatt 	sc->sc_pid = sa->sa_pid;
101c62a0ac4Smatt 
102c62a0ac4Smatt 	/* Map I/O space */
103c62a0ac4Smatt 	if (bus_space_map(sc->sc.iot, sa->sa_addr, sa->sa_size,
104c62a0ac4Smatt 			  0, &sc->sc.ioh)) {
105c62a0ac4Smatt 		printf(": cannot map mem space\n");
106c62a0ac4Smatt 		return;
107c62a0ac4Smatt 	}
108c62a0ac4Smatt 
109b3352941Saymeric 	sc->sc.sc_size = sa->sa_size;
110b3352941Saymeric 
111c62a0ac4Smatt 	/* enable peripheral clock */
112c62a0ac4Smatt 	at91_peripheral_clock(sc->sc_pid, 1);
113c62a0ac4Smatt 
114c62a0ac4Smatt 	printf("\n");
115c62a0ac4Smatt 
116c62a0ac4Smatt         /* Defer the rest until later */
117c62a0ac4Smatt         config_defer(self, at91ohci_callback);
118c62a0ac4Smatt }
119c62a0ac4Smatt 
120c62a0ac4Smatt void
at91ohci_callback(device_t self)121454af1c0Sdsl at91ohci_callback(device_t self)
122c62a0ac4Smatt {
123b3352941Saymeric 	struct at91ohci_softc *sc = device_private(self);
124c62a0ac4Smatt 
125c62a0ac4Smatt 	/* Disable interrupts, so we don't get any spurious ones. */
126c62a0ac4Smatt 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
127c62a0ac4Smatt 			  OHCI_ALL_INTRS);
128c62a0ac4Smatt 
129c62a0ac4Smatt 	sc->sc_ih = at91_intr_establish(sc->sc_pid, IPL_USB, INTR_HIGH_LEVEL, ohci_intr, sc);
1304e8e6643Sskrll 	int err = ohci_init(&sc->sc);
131c62a0ac4Smatt 
1324e8e6643Sskrll 	if (err) {
1334e8e6643Sskrll 		printf("%s: init failed, error=%d\n", device_xname(self), err);
134c62a0ac4Smatt 
135c62a0ac4Smatt 		at91_intr_disestablish(sc->sc_ih);
136c62a0ac4Smatt 		return;
137c62a0ac4Smatt 	}
138c62a0ac4Smatt 
139c62a0ac4Smatt 	/* Attach usb device. */
1402685996bSthorpej 	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint,
141*c7fb772bSthorpej 	    CFARGS_NONE);
142c62a0ac4Smatt }
143