icecube.c 7.96 KB
Newer Older
1 2 3 4
/*
 * (C) Copyright 2003
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
5 6 7
 * (C) Copyright 2004
 * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
 *
8
 * SPDX-License-Identifier:	GPL-2.0+
9 10 11 12
 */

#include <common.h>
#include <mpc5xxx.h>
13
#include <pci.h>
14
#include <asm/processor.h>
15
#include <libfdt.h>
16
#include <netdev.h>
17

18 19
#if defined(CONFIG_LITE5200B)
#include "mt46v32m16.h"
20
#else
21 22 23
# if defined(CONFIG_MPC5200_DDR)
#  include "mt46v16m16-75.h"
# else
24
#include "mt48lc16m16a2-75.h"
25
# endif
26
#endif
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

#ifdef CONFIG_LITE5200B_PM
/* u-boot part of low-power mode implementation */
#define SAVED_ADDR (*(void **)0x00000000)
#define PSC2_4 0x02

void lite5200b_wakeup(void)
{
	unsigned char wakeup_pin;
	void (*linux_wakeup)(void);

	/* check PSC2_4, if it's down "QT" is signaling we have a wakeup
	 * from low power mode */
	*(vu_char *)MPC5XXX_WU_GPIO_ENABLE = PSC2_4;
	__asm__ volatile ("sync");

	wakeup_pin = *(vu_char *)MPC5XXX_WU_GPIO_DATA_I;
	if (wakeup_pin & PSC2_4)
		return;

	/* acknowledge to "QT"
	 * by holding pin at 1 for 10 uS */
	*(vu_char *)MPC5XXX_WU_GPIO_DIR = PSC2_4;
	__asm__ volatile ("sync");
	*(vu_char *)MPC5XXX_WU_GPIO_DATA_O = PSC2_4;
	__asm__ volatile ("sync");
	udelay(10);

	/* put ram out of self-refresh */
	*(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x80000000;	/* mode_en */
	__asm__ volatile ("sync");
	*(vu_long *)MPC5XXX_SDRAM_CTRL |= 0x50000000;	/* cke ref_en */
	__asm__ volatile ("sync");
	*(vu_long *)MPC5XXX_SDRAM_CTRL &= ~0x80000000;	/* !mode_en */
	__asm__ volatile ("sync");
	udelay(10); /* wait a bit */

	/* jump back to linux kernel code */
	linux_wakeup = SAVED_ADDR;
	printf("\n\nLooks like we just woke, transferring control to 0x%08lx\n",
67
			(unsigned long)linux_wakeup);
68 69 70 71 72 73
	linux_wakeup();
}
#else
#define lite5200b_wakeup()
#endif

74
#ifndef CONFIG_SYS_RAMBOOT
75 76 77
static void sdram_start (int hi_addr)
{
	long hi_addr_bit = hi_addr ? 0x01000000 : 0;
78

79
	/* unlock mode register */
80 81
	*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | hi_addr_bit;
	__asm__ volatile ("sync");
82

83
	/* precharge all banks */
84 85 86 87
	*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit;
	__asm__ volatile ("sync");

#if SDRAM_DDR
88
	/* set mode register: extended mode */
89 90 91
	*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE;
	__asm__ volatile ("sync");

92
	/* set mode register: reset DLL */
93 94
	*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000;
	__asm__ volatile ("sync");
95
#endif
96 97 98 99 100

	/* precharge all banks */
	*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | hi_addr_bit;
	__asm__ volatile ("sync");

101
	/* auto refresh */
102 103 104
	*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | hi_addr_bit;
	__asm__ volatile ("sync");

105
	/* set mode register */
106 107
	*(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE;
	__asm__ volatile ("sync");
108

109
	/* normal operation */
110 111
	*(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit;
	__asm__ volatile ("sync");
112
}
wdenk's avatar
wdenk committed
113
#endif
114

115 116
/*
 * ATTENTION: Although partially referenced initdram does NOT make real use
117
 *            use of CONFIG_SYS_SDRAM_BASE. The code does not work if CONFIG_SYS_SDRAM_BASE
118 119 120
 *            is something else than 0x00000000.
 */

121
phys_size_t initdram (int board_type)
122
{
wdenk's avatar
wdenk committed
123
	ulong dramsize = 0;
124
	ulong dramsize2 = 0;
125 126
	uint svr, pvr;

127
#ifndef CONFIG_SYS_RAMBOOT
wdenk's avatar
wdenk committed
128
	ulong test1, test2;
129

130
	/* setup SDRAM chip selects */
131 132
	*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001e;/* 2G at 0x0 */
	*(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x80000000;/* disabled */
133
	__asm__ volatile ("sync");
134

135
	/* setup config registers */
136 137 138
	*(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1;
	*(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2;
	__asm__ volatile ("sync");
wdenk's avatar
wdenk committed
139

140 141 142 143
#if SDRAM_DDR
	/* set tap delay */
	*(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY;
	__asm__ volatile ("sync");
144
#endif
145

146
	/* find RAM size using SDRAM CS0 only */
147
	sdram_start(0);
148
	test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
149
	sdram_start(1);
150
	test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
151 152 153 154 155 156
	if (test1 > test2) {
		sdram_start(0);
		dramsize = test1;
	} else {
		dramsize = test2;
	}
157 158 159 160 161

	/* memory smaller than 1MB is impossible */
	if (dramsize < (1 << 20)) {
		dramsize = 0;
	}
162

163 164 165 166 167 168 169 170
	/* set SDRAM CS0 size according to the amount of RAM found */
	if (dramsize > 0) {
		*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + __builtin_ffs(dramsize >> 20) - 1;
	} else {
		*(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */
	}

	/* let SDRAM CS1 start right after CS0 */
171
	*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001e;/* 2G */
172 173

	/* find RAM size using SDRAM CS1 only */
174
	if (!dramsize)
175
		sdram_start(0);
176
	test2 = test1 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
177 178
	if (!dramsize) {
		sdram_start(1);
179
		test2 = get_ram_size((long *)(CONFIG_SYS_SDRAM_BASE + dramsize), 0x80000000);
180
	}
181 182 183 184 185 186
	if (test1 > test2) {
		sdram_start(0);
		dramsize2 = test1;
	} else {
		dramsize2 = test2;
	}
187

188 189 190 191
	/* memory smaller than 1MB is impossible */
	if (dramsize2 < (1 << 20)) {
		dramsize2 = 0;
	}
192

193 194 195 196 197 198 199 200
	/* set SDRAM CS1 size according to the amount of RAM found */
	if (dramsize2 > 0) {
		*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize
			| (0x13 + __builtin_ffs(dramsize2 >> 20) - 1);
	} else {
		*(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */
	}

201
#else /* CONFIG_SYS_RAMBOOT */
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

	/* retrieve size of memory connected to SDRAM CS0 */
	dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF;
	if (dramsize >= 0x13) {
		dramsize = (1 << (dramsize - 0x13)) << 20;
	} else {
		dramsize = 0;
	}

	/* retrieve size of memory connected to SDRAM CS1 */
	dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF;
	if (dramsize2 >= 0x13) {
		dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
	} else {
		dramsize2 = 0;
	}

219
#endif /* CONFIG_SYS_RAMBOOT */
220

221
	/*
Wolfgang Denk's avatar
Wolfgang Denk committed
222 223
	 * On MPC5200B we need to set the special configuration delay in the
	 * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
224 225
	 * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
	 *
Wolfgang Denk's avatar
Wolfgang Denk committed
226 227
	 * "The SDelay should be written to a value of 0x00000004. It is
	 * required to account for changes caused by normal wafer processing
228
	 * parameters."
Wolfgang Denk's avatar
Wolfgang Denk committed
229
	 */
230 231
	svr = get_svr();
	pvr = get_pvr();
Wolfgang Denk's avatar
Wolfgang Denk committed
232
	if ((SVR_MJREV(svr) >= 2) &&
233 234 235 236 237 238
	    (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4)) {

		*(vu_long *)MPC5XXX_SDRAM_SDELAY = 0x04;
		__asm__ volatile ("sync");
	}

239 240
	lite5200b_wakeup();

241 242 243
	return dramsize + dramsize2;
}

244 245
int checkboard (void)
{
246 247
#if defined (CONFIG_LITE5200B)
	puts ("Board: Freescale Lite5200B\n");
248
#else
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
	puts ("Board: Motorola MPC5200 (IceCube)\n");
#endif
	return 0;
}

void flash_preinit(void)
{
	/*
	 * Now, when we are in RAM, enable flash write
	 * access for detection process.
	 * Note that CS_BOOT cannot be cleared when
	 * executing in flash.
	 */
	*(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */
}
264

wdenk's avatar
wdenk committed
265 266 267
void flash_afterinit(ulong size)
{
	if (size == 0x800000) { /* adjust mapping */
268
		*(vu_long *)MPC5XXX_BOOTCS_START = *(vu_long *)MPC5XXX_CS0_START =
269
			START_REG(CONFIG_SYS_BOOTCS_START | size);
270
		*(vu_long *)MPC5XXX_BOOTCS_STOP = *(vu_long *)MPC5XXX_CS0_STOP =
271
			STOP_REG(CONFIG_SYS_BOOTCS_START | size, size);
wdenk's avatar
wdenk committed
272 273 274
	}
}

275 276 277 278 279 280 281 282 283 284
#ifdef	CONFIG_PCI
static struct pci_controller hose;

extern void pci_mpc5xxx_init(struct pci_controller *);

void pci_init_board(void)
{
	pci_mpc5xxx_init(&hose);
}
#endif
285

286
#if defined(CONFIG_CMD_IDE) && defined(CONFIG_IDE_RESET)
287 288 289

void init_ide_reset (void)
{
290
	debug ("init_ide_reset\n");
291

Wolfgang Denk's avatar
Wolfgang Denk committed
292
	/* Configure PSC1_4 as GPIO output for ATA reset */
293
	*(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4;
294
	*(vu_long *) MPC5XXX_WU_GPIO_DIR    |= GPIO_PSC1_4;
295
	/* Deassert reset */
296
	*(vu_long *) MPC5XXX_WU_GPIO_DATA_O   |= GPIO_PSC1_4;
297 298 299 300
}

void ide_set_reset (int idereset)
{
301 302
	debug ("ide_reset(%d)\n", idereset);

303
	if (idereset) {
304
		*(vu_long *) MPC5XXX_WU_GPIO_DATA_O &= ~GPIO_PSC1_4;
305 306
		/* Make a delay. MPC5200 spec says 25 usec min */
		udelay(500000);
307
	} else {
308
		*(vu_long *) MPC5XXX_WU_GPIO_DATA_O |=  GPIO_PSC1_4;
309 310
	}
}
311
#endif
312

313
#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
314 315 316 317 318 319
void
ft_board_setup(void *blob, bd_t *bd)
{
	ft_cpu_setup(blob, bd);
}
#endif
320 321 322

int board_eth_init(bd_t *bis)
{
323
	cpu_eth_init(bis); /* Built in FEC comes first */
324 325
	return pci_eth_init(bis);
}