aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
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
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')
-rw-r--r--arch/powerpc/sysdev/Makefile2
-rw-r--r--arch/powerpc/sysdev/dart.h41
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c (renamed from arch/powerpc/sysdev/u3_iommu.c)173
-rw-r--r--arch/powerpc/sysdev/mpic.c199
4 files changed, 287 insertions, 128 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index b3e3636a57b0..14b9abde2d27 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,6 +4,6 @@ obj-$(CONFIG_PPC_I8259) += i8259.o
4obj-$(CONFIG_PPC_MPC106) += grackle.o 4obj-$(CONFIG_PPC_MPC106) += grackle.o
5obj-$(CONFIG_BOOKE) += dcr.o 5obj-$(CONFIG_BOOKE) += dcr.o
6obj-$(CONFIG_40x) += dcr.o 6obj-$(CONFIG_40x) += dcr.o
7obj-$(CONFIG_U3_DART) += u3_iommu.o 7obj-$(CONFIG_U3_DART) += dart_iommu.o
8obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 8obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
9obj-$(CONFIG_83xx) += ipic.o 9obj-$(CONFIG_83xx) += ipic.o
diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h
index 33ed9ed7fc1e..c2d05763ccbe 100644
--- a/arch/powerpc/sysdev/dart.h
+++ b/arch/powerpc/sysdev/dart.h
@@ -20,29 +20,44 @@
20#define _POWERPC_SYSDEV_DART_H 20#define _POWERPC_SYSDEV_DART_H
21 21
22 22
23/* physical base of DART registers */
24#define DART_BASE 0xf8033000UL
25
26/* Offset from base to control register */ 23/* Offset from base to control register */
27#define DARTCNTL 0 24#define DART_CNTL 0
25
28/* Offset from base to exception register */ 26/* Offset from base to exception register */
29#define DARTEXCP 0x10 27#define DART_EXCP_U3 0x10
30/* Offset from base to TLB tag registers */ 28/* Offset from base to TLB tag registers */
31#define DARTTAG 0x1000 29#define DART_TAGS_U3 0x1000
32 30
31/* U4 registers */
32#define DART_BASE_U4 0x10
33#define DART_SIZE_U4 0x20
34#define DART_EXCP_U4 0x30
35#define DART_TAGS_U4 0x1000
33 36
34/* Control Register fields */ 37/* Control Register fields */
35 38
36/* base address of table (pfn) */ 39/* U3 registers */
37#define DARTCNTL_BASE_MASK 0xfffff 40#define DART_CNTL_U3_BASE_MASK 0xfffff
38#define DARTCNTL_BASE_SHIFT 12 41#define DART_CNTL_U3_BASE_SHIFT 12
42#define DART_CNTL_U3_FLUSHTLB 0x400
43#define DART_CNTL_U3_ENABLE 0x200
44#define DART_CNTL_U3_SIZE_MASK 0x1ff
45#define DART_CNTL_U3_SIZE_SHIFT 0
46
47/* U4 registers */
48#define DART_BASE_U4_BASE_MASK 0xffffff
49#define DART_BASE_U4_BASE_SHIFT 0
50#define DART_CNTL_U4_FLUSHTLB 0x20000000
51#define DART_CNTL_U4_ENABLE 0x80000000
52#define DART_SIZE_U4_SIZE_MASK 0x1fff
53#define DART_SIZE_U4_SIZE_SHIFT 0
54
55#define DART_REG(r) (dart + ((r) >> 2))
56#define DART_IN(r) (in_be32(DART_REG(r)))
57#define DART_OUT(r,v) (out_be32(DART_REG(r), (v)))
39 58
40#define DARTCNTL_FLUSHTLB 0x400
41#define DARTCNTL_ENABLE 0x200
42 59
43/* size of table in pages */ 60/* size of table in pages */
44#define DARTCNTL_SIZE_MASK 0x1ff
45#define DARTCNTL_SIZE_SHIFT 0
46 61
47 62
48/* DART table fields */ 63/* DART table fields */
diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 5c1a26a6d00c..df0dbdee762a 100644
--- a/arch/powerpc/sysdev/u3_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -1,25 +1,27 @@
1/* 1/*
2 * arch/powerpc/sysdev/u3_iommu.c 2 * arch/powerpc/sysdev/dart_iommu.c
3 * 3 *
4 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation 4 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
5 * Copyright (C) 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>,
6 * IBM Corporation
5 * 7 *
6 * Based on pSeries_iommu.c: 8 * Based on pSeries_iommu.c:
7 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation 9 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
8 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation 10 * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
9 * 11 *
10 * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu. 12 * Dynamic DMA mapping support, Apple U3, U4 & IBM CPC925 "DART" iommu.
13 *
11 * 14 *
12 *
13 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or 17 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version. 18 * (at your option) any later version.
17 * 19 *
18 * This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details. 23 * GNU General Public License for more details.
22 * 24 *
23 * You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software 26 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -57,21 +59,22 @@ static unsigned long dart_tablesize;
57static u32 *dart_vbase; 59static u32 *dart_vbase;
58 60
59/* Mapped base address for the dart */ 61/* Mapped base address for the dart */
60static unsigned int *dart; 62static unsigned int *__iomem dart;
61 63
62/* Dummy val that entries are set to when unused */ 64/* Dummy val that entries are set to when unused */
63static unsigned int dart_emptyval; 65static unsigned int dart_emptyval;
64 66
65static struct iommu_table iommu_table_u3; 67static struct iommu_table iommu_table_dart;
66static int iommu_table_u3_inited; 68static int iommu_table_dart_inited;
67static int dart_dirty; 69static int dart_dirty;
70static int dart_is_u4;
68 71
69#define DBG(...) 72#define DBG(...)
70 73
71static inline void dart_tlb_invalidate_all(void) 74static inline void dart_tlb_invalidate_all(void)
72{ 75{
73 unsigned long l = 0; 76 unsigned long l = 0;
74 unsigned int reg; 77 unsigned int reg, inv_bit;
75 unsigned long limit; 78 unsigned long limit;
76 79
77 DBG("dart: flush\n"); 80 DBG("dart: flush\n");
@@ -81,29 +84,28 @@ static inline void dart_tlb_invalidate_all(void)
81 * 84 *
82 * Gotcha: Sometimes, the DART won't detect that the bit gets 85 * Gotcha: Sometimes, the DART won't detect that the bit gets
83 * set. If so, clear it and set it again. 86 * set. If so, clear it and set it again.
84 */ 87 */
85 88
86 limit = 0; 89 limit = 0;
87 90
91 inv_bit = dart_is_u4 ? DART_CNTL_U4_FLUSHTLB : DART_CNTL_U3_FLUSHTLB;
88retry: 92retry:
89 reg = in_be32((unsigned int *)dart+DARTCNTL);
90 reg |= DARTCNTL_FLUSHTLB;
91 out_be32((unsigned int *)dart+DARTCNTL, reg);
92
93 l = 0; 93 l = 0;
94 while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) && 94 reg = DART_IN(DART_CNTL);
95 l < (1L<<limit)) { 95 reg |= inv_bit;
96 DART_OUT(DART_CNTL, reg);
97
98 while ((DART_IN(DART_CNTL) & inv_bit) && l < (1L << limit))
96 l++; 99 l++;
97 } 100 if (l == (1L << limit)) {
98 if (l == (1L<<limit)) {
99 if (limit < 4) { 101 if (limit < 4) {
100 limit++; 102 limit++;
101 reg = in_be32((unsigned int *)dart+DARTCNTL); 103 reg = DART_IN(DART_CNTL);
102 reg &= ~DARTCNTL_FLUSHTLB; 104 reg &= ~inv_bit;
103 out_be32((unsigned int *)dart+DARTCNTL, reg); 105 DART_OUT(DART_CNTL, reg);
104 goto retry; 106 goto retry;
105 } else 107 } else
106 panic("U3-DART: TLB did not flush after waiting a long " 108 panic("DART: TLB did not flush after waiting a long "
107 "time. Buggy U3 ?"); 109 "time. Buggy U3 ?");
108 } 110 }
109} 111}
@@ -115,7 +117,7 @@ static void dart_flush(struct iommu_table *tbl)
115 dart_dirty = 0; 117 dart_dirty = 0;
116} 118}
117 119
118static void dart_build(struct iommu_table *tbl, long index, 120static void dart_build(struct iommu_table *tbl, long index,
119 long npages, unsigned long uaddr, 121 long npages, unsigned long uaddr,
120 enum dma_data_direction direction) 122 enum dma_data_direction direction)
121{ 123{
@@ -128,7 +130,7 @@ static void dart_build(struct iommu_table *tbl, long index,
128 npages <<= DART_PAGE_FACTOR; 130 npages <<= DART_PAGE_FACTOR;
129 131
130 dp = ((unsigned int*)tbl->it_base) + index; 132 dp = ((unsigned int*)tbl->it_base) + index;
131 133
132 /* On U3, all memory is contigous, so we can move this 134 /* On U3, all memory is contigous, so we can move this
133 * out of the loop. 135 * out of the loop.
134 */ 136 */
@@ -148,7 +150,7 @@ static void dart_build(struct iommu_table *tbl, long index,
148static void dart_free(struct iommu_table *tbl, long index, long npages) 150static void dart_free(struct iommu_table *tbl, long index, long npages)
149{ 151{
150 unsigned int *dp; 152 unsigned int *dp;
151 153
152 /* We don't worry about flushing the TLB cache. The only drawback of 154 /* We don't worry about flushing the TLB cache. The only drawback of
153 * not doing it is that we won't catch buggy device drivers doing 155 * not doing it is that we won't catch buggy device drivers doing
154 * bad DMAs, but then no 32-bit architecture ever does either. 156 * bad DMAs, but then no 32-bit architecture ever does either.
@@ -160,7 +162,7 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
160 npages <<= DART_PAGE_FACTOR; 162 npages <<= DART_PAGE_FACTOR;
161 163
162 dp = ((unsigned int *)tbl->it_base) + index; 164 dp = ((unsigned int *)tbl->it_base) + index;
163 165
164 while (npages--) 166 while (npages--)
165 *(dp++) = dart_emptyval; 167 *(dp++) = dart_emptyval;
166} 168}
@@ -168,20 +170,25 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
168 170
169static int dart_init(struct device_node *dart_node) 171static int dart_init(struct device_node *dart_node)
170{ 172{
171 unsigned int regword;
172 unsigned int i; 173 unsigned int i;
173 unsigned long tmp; 174 unsigned long tmp, base, size;
175 struct resource r;
174 176
175 if (dart_tablebase == 0 || dart_tablesize == 0) { 177 if (dart_tablebase == 0 || dart_tablesize == 0) {
176 printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n"); 178 printk(KERN_INFO "DART: table not allocated, using "
179 "direct DMA\n");
177 return -ENODEV; 180 return -ENODEV;
178 } 181 }
179 182
183 if (of_address_to_resource(dart_node, 0, &r))
184 panic("DART: can't get register base ! ");
185
180 /* Make sure nothing from the DART range remains in the CPU cache 186 /* Make sure nothing from the DART range remains in the CPU cache
181 * from a previous mapping that existed before the kernel took 187 * from a previous mapping that existed before the kernel took
182 * over 188 * over
183 */ 189 */
184 flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize); 190 flush_dcache_phys_range(dart_tablebase,
191 dart_tablebase + dart_tablesize);
185 192
186 /* Allocate a spare page to map all invalid DART pages. We need to do 193 /* Allocate a spare page to map all invalid DART pages. We need to do
187 * that to work around what looks like a problem with the HT bridge 194 * that to work around what looks like a problem with the HT bridge
@@ -189,21 +196,16 @@ static int dart_init(struct device_node *dart_node)
189 */ 196 */
190 tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); 197 tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
191 if (!tmp) 198 if (!tmp)
192 panic("U3-DART: Cannot allocate spare page!"); 199 panic("DART: Cannot allocate spare page!");
193 dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK); 200 dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) &
201 DARTMAP_RPNMASK);
194 202
195 /* Map in DART registers. FIXME: Use device node to get base address */ 203 /* Map in DART registers */
196 dart = ioremap(DART_BASE, 0x7000); 204 dart = ioremap(r.start, r.end - r.start + 1);
197 if (dart == NULL) 205 if (dart == NULL)
198 panic("U3-DART: Cannot map registers!"); 206 panic("DART: Cannot map registers!");
199 207
200 /* Set initial control register contents: table base, 208 /* Map in DART table */
201 * table size and enable bit
202 */
203 regword = DARTCNTL_ENABLE |
204 ((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
205 (((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
206 << DARTCNTL_SIZE_SHIFT);
207 dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize); 209 dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
208 210
209 /* Fill initial table */ 211 /* Fill initial table */
@@ -211,36 +213,50 @@ static int dart_init(struct device_node *dart_node)
211 dart_vbase[i] = dart_emptyval; 213 dart_vbase[i] = dart_emptyval;
212 214
213 /* Initialize DART with table base and enable it. */ 215 /* Initialize DART with table base and enable it. */
214 out_be32((unsigned int *)dart, regword); 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 }
215 230
216 /* Invalidate DART to get rid of possible stale TLBs */ 231 /* Invalidate DART to get rid of possible stale TLBs */
217 dart_tlb_invalidate_all(); 232 dart_tlb_invalidate_all();
218 233
219 printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n"); 234 printk(KERN_INFO "DART IOMMU initialized for %s type chipset\n",
235 dart_is_u4 ? "U4" : "U3");
220 236
221 return 0; 237 return 0;
222} 238}
223 239
224static void iommu_table_u3_setup(void) 240static void iommu_table_dart_setup(void)
225{ 241{
226 iommu_table_u3.it_busno = 0; 242 iommu_table_dart.it_busno = 0;
227 iommu_table_u3.it_offset = 0; 243 iommu_table_dart.it_offset = 0;
228 /* it_size is in number of entries */ 244 /* it_size is in number of entries */
229 iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR; 245 iommu_table_dart.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
230 246
231 /* Initialize the common IOMMU code */ 247 /* Initialize the common IOMMU code */
232 iommu_table_u3.it_base = (unsigned long)dart_vbase; 248 iommu_table_dart.it_base = (unsigned long)dart_vbase;
233 iommu_table_u3.it_index = 0; 249 iommu_table_dart.it_index = 0;
234 iommu_table_u3.it_blocksize = 1; 250 iommu_table_dart.it_blocksize = 1;
235 iommu_init_table(&iommu_table_u3); 251 iommu_init_table(&iommu_table_dart);
236 252
237 /* Reserve the last page of the DART to avoid possible prefetch 253 /* Reserve the last page of the DART to avoid possible prefetch
238 * past the DART mapped area 254 * past the DART mapped area
239 */ 255 */
240 set_bit(iommu_table_u3.it_size - 1, iommu_table_u3.it_map); 256 set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
241} 257}
242 258
243static void iommu_dev_setup_u3(struct pci_dev *dev) 259static void iommu_dev_setup_dart(struct pci_dev *dev)
244{ 260{
245 struct device_node *dn; 261 struct device_node *dn;
246 262
@@ -254,35 +270,39 @@ static void iommu_dev_setup_u3(struct pci_dev *dev)
254 dn = pci_device_to_OF_node(dev); 270 dn = pci_device_to_OF_node(dev);
255 271
256 if (dn) 272 if (dn)
257 PCI_DN(dn)->iommu_table = &iommu_table_u3; 273 PCI_DN(dn)->iommu_table = &iommu_table_dart;
258} 274}
259 275
260static void iommu_bus_setup_u3(struct pci_bus *bus) 276static void iommu_bus_setup_dart(struct pci_bus *bus)
261{ 277{
262 struct device_node *dn; 278 struct device_node *dn;
263 279
264 if (!iommu_table_u3_inited) { 280 if (!iommu_table_dart_inited) {
265 iommu_table_u3_inited = 1; 281 iommu_table_dart_inited = 1;
266 iommu_table_u3_setup(); 282 iommu_table_dart_setup();
267 } 283 }
268 284
269 dn = pci_bus_to_OF_node(bus); 285 dn = pci_bus_to_OF_node(bus);
270 286
271 if (dn) 287 if (dn)
272 PCI_DN(dn)->iommu_table = &iommu_table_u3; 288 PCI_DN(dn)->iommu_table = &iommu_table_dart;
273} 289}
274 290
275static void iommu_dev_setup_null(struct pci_dev *dev) { } 291static void iommu_dev_setup_null(struct pci_dev *dev) { }
276static void iommu_bus_setup_null(struct pci_bus *bus) { } 292static void iommu_bus_setup_null(struct pci_bus *bus) { }
277 293
278void iommu_init_early_u3(void) 294void iommu_init_early_dart(void)
279{ 295{
280 struct device_node *dn; 296 struct device_node *dn;
281 297
282 /* Find the DART in the device-tree */ 298 /* Find the DART in the device-tree */
283 dn = of_find_compatible_node(NULL, "dart", "u3-dart"); 299 dn = of_find_compatible_node(NULL, "dart", "u3-dart");
284 if (dn == NULL) 300 if (dn == NULL) {
285 return; 301 dn = of_find_compatible_node(NULL, "dart", "u4-dart");
302 if (dn == NULL)
303 goto bail;
304 dart_is_u4 = 1;
305 }
286 306
287 /* Setup low level TCE operations for the core IOMMU code */ 307 /* Setup low level TCE operations for the core IOMMU code */
288 ppc_md.tce_build = dart_build; 308 ppc_md.tce_build = dart_build;
@@ -290,24 +310,27 @@ void iommu_init_early_u3(void)
290 ppc_md.tce_flush = dart_flush; 310 ppc_md.tce_flush = dart_flush;
291 311
292 /* Initialize the DART HW */ 312 /* Initialize the DART HW */
293 if (dart_init(dn)) { 313 if (dart_init(dn) == 0) {
294 /* If init failed, use direct iommu and null setup functions */ 314 ppc_md.iommu_dev_setup = iommu_dev_setup_dart;
295 ppc_md.iommu_dev_setup = iommu_dev_setup_null; 315 ppc_md.iommu_bus_setup = iommu_bus_setup_dart;
296 ppc_md.iommu_bus_setup = iommu_bus_setup_null;
297
298 /* Setup pci_dma ops */
299 pci_direct_iommu_init();
300 } else {
301 ppc_md.iommu_dev_setup = iommu_dev_setup_u3;
302 ppc_md.iommu_bus_setup = iommu_bus_setup_u3;
303 316
304 /* Setup pci_dma ops */ 317 /* Setup pci_dma ops */
305 pci_iommu_init(); 318 pci_iommu_init();
319
320 return;
306 } 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();
307} 330}
308 331
309 332
310void __init alloc_u3_dart_table(void) 333void __init alloc_dart_table(void)
311{ 334{
312 /* Only reserve DART space if machine has more than 2GB of RAM 335 /* Only reserve DART space if machine has more than 2GB of RAM
313 * or if requested with iommu=on on cmdline. 336 * or if requested with iommu=on on cmdline.
@@ -323,5 +346,5 @@ void __init alloc_u3_dart_table(void)
323 dart_tablebase = (unsigned long) 346 dart_tablebase = (unsigned long)
324 abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L)); 347 abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
325 348
326 printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase); 349 printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
327} 350}
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 9513ea78e6c1..4f26304d0263 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -13,6 +13,9 @@
13 */ 13 */
14 14
15#undef DEBUG 15#undef DEBUG
16#undef DEBUG_IPI
17#undef DEBUG_IRQ
18#undef DEBUG_LOW
16 19
17#include <linux/config.h> 20#include <linux/config.h>
18#include <linux/types.h> 21#include <linux/types.h>
@@ -168,35 +171,86 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
168/* Test if an interrupt is sourced from HyperTransport (used on broken U3s) 171/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
169 * to force the edge setting on the MPIC and do the ack workaround. 172 * to force the edge setting on the MPIC and do the ack workaround.
170 */ 173 */
171static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no) 174static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
172{ 175{
173 if (source_no >= 128 || !mpic->fixups) 176 if (source >= 128 || !mpic->fixups)
174 return 0; 177 return 0;
175 return mpic->fixups[source_no].base != NULL; 178 return mpic->fixups[source].base != NULL;
176} 179}
177 180
178 181
179static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no) 182static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
180{ 183{
181 struct mpic_irq_fixup *fixup = &mpic->fixups[source_no]; 184 struct mpic_irq_fixup *fixup = &mpic->fixups[source];
182 185
183 spin_lock(&mpic->fixup_lock); 186 if (fixup->applebase) {
184 writeb(0x11 + 2 * fixup->irq, fixup->base + 2); 187 unsigned int soff = (fixup->index >> 3) & ~3;
185 writel(fixup->data, fixup->base + 4); 188 unsigned int mask = 1U << (fixup->index & 0x1f);
186 spin_unlock(&mpic->fixup_lock); 189 writel(mask, fixup->applebase + soff);
190 } else {
191 spin_lock(&mpic->fixup_lock);
192 writeb(0x11 + 2 * fixup->index, fixup->base + 2);
193 writel(fixup->data, fixup->base + 4);
194 spin_unlock(&mpic->fixup_lock);
195 }
187} 196}
188 197
198static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
199 unsigned int irqflags)
200{
201 struct mpic_irq_fixup *fixup = &mpic->fixups[source];
202 unsigned long flags;
203 u32 tmp;
204
205 if (fixup->base == NULL)
206 return;
207
208 DBG("startup_ht_interrupt(%u, %u) index: %d\n",
209 source, irqflags, fixup->index);
210 spin_lock_irqsave(&mpic->fixup_lock, flags);
211 /* Enable and configure */
212 writeb(0x10 + 2 * fixup->index, fixup->base + 2);
213 tmp = readl(fixup->base + 4);
214 tmp &= ~(0x23U);
215 if (irqflags & IRQ_LEVEL)
216 tmp |= 0x22;
217 writel(tmp, fixup->base + 4);
218 spin_unlock_irqrestore(&mpic->fixup_lock, flags);
219}
220
221static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
222 unsigned int irqflags)
223{
224 struct mpic_irq_fixup *fixup = &mpic->fixups[source];
225 unsigned long flags;
226 u32 tmp;
227
228 if (fixup->base == NULL)
229 return;
230
231 DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
232
233 /* Disable */
234 spin_lock_irqsave(&mpic->fixup_lock, flags);
235 writeb(0x10 + 2 * fixup->index, fixup->base + 2);
236 tmp = readl(fixup->base + 4);
237 tmp &= ~1U;
238 writel(tmp, fixup->base + 4);
239 spin_unlock_irqrestore(&mpic->fixup_lock, flags);
240}
189 241
190static void __init mpic_scan_ioapic(struct mpic *mpic, u8 __iomem *devbase) 242static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
243 unsigned int devfn, u32 vdid)
191{ 244{
192 int i, irq, n; 245 int i, irq, n;
246 u8 __iomem *base;
193 u32 tmp; 247 u32 tmp;
194 u8 pos; 248 u8 pos;
195 249
196 for (pos = readb(devbase + 0x34); pos; pos = readb(devbase + pos + 1)) { 250 for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
197 u8 id = readb(devbase + pos); 251 pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
198 252 u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
199 if (id == 0x08) { 253 if (id == PCI_CAP_ID_HT_IRQCONF) {
200 id = readb(devbase + pos + 3); 254 id = readb(devbase + pos + 3);
201 if (id == 0x80) 255 if (id == 0x80)
202 break; 256 break;
@@ -205,33 +259,41 @@ static void __init mpic_scan_ioapic(struct mpic *mpic, u8 __iomem *devbase)
205 if (pos == 0) 259 if (pos == 0)
206 return; 260 return;
207 261
208 printk(KERN_INFO "mpic: - Workarounds @ %p, pos = 0x%02x\n", devbase, pos); 262 base = devbase + pos;
263 writeb(0x01, base + 2);
264 n = (readl(base + 4) >> 16) & 0xff;
209 265
210 devbase += pos; 266 printk(KERN_INFO "mpic: - HT:%02x.%x [0x%02x] vendor %04x device %04x"
211 267 " has %d irqs\n",
212 writeb(0x01, devbase + 2); 268 devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
213 n = (readl(devbase + 4) >> 16) & 0xff;
214 269
215 for (i = 0; i <= n; i++) { 270 for (i = 0; i <= n; i++) {
216 writeb(0x10 + 2 * i, devbase + 2); 271 writeb(0x10 + 2 * i, base + 2);
217 tmp = readl(devbase + 4); 272 tmp = readl(base + 4);
218 if ((tmp & 0x21) != 0x20)
219 continue;
220 irq = (tmp >> 16) & 0xff; 273 irq = (tmp >> 16) & 0xff;
221 mpic->fixups[irq].irq = i; 274 DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
222 mpic->fixups[irq].base = devbase; 275 /* mask it , will be unmasked later */
223 writeb(0x11 + 2 * i, devbase + 2); 276 tmp |= 0x1;
224 mpic->fixups[irq].data = readl(devbase + 4) | 0x80000000; 277 writel(tmp, base + 4);
278 mpic->fixups[irq].index = i;
279 mpic->fixups[irq].base = base;
280 /* Apple HT PIC has a non-standard way of doing EOIs */
281 if ((vdid & 0xffff) == 0x106b)
282 mpic->fixups[irq].applebase = devbase + 0x60;
283 else
284 mpic->fixups[irq].applebase = NULL;
285 writeb(0x11 + 2 * i, base + 2);
286 mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
225 } 287 }
226} 288}
227 289
228 290
229static void __init mpic_scan_ioapics(struct mpic *mpic) 291static void __init mpic_scan_ht_pics(struct mpic *mpic)
230{ 292{
231 unsigned int devfn; 293 unsigned int devfn;
232 u8 __iomem *cfgspace; 294 u8 __iomem *cfgspace;
233 295
234 printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n"); 296 printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
235 297
236 /* Allocate fixups array */ 298 /* Allocate fixups array */
237 mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup)); 299 mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
@@ -247,13 +309,14 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
247 cfgspace = ioremap(0xf2000000, 0x10000); 309 cfgspace = ioremap(0xf2000000, 0x10000);
248 BUG_ON(cfgspace == NULL); 310 BUG_ON(cfgspace == NULL);
249 311
250 /* Now we scan all slots. We do a very quick scan, we read the header type, 312 /* Now we scan all slots. We do a very quick scan, we read the header
251 * vendor ID and device ID only, that's plenty enough 313 * type, vendor ID and device ID only, that's plenty enough
252 */ 314 */
253 for (devfn = 0; devfn < 0x100; devfn++) { 315 for (devfn = 0; devfn < 0x100; devfn++) {
254 u8 __iomem *devbase = cfgspace + (devfn << 8); 316 u8 __iomem *devbase = cfgspace + (devfn << 8);
255 u8 hdr_type = readb(devbase + PCI_HEADER_TYPE); 317 u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
256 u32 l = readl(devbase + PCI_VENDOR_ID); 318 u32 l = readl(devbase + PCI_VENDOR_ID);
319 u16 s;
257 320
258 DBG("devfn %x, l: %x\n", devfn, l); 321 DBG("devfn %x, l: %x\n", devfn, l);
259 322
@@ -261,8 +324,12 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
261 if (l == 0xffffffff || l == 0x00000000 || 324 if (l == 0xffffffff || l == 0x00000000 ||
262 l == 0x0000ffff || l == 0xffff0000) 325 l == 0x0000ffff || l == 0xffff0000)
263 goto next; 326 goto next;
327 /* Check if is supports capability lists */
328 s = readw(devbase + PCI_STATUS);
329 if (!(s & PCI_STATUS_CAP_LIST))
330 goto next;
264 331
265 mpic_scan_ioapic(mpic, devbase); 332 mpic_scan_ht_pic(mpic, devbase, devfn, l);
266 333
267 next: 334 next:
268 /* next device, if function 0 */ 335 /* next device, if function 0 */
@@ -363,6 +430,31 @@ static void mpic_enable_irq(unsigned int irq)
363 break; 430 break;
364 } 431 }
365 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); 432 } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
433
434#ifdef CONFIG_MPIC_BROKEN_U3
435 if (mpic->flags & MPIC_BROKEN_U3) {
436 unsigned int src = irq - mpic->irq_offset;
437 if (mpic_is_ht_interrupt(mpic, src) &&
438 (irq_desc[irq].status & IRQ_LEVEL))
439 mpic_ht_end_irq(mpic, src);
440 }
441#endif /* CONFIG_MPIC_BROKEN_U3 */
442}
443
444static unsigned int mpic_startup_irq(unsigned int irq)
445{
446#ifdef CONFIG_MPIC_BROKEN_U3
447 struct mpic *mpic = mpic_from_irq(irq);
448 unsigned int src = irq - mpic->irq_offset;
449
450 if (mpic_is_ht_interrupt(mpic, src))
451 mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
452
453#endif /* CONFIG_MPIC_BROKEN_U3 */
454
455 mpic_enable_irq(irq);
456
457 return 0;
366} 458}
367 459
368static void mpic_disable_irq(unsigned int irq) 460static void mpic_disable_irq(unsigned int irq)
@@ -386,12 +478,27 @@ static void mpic_disable_irq(unsigned int irq)
386 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); 478 } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
387} 479}
388 480
481static void mpic_shutdown_irq(unsigned int irq)
482{
483#ifdef CONFIG_MPIC_BROKEN_U3
484 struct mpic *mpic = mpic_from_irq(irq);
485 unsigned int src = irq - mpic->irq_offset;
486
487 if (mpic_is_ht_interrupt(mpic, src))
488 mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
489
490#endif /* CONFIG_MPIC_BROKEN_U3 */
491
492 mpic_disable_irq(irq);
493}
494
389static void mpic_end_irq(unsigned int irq) 495static void mpic_end_irq(unsigned int irq)
390{ 496{
391 struct mpic *mpic = mpic_from_irq(irq); 497 struct mpic *mpic = mpic_from_irq(irq);
392 498
499#ifdef DEBUG_IRQ
393 DBG("%s: end_irq: %d\n", mpic->name, irq); 500 DBG("%s: end_irq: %d\n", mpic->name, irq);
394 501#endif
395 /* We always EOI on end_irq() even for edge interrupts since that 502 /* We always EOI on end_irq() even for edge interrupts since that
396 * should only lower the priority, the MPIC should have properly 503 * should only lower the priority, the MPIC should have properly
397 * latched another edge interrupt coming in anyway 504 * latched another edge interrupt coming in anyway
@@ -400,8 +507,9 @@ static void mpic_end_irq(unsigned int irq)
400#ifdef CONFIG_MPIC_BROKEN_U3 507#ifdef CONFIG_MPIC_BROKEN_U3
401 if (mpic->flags & MPIC_BROKEN_U3) { 508 if (mpic->flags & MPIC_BROKEN_U3) {
402 unsigned int src = irq - mpic->irq_offset; 509 unsigned int src = irq - mpic->irq_offset;
403 if (mpic_is_ht_interrupt(mpic, src)) 510 if (mpic_is_ht_interrupt(mpic, src) &&
404 mpic_apic_end_irq(mpic, src); 511 (irq_desc[irq].status & IRQ_LEVEL))
512 mpic_ht_end_irq(mpic, src);
405 } 513 }
406#endif /* CONFIG_MPIC_BROKEN_U3 */ 514#endif /* CONFIG_MPIC_BROKEN_U3 */
407 515
@@ -482,6 +590,8 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
482 mpic->name = name; 590 mpic->name = name;
483 591
484 mpic->hc_irq.typename = name; 592 mpic->hc_irq.typename = name;
593 mpic->hc_irq.startup = mpic_startup_irq;
594 mpic->hc_irq.shutdown = mpic_shutdown_irq;
485 mpic->hc_irq.enable = mpic_enable_irq; 595 mpic->hc_irq.enable = mpic_enable_irq;
486 mpic->hc_irq.disable = mpic_disable_irq; 596 mpic->hc_irq.disable = mpic_disable_irq;
487 mpic->hc_irq.end = mpic_end_irq; 597 mpic->hc_irq.end = mpic_end_irq;
@@ -650,10 +760,10 @@ void __init mpic_init(struct mpic *mpic)
650 mpic->irq_count = mpic->num_sources; 760 mpic->irq_count = mpic->num_sources;
651 761
652#ifdef CONFIG_MPIC_BROKEN_U3 762#ifdef CONFIG_MPIC_BROKEN_U3
653 /* Do the ioapic fixups on U3 broken mpic */ 763 /* Do the HT PIC fixups on U3 broken mpic */
654 DBG("MPIC flags: %x\n", mpic->flags); 764 DBG("MPIC flags: %x\n", mpic->flags);
655 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) 765 if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
656 mpic_scan_ioapics(mpic); 766 mpic_scan_ht_pics(mpic);
657#endif /* CONFIG_MPIC_BROKEN_U3 */ 767#endif /* CONFIG_MPIC_BROKEN_U3 */
658 768
659 for (i = 0; i < mpic->num_sources; i++) { 769 for (i = 0; i < mpic->num_sources; i++) {
@@ -840,7 +950,9 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
840 950
841 BUG_ON(mpic == NULL); 951 BUG_ON(mpic == NULL);
842 952
953#ifdef DEBUG_IPI
843 DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); 954 DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
955#endif
844 956
845 mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10, 957 mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
846 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); 958 mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
@@ -851,19 +963,28 @@ int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
851 u32 irq; 963 u32 irq;
852 964
853 irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; 965 irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
966#ifdef DEBUG_LOW
854 DBG("%s: get_one_irq(): %d\n", mpic->name, irq); 967 DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
855 968#endif
856 if (mpic->cascade && irq == mpic->cascade_vec) { 969 if (mpic->cascade && irq == mpic->cascade_vec) {
970#ifdef DEBUG_LOW
857 DBG("%s: cascading ...\n", mpic->name); 971 DBG("%s: cascading ...\n", mpic->name);
972#endif
858 irq = mpic->cascade(regs, mpic->cascade_data); 973 irq = mpic->cascade(regs, mpic->cascade_data);
859 mpic_eoi(mpic); 974 mpic_eoi(mpic);
860 return irq; 975 return irq;
861 } 976 }
862 if (unlikely(irq == MPIC_VEC_SPURRIOUS)) 977 if (unlikely(irq == MPIC_VEC_SPURRIOUS))
863 return -1; 978 return -1;
864 if (irq < MPIC_VEC_IPI_0) 979 if (irq < MPIC_VEC_IPI_0) {
980#ifdef DEBUG_IRQ
981 DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
982#endif
865 return irq + mpic->irq_offset; 983 return irq + mpic->irq_offset;
984 }
985#ifdef DEBUG_IPI
866 DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0); 986 DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
987#endif
867 return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset; 988 return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
868} 989}
869 990