156f86e39SMasahiro Yamada /*
256f86e39SMasahiro Yamada * (C) Copyright 2009
356f86e39SMasahiro Yamada * Marvell Semiconductor <www.marvell.com>
456f86e39SMasahiro Yamada * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
556f86e39SMasahiro Yamada *
656f86e39SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+
756f86e39SMasahiro Yamada */
856f86e39SMasahiro Yamada
956f86e39SMasahiro Yamada #include <common.h>
1056f86e39SMasahiro Yamada #include <netdev.h>
1156f86e39SMasahiro Yamada #include <asm/cache.h>
1256f86e39SMasahiro Yamada #include <asm/io.h>
1356f86e39SMasahiro Yamada #include <asm/arch/cpu.h>
1456f86e39SMasahiro Yamada #include <asm/arch/soc.h>
1556f86e39SMasahiro Yamada #include <mvebu_mmc.h>
1656f86e39SMasahiro Yamada
reset_cpu(unsigned long ignored)1756f86e39SMasahiro Yamada void reset_cpu(unsigned long ignored)
1856f86e39SMasahiro Yamada {
1956f86e39SMasahiro Yamada struct kwcpu_registers *cpureg =
2056f86e39SMasahiro Yamada (struct kwcpu_registers *)KW_CPU_REG_BASE;
2156f86e39SMasahiro Yamada
2256f86e39SMasahiro Yamada writel(readl(&cpureg->rstoutn_mask) | (1 << 2),
2356f86e39SMasahiro Yamada &cpureg->rstoutn_mask);
2456f86e39SMasahiro Yamada writel(readl(&cpureg->sys_soft_rst) | 1,
2556f86e39SMasahiro Yamada &cpureg->sys_soft_rst);
2656f86e39SMasahiro Yamada while (1) ;
2756f86e39SMasahiro Yamada }
2856f86e39SMasahiro Yamada
2956f86e39SMasahiro Yamada /*
3056f86e39SMasahiro Yamada * Window Size
3156f86e39SMasahiro Yamada * Used with the Base register to set the address window size and location.
3256f86e39SMasahiro Yamada * Must be programmed from LSB to MSB as sequence of ones followed by
3356f86e39SMasahiro Yamada * sequence of zeros. The number of ones specifies the size of the window in
3456f86e39SMasahiro Yamada * 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte).
3556f86e39SMasahiro Yamada * NOTE: A value of 0x0 specifies 64-KByte size.
3656f86e39SMasahiro Yamada */
kw_winctrl_calcsize(unsigned int sizeval)3756f86e39SMasahiro Yamada unsigned int kw_winctrl_calcsize(unsigned int sizeval)
3856f86e39SMasahiro Yamada {
3956f86e39SMasahiro Yamada int i;
4056f86e39SMasahiro Yamada unsigned int j = 0;
4156f86e39SMasahiro Yamada u32 val = sizeval >> 1;
4256f86e39SMasahiro Yamada
4356f86e39SMasahiro Yamada for (i = 0; val >= 0x10000; i++) {
4456f86e39SMasahiro Yamada j |= (1 << i);
4556f86e39SMasahiro Yamada val = val >> 1;
4656f86e39SMasahiro Yamada }
4756f86e39SMasahiro Yamada return (0x0000ffff & j);
4856f86e39SMasahiro Yamada }
4956f86e39SMasahiro Yamada
5056f86e39SMasahiro Yamada /*
5156f86e39SMasahiro Yamada * kw_config_adr_windows - Configure address Windows
5256f86e39SMasahiro Yamada *
5356f86e39SMasahiro Yamada * There are 8 address windows supported by Kirkwood Soc to addess different
5456f86e39SMasahiro Yamada * devices. Each window can be configured for size, BAR and remap addr
5556f86e39SMasahiro Yamada * Below configuration is standard for most of the cases
5656f86e39SMasahiro Yamada *
5756f86e39SMasahiro Yamada * If remap function not used, remap_lo must be set as base
5856f86e39SMasahiro Yamada *
5956f86e39SMasahiro Yamada * Reference Documentation:
6056f86e39SMasahiro Yamada * Mbus-L to Mbus Bridge Registers Configuration.
6156f86e39SMasahiro Yamada * (Sec 25.1 and 25.3 of Datasheet)
6256f86e39SMasahiro Yamada */
kw_config_adr_windows(void)6356f86e39SMasahiro Yamada int kw_config_adr_windows(void)
6456f86e39SMasahiro Yamada {
6556f86e39SMasahiro Yamada struct kwwin_registers *winregs =
6656f86e39SMasahiro Yamada (struct kwwin_registers *)KW_CPU_WIN_BASE;
6756f86e39SMasahiro Yamada
6856f86e39SMasahiro Yamada /* Window 0: PCIE MEM address space */
6956f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE,
7056f86e39SMasahiro Yamada KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl);
7156f86e39SMasahiro Yamada
7256f86e39SMasahiro Yamada writel(KW_DEFADR_PCI_MEM, &winregs[0].base);
7356f86e39SMasahiro Yamada writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo);
7456f86e39SMasahiro Yamada writel(0x0, &winregs[0].remap_hi);
7556f86e39SMasahiro Yamada
7656f86e39SMasahiro Yamada /* Window 1: PCIE IO address space */
7756f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE,
7856f86e39SMasahiro Yamada KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl);
7956f86e39SMasahiro Yamada writel(KW_DEFADR_PCI_IO, &winregs[1].base);
8056f86e39SMasahiro Yamada writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo);
8156f86e39SMasahiro Yamada writel(0x0, &winregs[1].remap_hi);
8256f86e39SMasahiro Yamada
8356f86e39SMasahiro Yamada /* Window 2: NAND Flash address space */
8456f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
8556f86e39SMasahiro Yamada KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl);
8656f86e39SMasahiro Yamada writel(KW_DEFADR_NANDF, &winregs[2].base);
8756f86e39SMasahiro Yamada writel(KW_DEFADR_NANDF, &winregs[2].remap_lo);
8856f86e39SMasahiro Yamada writel(0x0, &winregs[2].remap_hi);
8956f86e39SMasahiro Yamada
9056f86e39SMasahiro Yamada /* Window 3: SPI Flash address space */
9156f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
9256f86e39SMasahiro Yamada KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl);
9356f86e39SMasahiro Yamada writel(KW_DEFADR_SPIF, &winregs[3].base);
9456f86e39SMasahiro Yamada writel(KW_DEFADR_SPIF, &winregs[3].remap_lo);
9556f86e39SMasahiro Yamada writel(0x0, &winregs[3].remap_hi);
9656f86e39SMasahiro Yamada
9756f86e39SMasahiro Yamada /* Window 4: BOOT Memory address space */
9856f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
9956f86e39SMasahiro Yamada KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl);
10056f86e39SMasahiro Yamada writel(KW_DEFADR_BOOTROM, &winregs[4].base);
10156f86e39SMasahiro Yamada
10256f86e39SMasahiro Yamada /* Window 5: Security SRAM address space */
10356f86e39SMasahiro Yamada writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM,
10456f86e39SMasahiro Yamada KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl);
10556f86e39SMasahiro Yamada writel(KW_DEFADR_SASRAM, &winregs[5].base);
10656f86e39SMasahiro Yamada
10756f86e39SMasahiro Yamada /* Window 6-7: Disabled */
10856f86e39SMasahiro Yamada writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl);
10956f86e39SMasahiro Yamada writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl);
11056f86e39SMasahiro Yamada
11156f86e39SMasahiro Yamada return 0;
11256f86e39SMasahiro Yamada }
11356f86e39SMasahiro Yamada
11456f86e39SMasahiro Yamada /*
11556f86e39SMasahiro Yamada * SYSRSTn Duration Counter Support
11656f86e39SMasahiro Yamada *
11756f86e39SMasahiro Yamada * Kirkwood SoC implements a hardware-based SYSRSTn duration counter.
11856f86e39SMasahiro Yamada * When SYSRSTn is asserted low, a SYSRSTn duration counter is running.
11956f86e39SMasahiro Yamada * The SYSRSTn duration counter is useful for implementing a manufacturer
12056f86e39SMasahiro Yamada * or factory reset. Upon a long reset assertion that is greater than a
12156f86e39SMasahiro Yamada * pre-configured environment variable value for sysrstdelay,
12256f86e39SMasahiro Yamada * The counter value is stored in the SYSRSTn Length Counter Register
12356f86e39SMasahiro Yamada * The counter is based on the 25-MHz reference clock (40ns)
12456f86e39SMasahiro Yamada * It is a 29-bit counter, yielding a maximum counting duration of
12556f86e39SMasahiro Yamada * 2^29/25 MHz (21.4 seconds). When the counter reach its maximum value,
12656f86e39SMasahiro Yamada * it remains at this value until counter reset is triggered by setting
12756f86e39SMasahiro Yamada * bit 31 of KW_REG_SYSRST_CNT
12856f86e39SMasahiro Yamada */
kw_sysrst_action(void)12956f86e39SMasahiro Yamada static void kw_sysrst_action(void)
13056f86e39SMasahiro Yamada {
13156f86e39SMasahiro Yamada int ret;
132*00caae6dSSimon Glass char *s = env_get("sysrstcmd");
13356f86e39SMasahiro Yamada
13456f86e39SMasahiro Yamada if (!s) {
13556f86e39SMasahiro Yamada debug("Error.. %s failed, check sysrstcmd\n",
13656f86e39SMasahiro Yamada __FUNCTION__);
13756f86e39SMasahiro Yamada return;
13856f86e39SMasahiro Yamada }
13956f86e39SMasahiro Yamada
14056f86e39SMasahiro Yamada debug("Starting %s process...\n", __FUNCTION__);
14156f86e39SMasahiro Yamada ret = run_command(s, 0);
14256f86e39SMasahiro Yamada if (ret != 0)
14356f86e39SMasahiro Yamada debug("Error.. %s failed\n", __FUNCTION__);
14456f86e39SMasahiro Yamada else
14556f86e39SMasahiro Yamada debug("%s process finished\n", __FUNCTION__);
14656f86e39SMasahiro Yamada }
14756f86e39SMasahiro Yamada
kw_sysrst_check(void)14856f86e39SMasahiro Yamada static void kw_sysrst_check(void)
14956f86e39SMasahiro Yamada {
15056f86e39SMasahiro Yamada u32 sysrst_cnt, sysrst_dly;
15156f86e39SMasahiro Yamada char *s;
15256f86e39SMasahiro Yamada
15356f86e39SMasahiro Yamada /*
15456f86e39SMasahiro Yamada * no action if sysrstdelay environment variable is not defined
15556f86e39SMasahiro Yamada */
156*00caae6dSSimon Glass s = env_get("sysrstdelay");
15756f86e39SMasahiro Yamada if (s == NULL)
15856f86e39SMasahiro Yamada return;
15956f86e39SMasahiro Yamada
16056f86e39SMasahiro Yamada /* read sysrstdelay value */
16156f86e39SMasahiro Yamada sysrst_dly = (u32) simple_strtoul(s, NULL, 10);
16256f86e39SMasahiro Yamada
16356f86e39SMasahiro Yamada /* read SysRst Length counter register (bits 28:0) */
16456f86e39SMasahiro Yamada sysrst_cnt = (0x1fffffff & readl(KW_REG_SYSRST_CNT));
16556f86e39SMasahiro Yamada debug("H/w Rst hold time: %d.%d secs\n",
16656f86e39SMasahiro Yamada sysrst_cnt / SYSRST_CNT_1SEC_VAL,
16756f86e39SMasahiro Yamada sysrst_cnt % SYSRST_CNT_1SEC_VAL);
16856f86e39SMasahiro Yamada
16956f86e39SMasahiro Yamada /* clear the counter for next valid read*/
17056f86e39SMasahiro Yamada writel(1 << 31, KW_REG_SYSRST_CNT);
17156f86e39SMasahiro Yamada
17256f86e39SMasahiro Yamada /*
17356f86e39SMasahiro Yamada * sysrst_action:
17456f86e39SMasahiro Yamada * if H/w Reset key is pressed and hold for time
17556f86e39SMasahiro Yamada * more than sysrst_dly in seconds
17656f86e39SMasahiro Yamada */
17756f86e39SMasahiro Yamada if (sysrst_cnt >= SYSRST_CNT_1SEC_VAL * sysrst_dly)
17856f86e39SMasahiro Yamada kw_sysrst_action();
17956f86e39SMasahiro Yamada }
18056f86e39SMasahiro Yamada
18156f86e39SMasahiro Yamada #if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo(void)18256f86e39SMasahiro Yamada int print_cpuinfo(void)
18356f86e39SMasahiro Yamada {
18456f86e39SMasahiro Yamada char *rev = "??";
18556f86e39SMasahiro Yamada u16 devid = (readl(KW_REG_PCIE_DEVID) >> 16) & 0xffff;
18656f86e39SMasahiro Yamada u8 revid = readl(KW_REG_PCIE_REVID) & 0xff;
18756f86e39SMasahiro Yamada
18856f86e39SMasahiro Yamada if ((readl(KW_REG_DEVICE_ID) & 0x03) > 2) {
18956f86e39SMasahiro Yamada printf("Error.. %s:Unsupported Kirkwood SoC 88F%04x\n", __FUNCTION__, devid);
19056f86e39SMasahiro Yamada return -1;
19156f86e39SMasahiro Yamada }
19256f86e39SMasahiro Yamada
19356f86e39SMasahiro Yamada switch (revid) {
19456f86e39SMasahiro Yamada case 0:
19556f86e39SMasahiro Yamada if (devid == 0x6281)
19656f86e39SMasahiro Yamada rev = "Z0";
19756f86e39SMasahiro Yamada else if (devid == 0x6282)
19856f86e39SMasahiro Yamada rev = "A0";
19956f86e39SMasahiro Yamada break;
20056f86e39SMasahiro Yamada case 1:
20156f86e39SMasahiro Yamada rev = "A1";
20256f86e39SMasahiro Yamada break;
20356f86e39SMasahiro Yamada case 2:
20456f86e39SMasahiro Yamada rev = "A0";
20556f86e39SMasahiro Yamada break;
20656f86e39SMasahiro Yamada case 3:
20756f86e39SMasahiro Yamada rev = "A1";
20856f86e39SMasahiro Yamada break;
20956f86e39SMasahiro Yamada default:
21056f86e39SMasahiro Yamada break;
21156f86e39SMasahiro Yamada }
21256f86e39SMasahiro Yamada
21356f86e39SMasahiro Yamada printf("SoC: Kirkwood 88F%04x_%s\n", devid, rev);
21456f86e39SMasahiro Yamada return 0;
21556f86e39SMasahiro Yamada }
21656f86e39SMasahiro Yamada #endif /* CONFIG_DISPLAY_CPUINFO */
21756f86e39SMasahiro Yamada
21856f86e39SMasahiro Yamada #ifdef CONFIG_ARCH_CPU_INIT
arch_cpu_init(void)21956f86e39SMasahiro Yamada int arch_cpu_init(void)
22056f86e39SMasahiro Yamada {
22156f86e39SMasahiro Yamada u32 reg;
22256f86e39SMasahiro Yamada struct kwcpu_registers *cpureg =
22356f86e39SMasahiro Yamada (struct kwcpu_registers *)KW_CPU_REG_BASE;
22456f86e39SMasahiro Yamada
22556f86e39SMasahiro Yamada /* Linux expects` the internal registers to be at 0xf1000000 */
22656f86e39SMasahiro Yamada writel(KW_REGS_PHY_BASE, KW_OFFSET_REG);
22756f86e39SMasahiro Yamada
22856f86e39SMasahiro Yamada /* Enable and invalidate L2 cache in write through mode */
22956f86e39SMasahiro Yamada writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg);
23056f86e39SMasahiro Yamada invalidate_l2_cache();
23156f86e39SMasahiro Yamada
23256f86e39SMasahiro Yamada kw_config_adr_windows();
23356f86e39SMasahiro Yamada
23456f86e39SMasahiro Yamada #ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
23556f86e39SMasahiro Yamada /*
23656f86e39SMasahiro Yamada * Configures the I/O voltage of the pads connected to Egigabit
23756f86e39SMasahiro Yamada * Ethernet interface to 1.8V
23856f86e39SMasahiro Yamada * By default it is set to 3.3V
23956f86e39SMasahiro Yamada */
24056f86e39SMasahiro Yamada reg = readl(KW_REG_MPP_OUT_DRV_REG);
24156f86e39SMasahiro Yamada reg |= (1 << 7);
24256f86e39SMasahiro Yamada writel(reg, KW_REG_MPP_OUT_DRV_REG);
24356f86e39SMasahiro Yamada #endif
24456f86e39SMasahiro Yamada #ifdef CONFIG_KIRKWOOD_EGIGA_INIT
24556f86e39SMasahiro Yamada /*
24656f86e39SMasahiro Yamada * Set egiga port0/1 in normal functional mode
24756f86e39SMasahiro Yamada * This is required becasue on kirkwood by default ports are in reset mode
24856f86e39SMasahiro Yamada * OS egiga driver may not have provision to set them in normal mode
24956f86e39SMasahiro Yamada * and if u-boot is build without network support, network may fail at OS level
25056f86e39SMasahiro Yamada */
25156f86e39SMasahiro Yamada reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(0));
25256f86e39SMasahiro Yamada reg &= ~(1 << 4); /* Clear PortReset Bit */
25356f86e39SMasahiro Yamada writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(0)));
25456f86e39SMasahiro Yamada reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(1));
25556f86e39SMasahiro Yamada reg &= ~(1 << 4); /* Clear PortReset Bit */
25656f86e39SMasahiro Yamada writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(1)));
25756f86e39SMasahiro Yamada #endif
25856f86e39SMasahiro Yamada #ifdef CONFIG_KIRKWOOD_PCIE_INIT
25956f86e39SMasahiro Yamada /*
26056f86e39SMasahiro Yamada * Enable PCI Express Port0
26156f86e39SMasahiro Yamada */
26256f86e39SMasahiro Yamada reg = readl(&cpureg->ctrl_stat);
26356f86e39SMasahiro Yamada reg |= (1 << 0); /* Set PEX0En Bit */
26456f86e39SMasahiro Yamada writel(reg, &cpureg->ctrl_stat);
26556f86e39SMasahiro Yamada #endif
26656f86e39SMasahiro Yamada return 0;
26756f86e39SMasahiro Yamada }
26856f86e39SMasahiro Yamada #endif /* CONFIG_ARCH_CPU_INIT */
26956f86e39SMasahiro Yamada
27056f86e39SMasahiro Yamada /*
27156f86e39SMasahiro Yamada * SOC specific misc init
27256f86e39SMasahiro Yamada */
27356f86e39SMasahiro Yamada #if defined(CONFIG_ARCH_MISC_INIT)
arch_misc_init(void)27456f86e39SMasahiro Yamada int arch_misc_init(void)
27556f86e39SMasahiro Yamada {
27656f86e39SMasahiro Yamada volatile u32 temp;
27756f86e39SMasahiro Yamada
27856f86e39SMasahiro Yamada /*CPU streaming & write allocate */
27956f86e39SMasahiro Yamada temp = readfr_extra_feature_reg();
28056f86e39SMasahiro Yamada temp &= ~(1 << 28); /* disable wr alloc */
28156f86e39SMasahiro Yamada writefr_extra_feature_reg(temp);
28256f86e39SMasahiro Yamada
28356f86e39SMasahiro Yamada temp = readfr_extra_feature_reg();
28456f86e39SMasahiro Yamada temp &= ~(1 << 29); /* streaming disabled */
28556f86e39SMasahiro Yamada writefr_extra_feature_reg(temp);
28656f86e39SMasahiro Yamada
28756f86e39SMasahiro Yamada /* L2Cache settings */
28856f86e39SMasahiro Yamada temp = readfr_extra_feature_reg();
28956f86e39SMasahiro Yamada /* Disable L2C pre fetch - Set bit 24 */
29056f86e39SMasahiro Yamada temp |= (1 << 24);
29156f86e39SMasahiro Yamada /* enable L2C - Set bit 22 */
29256f86e39SMasahiro Yamada temp |= (1 << 22);
29356f86e39SMasahiro Yamada writefr_extra_feature_reg(temp);
29456f86e39SMasahiro Yamada
29556f86e39SMasahiro Yamada icache_enable();
29656f86e39SMasahiro Yamada /* Change reset vector to address 0x0 */
29756f86e39SMasahiro Yamada temp = get_cr();
29856f86e39SMasahiro Yamada set_cr(temp & ~CR_V);
29956f86e39SMasahiro Yamada
30056f86e39SMasahiro Yamada /* checks and execute resset to factory event */
30156f86e39SMasahiro Yamada kw_sysrst_check();
30256f86e39SMasahiro Yamada
30356f86e39SMasahiro Yamada return 0;
30456f86e39SMasahiro Yamada }
30556f86e39SMasahiro Yamada #endif /* CONFIG_ARCH_MISC_INIT */
30656f86e39SMasahiro Yamada
30756f86e39SMasahiro Yamada #ifdef CONFIG_MVGBE
cpu_eth_init(bd_t * bis)30856f86e39SMasahiro Yamada int cpu_eth_init(bd_t *bis)
30956f86e39SMasahiro Yamada {
31056f86e39SMasahiro Yamada mvgbe_initialize(bis);
31156f86e39SMasahiro Yamada return 0;
31256f86e39SMasahiro Yamada }
31356f86e39SMasahiro Yamada #endif
31456f86e39SMasahiro Yamada
31556f86e39SMasahiro Yamada #ifdef CONFIG_MVEBU_MMC
board_mmc_init(bd_t * bis)31656f86e39SMasahiro Yamada int board_mmc_init(bd_t *bis)
31756f86e39SMasahiro Yamada {
31856f86e39SMasahiro Yamada mvebu_mmc_init(bis);
31956f86e39SMasahiro Yamada return 0;
32056f86e39SMasahiro Yamada }
32156f86e39SMasahiro Yamada #endif /* CONFIG_MVEBU_MMC */
322