⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tgt_machdep.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$Id: tgt_machdep.c,v 1.11 2003/08/10 10:52:11 pefo Exp $ *//* * Copyright (c) 2002 Momentum Computer  (www.momenco.com) * Copyright (c) 2001 Opsycon AB  (www.opsycon.se) *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include <sys/param.h>#include <sys/syslog.h>#include <machine/endian.h>#include <sys/device.h>#include <machine/cpu.h>#include <machine/pio.h>#include <machine/intr.h>#include <dev/pci/pcivar.h>#include <sys/types.h>#include <termio.h>#include <string.h>#include <time.h>#include <stdlib.h>#include <autoconf.h>#include <machine/cpu.h>#include <machine/pio.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include "include/ocelot_c.h"#include "include/fpga.h"#include <pmon/dev/mv64340reg.h>#include <pmon/dev/ns16550.h>#include "include/m48t37.h"#include <pmon.h>#include "flash.h"#if (NMOD_FLASH_AMD + NMOD_FLASH_INTEL) == 0#ifdef HAVE_FLASH#undef HAVE_FLASH#endif#else#define HAVE_FLASH#endif#define	TOD_REG(x) (clkbase + x)extern struct trapframe DBGREG;extern char _end[];extern void *memset __P((void *, int, size_t));static int md_pipefreq = 0;static int md_cpufreq = 0;static int clk_invalid = 0;static int nvram_invalid = 0;static int cksum __P((void *p, size_t s, int set));static void _probe_frequencies __P((void));ConfigEntry	ConfigTable[] ={	{ (char *)COM1_BASE_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ },	{ (char *)COM2_BASE_ADDR, 0, ns16550, 256, CONS_BAUD, NS16550HZ },	{ 0 }};unsigned long _filebase;extern char MipsException[], MipsExceptionEnd[];unsigned char hwethadr[6];void initmips __P((u_int32_t));voidinitmips(msize)	u_int32_t msize;{	u_int32_t totalSize;	totalSize = msize;SBD_DISPLAY ("MSIZ", CHKPNT_AUTO); 	/* Adjust PCI drive strength -- this should be automatic, but	 * for some reason the auto-cal doesn't work properly	 * We need to do this here to give the settings time to work.	 */	GT_WRITE(PCI0_PADS_CALIBRATION, 0x80000000);	GT_WRITE(PCI0_PADS_CALIBRATION, 0x00004444);	GT_WRITE(PCI1_PADS_CALIBRATION, 0x80000000);	GT_WRITE(PCI1_PADS_CALIBRATION, 0x00004444);	totalmemsize = totalSize;	/*	 *  Set up memory address decoders to map entire memory.	 *  But first move away bootrom map to high memory.	 */	GT_WRITE(BOOTCS_BASE_ADDRESS, BOOT_BASE >> 16);	GT_WRITE(BOOTCS_SIZE, (BOOT_SIZE - 1) >> 16);	/* re-program the SDRAM decoder */	GT_WRITE(SCS_0_SIZE, (msize - 1) >> 16);	/* re-program the On-Chip SRAM decoder */	GT_WRITE(INTERNAL_SRAM_BASE, OC_SRAM_BASE >> 16);	/*	 *  Probe clock frequencys so delays will work properly.	 */	tgt_cpufreq();	/*	 *  Init PMON and debug	 */	cpuinfotab[0] = &DBGREG;	dbginit(NULL);	/*	 *  Set up exception vectors.	 */	bcopy(MipsException, (char *)TLB_MISS_EXC_VEC, MipsExceptionEnd - MipsException);	bcopy(MipsException, (char *)GEN_EXC_VEC, MipsExceptionEnd - MipsException);	CPU_FlushCache(); 	CPU_SetSR(0, SR_BOOT_EXC_VEC);	/*	 *  Register initial memory map.	 */	register_mem((void *)0, (void *)totalmemsize-1, MEM_RAM, "SDRAM");	register_mem((void *)CACHED_TO_PHYS(memtop), kmemtop-1,		MEM_DATA, "Kernel data");	register_mem((void *)0, (void *)CACHED_TO_PHYS(_end)-1,		MEM_CODE, "PMON2000");	register_mem((void *)CACHED_TO_PHYS(_end),		(void *)CACHED_TO_PHYS(heaptop)-1, MEM_DATA, "PMON2000 heap");	register_mem((void *)FPGA_BASE, (void *)BOOT_BASE+BOOT_SIZE-1,		MEM_IO, "decoded space");	register_mem((void *)FPGA_BASE, (void *)FPGA_BASE+FPGA_SIZE-1,		MEM_IO, "fpga control");	register_mem((void *)RTC_BASE, (void *)RTC_BASE+RTC_SIZE-1,		MEM_IO, "RTC and NVRAM");	register_mem((void *)UART_BASE, (void *)UART_BASE+UART_SIZE-1,		MEM_IO, "NS16552");	register_mem((void *)FLASH_BASE, (void *)FLASH_BASE+FLASH_SIZE-1,		MEM_FLASH, "DiskOnChip");	register_mem((void *)OC_SRAM_BASE, (void *)OC_SRAM_BASE+OC_SRAM_SIZE-1,		MEM_RAM, "on chip SRAM");	register_mem((void *)GT_BASE_ADDR, (void *)GT_BASE_ADDR+65535,		MEM_FLASH, "internal registers");	register_mem((void *)0xffc00000, (void *)0xffc7ffff,		MEM_FLASH, "boot flash");	/*	 * Launch!	 */	pmon_main();}/* *  Put all machine dependent initialization here. This call *  is done after console has been initialized so it's safe *  to output configuration and debug information with printf. */voidtgt_devconfig(){	_pci_devinit(1);	/* PCI device initialization */	/* Set the PHY addresses for the GT ethernet */	GT_WRITE(ETH_PHY_ADDR_REG, 0x2841);	/* configure internal arbiter for PCI0 */	GT_WRITE(MPP_CONTROL2, 0x00000011);	GT_WRITE(PCI_0_ARBITER, 0x80000030);	/* Configure GPP for output and blank initial display */	/* Note: We set the "active low" bits, so write 1 to turn on */	GT_WRITE(GPP_IO_CONTROL, 0xff<<24);	GT_WRITE(GPP_LEVEL_CONTROL, 0xff<<24);	GT_WRITE(GPP_VALUE, 0x00<<24);        config_init();        configure();}/* functions to get the MAC address from the EEPROM */void burn_clocks(void);int exchange_bit(int val, int cs);void get_mac(char dest[6]);/* this function needs to burn at least 1us -- should be more than plenty */void burn_clocks(void){	int i;	for (i = 0; i < 0x10000; i++)		;}int exchange_bit(int val, int cs){        /* place the data */	out8(FPGAREG(EEPROM), (val << 2) | cs);        burn_clocks();        /* turn the clock on */	out8(FPGAREG(EEPROM), (val << 2) | cs | 0x2);        burn_clocks();        /* turn the clock off and read-strobe */	out8(FPGAREG(EEPROM), (val << 2) | cs | 0x10);        /* return the data */        return ((in8(FPGAREG(EEPROM)) >> 3) & 0x1);}void get_mac(char dest[6]){        int 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);}voidtgt_devinit(){	/*	 *  Gather info about and configure caches.	 */	if(getenv("ocache_off")) {		CpuOnboardCacheOn = 0;	}	else {		CpuOnboardCacheOn = 1;	}	if(getenv("ecache_off")) {		CpuExternalCacheOn = 0;	}	else {		CpuExternalCacheOn = 1;	}	if(getenv("termA")) {		/* disable SCSI A termination */		out8(FPGAREG(CLR_REG), 0x10);	}	else {		/* enable SCSI A termination */		out8(FPGAREG(SET_REG), 0x10);	}	if(getenv("termB")) {		/* disable SCSI B termination */		out8(FPGAREG(CLR_REG), 0x20);	}	else {		/* enable SCSI B termination */		out8(FPGAREG(SET_REG), 0x20);	}	/* Register Discovery area where PCI lives */        register_mem((void *)0xc0000000, (void *)0xffffffff, MEM_IO, "MV64340 I/O");#ifndef SR71000	CPU_ConfigCache();#else	CpuPrimaryInstCacheSize = 32 * 1024;	CpuPrimaryInstCacheLSize = 32;	CpuPrimaryInstSetSize = CpuPrimaryInstCacheSize / 16;	CpuPrimaryDataCacheSize = 32 * 1024;	CpuPrimaryDataCacheLSize = 32;	CpuPrimaryDataSetSize = CpuPrimaryDataCacheSize / 16;	CpuSecondaryCacheSize = 512 * 1024;	CpuNWayCache = 8;	/* cpu_id and CpuCacheAlignMask? */	/* CpuTertiaryCacheSize is set in start.S */	if (CpuTertiaryCacheSize != 0)		CpuCacheType = 0x4 | 0x0100 | 0x0400; /* has L3, 4-way, L3 */	else		CpuCacheType = 0x4 | 0x0100;	/* has L2, 4-way */#endif	_pci_businit(1);	/* PCI bus initialization */	/* enable ethernet decoders */	GT_WRITE(ETH_BAR_0, 0x00000e00);		/* DDR SDRAM */	GT_WRITE(ETH_SIZE_REG_0, (totalmemsize - 1) & 0xffff0000);	GT_WRITE(ETH_BAR_1, 0x00000002 | OC_SRAM_BASE);	/* On-Chip SRAM */	GT_WRITE(ETH_SIZE_REG_1, 0x0003 << 16);	/* enable windows 0 and 1 */	GT_WRITE(ETH_BASE_ADDR_ENABLE_REG, 0x3c);	/* Load the MAC address from the EEPROM.	 * It is also in the NVRAM, and that copy can be gotten to with:	 * memcpy(hwethadr, (void *)NVRAM_ENETADDR, 6);	 */	get_mac(hwethadr);}voidtgt_reboot(){	void (*longreach) __P((void));	int i;	/* Reset reset cause */	out8(FPGAREG(RESET_STAT), in8(FPGAREG(RESET_STAT)));	/* Enable watchdog one tick at 1/16th second */	out8(M48T37_BASE+7, 0x84);	/* Then wait... */	for(i = 0; i < 200000000; i++);	/* Unreliable but try this if watchdog fails... */	printf("Watchdog reboot failed!\n");	longreach = (void *)0xbfc00000;	(*longreach)();	while(1);}/* *  This function makes inital HW setup for debugger and *  returns the apropriate setting for the status register. */register_ttgt_enable(int machtype){	/* XXX Do any HW specific setup */	return(SR_COP_1_BIT|SR_FR_32|SR_EXL);}/* *  Target dependent version printout. *  Printout available target version information. */voidtgt_cmd_vers(){	printf("Board revision level: %c.\n", in8(FPGAREG(REVISION)) + 'A');	printf("FPGA revision level: %d.%d.\n",		in8(FPGAREG(FPGA_REV)) >> 4, in8(FPGAREG(FPGA_REV)) & 15);}/* *  Display any target specific logo. */#if defined(HAVE_LOGO)voidtgt_logo(){}#endifstatic void_probe_frequencies(){#ifdef HAVE_TOD	int i, timeout, cur, sec, cnt;        int clkbase = M48T37_BASE;#endif	SBD_DISPLAY ("FREQ", CHKPNT_FREQ);	md_pipefreq = 300000000;	/* Defaults */	md_cpufreq  = 100000000;	clk_invalid = 1;#ifdef HAVE_TOD	/*	 *  Check if clock is stopped and start it if it is.	 */	if(inb(TOD_REG(TOD_SECOND)) & TOD_SECOND_ST) {		outb(TOD_REG(TOD_SECOND), inb(TOD_REG(TOD_SECOND)) & ~TOD_SECOND_ST);	}	else {		clk_invalid = 0;	}	/*	 * Do the next twice for two reasons. First make sure we run from	 * cache. Second make sure synched on second update. (Pun intended!)	 */	for(i = 2;  i != 0; i--) {		cnt = CPU_GetCOUNT();		timeout = 100000000;		/* stop update */		outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) | TOD_CTRL_R);		sec = inb(TOD_REG(TOD_SECOND)) & 0x0f; 		/* start update */		outb(TOD_REG(TOD_CTRL), inb(TOD_REG(TOD_CTRL)) & ~TOD_CTRL_R);		/* Loop for one sec, and see how many ticks we get.		 * Time out after (timeout) times through the loop.		 */		do {			timeout--;			/* stop update */			outb(TOD_REG(TOD_CTRL),				inb(TOD_REG(TOD_CTRL)) | TOD_CTRL_R);			cur = inb(TOD_REG(TOD_SECOND)) & 0x0f; 				/* start update */			outb(TOD_REG(TOD_CTRL),				inb(TOD_REG(TOD_CTRL)) & ~TOD_CTRL_R);		} while(timeout != 0 && cur == sec);		cnt = CPU_GetCOUNT() - cnt;		if(timeout == 0) {			clk_invalid = 1;			return;		/* Get out if clock is not running */		}	}	/*	 *  Calculate the external bus clock frequency.	 *  Here we calculate the CPU frequency based on the pipeline time.	 *  Yes, md_pipefreq is really the CPU speed.	 */	md_pipefreq = (cnt  + 5999)/ 10000;	md_pipefreq *= 20000;	/*	 *  Calculate the external frequency.	 *  md_cpufreq is actually SysClk, not core frequency	 */#ifdef SR71000	md_cpufreq = md_pipefreq;	md_pipefreq /= 2;	i =  (CPU_GetCONFIG() >> 23) & 1;		/* Halfclock bit */	md_cpufreq /= ( (((CPU_GetCONFIG() >> 20) & 7) + 2) * 2) + i;#else	i =  2 - ((CPU_GetCONFIG() >> 16) & 1);		/* Halfclock bit */	md_cpufreq = md_pipefreq * 2;	md_cpufreq /= (((CPU_GetCONFIG() >> 28) & 7) + 2) * i;#endif#endif /* HAVE_TOD */}/* *   Returns the CPU pipelie clock frequency */inttgt_pipefreq(){	if(md_pipefreq == 0) {		_probe_frequencies();	}	return(md_pipefreq);}/* *   Returns the external clock frequency, usually the bus clock */inttgt_cpufreq(){	if(md_cpufreq == 0) {		_probe_frequencies();	}	return(md_cpufreq);}#ifdef HAVE_TOD/* *  Returns the current time if a TOD clock is present or 0 *  This code is defunct after 2088... (out of bits) */#define FROMBCD(x)      (((x) >> 4) * 10 + ((x) & 0xf))#define TOBCD(x)        (((x) / 10 * 16) + ((x) % 10)) #define YEARDAYS(year)  ((((year) % 4) == 0 && \                         ((year % 100) != 0 || (year % 400) == 0)) ? 366 : 365)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -