km_arm.c 10.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * (C) Copyright 2009
 * Marvell Semiconductor <www.marvell.com>
 * Prafulla Wadaskar <prafulla@marvell.com>
 *
 * (C) Copyright 2009
 * Stefan Roese, DENX Software Engineering, sr@denx.de.
 *
 * (C) Copyright 2010
 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
 *
12
 * SPDX-License-Identifier:	GPL-2.0+
13 14 15 16 17 18 19
 */

#include <common.h>
#include <i2c.h>
#include <nand.h>
#include <netdev.h>
#include <miiphy.h>
20
#include <spi.h>
21
#include <asm/io.h>
22
#include <asm/arch/cpu.h>
23 24 25 26 27 28 29
#include <asm/arch/kirkwood.h>
#include <asm/arch/mpp.h>

#include "../common/common.h"

DECLARE_GLOBAL_DATA_PTR;

30 31 32 33 34 35 36 37 38 39
/*
 * BOCO FPGA definitions
 */
#define BOCO		0x10
#define REG_CTRL_H		0x02
#define MASK_WRL_UNITRUN	0x01
#define MASK_RBX_PGY_PRESENT	0x40
#define REG_IRQ_CIRQ2		0x2d
#define MASK_RBI_DEFECT_16	0x01

40
/* Multi-Purpose Pins Functionality configuration */
41
static const u32 kwmpp_config[] = {
42 43 44 45 46 47 48 49
	MPP0_NF_IO2,
	MPP1_NF_IO3,
	MPP2_NF_IO4,
	MPP3_NF_IO5,
	MPP4_NF_IO6,
	MPP5_NF_IO7,
	MPP6_SYSRST_OUTn,
	MPP7_PEX_RST_OUTn,
50
#if defined(CONFIG_SYS_I2C_SOFT)
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
	MPP8_GPIO,		/* SDA */
	MPP9_GPIO,		/* SCL */
#endif
#if defined(CONFIG_HARD_I2C)
	MPP8_TW_SDA,
	MPP9_TW_SCK,
#endif
	MPP10_UART0_TXD,
	MPP11_UART0_RXD,
	MPP12_GPO,		/* Reserved */
	MPP13_UART1_TXD,
	MPP14_UART1_RXD,
	MPP15_GPIO,		/* Not used */
	MPP16_GPIO,		/* Not used */
	MPP17_GPIO,		/* Reserved */
	MPP18_NF_IO0,
	MPP19_NF_IO1,
	MPP20_GPIO,
	MPP21_GPIO,
	MPP22_GPIO,
	MPP23_GPIO,
	MPP24_GPIO,
	MPP25_GPIO,
	MPP26_GPIO,
	MPP27_GPIO,
	MPP28_GPIO,
	MPP29_GPIO,
	MPP30_GPIO,
	MPP31_GPIO,
	MPP32_GPIO,
	MPP33_GPIO,
	MPP34_GPIO,		/* CDL1 (input) */
	MPP35_GPIO,		/* CDL2 (input) */
	MPP36_GPIO,		/* MAIN_IRQ (input) */
	MPP37_GPIO,		/* BOARD_LED */
	MPP38_GPIO,		/* Piggy3 LED[1] */
	MPP39_GPIO,		/* Piggy3 LED[2] */
	MPP40_GPIO,		/* Piggy3 LED[3] */
	MPP41_GPIO,		/* Piggy3 LED[4] */
	MPP42_GPIO,		/* Piggy3 LED[5] */
	MPP43_GPIO,		/* Piggy3 LED[6] */
92
	MPP44_GPIO,		/* Piggy3 LED[7], BIST_EN_L */
93 94 95 96 97 98 99 100
	MPP45_GPIO,		/* Piggy3 LED[8] */
	MPP46_GPIO,		/* Reserved */
	MPP47_GPIO,		/* Reserved */
	MPP48_GPIO,		/* Reserved */
	MPP49_GPIO,		/* SW_INTOUTn */
	0
};

101
#if defined(CONFIG_KM_MGCOGE3UN)
102 103 104
/*
 * Wait for startup OK from mgcoge3ne
 */
105
static int startup_allowed(void)
106 107 108 109 110 111 112 113 114 115 116 117 118
{
	unsigned char buf;

	/*
	 * Read CIRQ16 bit (bit 0)
	 */
	if (i2c_read(BOCO, REG_IRQ_CIRQ2, 1, &buf, 1) != 0)
		printf("%s: Error reading Boco\n", __func__);
	else
		if ((buf & MASK_RBI_DEFECT_16) == MASK_RBI_DEFECT_16)
			return 1;
	return 0;
}
119
#endif
120

121
#if (defined(CONFIG_KM_PIGGY4_88E6061)|defined(CONFIG_KM_PIGGY4_88E6352))
122
/*
H
Holger Brunck 已提交
123 124
 * All boards with PIGGY4 connected via a simple switch have ethernet always
 * present.
125 126 127 128 129 130
 */
int ethernet_present(void)
{
	return 1;
}
#else
131 132 133 134 135
int ethernet_present(void)
{
	uchar	buf;
	int	ret = 0;

136
	if (i2c_read(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
137
		printf("%s: Error reading Boco\n", __func__);
138 139
		return -1;
	}
140
	if ((buf & MASK_RBX_PGY_PRESENT) == MASK_RBX_PGY_PRESENT)
141
		ret = 1;
142

143 144
	return ret;
}
145
#endif
146

147
static int initialize_unit_leds(void)
148 149
{
	/*
150
	 * Init the unit LEDs per default they all are
151 152 153 154
	 * ok apart from bootstat
	 */
	uchar buf;

155
	if (i2c_read(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
156 157 158
		printf("%s: Error reading Boco\n", __func__);
		return -1;
	}
159 160
	buf |= MASK_WRL_UNITRUN;
	if (i2c_write(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
161 162 163 164 165 166
		printf("%s: Error writing Boco\n", __func__);
		return -1;
	}
	return 0;
}

167
static void set_bootcount_addr(void)
168 169 170 171 172 173 174 175
{
	uchar buf[32];
	unsigned int bootcountaddr;
	bootcountaddr = gd->ram_size - BOOTCOUNT_ADDR;
	sprintf((char *)buf, "0x%x", bootcountaddr);
	setenv("bootcountaddr", (char *)buf);
}

176 177
int misc_init_r(void)
{
178
#if defined(CONFIG_KM_MGCOGE3UN)
179 180 181 182 183
	char *wait_for_ne;
	wait_for_ne = getenv("waitforne");
	if (wait_for_ne != NULL) {
		if (strcmp(wait_for_ne, "true") == 0) {
			int cnt = 0;
184
			int abort = 0;
185 186
			puts("NE go: ");
			while (startup_allowed() == 0) {
187 188 189 190 191
				if (tstc()) {
					(void) getc(); /* consume input */
					abort = 1;
					break;
				}
192 193 194 195 196 197 198 199 200
				udelay(200000);
				cnt++;
				if (cnt == 5)
					puts("wait\b\b\b\b");
				if (cnt == 10) {
					cnt = 0;
					puts("    \b\b\b\b");
				}
			}
201 202 203 204
			if (abort == 1)
				printf("\nAbort waiting for ne\n");
			else
				puts("OK\n");
205 206 207
		}
	}
#endif
208 209

	initialize_unit_leds();
210 211
	set_km_env();
	set_bootcount_addr();
212 213 214
	return 0;
}

215
int board_early_init_f(void)
216
{
217
#if defined(CONFIG_SYS_I2C_SOFT)
218 219
	u32 tmp;

220 221 222 223
	/* set the 2 bitbang i2c pins as output gpios */
	tmp = readl(KW_GPIO0_BASE + 4);
	writel(tmp & (~KM_KIRKWOOD_SOFT_I2C_GPIOS) , KW_GPIO0_BASE + 4);
#endif
224 225
	/* adjust SDRAM size for bank 0 */
	kw_sdram_size_adjust(0);
226
	kirkwood_mpp_conf(kwmpp_config, NULL);
227 228
	return 0;
}
229

230 231 232 233 234 235 236
int board_init(void)
{
	/* address of boot parameters */
	gd->bd->bi_boot_params = kw_sdram_bar(0) + 0x100;

	/*
	 * The KM_FLASH_GPIO_PIN switches between using a
237 238 239
	 * NAND or a SPI FLASH. Set this pin on start
	 * to NAND mode.
	 */
240 241
	kw_gpio_set_valid(KM_FLASH_GPIO_PIN, 1);
	kw_gpio_direction_output(KM_FLASH_GPIO_PIN, 1);
242

243
#if defined(CONFIG_SYS_I2C_SOFT)
244 245 246 247 248 249
	/*
	 * Reinit the GPIO for I2C Bitbang driver so that the now
	 * available gpio framework is consistent. The calls to
	 * direction output in are not necessary, they are already done in
	 * board_early_init_f
	 */
250 251
	kw_gpio_set_valid(KM_KIRKWOOD_SDA_PIN, 1);
	kw_gpio_set_valid(KM_KIRKWOOD_SCL_PIN, 1);
252
#endif
253

254
#if defined(CONFIG_SYS_EEPROM_WREN)
255 256
	kw_gpio_set_valid(KM_KIRKWOOD_ENV_WP, 38);
	kw_gpio_direction_output(KM_KIRKWOOD_ENV_WP, 1);
257
#endif
258

259 260 261 262 263 264 265 266 267
#if defined(CONFIG_KM_FPGA_CONFIG)
	trigger_fpga_config();
#endif

	return 0;
}

int board_late_init(void)
{
268 269 270 271 272 273 274 275 276 277 278 279 280
#if defined(CONFIG_KMCOGE5UN)
/* I/O pin to erase flash RGPP09 = MPP43 */
#define KM_FLASH_ERASE_ENABLE	43
	u8 dip_switch = kw_gpio_get_value(KM_FLASH_ERASE_ENABLE);

	/* if pin 1 do full erase */
	if (dip_switch != 0) {
		/* start bootloader */
		puts("DIP:   Enabled\n");
		setenv("actual_bank", "0");
	}
#endif

281 282 283 284 285
#if defined(CONFIG_KM_FPGA_CONFIG)
	wait_for_fpga_config();
	fpga_reset();
	toggle_eeprom_spi_bus();
#endif
286 287 288
	return 0;
}

289
int board_spi_claim_bus(struct spi_slave *slave)
290
{
291
	kw_gpio_set_value(KM_FLASH_GPIO_PIN, 0);
292 293 294 295

	return 0;
}

296 297 298 299
void board_spi_release_bus(struct spi_slave *slave)
{
	kw_gpio_set_value(KM_FLASH_GPIO_PIN, 1);
}
300

301
#if (defined(CONFIG_KM_PIGGY4_88E6061))
302

303 304 305 306 307
#define	PHY_LED_SEL_REG		0x18
#define PHY_LED0_LINK		(0x5)
#define PHY_LED1_ACT		(0x8<<4)
#define PHY_LED2_INT		(0xe<<8)
#define	PHY_SPEC_CTRL_REG	0x1c
308
#define PHY_RGMII_CLK_STABLE	(0x1<<10)
309
#define PHY_CLSA		(0x1<<1)
310 311 312 313 314 315 316 317 318 319 320

/* Configure and enable MV88E3018 PHY */
void reset_phy(void)
{
	char *name = "egiga0";
	unsigned short reg;

	if (miiphy_set_current_dev(name))
		return;

	/* RGMII clk transition on data stable */
321
	if (!miiphy_read(name, CONFIG_PHY_BASE_ADR, PHY_SPEC_CTRL_REG, &reg))
322
		printf("Error reading PHY spec ctrl reg\n");
323 324
	if (!miiphy_write(name, CONFIG_PHY_BASE_ADR, PHY_SPEC_CTRL_REG,
		reg | PHY_RGMII_CLK_STABLE | PHY_CLSA))
325 326 327
		printf("Error writing PHY spec ctrl reg\n");

	/* leds setup */
328 329
	if (!miiphy_write(name, CONFIG_PHY_BASE_ADR, PHY_LED_SEL_REG,
		PHY_LED0_LINK | PHY_LED1_ACT | PHY_LED2_INT))
330 331 332 333 334
		printf("Error writing PHY LED reg\n");

	/* reset the phy */
	miiphy_reset(name, CONFIG_PHY_BASE_ADR);
}
335 336 337 338 339 340 341
#elif defined(CONFIG_KM_PIGGY4_88E6352)

#include <mv88e6352.h>

#if defined(CONFIG_KM_NUSA)
struct mv88e_sw_reg extsw_conf[] = {
	/*
342
	 * port 0, PIGGY4, autoneg
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
	 * first the fix for the 1000Mbits Autoneg, this is from
	 * a Marvell errata, the regs are undocumented
	 */
	{ PHY(0), PHY_PAGE, AN1000FIX_PAGE },
	{ PHY(0), PHY_STATUS, AN1000FIX },
	{ PHY(0), PHY_PAGE, 0 },
	/* now the real port and phy configuration */
	{ PORT(0), PORT_PHY, NO_SPEED_FOR },
	{ PORT(0), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
	{ PHY(0), PHY_1000_CTRL, NO_ADV },
	{ PHY(0), PHY_SPEC_CTRL, AUTO_MDIX_EN },
	{ PHY(0), PHY_CTRL, PHY_100_MBPS | AUTONEG_EN | AUTONEG_RST |
		FULL_DUPLEX },
	/* port 1, unused */
	{ PORT(1), PORT_CTRL, PORT_DIS },
	{ PHY(1), PHY_CTRL, PHY_PWR_DOWN },
	{ PHY(1), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
	/* port 2, unused */
	{ PORT(2), PORT_CTRL, PORT_DIS },
	{ PHY(2), PHY_CTRL, PHY_PWR_DOWN },
	{ PHY(2), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
	/* port 3, unused */
	{ PORT(3), PORT_CTRL, PORT_DIS },
	{ PHY(3), PHY_CTRL, PHY_PWR_DOWN },
	{ PHY(3), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
	/* port 4, ICNEV, SerDes, SGMII */
	{ PORT(4), PORT_STATUS, NO_PHY_DETECT },
	{ PORT(4), PORT_PHY, SPEED_1000_FOR },
	{ PORT(4), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
	{ PHY(4), PHY_CTRL, PHY_PWR_DOWN },
	{ PHY(4), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
	/* port 5, CPU_RGMII */
	{ PORT(5), PORT_PHY, RX_RGMII_TIM | TX_RGMII_TIM | FLOW_CTRL_EN |
		FLOW_CTRL_FOR | LINK_VAL | LINK_FOR | FULL_DPX |
		FULL_DPX_FOR | SPEED_1000_FOR },
	{ PORT(5), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
	/* port 6, unused, this port has no phy */
	{ PORT(6), PORT_CTRL, PORT_DIS },
};
#else
struct mv88e_sw_reg extsw_conf[] = {};
#endif

void reset_phy(void)
{
#if defined(CONFIG_KM_MVEXTSW_ADDR)
	char *name = "egiga0";

	if (miiphy_set_current_dev(name))
		return;

	mv88e_sw_program(name, CONFIG_KM_MVEXTSW_ADDR, extsw_conf,
		ARRAY_SIZE(extsw_conf));
	mv88e_sw_reset(name, CONFIG_KM_MVEXTSW_ADDR);
#endif
}

400 401
#else
/* Configure and enable MV88E1118 PHY on the piggy*/
402 403 404 405 406 407 408 409 410 411
void reset_phy(void)
{
	char *name = "egiga0";

	if (miiphy_set_current_dev(name))
		return;

	/* reset the phy */
	miiphy_reset(name, CONFIG_PHY_BASE_ADR);
}
412 413
#endif

414 415

#if defined(CONFIG_HUSH_INIT_VAR)
416
int hush_init_var(void)
417
{
418
	ivm_read_eeprom();
419 420 421 422
	return 0;
}
#endif

423
#if defined(CONFIG_SYS_I2C_SOFT)
424
void set_sda(int state)
425 426 427 428 429
{
	I2C_ACTIVE;
	I2C_SDA(state);
}

430
void set_scl(int state)
431 432 433 434
{
	I2C_SCL(state);
}

435
int get_sda(void)
436 437 438 439 440
{
	I2C_TRISTATE;
	return I2C_READ;
}

441
int get_scl(void)
442
{
443
	return kw_gpio_get_value(KM_KIRKWOOD_SCL_PIN) ? 1 : 0;
444 445 446
}
#endif

447 448 449 450 451 452 453
#if defined(CONFIG_POST)

#define KM_POST_EN_L	44
#define POST_WORD_OFF	8

int post_hotkeys_pressed(void)
{
454 455 456
#if defined(CONFIG_KM_COGE5UN)
	return kw_gpio_get_value(KM_POST_EN_L);
#else
457
	return !kw_gpio_get_value(KM_POST_EN_L);
458
#endif
459 460 461 462
}

ulong post_word_load(void)
{
H
Holger Brunck 已提交
463
	void* addr = (void *) (gd->ram_size - BOOTCOUNT_ADDR + POST_WORD_OFF);
464 465 466 467 468
	return in_le32(addr);

}
void post_word_store(ulong value)
{
H
Holger Brunck 已提交
469
	void* addr = (void *) (gd->ram_size - BOOTCOUNT_ADDR + POST_WORD_OFF);
470 471 472 473 474 475 476 477 478 479 480 481 482 483
	out_le32(addr, value);
}

int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
{
	*vstart = CONFIG_SYS_SDRAM_BASE;

	/* we go up to relocation plus a 1 MB margin */
	*size = CONFIG_SYS_TEXT_BASE - (1<<20);

	return 0;
}
#endif

484
#if defined(CONFIG_SYS_EEPROM_WREN)
485
int eeprom_write_enable(unsigned dev_addr, int state)
486
{
487
	kw_gpio_set_value(KM_KIRKWOOD_ENV_WP, !state);
488

489
	return !kw_gpio_get_value(KM_KIRKWOOD_ENV_WP);
490 491
}
#endif