xref: /dragonfly/sys/dev/drm/linux_iomapping.c (revision 3f2dd94a)
124409b39SFrançois Tigeot /*
224059068SFrançois Tigeot  * Copyright (c) 2014-2019 François Tigeot <ftigeot@wolfpond.org>
324409b39SFrançois Tigeot  * All rights reserved.
424409b39SFrançois Tigeot  *
524409b39SFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
624409b39SFrançois Tigeot  * modification, are permitted provided that the following conditions
724409b39SFrançois Tigeot  * are met:
824409b39SFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
924409b39SFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
1024409b39SFrançois Tigeot  *    disclaimer.
1124409b39SFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
1224409b39SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
1324409b39SFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
1424409b39SFrançois Tigeot  *
1524409b39SFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1624409b39SFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1724409b39SFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1824409b39SFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1924409b39SFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2024409b39SFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2124409b39SFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2224409b39SFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2324409b39SFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2424409b39SFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2524409b39SFrançois Tigeot  */
2624409b39SFrançois Tigeot 
2724409b39SFrançois Tigeot #include <machine/pmap.h>
2824409b39SFrançois Tigeot #include <vm/pmap.h>
2924409b39SFrançois Tigeot #include <vm/vm.h>
3024409b39SFrançois Tigeot 
3124409b39SFrançois Tigeot #include <linux/kernel.h>
3224409b39SFrançois Tigeot #include <linux/slab.h>
33742b09c6Szrj #include <linux/bug.h>
3424409b39SFrançois Tigeot #include <asm/page.h>
3524409b39SFrançois Tigeot #include <asm/io.h>
3624409b39SFrançois Tigeot 
3724059068SFrançois Tigeot struct lock iomap_lock = LOCK_INITIALIZER("dlioml", 0, LK_CANRECURSE);
3824059068SFrançois Tigeot 
3924409b39SFrançois Tigeot SLIST_HEAD(iomap_list_head, iomap) iomap_list = SLIST_HEAD_INITIALIZER(iomap_list);
4024409b39SFrançois Tigeot 
417c3d2bf2SFrançois Tigeot void __iomem *
__ioremap_common(unsigned long phys_addr,unsigned long size,int cache_mode)427c3d2bf2SFrançois Tigeot __ioremap_common(unsigned long phys_addr, unsigned long size, int cache_mode)
4324409b39SFrançois Tigeot {
4424409b39SFrançois Tigeot 	struct iomap *imp;
4524409b39SFrançois Tigeot 
4624409b39SFrançois Tigeot 	/* Ensure mappings are page-aligned */
4724409b39SFrançois Tigeot 	BUG_ON(phys_addr & PAGE_MASK);
4824409b39SFrançois Tigeot 	BUG_ON(size & PAGE_MASK);
4924409b39SFrançois Tigeot 
5024409b39SFrançois Tigeot 	imp = kmalloc(sizeof(struct iomap), M_DRM, M_WAITOK);
5124409b39SFrançois Tigeot 	imp->paddr = phys_addr;
5224409b39SFrançois Tigeot 	imp->npages = size / PAGE_SIZE;
537c3d2bf2SFrançois Tigeot 	imp->pmap_addr = pmap_mapdev_attr(phys_addr, size, cache_mode);
5424059068SFrançois Tigeot 	lockmgr(&iomap_lock, LK_EXCLUSIVE);
5524409b39SFrançois Tigeot 	SLIST_INSERT_HEAD(&iomap_list, imp, im_iomaps);
5624059068SFrançois Tigeot 	lockmgr(&iomap_lock, LK_RELEASE);
5724409b39SFrançois Tigeot 
587c3d2bf2SFrançois Tigeot 	return imp->pmap_addr;
5924409b39SFrançois Tigeot }
6024409b39SFrançois Tigeot 
iounmap(void __iomem * ptr)6124409b39SFrançois Tigeot void iounmap(void __iomem *ptr)
6224409b39SFrançois Tigeot {
6324409b39SFrançois Tigeot 	struct iomap *imp, *tmp_imp;
6424409b39SFrançois Tigeot 	int found = 0;
6524409b39SFrançois Tigeot 	int indx;
6624409b39SFrançois Tigeot 	vm_paddr_t paddr_end;
6724409b39SFrançois Tigeot 
6824409b39SFrançois Tigeot 	SLIST_FOREACH_MUTABLE(imp, &iomap_list, im_iomaps, tmp_imp) {
6924409b39SFrançois Tigeot 		if (imp->pmap_addr == ptr) {
7024409b39SFrançois Tigeot 			found = 1;
7124409b39SFrançois Tigeot 			break;
7224409b39SFrançois Tigeot 		}
7324409b39SFrançois Tigeot 	}
7424409b39SFrançois Tigeot 
7524409b39SFrançois Tigeot 	if (!found) {
7624409b39SFrançois Tigeot 		kprintf("iounmap: invalid address %p\n", ptr);
7724409b39SFrançois Tigeot 		return;
7824409b39SFrançois Tigeot 	}
7924409b39SFrançois Tigeot 
8024409b39SFrançois Tigeot 	paddr_end = imp->paddr + (imp->npages * PAGE_SIZE) - 1;
8124409b39SFrançois Tigeot 	/* Is this address space range backed by regular memory ? */
8277c48adbSMatthew Dillon 	for (indx = 0; phys_avail[indx].phys_end != 0; ++indx) {
8377c48adbSMatthew Dillon 		vm_paddr_t range_start = phys_avail[indx].phys_beg;
8477c48adbSMatthew Dillon 		vm_paddr_t size = phys_avail[indx].phys_end -
8577c48adbSMatthew Dillon 				  phys_avail[indx].phys_beg;
8624409b39SFrançois Tigeot 		vm_paddr_t range_end = range_start + size - 1;
8724409b39SFrançois Tigeot 
8824409b39SFrançois Tigeot 		if ((imp->paddr >= range_start) && (paddr_end <= range_end)) {
8924409b39SFrançois Tigeot 			/* Yes, change page caching attributes */
9024409b39SFrançois Tigeot 			pmap_change_attr(imp->paddr, imp->npages, PAT_WRITE_BACK);
9124409b39SFrançois Tigeot 			break;
9224409b39SFrançois Tigeot 		}
9324409b39SFrançois Tigeot 
9424409b39SFrançois Tigeot 	}
9524409b39SFrançois Tigeot 
9624409b39SFrançois Tigeot 	pmap_unmapdev((vm_offset_t)imp->pmap_addr, imp->npages * PAGE_SIZE);
9724409b39SFrançois Tigeot 
9824059068SFrançois Tigeot 	lockmgr(&iomap_lock, LK_EXCLUSIVE);
9924409b39SFrançois Tigeot 	SLIST_REMOVE(&iomap_list, imp, iomap, im_iomaps);
10024059068SFrançois Tigeot 	lockmgr(&iomap_lock, LK_RELEASE);
10124059068SFrançois Tigeot 
10224409b39SFrançois Tigeot 	kfree(imp);
10324409b39SFrançois Tigeot }
104*3f2dd94aSFrançois Tigeot 
105*3f2dd94aSFrançois Tigeot #include <sys/memrange.h>
106*3f2dd94aSFrançois Tigeot 
107*3f2dd94aSFrançois Tigeot int
arch_io_reserve_memtype_wc(resource_size_t start,resource_size_t size)108*3f2dd94aSFrançois Tigeot arch_io_reserve_memtype_wc(resource_size_t start, resource_size_t size)
109*3f2dd94aSFrançois Tigeot {
110*3f2dd94aSFrançois Tigeot 	int act;
111*3f2dd94aSFrançois Tigeot 	struct mem_range_desc mrdesc;
112*3f2dd94aSFrançois Tigeot 
113*3f2dd94aSFrançois Tigeot 	mrdesc.mr_base = start;
114*3f2dd94aSFrançois Tigeot 	mrdesc.mr_len = size;
115*3f2dd94aSFrançois Tigeot 	mrdesc.mr_flags = MDF_WRITECOMBINE;
116*3f2dd94aSFrançois Tigeot 	act = MEMRANGE_SET_UPDATE;
117*3f2dd94aSFrançois Tigeot 	strlcpy(mrdesc.mr_owner, "drm", sizeof(mrdesc.mr_owner));
118*3f2dd94aSFrançois Tigeot 	return mem_range_attr_set(&mrdesc, &act);
119*3f2dd94aSFrançois Tigeot }
120