Merge branch 'master' of git://git.denx.de/u-boot-marvell

- Misc enhancements to Clearfog, including board variant detection
  (Joel)
- Misc enhancements to Turris Mox, including generalization of the
  ARMADA37xx DDR size detection (Marek)
This commit is contained in:
Tom Rini 2020-04-14 08:47:07 -04:00
commit 142a07f2a4
26 changed files with 920 additions and 158 deletions

View File

@ -191,25 +191,25 @@ dtb-$(CONFIG_ARCH_MVEBU) += \
armada-3720-turris-mox.dtb \
armada-3720-uDPU.dtb \
armada-375-db.dtb \
armada-385-atl-x530.dtb \
armada-385-atl-x530DP.dtb \
armada-385-db-88f6820-amc.dtb \
armada-385-turris-omnia.dtb \
armada-388-clearfog.dtb \
armada-388-gp.dtb \
armada-388-helios4.dtb \
armada-385-db-88f6820-amc.dtb \
armada-385-turris-omnia.dtb \
armada-7040-db.dtb \
armada-38x-controlcenterdc.dtb \
armada-7040-db-nand.dtb \
armada-7040-db.dtb \
armada-8040-clearfog-gt-8k.dtb \
armada-8040-db.dtb \
armada-8040-mcbin.dtb \
armada-8040-clearfog-gt-8k.dtb \
armada-xp-crs305-1g-4s.dtb \
armada-xp-db-xc3-24g4xg.dtb \
armada-xp-gp.dtb \
armada-xp-maxbcm.dtb \
armada-xp-synology-ds414.dtb \
armada-xp-theadorable.dtb \
armada-38x-controlcenterdc.dtb \
armada-385-atl-x530.dtb \
armada-385-atl-x530DP.dtb \
armada-xp-db-xc3-24g4xg.dtb \
armada-xp-crs305-1g-4s.dtb
armada-xp-theadorable.dtb
dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
uniphier-ld11-global.dtb \

View File

@ -42,9 +42,24 @@
startup-delay-us = <2000000>;
shutdown-delay-us = <1000000>;
gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>;
enable-active-high;
regulator-boot-on;
};
vsdc_reg: vsdc-reg {
compatible = "regulator-gpio";
regulator-name = "vsdc";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
gpios = <&gpiosb 23 GPIO_ACTIVE_HIGH>;
gpios-states = <0>;
states = <1800000 0x1
3300000 0x0>;
enable-active-high;
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
@ -93,7 +108,11 @@
};
&sdhci1 {
wp-inverted;
bus-width = <4>;
cd-gpios = <&gpionb 10 GPIO_ACTIVE_HIGH>;
vqmmc-supply = <&vsdc_reg>;
marvell,pad-type = "sd";
status = "okay";
};

View File

@ -39,7 +39,6 @@
&eth0 {
/* ethernet@70000 */
mac-address = [00 50 43 02 02 01];
pinctrl-0 = <&ge0_rgmii_pins>;
pinctrl-names = "default";
phy = <&phy_dedicated>;

View File

@ -280,4 +280,6 @@ config SECURED_MODE_CSK_INDEX
default 0
depends on SECURED_MODE_IMAGE
source "board/solidrun/clearfog/Kconfig"
endif

View File

@ -45,54 +45,14 @@ const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
return NULL;
}
/* DRAM init code ... */
#define MV_SIP_DRAM_SIZE 0x82000010
static u64 a8k_dram_scan_ap_sz(void)
{
struct pt_regs pregs;
pregs.regs[0] = MV_SIP_DRAM_SIZE;
pregs.regs[1] = SOC_REGS_PHY_BASE;
smc_call(&pregs);
return pregs.regs[0];
}
static void a8k_dram_init_banksize(void)
{
/*
* The firmware (ATF) leaves a 1G whole above the 3G mark for IO
* devices. Higher RAM is mapped at 4G.
*
* Config 2 DRAM banks:
* Bank 0 - max size 4G - 1G
* Bank 1 - ram size - 4G + 1G
*/
phys_size_t max_bank0_size = SZ_4G - SZ_1G;
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
if (gd->ram_size <= max_bank0_size) {
gd->bd->bi_dram[0].size = gd->ram_size;
return;
}
gd->bd->bi_dram[0].size = max_bank0_size;
if (CONFIG_NR_DRAM_BANKS > 1) {
gd->bd->bi_dram[1].start = SZ_4G;
gd->bd->bi_dram[1].size = gd->ram_size - max_bank0_size;
}
}
__weak int dram_init_banksize(void)
{
if (CONFIG_IS_ENABLED(ARMADA_8K))
a8k_dram_init_banksize();
return a8k_dram_init_banksize();
else if (CONFIG_IS_ENABLED(ARMADA_3700))
return a3700_dram_init_banksize();
else
fdtdec_setup_memory_banksize();
return 0;
return fdtdec_setup_memory_banksize();
}
__weak int dram_init(void)
@ -103,6 +63,9 @@ __weak int dram_init(void)
return 0;
}
if (CONFIG_IS_ENABLED(ARMADA_3700))
return a3700_dram_init();
if (fdtdec_setup_mem_size_base() != 0)
return -EINVAL;

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
* Copyright (C) 2020 Marek Behun <marek.behun@nic.cz>
*/
#include <common.h>
@ -13,6 +14,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <asm/armv8/mmu.h>
#include <sort.h>
/* Armada 3700 */
#define MVEBU_GPIO_NB_REG_BASE (MVEBU_REGISTER(0x13800))
@ -26,39 +28,289 @@
#define MVEBU_NB_WARM_RST_REG (MVEBU_GPIO_NB_REG_BASE + 0x40)
#define MVEBU_NB_WARM_RST_MAGIC_NUM 0x1d1e
static struct mm_region mvebu_mem_map[] = {
/* Armada 3700 CPU Address Decoder registers */
#define MVEBU_CPU_DEC_WIN_REG_BASE (size_t)(MVEBU_REGISTER(0xcf00))
#define MVEBU_CPU_DEC_WIN_CTRL(w) \
(MVEBU_CPU_DEC_WIN_REG_BASE + ((w) << 4))
#define MVEBU_CPU_DEC_WIN_CTRL_EN BIT(0)
#define MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK 0xf
#define MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS 4
#define MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM 0
#define MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE 2
#define MVEBU_CPU_DEC_WIN_SIZE(w) (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x4)
#define MVEBU_CPU_DEC_WIN_BASE(w) (MVEBU_CPU_DEC_WIN_CTRL(w) + 0x8)
#define MVEBU_CPU_DEC_WIN_REMAP(w) (MVEBU_CPU_DEC_WIN_CTRL(w) + 0xc)
#define MVEBU_CPU_DEC_WIN_GRANULARITY 16
#define MVEBU_CPU_DEC_WINS 5
#define MAX_MEM_MAP_REGIONS (MVEBU_CPU_DEC_WINS + 2)
#define A3700_PTE_BLOCK_NORMAL \
(PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE)
#define A3700_PTE_BLOCK_DEVICE \
(PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE)
#define PCIE_PATH "/soc/pcie@d0070000"
DECLARE_GLOBAL_DATA_PTR;
static struct mm_region mvebu_mem_map[MAX_MEM_MAP_REGIONS] = {
{
/* RAM */
.phys = 0x0UL,
.virt = 0x0UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
},
{
/* SRAM, MMIO regions */
.phys = 0xd0000000UL,
.virt = 0xd0000000UL,
/*
* SRAM, MMIO regions
* Don't remove this, a3700_build_mem_map needs it.
*/
.phys = SOC_REGS_PHY_BASE,
.virt = SOC_REGS_PHY_BASE,
.size = 0x02000000UL, /* 32MiB internal registers */
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE
.attrs = A3700_PTE_BLOCK_DEVICE
},
{
/* PCI regions */
.phys = 0xe8000000UL,
.virt = 0xe8000000UL,
.size = 0x02000000UL, /* 32MiB master PCI space */
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE
},
{
/* List terminator */
0,
}
};
struct mm_region *mem_map = mvebu_mem_map;
static int get_cpu_dec_win(int win, u32 *tgt, u32 *base, u32 *size)
{
u32 reg;
reg = readl(MVEBU_CPU_DEC_WIN_CTRL(win));
if (!(reg & MVEBU_CPU_DEC_WIN_CTRL_EN))
return -1;
if (tgt) {
reg >>= MVEBU_CPU_DEC_WIN_CTRL_TGT_OFFS;
reg &= MVEBU_CPU_DEC_WIN_CTRL_TGT_MASK;
*tgt = reg;
}
if (base) {
reg = readl(MVEBU_CPU_DEC_WIN_BASE(win));
*base = reg << MVEBU_CPU_DEC_WIN_GRANULARITY;
}
if (size) {
/*
* Window size is encoded as the number of 1s from LSB to MSB,
* followed by 0s. The number of 1s specifies the size in 64 KiB
* granularity.
*/
reg = readl(MVEBU_CPU_DEC_WIN_SIZE(win));
*size = ((reg + 1) << MVEBU_CPU_DEC_WIN_GRANULARITY);
}
return 0;
}
/*
* Builds mem_map according to CPU Address Decoder settings, which were set by
* the TIMH image on the Cortex-M3 secure processor, or by ARM Trusted Firmware
*/
static void build_mem_map(void)
{
int win, region;
region = 1;
for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
u32 base, tgt, size;
u64 attrs;
/* skip disabled windows */
if (get_cpu_dec_win(win, &tgt, &base, &size))
continue;
if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
attrs = A3700_PTE_BLOCK_NORMAL;
else if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
attrs = A3700_PTE_BLOCK_DEVICE;
else
/* skip windows with other targets */
continue;
mvebu_mem_map[region].phys = base;
mvebu_mem_map[region].virt = base;
mvebu_mem_map[region].size = size;
mvebu_mem_map[region].attrs = attrs;
++region;
}
/* add list terminator */
mvebu_mem_map[region].size = 0;
mvebu_mem_map[region].attrs = 0;
}
void enable_caches(void)
{
build_mem_map();
icache_enable();
dcache_enable();
}
int a3700_dram_init(void)
{
int win;
gd->ram_size = 0;
for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
u32 base, tgt, size;
/* skip disabled windows */
if (get_cpu_dec_win(win, &tgt, &base, &size))
continue;
/* skip non-DRAM windows */
if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
continue;
/*
* It is possible that one image was built for boards with
* different RAM sizes, for example 512 MiB and 1 GiB.
* We therefore try to determine the actual RAM size in the
* window with get_ram_size.
*/
gd->ram_size += get_ram_size((void *)(size_t)base, size);
}
return 0;
}
struct a3700_dram_window {
size_t base, size;
};
static int dram_win_cmp(const void *a, const void *b)
{
size_t ab, bb;
ab = ((const struct a3700_dram_window *)a)->base;
bb = ((const struct a3700_dram_window *)b)->base;
if (ab < bb)
return -1;
else if (ab > bb)
return 1;
else
return 0;
}
int a3700_dram_init_banksize(void)
{
struct a3700_dram_window dram_wins[MVEBU_CPU_DEC_WINS];
int bank, win, ndram_wins;
u32 last_end;
size_t size;
ndram_wins = 0;
for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
u32 base, tgt, size;
/* skip disabled windows */
if (get_cpu_dec_win(win, &tgt, &base, &size))
continue;
/* skip non-DRAM windows */
if (tgt != MVEBU_CPU_DEC_WIN_CTRL_TGT_DRAM)
continue;
dram_wins[win].base = base;
dram_wins[win].size = size;
++ndram_wins;
}
qsort(dram_wins, ndram_wins, sizeof(dram_wins[0]), dram_win_cmp);
bank = 0;
last_end = -1;
for (win = 0; win < ndram_wins; ++win) {
/* again determining actual RAM size as in a3700_dram_init */
size = get_ram_size((void *)dram_wins[win].base,
dram_wins[win].size);
/*
* Check if previous window ends as the current starts. If yes,
* merge these windows into one "bank". This is possible by this
* simple check thanks to mem_map regions being qsorted in
* build_mem_map.
*/
if (last_end == dram_wins[win].base) {
gd->bd->bi_dram[bank - 1].size += size;
last_end += size;
} else {
if (bank == CONFIG_NR_DRAM_BANKS) {
printf("Need more CONFIG_NR_DRAM_BANKS\n");
return -ENOBUFS;
}
gd->bd->bi_dram[bank].start = dram_wins[win].base;
gd->bd->bi_dram[bank].size = size;
last_end = dram_wins[win].base + size;
++bank;
}
}
/*
* If there is more place for DRAM BANKS definitions than needed, fill
* the rest with zeros.
*/
for (; bank < CONFIG_NR_DRAM_BANKS; ++bank) {
gd->bd->bi_dram[bank].start = 0;
gd->bd->bi_dram[bank].size = 0;
}
return 0;
}
static u32 find_pcie_window_base(void)
{
int win;
for (win = 0; win < MVEBU_CPU_DEC_WINS; ++win) {
u32 base, tgt;
/* skip disabled windows */
if (get_cpu_dec_win(win, &tgt, &base, NULL))
continue;
if (tgt == MVEBU_CPU_DEC_WIN_CTRL_TGT_PCIE)
return base;
}
return -1;
}
int a3700_fdt_fix_pcie_regions(void *blob)
{
u32 new_ranges[14], base;
const u32 *ranges;
int node, len;
node = fdt_path_offset(blob, PCIE_PATH);
if (node < 0)
return node;
ranges = fdt_getprop(blob, node, "ranges", &len);
if (!ranges)
return -ENOENT;
if (len != sizeof(new_ranges))
return -EINVAL;
memcpy(new_ranges, ranges, len);
base = find_pcie_window_base();
if (base == -1)
return -ENOENT;
new_ranges[2] = cpu_to_fdt32(base);
new_ranges[4] = new_ranges[2];
new_ranges[9] = cpu_to_fdt32(base + 0x1000000);
new_ranges[11] = new_ranges[9];
return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len);
}
void reset_cpu(ulong ignored)
{
/*

View File

@ -2,5 +2,4 @@
#
# Copyright (C) 2016 Stefan Roese <sr@denx.de>
obj-y = cpu.o
obj-y += cache_llc.o
obj-y = cpu.o cache_llc.o dram.o

View File

@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Stefan Roese <sr@denx.de>
*/
#include <common.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <asm/system.h>
#include <linux/sizes.h>
DECLARE_GLOBAL_DATA_PTR;
#define MV_SIP_DRAM_SIZE 0x82000010
u64 a8k_dram_scan_ap_sz(void)
{
struct pt_regs pregs;
pregs.regs[0] = MV_SIP_DRAM_SIZE;
pregs.regs[1] = SOC_REGS_PHY_BASE;
smc_call(&pregs);
return pregs.regs[0];
}
int a8k_dram_init_banksize(void)
{
/*
* The firmware (ATF) leaves a 1G whole above the 3G mark for IO
* devices. Higher RAM is mapped at 4G.
*
* Config 2 DRAM banks:
* Bank 0 - max size 4G - 1G
* Bank 1 - ram size - 4G + 1G
*/
phys_size_t max_bank0_size = SZ_4G - SZ_1G;
gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
if (gd->ram_size <= max_bank0_size) {
gd->bd->bi_dram[0].size = gd->ram_size;
return 0;
}
gd->bd->bi_dram[0].size = max_bank0_size;
if (CONFIG_NR_DRAM_BANKS > 1) {
gd->bd->bi_dram[1].start = SZ_4G;
gd->bd->bi_dram[1].size = gd->ram_size - max_bank0_size;
}
return 0;
}

View File

@ -166,10 +166,23 @@ int ddr3_init(void);
/* Auto Voltage Scaling */
#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X)
void mv_avs_init(void);
void mv_rtc_config(void);
#else
static inline void mv_avs_init(void) {}
static inline void mv_rtc_config(void) {}
#endif
/* A8K dram functions */
u64 a8k_dram_scan_ap_sz(void);
int a8k_dram_init_banksize(void);
/* A3700 dram functions */
int a3700_dram_init(void);
int a3700_dram_init_banksize(void);
/* A3700 PCIe regions fixer for device tree */
int a3700_fdt_fix_pcie_regions(void *blob);
/*
* get_ref_clk
*

View File

@ -1366,16 +1366,16 @@ static void print_topology_details(const struct serdes_map *serdes_map,
DEBUG_INIT_S("board SerDes lanes topology details:\n");
DEBUG_INIT_S(" | Lane # | Speed | Type |\n");
DEBUG_INIT_S(" | Lane # | Speed | Type |\n");
DEBUG_INIT_S(" --------------------------------\n");
for (lane_num = 0; lane_num < count; lane_num++) {
if (serdes_map[lane_num].serdes_type == DEFAULT_SERDES)
continue;
DEBUG_INIT_S(" | ");
DEBUG_INIT_D(hws_get_physical_serdes_num(lane_num), 1);
DEBUG_INIT_S(" | ");
DEBUG_INIT_S(" | ");
DEBUG_INIT_D(serdes_map[lane_num].serdes_speed, 2);
DEBUG_INIT_S(" | ");
DEBUG_INIT_S(" | ");
DEBUG_INIT_S((char *)
serdes_type_to_string[serdes_map[lane_num].
serdes_type]);

View File

@ -257,6 +257,23 @@ u8 sys_env_device_rev_get(void)
return (value & (REVISON_ID_MASK)) >> REVISON_ID_OFFS;
}
void mv_rtc_config(void)
{
u32 i, val;
if (!(IS_ENABLED(CONFIG_ARMADA_38X) || IS_ENABLED(CONFIG_ARMADA_39X)))
return;
/* Activate pipe0 for read/write transaction, and set XBAR client number #1 */
val = 0x1 << DFX_PIPE_SELECT_PIPE0_ACTIVE_OFFS |
0x1 << DFX_PIPE_SELECT_XBAR_CLIENT_SEL_OFFS;
writel(val, MVEBU_DFX_BASE);
/* Set new RTC value for all memory wrappers */
for (i = 0; i < RTC_MEMORY_WRAPPER_COUNT; i++)
reg_write(RTC_MEMORY_WRAPPER_REG(i), RTC_MEMORY_WRAPPER_CTRL_VAL);
}
void mv_avs_init(void)
{
u32 sar_freq;

View File

@ -150,6 +150,19 @@
#define MPP_UART1_SET_MASK (~(0xff000))
#define MPP_UART1_SET_DATA (0x66000)
#define DFX_PIPE_SELECT_PIPE0_ACTIVE_OFFS 0
/* DFX_PIPE_SELECT_XBAR_CLIENT_SEL_OFFS: Since address completion in 14bit
* address mode, and given that [14:8] => [19:13], the 2 lower bits [9:8] =>
* [14:13] are dismissed. hence field offset is also shifted to 10
*/
#define DFX_PIPE_SELECT_XBAR_CLIENT_SEL_OFFS 10
#define RTC_MEMORY_CTRL_REG_BASE 0xE6000
#define RTC_MEMORY_WRAPPER_COUNT 8
#define RTC_MEMORY_WRAPPER_REG(i) (RTC_MEMORY_CTRL_REG_BASE + ((i) * 0x40))
#define RTC_MEMORY_CTRL_PDLVMC_FIELD_OFFS 6
#define RTC_MEMORY_WRAPPER_CTRL_VAL (0x1 << RTC_MEMORY_CTRL_PDLVMC_FIELD_OFFS)
#define AVS_DEBUG_CNTR_REG 0xe4124
#define AVS_DEBUG_CNTR_DEFAULT_VALUE 0x08008073

View File

@ -130,6 +130,9 @@ void board_init_f(ulong dummy)
/* Initialize Auto Voltage Scaling */
mv_avs_init();
/* Update read timing control for PCIe */
mv_rtc_config();
/*
* Return to the BootROM to continue the Marvell xmodem
* UART boot protocol. As initiated by the kwboot tool.

View File

@ -4,15 +4,17 @@
*/
#include <common.h>
#include <asm/arch/soc.h>
#include <asm/io.h>
#define RWTM_CMD_PARAM(i) (size_t)(0xd00b0000 + (i) * 4)
#define RWTM_CMD 0xd00b0040
#define RWTM_CMD_RETSTATUS 0xd00b0080
#define RWTM_CMD_STATUS(i) (size_t)(0xd00b0084 + (i) * 4)
#define RWTM_BASE (MVEBU_REGISTER(0xb0000))
#define RWTM_CMD_PARAM(i) (size_t)(RWTM_BASE + (i) * 4)
#define RWTM_CMD (RWTM_BASE + 0x40)
#define RWTM_CMD_RETSTATUS (RWTM_BASE + 0x80)
#define RWTM_CMD_STATUS(i) (size_t)(RWTM_BASE + 0x84 + (i) * 4)
#define RWTM_HOST_INT_RESET 0xd00b00c8
#define RWTM_HOST_INT_MASK 0xd00b00cc
#define RWTM_HOST_INT_RESET (RWTM_BASE + 0xc8)
#define RWTM_HOST_INT_MASK (RWTM_BASE + 0xcc)
#define SP_CMD_COMPLETE BIT(0)
#define MBOX_STS_SUCCESS (0x0 << 30)

View File

@ -4,18 +4,20 @@
*/
#include <common.h>
#include <init.h>
#include <asm/gpio.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <asm/io.h>
#include <dm.h>
#include <asm/gpio.h>
#include <clk.h>
#include <dm.h>
#include <env.h>
#include <spi.h>
#include <mvebu/comphy.h>
#include <miiphy.h>
#include <linux/string.h>
#include <linux/libfdt.h>
#include <fdt_support.h>
#include <init.h>
#include <linux/libfdt.h>
#include <linux/string.h>
#include <miiphy.h>
#include <mvebu/comphy.h>
#include <spi.h>
#include "mox_sp.h"
@ -28,32 +30,20 @@
#define MOX_MODULE_USB3 0x5
#define MOX_MODULE_PASSPCI 0x6
#define ARMADA_37XX_NB_GPIO_SEL 0xd0013830
#define ARMADA_37XX_SPI_CTRL 0xd0010600
#define ARMADA_37XX_SPI_CFG 0xd0010604
#define ARMADA_37XX_SPI_DOUT 0xd0010608
#define ARMADA_37XX_SPI_DIN 0xd001060c
#define ARMADA_37XX_NB_GPIO_SEL (MVEBU_REGISTER(0x13830))
#define ARMADA_37XX_SPI_CTRL (MVEBU_REGISTER(0x10600))
#define ARMADA_37XX_SPI_CFG (MVEBU_REGISTER(0x10604))
#define ARMADA_37XX_SPI_DOUT (MVEBU_REGISTER(0x10608))
#define ARMADA_37XX_SPI_DIN (MVEBU_REGISTER(0x1060c))
#define ETH1_PATH "/soc/internal-regs@d0000000/ethernet@40000"
#define MDIO_PATH "/soc/internal-regs@d0000000/mdio@32004"
#define SFP_GPIO_PATH "/soc/internal-regs@d0000000/spi@10600/moxtet@1/gpio@0"
#define PCIE_PATH "/soc/pcie@d0070000"
#define SFP_PATH "/sfp"
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
gd->ram_base = 0;
gd->ram_size = (phys_size_t)get_ram_size(0, 0x40000000);
return 0;
}
int dram_init_banksize(void)
{
gd->bd->bi_dram[0].start = (phys_addr_t)0;
gd->bd->bi_dram[0].size = gd->ram_size;
return 0;
}
#if defined(CONFIG_OF_BOARD_FIXUP)
int board_fix_fdt(void *blob)
{
@ -67,9 +57,11 @@ int board_fix_fdt(void *blob)
* to read SPI by reading/writing SPI registers directly
*/
writel(0x563fa, ARMADA_37XX_NB_GPIO_SEL);
writel(0x10df, ARMADA_37XX_SPI_CFG);
writel(0x2005b, ARMADA_37XX_SPI_CTRL);
/* put pin from GPIO to SPI mode */
clrbits_le32(ARMADA_37XX_NB_GPIO_SEL, BIT(12));
/* enable SPI CS1 */
setbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2))
udelay(1);
@ -89,7 +81,8 @@ int board_fix_fdt(void *blob)
size = i;
writel(0x5b, ARMADA_37XX_SPI_CTRL);
/* disable SPI CS1 */
clrbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17));
if (size > 1 && (topology[1] == MOX_MODULE_PCI ||
topology[1] == MOX_MODULE_USB3 ||
@ -112,6 +105,11 @@ int board_fix_fdt(void *blob)
return 0;
}
if (a3700_fdt_fix_pcie_regions(blob) < 0) {
printf("Cannot fix PCIe regions in U-Boot's device tree!\n");
return 0;
}
return 0;
}
#endif
@ -456,24 +454,22 @@ int last_stage_init(void)
}
break;
case MOX_MODULE_PCI:
if (pci) {
if (pci)
printf("Error: Only one Mini-PCIe module is supported!\n");
} else if (usb) {
else if (usb)
printf("Error: Mini-PCIe module cannot come after USB 3.0 module!\n");
} else if (i && (i != 1 || !passpci)) {
else if (i && (i != 1 || !passpci))
printf("Error: Mini-PCIe module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
} else {
else
++pci;
}
break;
case MOX_MODULE_TOPAZ:
if (topaz) {
if (topaz)
printf("Error: Only one Topaz module is supported!\n");
} else if (peridot >= 3) {
else if (peridot >= 3)
printf("Error: At most two Peridot modules can come before Topaz module!\n");
} else {
else
++topaz;
}
break;
case MOX_MODULE_PERIDOT:
if (sfp || topaz) {
@ -486,24 +482,22 @@ int last_stage_init(void)
}
break;
case MOX_MODULE_USB3:
if (pci) {
if (pci)
printf("Error: USB 3.0 module cannot come after Mini-PCIe module!\n");
} else if (usb) {
else if (usb)
printf("Error: Only one USB 3.0 module is supported!\n");
} else if (i && (i != 1 || !passpci)) {
else if (i && (i != 1 || !passpci))
printf("Error: USB 3.0 module should be the first connected module or come right after Passthrough Mini-PCIe module!\n");
} else {
else
++usb;
}
break;
case MOX_MODULE_PASSPCI:
if (passpci) {
if (passpci)
printf("Error: Only one Passthrough Mini-PCIe module is supported!\n");
} else if (i != 0) {
else if (i != 0)
printf("Error: Passthrough Mini-PCIe module should be the first connected module!\n");
} else {
else
++passpci;
}
}
}
@ -548,3 +542,267 @@ int last_stage_init(void)
return 0;
}
#if defined(CONFIG_OF_BOARD_SETUP)
static int vnode_by_path(void *blob, const char *fmt, va_list ap)
{
char path[128];
vsnprintf(path, 128, fmt, ap);
return fdt_path_offset(blob, path);
}
static int node_by_path(void *blob, const char *fmt, ...)
{
va_list ap;
int res;
va_start(ap, fmt);
res = vnode_by_path(blob, fmt, ap);
va_end(ap);
return res;
}
static int phandle_by_path(void *blob, const char *fmt, ...)
{
va_list ap;
int node, phandle, res;
va_start(ap, fmt);
node = vnode_by_path(blob, fmt, ap);
va_end(ap);
if (node < 0)
return node;
phandle = fdt_get_phandle(blob, node);
if (phandle > 0)
return phandle;
phandle = fdt_get_max_phandle(blob);
if (phandle < 0)
return phandle;
phandle += 1;
res = fdt_setprop_u32(blob, node, "linux,phandle", phandle);
if (res < 0)
return res;
res = fdt_setprop_u32(blob, node, "phandle", phandle);
if (res < 0)
return res;
return phandle;
}
static int enable_by_path(void *blob, const char *fmt, ...)
{
va_list ap;
int node;
va_start(ap, fmt);
node = vnode_by_path(blob, fmt, ap);
va_end(ap);
if (node < 0)
return node;
return fdt_setprop_string(blob, node, "status", "okay");
}
static bool is_topaz(int id)
{
return topaz && id == peridot + topaz - 1;
}
static int switch_addr(int id)
{
return is_topaz(id) ? 0x2 : 0x10 + id;
}
static int setup_switch(void *blob, int id)
{
int res, addr, i, node, phandle;
addr = switch_addr(id);
/* first enable the switch by setting status = "okay" */
res = enable_by_path(blob, MDIO_PATH "/switch%i@%x", id, addr);
if (res < 0)
return res;
/*
* now if there are more switches or a SFP module coming after,
* enable corresponding ports
*/
if (id < peridot + topaz - 1) {
res = enable_by_path(blob,
MDIO_PATH "/switch%i@%x/ports/port@a",
id, addr);
} else if (id == peridot - 1 && !topaz && sfp) {
res = enable_by_path(blob,
MDIO_PATH "/switch%i@%x/ports/port-sfp@a",
id, addr);
} else {
res = 0;
}
if (res < 0)
return res;
if (id >= peridot + topaz - 1)
return 0;
/* finally change link property if needed */
node = node_by_path(blob, MDIO_PATH "/switch%i@%x/ports/port@a", id,
addr);
if (node < 0)
return node;
for (i = id + 1; i < peridot + topaz; ++i) {
phandle = phandle_by_path(blob,
MDIO_PATH "/switch%i@%x/ports/port@%x",
i, switch_addr(i),
is_topaz(i) ? 5 : 9);
if (phandle < 0)
return phandle;
if (i == id + 1)
res = fdt_setprop_u32(blob, node, "link", phandle);
else
res = fdt_appendprop_u32(blob, node, "link", phandle);
if (res < 0)
return res;
}
return 0;
}
static int remove_disabled_nodes(void *blob)
{
while (1) {
int res, offset;
offset = fdt_node_offset_by_prop_value(blob, -1, "status",
"disabled", 9);
if (offset < 0)
break;
res = fdt_del_node(blob, offset);
if (res < 0)
return res;
}
return 0;
}
int ft_board_setup(void *blob, bd_t *bd)
{
int node, phandle, res;
/*
* If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are
* connected, enable the PCIe node.
*/
if (pci || usb || passpci) {
node = fdt_path_offset(blob, PCIE_PATH);
if (node < 0)
return node;
res = fdt_setprop_string(blob, node, "status", "okay");
if (res < 0)
return res;
/* Fix PCIe regions for devices with 4 GB RAM */
res = a3700_fdt_fix_pcie_regions(blob);
if (res < 0)
return res;
}
/*
* If MOX C (Topaz switch) and/or MOX E (Peridot switch) are connected,
* enable the eth1 node and setup the switches.
*/
if (peridot || topaz) {
int i;
res = enable_by_path(blob, ETH1_PATH);
if (res < 0)
return res;
for (i = 0; i < peridot + topaz; ++i) {
res = setup_switch(blob, i);
if (res < 0)
return res;
}
}
/*
* If MOX D (SFP cage module) is connected, enable the SFP node and eth1
* node. If there is no Peridot switch between MOX A and MOX D, add link
* to the SFP node to eth1 node.
* Also enable and configure SFP GPIO controller node.
*/
if (sfp) {
res = enable_by_path(blob, SFP_PATH);
if (res < 0)
return res;
res = enable_by_path(blob, ETH1_PATH);
if (res < 0)
return res;
if (!peridot) {
phandle = phandle_by_path(blob, SFP_PATH);
if (phandle < 0)
return res;
node = node_by_path(blob, ETH1_PATH);
if (node < 0)
return node;
res = fdt_setprop_u32(blob, node, "sfp", phandle);
if (res < 0)
return res;
res = fdt_setprop_string(blob, node, "phy-mode",
"sgmii");
if (res < 0)
return res;
}
res = enable_by_path(blob, SFP_GPIO_PATH);
if (res < 0)
return res;
if (sfp_pos) {
char newname[16];
/* moxtet-sfp is on non-zero position, change default */
node = node_by_path(blob, SFP_GPIO_PATH);
if (node < 0)
return node;
res = fdt_setprop_u32(blob, node, "reg", sfp_pos);
if (res < 0)
return res;
sprintf(newname, "gpio@%x", sfp_pos);
res = fdt_set_name(blob, node, newname);
if (res < 0)
return res;
}
}
fdt_fixup_ethernet(blob);
/* Finally remove disabled nodes, as per Rob Herring's request. */
remove_disabled_nodes(blob);
return 0;
}
#endif

View File

@ -66,7 +66,11 @@ static struct mv_ddr_topology_map board_topology_map = {
BUS_MASK_32BIT_ECC, /* subphys mask */
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
{ {0} }, /* raw spd data */
{0} /* timing parameters */
{0}, /* timing parameters */
{ {0} }, /* electrical configuration */
{0}, /* electrical parameters */
0, /* Clock enable mask */
160 /* Clock delay */
};
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)

View File

@ -0,0 +1,62 @@
menu "ClearFog configuration"
depends on TARGET_CLEARFOG
config TARGET_CLEARFOG_BASE
bool "Use ClearFog Base static configuration"
help
Use the ClearFog Base as the static configuration instead of the
default which uses the ClearFog Pro.
Runtime board detection is always attempted and used if available. The
static configuration is used as a fallback in cases where runtime
detection is disabled, is not available in hardware, or otherwise fails.
Only newer revisions of the ClearFog product line support runtime
detection via additional EEPROM hardware. This option enables selecting
the Base variant for older hardware revisions.
config CLEARFOG_CON3_SATA
bool "Use CON3 slot in SATA mode"
help
Use the CON3 port with SATA protocol instead of the default PCIe.
The ClearFog port allows usage of either mSATA or miniPCIe
modules, but the desired protocol must be configured at build
time since it affects the SerDes topology layout.
config CLEARFOG_CON2_SATA
bool "Use CON2 slot in SATA mode"
depends on !TARGET_CLEARFOG_BASE
help
Use the CON2 port with SATA protocol instead of the default PCIe.
The ClearFog port allows usage of either mSATA or miniPCIe
modules, but the desired protocol must be configured at build
time since it affects the SerDes topology layout.
config CLEARFOG_SFP_25GB
bool "Enable 2.5 Gbps mode for SFP"
help
Set the SFP module connection to support 2.5 Gbps transfer speed for the
SGMII connection (requires a supporting SFP). By default, transfer speed
of 1.25 Gbps is used, suitable for a more common 1 Gbps SFP module.
config ENV_SIZE
hex "Environment Size"
default 0x10000
config ENV_OFFSET
hex "Environment offset"
default 0xF0000
config ENV_SECT_SIZE
hex "Environment Sector-Size"
# Use SPI flash erase block size of 4 KiB
default 0x1000 if MVEBU_SPL_BOOT_DEVICE_SPI
# Use optimistic 64 KiB erase block, will vary between actual media
default 0x10000 if MVEBU_SPL_BOOT_DEVICE_MMC
config SYS_SPI_U_BOOT_OFFS
hex "address of u-boot payload in SPI flash"
default 0x20000
depends on MVEBU_SPL_BOOT_DEVICE_SPI
endmenu

View File

@ -42,6 +42,7 @@ static void cf_read_tlv_data(void)
read_tlv_data(&cf_tlv_data);
}
/* The starting board_serdes_map reflects original Clearfog Pro usage */
static struct serdes_map board_serdes_map[] = {
{SATA0, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0},
{SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
@ -51,20 +52,60 @@ static struct serdes_map board_serdes_map[] = {
{SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
};
void config_cfbase_serdes_map(void)
{
board_serdes_map[4].serdes_type = USB3_HOST0;
board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
}
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{
cf_read_tlv_data();
/* Apply build configuration options before runtime configuration */
if (IS_ENABLED(CONFIG_CLEARFOG_SFP_25GB))
board_serdes_map[5].serdes_speed = SERDES_SPEED_3_125_GBPS;
if (IS_ENABLED(CONFIG_CLEARFOG_CON2_SATA)) {
board_serdes_map[4].serdes_type = SATA2;
board_serdes_map[4].serdes_speed = SERDES_SPEED_3_GBPS;
board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[4].swap_rx = 1;
}
if (IS_ENABLED(CONFIG_CLEARFOG_CON3_SATA)) {
board_serdes_map[2].serdes_type = SATA1;
board_serdes_map[2].serdes_speed = SERDES_SPEED_3_GBPS;
board_serdes_map[2].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[2].swap_rx = 1;
}
/* Apply runtime detection changes */
if (sr_product_is(&cf_tlv_data, "Clearfog GTR")) {
board_serdes_map[0].serdes_type = PEX0;
board_serdes_map[0].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[0].serdes_mode = PEX_ROOT_COMPLEX_X1;
}
if (sr_product_is(&cf_tlv_data, "Clearfog Base")) {
board_serdes_map[4].serdes_type = USB3_HOST0;
board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[4].serdes_mode = SERDES_DEFAULT_MODE;
} else if (sr_product_is(&cf_tlv_data, "Clearfog Pro")) {
/* handle recognized product as noop, no adjustment required */
} else if (sr_product_is(&cf_tlv_data, "Clearfog Base")) {
config_cfbase_serdes_map();
} else {
/*
* Fallback to static default. EEPROM TLV support is not
* enabled, runtime detection failed, hardware support is not
* present, EEPROM is corrupt, or an unrecognized product name
* is present.
*/
if (IS_ENABLED(CONFIG_SPL_CMD_TLV_EEPROM))
puts("EEPROM TLV detection failed: ");
puts("Using static config for ");
if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE)) {
puts("Clearfog Base.\n");
config_cfbase_serdes_map();
} else {
puts("Clearfog Pro.\n");
}
}
*serdes_map_array = board_serdes_map;
@ -170,7 +211,9 @@ int board_init(void)
int checkboard(void)
{
char *board = "ClearFog";
char *board = "Clearfog Pro";
if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE))
board = "Clearfog Base";
cf_read_tlv_data();
if (strlen(cf_tlv_data.tlv_product_name[0]) > 0)
@ -200,6 +243,10 @@ int board_late_init(void)
env_set("fdtfile", "armada-385-clearfog-gtr-s4.dtb");
else if (sr_product_is(&cf_tlv_data, "Clearfog GTR L8"))
env_set("fdtfile", "armada-385-clearfog-gtr-l8.dtb");
else if (IS_ENABLED(CONFIG_TARGET_CLEARFOG_BASE))
env_set("fdtfile", "armada-388-clearfog-base.dtb");
else
env_set("fdtfile", "armada-388-clearfog-pro.dtb");
return 0;
}

View File

@ -9,8 +9,6 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_CLEARFOG=y
CONFIG_MVEBU_SPL_BOOT_DEVICE_MMC=y
CONFIG_ENV_SIZE=0x10000
CONFIG_ENV_OFFSET=0xF0000
CONFIG_DM_GPIO=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y

View File

@ -8,7 +8,7 @@ CONFIG_ENV_SIZE=0x10000
CONFIG_ENV_SECT_SIZE=0x10000
CONFIG_ENV_OFFSET=0x180000
CONFIG_DM_GPIO=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_NR_DRAM_BANKS=2
CONFIG_DEBUG_UART_BASE=0xd0012000
CONFIG_DEBUG_UART_CLOCK=25804800
CONFIG_DEBUG_UART=y
@ -37,6 +37,7 @@ CONFIG_CMD_BTRFS=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_MAC_PARTITION=y
CONFIG_OF_BOARD_FIXUP=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_DEFAULT_DEVICE_TREE="armada-3720-turris-mox"
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y

View File

@ -106,8 +106,10 @@ static int mv_ddr_training_params_set(u8 dev_num)
struct tune_train_params params;
int status;
u32 cs_num;
int ck_delay;
cs_num = mv_ddr_cs_num_get();
ck_delay = mv_ddr_ck_delay_get();
/* NOTE: do not remove any field initilization */
params.ck_delay = TUNE_TRAINING_PARAMS_CK_DELAY;
@ -131,6 +133,9 @@ static int mv_ddr_training_params_set(u8 dev_num)
params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS;
}
if (ck_delay > 0)
params.ck_delay = ck_delay;
status = ddr3_tip_tune_training_params(dev_num, &params);
if (MV_OK != status) {
printf("%s Training Sequence - FAILED\n", ddr_type);

View File

@ -127,6 +127,9 @@ struct mv_ddr_topology_map {
/* Clock enable mask */
u32 clk_enable;
/* Clock delay */
int ck_delay;
};
enum mv_ddr_iface_mode {

View File

@ -229,6 +229,16 @@ int mv_ddr_is_ecc_ena(void)
return 0;
}
int mv_ddr_ck_delay_get(void)
{
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
if (tm->ck_delay)
return tm->ck_delay;
return -1;
}
/* translate topology map definition to real memory size in bits */
static unsigned int mem_size[] = {
ADDR_SIZE_512MB,

View File

@ -319,6 +319,7 @@ unsigned short mv_ddr_bus_bit_mask_get(void);
unsigned int mv_ddr_if_bus_width_get(void);
unsigned int mv_ddr_cs_num_get(void);
int mv_ddr_is_ecc_ena(void);
int mv_ddr_ck_delay_get(void);
unsigned long long mv_ddr_mem_sz_per_cs_get(void);
unsigned long long mv_ddr_mem_sz_get(void);
unsigned int mv_ddr_rtt_nom_get(void);

View File

@ -434,10 +434,6 @@ static u32 ddr3_init_main(void)
scrub_size = 0;
#endif
#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
ecc = DRAM_ECC;
#endif
#if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT)
ecc = 0;
if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_ECC))

View File

@ -104,15 +104,59 @@
#define BOOT_TARGET_DEVICES_MMC(func)
#endif
#ifdef CONFIG_SCSI
#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
#else
#define BOOT_TARGET_DEVICES_SCSI(func)
#endif
#ifdef CONFIG_USB_STORAGE
#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
#else
#define BOOT_TARGET_DEVICES_USB(func)
#endif
#ifndef CONFIG_SCSI
#define BOOT_TARGET_DEVICES_SCSI_BUS0(func)
#define BOOT_TARGET_DEVICES_SCSI_BUS1(func)
#define BOOT_TARGET_DEVICES_SCSI_BUS2(func)
#else
/*
* With SCSI enabled, M.2 SATA is always located on bus 0
*/
#define BOOT_TARGET_DEVICES_SCSI_BUS0(func) func(SCSI, scsi, 0)
/*
* Either one or both mPCIe slots may be configured as mSATA interfaces. The
* SCSI bus ids are assigned based on sequence of hardware present, not always
* tied to hardware slot ids. As such, use second SCSI bus if either slot is
* set for SATA, and only use third SCSI bus if both slots are SATA enabled.
*/
#if defined (CONFIG_CLEARFOG_CON2_SATA) || defined (CONFIG_CLEARFOG_CON3_SATA)
#define BOOT_TARGET_DEVICES_SCSI_BUS1(func) func(SCSI, scsi, 1)
#else
#define BOOT_TARGET_DEVICES_SCSI_BUS1(func)
#endif
#if defined (CONFIG_CLEARFOG_CON2_SATA) && defined (CONFIG_CLEARFOG_CON3_SATA)
#define BOOT_TARGET_DEVICES_SCSI_BUS2(func) func(SCSI, scsi, 2)
#else
#define BOOT_TARGET_DEVICES_SCSI_BUS2(func)
#endif
#endif /* CONFIG_SCSI */
/*
* The SCSI buses are attempted in increasing bus order, there is no current
* mechanism to alter the default bus priority order for booting.
*/
#define BOOT_TARGET_DEVICES(func) \
BOOT_TARGET_DEVICES_MMC(func) \
BOOT_TARGET_DEVICES_SCSI(func) \
BOOT_TARGET_DEVICES_USB(func) \
BOOT_TARGET_DEVICES_SCSI_BUS0(func) \
BOOT_TARGET_DEVICES_SCSI_BUS1(func) \
BOOT_TARGET_DEVICES_SCSI_BUS2(func) \
func(PXE, pxe, na) \
func(DHCP, dhcp, na)
@ -134,7 +178,6 @@
#define CONFIG_EXTRA_ENV_SETTINGS \
RELOCATION_LIMITS_ENV_SETTINGS \
LOAD_ADDRESS_ENV_SETTINGS \
"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
"console=ttyS0,115200\0" \
BOOTENV