xref: /openbsd/sys/arch/octeon/dev/octohci.c (revision 71696a07)
1*71696a07Sdlg /*	$OpenBSD: octohci.c,v 1.4 2019/01/07 03:41:06 dlg Exp $ */
2494889e9Sjmatthew 
3494889e9Sjmatthew /*
4494889e9Sjmatthew  * Copyright (c) 2015 Jonathan Matthew  <jmatthew@openbsd.org>
5494889e9Sjmatthew  *
6494889e9Sjmatthew  * Permission to use, copy, modify, and/or distribute this software for any
7494889e9Sjmatthew  * purpose with or without fee is hereby granted, provided that the above
8494889e9Sjmatthew  * copyright notice and this permission notice appear in all copies.
9494889e9Sjmatthew  *
10494889e9Sjmatthew  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11494889e9Sjmatthew  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12494889e9Sjmatthew  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13494889e9Sjmatthew  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14494889e9Sjmatthew  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15494889e9Sjmatthew  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16494889e9Sjmatthew  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17494889e9Sjmatthew  */
18494889e9Sjmatthew 
19494889e9Sjmatthew #include <sys/param.h>
20494889e9Sjmatthew #include <sys/systm.h>
21494889e9Sjmatthew #include <sys/device.h>
22494889e9Sjmatthew 
23494889e9Sjmatthew #include <machine/intr.h>
24494889e9Sjmatthew #include <machine/bus.h>
25494889e9Sjmatthew #include <machine/octeonreg.h>
26494889e9Sjmatthew #include <machine/octeonvar.h>
27494889e9Sjmatthew 
28494889e9Sjmatthew #include <octeon/dev/octuctlreg.h>
29494889e9Sjmatthew #include <octeon/dev/octuctlvar.h>
30494889e9Sjmatthew 
31494889e9Sjmatthew #include <dev/usb/usb.h>
32494889e9Sjmatthew #include <dev/usb/usbdi.h>
33494889e9Sjmatthew #include <dev/usb/usbdivar.h>
34494889e9Sjmatthew 
35494889e9Sjmatthew #include <dev/usb/ohcireg.h>
36494889e9Sjmatthew #include <dev/usb/ohcivar.h>
37494889e9Sjmatthew 
38494889e9Sjmatthew struct octohci_softc {
39494889e9Sjmatthew 	struct ohci_softc	sc_ohci;
40494889e9Sjmatthew 
41494889e9Sjmatthew 	void			*sc_ih;
42fe5dbe47Sjmatthew 	uint64_t		sc_reg_size;
43494889e9Sjmatthew };
44494889e9Sjmatthew 
45494889e9Sjmatthew int		octohci_match(struct device *, void *, void *);
46494889e9Sjmatthew void		octohci_attach(struct device *, struct device *, void *);
47494889e9Sjmatthew void		octohci_attach_deferred(struct device *);
48494889e9Sjmatthew 
49494889e9Sjmatthew const struct cfattach octohci_ca = {
50494889e9Sjmatthew 	sizeof(struct octohci_softc), octohci_match, octohci_attach,
51494889e9Sjmatthew };
52494889e9Sjmatthew 
53494889e9Sjmatthew struct cfdriver octohci_cd = {
54494889e9Sjmatthew 	NULL, "ohci", DV_DULL
55494889e9Sjmatthew };
56494889e9Sjmatthew 
57494889e9Sjmatthew int
octohci_match(struct device * parent,void * match,void * aux)58494889e9Sjmatthew octohci_match(struct device *parent, void *match, void *aux)
59494889e9Sjmatthew {
60494889e9Sjmatthew 	struct octuctl_attach_args *aa = aux;
61fe5dbe47Sjmatthew 	return (OF_is_compatible(aa->aa_node, "cavium,octeon-6335-ohci"));
62494889e9Sjmatthew }
63494889e9Sjmatthew 
64494889e9Sjmatthew void
octohci_attach(struct device * parent,struct device * self,void * aux)65494889e9Sjmatthew octohci_attach(struct device *parent, struct device *self, void *aux)
66494889e9Sjmatthew {
67494889e9Sjmatthew 	struct octohci_softc *sc = (struct octohci_softc *)self;
68494889e9Sjmatthew 	struct octuctl_attach_args *aa = aux;
69494889e9Sjmatthew 	uint64_t port_ctl;
70494889e9Sjmatthew 	int rc;
71494889e9Sjmatthew 	int s;
72494889e9Sjmatthew 
73494889e9Sjmatthew 	sc->sc_ohci.iot = aa->aa_bust;
74494889e9Sjmatthew 	sc->sc_ohci.sc_bus.pipe_size = sizeof(struct usbd_pipe);
75494889e9Sjmatthew 	sc->sc_ohci.sc_bus.dmatag = aa->aa_dmat;
76494889e9Sjmatthew 
77fe5dbe47Sjmatthew 	rc = bus_space_map(sc->sc_ohci.iot, aa->aa_reg.addr, aa->aa_reg.size,
78494889e9Sjmatthew 	    0, &sc->sc_ohci.ioh);
79494889e9Sjmatthew 	KASSERT(rc == 0);
80fe5dbe47Sjmatthew 	sc->sc_reg_size = aa->aa_reg.size;
81494889e9Sjmatthew 
82494889e9Sjmatthew 	port_ctl = bus_space_read_8(aa->aa_octuctl_bust, aa->aa_ioh,
83494889e9Sjmatthew 	    UCTL_OHCI_CTL);
84494889e9Sjmatthew 	port_ctl &= ~UCTL_OHCI_CTL_L2C_ADDR_MSB_MASK;
85494889e9Sjmatthew 	port_ctl |= (1 << UCTL_OHCI_CTL_L2C_DESC_EMOD_SHIFT);
86494889e9Sjmatthew 	port_ctl |= (1 << UCTL_OHCI_CTL_L2C_BUFF_EMOD_SHIFT);
87494889e9Sjmatthew 	bus_space_write_8(aa->aa_octuctl_bust, aa->aa_ioh, UCTL_OHCI_CTL,
88494889e9Sjmatthew 	    port_ctl);
89494889e9Sjmatthew 
90494889e9Sjmatthew 	s = splusb();
91494889e9Sjmatthew 
92494889e9Sjmatthew 	sc->sc_ohci.sc_id_vendor = 0;
93494889e9Sjmatthew 	strlcpy(sc->sc_ohci.sc_vendor, "Octeon", sizeof(sc->sc_ohci.sc_vendor));
94494889e9Sjmatthew 
95494889e9Sjmatthew 	sc->sc_ih = octeon_intr_establish(CIU_INT_USB, IPL_USB, ohci_intr,
961e13e073Svisa 	    (void *)&sc->sc_ohci, sc->sc_ohci.sc_bus.bdev.dv_xname);
97494889e9Sjmatthew 	KASSERT(sc->sc_ih != NULL);
98494889e9Sjmatthew 
99*71696a07Sdlg 	printf(", ");
100*71696a07Sdlg 
101494889e9Sjmatthew 	if ((ohci_checkrev(&sc->sc_ohci) != USBD_NORMAL_COMPLETION) ||
102494889e9Sjmatthew 	    (ohci_handover(&sc->sc_ohci) != USBD_NORMAL_COMPLETION))
103494889e9Sjmatthew 		goto failed;
104494889e9Sjmatthew 
105494889e9Sjmatthew 	/* ignore interrupts for now */
106494889e9Sjmatthew 	sc->sc_ohci.sc_bus.dying = 1;
107494889e9Sjmatthew 	config_defer(self, octohci_attach_deferred);
108494889e9Sjmatthew 
109494889e9Sjmatthew 	splx(s);
110494889e9Sjmatthew 	return;
111494889e9Sjmatthew 
112494889e9Sjmatthew failed:
113494889e9Sjmatthew 	octeon_intr_disestablish(sc->sc_ih);
114fe5dbe47Sjmatthew 	bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh, sc->sc_reg_size);
115494889e9Sjmatthew 	splx(s);
116494889e9Sjmatthew 	return;
117494889e9Sjmatthew }
118494889e9Sjmatthew 
119494889e9Sjmatthew void
octohci_attach_deferred(struct device * self)120494889e9Sjmatthew octohci_attach_deferred(struct device *self)
121494889e9Sjmatthew {
122494889e9Sjmatthew 	struct octohci_softc *sc = (struct octohci_softc *)self;
123494889e9Sjmatthew 	usbd_status r;
124494889e9Sjmatthew 	int s;
125494889e9Sjmatthew 
126494889e9Sjmatthew 	s = splusb();
127494889e9Sjmatthew 	sc->sc_ohci.sc_bus.dying = 0;
128494889e9Sjmatthew 
129494889e9Sjmatthew 	r = ohci_init(&sc->sc_ohci);
130494889e9Sjmatthew 	splx(s);
131494889e9Sjmatthew 
132494889e9Sjmatthew 	if (r != USBD_NORMAL_COMPLETION) {
133494889e9Sjmatthew 		printf("%s: init failed, error=%d\n",
134494889e9Sjmatthew 		    sc->sc_ohci.sc_bus.bdev.dv_xname, r);
135494889e9Sjmatthew 		octeon_intr_disestablish(sc->sc_ih);
136494889e9Sjmatthew 		bus_space_unmap(sc->sc_ohci.iot, sc->sc_ohci.ioh,
137fe5dbe47Sjmatthew 		    sc->sc_reg_size);
138494889e9Sjmatthew 	} else {
139494889e9Sjmatthew 		config_found(self, &sc->sc_ohci.sc_bus, usbctlprint);
140494889e9Sjmatthew 	}
141494889e9Sjmatthew }
142