ADD: [hw29] support for new platform

BugzId: 74037
This commit is contained in:
Marcel Reichmuth 2022-03-01 14:34:23 +01:00
parent ea62802ceb
commit b9d1ec9479
17 changed files with 2039 additions and 0 deletions

View File

@ -86,6 +86,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \
armada-385-hw14.dtb \
armada-385-hw18.dtb \
armada-385-hw17.dtb \
armada-385-hw29.dtb \
armada-3720-db.dtb \
armada-3720-espressobin.dtb \
armada-375-db.dtb \

View File

@ -0,0 +1,244 @@
/*
* Device Tree file for the NetModule NBHW17 (NB2800)
*
* Copyright (C) 2016 NetModule
*
* Stefan Eichenberger <stefan.eichenberger@netmodule.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include "armada-385.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "NetModule Router HW29 with Armada A385";
compatible = "marvell,aramda385-nbhw29", "marvell,armada385", "marvell,armada380";
aliases {
/* So that mvebu u-boot can update the MAC addresses */
ethernet0 = &eth0;
ethernet1 = &eth1;
ethernet2 = &eth2;
};
memory {
device_type = "memory";
reg = <0x00000000 0x40000000>; /* 1 GB */
};
soc {
ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 /* CESA 0 SRAM */
MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 /* CESA 1 SRAM */
MBUS_ID(0x01, 0x3e) 0 0xfd000000 0x20000>; /* FPGA */
gpiofpga: gpio@fd0000000 {
compatible = "nm,nbhw-fpga";
reg = <MBUS_ID(0x01, 0x3e) 0 0x20000>; /* This translates to 0xfd000000 */
ngpios = <8500>;
gpio-controller;
gpio-bank-name = "FPGA";
#gpio-cells = <2>;
spi-ss = <&gpio1 5 0>; /* SS */
spi-sdo = <&gpio1 6 0>; /* SDO slave data out */
spi-sck = <&gpio1 7 0>; /* SCK */
spi-sdi = <&gpio1 8 0>; /* SDI slave data in */
fpga-reset = <&gpio0 19 0>; /* FPGA reset */
fpga-reset-logic = <&gpio1 12 0>; /* FPGA reset logic (after load)*/
};
fpga_conf: fpgaconf@0 {
compatible = "nm,nbhw29-fpga-config";
leds = <&gpiofpga 256 0>, <&gpiofpga 257 0>, <&gpiofpga 258 0>,
<&gpiofpga 259 0>, <&gpiofpga 260 0>, <&gpiofpga 261 0>,
<&gpiofpga 262 0>, <&gpiofpga 263 0>, <&gpiofpga 264 0>,
<&gpiofpga 265 0>, <&gpiofpga 266 0>, <&gpiofpga 267 0>,
<&gpiofpga 268 0>, <&gpiofpga 269 0>, <&gpiofpga 270 0>,
<&gpiofpga 271 0>;
misc@0 {
#gpio-cells = <4>;
// gpio controller, gpio number, low/high_active, default value
sd-card-enable = <&gpiofpga 65 GPIO_ACTIVE_HIGH 1>;
rs232-enable = <&gpiofpga 288 GPIO_ACTIVE_HIGH 1>;
};
// pcie slot 0
pcieslot@0 {
reset = <&gpiofpga 384 GPIO_ACTIVE_HIGH 1>;
power = <&gpiofpga 400 GPIO_ACTIVE_HIGH 0>;
power-3v8 = <&gpiofpga 464 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 2053 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 2069 GPIO_ACTIVE_LOW 1>;
clk = <&gpiofpga 416 GPIO_ACTIVE_HIGH 1>;
reset-1v8 = <&gpiofpga 2496 GPIO_ACTIVE_HIGH 0>;
reset-3v3 = <&gpiofpga 2497 GPIO_ACTIVE_HIGH 0>;
wdis-1v8 = <&gpiofpga 2498 GPIO_ACTIVE_HIGH 0>;
wdis-3v3 = <&gpiofpga 2499 GPIO_ACTIVE_HIGH 0>;
};
// pcie slot 1
pcieslot@1 {
reset = <&gpiofpga 385 GPIO_ACTIVE_HIGH 1>;
power = <&gpiofpga 401 GPIO_ACTIVE_HIGH 0>;
power-3v8 = <&gpiofpga 465 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 4101 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 4117 GPIO_ACTIVE_LOW 1>;
clk = <&gpiofpga 417 GPIO_ACTIVE_HIGH 1>;
reset-1v8 = <&gpiofpga 4544 GPIO_ACTIVE_HIGH 0>;
reset-3v3 = <&gpiofpga 4545 GPIO_ACTIVE_HIGH 0>;
wdis-1v8 = <&gpiofpga 4546 GPIO_ACTIVE_HIGH 0>;
wdis-3v3 = <&gpiofpga 4547 GPIO_ACTIVE_HIGH 0>;
};
// extension slot (ethernet switch)
pcieslot@2 {
reset = <&gpiofpga 386 GPIO_ACTIVE_HIGH 1>;
power = <&gpiofpga 402 GPIO_ACTIVE_HIGH 0>;
power-3v8 = <&gpiofpga 466 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 6149 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 6165 GPIO_ACTIVE_LOW 1>;
clk = <&gpiofpga 418 GPIO_ACTIVE_HIGH 0>;
reset-1v8 = <&gpiofpga 6592 GPIO_ACTIVE_HIGH 0>;
reset-3v3 = <&gpiofpga 6593 GPIO_ACTIVE_HIGH 0>;
wdis-1v8 = <&gpiofpga 6594 GPIO_ACTIVE_HIGH 0>;
wdis-3v3 = <&gpiofpga 6595 GPIO_ACTIVE_HIGH 0>;
};
// low end extension 0 (mapped in fpga as a pcie slot)
pcieslot@3 {
reset = <&gpiofpga 387 GPIO_ACTIVE_HIGH 1>;
power = <&gpiofpga 403 GPIO_ACTIVE_HIGH 0>;
power-3v8 = <&gpiofpga 467 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 8197 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 8213 GPIO_ACTIVE_LOW 1>;
reset-1v8 = <&gpiofpga 8640 GPIO_ACTIVE_HIGH 0>;
reset-3v3 = <&gpiofpga 8641 GPIO_ACTIVE_HIGH 0>;
wdis-1v8 = <&gpiofpga 8642 GPIO_ACTIVE_HIGH 0>;
wdis-3v3 = <&gpiofpga 8643 GPIO_ACTIVE_HIGH 0>;
};
// low end extension 1 (mapped in fpga as a pcie slot)
pcieslot@4 {
reset = <&gpiofpga 388 GPIO_ACTIVE_HIGH 1>;
power = <&gpiofpga 404 GPIO_ACTIVE_HIGH 0>;
power-3v8 = <&gpiofpga 468 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 10245 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 10261 GPIO_ACTIVE_LOW 1>;
reset-1v8 = <&gpiofpga 10688 GPIO_ACTIVE_HIGH 0>;
reset-3v3 = <&gpiofpga 10689 GPIO_ACTIVE_HIGH 0>;
wdis-1v8 = <&gpiofpga 10690 GPIO_ACTIVE_HIGH 0>;
wdis-3v3 = <&gpiofpga 10691 GPIO_ACTIVE_HIGH 0>;
};
// sfp (mapped in fpga also as a pcie slot)
sfp@0 {
power = <&gpiofpga 405 GPIO_ACTIVE_HIGH 1>;
reset = <&gpiofpga 389 GPIO_ACTIVE_HIGH 0>;
};
};
internal-regs {
i2c0: i2c@11000 {
status = "okay";
clock-frequency = <100000>;
};
i2c1: i2c@11100 {
status = "disabled";
};
sata@a8000 {
status = "disabled";
};
// Never ever enable this SATA controller on A385/A380 !
sata@e0000 {
status = "disabled";
};
sdhci@d8000 {
broken-cd;
wp-inverted;
no-1-8-v;
bus-width = <8>;
status = "okay";
};
serial@12000 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
serial@12100 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
};
usb@58000 {
status = "okay";
};
};
pcie-controller {
status = "okay";
/*
* The two PCIe units are accessible through
* standard PCIe slots on the board.
*/
pcie@3,0 {
/* Port 2, Lane 0 */
status = "okay";
};
pcie@4,0 {
/* Port 3, Lane 0 */
status = "okay";
};
};
};
};
&eth0 {
status = "disabled";
phy-mode = "sgmii";
phy = <&phy1>;
};
&eth1 {
status = "disabled";
phy-mode = "sgmii";
};
&eth2 {
status = "disabled";
phy-mode = "sgmii";
phy = <&phy0>;
};
&mdio {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
phy0: ethernet-phy@0 {
marvell,reg-init = <3 16 0 0x101e>;
reg = <0>;
};
phy1: ethernet-phy@1 {
marvell,reg-init = <3 16 0 0x101e>;
reg = <1>;
};
};

View File

@ -0,0 +1,48 @@
/*
* Device Tree file for the NetModule NBHW18 (NB1800) base variant
*
* Copyright (C) 2016 NetModule
*
* Stefan Eichenberger <stefan.eichenberger@netmodule.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
/dts-v1/;
#include "armada-385-hw29-common.dtsi"
/ {
model = "NetModule Router HW29 with Armada A385 (NG1850)";
chosen {
stdout-path = "serial0:115200n8";
};
soc {
internal-regs {
serial@12000 {
u-boot,dm-spl;
};
};
};
};
&eth0 {
status = "okay";
};
// SFP-Port
&eth1 {
status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
};
&eth2 {
status = "okay";
};

View File

@ -0,0 +1,54 @@
/*
* Device Tree file for the NetModule HW29 (NG1850) base variant
*
* Copyright (C) 2016 NetModule
*
* Stefan Eichenberger <stefan.eichenberger@netmodule.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
/dts-v1/;
#include "armada-385-hw29-common.dtsi"
/ {
model = "NetModule Router HW29 with Armada A385 (NG1850)";
soc {
gpiofpga: gpio@fd0000000 {
fpga-cinit = <&gpio0 13 0>; /* FPGA cinit */
fpga-cdone = <&gpio0 21 0>; /* FPGA cdone */
};
};
};
// LAN1 or SWITCH
// In U-Boot we only support the configuration with two separate eth phys
// without eth switch. This ensures that U-Boot initializes both eth phys
// properly by calling drivers/net/phy/marvel.c:m88e1518_config(..) which
// executes some quirks to work around some MV88E1512 phy erratas. Because
// the linux kernel does not apply those quirks, the phys would otherwise
// not work later in Linux, if they were not initialized by U-Boot.
// (To use the ethernet switch in U-Boot, eth0/LAN1 would have to be
// configured as fixed link like eth1. Then the switch would work in U-Boot,
// but the phy for eth0/LAN1 would not be initialized.)
&eth0 {
status = "okay";
};
// SFP-Port
&eth1 {
status = "disabled";
fixed-link {
speed = <1000>;
full-duplex;
};
};
// LAN0
&eth2 {
status = "okay";
};

View File

@ -100,6 +100,10 @@ config TARGET_NM_HW17
bool "Support HW17"
select 88F6820
config TARGET_NM_HW29
bool "Support HW29"
select 88F6820
config TARGET_TURRIS_OMNIA
bool "Support Turris Omnia"
select 88F6820
@ -157,6 +161,7 @@ config SYS_BOARD
default "hw14" if TARGET_NM_HW14
default "hw18" if TARGET_NM_HW18
default "hw17" if TARGET_NM_HW17
default "hw29" if TARGET_NM_HW29
config SYS_CONFIG_NAME
default "clearfog" if TARGET_CLEARFOG
@ -173,6 +178,7 @@ config SYS_CONFIG_NAME
default "armada-385-hw14" if TARGET_NM_HW14
default "armada-385-hw18" if TARGET_NM_HW18
default "armada-385-hw17" if TARGET_NM_HW17
default "armada-385-hw29" if TARGET_NM_HW29
config SYS_VENDOR
default "Marvell" if TARGET_DB_MV784MP_GP
@ -187,6 +193,7 @@ config SYS_VENDOR
default "nm" if TARGET_NM_HW14
default "nm" if TARGET_NM_HW18
default "nm" if TARGET_NM_HW17
default "nm" if TARGET_NM_HW29
config SYS_SOC
default "mvebu"

View File

@ -20,6 +20,8 @@
#define PMIC_REG_GPIO_MODE0_7 0x1D /* Control register for GPIOs 0..7 */
#define PMIC_REG_GPIO_MODE8_15 0x1E /* Control register for GPIOs 8..15 */
#define PMIC_REG_LDO6_CONT 0x2B
#define PMIC_REG_BBAT_CONT 0xC5 /* Control register for backup battery */
#define PMIC_REG_BUCK_ILIM_A 0x9A

View File

@ -0,0 +1,6 @@
DB_88F6820_GP BOARD
M: Stefan Roese <sr@denx.de>
S: Maintained
F: board/Marvell/db-88f6820-gp/
F: include/configs/db-88f6820-gp.h
F: configs/db-88f6820-gp_defconfig

35
board/nm/hw29/Makefile Normal file
View File

@ -0,0 +1,35 @@
#
# Copyright (C) 2015 Stefan Roese <sr@denx.de>
#
# SPDX-License-Identifier: GPL-2.0+
#
commonobj = ../common/bdparser.o \
../common/nbhw_bd.o \
../common/nbhw_env.o \
../common/nbhw_init.o \
../common/nbhw_fileaccess.o \
../common/nbhw_fpga_gpio.o \
../common/nbhw_partitions.o \
../common/nbhw_pcie_fixup.o
ccflags-y := -I../common
ifndef CONFIG_SPL_BUILD
obj-y := board.o nbhw_gpio.o nbhw_fpga_config.o \
../common/nbhw_sim.o nbhw_sim.o \
../common/da9063.o \
../common/lattice/core.o \
../common/lattice/hardware.o \
../common/lattice/intrface.o \
../common/lattice/SSPIEm.o \
../common/lattice/util.o $(commonobj)
else
obj-y := board.o nbhw_gpio.o \
../common/da9063.o \
../common/nbhw_bd.o \
../common/nbhw_partitions.o \
../common/bdparser.o \
../common/nbhw_bd.o
endif

18
board/nm/hw29/README Normal file
View File

@ -0,0 +1,18 @@
Update from original Marvell U-Boot to mainline U-Boot:
-------------------------------------------------------
The resulting image including the SPL binary with the
full DDR setup is "u-boot-spl.kwb".
To update the SPI NOR flash, please use the following
command:
=> sf probe;tftpboot 2000000 db-88f6820-gp/u-boot-spl.kwb;\
sf update 2000000 0 60000
Note that the original Marvell U-Boot seems to have
problems with the "sf update" command. This does not
work reliable. So here this command should be used:
=> sf probe;tftpboot 2000000 db-88f6820-gp/u-boot-spl.kwb;\
sf erase 0 60000;sf write 2000000 0 60000

822
board/nm/hw29/board.c Normal file
View File

@ -0,0 +1,822 @@
/*
* Copyright (C) 2015 Stefan Roese <sr@denx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#undef DEBUG
#include <common.h>
#include <i2c.h>
#include <miiphy.h>
#include <netdev.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <mmc.h>
#include <spl.h>
#include <linux/mbus.h>
#include <environment.h>
#include <fdt_support.h>
#include <dm.h>
#include <wdt.h>
#include <console.h> /* ctrlc */
#include <asm/gpio.h>
#include "nbhw_gpio.h"
#include "../common/nbhw_init.h"
#include "../common/nbhw_env.h"
#include "../common/nbhw_bd.h"
#include "../common/da9063.h"
#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
#include <../serdes/a38x/high_speed_env_spec.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Those values and defines are taken from the Marvell U-Boot version
* "u-boot-2013.01-2014_T3.0"
*/
#define GPP_OUT_ENA_LOW (~(BIT(6) | BIT(19) | BIT(29))) /* 1=Input, default input */
#define GPP_OUT_ENA_MID (~(BIT(12) | BIT(15)))
#define GPP_OUT_VAL_LOW (BIT(29))
#define GPP_OUT_VAL_MID (BIT(15))
#define GPP_POL_LOW 0x0
#define GPP_POL_MID 0x0
#define BD_EEPROM_ADDR (0x50) /* CPU BD EEPROM (8kByte) is at 50 (A0) */
#define BD_ADDRESS (0x0000) /* Board descriptor at beginning of EEPROM */
#define PD_ADDRESS (0x0200) /* Product descriptor */
#define PARTITION_ADDRESS (0x0600) /* Partition Table */
#define SERDES_CONFIG_ADDRESS (0x0800) /* SERDES config address */
#define DEV_CS0_BASE 0xfd000000
/* Default serdes configuration */
static struct serdes_map board_serdes_map[] = {
{ SGMII0, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0 }, /* ETH port 2 (same as HW18) */
{ PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 }, /* NVMe slot (was extension connetor on HW18) */
{ PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 }, /* PCIe for M.2 slot (was SFP on HW18) */
{ PEX3, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 }, /* Serdes for mPCIe slot (can be PEX3 or USB3_HOST1) (was first mPCIe slot on HW18) */
{ USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0 }, /* USB3 for M.2 slot (was Serdes for second mPCIe slot on HW18) */
{ SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0 } /* ETH port 1 (same as HW18) */
};
enum serdes_type get_serdes_type(int index)
{
if ((index>=0) && (index <ARRAY_SIZE(board_serdes_map)))
{
return board_serdes_map[index].serdes_type;
} else {
return LAST_SERDES_TYPE;
}
}
static BD_Context bdctx[3]; /* The descriptor context */
static int _bd_init(void)
{
if (bd_get_context(&bdctx[0], BD_EEPROM_ADDR, BD_ADDRESS) != 0) {
printf("%s() no valid bd found\n", __func__);
return -1;
}
if (bd_get_context(&bdctx[1], BD_EEPROM_ADDR, PD_ADDRESS) != 0) {
/* Ignore that, legacy boxes don't have a pd */
}
if (bd_get_context(&bdctx[2], BD_EEPROM_ADDR, PARTITION_ADDRESS) != 0) {
printf("%s() no valid partition table found\n", __func__);
}
bd_register_context_list(bdctx, ARRAY_SIZE(bdctx));
return 0;
}
typedef struct EEPROM_SERDES_CONFIG {
uint8_t magic[2];
uint8_t version;
uint8_t spare_0;
uint8_t serdes_cfg[6];
uint8_t spare1[2];
uint32_t crc32;
} EEPROM_SERDES_CONFIG;
static struct EEPROM_SERDES_CONFIG eeprom_serdes_config;
static void read_eeprom_serdes_config(void)
{
uint32_t crc;
if (i2c_read(BD_EEPROM_ADDR, SERDES_CONFIG_ADDRESS, 2, (uint8_t *)&eeprom_serdes_config, sizeof(eeprom_serdes_config))) {
goto fail;
}
crc = crc32(0, (uint8_t *)&eeprom_serdes_config, sizeof(eeprom_serdes_config)-4);
if ((eeprom_serdes_config.magic[0] != 0x83) ||
(eeprom_serdes_config.magic[1] != 0xfb) ||
(eeprom_serdes_config.version != 0x01) ||
(eeprom_serdes_config.crc32 != crc))
{
goto fail;
}
printf("Using user defined serdes config override\n");
return;
fail:
memset(&eeprom_serdes_config, 0xff, sizeof(eeprom_serdes_config));
printf("Using default serdes config (No user defined override)\n");
return;
}
static uint8_t get_eeprom_serdes_config(int serdes_index)
{
if ((serdes_index<0) || (serdes_index>=sizeof(eeprom_serdes_config.serdes_cfg))) return 0xff;
return eeprom_serdes_config.serdes_cfg[serdes_index];
}
static inline int __maybe_unused read_eeprom(void)
{
int res = _bd_init();
read_eeprom_serdes_config();
return res;
}
/* TODO: Create DA9063 Accessor Module */
#define CONFIG_PMIC_I2C_BUS 0
#define CONFIG_PMIC_I2C_ADDR 0x58 /* Pages 0 and 1, Pages 2 and 3 -> 0x59 */
#define RESET_REASON_SHM_LOCATION (0x3ffff000)
extern int console_init_f(void);
static int init_console(void)
{
int ret;
struct udevice *dev;
char *consoledev;
char buf[16] = "serial@12100";
debug("init console\n");
/* Make sure all devices are probed, it seems
* that this stuff is buggy in U-Boot */
ret = uclass_first_device(UCLASS_SERIAL, &dev);
if (ret) {
printf("Could not find any serial device\n");
return ret;
}
while (list_is_last(&dev->uclass_node, &dev->uclass->dev_head) == 0) {
uclass_next_device(&dev);
}
set_console();
/* Don't use external console, if we have no FPGA,
as it cannot work then. -> Switch to internal console then. */
// if (readw(0xfd000000)!=0x012f) { /* Check for correct FPGA signature */
printf("FPGA not ready. Forcing console to ttyS0\n");
env_set("defaultconsole", "ttyS0");
env_set("consoledev", "ttyS0");
// }
consoledev = env_get("consoledev");
if (strncmp(consoledev, "ttyS0", 5) == 0) {
strncpy(buf, "serial@12000", sizeof(buf));
}
env_set("stdin", buf);
env_set("stdout", buf);
env_set("stderr", buf);
return 0;
}
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{
int i, j;
int bd_config_is_broken = 0;
if (read_eeprom() < 0){
/* If we do not have a board descriptor use the default
serdes configuration defined in board_serdes_map */
puts("Could not read board descriptor using default serdes config.\n");
} else {
/* Check for broken serdes config in BD -> If multiple serdes lines are
configured for the same function something is obviously broken. */
for (i = 0; i<ARRAY_SIZE(board_serdes_map); i++) {
for (j = i+1; j<ARRAY_SIZE(board_serdes_map); j++) {
if ((bd_get_serdes_type(i) == bd_get_serdes_type(j)) &&
(bd_get_serdes_type(i) < DEFAULT_SERDES)) { // DEFAULT_SERDES & LAST_SERDES_TYPE are always ok
printf("Serdes lines %d and %d are configured for same function %d\n",
i, j, bd_get_serdes_type(i));
bd_config_is_broken = 1;
}
}
}
if (bd_config_is_broken) {
printf("Serdes config in BD is broken! -> Ignoring BD serdes config\n");
}
for (i = 0; i < ARRAY_SIZE(board_serdes_map); i++) {
enum serdes_type type;
uint8_t user_config = get_eeprom_serdes_config(i);
if (user_config != 0xff) {
/* if we have a user config we use that one */
type = (enum serdes_type)user_config;
} else {
/* otherwise we use the config from the bd if it is not broken */
if (bd_config_is_broken) {
type = LAST_SERDES_TYPE;
} else {
type = bd_get_serdes_type(i);
}
}
/* LAST_SERDES_TYPE means use compiled in default */
if (type < LAST_SERDES_TYPE) {
if ((type >= SGMII0) && (type <= SGMII2)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[i].serdes_mode = SERDES_DEFAULT_MODE;
}
else if ((type >= PEX0) && (type <= PEX3)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[i].serdes_mode = PEX_ROOT_COMPLEX_X1;
}
else if ((type >= USB3_HOST0) && (type <= USB3_HOST1)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[i].serdes_mode = PEX_ROOT_COMPLEX_X1;
}
else if ((type >= SATA0) && (type <= SATA3)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_3_GBPS;
board_serdes_map[i].serdes_mode = SERDES_DEFAULT_MODE;
}
else if ((type == DEFAULT_SERDES)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[i].serdes_mode = SERDES_DEFAULT_MODE;
} else {
printf("SERDES Type %d not supported\n", type);
/* Keep default serdes configuration */
type = board_serdes_map[i].serdes_type;
}
if (i==3) {
/* On V2 TX line for PCIe slot1 is inverted*/
board_serdes_map[i].swap_tx = 1;
}
debug("Configure SERDES %d to %d\n", i, type);
board_serdes_map[i].serdes_type = type;
}
}
}
*serdes_map_array = board_serdes_map;
*count = ARRAY_SIZE(board_serdes_map);
return 0;
}
/*
* Define the DDR layout / topology here in the board file. This will
* be used by the DDR3 init code in the SPL U-Boot version to configure
* the DDR3 controller.
*/
static struct mv_ddr_topology_map board_topology_map = {
DEBUG_LEVEL_ERROR,
0x1, /* active interfaces */
/* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
{ { { {0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0} },
SPEED_BIN_DDR_1600K, /* speed_bin */
MV_DDR_DEV_WIDTH_16BIT, /* sdram device width */
MV_DDR_DIE_CAP_4GBIT, /* die capacity */
MV_DDR_FREQ_667, /* frequency */
0, 0, /* cas_l cas_wl */
MV_DDR_TEMP_HIGH} }, /* temperature */
BUS_MASK_32BIT, /* subphys mask */
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
{ {0} }, /* raw spd data */
{0} /* timing parameters */
};
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
{
/* Return the board topology as defined in the board code */
return &board_topology_map;
}
#if defined(CONFIG_WATCHDOG)
void watchdog_init(void)
{
/* NOTE: Global watchdog counter register is at 0xf1020334
Could not find this in the manual. */
if (uclass_get_device(UCLASS_WDT, 0, (struct udevice **)&(gd->watchdog))) {
puts("Cannot enable watchdog!\n");
} else {
puts("Enabling watchdog\n");
wdt_start(gd->watchdog, (u32) 25000000 * 150, 0); /* Timer runs at 25 MHz */
}
}
/* Called by macro WATCHDOG_RESET */
void watchdog_reset(void)
{
static ulong next_reset = 0;
ulong now;
if (!(gd->watchdog)) return;
now = timer_get_us();
/* Do not reset the watchdog too often */
if (now > next_reset) {
wdt_reset(gd->watchdog);
next_reset = now + 1000000;
}
}
#endif
int board_early_init_f(void)
{
/* Configure MPP */
writel(0x00111111, MVEBU_MPP_BASE + 0x00);
writel(0x40000000, MVEBU_MPP_BASE + 0x04);
writel(0x55000444, MVEBU_MPP_BASE + 0x08);
writel(0x55053350, MVEBU_MPP_BASE + 0x0c);
writel(0x55555555, MVEBU_MPP_BASE + 0x10);
writel(0x06605505, MVEBU_MPP_BASE + 0x14);
writel(0x55550555, MVEBU_MPP_BASE + 0x18);
writel(0x00005551, MVEBU_MPP_BASE + 0x1c);
/* Set GPP Out value */
writel(GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
writel(GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
/* Set GPP Polarity */
writel(GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
writel(GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
/* Set GPP Out Enable */
writel(GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
writel(GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
return 0;
}
u32 spl_boot_mode(const u32 boot_device)
{
return MMCSD_MODE_EMMCBOOT;
}
void spl_board_init(void)
{
int err;
struct mmc *mmcp;
da9063_init(CONFIG_PMIC_I2C_BUS);
// FB 57727 Use synchronous mode for buck converters
// This solves the occasional rail lock up problem
da9063_set_reg(PMIC_REG_BCORE1_CONF, 0x81);
da9063_set_reg(PMIC_REG_BCORE2_CONF, 0x81);
da9063_set_reg(PMIC_REG_BIO_CONF, 0x81);
da9063_set_reg(PMIC_REG_BMEM_CONF, 0x81);
da9063_set_reg(PMIC_REG_BPERI_CONF, 0x81);
/* Enable LDO6 used for GNSS */
da9063_set_reg(PMIC_REG_LDO6_CONT, 0x81);
da9063_reset_reason_update(RESET_REASON_SHM_LOCATION);
err = mmc_initialize(0);
if (err)
return;
debug("SPL: select partition\n");
mmcp = find_mmc_device(0);
mmc_init(mmcp);
printf("Partition found: %p\n", mmcp);
/* select boot0 as first boot partition */
mmcp->part_config &= ~(PART_ACCESS_MASK << 3);
mmcp->part_config |= (1 << 3);
debug("Boot partition set to boot0\n");
}
static void set_gpios(void)
{
init_gpios();
}
#if !defined(CONFIG_SPL_BUILD)
static void pass_hw_rev(void)
{
int hw_ver = 0, hw_rev = 0;
char *old_env;
char hw_versions[128];
char new_env[256];
bd_get_hw_version(&hw_ver, &hw_rev);
snprintf(hw_versions, sizeof(hw_versions), "CP=%d.%d",
hw_ver, hw_rev);
old_env = env_get("add_version_bootargs");
/* Normaly add_version_bootargs should already be set (see board include file) */
if (old_env != 0) {
snprintf(new_env, sizeof(new_env), "%s %s", old_env, hw_versions);
}
else {
snprintf(new_env, sizeof(new_env), "env_set bootargs $bootargs %s\n", hw_versions);
}
env_set("add_version_bootargs", new_env);
}
#endif
int board_init(void)
{
#if defined(CONFIG_WATCHDOG)
watchdog_init();
#endif
/* adress of boot parameters */
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
/* Setup the MBUS mapping for Devicebus CS0 */
mbus_dt_setup_win(&mbus_state, DEV_CS0_BASE, 16 << 20,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS0);
if (read_eeprom() < 0)
puts("Could not get board ID.\n");
set_gpios();
/* @@se: With this call we disable a debug feature, that allows one to read out the memory
* over i2c at slave address 0x64. This feature is for some undocumented reasons enabled by default
* the default value is 0x00370010, according to the documentation it should be 0x00330010. If we set
* it back to this value address 0x64 is unused again. This is necessary because atsha204 uses 0x64 as
* slave address.
*/
writel(0x00330010, SOC_REGS_PHY_BASE + 0x0001108c);
return 0;
}
int board_early_init_r(void)
{
/* We need to force mmc_initialization here, so that
* we have mmc available for read of /boot/consoledev */
mmc_initialize(gd->bd);
/* We need to force the env relocation so that it won't overwritte the
* serial devices that we set in init_console */
env_relocate();
gd->env_valid = ENV_VALID;
return 0;
}
#if !defined(CONFIG_SPL_BUILD)
static bool get_button_state(void)
{
u8 state = 0x00;
(void)da9063_get_reg(PMIC_REG_STATUS_A, &state);
return (state & 0x01) == 0x01;
}
static int check_reset_button(void)
{
int counter = 0;
/* Check how long button is pressed */
do {
if (!get_button_state())
break;
udelay(100*1000); /* 100ms */
counter += 100;
if (counter == 2000) {
/* Indicate factory reset threshold */
/* let all green LEDs blink up */
set_led(LED0_GREEN, 1);
set_led(LED1_GREEN, 1);
set_led(LED2_GREEN, 1);
set_led(LED3_GREEN, 1);
set_led(LED4_GREEN, 1);
set_led(LED5_GREEN, 1);
udelay(400000); /* 400ms */
set_led(LED1_GREEN, 0);
set_led(LED2_GREEN, 0);
set_led(LED3_GREEN, 0);
set_led(LED4_GREEN, 0);
set_led(LED5_GREEN, 0);
} else if (counter == 12000) {
/* Indicate recovery boot threshold */
/* let all red LEDs blink up */
set_led(LED0_GREEN, 0);
set_led(LED0_RED, 1);
set_led(LED1_RED, 1);
set_led(LED2_RED, 1);
set_led(LED3_RED, 1);
set_led(LED4_RED, 1);
set_led(LED5_RED, 1);
udelay(400000); /* 400ms */
set_led(LED0_RED, 0);
set_led(LED1_RED, 0);
set_led(LED2_RED, 0);
set_led(LED3_RED, 0);
set_led(LED4_RED, 0);
set_led(LED5_RED, 0);
set_led(LED0_GREEN, 1);
}
} while (counter < 12000);
if (counter < 2000) {
/* Don't do anything for duration < 2s */
}
else if (counter < 12000)
{
/* Do factory reset for duration between 2s and 12s */
char new_bootargs[512];
char *bootargs = env_get("bootargs");
if (bootargs == 0) bootargs="";
printf("Do factory reset during boot...\n");
strncpy(new_bootargs, bootargs, sizeof(new_bootargs));
strncat(new_bootargs, " factory-reset", sizeof(new_bootargs));
env_set("bootargs", new_bootargs);
return 1;
}
else
{
/* Boot into recovery for duration > 12s */
printf("Booting recovery image...\n");
/* Set bootcmd to run recovery */
env_set("bootcmd", "run recovery");
return 0;
}
return 0;
}
#ifdef CONFIG_CMD_NB_TEST
/*
* Perform a hardware reset test. The complete test loops until
* interrupted by ctrl-c or by pressed the RESET button.
*/
int do_hwreset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int gpio_cpu_value = 0;
printf(" Press RESET button for testing or ctrl-c to abort\n");
while (gpio_cpu_value == 0) {
gpio_cpu_value = get_button_state() ? 1 : 0;
printf("RESET_BTN = %d\n",gpio_cpu_value);
if (ctrlc()) {
putc ('\n');
return 1;
}
udelay(20*1000);
}
return 1;
}
#endif /* CONFIG_CMD_NB_TEST */
#endif /* !defined(CONFIG_SPL_BUILD) */
int misc_init_r(void)
{
struct serdes_map* sm;
u8 sm_count;
/* Because U-Boot is buggy, we need to call this funktion again
* it will print the pre console buffer */
/* TODO: Moved following two lines to board_late_init because ttyS1 is currently not working without loaded bitstream */
// init_console();
// console_init_f();
/* Configure PMIC */
#if !defined(CONFIG_SPL_BUILD)
/* Enable PMIC LED */
da9063_set_reg(0x1e, 0x08);
/* Enable PMIC RTC backup charger (charge with 6mA to 3.1V) */
da9063_set_reg(PMIC_REG_BBAT_CONT, 0xff);
#endif
/* Determine SERDES configuration */
hws_board_topology_load(&sm, &sm_count);
return 0;
}
static void set_phy_page(const char *miidev, int phy_addr, int page)
{
miiphy_write(miidev, phy_addr, 22, page);
}
static void set_phy_fast_blink_mode(int phy_addr)
{
const char *miidev = miiphy_get_current_dev();
debug ("miidev: %s\n", miidev);
set_phy_page(miidev, phy_addr, 3);
miiphy_write(miidev, phy_addr, 16, 0x1032);
miiphy_write(miidev, phy_addr, 17, 0x4405);
miiphy_write(miidev, phy_addr, 18, 0x4A08);
set_phy_page(miidev, phy_addr, 0);
}
#if !defined(CONFIG_SPL_BUILD)
static void set_devicetree_name(void)
{
char devicetreename[64];
if (bd_get_devicetree(devicetreename, sizeof(devicetreename)) != 0) {
printf("Devicetree name not found, use legacy name\n");
strcpy(devicetreename, "armada-385-hw29-prod1.dtb");
}
env_set("fdt_image", devicetreename);
}
#endif
int board_late_init(void)
{
#if !defined(CONFIG_SPL_BUILD)
gpio_request(29, "RST_ETH_PHY_N");
gpio_direction_output(29, 0);
find_and_set_active_partition();
pass_hw_rev();
run_command("run load_fpga", CMD_FLAG_ENV);
#endif
/* TODO: Move the following two lines up to misc_init_r when ttyS1 works without FPGA again */
init_console();
console_init_f();
#if !defined(CONFIG_SPL_BUILD)
check_reset_button();
set_devicetree_name();
set_mac_address(0, 0);
set_mac_address(1, 1);
set_mac_address(2, 2);
/* Take phy out of reset after FPGA was loaded */
gpio_set_value(29, 1);
#endif
return 0;
}
int board_network_enable(struct mii_dev *bus)
{
static int NETWORK_ENABLED = 0;
if (!NETWORK_ENABLED) {
set_phy_fast_blink_mode(0);
set_phy_fast_blink_mode(1);
NETWORK_ENABLED = 1;
}
return 0;
}
int checkboard(void)
{
debug("Board: NetModule NBHW29\n");
return 0;
}
int board_fit_config_name_match(const char *name)
{
#ifdef CONFIG_SPL_BUILD
/* SPL has enabled serial0 per default and will output everything
* independend of /boot/consoledev */
#define DEFAULT_DTB_NAME "armada-385-hw29-spl"
#else
/* U-Boot will read /boot/consoledev and based on that it
* enables its own serial console */
#define DEFAULT_DTB_NAME "armada-385-hw29"
#endif
/* Check if name fits our dts */
return strcmp(DEFAULT_DTB_NAME, name);
}
#ifdef CONFIG_OF_BOARD_FIXUP
int fdt_enable_by_ofname(void *rw_fdt_blob, char *ofname)
{
int offset = fdt_path_offset(rw_fdt_blob, ofname);
return fdt_status_okay(rw_fdt_blob, offset);
}
int board_fix_fdt(void *fdt_blob)
{
return 0;
}
#endif
int pcie_lane_by_slot(int slot)
{
int serdes;
switch (slot) {
case 0 :
serdes = 3;
break;
case 1 :
serdes = 4;
break;
case 2 :
serdes = 1;
break;
default :
serdes = -1;
break;
}
if ((serdes<0) || serdes>=ARRAY_SIZE(board_serdes_map))
return -1;
switch (board_serdes_map[serdes].serdes_type)
{
case PEX0 :
return 0;
case PEX1 :
return 1;
case PEX2 :
return 2;
case PEX3 :
return 3;
default :
return -1;
}
}
/*
static void ft_enable_node(void* blob, const char* name)
{
int node_ofs = -1;
node_ofs = fdt_path_offset(blob, name);
if (node_ofs >= 0) {
fdt_setprop_string(blob, node_ofs, "status", "okay");
}
}
*/
int ft_board_setup(void *blob, bd_t *bd)
{
/* Enabled all components in dts depending on
current serdes configuration */
return 0;
}

View File

@ -0,0 +1,12 @@
#
# Copyright (C) 2014 Stefan Roese <sr@denx.de>
#
# Armada XP uses version 1 image format
VERSION 1
# Boot Media configurations
BOOT_FROM sdio
# Binary Header (bin_hdr) with DDR3 training code
BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068

View File

@ -0,0 +1,393 @@
#undef DEBUG
#include <common.h>
#include <dm.h>
#include <dm/device.h>
#include <dm/ofnode.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <errno.h>
#include "../common/nbhw_bd.h"
#include "../common/nbhw_sim.h"
DECLARE_GLOBAL_DATA_PTR;
struct gpio_desc leds[16];
struct udevice *driver_dev;
struct config_priv {
u32 led_count;
} priv;
typedef enum {
TYPE_USB,
TYPE_USB3,
TYPE_PCIE,
} slot_type_t;
struct pcie_slot_gpios {
struct gpio_desc reset;
struct gpio_desc power;
struct gpio_desc wdis_out;
struct gpio_desc wdis;
struct gpio_desc clk;
struct gpio_desc power_3v8;
struct gpio_desc reset_1v8;
struct gpio_desc reset_3v3;
struct gpio_desc wdis_1v8;
struct gpio_desc wdis_3v3;
};
struct sfp_gpios {
struct gpio_desc reset;
struct gpio_desc power;
};
#define PCIE_SLOT_COUNT 8
static struct pcie_slot_gpios pcie_slots[PCIE_SLOT_COUNT];
static struct sfp_gpios sfps;
static int pcie_slot_count = 0;
static int request_and_set_gpio_by_name(ofnode fdt,
const char *name, struct gpio_desc *desc)
{
int default_value = 0;
u32 gpio_array[4];
debug("%s\n", __func__);
/* Request the gpio described by the property */
if (gpio_request_by_name_nodev(fdt, name, 0, desc,
GPIOD_IS_OUT))
{
debug("Could not request gpio %s\n", name);
return -1;
}
/* Get the gpio array, to find out its default value (4 index) */
if (ofnode_read_u32_array(fdt, name, gpio_array, 4)) {
printf("Could not request gpio array %s\n", name);
return -1;
}
default_value = gpio_array[3];
debug("Set GPIO %s to %d\n", name, default_value);
dm_gpio_set_value(desc, default_value);
return 0;
}
static int add_sfp(ofnode fdt)
{
debug("%s\n", __func__);
request_and_set_gpio_by_name(fdt, "power",
&sfps.power);
request_and_set_gpio_by_name(fdt, "reset",
&sfps.reset);
return 0;
}
static int add_pcie_slot(ofnode fdt)
{
debug("%s\n", __func__);
request_and_set_gpio_by_name(fdt, "power",
&pcie_slots[pcie_slot_count].power);
request_and_set_gpio_by_name(fdt, "reset",
&pcie_slots[pcie_slot_count].reset);
request_and_set_gpio_by_name(fdt, "wdis-out",
&pcie_slots[pcie_slot_count].wdis_out);
request_and_set_gpio_by_name(fdt, "wdis",
&pcie_slots[pcie_slot_count].wdis);
request_and_set_gpio_by_name(fdt, "clk",
&pcie_slots[pcie_slot_count].clk);
request_and_set_gpio_by_name(fdt, "power-3v8",
&pcie_slots[pcie_slot_count].power_3v8);
request_and_set_gpio_by_name(fdt, "reset-1v8",
&pcie_slots[pcie_slot_count].reset_1v8);
request_and_set_gpio_by_name(fdt, "reset-3v3",
&pcie_slots[pcie_slot_count].reset_3v3);
request_and_set_gpio_by_name(fdt, "wdis-1v8",
&pcie_slots[pcie_slot_count].wdis_1v8);
request_and_set_gpio_by_name(fdt, "wdis-3v3",
&pcie_slots[pcie_slot_count].wdis_3v3);
pcie_slot_count++;
return 0;
}
static int has_slot_wlan(int slot)
{
int module;
char slotDescr[20];
char pdValue[200];
sprintf(slotDescr, "slot=%d", slot);
for (module=0; module<4; module++) {
strcpy(pdValue, "" ); /*init with an empty string*/
if (bd_get_pd_module(module, pdValue, sizeof(pdValue))==0) {
/* Wifi module needs PCIe */
if ((strstr(pdValue, slotDescr)) && (strstr(pdValue, "wlan-")))
return 1;
}
}
return 0;
}
static int configure_pcie_slots(void)
{
int i, res;
char volt[10];
configure_sim_slots(4);
udelay(1200000); /* 1.2 s */
for (i = 0; i < 5; i++) {
/* Set supply voltage of PCIe slots */
if ((bd_get_slot_supply_volt(i, volt, sizeof(volt)) == 0) &&
(strncmp(volt, "3v8", 3)==0)) {
dm_gpio_set_value(&pcie_slots[i].power_3v8, 1);
} else {
/* Default is 3v3 */
dm_gpio_set_value(&pcie_slots[i].power_3v8, 0);
}
/* Set reset signal voltage of PCIe slots */
res = bd_get_slot_perst_volt(i, volt, sizeof(volt));
if ((res == 0) && (strncmp(volt, "off", 3)==0)) {
/* No pull up */
dm_gpio_set_value(&pcie_slots[i].reset_1v8, 0);
dm_gpio_set_value(&pcie_slots[i].reset_3v3, 0);
} else if ((res == 0) && (strncmp(volt, "1v8", 3)==0)) {
dm_gpio_set_value(&pcie_slots[i].reset_1v8, 1);
dm_gpio_set_value(&pcie_slots[i].reset_3v3, 0);
} else {
/* Default is 3v3 */
dm_gpio_set_value(&pcie_slots[i].reset_1v8, 0);
dm_gpio_set_value(&pcie_slots[i].reset_3v3, 1);
}
/* Set wdis signal voltage of PCIe slots */
res = bd_get_slot_wdis_volt(i, volt, sizeof(volt));
if ((res == 0) && (strncmp(volt, "off", 3)==0)) {
/* No pull up */
dm_gpio_set_value(&pcie_slots[i].wdis_1v8, 0);
dm_gpio_set_value(&pcie_slots[i].wdis_3v3, 0);
} else if ((res == 0) && (strncmp(volt, "1v8", 3)==0)) {
dm_gpio_set_value(&pcie_slots[i].wdis_1v8, 1);
dm_gpio_set_value(&pcie_slots[i].wdis_3v3, 0);
} else {
/* Default is 3v3 */
dm_gpio_set_value(&pcie_slots[i].wdis_1v8, 0);
dm_gpio_set_value(&pcie_slots[i].wdis_3v3, 1);
}
}
/* Apply power to all PCIe slots */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].power, 1);
udelay(200000); /* 200 ms */
}
/* Assert reset after power is enabled */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 1);
}
/* Enable PCIe clock Note: Slot 1 has always clock. Slot 0 & extension
slot cannot have clock at same time. */
for (i = 0; i < 2; i ++) {
if (has_slot_wlan(i)) {
/* Only enable PCIe clock on WiFi modules as it confuses some LTE modems */
dm_gpio_set_value(&pcie_slots[i].clk, 1);
}
}
/* Deactivate WDIS */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].wdis_out, 1);
dm_gpio_set_value(&pcie_slots[i].wdis, 0);
udelay(2000); /* 2 ms needed by Reyax module as regulator is enabled by WDIS~*/
}
udelay(12000); /* 12 ms */
/* Deassert reset */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 0);
}
pci_init_board();
return 0;
}
static int configure_leds(void)
{
int i;
int led_count;
led_count = gpio_request_list_by_name(driver_dev, "leds", leds,
ARRAY_SIZE(leds), GPIOD_IS_OUT);
dm_gpio_set_value(&leds[0], 1);
for (i = 1; i < ARRAY_SIZE(leds); i++) {
dm_gpio_set_value(&leds[i], 0);
}
priv.led_count = led_count;
return 0;
}
void set_led(int index, int value)
{
if ((index<0) || (index>=priv.led_count)) return;
dm_gpio_set_value(&leds[index], value);
}
static int request_and_set_gpios(ofnode fdt,
struct gpio_desc *gpios, u32 max_gpios)
{
int i = 0;
int default_value = 0;
int offset = 0;
for (offset = fdt_first_property_offset(gd->fdt_blob, ofnode_to_offset(fdt));
offset >= 0;
offset = fdt_next_property_offset(gd->fdt_blob, offset)) {
u32 gpio_array[4];
const char *name;
const struct fdt_property *prop;
if (i >= max_gpios) {
printf("Too many gpio entries (max %d)\n", max_gpios);
break;
}
prop = fdt_get_property_by_offset(gd->fdt_blob, offset, NULL);
name = fdt_string(gd->fdt_blob, fdt32_to_cpu(prop->nameoff));
debug("Name: %s\n", name);
if (name[0] == '#') {
continue;
}
/* Request the gpio descriped by the property */
if (gpio_request_by_name_nodev(fdt, name, 0, &gpios[i],
GPIOD_IS_OUT))
{
printf("Could not request gpio %s\n", name);
return -1;
}
/* Get the gpio array, to find out its default value (4 index) */
if (ofnode_read_u32_array(fdt, name,
gpio_array, 4)) {
printf("Could not request gpio array %s\n", name);
return -1;
}
default_value = gpio_array[3];
debug("Set GPIO %s to %d\n", name, default_value);
dm_gpio_set_value(&gpios[i], default_value);
i++;
}
debug("leave %s with %d gpios\n", __func__, i);
return i;
}
static int configure_misc(ofnode fdt)
{
struct gpio_desc misc_gpios[16];
int gpio_count;
debug("%s\n", __func__);
gpio_count = request_and_set_gpios(fdt,
misc_gpios, ARRAY_SIZE(misc_gpios));
if (gpio_count < 1) {
return -1;
}
debug("Free gpios\n");
/* Free gpios so that we could use them via gpio subsystem */
gpio_free_list_nodev(misc_gpios, gpio_count);
debug("return %s\n", __func__);
return 0;
}
int nbhw_fpga_configure(void)
{
ofnode subnode;
ofnode node = driver_dev->node;
debug("%s\n", __func__);
ofnode_for_each_subnode(subnode, node) {
const char *name;
name = ofnode_get_name(subnode);
debug("Try to configure %s\n", name);
if (!strncmp("misc", name, 4)) {
configure_misc(subnode);
}
if (!strncmp("pcieslot", name, 8)) {
add_pcie_slot(subnode);
}
if (!strncmp("sfp", name, 3)) {
add_sfp(subnode);
}
}
if (configure_leds())
return -1;
if (configure_pcie_slots()) {
return -1;
}
return 0;
}
static int nbhw_fpga_config_bind(struct udevice *dev)
{
debug("%s\n", __func__);
driver_dev = dev;
return 0;
}
static const struct udevice_id nbhw_fpga_config_ids[] = {
{ .compatible = "nm,nbhw29-fpga-config" },
{ }
};
U_BOOT_DRIVER(gpio_nbhw_fpga_config) = {
.name = "nbhw29_fpga_config",
.id = UCLASS_ROOT,
.of_match = nbhw_fpga_config_ids,
.bind = nbhw_fpga_config_bind,
};

37
board/nm/hw29/nbhw_gpio.c Normal file
View File

@ -0,0 +1,37 @@
#include <common.h>
#include <asm/gpio.h>
#define GPIO_RESET_BUTTON (14)
void init_gpios(void)
{
gpio_request(GPIO_RESET_BUTTON, "GPIO_RESET_BUTTON");
gpio_direction_input(GPIO_RESET_BUTTON);
}
void out_usb_power(int enable)
{
// SET_LOGIC(enable, 1, BIT9);
}
void out_watchdog(int enable)
{
// SET_LOGIC(enable, 0, BIT19);
}
void out_fpga_logic_reset(int enable)
{
// SET_LOGIC(enable, 1, BIT12);
}
void out_ext_reset_en(int enable)
{
// SET_LOGIC(enable, 0, BIT7);
}
int in_reset_button(void)
{
return gpio_get_value(GPIO_RESET_BUTTON);
}

28
board/nm/hw29/nbhw_gpio.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef NBHW29_GPIO_H
#define NBHW29_GPIO_H
#include "../common/nbhw_gpio.h"
void init_gpios(void);
void out_usb_power(int enable);
void out_watchdog(int enable);
void out_fpga_logic_reset(int enable);
int in_fpga_cdone(void);
#define LED0_GREEN 0
#define LED0_RED 1
#define LED1_GREEN 2
#define LED1_RED 3
#define LED2_GREEN 4
#define LED2_RED 5
#define LED3_GREEN 6
#define LED3_RED 7
#define LED4_GREEN 8
#define LED4_RED 9
#define LED5_GREEN 10
#define LED5_RED 11
void set_led(int index, int value);
#endif

34
board/nm/hw29/nbhw_sim.c Normal file
View File

@ -0,0 +1,34 @@
#include <common.h>
#include "../common/nbhw_fpga_prog.h"
#define SIM_CTRL (0x0040)
void connect_sim_to_slot(int sim, int slot) {
uint16_t sim_ctrl;
uint16_t sim_shift;
uint16_t slot_sel;
if (sim > 1) {
printf("Invalid sim %d selected, can't connect slot %d\n", sim, slot);
return;
}
if (slot < 0)
slot_sel = 0;
else if (slot <= 4) {
slot_sel = slot + 1;
}
else {
printf("Invalid slot %d selected, can't connect sim %d\n", slot, sim);
return;
}
sim_shift = sim * 4;
sim_ctrl = FPGA_REG(SIM_CTRL);
sim_ctrl &= ~(0xF << sim_shift);
sim_ctrl |= slot_sel << sim_shift;
FPGA_REG(SIM_CTRL) = sim_ctrl;
}

View File

@ -0,0 +1,75 @@
CONFIG_ARM=y
CONFIG_ARCH_MVEBU=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_NM_HW29=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="armada-385-hw29-spl"
CONFIG_SMBIOS_PRODUCT_NAME="hw29"
CONFIG_FIT=y
CONFIG_FIT_ENABLE_SHA256_SUPPORT=y
CONFIG_BOOTDELAY=3
CONFIG_BOOTSTAGE_STASH_SIZE=4096
CONFIG_PRE_CONSOLE_BUFFER=y
CONFIG_SYS_CONSOLE_IS_IN_ENV=y
CONFIG_PRE_CON_BUF_SZ=4096
CONFIG_PRE_CON_BUF_ADDR=0x04000000
# CONFIG_CONSOLE_MUX is not set
CONFIG_DEFAULT_FDT_FILE="armada-385-hw29-spl"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPL=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x190
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_IMLS is not set
CONFIG_CMD_NB_TEST=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_MMC=y
CONFIG_CMD_SF=y
CONFIG_CMD_SPI=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_MII=y
CONFIG_CMD_PING=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_TIME=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_EFI_PARTITION=y
# CONFIG_PARTITION_UUIDS is not set
# CONFIG_SPL_PARTITION_UUIDS is not set
CONFIG_OF_BOARD_FIXUP=y
CONFIG_SPL_OF_TRANSLATE=y
CONFIG_OF_LIST="armada-385-hw29-spl armada-385-hw29"
CONFIG_MULTI_DTB_FIT=y
CONFIG_FPGA_LATTICE_SSPI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_MV=y
CONFIG_SPI_FLASH=y
CONFIG_MVNETA=y
CONFIG_PCI=y
# CONFIG_DEBUG_UART is not set
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_MARVELL=y
CONFIG_USB_STORAGE=y
CONFIG_MVEBU_GPIO=y
CONFIG_DM_GPIO=y
CONFIG_CMD_EEPROM=y
CONFIG_ENV_IS_IN_EEPROM=y
CONFIG_WDT=y
CONFIG_WDT_ORION=y

View File

@ -0,0 +1,223 @@
/*
* Copyright (C) 2014 Stefan Roese <sr@denx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _CONFIG_DB_88F6820_GP_H
#define _CONFIG_DB_88F6820_GP_H
/*
* High Level Configuration Options (easy to change)
*/
#define CONFIG_DISPLAY_BOARDINFO_LATE
/*
* TEXT_BASE needs to be below 16MiB, since this area is scrubbed
* for DDR ECC byte filling in the SPL before loading the main
* U-Boot into it.
*/
#define CONFIG_SYS_TEXT_BASE 0x00800000
#define CONFIG_SYS_TCLK 250000000 /* 250MHz */
/*
* Commands configuration
*/
#define CONFIG_CMD_PCI
/* I2C */
#define CONFIG_SYS_I2C
#define CONFIG_SYS_I2C_MVTWSI
#define CONFIG_I2C_MVTWSI_BASE0 MVEBU_TWSI_BASE
#define CONFIG_SYS_I2C_SLAVE 0x0
#define CONFIG_SYS_I2C_SPEED 100000
/*
* SDIO/MMC Card Configuration
*/
#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE
/* Partition support */
/* USB/EHCI configuration */
#define CONFIG_EHCI_IS_TDI
/* Environment in I2C EEPROM */
/**
* Layout on the NBHW08 Board:
* Offset Size Description
* 0x0000 0x200 The NetModule Boarddescriptor
* 0x0200 0x200 The NetModule Productdescriptor
* 0x0400 0x200 The NetModule License Descriptor
* 0x0600 0x400 The NetModule Parition table
* 0x0A00 0x600 reserved
* 0x1000 0xA00 The U-Boot environment
* 0x1A00 0x600 reserved
*/
#define CONFIG_ENV_OFFSET (0x1000) /* The Environment is located at 4k */
#define CONFIG_ENV_SIZE (0xA00) /* 64KiB */
#define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */
#define CONFIG_ENV_EEPROM_IS_ON_I2C
#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 /* Main EEPROM */
#define CONFIG_SYS_DEF_EEPROM_ADDR 0x50
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN (2)
#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 5
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 70
#define CONFIG_PHY_MARVELL /* there is a marvell phy */
#define PHY_ANEG_TIMEOUT 8000 /* PHY needs a longer aneg time */
/* PCIe support */
#ifndef CONFIG_SPL_BUILD
#define CONFIG_PCI_MVEBU
#define CONFIG_PCI_SCAN_SHOW
#endif
#if !defined(UBOOT_USER_BUILD) && !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
#define CONFIG_WATCHDOG
#endif
#define CONFIG_OF_BOARD_SETUP
#define CONFIG_SYS_ALT_MEMTEST
#ifndef CONFIG_SPL_BUILD
#define CONFIG_NM_LOGIN
#define CONFIG_CRYPT
#define CONFIG_SUPPORT_EMMC_RPMB
#define KERNEL_ADDR "0x01000000"
#define LOAD_ADDR "0x03000000"
#define FDT_ADDR "0x02000000"
#define PXE_ADDR "0x02800000"
#define CONFIG_EXTRA_ENV_SETTINGS \
"fdt_high=0x12000000\0" \
"initrd_high=0x13000000\0" \
"kernel_image=kernel.bin\0" \
"fdt_image=armada-385-hw29-prod1.dtb\0" \
"modeboot=sdboot\0" \
"fdt_addr=" FDT_ADDR "\0" \
"kernel_addr=" KERNEL_ADDR "\0" \
"load_addr=" LOAD_ADDR "\0" \
"root_part=1\0" /* Default root partition, overwritte in board file */ \
"eth1addr=00:11:22:33:44:55\0" \
"eth2addr=00:11:22:33:44:56\0" \
"eth3addr=00:11:22:33:44:57\0" \
"ethact=ethernet@34000\0" \
"add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 rootwait nvme_core.default_ps_max_latency_us=0 loglevel=4; run set_console_dev\0" \
"add_version_bootargs=setenv bootargs $bootargs\0" \
"fdt_skip_update=yes\0" \
"sdbringup=echo Try bringup boot && ext4load mmc 0:$root_part $kernel_addr /boot/zImage && " \
"ext4load mmc 0:$root_part $fdt_addr /boot/$fdt_image && setenv bootargs $bootargs rw;\0" \
"sdprod=ext4load mmc 0:$root_part $kernel_addr /boot/$kernel_image && " \
"ext4load mmc 0:$root_part $fdt_addr /boot/$fdt_image && setenv bootargs $bootargs ro;\0" \
"sdboot=if mmc dev 0; then nbhw_wlan_fixup &&" \
"echo Copying Linux from SD to RAM...; "\
"if test -e mmc 0:$root_part /boot/$kernel_image; then run sdprod; " \
"else run sdbringup; fi; " \
"run add_sd_bootargs; run add_version_bootargs; " \
"bootz $kernel_addr - $fdt_addr; fi\0" \
"bootcmd=run sdboot\0" \
"ipaddr=192.168.1.1\0" \
"serverip=192.168.1.254\0" \
"pxefile_addr_r=" PXE_ADDR "\0" \
"fdt_addr_r=" FDT_ADDR "\0" \
"kernel_addr_r=" KERNEL_ADDR "\0" \
"ramdisk_addr_r=" LOAD_ADDR "\0" \
"bootpretryperiod=1000\0" \
"tftptimeout=2000\0" \
"tftptimeoutcountmax=5\0" \
"bootpretryperiod=2000\0" \
"autoload=false\0" \
"defaultconsole=ttyS1\0" \
"set_console_dev=if test -n ${consoledev}; then setenv bootargs $bootargs console=$consoledev,115200; fi; true\0" \
"tftp_recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; setenv bootargs rdinit=/etc/preinit console=$defaultconsole,115200 debug; bootz $kernel_addr - $fdt_addr\0" \
"pxe_recovery=sleep 3 && dhcp && pxe get && pxe boot\0" \
"load_fpga=ext4load mmc 0:$root_part $kernel_addr /logic/LG00000000 && nbhw_fpga program lattice-sspi 0xffffffff $kernel_addr $filesize && nbhw_fpga configure\0" \
"recovery=run pxe_recovery || setenv ipaddr $ipaddr; setenv serverip $serverip; run tftp_recovery\0" /* setenv ipaddr and serverip is necessary, because dhclient can destroy the IPs inernally */
#endif
/* SPL */
/*
* Select the boot device here
*
* Currently supported are:
* SPL_BOOT_SPI_NOR_FLASH - Booting via SPI NOR flash
* SPL_BOOT_SDIO_MMC_CARD - Booting via SDIO/MMC card (partition 1)
*/
#define SPL_BOOT_SPI_NOR_FLASH 1
#define SPL_BOOT_SDIO_MMC_CARD 2
#define CONFIG_SPL_BOOT_DEVICE SPL_BOOT_SDIO_MMC_CARD
/* Defines for SPL */
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_SIZE (180 << 10)
#define CONFIG_SPL_TEXT_BASE 0x40000030
#define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_SIZE - 0x0030)
#define CONFIG_SPL_BSS_START_ADDR (0x40000000 + CONFIG_SPL_SIZE)
#define CONFIG_SPL_BSS_MAX_SIZE (16 << 10)
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_MALLOC_SIMPLE
#define CONFIG_OF_STDOUT_VIA_ALIAS
#endif
#define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10))
#define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4)
#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
/* SPL related SPI defines */
#define CONFIG_SPL_SPI_LOAD
#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x24000
#define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_SPI_U_BOOT_OFFS
#endif
#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD
/* SPL related MMC defines */
#define CONFIG_SYS_MMC_U_BOOT_OFFS (200 << 10)
#define CONFIG_SYS_U_BOOT_OFFS CONFIG_SYS_MMC_U_BOOT_OFFS
#ifdef CONFIG_SPL_BUILD
#define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER 0x00180000 /* in SDRAM */
#endif
#define CONFIG_SPL_BOARD_INIT
#endif
/*
* mv-common.h should be defined after CMD configs since it used them
* to enable certain macros
*/
#include "mv-common.h"
/*
* NBHW needs md5 support
*/
#ifndef CONFIG_MD5
#define CONFIG_MD5
#endif
/*
* We need some functions to be called after environment setup
*/
#define CONFIG_BOARD_LATE_INIT
#define CONFIG_AUTOBOOT_KEYED 1
#define CONFIG_AUTOBOOT_PROMPT \
"Press s to abort autoboot in %d seconds\n"
#undef CONFIG_AUTOBOOT_DELAY_STR
#define CONFIG_AUTOBOOT_STOP_STR "s"
#ifndef CONFIG_SPL_BUILD
#undef CONFIG_REQUIRE_SERIAL_CONSOLE
/* Wee need early init r to actually print the pre console buffer
* because u-boot is buggy */
#define CONFIG_BOARD_EARLY_INIT_R
#define CONFIG_MISC_INIT_R
#endif
#endif /* _CONFIG_DB_88F6820_GP_H */