sbc8548.c 14.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright 2007 Wind River Systemes, Inc. <www.windriver.com>
 * Copyright 2007 Embedded Specialties, Inc.
 *
 * Copyright 2004, 2007 Freescale Semiconductor.
 *
 * (C) Copyright 2002 Scott McNutt <smcnutt@artesyncp.com>
 *
 * 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
 */

#include <common.h>
#include <pci.h>
#include <asm/processor.h>
#include <asm/immap_85xx.h>
#include <asm/immap_fsl_pci.h>
33
#include <asm/fsl_ddr_sdram.h>
34
#include <spd_sdram.h>
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
#include <miiphy.h>
#include <libfdt.h>
#include <fdt_support.h>

#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
extern void ddr_enable_ecc(unsigned int dram_size);
#endif

DECLARE_GLOBAL_DATA_PTR;

void local_bus_init(void);
void sdram_init(void);
long int fixed_sdram (void);

int board_early_init_f (void)
{
	return 0;
}

int checkboard (void)
{
56 57 58
	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
	volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
	volatile u_char *rev= (void *)CONFIG_SYS_BD_REV;
59 60

	printf ("Board: Wind River SBC8548 Rev. 0x%01x\n",
61
			(*rev) >> 4);
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

	/*
	 * Initialize local bus.
	 */
	local_bus_init ();

	/*
	 * Fix CPU2 errata: A core hang possible while executing a
	 * msync instruction and a snoopable transaction from an I/O
	 * master tagged to make quick forward progress is present.
	 */
	ecm->eebpcr |= (1 << 16);

	/*
	 * Hack TSEC 3 and 4 IO voltages.
	 */
	gur->tsec34ioovcr = 0xe7e0;	/*  1110 0111 1110 0xxx */

	ecm->eedr = 0xffffffff;		/* clear ecm errors */
	ecm->eeer = 0xffffffff;		/* enable ecm errors */
	return 0;
}

85
phys_size_t
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
initdram(int board_type)
{
	long dram_size = 0;

	puts("Initializing\n");

#if defined(CONFIG_DDR_DLL)
	{
		/*
		 * Work around to stabilize DDR DLL MSYNC_IN.
		 * Errata DDR9 seems to have been fixed.
		 * This is now the workaround for Errata DDR11:
		 *    Override DLL = 1, Course Adj = 1, Tap Select = 0
		 */

101
		volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
102 103 104 105 106 107 108 109

		gur->ddrdllcr = 0x81000000;
		asm("sync;isync;msync");
		udelay(200);
	}
#endif

#if defined(CONFIG_SPD_EEPROM)
110 111 112
	dram_size = fsl_ddr_sdram();
	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
	dram_size *= 0x100000;
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
#else
	dram_size = fixed_sdram ();
#endif

#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
	/*
	 * Initialize and enable DDR ECC.
	 */
	ddr_enable_ecc(dram_size);
#endif
	/*
	 * SDRAM Initialization
	 */
	sdram_init();

	puts("    DDR: ");
	return dram_size;
}

/*
 * Initialize Local Bus
 */
void
local_bus_init(void)
{
138 139
	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
	volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

	uint clkdiv;
	uint lbc_hz;
	sys_info_t sysinfo;

	get_sys_info(&sysinfo);
	clkdiv = (lbc->lcrr & 0x0f) * 2;
	lbc_hz = sysinfo.freqSystemBus / 1000000 / clkdiv;

	gur->lbiuiplldcr1 = 0x00078080;
	if (clkdiv == 16) {
		gur->lbiuiplldcr0 = 0x7c0f1bf0;
	} else if (clkdiv == 8) {
		gur->lbiuiplldcr0 = 0x6c0f1bf0;
	} else if (clkdiv == 4) {
		gur->lbiuiplldcr0 = 0x5c0f1bf0;
	}

	lbc->lcrr |= 0x00030000;

	asm("sync;isync;msync");

	lbc->ltesr = 0xffffffff;	/* Clear LBC error interrupts */
	lbc->lteir = 0xffffffff;	/* Enable LBC error interrupts */
}

/*
 * Initialize SDRAM memory on the Local Bus.
 */
void
sdram_init(void)
{
172
#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
173 174

	uint idx;
175 176
	volatile ccsr_lbc_t *lbc = (void *)(CONFIG_SYS_MPC85xx_LBC_ADDR);
	uint *sdram_addr = (uint *)CONFIG_SYS_LBC_SDRAM_BASE;
177 178 179 180
	uint lsdmr_common;

	puts("    SDRAM: ");

181
	print_size (CONFIG_SYS_LBC_SDRAM_SIZE * 1024 * 1024, "\n");
182 183 184 185

	/*
	 * Setup SDRAM Base and Option Registers
	 */
186
	lbc->or3 = CONFIG_SYS_OR3_PRELIM;
187 188
	asm("msync");

189
	lbc->br3 = CONFIG_SYS_BR3_PRELIM;
190 191
	asm("msync");

192
	lbc->lbcr = CONFIG_SYS_LBC_LBCR;
193 194 195
	asm("msync");


196 197
	lbc->lsrt = CONFIG_SYS_LBC_LSRT;
	lbc->mrtpr = CONFIG_SYS_LBC_MRTPR;
198 199 200 201 202
	asm("msync");

	/*
	 * MPC8548 uses "new" 15-16 style addressing.
	 */
203 204
	lsdmr_common = CONFIG_SYS_LBC_LSDMR_COMMON;
	lsdmr_common |= CONFIG_SYS_LBC_LSDMR_BSMA1516;
205 206 207 208

	/*
	 * Issue PRECHARGE ALL command.
	 */
209
	lbc->lsdmr = lsdmr_common | CONFIG_SYS_LBC_LSDMR_OP_PCHALL;
210 211 212 213 214 215 216 217 218
	asm("sync;msync");
	*sdram_addr = 0xff;
	ppcDcbf((unsigned long) sdram_addr);
	udelay(100);

	/*
	 * Issue 8 AUTO REFRESH commands.
	 */
	for (idx = 0; idx < 8; idx++) {
219
		lbc->lsdmr = lsdmr_common | CONFIG_SYS_LBC_LSDMR_OP_ARFRSH;
220 221 222 223 224 225 226 227 228
		asm("sync;msync");
		*sdram_addr = 0xff;
		ppcDcbf((unsigned long) sdram_addr);
		udelay(100);
	}

	/*
	 * Issue 8 MODE-set command.
	 */
229
	lbc->lsdmr = lsdmr_common | CONFIG_SYS_LBC_LSDMR_OP_MRW;
230 231 232 233 234 235 236 237
	asm("sync;msync");
	*sdram_addr = 0xff;
	ppcDcbf((unsigned long) sdram_addr);
	udelay(100);

	/*
	 * Issue NORMAL OP command.
	 */
238
	lbc->lsdmr = lsdmr_common | CONFIG_SYS_LBC_LSDMR_OP_NORMAL;
239 240 241 242 243 244 245 246
	asm("sync;msync");
	*sdram_addr = 0xff;
	ppcDcbf((unsigned long) sdram_addr);
	udelay(200);    /* Overkill. Must wait > 200 bus cycles */

#endif	/* enable SDRAM init */
}

247
#if defined(CONFIG_SYS_DRAM_TEST)
248 249 250
int
testdram(void)
{
251 252
	uint *pstart = (uint *) CONFIG_SYS_MEMTEST_START;
	uint *pend = (uint *) CONFIG_SYS_MEMTEST_END;
253 254 255
	uint *p;

	printf("Testing DRAM from 0x%08x to 0x%08x\n",
256 257
	       CONFIG_SYS_MEMTEST_START,
	       CONFIG_SYS_MEMTEST_END);
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

	printf("DRAM test phase 1:\n");
	for (p = pstart; p < pend; p++)
		*p = 0xaaaaaaaa;

	for (p = pstart; p < pend; p++) {
		if (*p != 0xaaaaaaaa) {
			printf ("DRAM test fails at: %08x\n", (uint) p);
			return 1;
		}
	}

	printf("DRAM test phase 2:\n");
	for (p = pstart; p < pend; p++)
		*p = 0x55555555;

	for (p = pstart; p < pend; p++) {
		if (*p != 0x55555555) {
			printf ("DRAM test fails at: %08x\n", (uint) p);
			return 1;
		}
	}

	printf("DRAM test passed.\n");
	return 0;
}
#endif

#if	!defined(CONFIG_SPD_EEPROM)
/*************************************************************************
 *  fixed_sdram init -- doesn't use serial presence detect.
 *  assumes 256MB DDR2 SDRAM SODIMM, without ECC, running at DDR400 speed.
 ************************************************************************/
long int fixed_sdram (void)
{
293
    #define CONFIG_SYS_DDR_CONTROL 0xc300c000
294

295
	volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
296 297 298 299 300 301 302 303 304

	ddr->cs0_bnds		= 0x0000007f;
	ddr->cs1_bnds		= 0x008000ff;
	ddr->cs2_bnds		= 0x00000000;
	ddr->cs3_bnds		= 0x00000000;
	ddr->cs0_config		= 0x80010101;
	ddr->cs1_config		= 0x80010101;
	ddr->cs2_config		= 0x00000000;
	ddr->cs3_config		= 0x00000000;
305
	ddr->timing_cfg_3		= 0x00000000;
306 307 308 309 310 311 312 313 314 315
	ddr->timing_cfg_0	= 0x00220802;
	ddr->timing_cfg_1	= 0x38377322;
	ddr->timing_cfg_2	= 0x0fa044C7;
	ddr->sdram_cfg		= 0x4300C000;
	ddr->sdram_cfg_2	= 0x24401000;
	ddr->sdram_mode		= 0x23C00542;
	ddr->sdram_mode_2	= 0x00000000;
	ddr->sdram_interval	= 0x05080100;
	ddr->sdram_md_cntl	= 0x00000000;
	ddr->sdram_data_init	= 0x00000000;
W
Wolfgang Denk 已提交
316
	ddr->sdram_clk_cntl	= 0x03800000;
317 318 319 320 321
	asm("sync;isync;msync");
	udelay(500);

	#if defined (CONFIG_DDR_ECC)
	  /* Enable ECC checking */
322
	  ddr->sdram_cfg = (CONFIG_SYS_DDR_CONTROL | 0x20000000);
323
	#else
324
	  ddr->sdram_cfg = CONFIG_SYS_DDR_CONTROL;
325 326
	#endif

327
	return CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
}
#endif

#if defined(CONFIG_PCI) || defined(CONFIG_PCI1)
/* For some reason the Tundra PCI bridge shows up on itself as a
 * different device.  Work around that by refusing to configure it.
 */
void dummy_func(struct pci_controller* hose, pci_dev_t dev, struct pci_config_table *tab) { }

static struct pci_config_table pci_sbc8548_config_table[] = {
	{0x10e3, 0x0513, PCI_ANY_ID, 1, 3, PCI_ANY_ID, dummy_func, {0,0,0}},
	{0x1106, 0x0686, PCI_ANY_ID, 1, VIA_ID, 0, mpc85xx_config_via, {0,0,0}},
	{0x1106, 0x0571, PCI_ANY_ID, 1, VIA_ID, 1,
		mpc85xx_config_via_usbide, {0,0,0}},
	{0x1105, 0x3038, PCI_ANY_ID, 1, VIA_ID, 2,
		mpc85xx_config_via_usb, {0,0,0}},
	{0x1106, 0x3038, PCI_ANY_ID, 1, VIA_ID, 3,
		mpc85xx_config_via_usb2, {0,0,0}},
	{0x1106, 0x3058, PCI_ANY_ID, 1, VIA_ID, 5,
		mpc85xx_config_via_power, {0,0,0}},
	{0x1106, 0x3068, PCI_ANY_ID, 1, VIA_ID, 6,
		mpc85xx_config_via_ac97, {0,0,0}},
	{},
};

static struct pci_controller pci1_hose = {
	config_table: pci_sbc8548_config_table};
#endif	/* CONFIG_PCI */

#ifdef CONFIG_PCI2
static struct pci_controller pci2_hose;
#endif	/* CONFIG_PCI2 */

#ifdef CONFIG_PCIE1
static struct pci_controller pcie1_hose;
#endif	/* CONFIG_PCIE1 */

int first_free_busno=0;

void
pci_init_board(void)
{
370
	volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
371 372 373

#ifdef CONFIG_PCI1
{
374
	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCI1_ADDR;
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
	extern void fsl_pci_init(struct pci_controller *hose);
	struct pci_controller *hose = &pci1_hose;
	struct pci_config_table *table;

	uint pci_32 = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_PCI32;	/* PORDEVSR[15] */
	uint pci_arb = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_ARB;	/* PORDEVSR[14] */
	uint pci_clk_sel = gur->porpllsr & MPC85xx_PORDEVSR_PCI1_SPD;	/* PORPLLSR[16] */

	uint pci_agent = (host_agent == 3) || (host_agent == 4 ) || (host_agent == 6);

	uint pci_speed = get_clock_freq ();	/* PCI PSPEED in [4:5] */

	if (!(gur->devdisr & MPC85xx_DEVDISR_PCI1)) {
		printf ("    PCI: %d bit, %s MHz, %s, %s, %s\n",
			(pci_32) ? 32 : 64,
			(pci_speed == 33333000) ? "33" :
			(pci_speed == 66666000) ? "66" : "unknown",
			pci_clk_sel ? "sync" : "async",
			pci_agent ? "agent" : "host",
			pci_arb ? "arbiter" : "external-arbiter"
			);


		/* inbound */
		pci_set_region(hose->regions + 0,
400 401 402
			       CONFIG_SYS_PCI_MEMORY_BUS,
			       CONFIG_SYS_PCI_MEMORY_PHYS,
			       CONFIG_SYS_PCI_MEMORY_SIZE,
403 404 405 406 407
			       PCI_REGION_MEM | PCI_REGION_MEMORY);


		/* outbound memory */
		pci_set_region(hose->regions + 1,
408 409 410
			       CONFIG_SYS_PCI1_MEM_BASE,
			       CONFIG_SYS_PCI1_MEM_PHYS,
			       CONFIG_SYS_PCI1_MEM_SIZE,
411 412 413 414
			       PCI_REGION_MEM);

		/* outbound io */
		pci_set_region(hose->regions + 2,
415 416 417
			       CONFIG_SYS_PCI1_IO_BASE,
			       CONFIG_SYS_PCI1_IO_PHYS,
			       CONFIG_SYS_PCI1_IO_SIZE,
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
			       PCI_REGION_IO);
		hose->region_count = 3;

		/* relocate config table pointers */
		hose->config_table = \
			(struct pci_config_table *)((uint)hose->config_table + gd->reloc_off);
		for (table = hose->config_table; table && table->vendor; table++)
			table->config_device += gd->reloc_off;

		hose->first_busno=first_free_busno;
		pci_setup_indirect(hose, (int) &pci->cfg_addr, (int) &pci->cfg_data);

		fsl_pci_init(hose);
		first_free_busno=hose->last_busno+1;
		printf ("PCI on bus %02x - %02x\n",hose->first_busno,hose->last_busno);
#ifdef CONFIG_PCIX_CHECK
		if (!(gur->pordevsr & PORDEVSR_PCI)) {
			/* PCI-X init */
			if (CONFIG_SYS_CLK_FREQ < 66000000)
				printf("PCI-X will only work at 66 MHz\n");

			reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
				| PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
			pci_hose_write_config_word(hose, bus, PCIX_COMMAND, reg16);
		}
#endif
	} else {
		printf ("    PCI: disabled\n");
	}
}
#else
	gur->devdisr |= MPC85xx_DEVDISR_PCI1; /* disable */
#endif

#ifdef CONFIG_PCI2
{
	uint pci2_clk_sel = gur->porpllsr & 0x4000;	/* PORPLLSR[17] */
	uint pci_dual = get_pci_dual ();	/* PCI DUAL in CM_PCI[3] */
	if (pci_dual) {
		printf ("    PCI2: 32 bit, 66 MHz, %s\n",
			pci2_clk_sel ? "sync" : "async");
	} else {
		printf ("    PCI2: disabled\n");
	}
}
#else
	gur->devdisr |= MPC85xx_DEVDISR_PCI2; /* disable */
#endif /* CONFIG_PCI2 */

#ifdef CONFIG_PCIE1
{
469
	volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCIE1_ADDR;
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
	extern void fsl_pci_init(struct pci_controller *hose);
	struct pci_controller *hose = &pcie1_hose;
	int pcie_ep =  (host_agent == 0) || (host_agent == 2 ) || (host_agent == 3);

	int pcie_configured  = io_sel >= 1;

	if (pcie_configured && !(gur->devdisr & MPC85xx_DEVDISR_PCIE)){
		printf ("\n    PCIE connected to slot as %s (base address %x)",
			pcie_ep ? "End Point" : "Root Complex",
			(uint)pci);

		if (pci->pme_msg_det) {
			pci->pme_msg_det = 0xffffffff;
			debug (" with errors.  Clearing.  Now 0x%08x",pci->pme_msg_det);
		}
		printf ("\n");

		/* inbound */
		pci_set_region(hose->regions + 0,
489 490 491
			       CONFIG_SYS_PCI_MEMORY_BUS,
			       CONFIG_SYS_PCI_MEMORY_PHYS,
			       CONFIG_SYS_PCI_MEMORY_SIZE,
492 493 494 495
			       PCI_REGION_MEM | PCI_REGION_MEMORY);

		/* outbound memory */
		pci_set_region(hose->regions + 1,
496 497 498
			       CONFIG_SYS_PCIE1_MEM_BASE,
			       CONFIG_SYS_PCIE1_MEM_PHYS,
			       CONFIG_SYS_PCIE1_MEM_SIZE,
499 500 501 502
			       PCI_REGION_MEM);

		/* outbound io */
		pci_set_region(hose->regions + 2,
503 504 505
			       CONFIG_SYS_PCIE1_IO_BASE,
			       CONFIG_SYS_PCIE1_IO_PHYS,
			       CONFIG_SYS_PCIE1_IO_SIZE,
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
			       PCI_REGION_IO);

		hose->region_count = 3;

		hose->first_busno=first_free_busno;
		pci_setup_indirect(hose, (int) &pci->cfg_addr, (int) &pci->cfg_data);

		fsl_pci_init(hose);
		printf ("PCIE on bus %d - %d\n",hose->first_busno,hose->last_busno);

		first_free_busno=hose->last_busno+1;

	} else {
		printf ("    PCIE: disabled\n");
	}
 }
#else
	gur->devdisr |= MPC85xx_DEVDISR_PCIE; /* disable */
#endif

}

int last_stage_init(void)
{
	return 0;
}

#if defined(CONFIG_OF_BOARD_SETUP)
void
ft_pci_setup(void *blob, bd_t *bd)
{
	int node, tmp[2];

	node = fdt_path_offset(blob, "/aliases");
	tmp[0] = 0;
	if (node >= 0) {
#ifdef CONFIG_PCI1
543
		const char *path;
544 545 546 547 548 549 550
		path = fdt_getprop(blob, node, "pci0", NULL);
		if (path) {
			tmp[1] = pci1_hose.last_busno - pci1_hose.first_busno;
			do_fixup_by_path(blob, path, "bus-range", &tmp, 8, 1);
		}
#endif
#ifdef CONFIG_PCIE1
551
		const char *path;
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
		path = fdt_getprop(blob, node, "pci1", NULL);
		if (path) {
			tmp[1] = pcie1_hose.last_busno - pcie1_hose.first_busno;
			do_fixup_by_path(blob, path, "bus-range", &tmp, 8, 1);
		}
#endif
	}
}
#endif

#if defined(CONFIG_OF_BOARD_SETUP)
void
ft_board_setup(void *blob, bd_t *bd)
{
	ft_cpu_setup(blob, bd);
#ifdef CONFIG_PCI
	ft_pci_setup(blob, bd);
#endif
}
#endif