diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_psycho.c')
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 65 |
1 files changed, 7 insertions, 58 deletions
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); |