1 /* $NetBSD: plumohci.c,v 1.1 2000/03/25 15:08:26 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 UCHIYAMA Yasushi 5 * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * USB Open Host Controller driver. 32 * 33 * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe 34 * USB spec: http://www.usb.org/developers/data/usb11.pdf 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/proc.h> 42 #include <sys/queue.h> 43 44 /* busdma */ 45 #include <sys/mbuf.h> 46 #include <vm/vm.h> 47 #include <vm/vm_kern.h> 48 49 #define _HPCMIPS_BUS_DMA_PRIVATE 50 #include <machine/bus.h> 51 52 #include <dev/usb/usb.h> 53 #include <dev/usb/usbdi.h> 54 #include <dev/usb/usbdivar.h> 55 #include <dev/usb/usb_mem.h> 56 57 #include <dev/usb/ohcireg.h> 58 #include <dev/usb/ohcivar.h> 59 60 #include <hpcmips/tx/tx39var.h> 61 #include <hpcmips/dev/plumvar.h> 62 #include <hpcmips/dev/plumicuvar.h> 63 #include <hpcmips/dev/plumpowervar.h> 64 #include <hpcmips/dev/plumohcireg.h> 65 66 int plumohci_match __P((struct device *, struct cfdata *, void *)); 67 void plumohci_attach __P((struct device *, struct device *, void *)); 68 int plumohci_intr __P((void *)); 69 70 void __plumohci_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, 71 bus_addr_t, bus_size_t, int)); 72 int __plumohci_dmamem_alloc __P((bus_dma_tag_t, bus_size_t, bus_size_t, 73 bus_size_t, bus_dma_segment_t *, int, 74 int *, int)); 75 void __plumohci_dmamem_free __P((bus_dma_tag_t, bus_dma_segment_t *, 76 int)); 77 int __plumohci_dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *, 78 int, size_t, caddr_t *, int)); 79 void __plumohci_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t)); 80 81 struct hpcmips_bus_dma_tag plumohci_bus_dma_tag = { 82 _bus_dmamap_create, 83 _bus_dmamap_destroy, 84 _bus_dmamap_load, 85 _bus_dmamap_load_mbuf, 86 _bus_dmamap_load_uio, 87 _bus_dmamap_load_raw, 88 _bus_dmamap_unload, 89 __plumohci_dmamap_sync, 90 __plumohci_dmamem_alloc, 91 __plumohci_dmamem_free, 92 __plumohci_dmamem_map, 93 __plumohci_dmamem_unmap, 94 _bus_dmamem_mmap, 95 NULL 96 }; 97 98 struct plumohci_shm { 99 bus_space_handle_t ps_bsh; 100 paddr_t ps_paddr; 101 caddr_t ps_caddr; 102 size_t ps_size; 103 LIST_ENTRY(plumohci_shm) ps_link; 104 }; 105 106 struct plumohci_softc { 107 struct ohci_softc sc; 108 void *sc_ih; 109 void *sc_wakeih; 110 111 LIST_HEAD(, plumohci_shm) sc_shm_head; 112 }; 113 114 struct cfattach plumohci_ca = { 115 sizeof(struct plumohci_softc), plumohci_match, plumohci_attach, 116 }; 117 118 int 119 plumohci_match(parent, match, aux) 120 struct device *parent; 121 struct cfdata *match; 122 void *aux; 123 { 124 /* PLUM2 builtin OHCI module */ 125 126 return (1); 127 } 128 129 void 130 plumohci_attach(parent, self, aux) 131 struct device *parent; 132 struct device *self; 133 void *aux; 134 { 135 struct plumohci_softc *sc = (struct plumohci_softc *)self; 136 struct plum_attach_args *pa = aux; 137 usbd_status r; 138 139 sc->sc.iot = pa->pa_iot; 140 sc->sc.sc_bus.dmatag = &plumohci_bus_dma_tag; 141 sc->sc.sc_bus.dmatag->_dmamap_chipset_v = sc; 142 143 /* Map I/O space */ 144 if (bus_space_map(sc->sc.iot, PLUM_OHCI_REGBASE, OHCI_PAGE_SIZE, 145 0, &sc->sc.ioh)) { 146 printf(": cannot map mem space\n"); 147 return; 148 } 149 150 /* power up */ 151 /* 152 * in the case of PLUM2, UHOSTC uses the VRAM as the shared RAM 153 * so establish power/clock of Video contoroller 154 */ 155 plum_power_establish(pa->pa_pc, PLUM_PWR_EXTPW1); 156 plum_power_establish(pa->pa_pc, PLUM_PWR_USB); 157 158 /* Disable interrupts, so we don't can any spurious ones. */ 159 bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE, 160 OHCI_ALL_INTRS); 161 162 /* master enable */ 163 sc->sc_ih = plum_intr_establish(pa->pa_pc, PLUM_INT_USB, IST_EDGE, 164 IPL_USB, ohci_intr, sc); 165 #if 0 166 /* 167 * enable the clock restart request interrupt 168 * (for USBSUSPEND state) 169 */ 170 sc->sc_wakeih = plum_intr_establish(pa->pa_pc, PLUM_INT_USBWAKE, 171 IST_EDGE, IPL_USB, 172 plumohci_intr, sc); 173 #endif 174 /* 175 * Shared memory list. 176 */ 177 LIST_INIT(&sc->sc_shm_head); 178 179 printf("\n"); 180 181 r = ohci_init(&sc->sc); 182 183 if (r != USBD_NORMAL_COMPLETION) { 184 printf(": init failed, error=%d\n", r); 185 186 plum_intr_disestablish(pa->pa_pc, sc->sc_ih); 187 plum_intr_disestablish(pa->pa_pc, sc->sc_wakeih); 188 189 return; 190 } 191 192 /* Attach usb device. */ 193 sc->sc.sc_child = config_found((void *) sc, &sc->sc.sc_bus, 194 usbctlprint); 195 } 196 197 int 198 plumohci_intr(arg) 199 void *arg; 200 { 201 printf("Plum2 OHCI: wakeup intr\n"); 202 return 0; 203 } 204 205 /* 206 * Plum2 OHCI specific busdma routines. 207 * Plum2 OHCI shared buffer can't allocate on memory 208 * but V-RAM (busspace). 209 */ 210 211 void 212 __plumohci_dmamap_sync(t, map, offset, len, ops) 213 bus_dma_tag_t t; 214 bus_dmamap_t map; 215 bus_addr_t offset; 216 bus_size_t len; 217 int ops; 218 { 219 struct plumohci_softc *sc = t->_dmamap_chipset_v; 220 /* 221 * Flush the write buffer allocated on the V-RAM. 222 * Accessing any host controller register flushs write buffer 223 */ 224 225 (void)bus_space_read_4(sc->sc.iot, sc->sc.ioh, OHCI_REVISION); 226 } 227 228 int 229 __plumohci_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, 230 flags) 231 bus_dma_tag_t t; 232 bus_size_t size, alignment, boundary; 233 bus_dma_segment_t *segs; 234 int nsegs; 235 int *rsegs; 236 int flags; 237 { 238 struct plumohci_softc *sc = t->_dmamap_chipset_v; 239 struct plumohci_shm *ps; 240 bus_space_handle_t bsh; 241 paddr_t paddr; 242 caddr_t caddr; 243 int error; 244 245 size = round_page(size); 246 247 /* 248 * Allocate buffer from V-RAM area. 249 */ 250 error = bus_space_alloc(sc->sc.iot, PLUM_OHCI_SHMEMBASE, 251 PLUM_OHCI_SHMEMBASE + PLUM_OHCI_SHMEMSIZE - 1, 252 size, OHCI_PAGE_SIZE, OHCI_PAGE_SIZE, 0, 253 (bus_addr_t*)&caddr, &bsh); 254 if (error) 255 return (1); 256 257 pmap_extract(pmap_kernel(), (vaddr_t)caddr, &paddr); 258 259 ps = malloc(sizeof(struct plumohci_shm), M_DEVBUF, M_NOWAIT); 260 if (ps == 0) 261 return (1); 262 263 ps->ps_bsh = bsh; 264 ps->ps_size = segs[0].ds_len = size; 265 ps->ps_paddr = segs[0].ds_addr = paddr; 266 ps->ps_caddr = caddr; 267 268 LIST_INSERT_HEAD(&sc->sc_shm_head, ps, ps_link); 269 270 *rsegs = 1; 271 272 return (0); 273 } 274 275 void 276 __plumohci_dmamem_free(t, segs, nsegs) 277 bus_dma_tag_t t; 278 bus_dma_segment_t *segs; 279 int nsegs; 280 { 281 struct plumohci_softc *sc = t->_dmamap_chipset_v; 282 struct plumohci_shm *ps; 283 284 for (ps = LIST_FIRST(&sc->sc_shm_head); ps; 285 ps = LIST_NEXT(ps, ps_link)) { 286 287 if (ps->ps_paddr == segs[0].ds_addr) { 288 bus_space_free(sc->sc.iot, ps->ps_bsh, ps->ps_size); 289 LIST_REMOVE(ps, ps_link); 290 free(ps, M_DEVBUF); 291 292 return; 293 } 294 } 295 296 panic("__plumohci_dmamem_free: can't find corresponding handle."); 297 /* NOTREACHED */ 298 } 299 300 int 301 __plumohci_dmamem_map(t, segs, nsegs, size, kvap, flags) 302 bus_dma_tag_t t; 303 bus_dma_segment_t *segs; 304 int nsegs; 305 size_t size; 306 caddr_t *kvap; 307 int flags; 308 { 309 struct plumohci_softc *sc = t->_dmamap_chipset_v; 310 struct plumohci_shm *ps; 311 312 for (ps = LIST_FIRST(&sc->sc_shm_head); ps; 313 ps = LIST_NEXT(ps, ps_link)) { 314 if (ps->ps_paddr == segs[0].ds_addr) { 315 316 *kvap = ps->ps_caddr; 317 318 return (0); 319 } 320 } 321 322 return (1); 323 } 324 325 void 326 __plumohci_dmamem_unmap(t, kva, size) 327 bus_dma_tag_t t; 328 caddr_t kva; 329 size_t size; 330 { 331 /* nothing to do */ 332 } 333