1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Re-map IO memory to kernel address space so that we can access it. 4 * 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(). 8 * 9 * Copyright (C) 2009 Matt Fleming 10 */ 11 12 #include <linux/vmalloc.h> 13 #include <linux/ioport.h> 14 #include <linux/module.h> 15 #include <linux/mm.h> 16 #include <linux/io.h> 17 #include <linux/memblock.h> 18 #include <linux/proc_fs.h> 19 #include <asm/fixmap.h> 20 #include <asm/page.h> 21 #include <asm/pgalloc.h> 22 #include <asm/addrspace.h> 23 #include <asm/cacheflush.h> 24 #include <asm/tlbflush.h> 25 #include <asm/mmu.h> 26 #include <asm/mmu_context.h> 27 28 struct ioremap_map { 29 void __iomem *addr; 30 unsigned long size; 31 unsigned long fixmap_addr; 32 }; 33 34 static struct ioremap_map ioremap_maps[FIX_N_IOREMAPS]; 35 36 void __init ioremap_fixed_init(void) 37 { 38 struct ioremap_map *map; 39 int i; 40 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); 44 } 45 } 46 47 void __init __iomem * 48 ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot) 49 { 50 enum fixed_addresses idx0, idx; 51 struct ioremap_map *map; 52 unsigned int nrpages; 53 unsigned long offset; 54 int i, slot; 55 56 /* 57 * Mappings have to be page-aligned 58 */ 59 offset = phys_addr & ~PAGE_MASK; 60 phys_addr &= PAGE_MASK; 61 size = PAGE_ALIGN(phys_addr + size) - phys_addr; 62 63 slot = -1; 64 for (i = 0; i < FIX_N_IOREMAPS; i++) { 65 map = &ioremap_maps[i]; 66 if (!map->addr) { 67 map->size = size; 68 slot = i; 69 break; 70 } 71 } 72 73 if (slot < 0) 74 return NULL; 75 76 /* 77 * Mappings have to fit in the FIX_IOREMAP area. 78 */ 79 nrpages = size >> PAGE_SHIFT; 80 if (nrpages > FIX_N_IOREMAPS) 81 return NULL; 82 83 /* 84 * Ok, go for it.. 85 */ 86 idx0 = FIX_IOREMAP_BEGIN + slot; 87 idx = idx0; 88 while (nrpages > 0) { 89 pgprot_val(prot) |= _PAGE_WIRED; 90 __set_fixmap(idx, phys_addr, prot); 91 phys_addr += PAGE_SIZE; 92 idx++; 93 --nrpages; 94 } 95 96 map->addr = (void __iomem *)(offset + map->fixmap_addr); 97 return map->addr; 98 } 99 100 int iounmap_fixed(void __iomem *addr) 101 { 102 enum fixed_addresses idx; 103 struct ioremap_map *map; 104 unsigned int nrpages; 105 int i, slot; 106 107 slot = -1; 108 for (i = 0; i < FIX_N_IOREMAPS; i++) { 109 map = &ioremap_maps[i]; 110 if (map->addr == addr) { 111 slot = i; 112 break; 113 } 114 } 115 116 /* 117 * If we don't match, it's not for us. 118 */ 119 if (slot < 0) 120 return -EINVAL; 121 122 nrpages = map->size >> PAGE_SHIFT; 123 124 idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1; 125 while (nrpages > 0) { 126 __clear_fixmap(idx, __pgprot(_PAGE_WIRED)); 127 --idx; 128 --nrpages; 129 } 130 131 map->size = 0; 132 map->addr = NULL; 133 134 return 0; 135 } 136