aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2005-06-22 19:43:54 -0400
committerPaul Mackerras <paulus@samba.org>2005-06-22 19:43:54 -0400
commitae209cf10086b97e92e39af7cec0f84b21b6fca3 (patch)
tree9373d6ce5baef7e3d1d65e3fb21c5d0bbcbeec15 /arch
parentcebf589c822b5de87098b57644024d16f8dbc1bb (diff)
[PATCH] ppc64: Add driver for BPA iommu
Implementation of software load support for the BE iommu. This is very different from other iommu code on ppc64, since we only do a static mapping. The mapping is currently hardcoded but should really be read from the firmware, but they don't set up the device nodes yet. There is a single 512MB DMA window for PCI, USB and ethernet at 0x20000000 for our RAM. The Cell processor can put the I/O page table either in memory like the hashed page table (hardware load) or have the operating system write the entries into memory mapped CPU registers (software load). I use the software load mechanism because I know that all I/O page table entries for the amount of installed physical memory fit into the IO TLB cache. At the point when we get machines with more than 4GB of installed memory, we can either use hardware I/O page table access like the other platforms do or dynamically update the I/O TLB entries when a page fault occurs in the I/O subsystem. The software load can then use the macros that I have implemented for the static mapping in order to do the TLB cache updates. Signed-off-by: Arnd Bergmann <arndb@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/ppc64/kernel/Makefile3
-rw-r--r--arch/ppc64/kernel/bpa_iommu.c377
-rw-r--r--arch/ppc64/kernel/bpa_iommu.h65
-rw-r--r--arch/ppc64/kernel/bpa_setup.c3
4 files changed, 446 insertions, 2 deletions
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index bc58d80ee3d0..dffbfb7ac8d5 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -33,7 +33,8 @@ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
33 pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ 33 pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
34 pSeries_setup.o pSeries_iommu.o 34 pSeries_setup.o pSeries_iommu.o
35 35
36obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_nvram.o bpa_iic.o spider-pic.o 36obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
37 bpa_iic.o spider-pic.o
37 38
38obj-$(CONFIG_EEH) += eeh.o 39obj-$(CONFIG_EEH) += eeh.o
39obj-$(CONFIG_PROC_FS) += proc_ppc64.o 40obj-$(CONFIG_PROC_FS) += proc_ppc64.o
diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c
new file mode 100644
index 000000000000..f33a7bccb0d7
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.c
@@ -0,0 +1,377 @@
1/*
2 * IOMMU implementation for Broadband Processor Architecture
3 * We just establish a linear mapping at boot by setting all the
4 * IOPT cache entries in the CPU.
5 * The mapping functions should be identical to pci_direct_iommu,
6 * except for the handling of the high order bit that is required
7 * by the Spider bridge. These should be split into a separate
8 * file at the point where we get a different bridge chip.
9 *
10 * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH,
11 * Arnd Bergmann <arndb@de.ibm.com>
12 *
13 * Based on linear mapping
14 * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 */
21
22#undef DEBUG
23
24#include <linux/kernel.h>
25#include <linux/pci.h>
26#include <linux/delay.h>
27#include <linux/string.h>
28#include <linux/init.h>
29#include <linux/bootmem.h>
30#include <linux/mm.h>
31#include <linux/dma-mapping.h>
32
33#include <asm/sections.h>
34#include <asm/iommu.h>
35#include <asm/io.h>
36#include <asm/prom.h>
37#include <asm/pci-bridge.h>
38#include <asm/machdep.h>
39#include <asm/pmac_feature.h>
40#include <asm/abs_addr.h>
41#include <asm/system.h>
42
43#include "pci.h"
44#include "bpa_iommu.h"
45
46static inline unsigned long
47get_iopt_entry(unsigned long real_address, unsigned long ioid,
48 unsigned long prot)
49{
50 return (prot & IOPT_PROT_MASK)
51 | (IOPT_COHERENT)
52 | (IOPT_ORDER_VC)
53 | (real_address & IOPT_RPN_MASK)
54 | (ioid & IOPT_IOID_MASK);
55}
56
57typedef struct {
58 unsigned long val;
59} ioste;
60
61static inline ioste
62mk_ioste(unsigned long val)
63{
64 ioste ioste = { .val = val, };
65 return ioste;
66}
67
68static inline ioste
69get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size)
70{
71 unsigned long ps;
72 unsigned long iostep;
73 unsigned long nnpt;
74 unsigned long shift;
75
76 switch (page_size) {
77 case 0x1000000:
78 ps = IOST_PS_16M;
79 nnpt = 0; /* one page per segment */
80 shift = 5; /* segment has 16 iopt entries */
81 break;
82
83 case 0x100000:
84 ps = IOST_PS_1M;
85 nnpt = 0; /* one page per segment */
86 shift = 1; /* segment has 256 iopt entries */
87 break;
88
89 case 0x10000:
90 ps = IOST_PS_64K;
91 nnpt = 0x07; /* 8 pages per io page table */
92 shift = 0; /* all entries are used */
93 break;
94
95 case 0x1000:
96 ps = IOST_PS_4K;
97 nnpt = 0x7f; /* 128 pages per io page table */
98 shift = 0; /* all entries are used */
99 break;
100
101 default: /* not a known compile time constant */
102 BUILD_BUG_ON(1);
103 break;
104 }
105
106 iostep = iopt_base +
107 /* need 8 bytes per iopte */
108 (((io_address / page_size * 8)
109 /* align io page tables on 4k page boundaries */
110 << shift)
111 /* nnpt+1 pages go into each iopt */
112 & ~(nnpt << 12));
113
114 nnpt++; /* this seems to work, but the documentation is not clear
115 about wether we put nnpt or nnpt-1 into the ioste bits.
116 In theory, this can't work for 4k pages. */
117 return mk_ioste(IOST_VALID_MASK
118 | (iostep & IOST_PT_BASE_MASK)
119 | ((nnpt << 5) & IOST_NNPT_MASK)
120 | (ps & IOST_PS_MASK));
121}
122
123/* compute the address of an io pte */
124static inline unsigned long
125get_ioptep(ioste iost_entry, unsigned long io_address)
126{
127 unsigned long iopt_base;
128 unsigned long page_size;
129 unsigned long page_number;
130 unsigned long iopt_offset;
131
132 iopt_base = iost_entry.val & IOST_PT_BASE_MASK;
133 page_size = iost_entry.val & IOST_PS_MASK;
134
135 /* decode page size to compute page number */
136 page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);
137 /* page number is an offset into the io page table */
138 iopt_offset = (page_number << 3) & 0x7fff8ul;
139 return iopt_base + iopt_offset;
140}
141
142/* compute the tag field of the iopt cache entry */
143static inline unsigned long
144get_ioc_tag(ioste iost_entry, unsigned long io_address)
145{
146 unsigned long iopte = get_ioptep(iost_entry, io_address);
147
148 return IOPT_VALID_MASK
149 | ((iopte & 0x00000000000000ff8ul) >> 3)
150 | ((iopte & 0x0000003fffffc0000ul) >> 9);
151}
152
153/* compute the hashed 6 bit index for the 4-way associative pte cache */
154static inline unsigned long
155get_ioc_hash(ioste iost_entry, unsigned long io_address)
156{
157 unsigned long iopte = get_ioptep(iost_entry, io_address);
158
159 return ((iopte & 0x000000000000001f8ul) >> 3)
160 ^ ((iopte & 0x00000000000020000ul) >> 17)
161 ^ ((iopte & 0x00000000000010000ul) >> 15)
162 ^ ((iopte & 0x00000000000008000ul) >> 13)
163 ^ ((iopte & 0x00000000000004000ul) >> 11)
164 ^ ((iopte & 0x00000000000002000ul) >> 9)
165 ^ ((iopte & 0x00000000000001000ul) >> 7);
166}
167
168/* same as above, but pretend that we have a simpler 1-way associative
169 pte cache with an 8 bit index */
170static inline unsigned long
171get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)
172{
173 unsigned long iopte = get_ioptep(iost_entry, io_address);
174
175 return ((iopte & 0x000000000000001f8ul) >> 3)
176 ^ ((iopte & 0x00000000000020000ul) >> 17)
177 ^ ((iopte & 0x00000000000010000ul) >> 15)
178 ^ ((iopte & 0x00000000000008000ul) >> 13)
179 ^ ((iopte & 0x00000000000004000ul) >> 11)
180 ^ ((iopte & 0x00000000000002000ul) >> 9)
181 ^ ((iopte & 0x00000000000001000ul) >> 7)
182 ^ ((iopte & 0x0000000000000c000ul) >> 8);
183}
184
185static inline ioste
186get_iost_cache(void __iomem *base, unsigned long index)
187{
188 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
189 return mk_ioste(in_be64(&p[index]));
190}
191
192static inline void
193set_iost_cache(void __iomem *base, unsigned long index, ioste ste)
194{
195 unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
196 pr_debug("ioste %02lx was %016lx, store %016lx", index,
197 get_iost_cache(base, index).val, ste.val);
198 out_be64(&p[index], ste.val);
199 pr_debug(" now %016lx\n", get_iost_cache(base, index).val);
200}
201
202static inline unsigned long
203get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag)
204{
205 unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR);
206 unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG);
207
208 *tag = tags[index];
209 rmb();
210 return *p;
211}
212
213static inline void
214set_iopt_cache(void __iomem *base, unsigned long index,
215 unsigned long tag, unsigned long val)
216{
217 unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
218 unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
219 pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",
220 index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);
221
222 out_be64(p, val);
223 out_be64(&tags[index], tag);
224}
225
226static inline void
227set_iost_origin(void __iomem *base)
228{
229 unsigned long __iomem *p = base + IOC_ST_ORIGIN;
230 unsigned long origin = IOSTO_ENABLE | IOSTO_SW;
231
232 pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin);
233 out_be64(p, origin);
234}
235
236static inline void
237set_iocmd_config(void __iomem *base)
238{
239 unsigned long __iomem *p = base + 0xc00;
240 unsigned long conf;
241
242 conf = in_be64(p);
243 pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE);
244 out_be64(p, conf | IOCMD_CONF_TE);
245}
246
247/* FIXME: get these from the device tree */
248#define ioc_base 0x20000511000ull
249#define ioc_mmio_base 0x20000510000ull
250#define ioid 0x48a
251#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */
252#define io_page_size 0x1000000
253
254static unsigned long map_iopt_entry(unsigned long address)
255{
256 switch (address >> 20) {
257 case 0x600:
258 address = 0x24020000000ull; /* spider i/o */
259 break;
260 default:
261 address += iopt_phys_offset;
262 break;
263 }
264
265 return get_iopt_entry(address, ioid, IOPT_PROT_RW);
266}
267
268static void iommu_bus_setup_null(struct pci_bus *b) { }
269static void iommu_dev_setup_null(struct pci_dev *d) { }
270
271/* initialize the iommu to support a simple linear mapping
272 * for each DMA window used by any device. For now, we
273 * happen to know that there is only one DMA window in use,
274 * starting at iopt_phys_offset. */
275static void bpa_map_iommu(void)
276{
277 unsigned long address;
278 void __iomem *base;
279 ioste ioste;
280 unsigned long index;
281
282 base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);
283 pr_debug("%lx mapped to %p\n", ioc_base, base);
284 set_iocmd_config(base);
285 iounmap(base);
286
287 base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);
288 pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);
289
290 set_iost_origin(base);
291
292 for (address = 0; address < 0x100000000ul; address += io_page_size) {
293 ioste = get_iost_entry(0x10000000000ul, address, io_page_size);
294 if ((address & 0xfffffff) == 0) /* segment start */
295 set_iost_cache(base, address >> 28, ioste);
296 index = get_ioc_hash_1way(ioste, address);
297 pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
298 address, index, ioste.val);
299 set_iopt_cache(base,
300 get_ioc_hash_1way(ioste, address),
301 get_ioc_tag(ioste, address),
302 map_iopt_entry(address));
303 }
304 iounmap(base);
305}
306
307
308static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
309 dma_addr_t *dma_handle, unsigned int __nocast flag)
310{
311 void *ret;
312
313 ret = (void *)__get_free_pages(flag, get_order(size));
314 if (ret != NULL) {
315 memset(ret, 0, size);
316 *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID;
317 }
318 return ret;
319}
320
321static void bpa_free_coherent(struct device *hwdev, size_t size,
322 void *vaddr, dma_addr_t dma_handle)
323{
324 free_pages((unsigned long)vaddr, get_order(size));
325}
326
327static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr,
328 size_t size, enum dma_data_direction direction)
329{
330 return virt_to_abs(ptr) | BPA_DMA_VALID;
331}
332
333static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
334 size_t size, enum dma_data_direction direction)
335{
336}
337
338static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg,
339 int nents, enum dma_data_direction direction)
340{
341 int i;
342
343 for (i = 0; i < nents; i++, sg++) {
344 sg->dma_address = (page_to_phys(sg->page) + sg->offset)
345 | BPA_DMA_VALID;
346 sg->dma_length = sg->length;
347 }
348
349 return nents;
350}
351
352static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg,
353 int nents, enum dma_data_direction direction)
354{
355}
356
357static int bpa_dma_supported(struct device *dev, u64 mask)
358{
359 return mask < 0x100000000ull;
360}
361
362void bpa_init_iommu(void)
363{
364 bpa_map_iommu();
365
366 /* Direct I/O, IOMMU off */
367 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
368 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
369
370 pci_dma_ops.alloc_coherent = bpa_alloc_coherent;
371 pci_dma_ops.free_coherent = bpa_free_coherent;
372 pci_dma_ops.map_single = bpa_map_single;
373 pci_dma_ops.unmap_single = bpa_unmap_single;
374 pci_dma_ops.map_sg = bpa_map_sg;
375 pci_dma_ops.unmap_sg = bpa_unmap_sg;
376 pci_dma_ops.dma_supported = bpa_dma_supported;
377}
diff --git a/arch/ppc64/kernel/bpa_iommu.h b/arch/ppc64/kernel/bpa_iommu.h
new file mode 100644
index 000000000000..e547d77dfa04
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.h
@@ -0,0 +1,65 @@
1#ifndef BPA_IOMMU_H
2#define BPA_IOMMU_H
3
4/* some constants */
5enum {
6 /* segment table entries */
7 IOST_VALID_MASK = 0x8000000000000000ul,
8 IOST_TAG_MASK = 0x3000000000000000ul,
9 IOST_PT_BASE_MASK = 0x000003fffffff000ul,
10 IOST_NNPT_MASK = 0x0000000000000fe0ul,
11 IOST_PS_MASK = 0x000000000000000ful,
12
13 IOST_PS_4K = 0x1,
14 IOST_PS_64K = 0x3,
15 IOST_PS_1M = 0x5,
16 IOST_PS_16M = 0x7,
17
18 /* iopt tag register */
19 IOPT_VALID_MASK = 0x0000000200000000ul,
20 IOPT_TAG_MASK = 0x00000001fffffffful,
21
22 /* iopt cache register */
23 IOPT_PROT_MASK = 0xc000000000000000ul,
24 IOPT_PROT_NONE = 0x0000000000000000ul,
25 IOPT_PROT_READ = 0x4000000000000000ul,
26 IOPT_PROT_WRITE = 0x8000000000000000ul,
27 IOPT_PROT_RW = 0xc000000000000000ul,
28 IOPT_COHERENT = 0x2000000000000000ul,
29
30 IOPT_ORDER_MASK = 0x1800000000000000ul,
31 /* order access to same IOID/VC on same address */
32 IOPT_ORDER_ADDR = 0x0800000000000000ul,
33 /* similar, but only after a write access */
34 IOPT_ORDER_WRITES = 0x1000000000000000ul,
35 /* Order all accesses to same IOID/VC */
36 IOPT_ORDER_VC = 0x1800000000000000ul,
37
38 IOPT_RPN_MASK = 0x000003fffffff000ul,
39 IOPT_HINT_MASK = 0x0000000000000800ul,
40 IOPT_IOID_MASK = 0x00000000000007fful,
41
42 IOSTO_ENABLE = 0x8000000000000000ul,
43 IOSTO_ORIGIN = 0x000003fffffff000ul,
44 IOSTO_HW = 0x0000000000000800ul,
45 IOSTO_SW = 0x0000000000000400ul,
46
47 IOCMD_CONF_TE = 0x0000800000000000ul,
48
49 /* memory mapped registers */
50 IOC_PT_CACHE_DIR = 0x000,
51 IOC_ST_CACHE_DIR = 0x800,
52 IOC_PT_CACHE_REG = 0x910,
53 IOC_ST_ORIGIN = 0x918,
54 IOC_CONF = 0x930,
55
56 /* The high bit needs to be set on every DMA address,
57 only 2GB are addressable */
58 BPA_DMA_VALID = 0x80000000,
59 BPA_DMA_MASK = 0x7fffffff,
60};
61
62
63void bpa_init_iommu(void);
64
65#endif
diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c
index 0a43d8a93d76..57b3db66f458 100644
--- a/arch/ppc64/kernel/bpa_setup.c
+++ b/arch/ppc64/kernel/bpa_setup.c
@@ -46,6 +46,7 @@
46 46
47#include "pci.h" 47#include "pci.h"
48#include "bpa_iic.h" 48#include "bpa_iic.h"
49#include "bpa_iommu.h"
49 50
50#ifdef DEBUG 51#ifdef DEBUG
51#define DBG(fmt...) udbg_printf(fmt) 52#define DBG(fmt...) udbg_printf(fmt)
@@ -107,7 +108,7 @@ static void __init bpa_init_early(void)
107 108
108 hpte_init_native(); 109 hpte_init_native();
109 110
110 pci_direct_iommu_init(); 111 bpa_init_iommu();
111 112
112 ppc64_interrupt_controller = IC_BPA_IIC; 113 ppc64_interrupt_controller = IC_BPA_IIC;
113 114