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