aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile5
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c46
-rw-r--r--arch/powerpc/sysdev/mpic.c162
-rw-r--r--arch/powerpc/sysdev/mpic.h38
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c183
-rw-r--r--arch/powerpc/sysdev/mpic_u3msi.c186
-rw-r--r--arch/powerpc/sysdev/rom.c32
-rw-r--r--arch/powerpc/sysdev/tsi108_dev.c7
-rw-r--r--arch/powerpc/sysdev/tsi108_pci.c12
-rw-r--r--arch/powerpc/sysdev/uic.c2
10 files changed, 624 insertions, 49 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index e96ca9618dbb..9ce775c38ab7 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -2,7 +2,9 @@ ifeq ($(CONFIG_PPC64),y)
2EXTRA_CFLAGS += -mno-minimal-toc 2EXTRA_CFLAGS += -mno-minimal-toc
3endif 3endif
4 4
5obj-$(CONFIG_MPIC) += mpic.o 5mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o
6obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
7
6obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o 8obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
7obj-$(CONFIG_PPC_MPC106) += grackle.o 9obj-$(CONFIG_PPC_MPC106) += grackle.o
8obj-$(CONFIG_PPC_DCR) += dcr.o 10obj-$(CONFIG_PPC_DCR) += dcr.o
@@ -26,7 +28,6 @@ endif
26 28
27# Temporary hack until we have migrated to asm-powerpc 29# Temporary hack until we have migrated to asm-powerpc
28ifeq ($(ARCH),powerpc) 30ifeq ($(ARCH),powerpc)
29obj-$(CONFIG_MTD) += rom.o
30obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o 31obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
31obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o 32obj-$(CONFIG_8xx) += mpc8xx_pic.o commproc.o
32obj-$(CONFIG_UCODE_PATCH) += micropatch.o 33obj-$(CONFIG_UCODE_PATCH) += micropatch.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 336186dd7f10..a1d2042bb304 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -36,6 +36,7 @@
36#include <linux/pci.h> 36#include <linux/pci.h>
37#include <linux/dma-mapping.h> 37#include <linux/dma-mapping.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/suspend.h>
39#include <asm/io.h> 40#include <asm/io.h>
40#include <asm/prom.h> 41#include <asm/prom.h>
41#include <asm/iommu.h> 42#include <asm/iommu.h>
@@ -54,6 +55,9 @@ static unsigned long dart_tablesize;
54 55
55/* Virtual base address of the DART table */ 56/* Virtual base address of the DART table */
56static u32 *dart_vbase; 57static u32 *dart_vbase;
58#ifdef CONFIG_PM
59static u32 *dart_copy;
60#endif
57 61
58/* Mapped base address for the dart */ 62/* Mapped base address for the dart */
59static unsigned int __iomem *dart; 63static unsigned int __iomem *dart;
@@ -346,6 +350,48 @@ void iommu_init_early_dart(void)
346 set_pci_dma_ops(&dma_direct_ops); 350 set_pci_dma_ops(&dma_direct_ops);
347} 351}
348 352
353#ifdef CONFIG_PM
354static void iommu_dart_save(void)
355{
356 memcpy(dart_copy, dart_vbase, 2*1024*1024);
357}
358
359static void iommu_dart_restore(void)
360{
361 memcpy(dart_vbase, dart_copy, 2*1024*1024);
362 dart_tlb_invalidate_all();
363}
364
365static int __init iommu_init_late_dart(void)
366{
367 unsigned long tbasepfn;
368 struct page *p;
369
370 /* if no dart table exists then we won't need to save it
371 * and the area has also not been reserved */
372 if (!dart_tablebase)
373 return 0;
374
375 tbasepfn = __pa(dart_tablebase) >> PAGE_SHIFT;
376 register_nosave_region_late(tbasepfn,
377 tbasepfn + ((1<<24) >> PAGE_SHIFT));
378
379 /* For suspend we need to copy the dart contents because
380 * it is not part of the regular mapping (see above) and
381 * thus not saved automatically. The memory for this copy
382 * must be allocated early because we need 2 MB. */
383 p = alloc_pages(GFP_KERNEL, 21 - PAGE_SHIFT);
384 BUG_ON(!p);
385 dart_copy = page_address(p);
386
387 ppc_md.iommu_save = iommu_dart_save;
388 ppc_md.iommu_restore = iommu_dart_restore;
389
390 return 0;
391}
392
393late_initcall(iommu_init_late_dart);
394#endif
349 395
350void __init alloc_dart_table(void) 396void __init alloc_dart_table(void)
351{ 397{
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 0b84b7c775d8..4fd2bec89916 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -36,6 +36,8 @@
36#include <asm/mpic.h> 36#include <asm/mpic.h>
37#include <asm/smp.h> 37#include <asm/smp.h>
38 38
39#include "mpic.h"
40
39#ifdef DEBUG 41#ifdef DEBUG
40#define DBG(fmt...) printk(fmt) 42#define DBG(fmt...) printk(fmt)
41#else 43#else
@@ -354,6 +356,12 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
354 tmp |= 0x22; 356 tmp |= 0x22;
355 writel(tmp, fixup->base + 4); 357 writel(tmp, fixup->base + 4);
356 spin_unlock_irqrestore(&mpic->fixup_lock, flags); 358 spin_unlock_irqrestore(&mpic->fixup_lock, flags);
359
360#ifdef CONFIG_PM
361 /* use the lowest bit inverted to the actual HW,
362 * set if this fixup was enabled, clear otherwise */
363 mpic->save_data[source].fixup_data = tmp | 1;
364#endif
357} 365}
358 366
359static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source, 367static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
@@ -375,8 +383,58 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
375 tmp |= 1; 383 tmp |= 1;
376 writel(tmp, fixup->base + 4); 384 writel(tmp, fixup->base + 4);
377 spin_unlock_irqrestore(&mpic->fixup_lock, flags); 385 spin_unlock_irqrestore(&mpic->fixup_lock, flags);
386
387#ifdef CONFIG_PM
388 /* use the lowest bit inverted to the actual HW,
389 * set if this fixup was enabled, clear otherwise */
390 mpic->save_data[source].fixup_data = tmp & ~1;
391#endif
378} 392}
379 393
394#ifdef CONFIG_PCI_MSI
395static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
396 unsigned int devfn)
397{
398 u8 __iomem *base;
399 u8 pos, flags;
400 u64 addr = 0;
401
402 for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
403 pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
404 u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
405 if (id == PCI_CAP_ID_HT) {
406 id = readb(devbase + pos + 3);
407 if ((id & HT_5BIT_CAP_MASK) == HT_CAPTYPE_MSI_MAPPING)
408 break;
409 }
410 }
411
412 if (pos == 0)
413 return;
414
415 base = devbase + pos;
416
417 flags = readb(base + HT_MSI_FLAGS);
418 if (!(flags & HT_MSI_FLAGS_FIXED)) {
419 addr = readl(base + HT_MSI_ADDR_LO) & HT_MSI_ADDR_LO_MASK;
420 addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
421 }
422
423 printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
424 PCI_SLOT(devfn), PCI_FUNC(devfn),
425 flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
426
427 if (!(flags & HT_MSI_FLAGS_ENABLE))
428 writeb(flags | HT_MSI_FLAGS_ENABLE, base + HT_MSI_FLAGS);
429}
430#else
431static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
432 unsigned int devfn)
433{
434 return;
435}
436#endif
437
380static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, 438static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
381 unsigned int devfn, u32 vdid) 439 unsigned int devfn, u32 vdid)
382{ 440{
@@ -468,6 +526,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
468 goto next; 526 goto next;
469 527
470 mpic_scan_ht_pic(mpic, devbase, devfn, l); 528 mpic_scan_ht_pic(mpic, devbase, devfn, l);
529 mpic_scan_ht_msi(mpic, devbase, devfn);
471 530
472 next: 531 next:
473 /* next device, if function 0 */ 532 /* next device, if function 0 */
@@ -559,7 +618,7 @@ static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
559 */ 618 */
560 619
561 620
562static void mpic_unmask_irq(unsigned int irq) 621void mpic_unmask_irq(unsigned int irq)
563{ 622{
564 unsigned int loops = 100000; 623 unsigned int loops = 100000;
565 struct mpic *mpic = mpic_from_irq(irq); 624 struct mpic *mpic = mpic_from_irq(irq);
@@ -579,7 +638,7 @@ static void mpic_unmask_irq(unsigned int irq)
579 } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK); 638 } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
580} 639}
581 640
582static void mpic_mask_irq(unsigned int irq) 641void mpic_mask_irq(unsigned int irq)
583{ 642{
584 unsigned int loops = 100000; 643 unsigned int loops = 100000;
585 struct mpic *mpic = mpic_from_irq(irq); 644 struct mpic *mpic = mpic_from_irq(irq);
@@ -600,7 +659,7 @@ static void mpic_mask_irq(unsigned int irq)
600 } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK)); 659 } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
601} 660}
602 661
603static void mpic_end_irq(unsigned int irq) 662void mpic_end_irq(unsigned int irq)
604{ 663{
605 struct mpic *mpic = mpic_from_irq(irq); 664 struct mpic *mpic = mpic_from_irq(irq);
606 665
@@ -733,7 +792,7 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
733 } 792 }
734} 793}
735 794
736static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) 795int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
737{ 796{
738 struct mpic *mpic = mpic_from_irq(virq); 797 struct mpic *mpic = mpic_from_irq(virq);
739 unsigned int src = mpic_irq_to_hw(virq); 798 unsigned int src = mpic_irq_to_hw(virq);
@@ -834,6 +893,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
834 if (hw >= mpic->irq_count) 893 if (hw >= mpic->irq_count)
835 return -EINVAL; 894 return -EINVAL;
836 895
896 mpic_msi_reserve_hwirq(mpic, hw);
897
837 /* Default chip */ 898 /* Default chip */
838 chip = &mpic->hc_irq; 899 chip = &mpic->hc_irq;
839 900
@@ -1142,8 +1203,10 @@ void __init mpic_init(struct mpic *mpic)
1142 1203
1143 /* Do the HT PIC fixups on U3 broken mpic */ 1204 /* Do the HT PIC fixups on U3 broken mpic */
1144 DBG("MPIC flags: %x\n", mpic->flags); 1205 DBG("MPIC flags: %x\n", mpic->flags);
1145 if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) 1206 if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) {
1146 mpic_scan_ht_pics(mpic); 1207 mpic_scan_ht_pics(mpic);
1208 mpic_u3msi_init(mpic);
1209 }
1147 1210
1148 for (i = 0; i < mpic->num_sources; i++) { 1211 for (i = 0; i < mpic->num_sources; i++) {
1149 /* start with vector = source number, and masked */ 1212 /* start with vector = source number, and masked */
@@ -1167,6 +1230,12 @@ void __init mpic_init(struct mpic *mpic)
1167 1230
1168 /* Set current processor priority to 0 */ 1231 /* Set current processor priority to 0 */
1169 mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); 1232 mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
1233
1234#ifdef CONFIG_PM
1235 /* allocate memory to save mpic state */
1236 mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
1237 BUG_ON(mpic->save_data == NULL);
1238#endif
1170} 1239}
1171 1240
1172void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) 1241void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -1333,8 +1402,11 @@ unsigned int mpic_get_one_irq(struct mpic *mpic)
1333#ifdef DEBUG_LOW 1402#ifdef DEBUG_LOW
1334 DBG("%s: get_one_irq(): %d\n", mpic->name, src); 1403 DBG("%s: get_one_irq(): %d\n", mpic->name, src);
1335#endif 1404#endif
1336 if (unlikely(src == mpic->spurious_vec)) 1405 if (unlikely(src == mpic->spurious_vec)) {
1406 if (mpic->flags & MPIC_SPV_EOI)
1407 mpic_eoi(mpic);
1337 return NO_IRQ; 1408 return NO_IRQ;
1409 }
1338 return irq_linear_revmap(mpic->irqhost, src); 1410 return irq_linear_revmap(mpic->irqhost, src);
1339} 1411}
1340 1412
@@ -1417,3 +1489,79 @@ void __devinit smp_mpic_setup_cpu(int cpu)
1417 mpic_setup_this_cpu(); 1489 mpic_setup_this_cpu();
1418} 1490}
1419#endif /* CONFIG_SMP */ 1491#endif /* CONFIG_SMP */
1492
1493#ifdef CONFIG_PM
1494static int mpic_suspend(struct sys_device *dev, pm_message_t state)
1495{
1496 struct mpic *mpic = container_of(dev, struct mpic, sysdev);
1497 int i;
1498
1499 for (i = 0; i < mpic->num_sources; i++) {
1500 mpic->save_data[i].vecprio =
1501 mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
1502 mpic->save_data[i].dest =
1503 mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
1504 }
1505
1506 return 0;
1507}
1508
1509static int mpic_resume(struct sys_device *dev)
1510{
1511 struct mpic *mpic = container_of(dev, struct mpic, sysdev);
1512 int i;
1513
1514 for (i = 0; i < mpic->num_sources; i++) {
1515 mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
1516 mpic->save_data[i].vecprio);
1517 mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
1518 mpic->save_data[i].dest);
1519
1520#ifdef CONFIG_MPIC_U3_HT_IRQS
1521 {
1522 struct mpic_irq_fixup *fixup = &mpic->fixups[i];
1523
1524 if (fixup->base) {
1525 /* we use the lowest bit in an inverted meaning */
1526 if ((mpic->save_data[i].fixup_data & 1) == 0)
1527 continue;
1528
1529 /* Enable and configure */
1530 writeb(0x10 + 2 * fixup->index, fixup->base + 2);
1531
1532 writel(mpic->save_data[i].fixup_data & ~1,
1533 fixup->base + 4);
1534 }
1535 }
1536#endif
1537 } /* end for loop */
1538
1539 return 0;
1540}
1541#endif
1542
1543static struct sysdev_class mpic_sysclass = {
1544#ifdef CONFIG_PM
1545 .resume = mpic_resume,
1546 .suspend = mpic_suspend,
1547#endif
1548 set_kset_name("mpic"),
1549};
1550
1551static int mpic_init_sys(void)
1552{
1553 struct mpic *mpic = mpics;
1554 int error, id = 0;
1555
1556 error = sysdev_class_register(&mpic_sysclass);
1557
1558 while (mpic && !error) {
1559 mpic->sysdev.cls = &mpic_sysclass;
1560 mpic->sysdev.id = id++;
1561 error = sysdev_register(&mpic->sysdev);
1562 mpic = mpic->next;
1563 }
1564 return error;
1565}
1566
1567device_initcall(mpic_init_sys);
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
new file mode 100644
index 000000000000..3a1c3d2c594d
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic.h
@@ -0,0 +1,38 @@
1#ifndef _POWERPC_SYSDEV_MPIC_H
2#define _POWERPC_SYSDEV_MPIC_H
3
4/*
5 * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2 of the
10 * License.
11 *
12 */
13
14#ifdef CONFIG_PCI_MSI
15extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);
16extern int mpic_msi_init_allocator(struct mpic *mpic);
17extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num);
18extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);
19extern int mpic_u3msi_init(struct mpic *mpic);
20#else
21static inline void mpic_msi_reserve_hwirq(struct mpic *mpic,
22 irq_hw_number_t hwirq)
23{
24 return;
25}
26
27static inline int mpic_u3msi_init(struct mpic *mpic)
28{
29 return -1;
30}
31#endif
32
33extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
34extern void mpic_end_irq(unsigned int irq);
35extern void mpic_mask_irq(unsigned int irq);
36extern void mpic_unmask_irq(unsigned int irq);
37
38#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
new file mode 100644
index 000000000000..b076793033c2
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -0,0 +1,183 @@
1/*
2 * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; version 2 of the
7 * License.
8 *
9 */
10
11#include <linux/irq.h>
12#include <linux/bootmem.h>
13#include <linux/bitmap.h>
14#include <linux/msi.h>
15#include <asm/mpic.h>
16#include <asm/prom.h>
17#include <asm/hw_irq.h>
18#include <asm/ppc-pci.h>
19
20
21static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
22{
23 pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
24 bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
25}
26
27void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
28{
29 unsigned long flags;
30
31 /* The mpic calls this even when there is no allocator setup */
32 if (!mpic->hwirq_bitmap)
33 return;
34
35 spin_lock_irqsave(&mpic->bitmap_lock, flags);
36 __mpic_msi_reserve_hwirq(mpic, hwirq);
37 spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
38}
39
40irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
41{
42 unsigned long flags;
43 int offset, order = get_count_order(num);
44
45 spin_lock_irqsave(&mpic->bitmap_lock, flags);
46 /*
47 * This is fast, but stricter than we need. We might want to add
48 * a fallback routine which does a linear search with no alignment.
49 */
50 offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
51 order);
52 spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
53
54 pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
55 num, order, offset);
56
57 return offset;
58}
59
60void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
61{
62 unsigned long flags;
63 int order = get_count_order(num);
64
65 pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
66 num, order, offset);
67
68 spin_lock_irqsave(&mpic->bitmap_lock, flags);
69 bitmap_release_region(mpic->hwirq_bitmap, offset, order);
70 spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
71}
72
73#ifdef CONFIG_MPIC_U3_HT_IRQS
74static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
75{
76 irq_hw_number_t hwirq;
77 struct irq_host_ops *ops = mpic->irqhost->ops;
78 struct device_node *np;
79 int flags, index, i;
80 struct of_irq oirq;
81
82 pr_debug("mpic: found U3, guessing msi allocator setup\n");
83
84 /* Reserve source numbers we know are reserved in the HW */
85 for (i = 0; i < 8; i++)
86 __mpic_msi_reserve_hwirq(mpic, i);
87
88 for (i = 42; i < 46; i++)
89 __mpic_msi_reserve_hwirq(mpic, i);
90
91 for (i = 100; i < 105; i++)
92 __mpic_msi_reserve_hwirq(mpic, i);
93
94 np = NULL;
95 while ((np = of_find_all_nodes(np))) {
96 pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
97
98 index = 0;
99 while (of_irq_map_one(np, index++, &oirq) == 0) {
100 ops->xlate(mpic->irqhost, NULL, oirq.specifier,
101 oirq.size, &hwirq, &flags);
102 __mpic_msi_reserve_hwirq(mpic, hwirq);
103 }
104 }
105
106 return 0;
107}
108#else
109static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
110{
111 return -1;
112}
113#endif
114
115static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
116{
117 int i, len;
118 const u32 *p;
119
120 p = of_get_property(mpic->of_node, "msi-available-ranges", &len);
121 if (!p) {
122 pr_debug("mpic: no msi-available-ranges property found on %s\n",
123 mpic->of_node->full_name);
124 return -ENODEV;
125 }
126
127 if (len % 8 != 0) {
128 printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
129 "property on %s\n", mpic->of_node->full_name);
130 return -EINVAL;
131 }
132
133 bitmap_allocate_region(mpic->hwirq_bitmap, 0,
134 get_count_order(mpic->irq_count));
135
136 /* Format is: (<u32 start> <u32 count>)+ */
137 len /= sizeof(u32);
138 for (i = 0; i < len / 2; i++, p += 2)
139 mpic_msi_free_hwirqs(mpic, *p, *(p + 1));
140
141 return 0;
142}
143
144int mpic_msi_init_allocator(struct mpic *mpic)
145{
146 int rc, size;
147
148 BUG_ON(mpic->hwirq_bitmap);
149 spin_lock_init(&mpic->bitmap_lock);
150
151 size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
152 pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);
153
154 if (mem_init_done)
155 mpic->hwirq_bitmap = kmalloc(size, GFP_KERNEL);
156 else
157 mpic->hwirq_bitmap = alloc_bootmem(size);
158
159 if (!mpic->hwirq_bitmap) {
160 pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
161 return -ENOMEM;
162 }
163
164 memset(mpic->hwirq_bitmap, 0, size);
165
166 rc = mpic_msi_reserve_dt_hwirqs(mpic);
167 if (rc) {
168 if (mpic->flags & MPIC_U3_HT_IRQS)
169 rc = mpic_msi_reserve_u3_hwirqs(mpic);
170
171 if (rc)
172 goto out_free;
173 }
174
175 return 0;
176
177 out_free:
178 if (mem_init_done)
179 kfree(mpic->hwirq_bitmap);
180
181 mpic->hwirq_bitmap = NULL;
182 return rc;
183}
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
new file mode 100644
index 000000000000..305b864c25d9
--- /dev/null
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -0,0 +1,186 @@
1/*
2 * Copyright 2006, Segher Boessenkool, IBM Corporation.
3 * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; version 2 of the
8 * License.
9 *
10 */
11
12#include <linux/irq.h>
13#include <linux/bootmem.h>
14#include <linux/msi.h>
15#include <asm/mpic.h>
16#include <asm/prom.h>
17#include <asm/hw_irq.h>
18#include <asm/ppc-pci.h>
19
20#include "mpic.h"
21
22/* A bit ugly, can we get this from the pci_dev somehow? */
23static struct mpic *msi_mpic;
24
25static void mpic_u3msi_mask_irq(unsigned int irq)
26{
27 mask_msi_irq(irq);
28 mpic_mask_irq(irq);
29}
30
31static void mpic_u3msi_unmask_irq(unsigned int irq)
32{
33 mpic_unmask_irq(irq);
34 unmask_msi_irq(irq);
35}
36
37static struct irq_chip mpic_u3msi_chip = {
38 .shutdown = mpic_u3msi_mask_irq,
39 .mask = mpic_u3msi_mask_irq,
40 .unmask = mpic_u3msi_unmask_irq,
41 .eoi = mpic_end_irq,
42 .set_type = mpic_set_irq_type,
43 .typename = "MPIC-U3MSI",
44};
45
46static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
47{
48 u8 flags;
49 u32 tmp;
50 u64 addr;
51
52 pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);
53
54 if (flags & HT_MSI_FLAGS_FIXED)
55 return HT_MSI_FIXED_ADDR;
56
57 pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
58 addr = tmp & HT_MSI_ADDR_LO_MASK;
59 pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
60 addr = addr | ((u64)tmp << 32);
61
62 return addr;
63}
64
65static u64 find_ht_magic_addr(struct pci_dev *pdev)
66{
67 struct pci_bus *bus;
68 unsigned int pos;
69
70 for (bus = pdev->bus; bus; bus = bus->parent) {
71 pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
72 if (pos)
73 return read_ht_magic_addr(bus->self, pos);
74 }
75
76 return 0;
77}
78
79static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
80{
81 if (type == PCI_CAP_ID_MSIX)
82 pr_debug("u3msi: MSI-X untested, trying anyway.\n");
83
84 /* If we can't find a magic address then MSI ain't gonna work */
85 if (find_ht_magic_addr(pdev) == 0) {
86 pr_debug("u3msi: no magic address found for %s\n",
87 pci_name(pdev));
88 return -ENXIO;
89 }
90
91 return 0;
92}
93
94static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
95{
96 struct msi_desc *entry;
97
98 list_for_each_entry(entry, &pdev->msi_list, list) {
99 if (entry->irq == NO_IRQ)
100 continue;
101
102 set_irq_msi(entry->irq, NULL);
103 mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1);
104 irq_dispose_mapping(entry->irq);
105 }
106
107 return;
108}
109
110static void u3msi_compose_msi_msg(struct pci_dev *pdev, int virq,
111 struct msi_msg *msg)
112{
113 u64 addr;
114
115 addr = find_ht_magic_addr(pdev);
116 msg->address_lo = addr & 0xFFFFFFFF;
117 msg->address_hi = addr >> 32;
118 msg->data = virq_to_hw(virq);
119
120 pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) at address 0x%lx\n",
121 virq, virq_to_hw(virq), addr);
122}
123
124static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
125{
126 irq_hw_number_t hwirq;
127 int rc;
128 unsigned int virq;
129 struct msi_desc *entry;
130 struct msi_msg msg;
131
132 list_for_each_entry(entry, &pdev->msi_list, list) {
133 hwirq = mpic_msi_alloc_hwirqs(msi_mpic, 1);
134 if (hwirq < 0) {
135 rc = hwirq;
136 pr_debug("u3msi: failed allocating hwirq\n");
137 goto out_free;
138 }
139
140 virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
141 if (virq == NO_IRQ) {
142 pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq);
143 mpic_msi_free_hwirqs(msi_mpic, hwirq, 1);
144 rc = -ENOSPC;
145 goto out_free;
146 }
147
148 set_irq_msi(virq, entry);
149 set_irq_chip(virq, &mpic_u3msi_chip);
150 set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
151
152 u3msi_compose_msi_msg(pdev, virq, &msg);
153 write_msi_msg(virq, &msg);
154
155 hwirq++;
156 }
157
158 return 0;
159
160 out_free:
161 u3msi_teardown_msi_irqs(pdev);
162 return rc;
163}
164
165int mpic_u3msi_init(struct mpic *mpic)
166{
167 int rc;
168
169 rc = mpic_msi_init_allocator(mpic);
170 if (rc) {
171 pr_debug("u3msi: Error allocating bitmap!\n");
172 return rc;
173 }
174
175 pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");
176
177 BUG_ON(msi_mpic);
178 msi_mpic = mpic;
179
180 WARN_ON(ppc_md.setup_msi_irqs);
181 ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
182 ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
183 ppc_md.msi_check_device = u3msi_msi_check_device;
184
185 return 0;
186}
diff --git a/arch/powerpc/sysdev/rom.c b/arch/powerpc/sysdev/rom.c
deleted file mode 100644
index c855a3b298a3..000000000000
--- a/arch/powerpc/sysdev/rom.c
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * ROM device registration
3 *
4 * (C) 2006 MontaVista Software, Inc. This file is licensed under
5 * the terms of the GNU General Public License version 2. This program
6 * is licensed "as is" without any warranty of any kind, whether express
7 * or implied.
8 */
9
10#include <linux/kernel.h>
11#include <asm/of_device.h>
12#include <asm/of_platform.h>
13
14static int __init powerpc_flash_init(void)
15{
16 struct device_node *node = NULL;
17
18 /*
19 * Register all the devices which type is "rom"
20 */
21 while ((node = of_find_node_by_type(node, "rom")) != NULL) {
22 if (node->name == NULL) {
23 printk(KERN_WARNING "powerpc_flash_init: found 'rom' "
24 "device, but with no name, skipping...\n");
25 continue;
26 }
27 of_platform_device_create(node, node->name, NULL);
28 }
29 return 0;
30}
31
32arch_initcall(powerpc_flash_init);
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 337039ee51e6..7d3b09b7d544 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -107,8 +107,9 @@ static int __init tsi108_eth_of_init(void)
107 goto err; 107 goto err;
108 } 108 }
109 109
110 mac_addr = of_get_property(np, "address", NULL); 110 mac_addr = of_get_mac_address(np);
111 memcpy(tsi_eth_data.mac_addr, mac_addr, 6); 111 if (mac_addr)
112 memcpy(tsi_eth_data.mac_addr, mac_addr, 6);
112 113
113 ph = of_get_property(np, "phy-handle", NULL); 114 ph = of_get_property(np, "phy-handle", NULL);
114 phy = of_find_node_by_phandle(*ph); 115 phy = of_find_node_by_phandle(*ph);
@@ -129,6 +130,8 @@ static int __init tsi108_eth_of_init(void)
129 tsi_eth_data.phyregs = res.start; 130 tsi_eth_data.phyregs = res.start;
130 tsi_eth_data.phy = *phy_id; 131 tsi_eth_data.phy = *phy_id;
131 tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); 132 tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
133 if (of_device_is_compatible(phy, "bcm54xx"))
134 tsi_eth_data.phy_type = TSI108_PHY_BCM54XX;
132 of_node_put(phy); 135 of_node_put(phy);
133 ret = 136 ret =
134 platform_device_add_data(tsi_eth_dev, &tsi_eth_data, 137 platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 58b9e7f8abf2..2153163fa593 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -35,6 +35,7 @@
35#include <asm/machdep.h> 35#include <asm/machdep.h>
36#include <asm/pci-bridge.h> 36#include <asm/pci-bridge.h>
37#include <asm/tsi108.h> 37#include <asm/tsi108.h>
38#include <asm/tsi108_pci.h>
38#include <asm/tsi108_irq.h> 39#include <asm/tsi108_irq.h>
39#include <asm/prom.h> 40#include <asm/prom.h>
40 41
@@ -49,6 +50,7 @@
49 ((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base) 50 ((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base)
50 51
51u32 tsi108_pci_cfg_base; 52u32 tsi108_pci_cfg_base;
53static u32 tsi108_pci_cfg_phys;
52u32 tsi108_csr_vir_base; 54u32 tsi108_csr_vir_base;
53static struct device_node *pci_irq_node; 55static struct device_node *pci_irq_node;
54static struct irq_host *pci_irq_host; 56static struct irq_host *pci_irq_host;
@@ -185,7 +187,7 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
185 187
186void tsi108_clear_pci_cfg_error(void) 188void tsi108_clear_pci_cfg_error(void)
187{ 189{
188 tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS); 190 tsi108_clear_pci_error(tsi108_pci_cfg_phys);
189} 191}
190 192
191static struct pci_ops tsi108_direct_pci_ops = { 193static struct pci_ops tsi108_direct_pci_ops = {
@@ -193,17 +195,17 @@ static struct pci_ops tsi108_direct_pci_ops = {
193 tsi108_direct_write_config 195 tsi108_direct_write_config
194}; 196};
195 197
196int __init tsi108_setup_pci(struct device_node *dev) 198int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary)
197{ 199{
198 int len; 200 int len;
199 struct pci_controller *hose; 201 struct pci_controller *hose;
200 struct resource rsrc; 202 struct resource rsrc;
201 const int *bus_range; 203 const int *bus_range;
202 int primary = 0, has_address = 0; 204 int has_address = 0;
203 205
204 /* PCI Config mapping */ 206 /* PCI Config mapping */
205 tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS, 207 tsi108_pci_cfg_base = (u32)ioremap(cfg_phys, TSI108_PCI_CFG_SIZE);
206 TSI108_PCI_CFG_SIZE); 208 tsi108_pci_cfg_phys = cfg_phys;
207 DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__, 209 DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
208 tsi108_pci_cfg_base); 210 tsi108_pci_cfg_base);
209 211
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 968fb40af9dc..89059895a20d 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -221,7 +221,7 @@ static struct uic * __init uic_init_one(struct device_node *node)
221 const u32 *indexp, *dcrreg; 221 const u32 *indexp, *dcrreg;
222 int len; 222 int len;
223 223
224 BUG_ON(! device_is_compatible(node, "ibm,uic")); 224 BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
225 225
226 uic = alloc_bootmem(sizeof(*uic)); 226 uic = alloc_bootmem(sizeof(*uic));
227 if (! uic) 227 if (! uic)