]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
74588d8b HS |
2 | /* |
3 | * Re-map IO memory to kernel address space so that we can access it. | |
4 | * This is needed for high PCI addresses that aren't mapped in the | |
5 | * 640k-1MB IO memory area on PC's | |
6 | * | |
7 | * (C) Copyright 1995 1996 Linus Torvalds | |
8 | */ | |
74588d8b HS |
9 | #include <linux/vmalloc.h> |
10 | #include <linux/mm.h> | |
e8edc6e0 | 11 | #include <linux/sched.h> |
53fa6645 | 12 | #include <linux/io.h> |
8bc3bcc9 | 13 | #include <linux/export.h> |
74588d8b | 14 | #include <asm/cacheflush.h> |
74588d8b | 15 | |
2a681cfa JR |
16 | #include "pgalloc-track.h" |
17 | ||
0ddab1d2 | 18 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP |
86d0c164 | 19 | static unsigned int __ro_after_init iomap_max_page_shift = BITS_PER_LONG - 1; |
0ddab1d2 TK |
20 | |
21 | static int __init set_nohugeiomap(char *str) | |
22 | { | |
86d0c164 | 23 | iomap_max_page_shift = PAGE_SHIFT; |
0ddab1d2 TK |
24 | return 0; |
25 | } | |
26 | early_param("nohugeiomap", set_nohugeiomap); | |
bbc180a5 | 27 | #else /* CONFIG_HAVE_ARCH_HUGE_VMAP */ |
86d0c164 | 28 | static const unsigned int iomap_max_page_shift = PAGE_SHIFT; |
0ddab1d2 TK |
29 | #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ |
30 | ||
95f0ddf0 NP |
31 | int ioremap_page_range(unsigned long addr, |
32 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) | |
33 | { | |
bbc180a5 | 34 | return vmap_range(addr, end, phys_addr, prot, iomap_max_page_shift); |
95f0ddf0 NP |
35 | } |
36 | ||
80b0ca98 CH |
37 | #ifdef CONFIG_GENERIC_IOREMAP |
38 | void __iomem *ioremap_prot(phys_addr_t addr, size_t size, unsigned long prot) | |
39 | { | |
40 | unsigned long offset, vaddr; | |
41 | phys_addr_t last_addr; | |
42 | struct vm_struct *area; | |
43 | ||
44 | /* Disallow wrap-around or zero size */ | |
45 | last_addr = addr + size - 1; | |
46 | if (!size || last_addr < addr) | |
47 | return NULL; | |
48 | ||
49 | /* Page-align mappings */ | |
50 | offset = addr & (~PAGE_MASK); | |
51 | addr -= offset; | |
52 | size = PAGE_ALIGN(size + offset); | |
53 | ||
54 | area = get_vm_area_caller(size, VM_IOREMAP, | |
55 | __builtin_return_address(0)); | |
56 | if (!area) | |
57 | return NULL; | |
58 | vaddr = (unsigned long)area->addr; | |
59 | ||
60 | if (ioremap_page_range(vaddr, vaddr + size, addr, __pgprot(prot))) { | |
61 | free_vm_area(area); | |
62 | return NULL; | |
63 | } | |
64 | ||
65 | return (void __iomem *)(vaddr + offset); | |
66 | } | |
67 | EXPORT_SYMBOL(ioremap_prot); | |
68 | ||
69 | void iounmap(volatile void __iomem *addr) | |
70 | { | |
71 | vunmap((void *)((unsigned long)addr & PAGE_MASK)); | |
72 | } | |
73 | EXPORT_SYMBOL(iounmap); | |
74 | #endif /* CONFIG_GENERIC_IOREMAP */ |