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

📄 sc520.c.svn-base

📁 u-boot for S3c2443 processor
💻 SVN-BASE
字号:
/* * (C) Copyright 2002 * Daniel Engstr鰉, Omicron Ceti AB <daniel@omicron.se>. * * See file CREDITS for list of people who contributed to this * project. * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* stuff specific for the sc520, * but idependent of implementation */#include <config.h>#ifdef CONFIG_SC520#include <common.h>#include <config.h>#include <pci.h>#include <ssi.h>#include <asm/io.h>#include <asm/pci.h>#include <asm/ic/sc520.h>/* * utility functions for boards based on the AMD sc520 * * void write_mmcr_byte(u16 mmcr, u8 data) * void write_mmcr_word(u16 mmcr, u16 data) * void write_mmcr_long(u16 mmcr, u32 data) * * u8   read_mmcr_byte(u16 mmcr) * u16  read_mmcr_word(u16 mmcr) * u32  read_mmcr_long(u16 mmcr) * * void init_sc520(void) * unsigned long init_sc520_dram(void) * void pci_sc520_init(struct pci_controller *hose) * * void reset_timer(void) * ulong get_timer(ulong base) * void set_timer(ulong t) * void udelay(unsigned long usec) * */static u32 mmcr_base= 0xfffef000;void write_mmcr_byte(u16 mmcr, u8 data){	writeb(data, mmcr+mmcr_base);}void write_mmcr_word(u16 mmcr, u16 data){	writew(data, mmcr+mmcr_base);}void write_mmcr_long(u16 mmcr, u32 data){	writel(data, mmcr+mmcr_base);}u8 read_mmcr_byte(u16 mmcr){	return readb(mmcr+mmcr_base);}u16 read_mmcr_word(u16 mmcr){	return readw(mmcr+mmcr_base);}u32 read_mmcr_long(u16 mmcr){	return readl(mmcr+mmcr_base);}void init_sc520(void){	DECLARE_GLOBAL_DATA_PTR;	/* Set the UARTxCTL register at it's slower,	 * baud clock giving us a 1.8432 MHz reference	 */	write_mmcr_byte(SC520_UART1CTL, 7);	write_mmcr_byte(SC520_UART2CTL, 7);	/* first set the timer pin mapping */	write_mmcr_byte(SC520_CLKSEL, 0x72);	/* no clock frequency selected, use 1.1892MHz */	/* enable PCI bus arbitrer */	write_mmcr_byte(SC520_SYSARBCTL,0x02);  /* enable concurrent mode */	write_mmcr_word(SC520_SYSARBMENB,0x1f); /* enable external grants */	write_mmcr_word(SC520_HBCTL,0x04);      /* enable posted-writes */	if (CFG_SC520_HIGH_SPEED) {		write_mmcr_byte(SC520_CPUCTL, 0x2);	/* set it to 133 MHz and write back */		gd->cpu_clk = 133000000;		printf("## CPU Speed set to 133MHz\n");	} else {		write_mmcr_byte(SC520_CPUCTL, 1);	/* set CPU to 100 MHz and write back cache */		printf("## CPU Speed set to 100MHz\n");		gd->cpu_clk = 100000000;	}	/* wait at least one millisecond */	asm("movl	$0x2000,%%ecx\n"	    "wait_loop:	pushl %%ecx\n"	    "popl	%%ecx\n"	    "loop wait_loop\n": : : "ecx");	/* turn on the SDRAM write buffer */	write_mmcr_byte(SC520_DBCTL, 0x11);	/* turn on the cache and disable write through */	asm("movl	%%cr0, %%eax\n"	    "andl	$0x9fffffff, %%eax\n"	    "movl	%%eax, %%cr0\n"  : : : "eax");}unsigned long init_sc520_dram(void){	DECLARE_GLOBAL_DATA_PTR;	bd_t *bd = gd->bd;	u32 dram_present=0;	u32 dram_ctrl;	int val;	int cas_precharge_delay = CFG_SDRAM_PRECHARGE_DELAY;	int refresh_rate        = CFG_SDRAM_REFRESH_RATE;	int ras_cas_delay       = CFG_SDRAM_RAS_CAS_DELAY;	/* set SDRAM speed here */	refresh_rate/=78;	if (refresh_rate<=1) {		val = 0;  /* 7.8us */	} else if (refresh_rate==2) {		val = 1;  /* 15.6us */	} else if (refresh_rate==3 || refresh_rate==4) {		val = 2;  /* 31.2us */	} else {		val = 3;  /* 62.4us */	}	write_mmcr_byte(SC520_DRCCTL, (read_mmcr_byte(SC520_DRCCTL) & 0xcf) | (val<<4));	val = read_mmcr_byte(SC520_DRCTMCTL);	val &= 0xf0;	if (cas_precharge_delay==3) {		val |= 0x04;   /* 3T */	} else if (cas_precharge_delay==4) {		val |= 0x08;   /* 4T */	} else if (cas_precharge_delay>4) {		val |= 0x0c;	}	if (ras_cas_delay > 3) {		val |= 2;	} else {		val |= 1;	}	write_mmcr_byte(SC520_DRCTMCTL, val);	/* We read-back the configuration of the dram	 * controller that the assembly code wrote */	dram_ctrl = read_mmcr_long(SC520_DRCBENDADR);	bd->bi_dram[0].start = 0;	if (dram_ctrl & 0x80) {		/* bank 0 enabled */		dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;		bd->bi_dram[0].size = bd->bi_dram[1].start;	} else {		bd->bi_dram[0].size = 0;		bd->bi_dram[1].start = bd->bi_dram[0].start;	}	if (dram_ctrl & 0x8000) {		/* bank 1 enabled */		dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;		bd->bi_dram[1].size = bd->bi_dram[2].start -  bd->bi_dram[1].start;	} else {		bd->bi_dram[1].size = 0;		bd->bi_dram[2].start = bd->bi_dram[1].start;	}	if (dram_ctrl & 0x800000) {		/* bank 2 enabled */		dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;		bd->bi_dram[2].size = bd->bi_dram[3].start -  bd->bi_dram[2].start;	} else {		bd->bi_dram[2].size = 0;		bd->bi_dram[3].start = bd->bi_dram[2].start;	}	if (dram_ctrl & 0x80000000) {		/* bank 3 enabled */		dram_present  = (dram_ctrl & 0x7f000000) >> 2;		bd->bi_dram[3].size = dram_present -  bd->bi_dram[3].start;	} else {		bd->bi_dram[3].size = 0;	}#if 0	printf("Configured %d bytes of dram\n", dram_present);#endif	gd->ram_size = dram_present;	return dram_present;}#ifdef CONFIG_PCIstatic struct {	u8 priority;	u16 level_reg;	u8 level_bit;} sc520_irq[] = {	{ SC520_IRQ0,  SC520_MPICMODE,  0x01 },	{ SC520_IRQ1,  SC520_MPICMODE,  0x02 },	{ SC520_IRQ2,  SC520_SL1PICMODE, 0x02 },	{ SC520_IRQ3,  SC520_MPICMODE,  0x08 },	{ SC520_IRQ4,  SC520_MPICMODE,  0x10 },	{ SC520_IRQ5,  SC520_MPICMODE,  0x20 },	{ SC520_IRQ6,  SC520_MPICMODE,  0x40 },	{ SC520_IRQ7,  SC520_MPICMODE,  0x80 },	{ SC520_IRQ8,  SC520_SL1PICMODE, 0x01 },	{ SC520_IRQ9,  SC520_SL1PICMODE, 0x02 },	{ SC520_IRQ10, SC520_SL1PICMODE, 0x04 },	{ SC520_IRQ11, SC520_SL1PICMODE, 0x08 },	{ SC520_IRQ12, SC520_SL1PICMODE, 0x10 },	{ SC520_IRQ13, SC520_SL1PICMODE, 0x20 },	{ SC520_IRQ14, SC520_SL1PICMODE, 0x40 },	{ SC520_IRQ15, SC520_SL1PICMODE, 0x80 }};/* The interrupt used for PCI INTA-INTD  */int sc520_pci_ints[15] = {	-1, -1, -1, -1, -1, -1, -1, -1,		-1, -1, -1, -1, -1, -1, -1};/* utility function to configure a pci interrupt */int pci_sc520_set_irq(int pci_pin, int irq){	int i;# if 0	printf("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq);#endif	if (irq < 0 || irq > 15) {		return -1; /* illegal irq */	}	if (pci_pin < 0 || pci_pin > 15) {		return -1; /* illegal pci int pin */	}	/* first disable any non-pci interrupt source that use	 * this level */	for (i=SC520_GPTMR0MAP;i<=SC520_GP10IMAP;i++) {		if (i>=SC520_PCIINTAMAP&&i<=SC520_PCIINTDMAP) {			continue;		}		if (read_mmcr_byte(i) == sc520_irq[irq].priority) {			write_mmcr_byte(i, SC520_IRQ_DISABLED);		}	}	/* Set the trigger to level */	write_mmcr_byte(sc520_irq[irq].level_reg,			read_mmcr_byte(sc520_irq[irq].level_reg) | sc520_irq[irq].level_bit);	if (pci_pin < 4) {		/* PCI INTA-INTD */		/* route the interrupt */		write_mmcr_byte(SC520_PCIINTAMAP + pci_pin, sc520_irq[irq].priority);	} else {		/* GPIRQ0-GPIRQ10 used for additional PCI INTS */		write_mmcr_byte(SC520_GP0IMAP + pci_pin - 4, sc520_irq[irq].priority);		/* also set the polarity in this case */		write_mmcr_word(SC520_INTPINPOL,				read_mmcr_word(SC520_INTPINPOL) | (1 << (pci_pin-4)));	}	/* register the pin */	sc520_pci_ints[pci_pin] = irq;	return 0; /* OK */}void pci_sc520_init(struct pci_controller *hose){	hose->first_busno = 0;	hose->last_busno = 0xff;	/* System memory space */	pci_set_region(hose->regions + 0,		       SC520_PCI_MEMORY_BUS,		       SC520_PCI_MEMORY_PHYS,		       SC520_PCI_MEMORY_SIZE,		       PCI_REGION_MEM | PCI_REGION_MEMORY);	/* PCI memory space */	pci_set_region(hose->regions + 1,		       SC520_PCI_MEM_BUS,		       SC520_PCI_MEM_PHYS,		       SC520_PCI_MEM_SIZE,		       PCI_REGION_MEM);	/* ISA/PCI memory space */	pci_set_region(hose->regions + 2,		       SC520_ISA_MEM_BUS,		       SC520_ISA_MEM_PHYS,		       SC520_ISA_MEM_SIZE,		       PCI_REGION_MEM);	/* PCI I/O space */	pci_set_region(hose->regions + 3,		       SC520_PCI_IO_BUS,		       SC520_PCI_IO_PHYS,		       SC520_PCI_IO_SIZE,		       PCI_REGION_IO);	/* ISA/PCI I/O space */	pci_set_region(hose->regions + 4,		       SC520_ISA_IO_BUS,		       SC520_ISA_IO_PHYS,		       SC520_ISA_IO_SIZE,		       PCI_REGION_IO);	hose->region_count = 5;	pci_setup_type1(hose,			SC520_REG_ADDR,			SC520_REG_DATA);	pci_register_hose(hose);	hose->last_busno = pci_hose_scan(hose);	/* enable target memory acceses on host brige */	pci_write_config_word(0, PCI_COMMAND,			      PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);}#endif#ifdef CFG_TIMER_SC520void reset_timer(void){	write_mmcr_word(SC520_GPTMR0CNT, 0);	write_mmcr_word(SC520_GPTMR0CTL, 0x6001);}ulong get_timer(ulong base){	/* fixme: 30 or 33 */	return 	read_mmcr_word(SC520_GPTMR0CNT) / 33;}void set_timer(ulong t){	/* FixMe: use two cascade coupled timers */	write_mmcr_word(SC520_GPTMR0CTL, 0x4001);	write_mmcr_word(SC520_GPTMR0CNT, t*33);	write_mmcr_word(SC520_GPTMR0CTL, 0x6001);}void udelay(unsigned long usec){	int m=0;	long u;	read_mmcr_word(SC520_SWTMRMILLI);	read_mmcr_word(SC520_SWTMRMICRO);#if 0	/* do not enable this line, udelay is used in the serial driver -> recursion */	printf("udelay: %ld m.u %d.%d  tm.tu %d.%d\n", usec, m, u, tm, tu);#endif	while (1) {		m += read_mmcr_word(SC520_SWTMRMILLI);		u = read_mmcr_word(SC520_SWTMRMICRO) + (m * 1000);		if (usec <= u) {			break;		}	}}#endifint ssi_set_interface(int freq, int lsb_first, int inv_clock, int inv_phase){	u8 temp=0;	if (freq >= 8192) {		temp |= CTL_CLK_SEL_4;	} else if (freq >= 4096) {		temp |= CTL_CLK_SEL_8;	} else if (freq >= 2048) {		temp |= CTL_CLK_SEL_16;	} else if (freq >= 1024) {		temp |= CTL_CLK_SEL_32;	} else if (freq >= 512) {		temp |= CTL_CLK_SEL_64;	} else if (freq >= 256) {		temp |= CTL_CLK_SEL_128;	} else if (freq >= 128) {		temp |= CTL_CLK_SEL_256;	} else {		temp |= CTL_CLK_SEL_512;	}	if (!lsb_first) {		temp |= MSBF_ENB;	}	if (inv_clock) {		temp |= CLK_INV_ENB;	}	if (inv_phase) {		temp |= PHS_INV_ENB;	}	write_mmcr_byte(SC520_SSICTL, temp);	return 0;}u8 ssi_txrx_byte(u8 data){	write_mmcr_byte(SC520_SSIXMIT, data);	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMITRCV);	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);	return read_mmcr_byte(SC520_SSIRCV);}void ssi_tx_byte(u8 data){	write_mmcr_byte(SC520_SSIXMIT, data);	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_XMIT);}u8 ssi_rx_byte(void){	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);	write_mmcr_byte(SC520_SSICMD, SSICMD_CMD_SEL_RCV);	while ((read_mmcr_byte(SC520_SSISTA)) & SSISTA_BSY);	return read_mmcr_byte(SC520_SSIRCV);}#endif /* CONFIG_SC520 */

⌨️ 快捷键说明

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