| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2 | * Maintainer: Tom Rini <trini@kernel.crashing.org> | 
|  | 3 | * | 
|  | 4 | * In the past: Gary Thomas, Cort Dougan <cort@cs.nmt.edu> | 
|  | 5 | */ | 
|  | 6 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7 | #include <linux/pci_ids.h> | 
|  | 8 | #include <linux/types.h> | 
|  | 9 | #include <asm/residual.h> | 
|  | 10 | #include <asm/string.h> | 
|  | 11 | #include <asm/byteorder.h> | 
|  | 12 | #include "mpc10x.h" | 
|  | 13 | #include "of1275.h" | 
|  | 14 | #include "nonstdio.h" | 
|  | 15 |  | 
|  | 16 | extern int keyb_present;	/* keyboard controller is present by default */ | 
|  | 17 | RESIDUAL hold_resid_buf; | 
|  | 18 | RESIDUAL *hold_residual = &hold_resid_buf; | 
|  | 19 | static void *OFW_interface;	/* Pointer to OF, if available. */ | 
|  | 20 |  | 
|  | 21 | #ifdef CONFIG_VGA_CONSOLE | 
|  | 22 | char *vidmem = (char *)0xC00B8000; | 
|  | 23 | int lines = 25, cols = 80; | 
|  | 24 | int orig_x, orig_y = 24; | 
|  | 25 | #endif /* CONFIG_VGA_CONSOLE */ | 
|  | 26 |  | 
|  | 27 | extern int CRT_tstc(void); | 
|  | 28 | extern int vga_init(unsigned char *ISA_mem); | 
|  | 29 | extern void gunzip(void *, int, unsigned char *, int *); | 
|  | 30 | extern unsigned long serial_init(int chan, void *ignored); | 
|  | 31 | extern void serial_fixups(void); | 
|  | 32 | extern struct bi_record *decompress_kernel(unsigned long load_addr, | 
|  | 33 | int num_words, unsigned long cksum); | 
|  | 34 | extern void disable_6xx_mmu(void); | 
|  | 35 | extern unsigned long mpc10x_get_mem_size(void); | 
|  | 36 |  | 
|  | 37 | static void | 
|  | 38 | writel(unsigned int val, unsigned int address) | 
|  | 39 | { | 
|  | 40 | /* Ensure I/O operations complete */ | 
|  | 41 | __asm__ volatile("eieio"); | 
|  | 42 | *(unsigned int *)address = cpu_to_le32(val); | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | #define PCI_CFG_ADDR(dev,off)	((0x80<<24) | (dev<<8) | (off&0xfc)) | 
|  | 46 | #define PCI_CFG_DATA(off)	(MPC10X_MAPA_CNFG_DATA+(off&3)) | 
|  | 47 |  | 
|  | 48 | static void | 
|  | 49 | pci_read_config_32(unsigned char devfn, | 
|  | 50 | unsigned char offset, | 
|  | 51 | unsigned int *val) | 
|  | 52 | { | 
|  | 53 | /* Ensure I/O operations complete */ | 
|  | 54 | __asm__ volatile("eieio"); | 
|  | 55 | *(unsigned int *)PCI_CFG_ADDR(devfn,offset) = | 
|  | 56 | cpu_to_le32(MPC10X_MAPA_CNFG_ADDR); | 
|  | 57 | /* Ensure I/O operations complete */ | 
|  | 58 | __asm__ volatile("eieio"); | 
|  | 59 | *val = le32_to_cpu(*(unsigned int *)PCI_CFG_DATA(offset)); | 
|  | 60 | return; | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | #ifdef CONFIG_VGA_CONSOLE | 
|  | 64 | void | 
|  | 65 | scroll(void) | 
|  | 66 | { | 
|  | 67 | int i; | 
|  | 68 |  | 
|  | 69 | memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); | 
|  | 70 | for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) | 
|  | 71 | vidmem[i] = ' '; | 
|  | 72 | } | 
|  | 73 | #endif /* CONFIG_VGA_CONSOLE */ | 
|  | 74 |  | 
|  | 75 | unsigned long | 
|  | 76 | load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, | 
|  | 77 | RESIDUAL *residual, void *OFW) | 
|  | 78 | { | 
|  | 79 | int start_multi = 0; | 
|  | 80 | unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; | 
|  | 81 |  | 
|  | 82 | /* If we have Open Firmware, initialise it immediately */ | 
|  | 83 | if (OFW) { | 
|  | 84 | OFW_interface = OFW; | 
|  | 85 | ofinit(OFW_interface); | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | board_isa_init(); | 
|  | 89 | #if defined(CONFIG_VGA_CONSOLE) | 
|  | 90 | vga_init((unsigned char *)0xC0000000); | 
|  | 91 | #endif /* CONFIG_VGA_CONSOLE */ | 
|  | 92 |  | 
|  | 93 | if (residual) { | 
|  | 94 | /* Is this Motorola PPCBug? */ | 
|  | 95 | if ((1 & residual->VitalProductData.FirmwareSupports) && | 
|  | 96 | (1 == residual->VitalProductData.FirmwareSupplier)) { | 
|  | 97 | unsigned char base_mod; | 
|  | 98 | unsigned char board_type = inb(0x801) & 0xF0; | 
|  | 99 |  | 
|  | 100 | /* | 
|  | 101 | * Reset the onboard 21x4x Ethernet | 
|  | 102 | * Motorola Ethernet is at IDSEL 14 (devfn 0x70) | 
|  | 103 | */ | 
|  | 104 | pci_read_config_32(0x70, 0x00, &pci_viddid); | 
|  | 105 | pci_did = (pci_viddid & 0xffff0000) >> 16; | 
|  | 106 | /* Be sure we've really found a 21x4x chip */ | 
|  | 107 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) && | 
|  | 108 | ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) || | 
|  | 109 | (pci_did == PCI_DEVICE_ID_DEC_TULIP) || | 
|  | 110 | (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) || | 
|  | 111 | (pci_did == PCI_DEVICE_ID_DEC_21142))) { | 
|  | 112 | pci_read_config_32(0x70, | 
|  | 113 | 0x10, | 
|  | 114 | &tulip_pci_base); | 
|  | 115 | /* Get the physical base address */ | 
|  | 116 | tulip_base = | 
|  | 117 | (tulip_pci_base & ~0x03UL) + 0x80000000; | 
|  | 118 | /* Strobe the 21x4x reset bit in CSR0 */ | 
|  | 119 | writel(0x1, tulip_base); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | /* If this is genesis 2 board then check for no | 
|  | 123 | * keyboard controller and more than one processor. | 
|  | 124 | */ | 
|  | 125 | if (board_type == 0xe0) { | 
|  | 126 | base_mod = inb(0x803); | 
|  | 127 | /* if a MVME2300/2400 or a Sitka then no keyboard */ | 
|  | 128 | if((base_mod == 0xFA) || (base_mod == 0xF9) || | 
|  | 129 | (base_mod == 0xE1)) { | 
|  | 130 | keyb_present = 0;	/* no keyboard */ | 
|  | 131 | } | 
|  | 132 | } | 
|  | 133 | /* If this is a multiprocessor system then | 
|  | 134 | * park the other processor so that the | 
|  | 135 | * kernel knows where to find them. | 
|  | 136 | */ | 
|  | 137 | if (residual->MaxNumCpus > 1) | 
|  | 138 | start_multi = 1; | 
|  | 139 | } | 
|  | 140 | memcpy(hold_residual,residual,sizeof(RESIDUAL)); | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | /* Call decompress_kernel */ | 
|  | 144 | decompress_kernel(load_addr, num_words, cksum); | 
|  | 145 |  | 
|  | 146 | if (start_multi) { | 
|  | 147 | residual->VitalProductData.SmpIar = (unsigned long)0xc0; | 
|  | 148 | residual->Cpus[1].CpuState = CPU_GOOD; | 
|  | 149 | hold_residual->VitalProductData.Reserved5 = 0xdeadbeef; | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | /* Now go and clear out the BATs and ensure that our MSR is | 
|  | 153 | * correct .*/ | 
|  | 154 | disable_6xx_mmu(); | 
|  | 155 |  | 
|  | 156 | /* Make r3 be a pointer to the residual data. */ | 
|  | 157 | return (unsigned long)hold_residual; | 
|  | 158 | } | 
|  | 159 |  | 
|  | 160 | unsigned long | 
|  | 161 | get_mem_size(void) | 
|  | 162 | { | 
|  | 163 | unsigned int pci_viddid, pci_did; | 
|  | 164 |  | 
|  | 165 | /* First, figure out what kind of host bridge we are on.  If it's | 
|  | 166 | * an MPC10x, we can ask it directly how much memory it has. | 
|  | 167 | * Otherwise, see if the residual data has anything.  This isn't | 
|  | 168 | * the best way, but it can be the only way.  If there's nothing, | 
|  | 169 | * assume 32MB. -- Tom. | 
|  | 170 | */ | 
|  | 171 | /* See what our host bridge is. */ | 
|  | 172 | pci_read_config_32(0x00, 0x00, &pci_viddid); | 
|  | 173 | pci_did = (pci_viddid & 0xffff0000) >> 16; | 
|  | 174 | /* See if we are on an MPC10x. */ | 
|  | 175 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA) | 
|  | 176 | && ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105) | 
|  | 177 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106) | 
|  | 178 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107))) | 
|  | 179 | return mpc10x_get_mem_size(); | 
|  | 180 | /* If it's not, see if we have anything in the residual data. */ | 
|  | 181 | else if (hold_residual && hold_residual->TotalMemory) | 
|  | 182 | return hold_residual->TotalMemory; | 
|  | 183 | else if (OFW_interface) { | 
|  | 184 | /* | 
|  | 185 | * This is a 'best guess' check.  We want to make sure | 
|  | 186 | * we don't try this on a PReP box without OF | 
|  | 187 | *     -- Cort | 
|  | 188 | */ | 
|  | 189 | while (OFW_interface) | 
|  | 190 | { | 
|  | 191 | phandle dev_handle; | 
|  | 192 | int mem_info[2]; | 
|  | 193 |  | 
|  | 194 | /* get handle to memory description */ | 
|  | 195 | if (!(dev_handle = finddevice("/memory@0"))) | 
|  | 196 | break; | 
|  | 197 |  | 
|  | 198 | /* get the info */ | 
|  | 199 | if (getprop(dev_handle, "reg", mem_info, | 
|  | 200 | sizeof(mem_info)) != 8) | 
|  | 201 | break; | 
|  | 202 |  | 
|  | 203 | return mem_info[1]; | 
|  | 204 | } | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | /* Fall back to hard-coding 32MB. */ | 
|  | 208 | return 32*1024*1024; | 
|  | 209 | } |