| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright 2002 Momentum Computer Inc. | 
					
						
							|  |  |  |  * Author: Matthew Dharm <mdharm@momenco.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Louis Hamilton, Red Hat, Inc. | 
					
						
							|  |  |  |  *   hamilton@redhat.com  [MIPS64 modifications] | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2004 PMC-Sierra | 
					
						
							|  |  |  |  * Author: Manish Lachwani (lachwani@pmc-sierra.com) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Based on Ocelot Linux port, which is | 
					
						
							|  |  |  |  * Copyright 2001 MontaVista Software Inc. | 
					
						
							|  |  |  |  * Author: jsun@mvista.com or jsun@junsun.net | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute  it and/or modify it | 
					
						
							|  |  |  |  * under  the terms of  the GNU General  Public License as published by the | 
					
						
							|  |  |  |  * Free Software Foundation;  either version 2 of the  License, or (at your | 
					
						
							|  |  |  |  * option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2004 MontaVista Software Inc. | 
					
						
							|  |  |  |  * Author: Manish Lachwani, mlachwani@mvista.com | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #include <linux/config.h>
 | 
					
						
							|  |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/bootmem.h>
 | 
					
						
							|  |  |  | #include <linux/mv643xx.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <asm/addrspace.h>
 | 
					
						
							|  |  |  | #include <asm/bootinfo.h>
 | 
					
						
							|  |  |  | #include <asm/pmon.h>
 | 
					
						
							|  |  |  | #include "ocelot_3_fpga.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct callvectors* debug_vectors; | 
					
						
							|  |  |  | extern unsigned long marvell_base; | 
					
						
							|  |  |  | extern unsigned long cpu_clock; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_MV643XX_ETH
 | 
					
						
							|  |  |  | extern unsigned char prom_mac_addr_base[6]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char *get_system_type(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return "Momentum Ocelot-3"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_MV643XX_ETH
 | 
					
						
							|  |  |  | void burn_clocks(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* this loop should burn at least 1us -- this should be plenty */ | 
					
						
							|  |  |  | 	for (i = 0; i < 0x10000; i++) | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u8 exchange_bit(u8 val, u8 cs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* place the data */ | 
					
						
							|  |  |  | 	OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); | 
					
						
							|  |  |  | 	burn_clocks(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* turn the clock on */ | 
					
						
							|  |  |  | 	OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); | 
					
						
							|  |  |  | 	burn_clocks(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* turn the clock off and read-strobe */ | 
					
						
							|  |  |  | 	OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* return the data */ | 
					
						
							|  |  |  | 	return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void get_mac(char dest[6]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 
					
						
							|  |  |  | 	int i,j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < 12; i++) | 
					
						
							|  |  |  | 		exchange_bit(read_opcode[i], 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (j = 0; j < 6; j++) { | 
					
						
							|  |  |  | 		dest[j] = 0; | 
					
						
							|  |  |  | 		for (i = 0; i < 8; i++) { | 
					
						
							|  |  |  | 			dest[j] <<= 1; | 
					
						
							|  |  |  | 			dest[j] |= exchange_bit(0, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* turn off CS */ | 
					
						
							|  |  |  | 	exchange_bit(0,0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #ifdef CONFIG_64BIT
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | unsigned long signext(unsigned long addr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	addr &= 0xffffffff; | 
					
						
							|  |  |  | 	return (unsigned long)((int)addr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void *get_arg(unsigned long args, int arc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long ul; | 
					
						
							|  |  |  | 	unsigned char *puc, uc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	args += (arc * 4); | 
					
						
							|  |  |  | 	ul = (unsigned long)signext(args); | 
					
						
							|  |  |  | 	puc = (unsigned char *)ul; | 
					
						
							|  |  |  | 	if (puc == 0) | 
					
						
							|  |  |  | 		return (void *)0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_CPU_LITTLE_ENDIAN
 | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul = (unsigned long)uc; | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= (((unsigned long)uc) << 8); | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= (((unsigned long)uc) << 16); | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= (((unsigned long)uc) << 24); | 
					
						
							|  |  |  | #else  /* CONFIG_CPU_LITTLE_ENDIAN */
 | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul = ((unsigned long)uc) << 24; | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= (((unsigned long)uc) << 16); | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= (((unsigned long)uc) << 8); | 
					
						
							|  |  |  | 	uc = *puc++; | 
					
						
							|  |  |  | 	ul |= ((unsigned long)uc); | 
					
						
							|  |  |  | #endif  /* CONFIG_CPU_LITTLE_ENDIAN */
 | 
					
						
							|  |  |  | 	ul = signext(ul); | 
					
						
							|  |  |  | 	return (void *)ul; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | char *arg64(unsigned long addrin, int arg_index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned long args; | 
					
						
							|  |  |  | 	char *p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	args = signext(addrin); | 
					
						
							|  |  |  | 	p = (char *)get_arg(args, arg_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #endif  /* CONFIG_64BIT */
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | void __init prom_init(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int argc = fw_arg0; | 
					
						
							|  |  |  | 	char **arg = (char **) fw_arg1; | 
					
						
							|  |  |  | 	char **env = (char **) fw_arg2; | 
					
						
							|  |  |  | 	struct callvectors *cv = (struct callvectors *) fw_arg3; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #ifdef CONFIG_64BIT
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	char *ptr; | 
					
						
							|  |  |  | 	printk("prom_init - MIPS64\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* save the PROM vectors for debugging use */ | 
					
						
							|  |  |  | 	debug_vectors = (struct callvectors *)signext((unsigned long)cv); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* arg[0] is "g", the rest is boot parameters */ | 
					
						
							|  |  |  | 	arcs_cmdline[0] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 1; i < argc; i++) { | 
					
						
							|  |  |  | 		ptr = (char *)arg64((unsigned long)arg, i); | 
					
						
							|  |  |  | 		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >= | 
					
						
							|  |  |  | 		    sizeof(arcs_cmdline)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		strcat(arcs_cmdline, ptr); | 
					
						
							|  |  |  | 		strcat(arcs_cmdline, " "); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (1) { | 
					
						
							|  |  |  | 		ptr = (char *)arg64((unsigned long)env, i); | 
					
						
							|  |  |  | 		if (! ptr) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) { | 
					
						
							|  |  |  | 			marvell_base = simple_strtol(ptr + strlen("gtbase="), | 
					
						
							|  |  |  | 							NULL, 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if ((marvell_base & 0xffffffff00000000) == 0) | 
					
						
							|  |  |  | 				marvell_base |= 0xffffffff00000000; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			printk("marvell_base set to 0x%016lx\n", marvell_base); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) { | 
					
						
							|  |  |  | 			cpu_clock = simple_strtol(ptr + strlen("cpuclock="), | 
					
						
							|  |  |  | 							NULL, 10); | 
					
						
							|  |  |  | 			printk("cpu_clock set to %d\n", cpu_clock); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	printk("arcs_cmdline: %s\n", arcs_cmdline); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #else   /* CONFIG_64BIT */
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* save the PROM vectors for debugging use */ | 
					
						
							|  |  |  | 	debug_vectors = cv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* arg[0] is "g", the rest is boot parameters */ | 
					
						
							|  |  |  | 	arcs_cmdline[0] = '\0'; | 
					
						
							|  |  |  | 	for (i = 1; i < argc; i++) { | 
					
						
							|  |  |  | 		if (strlen(arcs_cmdline) + strlen(arg[i] + 1) | 
					
						
							|  |  |  | 		    >= sizeof(arcs_cmdline)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		strcat(arcs_cmdline, arg[i]); | 
					
						
							|  |  |  | 		strcat(arcs_cmdline, " "); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (*env) { | 
					
						
							|  |  |  | 		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { | 
					
						
							|  |  |  | 			marvell_base = simple_strtol(*env + strlen("gtbase="), | 
					
						
							|  |  |  | 							NULL, 16); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) { | 
					
						
							|  |  |  | 			cpu_clock = simple_strtol(*env + strlen("cpuclock="), | 
					
						
							|  |  |  | 							NULL, 10); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		env++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #endif /* CONFIG_64BIT */
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mips_machgroup = MACH_GROUP_MOMENCO; | 
					
						
							|  |  |  | 	mips_machtype = MACH_MOMENCO_OCELOT_3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef CONFIG_MV643XX_ETH
 | 
					
						
							|  |  |  | 	/* get the base MAC address for on-board ethernet ports */ | 
					
						
							|  |  |  | 	get_mac(prom_mac_addr_base); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-03 15:56:16 -07:00
										 |  |  | #ifndef CONFIG_64BIT
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	debug_vectors->printf("Booting Linux kernel...\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-28 00:42:56 -04:00
										 |  |  | unsigned long __init prom_free_prom_memory(void) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-28 00:42:56 -04:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __init prom_fixup_mem_map(unsigned long start, unsigned long end) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } |