1 1.1 takemura /* 2 1.1 takemura * Copyright (c) 2001 HAMAJIMA Katsuomi. All rights reserved. 3 1.1 takemura * 4 1.1 takemura * Redistribution and use in source and binary forms, with or without 5 1.1 takemura * modification, are permitted provided that the following conditions 6 1.1 takemura * are met: 7 1.1 takemura * 1. Redistributions of source code must retain the above copyright 8 1.1 takemura * notice, this list of conditions and the following disclaimer. 9 1.1 takemura * 2. Redistributions in binary form must reproduce the above copyright 10 1.1 takemura * notice, this list of conditions and the following disclaimer in the 11 1.1 takemura * documentation and/or other materials provided with the distribution. 12 1.1 takemura * 13 1.1 takemura * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 1.1 takemura * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 1.1 takemura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 1.1 takemura * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 1.1 takemura * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 1.1 takemura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 1.1 takemura * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 1.1 takemura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 1.1 takemura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 1.1 takemura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 1.1 takemura * SUCH DAMAGE. 24 1.1 takemura */ 25 1.1 takemura 26 1.4 lukem #include <sys/cdefs.h> 27 1.8 matt __KERNEL_RCSID(0, "$NetBSD: vrdcu.c,v 1.8 2015/06/11 08:22:09 matt Exp $"); 28 1.4 lukem 29 1.1 takemura #include <sys/param.h> 30 1.1 takemura #include <sys/systm.h> 31 1.1 takemura #include <sys/device.h> 32 1.1 takemura 33 1.1 takemura #include <uvm/uvm_extern.h> 34 1.1 takemura 35 1.1 takemura #include <machine/cpu.h> 36 1.1 takemura #include <machine/bus.h> 37 1.1 takemura #include <machine/bus_dma_hpcmips.h> 38 1.1 takemura 39 1.1 takemura #include <hpcmips/vr/vripif.h> 40 1.1 takemura #include <hpcmips/vr/dcureg.h> 41 1.1 takemura 42 1.1 takemura #ifdef VRDCU_DEBUG 43 1.1 takemura int vrdcu_debug = VRDCU_DEBUG; 44 1.1 takemura #define DPRINTFN(n,x) if (vrdcu_debug>(n)) printf x; 45 1.1 takemura #else 46 1.1 takemura #define DPRINTFN(n,x) 47 1.1 takemura #endif 48 1.1 takemura 49 1.1 takemura struct vrdcu_softc { 50 1.1 takemura bus_space_tag_t sc_iot; 51 1.1 takemura bus_space_handle_t sc_ioh; 52 1.1 takemura struct vrdcu_chipset_tag sc_chipset; 53 1.1 takemura int sc_status; /* DMA status */ 54 1.1 takemura }; 55 1.1 takemura 56 1.7 chs int vrdcu_match(device_t, cfdata_t, void *); 57 1.7 chs void vrdcu_attach(device_t, device_t, void *); 58 1.1 takemura 59 1.7 chs CFATTACH_DECL_NEW(vrdcu, sizeof(struct vrdcu_softc), 60 1.3 thorpej vrdcu_match, vrdcu_attach, NULL, NULL); 61 1.1 takemura 62 1.1 takemura int vrdcu_enable_aiuin(vrdcu_chipset_tag_t); 63 1.1 takemura int vrdcu_enable_aiuout(vrdcu_chipset_tag_t); 64 1.1 takemura int vrdcu_enable_fir(vrdcu_chipset_tag_t); 65 1.1 takemura void vrdcu_disable(vrdcu_chipset_tag_t); 66 1.1 takemura void vrdcu_fir_direction(vrdcu_chipset_tag_t, int); 67 1.1 takemura int _vrdcu_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, 68 1.1 takemura bus_size_t, bus_dma_segment_t *, int, int *, int); 69 1.1 takemura 70 1.1 takemura struct bus_dma_tag vrdcu_bus_dma_tag = { 71 1.1 takemura NULL, 72 1.1 takemura { 73 1.1 takemura _hpcmips_bd_map_create, 74 1.1 takemura _hpcmips_bd_map_destroy, 75 1.1 takemura _hpcmips_bd_map_load, 76 1.1 takemura _hpcmips_bd_map_load_mbuf, 77 1.1 takemura _hpcmips_bd_map_load_uio, 78 1.1 takemura _hpcmips_bd_map_load_raw, 79 1.1 takemura _hpcmips_bd_map_unload, 80 1.1 takemura _hpcmips_bd_map_sync, 81 1.1 takemura _vrdcu_dmamem_alloc, 82 1.1 takemura _hpcmips_bd_mem_free, 83 1.1 takemura _hpcmips_bd_mem_map, 84 1.1 takemura _hpcmips_bd_mem_unmap, 85 1.1 takemura _hpcmips_bd_mem_mmap, 86 1.1 takemura }, 87 1.1 takemura }; 88 1.1 takemura 89 1.1 takemura int 90 1.7 chs vrdcu_match(device_t parent, cfdata_t cf, void *aux) 91 1.1 takemura { 92 1.1 takemura return 2; /* 1st attach group of vrip */ 93 1.1 takemura } 94 1.1 takemura 95 1.1 takemura void 96 1.7 chs vrdcu_attach(device_t parent, device_t self, void *aux) 97 1.1 takemura { 98 1.1 takemura struct vrip_attach_args *va = aux; 99 1.7 chs struct vrdcu_softc *sc = device_private(self); 100 1.1 takemura 101 1.1 takemura sc->sc_iot = va->va_iot; 102 1.1 takemura sc->sc_chipset.dc_sc = sc; 103 1.1 takemura sc->sc_chipset.dc_enable_aiuin = vrdcu_enable_aiuin; 104 1.1 takemura sc->sc_chipset.dc_enable_aiuout = vrdcu_enable_aiuout; 105 1.1 takemura sc->sc_chipset.dc_enable_fir = vrdcu_enable_fir; 106 1.1 takemura sc->sc_chipset.dc_disable = vrdcu_disable; 107 1.1 takemura sc->sc_chipset.dc_fir_direction = vrdcu_fir_direction; 108 1.1 takemura 109 1.1 takemura if (bus_space_map(sc->sc_iot, va->va_addr, va->va_size, 110 1.1 takemura 0 /* no flags */, &sc->sc_ioh)) { 111 1.7 chs printf("%s: can't map i/o space\n", device_xname(self)); 112 1.1 takemura return; 113 1.1 takemura } 114 1.1 takemura printf("\n"); 115 1.1 takemura vrip_register_dcu(va->va_vc, &sc->sc_chipset); 116 1.1 takemura 117 1.1 takemura sc->sc_status = DMASDS; 118 1.1 takemura /* reset DCU */ 119 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMARST_REG_W, DMARST); 120 1.1 takemura } 121 1.1 takemura 122 1.1 takemura int 123 1.1 takemura vrdcu_enable_aiuin(vrdcu_chipset_tag_t dc) 124 1.1 takemura { 125 1.1 takemura struct vrdcu_softc *sc = dc->dc_sc; 126 1.1 takemura int mask; 127 1.1 takemura 128 1.1 takemura DPRINTFN(1, ("vrdcu_enable_aiuin\n")); 129 1.1 takemura 130 1.1 takemura if (sc->sc_status){ 131 1.1 takemura mask = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W); 132 1.1 takemura if (mask & DMAMSKAIN) { 133 1.1 takemura DPRINTFN(0, ("vrdcu_enable_aiuin: already enabled\n")); 134 1.1 takemura return 0; 135 1.1 takemura } else { 136 1.1 takemura DPRINTFN(0, ("vrdcu_enable_aiuin: device busy\n")); 137 1.1 takemura return EBUSY; 138 1.1 takemura } 139 1.1 takemura } 140 1.1 takemura sc->sc_status = DMASEN; 141 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W, DMAMSKAIN); 142 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMASEN_REG_W, sc->sc_status); 143 1.1 takemura return 0; 144 1.1 takemura } 145 1.1 takemura 146 1.1 takemura int 147 1.1 takemura vrdcu_enable_aiuout(vrdcu_chipset_tag_t dc) 148 1.1 takemura { 149 1.1 takemura struct vrdcu_softc *sc = dc->dc_sc; 150 1.1 takemura int mask; 151 1.1 takemura 152 1.1 takemura DPRINTFN(1, ("vrdcu_enable_aiuout\n")); 153 1.1 takemura 154 1.1 takemura if (sc->sc_status){ 155 1.1 takemura mask = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W); 156 1.1 takemura if (mask & DMAMSKAOUT) { 157 1.1 takemura DPRINTFN(0, ("vrdcu_enable_aiuout: already enabled\n")); 158 1.1 takemura return 0; 159 1.1 takemura } else { 160 1.1 takemura DPRINTFN(0, ("vrdcu_enable_aiuout: device busy\n")); 161 1.1 takemura return EBUSY; 162 1.1 takemura } 163 1.1 takemura } 164 1.1 takemura sc->sc_status = DMASEN; 165 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W, DMAMSKAOUT); 166 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMASEN_REG_W, sc->sc_status); 167 1.1 takemura return 0; 168 1.1 takemura } 169 1.1 takemura 170 1.1 takemura int 171 1.1 takemura vrdcu_enable_fir(vrdcu_chipset_tag_t dc) 172 1.1 takemura { 173 1.1 takemura struct vrdcu_softc *sc = dc->dc_sc; 174 1.1 takemura int mask; 175 1.1 takemura 176 1.1 takemura DPRINTFN(1, ("vrdcu_enable_fir\n")); 177 1.1 takemura 178 1.1 takemura if (sc->sc_status){ 179 1.1 takemura mask = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W); 180 1.1 takemura if (mask & DMAMSKFOUT) { 181 1.1 takemura DPRINTFN(0, ("vrdcu_enable_fir: already enabled\n")); 182 1.1 takemura return 0; 183 1.1 takemura } else { 184 1.1 takemura DPRINTFN(0, ("vrdcu_enable_fir: device busy\n")); 185 1.1 takemura return EBUSY; 186 1.1 takemura } 187 1.1 takemura } 188 1.1 takemura sc->sc_status = DMASEN; 189 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMAMSK_REG_W, DMAMSKFOUT); 190 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMASEN_REG_W, sc->sc_status); 191 1.1 takemura return 0; 192 1.1 takemura } 193 1.1 takemura 194 1.1 takemura void 195 1.1 takemura vrdcu_disable(vrdcu_chipset_tag_t dc) 196 1.1 takemura { 197 1.1 takemura struct vrdcu_softc *sc = dc->dc_sc; 198 1.1 takemura 199 1.1 takemura DPRINTFN(1, ("vrdcu_disable\n")); 200 1.1 takemura 201 1.1 takemura sc->sc_status = DMASDS; 202 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, DMASEN_REG_W, sc->sc_status); 203 1.1 takemura } 204 1.1 takemura 205 1.1 takemura void 206 1.1 takemura vrdcu_fir_direction(vrdcu_chipset_tag_t dc, int dir) 207 1.1 takemura { 208 1.1 takemura struct vrdcu_softc *sc = dc->dc_sc; 209 1.1 takemura 210 1.1 takemura DPRINTFN(1, ("vrdcu_fir_direction: dir %d\n", dir)); 211 1.1 takemura 212 1.1 takemura bus_space_write_2(sc->sc_iot, sc->sc_ioh, 213 1.1 takemura DMATD_REG_W, dir & DMATDMASK); 214 1.1 takemura } 215 1.1 takemura 216 1.1 takemura int 217 1.1 takemura _vrdcu_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment, 218 1.1 takemura bus_size_t boundary, bus_dma_segment_t *segs, 219 1.1 takemura int nsegs, int *rsegs, int flags) 220 1.1 takemura { 221 1.1 takemura paddr_t high; 222 1.1 takemura 223 1.1 takemura DPRINTFN(1, ("_vrdcu_dmamem_alloc\n")); 224 1.1 takemura 225 1.8 matt high = (pmap_limits.avail_end < VRDMAAU_BOUNCE_THRESHOLD ? 226 1.8 matt pmap_limits.avail_end : VRDMAAU_BOUNCE_THRESHOLD) - PAGE_SIZE; 227 1.1 takemura alignment = alignment > VRDMAAU_ALIGNMENT ? 228 1.1 takemura alignment : VRDMAAU_ALIGNMENT; 229 1.1 takemura 230 1.1 takemura return _hpcmips_bd_mem_alloc_range(t, size, alignment, boundary, 231 1.1 takemura segs, nsegs, rsegs, flags, 232 1.8 matt pmap_limits.avail_start, high); 233 1.1 takemura } 234