aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/Makefile2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c65
-rw-r--r--arch/sparc64/kernel/pci_sabre.c63
-rw-r--r--arch/sparc64/kernel/psycho_common.c93
-rw-r--r--arch/sparc64/kernel/psycho_common.h8
5 files changed, 111 insertions, 120 deletions
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index fb02807167eb..c0b8009ab196 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y := process.o setup.o cpu.o idprom.o reboot.o \
16 16
17obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 17obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
18obj-$(CONFIG_STACKTRACE) += stacktrace.o 18obj-$(CONFIG_STACKTRACE) += stacktrace.o
19obj-$(CONFIG_PCI) += pci.o pci_common.o \ 19obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \
20 pci_psycho.o pci_sabre.o pci_schizo.o \ 20 pci_psycho.o pci_sabre.o pci_schizo.o \
21 pci_sun4v.o pci_sun4v_asm.o pci_fire.o 21 pci_sun4v.o pci_sun4v_asm.o pci_fire.o
22obj-$(CONFIG_PCI_MSI) += pci_msi.o 22obj-$(CONFIG_PCI_MSI) += pci_msi.o
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 4562b3e0b544..4681e3d8b5fb 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -20,6 +20,7 @@
20 20
21#include "pci_impl.h" 21#include "pci_impl.h"
22#include "iommu_common.h" 22#include "iommu_common.h"
23#include "psycho_common.h"
23 24
24#define DRIVER_NAME "psycho" 25#define DRIVER_NAME "psycho"
25#define PFX DRIVER_NAME ": " 26#define PFX DRIVER_NAME ": "
@@ -787,63 +788,6 @@ static void __init psycho_scan_bus(struct pci_pbm_info *pbm,
787 psycho_register_error_handlers(pbm); 788 psycho_register_error_handlers(pbm);
788} 789}
789 790
790static int psycho_iommu_init(struct pci_pbm_info *pbm)
791{
792 struct iommu *iommu = pbm->iommu;
793 unsigned long i;
794 u64 control;
795 int err;
796
797 /* Register addresses. */
798 iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
799 iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
800 iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
801 iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL);
802
803 /* PSYCHO's IOMMU lacks ctx flushing. */
804 iommu->iommu_ctxflush = 0;
805
806 /* We use the main control register of PSYCHO as the write
807 * completion register.
808 */
809 iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL;
810
811 /*
812 * Invalidate TLB Entries.
813 */
814 control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL);
815 control |= PSYCHO_IOMMU_CTRL_DENAB;
816 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control);
817 for (i = 0; i < 16; i++) {
818 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
819 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
820 }
821
822 /* Leave diag mode enabled for full-flushing done
823 * in pci_iommu.c
824 */
825 err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff,
826 pbm->numa_node);
827 if (err) {
828 printk(KERN_ERR PFX "iommu_table_init() fails\n");
829 return err;
830 }
831
832 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE,
833 __pa(iommu->page_table));
834
835 control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL);
836 control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
837 control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
838 psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control);
839
840 /* If necessary, hook us up for starfire IRQ translations. */
841 if (this_is_starfire)
842 starfire_hookup(pbm->portid);
843
844 return 0;
845}
846
847#define PSYCHO_IRQ_RETRY 0x1a00UL 791#define PSYCHO_IRQ_RETRY 0x1a00UL
848#define PSYCHO_PCIA_DIAG 0x2020UL 792#define PSYCHO_PCIA_DIAG 0x2020UL
849#define PSYCHO_PCIB_DIAG 0x4020UL 793#define PSYCHO_PCIB_DIAG 0x4020UL
@@ -1053,9 +997,14 @@ static int __devinit psycho_probe(struct of_device *op,
1053 997
1054 psycho_controller_hwinit(pbm); 998 psycho_controller_hwinit(pbm);
1055 if (!pbm->sibling) { 999 if (!pbm->sibling) {
1056 err = psycho_iommu_init(pbm); 1000 err = psycho_iommu_init(pbm, 128, 0xc0000000,
1001 0xffffffff, PSYCHO_CONTROL);
1057 if (err) 1002 if (err)
1058 goto out_free_iommu; 1003 goto out_free_iommu;
1004
1005 /* If necessary, hook us up for starfire IRQ translations. */
1006 if (this_is_starfire)
1007 starfire_hookup(pbm->portid);
1059 } 1008 }
1060 1009
1061 psycho_pbm_init(pbm, op, is_pbm_a); 1010 psycho_pbm_init(pbm, op, is_pbm_a);
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 196049bb14b2..a3a276de75ab 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -20,6 +20,7 @@
20 20
21#include "pci_impl.h" 21#include "pci_impl.h"
22#include "iommu_common.h" 22#include "iommu_common.h"
23#include "psycho_common.h"
23 24
24#define DRIVER_NAME "sabre" 25#define DRIVER_NAME "sabre"
25#define PFX DRIVER_NAME ": " 26#define PFX DRIVER_NAME ": "
@@ -674,66 +675,6 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm,
674 sabre_register_error_handlers(pbm); 675 sabre_register_error_handlers(pbm);
675} 676}
676 677
677static int sabre_iommu_init(struct pci_pbm_info *pbm,
678 int tsbsize, unsigned long dvma_offset,
679 u32 dma_mask)
680{
681 struct iommu *iommu = pbm->iommu;
682 unsigned long i;
683 u64 control;
684 int err;
685
686 /* Register addresses. */
687 iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL;
688 iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE;
689 iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH;
690 iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL);
691 iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC;
692 /* Sabre's IOMMU lacks ctx flushing. */
693 iommu->iommu_ctxflush = 0;
694
695 /* Invalidate TLB Entries. */
696 control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL);
697 control |= SABRE_IOMMUCTRL_DENAB;
698 sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
699
700 for(i = 0; i < 16; i++) {
701 sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
702 sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
703 }
704
705 /* Leave diag mode enabled for full-flushing done
706 * in pci_iommu.c
707 */
708 err = iommu_table_init(iommu, tsbsize * 1024 * 8,
709 dvma_offset, dma_mask, pbm->numa_node);
710 if (err) {
711 printk(KERN_ERR PFX "iommu_table_init() failed\n");
712 return err;
713 }
714
715 sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE,
716 __pa(iommu->page_table));
717
718 control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL);
719 control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
720 control |= SABRE_IOMMUCTRL_ENAB;
721 switch(tsbsize) {
722 case 64:
723 control |= SABRE_IOMMU_TSBSZ_64K;
724 break;
725 case 128:
726 control |= SABRE_IOMMU_TSBSZ_128K;
727 break;
728 default:
729 printk(KERN_ERR PFX "Illegal TSB size %d\n", tsbsize);
730 return -EINVAL;
731 }
732 sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
733
734 return 0;
735}
736
737static void __init sabre_pbm_init(struct pci_pbm_info *pbm, 678static void __init sabre_pbm_init(struct pci_pbm_info *pbm,
738 struct of_device *op) 679 struct of_device *op)
739{ 680{
@@ -862,7 +803,7 @@ static int __devinit sabre_probe(struct of_device *op,
862 goto out_free_iommu; 803 goto out_free_iommu;
863 } 804 }
864 805
865 err = sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask); 806 err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC);
866 if (err) 807 if (err)
867 goto out_free_iommu; 808 goto out_free_iommu;
868 809
diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c
new file mode 100644
index 000000000000..07acc13637b3
--- /dev/null
+++ b/arch/sparc64/kernel/psycho_common.c
@@ -0,0 +1,93 @@
1/* psycho_common.c: Code common to PSYCHO and derivative PCI controllers.
2 *
3 * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
4 */
5#include <linux/kernel.h>
6
7#include <asm/upa.h>
8
9#include "pci_impl.h"
10#include "psycho_common.h"
11
12#define PSYCHO_IOMMU_TAG 0xa580UL
13#define PSYCHO_IOMMU_DATA 0xa600UL
14
15static void psycho_iommu_flush(struct pci_pbm_info *pbm)
16{
17 int i;
18
19 for (i = 0; i < 16; i++) {
20 unsigned long off = i * 8;
21
22 upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off);
23 upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off);
24 }
25}
26
27#define PSYCHO_IOMMU_CONTROL 0x0200UL
28#define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL
29#define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL
30#define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL
31#define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL
32#define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL
33#define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL
34#define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL
35#define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL
36#define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL
37#define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL
38#define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL
39#define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL
40#define PSYCHO_IOMMU_FLUSH 0x0210UL
41#define PSYCHO_IOMMU_TSBBASE 0x0208UL
42
43int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize,
44 u32 dvma_offset, u32 dma_mask,
45 unsigned long write_complete_offset)
46{
47 struct iommu *iommu = pbm->iommu;
48 u64 control;
49 int err;
50
51 iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
52 iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
53 iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
54 iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG;
55 iommu->write_complete_reg = (pbm->controller_regs +
56 write_complete_offset);
57
58 iommu->iommu_ctxflush = 0;
59
60 control = upa_readq(iommu->iommu_control);
61 control |= PSYCHO_IOMMU_CTRL_DENAB;
62 upa_writeq(control, iommu->iommu_control);
63
64 psycho_iommu_flush(pbm);
65
66 /* Leave diag mode enabled for full-flushing done in pci_iommu.c */
67 err = iommu_table_init(iommu, tsbsize * 1024 * 8,
68 dvma_offset, dma_mask, pbm->numa_node);
69 if (err)
70 return err;
71
72 upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase);
73
74 control = upa_readq(iommu->iommu_control);
75 control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
76 control |= PSYCHO_IOMMU_CTRL_ENAB;
77
78 switch (tsbsize) {
79 case 64:
80 control |= PSYCHO_IOMMU_TSBSZ_64K;
81 break;
82 case 128:
83 control |= PSYCHO_IOMMU_TSBSZ_128K;
84 break;
85 default:
86 return -EINVAL;
87 }
88
89 upa_writeq(control, iommu->iommu_control);
90
91 return 0;
92
93}
diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h
new file mode 100644
index 000000000000..bffaff57d5e0
--- /dev/null
+++ b/arch/sparc64/kernel/psycho_common.h
@@ -0,0 +1,8 @@
1#ifndef _PSYCHO_COMMON_H
2#define _PSYCHO_COMMON_H
3
4extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize,
5 u32 dvma_offset, u32 dma_mask,
6 unsigned long write_complete_offset);
7
8#endif /* _PSYCHO_COMMON_H */