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