1 // SPDX-License-Identifier: GPL-2.0
3 * Re-map IO memory to kernel address space so that we can access it.
5 * These functions should only be used when it is necessary to map a
6 * physical address space into the kernel address space before ioremap()
7 * can be used, e.g. early in boot before paging_init().
9 * Copyright (C) 2009 Matt Fleming
12 #include <linux/vmalloc.h>
13 #include <linux/ioport.h>
14 #include <linux/module.h>
17 #include <linux/memblock.h>
18 #include <linux/proc_fs.h>
19 #include <asm/fixmap.h>
21 #include <asm/addrspace.h>
22 #include <asm/cacheflush.h>
23 #include <asm/tlbflush.h>
25 #include <asm/mmu_context.h>
31 unsigned long fixmap_addr
;
34 static struct ioremap_map ioremap_maps
[FIX_N_IOREMAPS
];
36 void __init
ioremap_fixed_init(void)
38 struct ioremap_map
*map
;
41 for (i
= 0; i
< FIX_N_IOREMAPS
; i
++) {
42 map
= &ioremap_maps
[i
];
43 map
->fixmap_addr
= __fix_to_virt(FIX_IOREMAP_BEGIN
+ i
);
48 ioremap_fixed(phys_addr_t phys_addr
, unsigned long size
, pgprot_t prot
)
50 enum fixed_addresses idx0
, idx
;
51 struct ioremap_map
*map
;
57 * Mappings have to be page-aligned
59 offset
= phys_addr
& ~PAGE_MASK
;
60 phys_addr
&= PAGE_MASK
;
61 size
= PAGE_ALIGN(phys_addr
+ size
) - phys_addr
;
64 for (i
= 0; i
< FIX_N_IOREMAPS
; i
++) {
65 map
= &ioremap_maps
[i
];
77 * Mappings have to fit in the FIX_IOREMAP area.
79 nrpages
= size
>> PAGE_SHIFT
;
80 if (nrpages
> FIX_N_IOREMAPS
)
86 idx0
= FIX_IOREMAP_BEGIN
+ slot
;
89 pgprot_val(prot
) |= _PAGE_WIRED
;
90 __set_fixmap(idx
, phys_addr
, prot
);
91 phys_addr
+= PAGE_SIZE
;
96 map
->addr
= (void __iomem
*)(offset
+ map
->fixmap_addr
);
100 int iounmap_fixed(void __iomem
*addr
)
102 enum fixed_addresses idx
;
103 struct ioremap_map
*map
;
104 unsigned int nrpages
;
108 for (i
= 0; i
< FIX_N_IOREMAPS
; i
++) {
109 map
= &ioremap_maps
[i
];
110 if (map
->addr
== addr
) {
117 * If we don't match, it's not for us.
122 nrpages
= map
->size
>> PAGE_SHIFT
;
124 idx
= FIX_IOREMAP_BEGIN
+ slot
+ nrpages
- 1;
125 while (nrpages
> 0) {
126 __clear_fixmap(idx
, __pgprot(_PAGE_WIRED
));