1 /* $NetBSD: plumohci.c,v 1.11 2007/03/04 05:59:52 christos Exp $ */
4 * Copyright (c) 2000 UCHIYAMA Yasushi
5 * Copyright (c) 1999 MAEKAWA Masahide <bishop@rr.iij4u.or.jp>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
31 * USB Open Host Controller driver.
33 * OHCI spec: ftp://ftp.compaq.com/pub/supportinformation/papers/hcir1_0a.exe
34 * USB spec: http://www.usb.org/developers/data/usb11.pdf
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: plumohci.c,v 1.11 2007/03/04 05:59:52 christos Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
45 #include <sys/queue.h>
49 #include <uvm/uvm_extern.h>
51 #include <machine/bus.h>
52 #include <machine/bus_dma_hpcmips.h>
54 #include <dev/usb/usb.h>
55 #include <dev/usb/usbdi.h>
56 #include <dev/usb/usbdivar.h>
57 #include <dev/usb/usb_mem.h>
59 #include <dev/usb/ohcireg.h>
60 #include <dev/usb/ohcivar.h>
62 #include <hpcmips/tx/tx39var.h>
63 #include <hpcmips/dev/plumvar.h>
64 #include <hpcmips/dev/plumicuvar.h>
65 #include <hpcmips/dev/plumpowervar.h>
66 #include <hpcmips/dev/plumohcireg.h>
68 int plumohci_match(struct device
*, struct cfdata
*, void *);
69 void plumohci_attach(struct device
*, struct device
*, void *);
70 int plumohci_intr(void *);
72 void __plumohci_dmamap_sync(bus_dma_tag_t
, bus_dmamap_t
,
73 bus_addr_t
, bus_size_t
, int);
74 int __plumohci_dmamem_alloc(bus_dma_tag_t
, bus_size_t
, bus_size_t
,
75 bus_size_t
, bus_dma_segment_t
*, int, int *, int);
76 void __plumohci_dmamem_free(bus_dma_tag_t
, bus_dma_segment_t
*, int);
77 int __plumohci_dmamem_map(bus_dma_tag_t
, bus_dma_segment_t
*,
78 int, size_t, void **, int);
79 void __plumohci_dmamem_unmap(bus_dma_tag_t
, void *, size_t);
81 struct bus_dma_tag_hpcmips plumohci_bus_dma_tag
= {
85 _hpcmips_bd_map_create
,
86 _hpcmips_bd_map_destroy
,
88 _hpcmips_bd_map_load_mbuf
,
89 _hpcmips_bd_map_load_uio
,
90 _hpcmips_bd_map_load_raw
,
91 _hpcmips_bd_map_unload
,
92 __plumohci_dmamap_sync
,
93 __plumohci_dmamem_alloc
,
94 __plumohci_dmamem_free
,
95 __plumohci_dmamem_map
,
96 __plumohci_dmamem_unmap
,
103 struct plumohci_shm
{
104 bus_space_handle_t ps_bsh
;
108 LIST_ENTRY(plumohci_shm
) ps_link
;
111 struct plumohci_softc
{
112 struct ohci_softc sc
;
116 LIST_HEAD(, plumohci_shm
) sc_shm_head
;
119 CFATTACH_DECL_NEW(plumohci
, sizeof(struct plumohci_softc
),
120 plumohci_match
, plumohci_attach
, NULL
, NULL
);
123 plumohci_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
125 /* PLUM2 builtin OHCI module */
131 plumohci_attach(struct device
*parent
, struct device
*self
, void *aux
)
133 struct plumohci_softc
*sc
= device_private(self
);
134 struct plum_attach_args
*pa
= aux
;
137 sc
->sc
.sc_dev
= self
;
138 sc
->sc
.sc_bus
.hci_private
= sc
;
140 sc
->sc
.iot
= pa
->pa_iot
;
141 sc
->sc
.sc_bus
.dmatag
= &plumohci_bus_dma_tag
.bdt
;
142 plumohci_bus_dma_tag
._dmamap_chipset_v
= sc
;
145 if (bus_space_map(sc
->sc
.iot
, PLUM_OHCI_REGBASE
, OHCI_PAGE_SIZE
,
147 printf(": cannot map mem space\n");
153 * in the case of PLUM2, UHOSTC uses the VRAM as the shared RAM
154 * so establish power/clock of Video contoroller
156 plum_power_establish(pa
->pa_pc
, PLUM_PWR_EXTPW1
);
157 plum_power_establish(pa
->pa_pc
, PLUM_PWR_USB
);
159 /* Disable interrupts, so we don't can any spurious ones. */
160 bus_space_write_4(sc
->sc
.iot
, sc
->sc
.ioh
, OHCI_INTERRUPT_DISABLE
,
164 sc
->sc_ih
= plum_intr_establish(pa
->pa_pc
, PLUM_INT_USB
, IST_EDGE
,
165 IPL_USB
, ohci_intr
, sc
);
168 * enable the clock restart request interrupt
169 * (for USBSUSPEND state)
171 sc
->sc_wakeih
= plum_intr_establish(pa
->pa_pc
, PLUM_INT_USBWAKE
,
176 * Shared memory list.
178 LIST_INIT(&sc
->sc_shm_head
);
182 r
= ohci_init(&sc
->sc
);
184 if (r
!= USBD_NORMAL_COMPLETION
) {
185 printf(": init failed, error=%d\n", r
);
187 plum_intr_disestablish(pa
->pa_pc
, sc
->sc_ih
);
188 plum_intr_disestablish(pa
->pa_pc
, sc
->sc_wakeih
);
193 /* Attach usb device. */
194 sc
->sc
.sc_child
= config_found(self
, &sc
->sc
.sc_bus
, usbctlprint
);
198 plumohci_intr(void *arg
)
200 printf("Plum2 OHCI: wakeup intr\n");
205 * Plum2 OHCI specific busdma routines.
206 * Plum2 OHCI shared buffer can't allocate on memory
207 * but V-RAM (busspace).
211 __plumohci_dmamap_sync(bus_dma_tag_t tx
, bus_dmamap_t map
, bus_addr_t offset
,
212 bus_size_t len
, int ops
)
214 struct bus_dma_tag_hpcmips
*t
= (struct bus_dma_tag_hpcmips
*)tx
;
215 struct plumohci_softc
*sc
= t
->_dmamap_chipset_v
;
218 * Flush the write buffer allocated on the V-RAM.
219 * Accessing any host controller register flushs write buffer
221 (void)bus_space_read_4(sc
->sc
.iot
, sc
->sc
.ioh
, OHCI_REVISION
);
225 __plumohci_dmamem_alloc(bus_dma_tag_t tx
, bus_size_t size
,
226 bus_size_t alignment
, bus_size_t boundary
, bus_dma_segment_t
*segs
,
227 int nsegs
, int *rsegs
, int flags
)
229 struct bus_dma_tag_hpcmips
*t
= (struct bus_dma_tag_hpcmips
*)tx
;
230 struct plumohci_softc
*sc
= t
->_dmamap_chipset_v
;
231 struct plumohci_shm
*ps
;
232 bus_space_handle_t bsh
;
237 size
= round_page(size
);
240 * Allocate buffer from V-RAM area.
242 error
= bus_space_alloc(sc
->sc
.iot
, PLUM_OHCI_SHMEMBASE
,
243 PLUM_OHCI_SHMEMBASE
+ PLUM_OHCI_SHMEMSIZE
- 1,
244 size
, OHCI_PAGE_SIZE
, OHCI_PAGE_SIZE
, 0,
245 (bus_addr_t
*)(void *)&caddr
, &bsh
);
249 pmap_extract(pmap_kernel(), (vaddr_t
)caddr
, &paddr
);
251 ps
= malloc(sizeof(struct plumohci_shm
), M_DEVBUF
, M_NOWAIT
);
256 ps
->ps_size
= segs
[0].ds_len
= size
;
257 ps
->ps_paddr
= segs
[0].ds_addr
= paddr
;
258 ps
->ps_caddr
= caddr
;
260 LIST_INSERT_HEAD(&sc
->sc_shm_head
, ps
, ps_link
);
268 __plumohci_dmamem_free(bus_dma_tag_t tx
, bus_dma_segment_t
*segs
, int nsegs
)
270 struct bus_dma_tag_hpcmips
*t
= (struct bus_dma_tag_hpcmips
*)tx
;
271 struct plumohci_softc
*sc
= t
->_dmamap_chipset_v
;
272 struct plumohci_shm
*ps
;
274 for (ps
= LIST_FIRST(&sc
->sc_shm_head
); ps
;
275 ps
= LIST_NEXT(ps
, ps_link
)) {
277 if (ps
->ps_paddr
== segs
[0].ds_addr
) {
278 bus_space_free(sc
->sc
.iot
, ps
->ps_bsh
, ps
->ps_size
);
279 LIST_REMOVE(ps
, ps_link
);
286 panic("__plumohci_dmamem_free: can't find corresponding handle.");
291 __plumohci_dmamem_map(bus_dma_tag_t tx
, bus_dma_segment_t
*segs
, int nsegs
,
292 size_t size
, void **kvap
, int flags
)
294 struct bus_dma_tag_hpcmips
*t
= (struct bus_dma_tag_hpcmips
*)tx
;
295 struct plumohci_softc
*sc
= t
->_dmamap_chipset_v
;
296 struct plumohci_shm
*ps
;
298 for (ps
= LIST_FIRST(&sc
->sc_shm_head
); ps
;
299 ps
= LIST_NEXT(ps
, ps_link
)) {
300 if (ps
->ps_paddr
== segs
[0].ds_addr
) {
302 *kvap
= ps
->ps_caddr
;
312 __plumohci_dmamem_unmap(bus_dma_tag_t t
, void *kva
, size_t size
)