File: /usr/src/linux/arch/mips/sgi/kernel/indy_mc.c
1 /*
2 * indy_mc.c: Routines for manipulating the INDY memory controller.
3 *
4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
5 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes
6 *
7 * $Id: indy_mc.c,v 1.7 1999/12/04 03:59:00 ralf Exp $
8 */
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11
12 #include <asm/addrspace.h>
13 #include <asm/ptrace.h>
14 #include <asm/sgi/sgimc.h>
15 #include <asm/sgi/sgihpc.h>
16 #include <asm/sgialib.h>
17
18 /* #define DEBUG_SGIMC */
19
20 struct sgimc_misc_ctrl *mcmisc_regs;
21 u32 *rpsscounter;
22 struct sgimc_dma_ctrl *dmactrlregs;
23
24 static inline char *mconfig_string(unsigned long val)
25 {
26 switch(val & SGIMC_MCONFIG_RMASK) {
27 case SGIMC_MCONFIG_FOURMB:
28 return "4MB";
29
30 case SGIMC_MCONFIG_EIGHTMB:
31 return "8MB";
32
33 case SGIMC_MCONFIG_SXTEENMB:
34 return "16MB";
35
36 case SGIMC_MCONFIG_TTWOMB:
37 return "32MB";
38
39 case SGIMC_MCONFIG_SFOURMB:
40 return "64MB";
41
42 case SGIMC_MCONFIG_OTEIGHTMB:
43 return "128MB";
44
45 default:
46 return "wheee, unknown";
47 };
48 }
49
50 void __init sgimc_init(void)
51 {
52 unsigned long tmpreg;
53
54 mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000);
55 rpsscounter = (unsigned int *) (KSEG1 + 0x1fa01004);
56 dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000);
57
58 printk("MC: SGI memory controller Revision %d\n",
59 (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV);
60
61 #if 0 /* XXX Until I figure out what this bit really indicates XXX */
62 /* XXX Is this systemid bit reliable? */
63 if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) {
64 EISA_bus = 1;
65 printk("with EISA\n");
66 } else {
67 EISA_bus = 0;
68 printk("no EISA\n");
69 }
70 #endif
71
72 #ifdef DEBUG_SGIMC
73 prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n",
74 mconfig_string(mcmisc_regs->mconfig0),
75 mconfig_string(mcmisc_regs->mconfig1));
76
77 prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n",
78 mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1);
79 prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n",
80 mcmisc_regs->divider, mcmisc_regs->gioparm);
81 #endif
82
83 /* Place the MC into a known state. This must be done before
84 * interrupts are first enabled etc.
85 */
86
87 /* Step 1: The CPU/GIO error status registers will not latch
88 * up a new error status until the register has been
89 * cleared by the cpu. These status registers are
90 * cleared by writing any value to them.
91 */
92 mcmisc_regs->cstat = mcmisc_regs->gstat = 0;
93
94 /* Step 2: Enable all parity checking in cpu control register
95 * zero.
96 */
97 tmpreg = mcmisc_regs->cpuctrl0;
98 tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM |
99 SGIMC_CCTRL0_R4KNOCHKPARR);
100 mcmisc_regs->cpuctrl0 = tmpreg;
101
102 /* Step 3: Setup the MC write buffer depth, this is controlled
103 * in cpu control register 1 in the lower 4 bits.
104 */
105 tmpreg = mcmisc_regs->cpuctrl1;
106 tmpreg &= ~0xf;
107 tmpreg |= 0xd;
108 mcmisc_regs->cpuctrl1 = tmpreg;
109
110 /* Step 4: Initialize the RPSS divider register to run as fast
111 * as it can correctly operate. The register is laid
112 * out as follows:
113 *
114 * ----------------------------------------
115 * | RESERVED | INCREMENT | DIVIDER |
116 * ----------------------------------------
117 * 31 16 15 8 7 0
118 *
119 * DIVIDER determines how often a 'tick' happens,
120 * INCREMENT determines by how the RPSS increment
121 * registers value increases at each 'tick'. Thus,
122 * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101
123 */
124 mcmisc_regs->divider = 0x101;
125
126 /* Step 5: Initialize GIO64 arbitrator configuration register.
127 *
128 * NOTE: If you dork with startup code the HPC init code in
129 * sgihpc_init() must run before us because of how we
130 * need to know Guiness vs. FullHouse and the board
131 * revision on this machine. You have been warned.
132 */
133
134 /* First the basic invariants across all gio64 implementations. */
135 tmpreg = SGIMC_GIOPARM_HPC64; /* All 1st HPC's interface at 64bits. */
136 tmpreg |= SGIMC_GIOPARM_ONEBUS; /* Only one physical GIO bus exists. */
137
138 if(sgi_guiness) {
139 /* Guiness specific settings. */
140 tmpreg |= SGIMC_GIOPARM_EISA64; /* MC talks to EISA at 64bits */
141 tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */
142 } else {
143 /* Fullhouse specific settings. */
144 if(sgi_boardid < 2) {
145 tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */
146 tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */
147 tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */
148 tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */
149 } else {
150 tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */
151 tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */
152 tmpreg |= SGIMC_GIOPARM_PLINEEXP1;
153 tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */
154 /* someone forgot this poor little guy... */
155 tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */
156 }
157 }
158 mcmisc_regs->gioparm = tmpreg; /* poof */
159 }
160