diff options
-rw-r--r-- | arch/sparc64/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 65 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 63 | ||||
-rw-r--r-- | arch/sparc64/kernel/psycho_common.c | 93 | ||||
-rw-r--r-- | arch/sparc64/kernel/psycho_common.h | 8 |
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 | ||
17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
19 | obj-$(CONFIG_PCI) += pci.o pci_common.o \ | 19 | obj-$(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 |
22 | obj-$(CONFIG_PCI_MSI) += pci_msi.o | 22 | obj-$(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 | ||
790 | static 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 | ||
677 | static 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 | |||
737 | static void __init sabre_pbm_init(struct pci_pbm_info *pbm, | 678 | static 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 | |||
15 | static 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 | |||
43 | int 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 | |||
4 | extern 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 */ | ||