aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-09-10 06:07:03 -0400
committerDavid S. Miller <davem@davemloft.net>2008-09-11 02:11:56 -0400
commita21cff3e5e39c087b5a4c5efb20f1744475c556e (patch)
tree1438e43c4d7b2d4042f074afc887fe2e7c30e7ad
parent22fecbae4446ad470b9237ee9b79f80f343b3838 (diff)
sparc64: Start commonizing code common between SABRE and PSYCHO.
These are very similar chips, in fact they are identical in some macro blocks. So start commonizing code which they can share. We begin with the IOMMU initialization sequence. Signed-off-by: David S. Miller <davem@davemloft.net>
-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 */