aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/psycho_common.c
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 /arch/sparc64/kernel/psycho_common.c
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>
Diffstat (limited to 'arch/sparc64/kernel/psycho_common.c')
-rw-r--r--arch/sparc64/kernel/psycho_common.c93
1 files changed, 93 insertions, 0 deletions
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}