1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * ioport.c: Simple io mapping allocator. |
4 | * |
5 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) |
6 | * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) |
7 | * |
8 | * 1996: sparc_free_io, 1999: ioremap()/iounmap() by Pete Zaitcev. |
9 | * |
10 | * 2000/01/29 |
11 | * <rth> zait: as long as pci_alloc_consistent produces something addressable, |
12 | * things are ok. |
13 | * <zaitcev> rth: no, it is relevant, because get_free_pages returns you a |
14 | * pointer into the big page mapping |
15 | * <rth> zait: so what? |
16 | * <rth> zait: remap_it_my_way(virt_to_phys(get_free_page())) |
17 | * <zaitcev> Hmm |
18 | * <zaitcev> Suppose I did this remap_it_my_way(virt_to_phys(get_free_page())). |
19 | * So far so good. |
20 | * <zaitcev> Now, driver calls pci_free_consistent(with result of |
21 | * remap_it_my_way()). |
22 | * <zaitcev> How do you find the address to pass to free_pages()? |
23 | * <rth> zait: walk the page tables? It's only two or three level after all. |
24 | * <rth> zait: you have to walk them anyway to remove the mapping. |
25 | * <zaitcev> Hmm |
26 | * <zaitcev> Sounds reasonable |
27 | */ |
28 | |
29 | #include <linux/module.h> |
30 | #include <linux/sched.h> |
31 | #include <linux/kernel.h> |
32 | #include <linux/errno.h> |
33 | #include <linux/types.h> |
34 | #include <linux/ioport.h> |
35 | #include <linux/mm.h> |
36 | #include <linux/slab.h> |
37 | #include <linux/pci.h> /* struct pci_dev */ |
38 | #include <linux/proc_fs.h> |
39 | #include <linux/seq_file.h> |
40 | #include <linux/scatterlist.h> |
41 | #include <linux/dma-map-ops.h> |
42 | #include <linux/of.h> |
43 | |
44 | #include <asm/io.h> |
45 | #include <asm/vaddrs.h> |
46 | #include <asm/oplib.h> |
47 | #include <asm/prom.h> |
48 | #include <asm/page.h> |
49 | #include <asm/pgalloc.h> |
50 | #include <asm/dma.h> |
51 | #include <asm/iommu.h> |
52 | #include <asm/io-unit.h> |
53 | #include <asm/leon.h> |
54 | |
55 | static void __iomem *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz); |
56 | static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, |
57 | unsigned long size, char *name); |
58 | static void _sparc_free_io(struct resource *res); |
59 | |
60 | static void register_proc_sparc_ioport(void); |
61 | |
62 | /* This points to the next to use virtual memory for DVMA mappings */ |
63 | static struct resource _sparc_dvma = { |
64 | .name = "sparc_dvma" , .start = DVMA_VADDR, .end = DVMA_END - 1 |
65 | }; |
66 | /* This points to the start of I/O mappings, cluable from outside. */ |
67 | /*ext*/ struct resource sparc_iomap = { |
68 | .name = "sparc_iomap" , .start = IOBASE_VADDR, .end = IOBASE_END - 1 |
69 | }; |
70 | |
71 | /* |
72 | * Our mini-allocator... |
73 | * Boy this is gross! We need it because we must map I/O for |
74 | * timers and interrupt controller before the kmalloc is available. |
75 | */ |
76 | |
77 | #define XNMLN 15 |
78 | #define XNRES 10 /* SS-10 uses 8 */ |
79 | |
80 | struct xresource { |
81 | struct resource xres; /* Must be first */ |
82 | int xflag; /* 1 == used */ |
83 | char xname[XNMLN+1]; |
84 | }; |
85 | |
86 | static struct xresource xresv[XNRES]; |
87 | |
88 | static struct xresource *xres_alloc(void) { |
89 | struct xresource *xrp; |
90 | int n; |
91 | |
92 | xrp = xresv; |
93 | for (n = 0; n < XNRES; n++) { |
94 | if (xrp->xflag == 0) { |
95 | xrp->xflag = 1; |
96 | return xrp; |
97 | } |
98 | xrp++; |
99 | } |
100 | return NULL; |
101 | } |
102 | |
103 | static void xres_free(struct xresource *xrp) { |
104 | xrp->xflag = 0; |
105 | } |
106 | |
107 | /* |
108 | * These are typically used in PCI drivers |
109 | * which are trying to be cross-platform. |
110 | * |
111 | * Bus type is always zero on IIep. |
112 | */ |
113 | void __iomem *ioremap(phys_addr_t offset, size_t size) |
114 | { |
115 | char name[14]; |
116 | |
117 | sprintf(buf: name, fmt: "phys_%08x" , (u32)offset); |
118 | return _sparc_alloc_io(busno: 0, phys: (unsigned long)offset, size, name); |
119 | } |
120 | EXPORT_SYMBOL(ioremap); |
121 | |
122 | /* |
123 | * Complementary to ioremap(). |
124 | */ |
125 | void iounmap(volatile void __iomem *virtual) |
126 | { |
127 | unsigned long vaddr = (unsigned long) virtual & PAGE_MASK; |
128 | struct resource *res; |
129 | |
130 | /* |
131 | * XXX Too slow. Can have 8192 DVMA pages on sun4m in the worst case. |
132 | * This probably warrants some sort of hashing. |
133 | */ |
134 | if ((res = lookup_resource(root: &sparc_iomap, start: vaddr)) == NULL) { |
135 | printk("free_io/iounmap: cannot free %lx\n" , vaddr); |
136 | return; |
137 | } |
138 | _sparc_free_io(res); |
139 | |
140 | if ((char *)res >= (char*)xresv && (char *)res < (char *)&xresv[XNRES]) { |
141 | xres_free(xrp: (struct xresource *)res); |
142 | } else { |
143 | kfree(objp: res); |
144 | } |
145 | } |
146 | EXPORT_SYMBOL(iounmap); |
147 | |
148 | void __iomem *of_ioremap(struct resource *res, unsigned long offset, |
149 | unsigned long size, char *name) |
150 | { |
151 | return _sparc_alloc_io(busno: res->flags & 0xF, |
152 | phys: res->start + offset, |
153 | size, name); |
154 | } |
155 | EXPORT_SYMBOL(of_ioremap); |
156 | |
157 | void of_iounmap(struct resource *res, void __iomem *base, unsigned long size) |
158 | { |
159 | iounmap(base); |
160 | } |
161 | EXPORT_SYMBOL(of_iounmap); |
162 | |
163 | /* |
164 | * Meat of mapping |
165 | */ |
166 | static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, |
167 | unsigned long size, char *name) |
168 | { |
169 | static int printed_full; |
170 | struct xresource *xres; |
171 | struct resource *res; |
172 | char *tack; |
173 | int tlen; |
174 | void __iomem *va; /* P3 diag */ |
175 | |
176 | if (name == NULL) name = "???" ; |
177 | |
178 | if ((xres = xres_alloc()) != NULL) { |
179 | tack = xres->xname; |
180 | res = &xres->xres; |
181 | } else { |
182 | if (!printed_full) { |
183 | printk("ioremap: done with statics, switching to malloc\n" ); |
184 | printed_full = 1; |
185 | } |
186 | tlen = strlen(name); |
187 | tack = kmalloc(size: sizeof (struct resource) + tlen + 1, GFP_KERNEL); |
188 | if (tack == NULL) return NULL; |
189 | memset(tack, 0, sizeof(struct resource)); |
190 | res = (struct resource *) tack; |
191 | tack += sizeof (struct resource); |
192 | } |
193 | |
194 | strscpy(tack, name, XNMLN+1); |
195 | res->name = tack; |
196 | |
197 | va = _sparc_ioremap(res, bus: busno, pa: phys, sz: size); |
198 | /* printk("ioremap(0x%x:%08lx[0x%lx])=%p\n", busno, phys, size, va); */ /* P3 diag */ |
199 | return va; |
200 | } |
201 | |
202 | /* |
203 | */ |
204 | static void __iomem * |
205 | _sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz) |
206 | { |
207 | unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK); |
208 | |
209 | if (allocate_resource(root: &sparc_iomap, new: res, |
210 | size: (offset + sz + PAGE_SIZE-1) & PAGE_MASK, |
211 | min: sparc_iomap.start, max: sparc_iomap.end, PAGE_SIZE, NULL, NULL) != 0) { |
212 | /* Usually we cannot see printks in this case. */ |
213 | prom_printf("alloc_io_res(%s): cannot occupy\n" , |
214 | (res->name != NULL)? res->name: "???" ); |
215 | prom_halt(); |
216 | } |
217 | |
218 | pa &= PAGE_MASK; |
219 | srmmu_mapiorange(bus, pa, res->start, resource_size(res)); |
220 | |
221 | return (void __iomem *)(unsigned long)(res->start + offset); |
222 | } |
223 | |
224 | /* |
225 | * Complementary to _sparc_ioremap(). |
226 | */ |
227 | static void _sparc_free_io(struct resource *res) |
228 | { |
229 | unsigned long plen; |
230 | |
231 | plen = resource_size(res); |
232 | BUG_ON((plen & (PAGE_SIZE-1)) != 0); |
233 | srmmu_unmapiorange(res->start, plen); |
234 | release_resource(new: res); |
235 | } |
236 | |
237 | unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len) |
238 | { |
239 | struct resource *res; |
240 | |
241 | res = kzalloc(size: sizeof(*res), GFP_KERNEL); |
242 | if (!res) |
243 | return 0; |
244 | res->name = dev->of_node->full_name; |
245 | |
246 | if (allocate_resource(root: &_sparc_dvma, new: res, size: len, min: _sparc_dvma.start, |
247 | max: _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) { |
248 | printk("%s: cannot occupy 0x%zx" , __func__, len); |
249 | kfree(objp: res); |
250 | return 0; |
251 | } |
252 | |
253 | return res->start; |
254 | } |
255 | |
256 | bool sparc_dma_free_resource(void *cpu_addr, size_t size) |
257 | { |
258 | unsigned long addr = (unsigned long)cpu_addr; |
259 | struct resource *res; |
260 | |
261 | res = lookup_resource(root: &_sparc_dvma, start: addr); |
262 | if (!res) { |
263 | printk("%s: cannot free %p\n" , __func__, cpu_addr); |
264 | return false; |
265 | } |
266 | |
267 | if ((addr & (PAGE_SIZE - 1)) != 0) { |
268 | printk("%s: unaligned va %p\n" , __func__, cpu_addr); |
269 | return false; |
270 | } |
271 | |
272 | size = PAGE_ALIGN(size); |
273 | if (resource_size(res) != size) { |
274 | printk("%s: region 0x%lx asked 0x%zx\n" , |
275 | __func__, (long)resource_size(res), size); |
276 | return false; |
277 | } |
278 | |
279 | release_resource(new: res); |
280 | kfree(objp: res); |
281 | return true; |
282 | } |
283 | |
284 | #ifdef CONFIG_SBUS |
285 | |
286 | void sbus_set_sbus64(struct device *dev, int x) |
287 | { |
288 | printk("sbus_set_sbus64: unsupported\n" ); |
289 | } |
290 | EXPORT_SYMBOL(sbus_set_sbus64); |
291 | |
292 | static int __init sparc_register_ioport(void) |
293 | { |
294 | register_proc_sparc_ioport(); |
295 | |
296 | return 0; |
297 | } |
298 | |
299 | arch_initcall(sparc_register_ioport); |
300 | |
301 | #endif /* CONFIG_SBUS */ |
302 | |
303 | /* |
304 | * IIep is write-through, not flushing on cpu to device transfer. |
305 | * |
306 | * On LEON systems without cache snooping, the entire D-CACHE must be flushed to |
307 | * make DMA to cacheable memory coherent. |
308 | */ |
309 | void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, |
310 | enum dma_data_direction dir) |
311 | { |
312 | if (dir != DMA_TO_DEVICE && |
313 | sparc_cpu_model == sparc_leon && |
314 | !sparc_leon3_snooping_enabled()) |
315 | leon_flush_dcache_all(); |
316 | } |
317 | |
318 | #ifdef CONFIG_PROC_FS |
319 | |
320 | static int sparc_io_proc_show(struct seq_file *m, void *v) |
321 | { |
322 | struct resource *root = m->private, *r; |
323 | const char *nm; |
324 | |
325 | for (r = root->child; r != NULL; r = r->sibling) { |
326 | if ((nm = r->name) == NULL) nm = "???" ; |
327 | seq_printf(m, fmt: "%016llx-%016llx: %s\n" , |
328 | (unsigned long long)r->start, |
329 | (unsigned long long)r->end, nm); |
330 | } |
331 | |
332 | return 0; |
333 | } |
334 | #endif /* CONFIG_PROC_FS */ |
335 | |
336 | static void register_proc_sparc_ioport(void) |
337 | { |
338 | #ifdef CONFIG_PROC_FS |
339 | proc_create_single_data(name: "io_map" , mode: 0, NULL, show: sparc_io_proc_show, |
340 | data: &sparc_iomap); |
341 | proc_create_single_data(name: "dvma_map" , mode: 0, NULL, show: sparc_io_proc_show, |
342 | data: &_sparc_dvma); |
343 | #endif |
344 | } |
345 | |