167fa8c25SHeiko Schocher /*
267fa8c25SHeiko Schocher * (C) Copyright 2009
367fa8c25SHeiko Schocher * Marvell Semiconductor <www.marvell.com>
467fa8c25SHeiko Schocher * Prafulla Wadaskar <prafulla@marvell.com>
567fa8c25SHeiko Schocher *
667fa8c25SHeiko Schocher * (C) Copyright 2009
767fa8c25SHeiko Schocher * Stefan Roese, DENX Software Engineering, sr@denx.de.
867fa8c25SHeiko Schocher *
967fa8c25SHeiko Schocher * (C) Copyright 2010
1067fa8c25SHeiko Schocher * Heiko Schocher, DENX Software Engineering, hs@denx.de.
1167fa8c25SHeiko Schocher *
121a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
1367fa8c25SHeiko Schocher */
1467fa8c25SHeiko Schocher
1567fa8c25SHeiko Schocher #include <common.h>
1667fa8c25SHeiko Schocher #include <i2c.h>
1767fa8c25SHeiko Schocher #include <nand.h>
1867fa8c25SHeiko Schocher #include <netdev.h>
1967fa8c25SHeiko Schocher #include <miiphy.h>
200c25defcSValentin Longchamp #include <spi.h>
2167fa8c25SHeiko Schocher #include <asm/io.h>
22a7efd719SLei Wen #include <asm/arch/cpu.h>
233dc23f78SStefan Roese #include <asm/arch/soc.h>
2467fa8c25SHeiko Schocher #include <asm/arch/mpp.h>
2567fa8c25SHeiko Schocher
2667fa8c25SHeiko Schocher #include "../common/common.h"
2767fa8c25SHeiko Schocher
2867fa8c25SHeiko Schocher DECLARE_GLOBAL_DATA_PTR;
2967fa8c25SHeiko Schocher
308612b701SHolger Brunck /*
318612b701SHolger Brunck * BOCO FPGA definitions
328612b701SHolger Brunck */
338612b701SHolger Brunck #define BOCO 0x10
348612b701SHolger Brunck #define REG_CTRL_H 0x02
358612b701SHolger Brunck #define MASK_WRL_UNITRUN 0x01
368612b701SHolger Brunck #define MASK_RBX_PGY_PRESENT 0x40
378612b701SHolger Brunck #define REG_IRQ_CIRQ2 0x2d
388612b701SHolger Brunck #define MASK_RBI_DEFECT_16 0x01
398612b701SHolger Brunck
409ff739e4STobias Müller /*
419ff739e4STobias Müller * PHY registers definitions
429ff739e4STobias Müller */
439ff739e4STobias Müller #define PHY_MARVELL_OUI 0x5043
449ff739e4STobias Müller #define PHY_MARVELL_88E1118_MODEL 0x0022
459ff739e4STobias Müller #define PHY_MARVELL_88E1118R_MODEL 0x0024
469ff739e4STobias Müller
479ff739e4STobias Müller #define PHY_MARVELL_PAGE_REG 0x0016
489ff739e4STobias Müller #define PHY_MARVELL_DEFAULT_PAGE 0x0000
499ff739e4STobias Müller
509ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_PAGE 0x0003
519ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_REG 0x0010
529ff739e4STobias Müller
539ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_RESERVED 0x1000
549ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_LED0_1000MB (0x7<<0)
559ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_LED1_ACT (0x3<<4)
569ff739e4STobias Müller #define PHY_MARVELL_88E1118R_LED_CTRL_LED2_LINK (0x0<<8)
579ff739e4STobias Müller
58e23fde7dSHolger Brunck /* I/O pin to erase flash RGPP09 = MPP43 */
59e23fde7dSHolger Brunck #define KM_FLASH_ERASE_ENABLE 43
60e23fde7dSHolger Brunck
6167fa8c25SHeiko Schocher /* Multi-Purpose Pins Functionality configuration */
629d86f0c3SAlbert ARIBAUD static const u32 kwmpp_config[] = {
6367fa8c25SHeiko Schocher MPP0_NF_IO2,
6467fa8c25SHeiko Schocher MPP1_NF_IO3,
6567fa8c25SHeiko Schocher MPP2_NF_IO4,
6667fa8c25SHeiko Schocher MPP3_NF_IO5,
6767fa8c25SHeiko Schocher MPP4_NF_IO6,
6867fa8c25SHeiko Schocher MPP5_NF_IO7,
6967fa8c25SHeiko Schocher MPP6_SYSRST_OUTn,
709c134e18SGerlando Falauto #if defined(KM_PCIE_RESET_MPP7)
719c134e18SGerlando Falauto MPP7_GPO,
729c134e18SGerlando Falauto #else
7367fa8c25SHeiko Schocher MPP7_PEX_RST_OUTn,
749c134e18SGerlando Falauto #endif
75ea818dbbSHeiko Schocher #if defined(CONFIG_SYS_I2C_SOFT)
7667fa8c25SHeiko Schocher MPP8_GPIO, /* SDA */
7767fa8c25SHeiko Schocher MPP9_GPIO, /* SCL */
7867fa8c25SHeiko Schocher #endif
7967fa8c25SHeiko Schocher MPP10_UART0_TXD,
8067fa8c25SHeiko Schocher MPP11_UART0_RXD,
8167fa8c25SHeiko Schocher MPP12_GPO, /* Reserved */
8267fa8c25SHeiko Schocher MPP13_UART1_TXD,
8367fa8c25SHeiko Schocher MPP14_UART1_RXD,
8467fa8c25SHeiko Schocher MPP15_GPIO, /* Not used */
8567fa8c25SHeiko Schocher MPP16_GPIO, /* Not used */
8667fa8c25SHeiko Schocher MPP17_GPIO, /* Reserved */
8767fa8c25SHeiko Schocher MPP18_NF_IO0,
8867fa8c25SHeiko Schocher MPP19_NF_IO1,
8967fa8c25SHeiko Schocher MPP20_GPIO,
9067fa8c25SHeiko Schocher MPP21_GPIO,
9167fa8c25SHeiko Schocher MPP22_GPIO,
9267fa8c25SHeiko Schocher MPP23_GPIO,
9367fa8c25SHeiko Schocher MPP24_GPIO,
9467fa8c25SHeiko Schocher MPP25_GPIO,
9567fa8c25SHeiko Schocher MPP26_GPIO,
9667fa8c25SHeiko Schocher MPP27_GPIO,
9767fa8c25SHeiko Schocher MPP28_GPIO,
9867fa8c25SHeiko Schocher MPP29_GPIO,
9967fa8c25SHeiko Schocher MPP30_GPIO,
10067fa8c25SHeiko Schocher MPP31_GPIO,
10167fa8c25SHeiko Schocher MPP32_GPIO,
10267fa8c25SHeiko Schocher MPP33_GPIO,
10367fa8c25SHeiko Schocher MPP34_GPIO, /* CDL1 (input) */
10467fa8c25SHeiko Schocher MPP35_GPIO, /* CDL2 (input) */
10567fa8c25SHeiko Schocher MPP36_GPIO, /* MAIN_IRQ (input) */
10667fa8c25SHeiko Schocher MPP37_GPIO, /* BOARD_LED */
10767fa8c25SHeiko Schocher MPP38_GPIO, /* Piggy3 LED[1] */
10867fa8c25SHeiko Schocher MPP39_GPIO, /* Piggy3 LED[2] */
10967fa8c25SHeiko Schocher MPP40_GPIO, /* Piggy3 LED[3] */
11067fa8c25SHeiko Schocher MPP41_GPIO, /* Piggy3 LED[4] */
11167fa8c25SHeiko Schocher MPP42_GPIO, /* Piggy3 LED[5] */
11267fa8c25SHeiko Schocher MPP43_GPIO, /* Piggy3 LED[6] */
11344097e26SHeiko Schocher MPP44_GPIO, /* Piggy3 LED[7], BIST_EN_L */
11467fa8c25SHeiko Schocher MPP45_GPIO, /* Piggy3 LED[8] */
11567fa8c25SHeiko Schocher MPP46_GPIO, /* Reserved */
11667fa8c25SHeiko Schocher MPP47_GPIO, /* Reserved */
11767fa8c25SHeiko Schocher MPP48_GPIO, /* Reserved */
11867fa8c25SHeiko Schocher MPP49_GPIO, /* SW_INTOUTn */
11967fa8c25SHeiko Schocher 0
12067fa8c25SHeiko Schocher };
12167fa8c25SHeiko Schocher
1220bb95a68SValentin Longchamp static uchar ivm_content[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
1230bb95a68SValentin Longchamp
124f945439aSHolger Brunck #if defined(CONFIG_KM_MGCOGE3UN)
1258612b701SHolger Brunck /*
1268612b701SHolger Brunck * Wait for startup OK from mgcoge3ne
1278612b701SHolger Brunck */
startup_allowed(void)128aef0bdc0SHolger Brunck static int startup_allowed(void)
1298612b701SHolger Brunck {
1308612b701SHolger Brunck unsigned char buf;
1318612b701SHolger Brunck
1328612b701SHolger Brunck /*
1338612b701SHolger Brunck * Read CIRQ16 bit (bit 0)
1348612b701SHolger Brunck */
1358612b701SHolger Brunck if (i2c_read(BOCO, REG_IRQ_CIRQ2, 1, &buf, 1) != 0)
1368612b701SHolger Brunck printf("%s: Error reading Boco\n", __func__);
1378612b701SHolger Brunck else
1388612b701SHolger Brunck if ((buf & MASK_RBI_DEFECT_16) == MASK_RBI_DEFECT_16)
1398612b701SHolger Brunck return 1;
1408612b701SHolger Brunck return 0;
1418612b701SHolger Brunck }
14201fa4e8cSValentin Longchamp #endif
1438612b701SHolger Brunck
144f945439aSHolger Brunck #if (defined(CONFIG_KM_PIGGY4_88E6061)|defined(CONFIG_KM_PIGGY4_88E6352))
1458612b701SHolger Brunck /*
1468170aefcSHolger Brunck * All boards with PIGGY4 connected via a simple switch have ethernet always
1478170aefcSHolger Brunck * present.
1488612b701SHolger Brunck */
ethernet_present(void)1498612b701SHolger Brunck int ethernet_present(void)
1508612b701SHolger Brunck {
1518612b701SHolger Brunck return 1;
1528612b701SHolger Brunck }
1538612b701SHolger Brunck #else
ethernet_present(void)15467fa8c25SHeiko Schocher int ethernet_present(void)
15567fa8c25SHeiko Schocher {
15667fa8c25SHeiko Schocher uchar buf;
15767fa8c25SHeiko Schocher int ret = 0;
15867fa8c25SHeiko Schocher
1598612b701SHolger Brunck if (i2c_read(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
160b11f53f3SHeiko Schocher printf("%s: Error reading Boco\n", __func__);
16167fa8c25SHeiko Schocher return -1;
16267fa8c25SHeiko Schocher }
1638612b701SHolger Brunck if ((buf & MASK_RBX_PGY_PRESENT) == MASK_RBX_PGY_PRESENT)
16467fa8c25SHeiko Schocher ret = 1;
165b11f53f3SHeiko Schocher
16667fa8c25SHeiko Schocher return ret;
16767fa8c25SHeiko Schocher }
1688612b701SHolger Brunck #endif
16967fa8c25SHeiko Schocher
initialize_unit_leds(void)17074ae612fSHolger Brunck static int initialize_unit_leds(void)
171731b9680SHeiko Schocher {
172731b9680SHeiko Schocher /*
1738612b701SHolger Brunck * Init the unit LEDs per default they all are
174731b9680SHeiko Schocher * ok apart from bootstat
175731b9680SHeiko Schocher */
176731b9680SHeiko Schocher uchar buf;
177731b9680SHeiko Schocher
1788612b701SHolger Brunck if (i2c_read(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
179731b9680SHeiko Schocher printf("%s: Error reading Boco\n", __func__);
180731b9680SHeiko Schocher return -1;
181731b9680SHeiko Schocher }
1828612b701SHolger Brunck buf |= MASK_WRL_UNITRUN;
1838612b701SHolger Brunck if (i2c_write(BOCO, REG_CTRL_H, 1, &buf, 1) != 0) {
184731b9680SHeiko Schocher printf("%s: Error writing Boco\n", __func__);
185731b9680SHeiko Schocher return -1;
186731b9680SHeiko Schocher }
187731b9680SHeiko Schocher return 0;
188731b9680SHeiko Schocher }
189731b9680SHeiko Schocher
set_bootcount_addr(void)19074ae612fSHolger Brunck static void set_bootcount_addr(void)
19122c67d08SValentin Longchamp {
19222c67d08SValentin Longchamp uchar buf[32];
19322c67d08SValentin Longchamp unsigned int bootcountaddr;
19422c67d08SValentin Longchamp bootcountaddr = gd->ram_size - BOOTCOUNT_ADDR;
19522c67d08SValentin Longchamp sprintf((char *)buf, "0x%x", bootcountaddr);
196382bee57SSimon Glass env_set("bootcountaddr", (char *)buf);
19722c67d08SValentin Longchamp }
19822c67d08SValentin Longchamp
misc_init_r(void)19967fa8c25SHeiko Schocher int misc_init_r(void)
20067fa8c25SHeiko Schocher {
201f945439aSHolger Brunck #if defined(CONFIG_KM_MGCOGE3UN)
2028612b701SHolger Brunck char *wait_for_ne;
203e23fde7dSHolger Brunck u8 dip_switch = kw_gpio_get_value(KM_FLASH_ERASE_ENABLE);
204*00caae6dSSimon Glass wait_for_ne = env_get("waitforne");
205e23fde7dSHolger Brunck
206e23fde7dSHolger Brunck if ((wait_for_ne != NULL) && (dip_switch == 0)) {
2078612b701SHolger Brunck if (strcmp(wait_for_ne, "true") == 0) {
2088612b701SHolger Brunck int cnt = 0;
2096264800eSHolger Brunck int abort = 0;
2108612b701SHolger Brunck puts("NE go: ");
2118612b701SHolger Brunck while (startup_allowed() == 0) {
2126264800eSHolger Brunck if (tstc()) {
2136264800eSHolger Brunck (void) getc(); /* consume input */
2146264800eSHolger Brunck abort = 1;
2156264800eSHolger Brunck break;
2166264800eSHolger Brunck }
2178612b701SHolger Brunck udelay(200000);
2188612b701SHolger Brunck cnt++;
2198612b701SHolger Brunck if (cnt == 5)
2208612b701SHolger Brunck puts("wait\b\b\b\b");
2218612b701SHolger Brunck if (cnt == 10) {
2228612b701SHolger Brunck cnt = 0;
2238612b701SHolger Brunck puts(" \b\b\b\b");
2248612b701SHolger Brunck }
2258612b701SHolger Brunck }
2266264800eSHolger Brunck if (abort == 1)
2276264800eSHolger Brunck printf("\nAbort waiting for ne\n");
2286264800eSHolger Brunck else
2298612b701SHolger Brunck puts("OK\n");
2308612b701SHolger Brunck }
2318612b701SHolger Brunck }
2328612b701SHolger Brunck #endif
233731b9680SHeiko Schocher
23460c4ae00SValentin Longchamp ivm_read_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
2350bb95a68SValentin Longchamp
236731b9680SHeiko Schocher initialize_unit_leds();
23722c67d08SValentin Longchamp set_km_env();
23822c67d08SValentin Longchamp set_bootcount_addr();
23967fa8c25SHeiko Schocher return 0;
24067fa8c25SHeiko Schocher }
24167fa8c25SHeiko Schocher
board_early_init_f(void)2426b0ccc3bSHeiko Schocher int board_early_init_f(void)
24367fa8c25SHeiko Schocher {
244ea818dbbSHeiko Schocher #if defined(CONFIG_SYS_I2C_SOFT)
24567fa8c25SHeiko Schocher u32 tmp;
24667fa8c25SHeiko Schocher
247c471d848SHolger Brunck /* set the 2 bitbang i2c pins as output gpios */
248d5c5132fSStefan Roese tmp = readl(MVEBU_GPIO0_BASE + 4);
249d5c5132fSStefan Roese writel(tmp & (~KM_KIRKWOOD_SOFT_I2C_GPIOS) , MVEBU_GPIO0_BASE + 4);
250c471d848SHolger Brunck #endif
2513a5b9fe6SHolger Brunck /* adjust SDRAM size for bank 0 */
25296c5f081SStefan Roese mvebu_sdram_size_adjust(0);
253c471d848SHolger Brunck kirkwood_mpp_conf(kwmpp_config, NULL);
2546b0ccc3bSHeiko Schocher return 0;
2556b0ccc3bSHeiko Schocher }
2566b0ccc3bSHeiko Schocher
board_init(void)2576b0ccc3bSHeiko Schocher int board_init(void)
2586b0ccc3bSHeiko Schocher {
2596b0ccc3bSHeiko Schocher /* address of boot parameters */
26096c5f081SStefan Roese gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
2616b0ccc3bSHeiko Schocher
262c471d848SHolger Brunck /*
263c471d848SHolger Brunck * The KM_FLASH_GPIO_PIN switches between using a
264c471d848SHolger Brunck * NAND or a SPI FLASH. Set this pin on start
265c471d848SHolger Brunck * to NAND mode.
266c471d848SHolger Brunck */
267c471d848SHolger Brunck kw_gpio_set_valid(KM_FLASH_GPIO_PIN, 1);
268c471d848SHolger Brunck kw_gpio_direction_output(KM_FLASH_GPIO_PIN, 1);
269c471d848SHolger Brunck
270ea818dbbSHeiko Schocher #if defined(CONFIG_SYS_I2C_SOFT)
271c471d848SHolger Brunck /*
272c471d848SHolger Brunck * Reinit the GPIO for I2C Bitbang driver so that the now
273c471d848SHolger Brunck * available gpio framework is consistent. The calls to
274c471d848SHolger Brunck * direction output in are not necessary, they are already done in
275c471d848SHolger Brunck * board_early_init_f
276c471d848SHolger Brunck */
277c471d848SHolger Brunck kw_gpio_set_valid(KM_KIRKWOOD_SDA_PIN, 1);
278c471d848SHolger Brunck kw_gpio_set_valid(KM_KIRKWOOD_SCL_PIN, 1);
279c471d848SHolger Brunck #endif
280c471d848SHolger Brunck
281c471d848SHolger Brunck #if defined(CONFIG_SYS_EEPROM_WREN)
282c471d848SHolger Brunck kw_gpio_set_valid(KM_KIRKWOOD_ENV_WP, 38);
283c471d848SHolger Brunck kw_gpio_direction_output(KM_KIRKWOOD_ENV_WP, 1);
284c471d848SHolger Brunck #endif
285c471d848SHolger Brunck
286b37f7724SValentin Longchamp #if defined(CONFIG_KM_FPGA_CONFIG)
287b37f7724SValentin Longchamp trigger_fpga_config();
288b37f7724SValentin Longchamp #endif
289b37f7724SValentin Longchamp
290b37f7724SValentin Longchamp return 0;
291b37f7724SValentin Longchamp }
292b37f7724SValentin Longchamp
board_late_init(void)293b37f7724SValentin Longchamp int board_late_init(void)
294b37f7724SValentin Longchamp {
29530f9ad77SValentin Longchamp #if (defined(CONFIG_KM_COGE5UN) | defined(CONFIG_KM_MGCOGE3UN))
296b8cf7cc8SThomas Herzmann u8 dip_switch = kw_gpio_get_value(KM_FLASH_ERASE_ENABLE);
297b8cf7cc8SThomas Herzmann
298b8cf7cc8SThomas Herzmann /* if pin 1 do full erase */
299b8cf7cc8SThomas Herzmann if (dip_switch != 0) {
300b8cf7cc8SThomas Herzmann /* start bootloader */
301b8cf7cc8SThomas Herzmann puts("DIP: Enabled\n");
302382bee57SSimon Glass env_set("actual_bank", "0");
303b8cf7cc8SThomas Herzmann }
304b8cf7cc8SThomas Herzmann #endif
305b8cf7cc8SThomas Herzmann
306b37f7724SValentin Longchamp #if defined(CONFIG_KM_FPGA_CONFIG)
307b37f7724SValentin Longchamp wait_for_fpga_config();
308b37f7724SValentin Longchamp fpga_reset();
309b37f7724SValentin Longchamp toggle_eeprom_spi_bus();
310b37f7724SValentin Longchamp #endif
31167fa8c25SHeiko Schocher return 0;
31267fa8c25SHeiko Schocher }
31367fa8c25SHeiko Schocher
board_spi_claim_bus(struct spi_slave * slave)3140c25defcSValentin Longchamp int board_spi_claim_bus(struct spi_slave *slave)
31567fa8c25SHeiko Schocher {
3160c25defcSValentin Longchamp kw_gpio_set_value(KM_FLASH_GPIO_PIN, 0);
31767fa8c25SHeiko Schocher
31867fa8c25SHeiko Schocher return 0;
31967fa8c25SHeiko Schocher }
32067fa8c25SHeiko Schocher
board_spi_release_bus(struct spi_slave * slave)3210c25defcSValentin Longchamp void board_spi_release_bus(struct spi_slave *slave)
3220c25defcSValentin Longchamp {
3230c25defcSValentin Longchamp kw_gpio_set_value(KM_FLASH_GPIO_PIN, 1);
3240c25defcSValentin Longchamp }
32567fa8c25SHeiko Schocher
3266ef64861SHolger Brunck #if (defined(CONFIG_KM_PIGGY4_88E6061))
3278f2827fcSValentin Longchamp
328c1b8514aSValentin Longchamp #define PHY_LED_SEL_REG 0x18
3298f2827fcSValentin Longchamp #define PHY_LED0_LINK (0x5)
3308f2827fcSValentin Longchamp #define PHY_LED1_ACT (0x8<<4)
3318f2827fcSValentin Longchamp #define PHY_LED2_INT (0xe<<8)
332c1b8514aSValentin Longchamp #define PHY_SPEC_CTRL_REG 0x1c
3338f2827fcSValentin Longchamp #define PHY_RGMII_CLK_STABLE (0x1<<10)
3348f2827fcSValentin Longchamp #define PHY_CLSA (0x1<<1)
3358f2827fcSValentin Longchamp
3368f2827fcSValentin Longchamp /* Configure and enable MV88E3018 PHY */
reset_phy(void)3378f2827fcSValentin Longchamp void reset_phy(void)
3388f2827fcSValentin Longchamp {
3398f2827fcSValentin Longchamp char *name = "egiga0";
3408f2827fcSValentin Longchamp unsigned short reg;
3418f2827fcSValentin Longchamp
3428f2827fcSValentin Longchamp if (miiphy_set_current_dev(name))
3438f2827fcSValentin Longchamp return;
3448f2827fcSValentin Longchamp
3458f2827fcSValentin Longchamp /* RGMII clk transition on data stable */
346fa6e0ecbSHolger Brunck if (miiphy_read(name, CONFIG_PHY_BASE_ADR, PHY_SPEC_CTRL_REG, ®))
3478f2827fcSValentin Longchamp printf("Error reading PHY spec ctrl reg\n");
348fa6e0ecbSHolger Brunck if (miiphy_write(name, CONFIG_PHY_BASE_ADR, PHY_SPEC_CTRL_REG,
349c1b8514aSValentin Longchamp reg | PHY_RGMII_CLK_STABLE | PHY_CLSA))
3508f2827fcSValentin Longchamp printf("Error writing PHY spec ctrl reg\n");
3518f2827fcSValentin Longchamp
3528f2827fcSValentin Longchamp /* leds setup */
353fa6e0ecbSHolger Brunck if (miiphy_write(name, CONFIG_PHY_BASE_ADR, PHY_LED_SEL_REG,
354c1b8514aSValentin Longchamp PHY_LED0_LINK | PHY_LED1_ACT | PHY_LED2_INT))
3558f2827fcSValentin Longchamp printf("Error writing PHY LED reg\n");
3568f2827fcSValentin Longchamp
3578f2827fcSValentin Longchamp /* reset the phy */
3588f2827fcSValentin Longchamp miiphy_reset(name, CONFIG_PHY_BASE_ADR);
3598f2827fcSValentin Longchamp }
36052638c41SValentin Longchamp #elif defined(CONFIG_KM_PIGGY4_88E6352)
36152638c41SValentin Longchamp
36252638c41SValentin Longchamp #include <mv88e6352.h>
36352638c41SValentin Longchamp
36452638c41SValentin Longchamp #if defined(CONFIG_KM_NUSA)
36552638c41SValentin Longchamp struct mv88e_sw_reg extsw_conf[] = {
36652638c41SValentin Longchamp /*
36752638c41SValentin Longchamp * port 0, PIGGY4, autoneg
36852638c41SValentin Longchamp * first the fix for the 1000Mbits Autoneg, this is from
36952638c41SValentin Longchamp * a Marvell errata, the regs are undocumented
37052638c41SValentin Longchamp */
37152638c41SValentin Longchamp { PHY(0), PHY_PAGE, AN1000FIX_PAGE },
37252638c41SValentin Longchamp { PHY(0), PHY_STATUS, AN1000FIX },
37352638c41SValentin Longchamp { PHY(0), PHY_PAGE, 0 },
37452638c41SValentin Longchamp /* now the real port and phy configuration */
37552638c41SValentin Longchamp { PORT(0), PORT_PHY, NO_SPEED_FOR },
37652638c41SValentin Longchamp { PORT(0), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
37752638c41SValentin Longchamp { PHY(0), PHY_1000_CTRL, NO_ADV },
37852638c41SValentin Longchamp { PHY(0), PHY_SPEC_CTRL, AUTO_MDIX_EN },
37952638c41SValentin Longchamp { PHY(0), PHY_CTRL, PHY_100_MBPS | AUTONEG_EN | AUTONEG_RST |
38052638c41SValentin Longchamp FULL_DUPLEX },
38152638c41SValentin Longchamp /* port 1, unused */
38252638c41SValentin Longchamp { PORT(1), PORT_CTRL, PORT_DIS },
38352638c41SValentin Longchamp { PHY(1), PHY_CTRL, PHY_PWR_DOWN },
38452638c41SValentin Longchamp { PHY(1), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
38552638c41SValentin Longchamp /* port 2, unused */
38652638c41SValentin Longchamp { PORT(2), PORT_CTRL, PORT_DIS },
38752638c41SValentin Longchamp { PHY(2), PHY_CTRL, PHY_PWR_DOWN },
38852638c41SValentin Longchamp { PHY(2), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
38952638c41SValentin Longchamp /* port 3, unused */
39052638c41SValentin Longchamp { PORT(3), PORT_CTRL, PORT_DIS },
39152638c41SValentin Longchamp { PHY(3), PHY_CTRL, PHY_PWR_DOWN },
39252638c41SValentin Longchamp { PHY(3), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
39352638c41SValentin Longchamp /* port 4, ICNEV, SerDes, SGMII */
39452638c41SValentin Longchamp { PORT(4), PORT_STATUS, NO_PHY_DETECT },
39552638c41SValentin Longchamp { PORT(4), PORT_PHY, SPEED_1000_FOR },
39652638c41SValentin Longchamp { PORT(4), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
39752638c41SValentin Longchamp { PHY(4), PHY_CTRL, PHY_PWR_DOWN },
39852638c41SValentin Longchamp { PHY(4), PHY_SPEC_CTRL, SPEC_PWR_DOWN },
39952638c41SValentin Longchamp /* port 5, CPU_RGMII */
40052638c41SValentin Longchamp { PORT(5), PORT_PHY, RX_RGMII_TIM | TX_RGMII_TIM | FLOW_CTRL_EN |
40152638c41SValentin Longchamp FLOW_CTRL_FOR | LINK_VAL | LINK_FOR | FULL_DPX |
40252638c41SValentin Longchamp FULL_DPX_FOR | SPEED_1000_FOR },
40352638c41SValentin Longchamp { PORT(5), PORT_CTRL, FORWARDING | EGRS_FLD_ALL },
40452638c41SValentin Longchamp /* port 6, unused, this port has no phy */
40552638c41SValentin Longchamp { PORT(6), PORT_CTRL, PORT_DIS },
40652638c41SValentin Longchamp };
40752638c41SValentin Longchamp #else
40852638c41SValentin Longchamp struct mv88e_sw_reg extsw_conf[] = {};
40952638c41SValentin Longchamp #endif
41052638c41SValentin Longchamp
reset_phy(void)41152638c41SValentin Longchamp void reset_phy(void)
41252638c41SValentin Longchamp {
41352638c41SValentin Longchamp #if defined(CONFIG_KM_MVEXTSW_ADDR)
41452638c41SValentin Longchamp char *name = "egiga0";
41552638c41SValentin Longchamp
41652638c41SValentin Longchamp if (miiphy_set_current_dev(name))
41752638c41SValentin Longchamp return;
41852638c41SValentin Longchamp
41952638c41SValentin Longchamp mv88e_sw_program(name, CONFIG_KM_MVEXTSW_ADDR, extsw_conf,
42052638c41SValentin Longchamp ARRAY_SIZE(extsw_conf));
42152638c41SValentin Longchamp mv88e_sw_reset(name, CONFIG_KM_MVEXTSW_ADDR);
42252638c41SValentin Longchamp #endif
42352638c41SValentin Longchamp }
42452638c41SValentin Longchamp
4258f2827fcSValentin Longchamp #else
4268f2827fcSValentin Longchamp /* Configure and enable MV88E1118 PHY on the piggy*/
reset_phy(void)42767fa8c25SHeiko Schocher void reset_phy(void)
42867fa8c25SHeiko Schocher {
4299ff739e4STobias Müller unsigned int oui;
4309ff739e4STobias Müller unsigned char model, rev;
4319ff739e4STobias Müller
43267fa8c25SHeiko Schocher char *name = "egiga0";
43367fa8c25SHeiko Schocher
43467fa8c25SHeiko Schocher if (miiphy_set_current_dev(name))
43567fa8c25SHeiko Schocher return;
43667fa8c25SHeiko Schocher
43767fa8c25SHeiko Schocher /* reset the phy */
43867fa8c25SHeiko Schocher miiphy_reset(name, CONFIG_PHY_BASE_ADR);
4399ff739e4STobias Müller
4409ff739e4STobias Müller /* get PHY model */
4419ff739e4STobias Müller if (miiphy_info(name, CONFIG_PHY_BASE_ADR, &oui, &model, &rev))
4429ff739e4STobias Müller return;
4439ff739e4STobias Müller
4449ff739e4STobias Müller /* check for Marvell 88E1118R Gigabit PHY (PIGGY3) */
4459ff739e4STobias Müller if ((oui == PHY_MARVELL_OUI) &&
4469ff739e4STobias Müller (model == PHY_MARVELL_88E1118R_MODEL)) {
4479ff739e4STobias Müller /* set page register to 3 */
4489ff739e4STobias Müller if (miiphy_write(name, CONFIG_PHY_BASE_ADR,
4499ff739e4STobias Müller PHY_MARVELL_PAGE_REG,
4509ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_PAGE))
4519ff739e4STobias Müller printf("Error writing PHY page reg\n");
4529ff739e4STobias Müller
4539ff739e4STobias Müller /*
4549ff739e4STobias Müller * leds setup as printed on PCB:
4559ff739e4STobias Müller * LED2 (Link): 0x0 (On Link, Off No Link)
4569ff739e4STobias Müller * LED1 (Activity): 0x3 (On Activity, Off No Activity)
4579ff739e4STobias Müller * LED0 (Speed): 0x7 (On 1000 MBits, Off Else)
4589ff739e4STobias Müller */
4599ff739e4STobias Müller if (miiphy_write(name, CONFIG_PHY_BASE_ADR,
4609ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_REG,
4619ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_RESERVED |
4629ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_LED0_1000MB |
4639ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_LED1_ACT |
4649ff739e4STobias Müller PHY_MARVELL_88E1118R_LED_CTRL_LED2_LINK))
4659ff739e4STobias Müller printf("Error writing PHY LED reg\n");
4669ff739e4STobias Müller
4679ff739e4STobias Müller /* set page register back to 0 */
4689ff739e4STobias Müller if (miiphy_write(name, CONFIG_PHY_BASE_ADR,
4699ff739e4STobias Müller PHY_MARVELL_PAGE_REG,
4709ff739e4STobias Müller PHY_MARVELL_DEFAULT_PAGE))
4719ff739e4STobias Müller printf("Error writing PHY page reg\n");
4729ff739e4STobias Müller }
47367fa8c25SHeiko Schocher }
4748f2827fcSValentin Longchamp #endif
4758f2827fcSValentin Longchamp
47667fa8c25SHeiko Schocher
47767fa8c25SHeiko Schocher #if defined(CONFIG_HUSH_INIT_VAR)
hush_init_var(void)47867fa8c25SHeiko Schocher int hush_init_var(void)
47967fa8c25SHeiko Schocher {
4800bb95a68SValentin Longchamp ivm_analyze_eeprom(ivm_content, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
48167fa8c25SHeiko Schocher return 0;
48267fa8c25SHeiko Schocher }
48367fa8c25SHeiko Schocher #endif
48467fa8c25SHeiko Schocher
485ea818dbbSHeiko Schocher #if defined(CONFIG_SYS_I2C_SOFT)
set_sda(int state)48667fa8c25SHeiko Schocher void set_sda(int state)
48767fa8c25SHeiko Schocher {
48867fa8c25SHeiko Schocher I2C_ACTIVE;
48967fa8c25SHeiko Schocher I2C_SDA(state);
49067fa8c25SHeiko Schocher }
49167fa8c25SHeiko Schocher
set_scl(int state)49267fa8c25SHeiko Schocher void set_scl(int state)
49367fa8c25SHeiko Schocher {
49467fa8c25SHeiko Schocher I2C_SCL(state);
49567fa8c25SHeiko Schocher }
49667fa8c25SHeiko Schocher
get_sda(void)49767fa8c25SHeiko Schocher int get_sda(void)
49867fa8c25SHeiko Schocher {
49967fa8c25SHeiko Schocher I2C_TRISTATE;
50067fa8c25SHeiko Schocher return I2C_READ;
50167fa8c25SHeiko Schocher }
50267fa8c25SHeiko Schocher
get_scl(void)50367fa8c25SHeiko Schocher int get_scl(void)
50467fa8c25SHeiko Schocher {
50544097e26SHeiko Schocher return kw_gpio_get_value(KM_KIRKWOOD_SCL_PIN) ? 1 : 0;
50667fa8c25SHeiko Schocher }
50767fa8c25SHeiko Schocher #endif
50867fa8c25SHeiko Schocher
5099400f8faSValentin Longchamp #if defined(CONFIG_POST)
5109400f8faSValentin Longchamp
5119400f8faSValentin Longchamp #define KM_POST_EN_L 44
5129400f8faSValentin Longchamp #define POST_WORD_OFF 8
5139400f8faSValentin Longchamp
post_hotkeys_pressed(void)5149400f8faSValentin Longchamp int post_hotkeys_pressed(void)
5159400f8faSValentin Longchamp {
516d9354530SHolger Brunck #if defined(CONFIG_KM_COGE5UN)
517d9354530SHolger Brunck return kw_gpio_get_value(KM_POST_EN_L);
518d9354530SHolger Brunck #else
5199400f8faSValentin Longchamp return !kw_gpio_get_value(KM_POST_EN_L);
520d9354530SHolger Brunck #endif
5219400f8faSValentin Longchamp }
5229400f8faSValentin Longchamp
post_word_load(void)5239400f8faSValentin Longchamp ulong post_word_load(void)
5249400f8faSValentin Longchamp {
5256a23f311SHolger Brunck void* addr = (void *) (gd->ram_size - BOOTCOUNT_ADDR + POST_WORD_OFF);
5269400f8faSValentin Longchamp return in_le32(addr);
5279400f8faSValentin Longchamp
5289400f8faSValentin Longchamp }
post_word_store(ulong value)5299400f8faSValentin Longchamp void post_word_store(ulong value)
5309400f8faSValentin Longchamp {
5316a23f311SHolger Brunck void* addr = (void *) (gd->ram_size - BOOTCOUNT_ADDR + POST_WORD_OFF);
5329400f8faSValentin Longchamp out_le32(addr, value);
5339400f8faSValentin Longchamp }
5349400f8faSValentin Longchamp
arch_memory_test_prepare(u32 * vstart,u32 * size,phys_addr_t * phys_offset)5359400f8faSValentin Longchamp int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
5369400f8faSValentin Longchamp {
5379400f8faSValentin Longchamp *vstart = CONFIG_SYS_SDRAM_BASE;
5389400f8faSValentin Longchamp
5399400f8faSValentin Longchamp /* we go up to relocation plus a 1 MB margin */
5409400f8faSValentin Longchamp *size = CONFIG_SYS_TEXT_BASE - (1<<20);
5419400f8faSValentin Longchamp
5429400f8faSValentin Longchamp return 0;
5439400f8faSValentin Longchamp }
5449400f8faSValentin Longchamp #endif
5459400f8faSValentin Longchamp
54667fa8c25SHeiko Schocher #if defined(CONFIG_SYS_EEPROM_WREN)
eeprom_write_enable(unsigned dev_addr,int state)54767fa8c25SHeiko Schocher int eeprom_write_enable(unsigned dev_addr, int state)
54867fa8c25SHeiko Schocher {
54944097e26SHeiko Schocher kw_gpio_set_value(KM_KIRKWOOD_ENV_WP, !state);
55067fa8c25SHeiko Schocher
55144097e26SHeiko Schocher return !kw_gpio_get_value(KM_KIRKWOOD_ENV_WP);
55267fa8c25SHeiko Schocher }
55367fa8c25SHeiko Schocher #endif
554