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