1 1.5 dyoung /* $NetBSD: pxa2x0_udc.c,v 1.5 2011/07/01 20:32:51 dyoung 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.5 dyoung #include <sys/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