1 /* 2 * Re-map IO memory to kernel address space so that we can access it. 3 * 4 * These functions should only be used when it is necessary to map a 5 * physical address space into the kernel address space before ioremap() 6 * can be used, e.g. early in boot before paging_init(). 7 * 8 * Copyright (C) 2009 Matt Fleming 9 */ 10 11 #include <linux/vmalloc.h> 12 #include <linux/ioport.h> 13 #include <linux/module.h> 14 #include <linux/mm.h> 15 #include <linux/io.h> 16 #include <linux/bootmem.h> 17 #include <linux/proc_fs.h> 18 #include <linux/slab.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(resource_size_t phys_addr, unsigned long offset, 49 unsigned long size, pgprot_t prot) 50 { 51 enum fixed_addresses idx0, idx; 52 struct ioremap_map *map; 53 unsigned int nrpages; 54 int i, slot; 55 56 slot = -1; 57 for (i = 0; i < FIX_N_IOREMAPS; i++) { 58 map = &ioremap_maps[i]; 59 if (!map->addr) { 60 map->size = size; 61 slot = i; 62 break; 63 } 64 } 65 66 if (slot < 0) 67 return NULL; 68 69 /* 70 * Mappings have to fit in the FIX_IOREMAP area. 71 */ 72 nrpages = size >> PAGE_SHIFT; 73 if (nrpages > FIX_N_IOREMAPS) 74 return NULL; 75 76 /* 77 * Ok, go for it.. 78 */ 79 idx0 = FIX_IOREMAP_BEGIN + slot; 80 idx = idx0; 81 while (nrpages > 0) { 82 pgprot_val(prot) |= _PAGE_WIRED; 83 __set_fixmap(idx, phys_addr, prot); 84 phys_addr += PAGE_SIZE; 85 idx++; 86 --nrpages; 87 } 88 89 map->addr = (void __iomem *)(offset + map->fixmap_addr); 90 return map->addr; 91 } 92 93 int iounmap_fixed(void __iomem *addr) 94 { 95 enum fixed_addresses idx; 96 struct ioremap_map *map; 97 unsigned int nrpages; 98 int i, slot; 99 100 slot = -1; 101 for (i = 0; i < FIX_N_IOREMAPS; i++) { 102 map = &ioremap_maps[i]; 103 if (map->addr == addr) { 104 slot = i; 105 break; 106 } 107 } 108 109 /* 110 * If we don't match, it's not for us. 111 */ 112 if (slot < 0) 113 return -EINVAL; 114 115 nrpages = map->size >> PAGE_SHIFT; 116 117 idx = FIX_IOREMAP_BEGIN + slot + nrpages - 1; 118 while (nrpages > 0) { 119 __clear_fixmap(idx, __pgprot(_PAGE_WIRED)); 120 --idx; 121 --nrpages; 122 } 123 124 map->size = 0; 125 map->addr = NULL; 126 127 return 0; 128 } 129