mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-08-20 08:58:52 +09:00
![Tom Rini](/assets/img/avatar_default.png)
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
321 lines
8.5 KiB
C
321 lines
8.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* (C) Copyright 2009
|
|
* Marvell Semiconductor <www.marvell.com>
|
|
* Written-by: Prafulla Wadaskar <prafulla@marvell.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <netdev.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch/cpu.h>
|
|
#include <asm/arch/soc.h>
|
|
#include <mvebu_mmc.h>
|
|
|
|
void reset_cpu(unsigned long ignored)
|
|
{
|
|
struct kwcpu_registers *cpureg =
|
|
(struct kwcpu_registers *)KW_CPU_REG_BASE;
|
|
|
|
writel(readl(&cpureg->rstoutn_mask) | (1 << 2),
|
|
&cpureg->rstoutn_mask);
|
|
writel(readl(&cpureg->sys_soft_rst) | 1,
|
|
&cpureg->sys_soft_rst);
|
|
while (1) ;
|
|
}
|
|
|
|
/*
|
|
* Window Size
|
|
* Used with the Base register to set the address window size and location.
|
|
* Must be programmed from LSB to MSB as sequence of ones followed by
|
|
* sequence of zeros. The number of ones specifies the size of the window in
|
|
* 64 KByte granularity (e.g., a value of 0x00FF specifies 256 = 16 MByte).
|
|
* NOTE: A value of 0x0 specifies 64-KByte size.
|
|
*/
|
|
unsigned int kw_winctrl_calcsize(unsigned int sizeval)
|
|
{
|
|
int i;
|
|
unsigned int j = 0;
|
|
u32 val = sizeval >> 1;
|
|
|
|
for (i = 0; val >= 0x10000; i++) {
|
|
j |= (1 << i);
|
|
val = val >> 1;
|
|
}
|
|
return (0x0000ffff & j);
|
|
}
|
|
|
|
/*
|
|
* kw_config_adr_windows - Configure address Windows
|
|
*
|
|
* There are 8 address windows supported by Kirkwood Soc to addess different
|
|
* devices. Each window can be configured for size, BAR and remap addr
|
|
* Below configuration is standard for most of the cases
|
|
*
|
|
* If remap function not used, remap_lo must be set as base
|
|
*
|
|
* Reference Documentation:
|
|
* Mbus-L to Mbus Bridge Registers Configuration.
|
|
* (Sec 25.1 and 25.3 of Datasheet)
|
|
*/
|
|
int kw_config_adr_windows(void)
|
|
{
|
|
struct kwwin_registers *winregs =
|
|
(struct kwwin_registers *)KW_CPU_WIN_BASE;
|
|
|
|
/* Window 0: PCIE MEM address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE,
|
|
KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl);
|
|
|
|
writel(KW_DEFADR_PCI_MEM, &winregs[0].base);
|
|
writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo);
|
|
writel(0x0, &winregs[0].remap_hi);
|
|
|
|
/* Window 1: PCIE IO address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE,
|
|
KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl);
|
|
writel(KW_DEFADR_PCI_IO, &winregs[1].base);
|
|
writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo);
|
|
writel(0x0, &winregs[1].remap_hi);
|
|
|
|
/* Window 2: NAND Flash address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
|
|
KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl);
|
|
writel(KW_DEFADR_NANDF, &winregs[2].base);
|
|
writel(KW_DEFADR_NANDF, &winregs[2].remap_lo);
|
|
writel(0x0, &winregs[2].remap_hi);
|
|
|
|
/* Window 3: SPI Flash address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
|
|
KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl);
|
|
writel(KW_DEFADR_SPIF, &winregs[3].base);
|
|
writel(KW_DEFADR_SPIF, &winregs[3].remap_lo);
|
|
writel(0x0, &winregs[3].remap_hi);
|
|
|
|
/* Window 4: BOOT Memory address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
|
|
KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl);
|
|
writel(KW_DEFADR_BOOTROM, &winregs[4].base);
|
|
|
|
/* Window 5: Security SRAM address space */
|
|
writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM,
|
|
KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl);
|
|
writel(KW_DEFADR_SASRAM, &winregs[5].base);
|
|
|
|
/* Window 6-7: Disabled */
|
|
writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl);
|
|
writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* SYSRSTn Duration Counter Support
|
|
*
|
|
* Kirkwood SoC implements a hardware-based SYSRSTn duration counter.
|
|
* When SYSRSTn is asserted low, a SYSRSTn duration counter is running.
|
|
* The SYSRSTn duration counter is useful for implementing a manufacturer
|
|
* or factory reset. Upon a long reset assertion that is greater than a
|
|
* pre-configured environment variable value for sysrstdelay,
|
|
* The counter value is stored in the SYSRSTn Length Counter Register
|
|
* The counter is based on the 25-MHz reference clock (40ns)
|
|
* It is a 29-bit counter, yielding a maximum counting duration of
|
|
* 2^29/25 MHz (21.4 seconds). When the counter reach its maximum value,
|
|
* it remains at this value until counter reset is triggered by setting
|
|
* bit 31 of KW_REG_SYSRST_CNT
|
|
*/
|
|
static void kw_sysrst_action(void)
|
|
{
|
|
int ret;
|
|
char *s = env_get("sysrstcmd");
|
|
|
|
if (!s) {
|
|
debug("Error.. %s failed, check sysrstcmd\n",
|
|
__FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
debug("Starting %s process...\n", __FUNCTION__);
|
|
ret = run_command(s, 0);
|
|
if (ret != 0)
|
|
debug("Error.. %s failed\n", __FUNCTION__);
|
|
else
|
|
debug("%s process finished\n", __FUNCTION__);
|
|
}
|
|
|
|
static void kw_sysrst_check(void)
|
|
{
|
|
u32 sysrst_cnt, sysrst_dly;
|
|
char *s;
|
|
|
|
/*
|
|
* no action if sysrstdelay environment variable is not defined
|
|
*/
|
|
s = env_get("sysrstdelay");
|
|
if (s == NULL)
|
|
return;
|
|
|
|
/* read sysrstdelay value */
|
|
sysrst_dly = (u32) simple_strtoul(s, NULL, 10);
|
|
|
|
/* read SysRst Length counter register (bits 28:0) */
|
|
sysrst_cnt = (0x1fffffff & readl(KW_REG_SYSRST_CNT));
|
|
debug("H/w Rst hold time: %d.%d secs\n",
|
|
sysrst_cnt / SYSRST_CNT_1SEC_VAL,
|
|
sysrst_cnt % SYSRST_CNT_1SEC_VAL);
|
|
|
|
/* clear the counter for next valid read*/
|
|
writel(1 << 31, KW_REG_SYSRST_CNT);
|
|
|
|
/*
|
|
* sysrst_action:
|
|
* if H/w Reset key is pressed and hold for time
|
|
* more than sysrst_dly in seconds
|
|
*/
|
|
if (sysrst_cnt >= SYSRST_CNT_1SEC_VAL * sysrst_dly)
|
|
kw_sysrst_action();
|
|
}
|
|
|
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
|
int print_cpuinfo(void)
|
|
{
|
|
char *rev = "??";
|
|
u16 devid = (readl(KW_REG_PCIE_DEVID) >> 16) & 0xffff;
|
|
u8 revid = readl(KW_REG_PCIE_REVID) & 0xff;
|
|
|
|
if ((readl(KW_REG_DEVICE_ID) & 0x03) > 2) {
|
|
printf("Error.. %s:Unsupported Kirkwood SoC 88F%04x\n", __FUNCTION__, devid);
|
|
return -1;
|
|
}
|
|
|
|
switch (revid) {
|
|
case 0:
|
|
if (devid == 0x6281)
|
|
rev = "Z0";
|
|
else if (devid == 0x6282)
|
|
rev = "A0";
|
|
break;
|
|
case 1:
|
|
rev = "A1";
|
|
break;
|
|
case 2:
|
|
rev = "A0";
|
|
break;
|
|
case 3:
|
|
rev = "A1";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
printf("SoC: Kirkwood 88F%04x_%s\n", devid, rev);
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_DISPLAY_CPUINFO */
|
|
|
|
#ifdef CONFIG_ARCH_CPU_INIT
|
|
int arch_cpu_init(void)
|
|
{
|
|
u32 reg;
|
|
struct kwcpu_registers *cpureg =
|
|
(struct kwcpu_registers *)KW_CPU_REG_BASE;
|
|
|
|
/* Linux expects` the internal registers to be at 0xf1000000 */
|
|
writel(KW_REGS_PHY_BASE, KW_OFFSET_REG);
|
|
|
|
/* Enable and invalidate L2 cache in write through mode */
|
|
writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg);
|
|
invalidate_l2_cache();
|
|
|
|
kw_config_adr_windows();
|
|
|
|
#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
|
|
/*
|
|
* Configures the I/O voltage of the pads connected to Egigabit
|
|
* Ethernet interface to 1.8V
|
|
* By default it is set to 3.3V
|
|
*/
|
|
reg = readl(KW_REG_MPP_OUT_DRV_REG);
|
|
reg |= (1 << 7);
|
|
writel(reg, KW_REG_MPP_OUT_DRV_REG);
|
|
#endif
|
|
#ifdef CONFIG_KIRKWOOD_EGIGA_INIT
|
|
/*
|
|
* Set egiga port0/1 in normal functional mode
|
|
* This is required becasue on kirkwood by default ports are in reset mode
|
|
* OS egiga driver may not have provision to set them in normal mode
|
|
* and if u-boot is build without network support, network may fail at OS level
|
|
*/
|
|
reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(0));
|
|
reg &= ~(1 << 4); /* Clear PortReset Bit */
|
|
writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(0)));
|
|
reg = readl(KWGBE_PORT_SERIAL_CONTROL1_REG(1));
|
|
reg &= ~(1 << 4); /* Clear PortReset Bit */
|
|
writel(reg, (KWGBE_PORT_SERIAL_CONTROL1_REG(1)));
|
|
#endif
|
|
#ifdef CONFIG_KIRKWOOD_PCIE_INIT
|
|
/*
|
|
* Enable PCI Express Port0
|
|
*/
|
|
reg = readl(&cpureg->ctrl_stat);
|
|
reg |= (1 << 0); /* Set PEX0En Bit */
|
|
writel(reg, &cpureg->ctrl_stat);
|
|
#endif
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_ARCH_CPU_INIT */
|
|
|
|
/*
|
|
* SOC specific misc init
|
|
*/
|
|
#if defined(CONFIG_ARCH_MISC_INIT)
|
|
int arch_misc_init(void)
|
|
{
|
|
volatile u32 temp;
|
|
|
|
/*CPU streaming & write allocate */
|
|
temp = readfr_extra_feature_reg();
|
|
temp &= ~(1 << 28); /* disable wr alloc */
|
|
writefr_extra_feature_reg(temp);
|
|
|
|
temp = readfr_extra_feature_reg();
|
|
temp &= ~(1 << 29); /* streaming disabled */
|
|
writefr_extra_feature_reg(temp);
|
|
|
|
/* L2Cache settings */
|
|
temp = readfr_extra_feature_reg();
|
|
/* Disable L2C pre fetch - Set bit 24 */
|
|
temp |= (1 << 24);
|
|
/* enable L2C - Set bit 22 */
|
|
temp |= (1 << 22);
|
|
writefr_extra_feature_reg(temp);
|
|
|
|
icache_enable();
|
|
/* Change reset vector to address 0x0 */
|
|
temp = get_cr();
|
|
set_cr(temp & ~CR_V);
|
|
|
|
/* checks and execute resset to factory event */
|
|
kw_sysrst_check();
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_ARCH_MISC_INIT */
|
|
|
|
#ifdef CONFIG_MVGBE
|
|
int cpu_eth_init(bd_t *bis)
|
|
{
|
|
mvgbe_initialize(bis);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MVEBU_MMC
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
mvebu_mmc_init(bis);
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_MVEBU_MMC */
|