pxa2x0_udc.c revision 1.4 1 1.4 nonaka /* $NetBSD: pxa2x0_udc.c,v 1.4 2011/06/09 17:29:42 nonaka Exp $ */
2 1.1 peter /* $OpenBSD: pxa27x_udc.c,v 1.5 2005/03/30 14:24:39 dlg Exp $ */
3 1.1 peter
4 1.1 peter /*
5 1.1 peter * Copyright (c) 2005 David Gwynne <dlg (at) openbsd.org>
6 1.1 peter *
7 1.1 peter * Permission to use, copy, modify, and distribute this software for any
8 1.1 peter * purpose with or without fee is hereby granted, provided that the above
9 1.1 peter * copyright notice and this permission notice appear in all copies.
10 1.1 peter *
11 1.1 peter * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 peter * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 peter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 peter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 peter * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 peter * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 peter * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 peter */
19 1.1 peter
20 1.1 peter #include <sys/param.h>
21 1.1 peter #include <sys/systm.h>
22 1.1 peter #include <sys/device.h>
23 1.1 peter #include <sys/kernel.h>
24 1.1 peter
25 1.1 peter #include <machine/intr.h>
26 1.1 peter #include <machine/bus.h>
27 1.1 peter
28 1.1 peter #include <arm/xscale/pxa2x0cpu.h>
29 1.1 peter #include <arm/xscale/pxa2x0reg.h>
30 1.1 peter #include <arm/xscale/pxa2x0var.h>
31 1.1 peter #include <arm/xscale/pxa2x0_gpio.h>
32 1.1 peter
33 1.1 peter struct pxaudc_softc {
34 1.4 nonaka device_t sc_dev;
35 1.1 peter bus_space_tag_t sc_iot;
36 1.1 peter bus_space_handle_t sc_ioh;
37 1.1 peter bus_size_t sc_size;
38 1.1 peter
39 1.1 peter void *sc_powerhook;
40 1.1 peter };
41 1.1 peter
42 1.4 nonaka static int pxaudc_match(device_t, cfdata_t, void *);
43 1.4 nonaka static void pxaudc_attach(device_t, device_t, void *);
44 1.4 nonaka static int pxaudc_detach(device_t, int);
45 1.1 peter
46 1.4 nonaka CFATTACH_DECL_NEW(pxaudc, sizeof(struct pxaudc_softc),
47 1.1 peter pxaudc_match, pxaudc_attach, pxaudc_detach, NULL);
48 1.1 peter
49 1.1 peter static void pxaudc_power(int, void *);
50 1.1 peter static void pxaudc_enable(struct pxaudc_softc *);
51 1.1 peter
52 1.1 peter static int
53 1.4 nonaka pxaudc_match(device_t parent, cfdata_t cf, void *aux)
54 1.1 peter {
55 1.2 kiyohara struct pxaip_attach_args *pxa = aux;
56 1.1 peter
57 1.2 kiyohara if (CPU_IS_PXA270 && strcmp(pxa->pxa_name, cf->cf_name) == 0) {
58 1.2 kiyohara pxa->pxa_size = PXA270_USBDC_SIZE;
59 1.1 peter return 1;
60 1.2 kiyohara }
61 1.1 peter return 0;
62 1.1 peter }
63 1.1 peter
64 1.1 peter static void
65 1.4 nonaka pxaudc_attach(device_t parent, device_t self, void *aux)
66 1.1 peter {
67 1.4 nonaka struct pxaudc_softc *sc = device_private(self);
68 1.1 peter struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux;
69 1.1 peter
70 1.4 nonaka sc->sc_dev = self;
71 1.1 peter sc->sc_iot = pxa->pxa_iot;
72 1.1 peter sc->sc_size = 0;
73 1.1 peter sc->sc_powerhook = NULL;
74 1.1 peter
75 1.4 nonaka aprint_normal(": USB Device Controller\n");
76 1.4 nonaka aprint_naive("\n");
77 1.4 nonaka
78 1.2 kiyohara if (bus_space_map(sc->sc_iot, pxa->pxa_addr, pxa->pxa_size, 0,
79 1.1 peter &sc->sc_ioh)) {
80 1.4 nonaka aprint_error_dev(self, "couldn't map memory space\n");
81 1.1 peter return;
82 1.1 peter }
83 1.2 kiyohara sc->sc_size = pxa->pxa_size;
84 1.1 peter
85 1.1 peter bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, sc->sc_size,
86 1.1 peter BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
87 1.1 peter
88 1.1 peter pxa2x0_clkman_config(CKEN_USBDC, 1);
89 1.1 peter
90 1.1 peter pxaudc_enable(sc);
91 1.1 peter
92 1.4 nonaka sc->sc_powerhook = powerhook_establish(device_xname(self),
93 1.1 peter pxaudc_power, sc);
94 1.1 peter if (sc->sc_powerhook == NULL) {
95 1.4 nonaka aprint_error_dev(self, "unable to establish powerhook.\n");
96 1.1 peter }
97 1.1 peter }
98 1.1 peter
99 1.1 peter static int
100 1.4 nonaka pxaudc_detach(device_t self, int flags)
101 1.1 peter {
102 1.4 nonaka struct pxaudc_softc *sc = device_private(self);
103 1.1 peter
104 1.1 peter if (sc->sc_powerhook)
105 1.1 peter powerhook_disestablish(sc->sc_powerhook);
106 1.1 peter
107 1.1 peter if (sc->sc_size) {
108 1.1 peter bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
109 1.1 peter sc->sc_size = 0;
110 1.1 peter }
111 1.1 peter
112 1.1 peter return 0;
113 1.1 peter }
114 1.1 peter
115 1.1 peter static void
116 1.1 peter pxaudc_power(int why, void *arg)
117 1.1 peter {
118 1.1 peter struct pxaudc_softc *sc = (struct pxaudc_softc *)arg;
119 1.1 peter
120 1.1 peter switch (why) {
121 1.1 peter case PWR_RESUME:
122 1.1 peter pxaudc_enable(sc);
123 1.1 peter break;
124 1.1 peter }
125 1.1 peter }
126 1.1 peter
127 1.1 peter static void
128 1.1 peter pxaudc_enable(struct pxaudc_softc *sc)
129 1.1 peter {
130 1.1 peter uint32_t hr;
131 1.1 peter
132 1.1 peter /* disable the controller */
133 1.1 peter hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UDCCR);
134 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UDCCR,
135 1.1 peter hr & ~USBDC_UDCCR_UDE);
136 1.1 peter
137 1.1 peter hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UDCICR1);
138 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UDCICR1,
139 1.1 peter hr | USBDC_UDCICR1_IERS);
140 1.1 peter
141 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR, 0);
142 1.1 peter hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR);
143 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR,
144 1.1 peter hr | USBDC_UP2OCR_HXS);
145 1.1 peter hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR);
146 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR,
147 1.1 peter hr | USBDC_UP2OCR_HXOE);
148 1.1 peter hr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR);
149 1.1 peter bus_space_write_4(sc->sc_iot, sc->sc_ioh, USBDC_UP2OCR,
150 1.1 peter hr | USBDC_UP2OCR_DPPDE|USBDC_UP2OCR_DMPDE);
151 1.1 peter }
152