iphase4539.c 12 KB
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 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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 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 138 139 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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 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 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 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 370 371 372 373 374 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 400 401 402 403 404 405 406 407 408
/*
 * (C) Copyright 2002 Wolfgang Grandegger <wg@denx.de>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <ioports.h>
#include <mpc8260.h>
#include <asm/io.h>
#include <asm/immap_8260.h>

int hwc_flash_size (void);
int hwc_local_sdram_size (void);
int hwc_main_sdram_size (void);
int hwc_serial_number (void);
int hwc_mac_address (char *str);
int hwc_manufact_date (char *str);
int seeprom_read (int addr, uchar * data, int size);

/*
 * I/O Port configuration table
 *
 * if conf is 1, then that port pin will be configured at boot time
 * according to the five values podr/pdir/ppar/psor/pdat for that entry
 *
 * The port definitions are taken from the old firmware (see
 * also SYS/H/4539.H):
 *
 *        ppar      psor        pdir       podr       pdat
 * PA: 0x02ffffff 0x02c00000 0xfc403fe6 0x00000000 0x02403fc0
 * PB: 0x0fffdeb0 0x000000b0 0x0f032347 0x00000000 0x0f000290
 * PC: 0x030ffa55 0x030f0040 0xbcf005ea 0x00000000 0xc0c0ba7d
 * PD: 0x09c04e3c 0x01000e3c 0x0a7ff1c3 0x00000000 0x00ce0ae9
 */
const iop_conf_t iop_conf_tab[4][32] = {

	/* Port A configuration */
	{							/* conf ppar psor pdir podr pdat */
	 {0, 1, 0, 0, 0, 0},		/* PA31 FCC1_TXENB  SLAVE */
	 {0, 1, 0, 1, 0, 0},		/* PA30 FCC1_TXCLAV SLAVE */
	 {0, 1, 0, 1, 0, 0},		/* PA29 FCC1_TXSOC */
	 {0, 1, 0, 0, 0, 0},		/* PA28 FCC1_RXENB  SLAVE */
	 {0, 1, 0, 0, 0, 0},		/* PA27 FCC1_RXSOC */
	 {0, 1, 0, 1, 0, 0},		/* PA26 FCC1_RXCLAV SLAVE */
	 {0, 1, 0, 1, 0, 1},		/* PA25 FCC1_TXD0 */
	 {0, 1, 0, 1, 0, 1},		/* PA24 FCC1_TXD1 */
	 {0, 1, 0, 1, 0, 1},		/* PA23 FCC1_TXD2 */
	 {0, 1, 0, 1, 0, 1},		/* PA22 FCC1_TXD3 */
	 {0, 1, 0, 1, 0, 1},		/* PA21 FCC1_TXD4 */
	 {0, 1, 0, 1, 0, 1},		/* PA20 FCC1_TXD5 */
	 {0, 1, 0, 1, 0, 1},		/* PA19 FCC1_TXD6 */
	 {0, 1, 0, 1, 0, 1},		/* PA18 FCC1_TXD7 */
	 {0, 1, 0, 0, 0, 0},		/* PA17 FCC1_RXD7 */
	 {0, 1, 0, 0, 0, 0},		/* PA16 FCC1_RXD6 */
	 {0, 1, 0, 0, 0, 0},		/* PA15 FCC1_RXD5 */
	 {0, 1, 0, 0, 0, 0},		/* PA14 FCC1_RXD4 */
	 {0, 1, 0, 0, 0, 0},		/* PA13 FCC1_RXD3 */
	 {0, 1, 0, 0, 0, 0},		/* PA12 FCC1_RXD2 */
	 {0, 1, 0, 0, 0, 0},		/* PA11 FCC1_RXD1 */
	 {0, 1, 0, 0, 0, 0},		/* PA10 FCC1_RXD0 */
	 {0, 1, 1, 1, 0, 1},		/* PA9  TDMA1_L1TXD */
	 {0, 1, 1, 0, 0, 0},		/* PA8  TDMA1_L1RXD */
	 {0, 0, 0, 0, 0, 0},		/* PA7  CONFIG0 */
	 {0, 1, 1, 0, 0, 1},		/* PA6  TDMA1_L1RSYNC */
	 {0, 0, 0, 1, 0, 0},		/* PA5  FCC2:RxAddr[2] */
	 {0, 0, 0, 1, 0, 0},		/* PA4  FCC2:RxAddr[1] */
	 {0, 0, 0, 1, 0, 0},		/* PA3  FCC2:RxAddr[0] */
	 {0, 0, 0, 1, 0, 0},		/* PA2  FCC2:TxAddr[0] */
	 {0, 0, 0, 1, 0, 0},		/* PA1  FCC2:TxAddr[1] */
	 {0, 0, 0, 1, 0, 0}			/* PA0  FCC2:TxAddr[2] */
	 },
	/* Port B configuration */
	{							/* conf ppar psor pdir podr pdat */
	 {0, 0, 0, 1, 0, 0},		/* PB31 FCC2_RXSOC */
	 {0, 0, 0, 1, 0, 0},		/* PB30 FCC2_TXSOC */
	 {0, 0, 0, 1, 0, 0},		/* PB29 FCC2_RXCLAV */
	 {0, 0, 0, 0, 0, 0},		/* PB28 CONFIG2 */
	 {0, 1, 1, 0, 0, 1},		/* PB27 FCC2_TXD0 */
	 {0, 1, 1, 0, 0, 0},		/* PB26 FCC2_TXD1 */
	 {0, 0, 0, 1, 0, 0},		/* PB25 FCC2_TXD4 */
	 {0, 1, 1, 0, 0, 1},		/* PB24 FCC2_TXD5 */
	 {0, 0, 0, 1, 0, 0},		/* PB23 FCC2_TXD6 */
	 {0, 1, 0, 1, 0, 1},		/* PB22 FCC2_TXD7 */
	 {0, 1, 0, 0, 0, 0},		/* PB21 FCC2_RXD7 */
	 {0, 1, 0, 0, 0, 0},		/* PB20 FCC2_RXD6 */
	 {0, 1, 0, 0, 0, 0},		/* PB19 FCC2_RXD5 */
	 {0, 0, 0, 1, 0, 0},		/* PB18 FCC2_RXD4 */
	 {1, 1, 0, 0, 0, 0},		/* PB17 FCC3_RX_DV */
	 {1, 1, 0, 0, 0, 0},		/* PB16 FCC3_RX_ER */
	 {1, 1, 0, 1, 0, 0},		/* PB15 FCC3_TX_ER */
	 {1, 1, 0, 1, 0, 0},		/* PB14 FCC3_TX_EN */
	 {1, 1, 0, 0, 0, 0},		/* PB13 FCC3_COL */
	 {1, 1, 0, 0, 0, 0},		/* PB12 FCC3_CRS */
	 {1, 1, 0, 0, 0, 0},		/* PB11 FCC3_RXD3 */
	 {1, 1, 0, 0, 0, 0},		/* PB10 FCC3_RXD2 */
	 {1, 1, 0, 0, 0, 0},		/* PB9  FCC3_RXD1 */
	 {1, 1, 0, 0, 0, 0},		/* PB8  FCC3_RXD0 */
	 {1, 1, 0, 1, 0, 1},		/* PB7  FCC3_TXD0 */
	 {1, 1, 0, 1, 0, 1},		/* PB6  FCC3_TXD1 */
	 {1, 1, 0, 1, 0, 1},		/* PB5  FCC3_TXD2 */
	 {1, 1, 0, 1, 0, 1},		/* PB4  FCC3_TXD3 */
	 {0, 0, 0, 0, 0, 0},		/* PB3  */
	 {0, 0, 0, 0, 0, 0},		/* PB2  */
	 {0, 0, 0, 0, 0, 0},		/* PB1  */
	 {0, 0, 0, 0, 0, 0},		/* PB0  */
	 },
	/* Port C configuration */
	{							/* conf ppar psor pdir podr pdat */
	 {0, 1, 0, 0, 0, 1},		/* PC31 CLK1 */
	 {0, 0, 0, 1, 0, 0},		/* PC30 U1MASTER_N */
	 {0, 1, 0, 0, 0, 1},		/* PC29 CLK3 */
	 {0, 0, 0, 1, 0, 1},		/* PC28 -MT90220_RST */
	 {0, 1, 0, 0, 0, 1},		/* PC27 CLK5 */
	 {0, 0, 0, 1, 0, 1},		/* PC26 -QUADFALC_RST */
	 {0, 1, 1, 1, 0, 1},		/* PC25 BRG4 */
	 {1, 0, 0, 1, 0, 0},		/* PC24 MDIO */
	 {1, 0, 0, 1, 0, 0},		/* PC23 MDC */
	 {0, 1, 0, 0, 0, 1},		/* PC22 CLK10 */
	 {0, 0, 0, 1, 0, 0},		/* PC21  */
	 {0, 1, 0, 0, 0, 1},		/* PC20 CLK12 */
	 {0, 1, 0, 0, 0, 1},		/* PC19 CLK13 */
	 {1, 1, 0, 0, 0, 1},		/* PC18 CLK14 */
	 {0, 1, 0, 0, 0, 0},		/* PC17 CLK15 */
	 {1, 1, 0, 0, 0, 1},		/* PC16 CLK16 */
	 {0, 1, 1, 0, 0, 0},		/* PC15 FCC1_TXADDR0 SLAVE */
	 {0, 1, 1, 0, 0, 0},		/* PC14 FCC1_RXADDR0 SLAVE */
	 {0, 1, 1, 0, 0, 0},		/* PC13 FCC1_TXADDR1 SLAVE */
	 {0, 1, 1, 0, 0, 0},		/* PC12 FCC1_RXADDR1 SLAVE */
	 {0, 0, 0, 1, 0, 0},		/* PC11 FCC2_RXD2 */
	 {0, 0, 0, 1, 0, 0},		/* PC10 FCC2_RXD3 */
	 {0, 0, 0, 1, 0, 1},		/* PC9  LTMODE */
	 {0, 0, 0, 1, 0, 1},		/* PC8  SELSYNC */
	 {0, 1, 1, 0, 0, 0},		/* PC7  FCC1_TXADDR2 SLAVE  */
	 {0, 1, 1, 0, 0, 0},		/* PC6  FCC1_RXADDR2 SLAVE */
	 {0, 0, 0, 1, 0, 0},		/* PC5  FCC2_TXCLAV MASTER */
	 {0, 0, 0, 1, 0, 0},		/* PC4  FCC2_RXENB MASTER */
	 {0, 0, 0, 1, 0, 0},		/* PC3  FCC2_TXD2 */
	 {0, 0, 0, 1, 0, 0},		/* PC2  FCC2_TXD3 */
	 {0, 0, 0, 0, 0, 1},		/* PC1  PTMC -PTEENB */
	 {0, 0, 0, 1, 0, 1},		/* PC0  COMCLK_N */
	 },
	/* Port D configuration */
	{							/* conf ppar psor pdir podr pdat */
	 {0, 0, 0, 1, 0, 1},		/* PD31 -CAM_RST */
	 {0, 0, 0, 1, 0, 0},		/* PD30 FCC2_TXENB */
	 {0, 1, 1, 0, 0, 0},		/* PD29 FCC1_RXADDR3 SLAVE */
	 {0, 1, 1, 0, 0, 1},		/* PD28 TDMC1_L1TXD */
	 {0, 1, 1, 0, 0, 0},		/* PD27 TDMC1_L1RXD */
	 {0, 1, 1, 0, 0, 1},		/* PD26 TDMC1_L1RSYNC */
	 {0, 0, 0, 1, 0, 1},		/* PD25 LED0 -OFF */
	 {0, 0, 0, 1, 0, 1},		/* PD24 LED5 -OFF */
	 {1, 0, 0, 1, 0, 1},		/* PD23 -LXT971_RST */
	 {0, 1, 1, 0, 0, 1},		/* PD22 TDMA2_L1TXD */
	 {0, 1, 1, 0, 0, 0},		/* PD21 TDMA2_L1RXD */
	 {0, 1, 1, 0, 0, 1},		/* PD20 TDMA2_L1RSYNC */
	 {0, 0, 0, 1, 0, 0},		/* PD19 FCC2_TXADDR3 */
	 {0, 0, 0, 1, 0, 0},		/* PD18 FCC2_RXADDR3 */
	 {0, 1, 0, 1, 0, 0},		/* PD17 BRG2 */
	 {0, 0, 0, 1, 0, 0},		/* PD16  */
	 {0, 0, 0, 1, 0, 0},		/* PD15 PT2TO1 */
	 {0, 0, 0, 1, 0, 1},		/* PD14 PT4TO3 */
	 {0, 0, 0, 1, 0, 1},		/* PD13 -SWMODE */
	 {0, 0, 0, 1, 0, 1},		/* PD12 -PTMODE */
	 {0, 0, 0, 1, 0, 0},		/* PD11 FCC2_RXD0 */
	 {0, 0, 0, 1, 0, 0},		/* PD10 FCC2_RXD1 */
	 {1, 1, 0, 1, 0, 1},		/* PD9  SMC1_SMTXD */
	 {1, 1, 0, 0, 0, 1},		/* PD8  SMC1_SMRXD */
	 {0, 1, 1, 0, 0, 0},		/* PD7  FCC1_TXADDR3 SLAVE */
	 {0, 0, 0, 1, 0, 0},		/* PD6  IMAMODE */
	 {0, 0, 0, 0, 0, 0},		/* PD5  CONFIG2 */
	 {0, 1, 0, 1, 0, 0},		/* PD4  BRG8 */
	 {0, 0, 0, 0, 0, 0},		/* PD3  */
	 {0, 0, 0, 0, 0, 0},		/* PD2  */
	 {0, 0, 0, 0, 0, 0},		/* PD1  */
	 {0, 0, 0, 0, 0, 0},		/* PD0  */
	 }
};

phys_size_t initdram (int board_type)
{
	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
	volatile memctl8260_t *memctl = &immap->im_memctl;
	volatile uchar *base;
	ulong maxsize;
	int i;

	memctl->memc_psrt = CONFIG_SYS_PSRT;
	memctl->memc_mptpr = CONFIG_SYS_MPTPR;

#ifndef CONFIG_SYS_RAMBOOT
	immap->im_siu_conf.sc_ppc_acr = 0x00000026;
	immap->im_siu_conf.sc_ppc_alrh = 0x01276345;
	immap->im_siu_conf.sc_ppc_alrl = 0x89ABCDEF;
	immap->im_siu_conf.sc_lcl_acr = 0x00000000;
	immap->im_siu_conf.sc_lcl_alrh = 0x01234567;
	immap->im_siu_conf.sc_lcl_alrl = 0x89ABCDEF;
	immap->im_siu_conf.sc_tescr1 = 0x00004000;
	immap->im_siu_conf.sc_ltescr1 = 0x00004000;

	/* Init Main SDRAM */
#define OP_VALUE   0x404A241A
#define OP_VALUE_M (OP_VALUE & 0x87FFFFFF);
	base = (uchar *) CONFIG_SYS_SDRAM_BASE;
	memctl->memc_psdmr = 0x28000000 | OP_VALUE_M;
	*base = 0xFF;
	memctl->memc_psdmr = 0x08000000 | OP_VALUE_M;
	for (i = 0; i < 8; i++)
		*base = 0xFF;
	memctl->memc_psdmr = 0x18000000 | OP_VALUE_M;
	*(base + 0x110) = 0xFF;
	memctl->memc_psdmr = OP_VALUE;
	memctl->memc_lsdmr = 0x4086A522;
	*base = 0xFF;

	/* We must be able to test a location outsize the maximum legal size
	 * to find out THAT we are outside; but this address still has to be
	 * mapped by the controller. That means, that the initial mapping has
	 * to be (at least) twice as large as the maximum expected size.
	 */
	maxsize = (1 + (~memctl->memc_or1 | 0x7fff)) / 2;

	maxsize = get_ram_size((long *)base, maxsize);

	memctl->memc_or1 |= ~(maxsize - 1);

	if (maxsize != hwc_main_sdram_size ())
		printf ("Oops: memory test has not found all memory!\n");
#endif

	icache_enable ();
	/* return total ram size of SDRAM */
	return (maxsize);
}

int checkboard (void)
{
	char string[32];

	hwc_manufact_date (string);

	printf ("Board: Interphase 4539 (#%d %s)\n",
		hwc_serial_number (),
		string);

#ifdef DEBUG
	printf ("Manufacturing date: %s\n", string);
	printf ("Serial number     : %d\n", hwc_serial_number ());
	printf ("FLASH size        : %d MB\n", hwc_flash_size () >> 20);
	printf ("Main SDRAM size   : %d MB\n", hwc_main_sdram_size () >> 20);
	printf ("Local SDRAM size  : %d MB\n", hwc_local_sdram_size () >> 20);
	hwc_mac_address (string);
	printf ("MAC address       : %s\n", string);
#endif

	return 0;
}

int misc_init_r (void)
{
	char *s, str[32];
	int num;

	if ((s = getenv ("serial#")) == NULL &&
		(num = hwc_serial_number ()) != -1) {
		sprintf (str, "%06d", num);
		setenv ("serial#", str);
	}
	if ((s = getenv ("ethaddr")) == NULL && hwc_mac_address (str) == 0) {
		setenv ("ethaddr", str);
	}
	return (0);
}

/***************************************************************
 * We take some basic Hardware Configuration Parameter from the
 * Serial EEPROM conected to the PSpan bridge. We keep it as
 * simple as possible.
 */
int hwc_flash_size (void)
{
	uchar byte;

	if (!seeprom_read (0x40, &byte, sizeof (byte))) {
		switch ((byte >> 2) & 0x3) {
		case 0x1:
			return 0x0400000;
			break;
		case 0x2:
			return 0x0800000;
			break;
		case 0x3:
			return 0x1000000;
		default:
			return 0x0100000;
		}
	}
	return -1;
}
int hwc_local_sdram_size (void)
{
	uchar byte;

	if (!seeprom_read (0x40, &byte, sizeof (byte))) {
		switch ((byte & 0x03)) {
		case 0x1:
			return 0x0800000;
		case 0x2:
			return 0x1000000;
		default:
			return 0;			/* not present */
		}
	}
	return -1;
}
int hwc_main_sdram_size (void)
{
	uchar byte;

	if (!seeprom_read (0x41, &byte, sizeof (byte))) {
		return 0x1000000 << ((byte >> 5) & 0x7);
	}
	return -1;
}
int hwc_serial_number (void)
{
	int sn = -1;

	if (!seeprom_read (0xa0, (uchar *) &sn, sizeof (sn))) {
		sn = cpu_to_le32 (sn);
	}
	return sn;
}
int hwc_mac_address (char *str)
{
	char mac[6];

	if (!seeprom_read (0xb0, (uchar *)mac, sizeof (mac))) {
		sprintf (str, "%02x:%02x:%02x:%02x:%02x:%02x\n",
				 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	} else {
		strcpy (str, "ERROR");
		return -1;
	}
	return 0;
}
int hwc_manufact_date (char *str)
{
	uchar byte;
	int value;

	if (seeprom_read (0x92, &byte, sizeof (byte)))
		goto out;
	value = byte;
	if (seeprom_read (0x93, &byte, sizeof (byte)))
		goto out;
	value += byte << 8;
	sprintf (str, "%02d/%02d/%04d",
			 value & 0x1F, (value >> 5) & 0xF,
			 1980 + ((value >> 9) & 0x1FF));
	return 0;

  out:
	strcpy (str, "ERROR");
	return -1;
}

#define PSPAN_ADDR      0xF0020000
#define EEPROM_REG      0x408
#define EEPROM_READ_CMD 0xA000
#define PSPAN_WRITE(a,v) \
    *((volatile unsigned long *)(PSPAN_ADDR+(a))) = v; eieio()
#define PSPAN_READ(a) \
    *((volatile unsigned long *)(PSPAN_ADDR+(a)))

int seeprom_read (int addr, uchar * data, int size)
{
	ulong val, cmd;
	int i;

	for (i = 0; i < size; i++) {

		cmd = EEPROM_READ_CMD;
		cmd |= ((addr + i) << 24) & 0xff000000;

		/* Wait for ACT to authorize write */
		while ((val = PSPAN_READ (EEPROM_REG)) & 0x80)
			eieio ();

		/* Write command */
		PSPAN_WRITE (EEPROM_REG, cmd);

		/* Wait for data to be valid */
		while ((val = PSPAN_READ (EEPROM_REG)) & 0x80)
			eieio ();
		/* Do it twice, first read might be erratic */
		while ((val = PSPAN_READ (EEPROM_REG)) & 0x80)
			eieio ();

		/* Read error */
		if (val & 0x00000040) {
			return -1;
		} else {
			data[i] = (val >> 16) & 0xff;
		}
	}
	return 0;
}