Home | History | Annotate | Line # | Download | only in sgimips
      1 /*	$NetBSD: bus.c,v 1.70 2023/12/20 15:29:07 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.70 2023/12/20 15:29:07 thorpej Exp $");
     35 
     36 #include <sys/param.h>
     37 #include <sys/systm.h>
     38 #include <sys/endian.h>
     39 #include <sys/bswap.h>
     40 #include <sys/kernel.h>
     41 #include <sys/device.h>
     42 #include <sys/proc.h>
     43 #include <sys/mbuf.h>
     44 
     45 #define _MIPS_BUS_DMA_PRIVATE
     46 
     47 #include <sys/bus.h>
     48 #include <machine/cpu.h>
     49 #include <machine/machtype.h>
     50 
     51 #include <uvm/uvm_extern.h>
     52 
     53 #include <mips/cpuregs.h>
     54 #include <mips/locore.h>
     55 #include <mips/cache.h>
     56 
     57 #include <sgimips/mace/macereg.h>
     58 
     59 #include "opt_sgimace.h"
     60 
     61 struct mips_bus_dma_tag sgimips_default_bus_dma_tag = {
     62 	._dmamap_ops = _BUS_DMAMAP_OPS_INITIALIZER,
     63 	._dmamem_ops = _BUS_DMAMEM_OPS_INITIALIZER,
     64 	._dmatag_ops = _BUS_DMATAG_OPS_INITIALIZER,
     65 };
     66 
     67 static void normal_bus_mem_init(bus_space_tag_t, void *);
     68 
     69 static struct mips_bus_space	normal_mbst;
     70 bus_space_tag_t	normal_memt = NULL;
     71 
     72 /*
     73  * XXX
     74  * I'm not sure how well the common MIPS bus_dma.c handles MIPS-I and I don't
     75  * have any IP1x hardware, so I'll leave this in just in case it needs to be
     76  * put back
     77  */
     78 
     79 void
     80 sgimips_bus_dma_init(void)
     81 {
     82 	normal_bus_mem_init(&normal_mbst, NULL);
     83 	normal_memt = &normal_mbst;
     84 
     85 #ifdef MIPS1
     86 	switch (mach_type) {
     87 	/* R2000/R3000 */
     88 	case MACH_SGI_IP6 | MACH_SGI_IP10: /* same number... */
     89 	case MACH_SGI_IP12:
     90 		sgimips_default_bus_dma_tag._dmamap_ops.dmamap_sync =
     91 		    _bus_dmamap_sync_mips1;
     92 		break;
     93 	}
     94 #endif
     95 }
     96 
     97 /*
     98  * XXX
     99  * left in for illustrative purposes
    100  */
    101 
    102 #if 0
    103 u_int8_t
    104 bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
    105 {
    106 	wbflush(); /* XXX ? */
    107 
    108 	switch (t) {
    109 	case SGIMIPS_BUS_SPACE_NORMAL:
    110 		return *(volatile u_int8_t *)(vaddr_t)(h + o);
    111 	case SGIMIPS_BUS_SPACE_IP6_DPCLOCK:
    112 		return *(volatile u_int8_t *)(vaddr_t)(h + (o << 2));
    113 	case SGIMIPS_BUS_SPACE_HPC:
    114 		return *(volatile u_int8_t *)(vaddr_t)(h + (o << 2) + 3);
    115 	case SGIMIPS_BUS_SPACE_MEM:
    116 	case SGIMIPS_BUS_SPACE_IO:
    117 		return *(volatile u_int8_t *)(vaddr_t)(h + (o | 3) - (o & 3));
    118 	case SGIMIPS_BUS_SPACE_MACE:
    119 		return *(volatile u_int8_t *)(vaddr_t)(h + (o << 8) + 7);
    120 	default:
    121 		panic("no bus tag");
    122 	}
    123 }
    124 #endif
    125 
    126 #ifdef MIPS1
    127 /* Common function from DMA map synchronization. May be called
    128  * by chipset-specific DMA map synchronization functions.
    129  *
    130  * This is the R3000 version.
    131  */
    132 void
    133 _bus_dmamap_sync_mips1(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
    134 		       bus_size_t len, int ops)
    135 {
    136 	bus_size_t minlen;
    137 	bus_addr_t addr;
    138 	int i;
    139 
    140 	/*
    141 	 * Mixing PRE and POST operations is not allowed.
    142 	 */
    143 	 if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
    144 	     (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
    145 		 panic("_bus_dmamap_sync_mips1: mix PRE and POST");
    146 
    147 #ifdef DIAGNOSTIC
    148 	if (offset >= map->dm_mapsize)
    149 		panic("_bus_dmamap_sync_mips1: bad offset %"PRIxPSIZE
    150 		" (map size is %"PRIxPSIZE")"
    151 		    , offset, map->dm_mapsize);
    152 	if (len == 0 || (offset + len) > map->dm_mapsize)
    153 		panic("_bus_dmamap_sync_mips1: bad length");
    154 #endif
    155 
    156 	/*
    157 	 * The R3000 cache is write-through. Therefore, we only need
    158 	 * to drain the write buffer on PREWRITE. The cache is not
    159 	 * coherent, however, so we need to invalidate the data cache
    160 	 * on PREREAD (should we do it POSTREAD instead?).
    161 	 *
    162 	 * POSTWRITE (and POSTREAD, currently) are noops.
    163 	 */
    164 
    165 	if (ops & BUS_DMASYNC_PREWRITE) {
    166 		/*
    167 		 * Flush the write buffer.
    168 		 */
    169 		 wbflush();
    170 	 }
    171 
    172 	/*
    173 	 * If we're not doing PREREAD, nothing more to do.
    174 	 */
    175 	if ((ops & BUS_DMASYNC_PREREAD) == 0)
    176 		return;
    177 
    178 	/*
    179 	 * No cache invalidation is necessary if the DMA map covers
    180 	 * COHERENT DMA-safe memory (which is mapped un-cached).
    181 	 */
    182 	if (map->_dm_flags & SGIMIPS_DMAMAP_COHERENT)
    183 		return;
    184 
    185 	/*
    186 	 * If we are going to hit something as large or larger
    187 	 * than the entire data cache, just nail the whole thing.
    188 	 *
    189 	 * NOTE: Even though this is `wbinv_all', since the cache is
    190 	 * write-through, it just invalidates it.
    191 	 */
    192 	if (len >= mips_cache_info.mci_pdcache_size) {
    193 		mips_dcache_wbinv_all();
    194 		return;
    195 	}
    196 
    197 	for (i = 0; i < map->dm_nsegs && len != 0; i++) {
    198 		/* Find the beginning segment. */
    199 		if (offset >= map->dm_segs[i].ds_len) {
    200 			offset -= map->dm_segs[i].ds_len;
    201 			continue;
    202 		}
    203 
    204 		/*
    205 		 * Now at the first segment to sync; nail
    206 		 * each segment until we have exhausted the
    207 		 * length.
    208 		 */
    209 		minlen = len < map->dm_segs[i].ds_len - offset ?
    210 		    len : map->dm_segs[i].ds_len - offset;
    211 
    212 		addr = map->dm_segs[i].ds_addr;
    213 
    214 #ifdef BUS_DMA_DEBUG
    215 		printf("bus_dmamap_sync_mips1: flushing segment %d "
    216 		    "(0x%"PRIxBUSADDR"..0x%"PRIxBUSADDR") ...", i,
    217 		    addr + offset, addr + offset + minlen - 1);
    218 #endif
    219 		mips_dcache_inv_range(
    220 		    MIPS_PHYS_TO_KSEG0(addr + offset), minlen);
    221 #ifdef BUS_DMA_DEBUG
    222 		printf("\n");
    223 #endif
    224 		offset = 0;
    225 		len -= minlen;
    226 	}
    227 }
    228 #endif
    229 
    230 #define CHIP	   		normal
    231 #define	CHIP_MEM		/* defined */
    232 #define	CHIP_W1_BUS_START(v)	0x00000000UL
    233 #define CHIP_W1_BUS_END(v)	0xffffffffUL
    234 #define	CHIP_W1_SYS_START(v)	0x00000000UL
    235 #define	CHIP_W1_SYS_END(v)	0xffffffffUL
    236 
    237 #include <mips/mips/bus_space_alignstride_chipdep.c>
    238