xref: /linux/arch/csky/mm/ioremap.c (revision 7f80fe207de9602aaff028c79345caa68c90cd31)
1013de2d6SGuo Ren // SPDX-License-Identifier: GPL-2.0
2013de2d6SGuo Ren // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3013de2d6SGuo Ren 
4013de2d6SGuo Ren #include <linux/export.h>
5013de2d6SGuo Ren #include <linux/mm.h>
6013de2d6SGuo Ren #include <linux/vmalloc.h>
7013de2d6SGuo Ren #include <linux/io.h>
8013de2d6SGuo Ren 
9013de2d6SGuo Ren #include <asm/pgtable.h>
10013de2d6SGuo Ren 
11013de2d6SGuo Ren void __iomem *ioremap(phys_addr_t addr, size_t size)
12013de2d6SGuo Ren {
13013de2d6SGuo Ren 	phys_addr_t last_addr;
14013de2d6SGuo Ren 	unsigned long offset, vaddr;
15013de2d6SGuo Ren 	struct vm_struct *area;
16013de2d6SGuo Ren 	pgprot_t prot;
17013de2d6SGuo Ren 
18013de2d6SGuo Ren 	last_addr = addr + size - 1;
19013de2d6SGuo Ren 	if (!size || last_addr < addr)
20013de2d6SGuo Ren 		return NULL;
21013de2d6SGuo Ren 
22013de2d6SGuo Ren 	offset = addr & (~PAGE_MASK);
23013de2d6SGuo Ren 	addr &= PAGE_MASK;
24013de2d6SGuo Ren 	size = PAGE_ALIGN(size + offset);
25013de2d6SGuo Ren 
26013de2d6SGuo Ren 	area = get_vm_area_caller(size, VM_ALLOC, __builtin_return_address(0));
27013de2d6SGuo Ren 	if (!area)
28013de2d6SGuo Ren 		return NULL;
29013de2d6SGuo Ren 
30013de2d6SGuo Ren 	vaddr = (unsigned long)area->addr;
31013de2d6SGuo Ren 
32*7f80fe20SGuo Ren 	prot = pgprot_noncached(PAGE_KERNEL);
33013de2d6SGuo Ren 
34013de2d6SGuo Ren 	if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
35013de2d6SGuo Ren 		free_vm_area(area);
36013de2d6SGuo Ren 		return NULL;
37013de2d6SGuo Ren 	}
38013de2d6SGuo Ren 
39013de2d6SGuo Ren 	return (void __iomem *)(vaddr + offset);
40013de2d6SGuo Ren }
41013de2d6SGuo Ren EXPORT_SYMBOL(ioremap);
42013de2d6SGuo Ren 
43013de2d6SGuo Ren void iounmap(void __iomem *addr)
44013de2d6SGuo Ren {
45013de2d6SGuo Ren 	vunmap((void *)((unsigned long)addr & PAGE_MASK));
46013de2d6SGuo Ren }
47013de2d6SGuo Ren EXPORT_SYMBOL(iounmap);
4876d21d18SGuo Ren 
4976d21d18SGuo Ren pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
5076d21d18SGuo Ren 			      unsigned long size, pgprot_t vma_prot)
5176d21d18SGuo Ren {
5276d21d18SGuo Ren 	if (!pfn_valid(pfn)) {
5376d21d18SGuo Ren 		return pgprot_noncached(vma_prot);
5476d21d18SGuo Ren 	} else if (file->f_flags & O_SYNC) {
55*7f80fe20SGuo Ren 		return pgprot_writecombine(vma_prot);
5676d21d18SGuo Ren 	}
5776d21d18SGuo Ren 
5876d21d18SGuo Ren 	return vma_prot;
5976d21d18SGuo Ren }
6076d21d18SGuo Ren EXPORT_SYMBOL(phys_mem_access_prot);
61