Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */ 2 : : /* 3 : : * Copyright © 2008 Keith Packard <keithp@keithp.com> 4 : : */ 5 : : 6 : : #ifndef _LINUX_IO_MAPPING_H 7 : : #define _LINUX_IO_MAPPING_H 8 : : 9 : : #include <linux/types.h> 10 : : #include <linux/slab.h> 11 : : #include <linux/bug.h> 12 : : #include <linux/io.h> 13 : : #include <asm/page.h> 14 : : 15 : : /* 16 : : * The io_mapping mechanism provides an abstraction for mapping 17 : : * individual pages from an io device to the CPU in an efficient fashion. 18 : : * 19 : : * See Documentation/io-mapping.txt 20 : : */ 21 : : 22 : : struct io_mapping { 23 : : resource_size_t base; 24 : : unsigned long size; 25 : : pgprot_t prot; 26 : : void __iomem *iomem; 27 : : }; 28 : : 29 : : #ifdef CONFIG_HAVE_ATOMIC_IOMAP 30 : : 31 : : #include <linux/pfn.h> 32 : : #include <asm/iomap.h> 33 : : /* 34 : : * For small address space machines, mapping large objects 35 : : * into the kernel virtual space isn't practical. Where 36 : : * available, use fixmap support to dynamically map pages 37 : : * of the object at run time. 38 : : */ 39 : : 40 : : static inline struct io_mapping * 41 : : io_mapping_init_wc(struct io_mapping *iomap, 42 : : resource_size_t base, 43 : : unsigned long size) 44 : : { 45 : : pgprot_t prot; 46 : : 47 : : if (iomap_create_wc(base, size, &prot)) 48 : : return NULL; 49 : : 50 : : iomap->base = base; 51 : : iomap->size = size; 52 : : iomap->prot = prot; 53 : : return iomap; 54 : : } 55 : : 56 : : static inline void 57 : : io_mapping_fini(struct io_mapping *mapping) 58 : : { 59 : : iomap_free(mapping->base, mapping->size); 60 : : } 61 : : 62 : : /* Atomic map/unmap */ 63 : : static inline void __iomem * 64 : : io_mapping_map_atomic_wc(struct io_mapping *mapping, 65 : : unsigned long offset) 66 : : { 67 : : resource_size_t phys_addr; 68 : : 69 : : BUG_ON(offset >= mapping->size); 70 : : phys_addr = mapping->base + offset; 71 : : return iomap_atomic_prot_pfn(PHYS_PFN(phys_addr), mapping->prot); 72 : : } 73 : : 74 : : static inline void 75 : : io_mapping_unmap_atomic(void __iomem *vaddr) 76 : : { 77 : : iounmap_atomic(vaddr); 78 : : } 79 : : 80 : : static inline void __iomem * 81 : : io_mapping_map_wc(struct io_mapping *mapping, 82 : : unsigned long offset, 83 : : unsigned long size) 84 : : { 85 : : resource_size_t phys_addr; 86 : : 87 : : BUG_ON(offset >= mapping->size); 88 : : phys_addr = mapping->base + offset; 89 : : 90 : : return ioremap_wc(phys_addr, size); 91 : : } 92 : : 93 : : static inline void 94 : : io_mapping_unmap(void __iomem *vaddr) 95 : : { 96 : : iounmap(vaddr); 97 : : } 98 : : 99 : : #else 100 : : 101 : : #include <linux/uaccess.h> 102 : : #include <asm/pgtable.h> 103 : : 104 : : /* Create the io_mapping object*/ 105 : : static inline struct io_mapping * 106 : 0 : io_mapping_init_wc(struct io_mapping *iomap, 107 : : resource_size_t base, 108 : : unsigned long size) 109 : : { 110 : 0 : iomap->base = base; 111 : 0 : iomap->size = size; 112 : 0 : iomap->iomem = ioremap_wc(base, size); 113 : : #if defined(pgprot_noncached_wc) /* archs can't agree on a name ... */ 114 : : iomap->prot = pgprot_noncached_wc(PAGE_KERNEL); 115 : : #elif defined(pgprot_writecombine) 116 : 0 : iomap->prot = pgprot_writecombine(PAGE_KERNEL); 117 : : #else 118 : : iomap->prot = pgprot_noncached(PAGE_KERNEL); 119 : : #endif 120 : : 121 : 0 : return iomap; 122 : : } 123 : : 124 : : static inline void 125 : 0 : io_mapping_fini(struct io_mapping *mapping) 126 : : { 127 : 0 : iounmap(mapping->iomem); 128 : 0 : } 129 : : 130 : : /* Non-atomic map/unmap */ 131 : : static inline void __iomem * 132 : 0 : io_mapping_map_wc(struct io_mapping *mapping, 133 : : unsigned long offset, 134 : : unsigned long size) 135 : : { 136 [ # # # # ]: 0 : return mapping->iomem + offset; 137 : : } 138 : : 139 : : static inline void 140 : 0 : io_mapping_unmap(void __iomem *vaddr) 141 : : { 142 : 0 : } 143 : : 144 : : /* Atomic map/unmap */ 145 : : static inline void __iomem * 146 : 0 : io_mapping_map_atomic_wc(struct io_mapping *mapping, 147 : : unsigned long offset) 148 : : { 149 : 0 : preempt_disable(); 150 : 0 : pagefault_disable(); 151 : 0 : return io_mapping_map_wc(mapping, offset, PAGE_SIZE); 152 : : } 153 : : 154 : : static inline void 155 : 0 : io_mapping_unmap_atomic(void __iomem *vaddr) 156 : : { 157 : 0 : io_mapping_unmap(vaddr); 158 : 0 : pagefault_enable(); 159 : 0 : preempt_enable(); 160 : 0 : } 161 : : 162 : : #endif /* HAVE_ATOMIC_IOMAP */ 163 : : 164 : : static inline struct io_mapping * 165 : : io_mapping_create_wc(resource_size_t base, 166 : : unsigned long size) 167 : : { 168 : : struct io_mapping *iomap; 169 : : 170 : : iomap = kmalloc(sizeof(*iomap), GFP_KERNEL); 171 : : if (!iomap) 172 : : return NULL; 173 : : 174 : : if (!io_mapping_init_wc(iomap, base, size)) { 175 : : kfree(iomap); 176 : : return NULL; 177 : : } 178 : : 179 : : return iomap; 180 : : } 181 : : 182 : : static inline void 183 : : io_mapping_free(struct io_mapping *iomap) 184 : : { 185 : : io_mapping_fini(iomap); 186 : : kfree(iomap); 187 : : } 188 : : 189 : : #endif /* _LINUX_IO_MAPPING_H */