aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/dart_iommu.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-12-13 21:10:10 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-08 23:03:17 -0500
commit1beb6a7d6cbed3ac03500ce9b5b9bb632c512039 (patch)
tree727aa76da5a82fca449dadf3cebbadc414ad6555 /arch/powerpc/sysdev/dart_iommu.c
parentcd0c7f06803be06a5cf4564aa5a900f4b6aea603 (diff)
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
This adds some very basic support for the new machines, including the Quad G5 (tested), and other new dual core based machines and iMac G5 iSight (untested). This is still experimental ! There is no thermal control yet, there is no proper handing of MSIs, etc.. but it boots, I have all 4 cores up on my machine. Compared to the previous version of this patch, this one adds DART IOMMU support for the U4 chipset and thus should work fine on setups with more than 2Gb of RAM. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev/dart_iommu.c')
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
new file mode 100644
index 000000000000..df0dbdee762a
--- /dev/null
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -0,0 +1,350 @@
1/*
2 * arch/powerpc/sysdev/dart_iommu.c
3 *
4 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
5 * Copyright (C) 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>,
6 * IBM Corporation
7 *
8 * Based on pSeries_iommu.c:
9 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
10 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
11 *
12 * Dynamic DMA mapping support, Apple U3, U4 & IBM CPC925 "DART" iommu.
13 *
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/config.h>
31#include <linux/init.h>
32#include <linux/types.h>
33#include <linux/slab.h>
34#include <linux/mm.h>
35#include <linux/spinlock.h>
36#include <linux/string.h>
37#include <linux/pci.h>
38#include <linux/dma-mapping.h>
39#include <linux/vmalloc.h>
40#include <asm/io.h>
41#include <asm/prom.h>
42#include <asm/iommu.h>
43#include <asm/pci-bridge.h>
44#include <asm/machdep.h>
45#include <asm/abs_addr.h>
46#include <asm/cacheflush.h>
47#include <asm/lmb.h>
48#include <asm/ppc-pci.h>
49
50#include "dart.h"
51
52extern int iommu_force_on;
53
54/* Physical base address and size of the DART table */
55unsigned long dart_tablebase; /* exported to htab_initialize */
56static unsigned long dart_tablesize;
57
58/* Virtual base address of the DART table */
59static u32 *dart_vbase;
60
61/* Mapped base address for the dart */
62static unsigned int *__iomem dart;
63
64/* Dummy val that entries are set to when unused */
65static unsigned int dart_emptyval;
66
67static struct iommu_table iommu_table_dart;
68static int iommu_table_dart_inited;
69static int dart_dirty;
70static int dart_is_u4;
71
72#define DBG(...)
73
74static inline void dart_tlb_invalidate_all(void)
75{
76 unsigned long l = 0;
77 unsigned int reg, inv_bit;
78 unsigned long limit;
79
80 DBG("dart: flush\n");
81
82 /* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
83 * control register and wait for it to clear.
84 *
85 * Gotcha: Sometimes, the DART won't detect that the bit gets
86 * set. If so, clear it and set it again.
87 */
88
89 limit = 0;
90
91 inv_bit = dart_is_u4 ? DART_CNTL_U4_FLUSHTLB : DART_CNTL_U3_FLUSHTLB;
92retry:
93 l = 0;
94 reg = DART_IN(DART_CNTL);
95 reg |= inv_bit;
96 DART_OUT(DART_CNTL, reg);
97
98 while ((DART_IN(DART_CNTL) & inv_bit) && l < (1L << limit))
99 l++;
100 if (l == (1L << limit)) {
101 if (limit < 4) {
102 limit++;
103 reg = DART_IN(DART_CNTL);
104 reg &= ~inv_bit;
105 DART_OUT(DART_CNTL, reg);
106 goto retry;
107 } else
108 panic("DART: TLB did not flush after waiting a long "
109 "time. Buggy U3 ?");
110 }
111}
112
113static void dart_flush(struct iommu_table *tbl)
114{
115 if (dart_dirty)
116 dart_tlb_invalidate_all();
117 dart_dirty = 0;
118}
119
120static void dart_build(struct iommu_table *tbl, long index,
121 long npages, unsigned long uaddr,
122 enum dma_data_direction direction)
123{
124 unsigned int *dp;
125 unsigned int rpn;
126
127 DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
128
129 index <<= DART_PAGE_FACTOR;
130 npages <<= DART_PAGE_FACTOR;
131
132 dp = ((unsigned int*)tbl->it_base) + index;
133
134 /* On U3, all memory is contigous, so we can move this
135 * out of the loop.
136 */
137 while (npages--) {
138 rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
139
140 *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
141
142 rpn++;
143 uaddr += DART_PAGE_SIZE;
144 }
145
146 dart_dirty = 1;
147}
148
149
150static void dart_free(struct iommu_table *tbl, long index, long npages)
151{
152 unsigned int *dp;
153
154 /* We don't worry about flushing the TLB cache. The only drawback of
155 * not doing it is that we won't catch buggy device drivers doing
156 * bad DMAs, but then no 32-bit architecture ever does either.
157 */
158
159 DBG("dart: free at: %lx, %lx\n", index, npages);
160
161 index <<= DART_PAGE_FACTOR;
162 npages <<= DART_PAGE_FACTOR;
163
164 dp = ((unsigned int *)tbl->it_base) + index;
165
166 while (npages--)
167 *(dp++) = dart_emptyval;
168}
169
170
171static int dart_init(struct device_node *dart_node)
172{
173 unsigned int i;
174 unsigned long tmp, base, size;
175 struct resource r;
176
177 if (dart_tablebase == 0 || dart_tablesize == 0) {
178 printk(KERN_INFO "DART: table not allocated, using "
179 "direct DMA\n");
180 return -ENODEV;
181 }
182
183 if (of_address_to_resource(dart_node, 0, &r))
184 panic("DART: can't get register base ! ");
185
186 /* Make sure nothing from the DART range remains in the CPU cache
187 * from a previous mapping that existed before the kernel took
188 * over
189 */
190 flush_dcache_phys_range(dart_tablebase,
191 dart_tablebase + dart_tablesize);
192
193 /* Allocate a spare page to map all invalid DART pages. We need to do
194 * that to work around what looks like a problem with the HT bridge
195 * prefetching into invalid pages and corrupting data
196 */
197 tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
198 if (!tmp)
199 panic("DART: Cannot allocate spare page!");
200 dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) &
201 DARTMAP_RPNMASK);
202
203 /* Map in DART registers */
204 dart = ioremap(r.start, r.end - r.start + 1);
205 if (dart == NULL)
206 panic("DART: Cannot map registers!");
207
208 /* Map in DART table */
209 dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
210
211 /* Fill initial table */
212 for (i = 0; i < dart_tablesize/4; i++)
213 dart_vbase[i] = dart_emptyval;
214
215 /* Initialize DART with table base and enable it. */
216 base = dart_tablebase >> DART_PAGE_SHIFT;
217 size = dart_tablesize >> DART_PAGE_SHIFT;
218 if (dart_is_u4) {
219 BUG_ON(size & ~DART_SIZE_U4_SIZE_MASK);
220 DART_OUT(DART_BASE_U4, base);
221 DART_OUT(DART_SIZE_U4, size);
222 DART_OUT(DART_CNTL, DART_CNTL_U4_ENABLE);
223 } else {
224 BUG_ON(size & ~DART_CNTL_U3_SIZE_MASK);
225 DART_OUT(DART_CNTL,
226 DART_CNTL_U3_ENABLE |
227 (base << DART_CNTL_U3_BASE_SHIFT) |
228 (size << DART_CNTL_U3_SIZE_SHIFT));
229 }
230
231 /* Invalidate DART to get rid of possible stale TLBs */
232 dart_tlb_invalidate_all();
233
234 printk(KERN_INFO "DART IOMMU initialized for %s type chipset\n",
235 dart_is_u4 ? "U4" : "U3");
236
237 return 0;
238}
239
240static void iommu_table_dart_setup(void)
241{
242 iommu_table_dart.it_busno = 0;
243 iommu_table_dart.it_offset = 0;
244 /* it_size is in number of entries */
245 iommu_table_dart.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
246
247 /* Initialize the common IOMMU code */
248 iommu_table_dart.it_base = (unsigned long)dart_vbase;
249 iommu_table_dart.it_index = 0;
250 iommu_table_dart.it_blocksize = 1;
251 iommu_init_table(&iommu_table_dart);
252
253 /* Reserve the last page of the DART to avoid possible prefetch
254 * past the DART mapped area
255 */
256 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
257}
258
259static void iommu_dev_setup_dart(struct pci_dev *dev)
260{
261 struct device_node *dn;
262
263 /* We only have one iommu table on the mac for now, which makes
264 * things simple. Setup all PCI devices to point to this table
265 *
266 * We must use pci_device_to_OF_node() to make sure that
267 * we get the real "final" pointer to the device in the
268 * pci_dev sysdata and not the temporary PHB one
269 */
270 dn = pci_device_to_OF_node(dev);
271
272 if (dn)
273 PCI_DN(dn)->iommu_table = &iommu_table_dart;
274}
275
276static void iommu_bus_setup_dart(struct pci_bus *bus)
277{
278 struct device_node *dn;
279
280 if (!iommu_table_dart_inited) {
281 iommu_table_dart_inited = 1;
282 iommu_table_dart_setup();
283 }
284
285 dn = pci_bus_to_OF_node(bus);
286
287 if (dn)
288 PCI_DN(dn)->iommu_table = &iommu_table_dart;
289}
290
291static void iommu_dev_setup_null(struct pci_dev *dev) { }
292static void iommu_bus_setup_null(struct pci_bus *bus) { }
293
294void iommu_init_early_dart(void)
295{
296 struct device_node *dn;
297
298 /* Find the DART in the device-tree */
299 dn = of_find_compatible_node(NULL, "dart", "u3-dart");
300 if (dn == NULL) {
301 dn = of_find_compatible_node(NULL, "dart", "u4-dart");
302 if (dn == NULL)
303 goto bail;
304 dart_is_u4 = 1;
305 }
306
307 /* Setup low level TCE operations for the core IOMMU code */
308 ppc_md.tce_build = dart_build;
309 ppc_md.tce_free = dart_free;
310 ppc_md.tce_flush = dart_flush;
311
312 /* Initialize the DART HW */
313 if (dart_init(dn) == 0) {
314 ppc_md.iommu_dev_setup = iommu_dev_setup_dart;
315 ppc_md.iommu_bus_setup = iommu_bus_setup_dart;
316
317 /* Setup pci_dma ops */
318 pci_iommu_init();
319
320 return;
321 }
322
323 bail:
324 /* If init failed, use direct iommu and null setup functions */
325 ppc_md.iommu_dev_setup = iommu_dev_setup_null;
326 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
327
328 /* Setup pci_dma ops */
329 pci_direct_iommu_init();
330}
331
332
333void __init alloc_dart_table(void)
334{
335 /* Only reserve DART space if machine has more than 2GB of RAM
336 * or if requested with iommu=on on cmdline.
337 */
338 if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
339 return;
340
341 /* 512 pages (2MB) is max DART tablesize. */
342 dart_tablesize = 1UL << 21;
343 /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
344 * will blow up an entire large page anyway in the kernel mapping
345 */
346 dart_tablebase = (unsigned long)
347 abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
348
349 printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
350}