xref: /netbsd-src/sys/arch/arc/jazz/jazzdmatlb.c (revision 8ff6f65dafc58186614d149001c905dec4c934a2)
1*8ff6f65dSthorpej /*	$NetBSD: jazzdmatlb.c,v 1.18 2023/12/20 06:36:02 thorpej Exp $	*/
231a9a256Ssoda /*	$OpenBSD: dma.c,v 1.5 1998/03/01 16:49:57 niklas Exp $	*/
331a9a256Ssoda 
431a9a256Ssoda /*-
531a9a256Ssoda  * Copyright (C) 2000 Shuichiro URATA.  All rights reserved.
631a9a256Ssoda  *
731a9a256Ssoda  * Redistribution and use in source and binary forms, with or without
831a9a256Ssoda  * modification, are permitted provided that the following conditions
931a9a256Ssoda  * are met:
1031a9a256Ssoda  * 1. Redistributions of source code must retain the above copyright
1131a9a256Ssoda  *    notice, this list of conditions and the following disclaimer.
1231a9a256Ssoda  * 2. Redistributions in binary form must reproduce the above copyright
1331a9a256Ssoda  *    notice, this list of conditions and the following disclaimer in the
1431a9a256Ssoda  *    documentation and/or other materials provided with the distribution.
1531a9a256Ssoda  * 3. The name of the author may not be used to endorse or promote products
1631a9a256Ssoda  *    derived from this software without specific prior written permission.
1731a9a256Ssoda  *
1831a9a256Ssoda  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1931a9a256Ssoda  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2031a9a256Ssoda  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2131a9a256Ssoda  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2231a9a256Ssoda  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2331a9a256Ssoda  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2431a9a256Ssoda  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2531a9a256Ssoda  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2631a9a256Ssoda  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2731a9a256Ssoda  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2831a9a256Ssoda  */
2931a9a256Ssoda 
3031a9a256Ssoda /*
3131a9a256Ssoda  * Jazz derived system dma driver. Handles resource allocation and
3231a9a256Ssoda  * logical (virtual) address remaping.
3331a9a256Ssoda  */
3431a9a256Ssoda 
35a4183603Slukem #include <sys/cdefs.h>
36*8ff6f65dSthorpej __KERNEL_RCSID(0, "$NetBSD: jazzdmatlb.c,v 1.18 2023/12/20 06:36:02 thorpej Exp $");
37a4183603Slukem 
3831a9a256Ssoda #include <sys/param.h>
3931a9a256Ssoda #include <sys/systm.h>
4031a9a256Ssoda #include <sys/device.h>
4180373b7eSchs #include <sys/proc.h>
42d8673138Sthorpej #include <sys/vmem.h>
4331a9a256Ssoda 
4447ef8ee9Smrg #include <uvm/uvm_extern.h>
4531a9a256Ssoda 
4631a9a256Ssoda #include <machine/autoconf.h>
47cf10107dSdyoung #include <sys/bus.h>
4831a9a256Ssoda 
4931a9a256Ssoda #include <arc/jazz/jazzdmatlbreg.h>
5031a9a256Ssoda #include <arc/jazz/jazzdmatlbvar.h>
5131a9a256Ssoda 
52af66038fSthorpej #include <mips/cache.h>
53af66038fSthorpej 
547fe2a5a0Stsutsui extern paddr_t	kvtophys(vaddr_t);	/* XXX */
5531a9a256Ssoda 
5631a9a256Ssoda #define NDMATLB		(JAZZ_DMATLB_SIZE / sizeof(jazz_dma_pte_t))
5731a9a256Ssoda 
5831a9a256Ssoda static bus_space_tag_t dmatlb_iot;
5931a9a256Ssoda static bus_space_handle_t dmatlb_ioh;
6031a9a256Ssoda 
61d8673138Sthorpej static vmem_t *dmatlb_arena;
6231a9a256Ssoda static jazz_dma_pte_t *dma_tlb;
6331a9a256Ssoda 
6431a9a256Ssoda /*
6531a9a256Ssoda  *  Initialize the dma mapping register area and pool.
6631a9a256Ssoda  */
6731a9a256Ssoda void
jazz_dmatlb_init(bus_space_tag_t iot,bus_addr_t ioaddr)687fe2a5a0Stsutsui jazz_dmatlb_init(bus_space_tag_t iot, bus_addr_t ioaddr)
6931a9a256Ssoda {
7031a9a256Ssoda 	int err;
7131a9a256Ssoda 
7231a9a256Ssoda 	dmatlb_iot = iot;
7331a9a256Ssoda 	err = bus_space_map(iot, ioaddr, JAZZ_DMATLB_REGSIZE, 0, &dmatlb_ioh);
7431a9a256Ssoda 	if (err != 0)
750f09ed48Sprovos 		panic("jazz_dmatlb_init: cannot map 0x%lx", ioaddr);
7631a9a256Ssoda 
7731a9a256Ssoda 	dma_tlb = (jazz_dma_pte_t *)PICA_TL_BASE;
7831a9a256Ssoda 
79af66038fSthorpej 	mips_dcache_wbinv_all();/* Make sure no map entries are cached */
8066f3c84bStsutsui 	memset((char *)dma_tlb, 0, JAZZ_DMATLB_SIZE);
8131a9a256Ssoda 
82d8673138Sthorpej 	dmatlb_arena = vmem_create("dmatlb", 0, NDMATLB,
83d8673138Sthorpej 				   1,		/* quantum */
84d8673138Sthorpej 				   NULL,	/* importfn */
85d8673138Sthorpej 				   NULL,	/* releasefn */
86d8673138Sthorpej 				   NULL,	/* source */
87d8673138Sthorpej 				   0,		/* qcache_max */
88d8673138Sthorpej 				   VM_SLEEP,
89d8673138Sthorpej 				   IPL_VM);
90d8673138Sthorpej 	KASSERT(dmatlb_arena != NULL);
9131a9a256Ssoda 
9231a9a256Ssoda 	bus_space_write_4(dmatlb_iot, dmatlb_ioh, JAZZ_DMATLBREG_MAP,
9331a9a256Ssoda 	    MIPS_KSEG1_TO_PHYS(dma_tlb));
9431a9a256Ssoda 	bus_space_write_4(dmatlb_iot, dmatlb_ioh, JAZZ_DMATLBREG_LIMIT,
9531a9a256Ssoda 	    JAZZ_DMATLB_SIZE);
9631a9a256Ssoda 	jazz_dmatlb_flush();
9731a9a256Ssoda }
9831a9a256Ssoda 
9931a9a256Ssoda /*
10031a9a256Ssoda  *  Allocate an array of 'size' DMA PTEs.
10131a9a256Ssoda  *  Return address to first pte.
10231a9a256Ssoda  */
10331a9a256Ssoda jazz_dma_pte_t *
jazz_dmatlb_alloc(int npte,bus_size_t boundary,int flags,bus_addr_t * addr)1047fe2a5a0Stsutsui jazz_dmatlb_alloc(int npte, bus_size_t boundary, int flags, bus_addr_t *addr)
10531a9a256Ssoda {
106d8673138Sthorpej 	vmem_addr_t start;
10731a9a256Ssoda 	int err;
10831a9a256Ssoda 
109d8673138Sthorpej 	const vm_flag_t vmflags = VM_INSTANTFIT |
110d8673138Sthorpej 	    ((flags & BUS_DMA_WAITOK) ? VM_SLEEP : VM_NOSLEEP);
111d8673138Sthorpej 
112d8673138Sthorpej 	err = vmem_xalloc(dmatlb_arena, npte,
113d8673138Sthorpej 			  1,			/* align */
114d8673138Sthorpej 			  0,			/* phase */
115d8673138Sthorpej 			  boundary / JAZZ_DMA_PAGE_SIZE,
116d8673138Sthorpej 			  VMEM_ADDR_MIN,
117d8673138Sthorpej 			  VMEM_ADDR_MAX,
118d8673138Sthorpej 			  vmflags,
11931a9a256Ssoda 			  &start);
12031a9a256Ssoda 	if (err)
1217fe2a5a0Stsutsui 		return NULL;
12231a9a256Ssoda 
12331a9a256Ssoda 	*addr = start * JAZZ_DMA_PAGE_SIZE;
12431a9a256Ssoda 
1257fe2a5a0Stsutsui 	return dma_tlb + start;
12631a9a256Ssoda }
12731a9a256Ssoda 
12831a9a256Ssoda /*
12931a9a256Ssoda  *  Free an array of DMA PTEs.
13031a9a256Ssoda  */
13131a9a256Ssoda void
jazz_dmatlb_free(bus_addr_t addr,int npte)1327fe2a5a0Stsutsui jazz_dmatlb_free(bus_addr_t addr, int npte)
13331a9a256Ssoda {
134d8673138Sthorpej 	vmem_addr_t start;
13531a9a256Ssoda 
13631a9a256Ssoda 	start = addr / JAZZ_DMA_PAGE_SIZE;
137d8673138Sthorpej 	vmem_xfree(dmatlb_arena, start, npte);
13831a9a256Ssoda }
13931a9a256Ssoda 
14031a9a256Ssoda /*
14131a9a256Ssoda  *  Map up a virtual address space in dma space given by
14231a9a256Ssoda  *  the dma control structure.
14331a9a256Ssoda  */
14431a9a256Ssoda void
jazz_dmatlb_map_va(struct vmspace * vm,vaddr_t va,vsize_t size,jazz_dma_pte_t * dma_pte)145ec5a9318Syamt jazz_dmatlb_map_va(struct vmspace *vm, vaddr_t va, vsize_t size,
1467fe2a5a0Stsutsui     jazz_dma_pte_t *dma_pte)
14731a9a256Ssoda {
14831a9a256Ssoda 	paddr_t pa;
14931a9a256Ssoda 
15031a9a256Ssoda 	size = jazz_dma_page_round(size + jazz_dma_page_offs(va));
15131a9a256Ssoda 	va &= JAZZ_DMA_PAGE_NUM;
15231a9a256Ssoda 	while (size > 0) {
153ec5a9318Syamt 		if (!VMSPACE_IS_KERNEL_P(vm))
154ec5a9318Syamt 			(void)pmap_extract(vm_map_pmap(&vm->vm_map), va, &pa);
15531a9a256Ssoda 		else
15631a9a256Ssoda 			pa = kvtophys(va);
15731a9a256Ssoda 
15831a9a256Ssoda 		pa &= JAZZ_DMA_PAGE_NUM;
15931a9a256Ssoda 		dma_pte->lo_addr = pa;
16031a9a256Ssoda 		dma_pte->hi_addr = 0;
16131a9a256Ssoda 		dma_pte++;
16231a9a256Ssoda 		va += JAZZ_DMA_PAGE_SIZE;
16331a9a256Ssoda 		size -= JAZZ_DMA_PAGE_SIZE;
16431a9a256Ssoda 	}
16531a9a256Ssoda }
16631a9a256Ssoda 
16731a9a256Ssoda /*
16831a9a256Ssoda  *  Map up a physical address space in dma space given by
16931a9a256Ssoda  *  the dma control structure.
17031a9a256Ssoda  */
17131a9a256Ssoda void
jazz_dmatlb_map_pa(paddr_t pa,psize_t size,jazz_dma_pte_t * dma_pte)1727fe2a5a0Stsutsui jazz_dmatlb_map_pa(paddr_t pa, psize_t size, jazz_dma_pte_t *dma_pte)
17331a9a256Ssoda {
1747fe2a5a0Stsutsui 
17531a9a256Ssoda 	size = jazz_dma_page_round(size + jazz_dma_page_offs(pa));
17631a9a256Ssoda 	pa &= JAZZ_DMA_PAGE_NUM;
17731a9a256Ssoda 	while (size > 0) {
17831a9a256Ssoda 		dma_pte->lo_addr = pa;
17931a9a256Ssoda 		dma_pte->hi_addr = 0;
18031a9a256Ssoda 		dma_pte++;
18131a9a256Ssoda 		pa += JAZZ_DMA_PAGE_SIZE;
18231a9a256Ssoda 		size -= JAZZ_DMA_PAGE_SIZE;
18331a9a256Ssoda 	}
18431a9a256Ssoda }
18531a9a256Ssoda 
18631a9a256Ssoda /*
18731a9a256Ssoda  *  Prepare for new dma by flushing
18831a9a256Ssoda  */
18931a9a256Ssoda void
jazz_dmatlb_flush(void)1907fe2a5a0Stsutsui jazz_dmatlb_flush(void)
19131a9a256Ssoda {
1927fe2a5a0Stsutsui 
19331a9a256Ssoda 	bus_space_write_4(dmatlb_iot, dmatlb_ioh, JAZZ_DMATLBREG_IVALID, 0);
19431a9a256Ssoda }
195