Home | History | Annotate | Line # | Download | only in dev
      1  1.16   thorpej /*	$NetBSD: ohci_sbus.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $	*/
      2   1.1       uch 
      3   1.1       uch /*-
      4   1.1       uch  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5   1.1       uch  * All rights reserved.
      6   1.1       uch  *
      7   1.1       uch  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1       uch  * by UCHIYAMA Yasushi.
      9   1.1       uch  *
     10   1.1       uch  * Redistribution and use in source and binary forms, with or without
     11   1.1       uch  * modification, are permitted provided that the following conditions
     12   1.1       uch  * are met:
     13   1.1       uch  * 1. Redistributions of source code must retain the above copyright
     14   1.1       uch  *    notice, this list of conditions and the following disclaimer.
     15   1.1       uch  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1       uch  *    notice, this list of conditions and the following disclaimer in the
     17   1.1       uch  *    documentation and/or other materials provided with the distribution.
     18   1.1       uch  *
     19   1.1       uch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1       uch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1       uch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1       uch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1       uch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1       uch  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1       uch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1       uch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1       uch  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1       uch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1       uch  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1       uch  */
     31   1.4     lukem 
     32   1.4     lukem #include <sys/cdefs.h>
     33  1.16   thorpej __KERNEL_RCSID(0, "$NetBSD: ohci_sbus.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $");
     34   1.1       uch 
     35   1.1       uch #include <sys/param.h>
     36  1.14   thorpej #include <sys/kmem.h>
     37   1.1       uch 
     38   1.1       uch /* bus_dma */
     39   1.1       uch #include <sys/mbuf.h>
     40   1.1       uch #include <uvm/uvm_extern.h>
     41   1.1       uch 
     42   1.1       uch #define _PLAYSTATION2_BUS_DMA_PRIVATE
     43   1.1       uch #include <machine/bus.h>
     44   1.1       uch #include <machine/autoconf.h>
     45   1.1       uch 
     46  1.13      maya #include <mips/cpuregs.h>
     47  1.13      maya 
     48   1.1       uch #include <dev/usb/usb.h>
     49   1.1       uch #include <dev/usb/usbdi.h>
     50   1.1       uch #include <dev/usb/usbdivar.h>
     51   1.5        he #include <dev/usb/usb_mem.h>
     52   1.1       uch 
     53   1.1       uch #include <dev/usb/ohcireg.h>
     54   1.1       uch #include <dev/usb/ohcivar.h>
     55   1.1       uch 
     56   1.1       uch #include <playstation2/ee/sifvar.h>	/* DMA staff */
     57   1.1       uch #include <playstation2/ee/dmacvar.h>
     58   1.1       uch #include <playstation2/dev/sbusvar.h>
     59   1.1       uch 
     60   1.1       uch #ifdef DEBUG
     61   1.1       uch #define STATIC
     62   1.1       uch #else
     63   1.1       uch #define STATIC static
     64   1.1       uch #endif
     65   1.1       uch 
     66   1.1       uch #define	SBUS_OHCI_REGBASE	MIPS_PHYS_TO_KSEG1(0x1f801600)
     67   1.1       uch #define SBUS_OHCI_REGSIZE	0x1000
     68   1.1       uch 
     69   1.1       uch STATIC int ohci_sbus_match(struct device *, struct cfdata *, void *);
     70   1.1       uch STATIC void ohci_sbus_attach(struct device *, struct device *, void *);
     71   1.1       uch 
     72   1.1       uch STATIC void _ohci_sbus_map_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
     73   1.1       uch     bus_size_t, int);
     74   1.1       uch STATIC int _ohci_sbus_mem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
     75   1.1       uch     bus_size_t, bus_dma_segment_t *, int, int *, int);
     76   1.1       uch STATIC void _ohci_sbus_mem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
     77   1.1       uch STATIC int _ohci_sbus_mem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t,
     78   1.7  christos     void **, int);
     79   1.7  christos STATIC void _ohci_sbus_mem_unmap(bus_dma_tag_t, void *, size_t);
     80   1.1       uch 
     81   1.1       uch struct playstation2_bus_dma_tag ohci_bus_dma_tag = {
     82   1.1       uch 	_bus_dmamap_create,
     83   1.1       uch 	_bus_dmamap_destroy,
     84   1.1       uch 	_bus_dmamap_load,
     85   1.1       uch 	_bus_dmamap_load_mbuf,
     86   1.1       uch 	_bus_dmamap_load_uio,
     87   1.1       uch 	_bus_dmamap_load_raw,
     88   1.1       uch 	_bus_dmamap_unload,
     89   1.1       uch 	_ohci_sbus_map_sync,
     90   1.1       uch 	_ohci_sbus_mem_alloc,
     91   1.1       uch 	_ohci_sbus_mem_free,
     92   1.1       uch 	_ohci_sbus_mem_map,
     93   1.1       uch 	_ohci_sbus_mem_unmap,
     94   1.1       uch 	_bus_dmamem_mmap,
     95   1.1       uch };
     96   1.1       uch 
     97   1.1       uch struct ohci_dma_segment {
     98   1.1       uch 	struct iopdma_segment ds_iopdma_seg;
     99   1.1       uch 
    100   1.1       uch 	LIST_ENTRY(ohci_dma_segment) ds_link;
    101   1.1       uch };
    102   1.1       uch 
    103   1.1       uch struct ohci_sbus_softc {
    104   1.1       uch 	struct ohci_softc sc;
    105   1.1       uch 
    106   1.1       uch 	LIST_HEAD(, ohci_dma_segment) sc_dmaseg_head;
    107   1.1       uch };
    108   1.1       uch 
    109   1.8  drochner CFATTACH_DECL_NEW(ohci_sbus, sizeof(struct ohci_sbus_softc),
    110   1.3   thorpej     ohci_sbus_match, ohci_sbus_attach, NULL, NULL);
    111   1.1       uch 
    112   1.1       uch int
    113   1.1       uch ohci_sbus_match(struct device *parent, struct cfdata *cf, void *aux)
    114   1.1       uch {
    115   1.1       uch 
    116  1.12     skrll 	return 1;
    117   1.1       uch }
    118   1.1       uch 
    119   1.1       uch void
    120   1.1       uch ohci_sbus_attach(struct device *parent, struct device *self, void *aux)
    121   1.1       uch {
    122   1.8  drochner 	struct ohci_sbus_softc *sc = device_private(self);
    123   1.1       uch 
    124   1.1       uch 	printf("\n");
    125   1.1       uch 
    126   1.8  drochner 	sc->sc.sc_dev = self;
    127  1.12     skrll 	sc->sc.sc_bus.ub_hcpriv = sc;
    128   1.8  drochner 
    129   1.1       uch 	sc->sc.iot = bus_space_create(0, "OHCI I/O space", SBUS_OHCI_REGBASE,
    130   1.1       uch 	    SBUS_OHCI_REGSIZE);
    131   1.1       uch 	sc->sc.ioh = SBUS_OHCI_REGBASE;
    132   1.1       uch 
    133   1.1       uch 	ohci_bus_dma_tag._dmachip_cookie = sc;
    134  1.12     skrll 	sc->sc.sc_bus.ub_dmatag = &ohci_bus_dma_tag;
    135   1.1       uch 
    136   1.1       uch 	/* Disable interrupts, so we don't can any spurious ones. */
    137   1.1       uch 	bus_space_write_4(sc->sc.iot, sc->sc.ioh, OHCI_INTERRUPT_DISABLE,
    138   1.1       uch 	    OHCI_ALL_INTRS);
    139   1.1       uch 
    140   1.1       uch 	sbus_intr_establish(SBUS_IRQ_USB, ohci_intr, sc);
    141   1.1       uch 
    142   1.1       uch 	/* IOP/EE DMA relay segment list */
    143   1.1       uch 	LIST_INIT(&sc->sc_dmaseg_head);
    144   1.1       uch 
    145  1.12     skrll 	int err = ohci_init(&sc->sc);
    146  1.12     skrll 
    147  1.12     skrll 	if (err) {
    148  1.12     skrll 		printf(": init failed. error=%d\n", err);
    149   1.1       uch 		return;
    150   1.1       uch 	}
    151   1.1       uch 
    152   1.1       uch 	/* Attach usb device. */
    153  1.15   thorpej 	sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint,
    154  1.16   thorpej 	    CFARGS_NONE);
    155   1.1       uch }
    156   1.1       uch 
    157   1.1       uch void
    158   1.1       uch _ohci_sbus_map_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
    159   1.1       uch     bus_size_t len, int ops)
    160   1.1       uch {
    161   1.1       uch 
    162   1.1       uch 	dmac_sync_buffer(); /* XXX over flush */
    163   1.1       uch }
    164   1.1       uch 
    165   1.1       uch int
    166   1.1       uch _ohci_sbus_mem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
    167   1.1       uch     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
    168   1.1       uch     int flags)
    169   1.1       uch {
    170   1.1       uch 	struct ohci_sbus_softc *sc = t->_dmachip_cookie;
    171   1.1       uch 	struct ohci_dma_segment *ds;
    172   1.1       uch 	struct iopdma_segment *iopdma_seg;
    173   1.1       uch 	int error;
    174   1.1       uch 
    175   1.1       uch 	KDASSERT(sc);
    176  1.14   thorpej 	ds = kmem_intr_alloc(sizeof(struct ohci_dma_segment), KM_NOSLEEP);
    177   1.1       uch 	if (ds == NULL)
    178  1.12     skrll 		return 1;
    179   1.1       uch 	/*
    180   1.1       uch 	 * Allocate DMA Area (IOP DMA Area <-> SIF DMA <-> EE DMA Area)
    181   1.1       uch 	 */
    182   1.1       uch 	iopdma_seg = &ds->ds_iopdma_seg;
    183   1.1       uch 	error = iopdma_allocate_buffer(iopdma_seg, size);
    184   1.1       uch 
    185   1.1       uch 	if (error) {
    186  1.14   thorpej 		kmem_intr_free(ds, sizeof(*ds));
    187  1.12     skrll 		return 1;
    188   1.1       uch 	}
    189   1.1       uch 
    190   1.1       uch 	segs[0].ds_len	  = iopdma_seg->size;
    191   1.1       uch 	segs[0].ds_addr	  = iopdma_seg->iop_paddr;
    192   1.1       uch 	segs[0]._ds_vaddr = iopdma_seg->ee_vaddr;
    193   1.1       uch 
    194   1.1       uch 	LIST_INSERT_HEAD(&sc->sc_dmaseg_head, ds, ds_link);
    195   1.1       uch 
    196   1.1       uch 	*rsegs = 1;
    197   1.1       uch 
    198  1.12     skrll 	return 0;
    199   1.1       uch }
    200   1.1       uch 
    201   1.1       uch void
    202   1.1       uch _ohci_sbus_mem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
    203   1.1       uch {
    204   1.1       uch 	struct ohci_sbus_softc *sc = t->_dmachip_cookie;
    205   1.1       uch 	struct ohci_dma_segment *ds;
    206   1.1       uch 	paddr_t addr = segs[0].ds_addr;
    207   1.1       uch 
    208   1.1       uch 	for (ds = LIST_FIRST(&sc->sc_dmaseg_head); ds != NULL;
    209   1.1       uch 	    ds = LIST_NEXT(ds, ds_link)) {
    210   1.1       uch 		if (ds->ds_iopdma_seg.iop_paddr == addr) {
    211   1.1       uch 			iopdma_free_buffer(&ds->ds_iopdma_seg);
    212   1.1       uch 
    213   1.1       uch 			LIST_REMOVE(ds, ds_link);
    214  1.14   thorpej 			kmem_intr_free(ds, sizeof(*ds));
    215   1.1       uch 			return;
    216   1.1       uch 		}
    217   1.1       uch 	}
    218   1.1       uch 
    219   1.1       uch 	panic("_dmamem_free: can't find corresponding handle.");
    220   1.1       uch 	/* NOTREACHED */
    221   1.1       uch }
    222   1.1       uch 
    223   1.1       uch int
    224   1.1       uch _ohci_sbus_mem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size,
    225   1.7  christos     void **kvap, int flags)
    226   1.1       uch {
    227   1.1       uch 	struct ohci_sbus_softc *sc = t->_dmachip_cookie;
    228   1.1       uch 	struct ohci_dma_segment *ds;
    229   1.1       uch 	paddr_t addr = segs[0].ds_addr;
    230   1.1       uch 
    231   1.1       uch 	for (ds = LIST_FIRST(&sc->sc_dmaseg_head); ds != NULL;
    232   1.1       uch 	    ds = LIST_NEXT(ds, ds_link)) {
    233   1.1       uch 		if (ds->ds_iopdma_seg.iop_paddr == addr) {
    234   1.1       uch 
    235   1.7  christos 			*kvap = (void *)ds->ds_iopdma_seg.ee_vaddr;
    236   1.1       uch 
    237  1.12     skrll 			return 0;
    238   1.1       uch 		}
    239   1.1       uch 	}
    240   1.1       uch 
    241  1.12     skrll 	return 1;
    242   1.1       uch }
    243   1.1       uch 
    244   1.1       uch void
    245   1.7  christos _ohci_sbus_mem_unmap(bus_dma_tag_t t, void *kva, size_t size)
    246   1.1       uch {
    247   1.1       uch 	/* nothing to do */
    248   1.1       uch }
    249