ADD: [hw14] added hw14 platform to support new mc board

BugzId: 66150
This commit is contained in:
Marcel Reichmuth 2021-03-22 13:11:06 +01:00
parent 21fb3f581f
commit 1ffa09d30f
54 changed files with 3613 additions and 1753 deletions

View File

@ -617,9 +617,6 @@ KBUILD_AFLAGS += -Wa,-gstabs,-S
endif
endif
# Prohibit date/time macros, which would make the build non-deterministic
KBUILD_CFLAGS += $(call cc-option,-Werror=date-time)
include scripts/Makefile.extrawarn
# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments

View File

@ -83,6 +83,7 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
tegra210-p2571.dtb
dtb-$(CONFIG_ARCH_MVEBU) += \
armada-385-hw14.dtb \
armada-385-nbhw18-v2.dtb \
armada-385-nbhw17-v1.dtb \
armada-3720-db.dtb \

View File

@ -0,0 +1,240 @@
/*
* Device Tree file for the NetModule HW14 (NB3800)
*
* Copyright (C) 2021 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 NBHW14 with Armada A385";
compatible = "marvell,aramda385-hw14", "marvell,armada385", "marvell,armada380";
aliases {
/* So that mvebu u-boot can update the MAC addresses */
ethernet0 = &eth0;
ethernet1 = &eth1;
ethernet2 = &eth2;
/delete-property/ gpio0; /* Causes warnings when requesting gpios */
/delete-property/ gpio1; /* Causes warnings when requesting gpios */
};
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 (CS0) */
MBUS_ID(0x01, 0x3d) 0 0xf4000000 0x20000>; /* GPIO Ext (CS1) */
gpioext: gpio@f40000000 {
compatible = "nm,nbhw-gpio-ext";
reg = <MBUS_ID(0x01, 0x3d) 0 0x20000>; /* This translates to 0xf4000000 */
ngpios = <8>;
gpio-controller;
gpio-bank-name = "Ext";
#gpio-cells = <2>;
};
/* Following node cannot be put into corresponding
I2C bus, because I2C does not use DM and therefore
it would not get probed. */
gpioi2c: gpio@76 {
compatible = "nxp,pca9539";
reg = <0x76 0x00 0x00>;
gpio-controller;
#gpio-cells = <2>;
status = "okay";
};
gpio_pins {
compatible = "nm,gpios";
wd_enable = <&gpioext 4 GPIO_ACTIVE_LOW 0>;
rst_i2c_exp = <&gpioext 5 GPIO_ACTIVE_LOW 1>;
led_dbg = <&gpioext 7 GPIO_ACTIVE_HIGH 0>;
en_sata_pwr = <&gpioi2c 0 GPIO_ACTIVE_HIGH 0>;
usb1_vbus_in = <&gpioi2c 1 GPIO_ACTIVE_HIGH 0>;
usb1_drive_vbus = <&gpioi2c 2 GPIO_ACTIVE_HIGH 0>;
usb1_pwr_fault = <&gpioi2c 3 GPIO_ACTIVE_HIGH 0>;
ext_rst_en = <&gpioi2c 4 GPIO_ACTIVE_LOW 1>;
rst_fpga = <&gpioi2c 5 GPIO_ACTIVE_LOW 1>;
rst_usb_hub = <&gpioi2c 6 GPIO_ACTIVE_LOW 1>;
rst_pse_eth = <&gpioi2c 7 GPIO_ACTIVE_LOW 1>;
reset_button = <&gpio1 24 GPIO_ACTIVE_LOW 1>;
ext_oe = <&gpio0 21 GPIO_ACTIVE_LOW 0>;
serdes4_mux_en = <&gpiofpga 535 GPIO_ACTIVE_LOW 0>;
serdes4_mux_sel = <&gpiofpga 534 GPIO_ACTIVE_HIGH 1>; // 0=usb3, 1=pci
pex2_clk_1_4_mux_en = <&gpiofpga 533 GPIO_ACTIVE_LOW 0>;
pex2_clk_1_4_mux_sel = <&gpiofpga 532 GPIO_ACTIVE_HIGH 1>; // 0=pex2_clk on slot4, 1= pex2_clk on slot1
};
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-sck = <&gpioext 0 GPIO_ACTIVE_HIGH 0>; /* SCK */
spi-sdi = <&gpioext 1 GPIO_ACTIVE_HIGH 0>; /* SDI slave data in */
spi-ss = <&gpioext 2 GPIO_ACTIVE_LOW 0>; /* SS */
fpga-reset-logic = <&gpioi2c 5 GPIO_ACTIVE_HIGH 0>; /* FPGA logic reset */
fpga-cdone = <&gpioi2c 8 GPIO_ACTIVE_HIGH 0>; /* FPGA cdone */
fpga-cinit = <&gpioi2c 9 GPIO_ACTIVE_LOW 0>; /* FPGA cinit */
};
fpga_conf: fpgaconf@0 {
compatible = "nm,hw14-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>;
// pcie slot 0
pcieslot@0 {
reset = <&gpiofpga 384 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 400 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 2053 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 2069 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 1
pcieslot@1 {
reset = <&gpiofpga 385 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 401 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 4101 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 4117 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 2
pcieslot@2 {
reset = <&gpiofpga 386 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 402 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 6149 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 6165 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 3
pcieslot@3 {
reset = <&gpiofpga 387 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 403 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 8197 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 8213 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 4
pcieslot@4 {
reset = <&gpiofpga 388 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 404 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 10245 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 10261 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 5
pcieslot@5 {
reset = <&gpiofpga 389 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 405 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 12293 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 12309 GPIO_ACTIVE_LOW 1>;
};
};
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";
};
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";
};
};
};
};
// MAC0 is used for RGMII/MII (100 MBit/s switches on NB3701/NB3711)
&eth0 { /* ethernet@70000 */
status = "okay";
phy-mode = "mii";
fixed-link {
speed = <100>;
full-duplex;
};
};
// MAC1 is used for SGMII (1 GBit/s switches on NB3800)
&eth1 { /* ethernet@30000 */
status = "okay";
phy-mode = "sgmii";
fixed-link {
speed = <1000>;
full-duplex;
};
};
&mdio {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
};

View File

@ -0,0 +1,40 @@
/*
* Device Tree file for the NetModule HW14 (NB3800) base variant
*
* Copyright (C) 2020 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-hw14-common.dtsi"
/ {
model = "NetModule Router HW14 with Armada A385 (NB3800)";
chosen {
stdout-path = "serial0:115200n8";
};
soc {
internal-regs {
serial@12000 {
u-boot,dm-spl;
};
};
};
};
&eth0 {
status = "okay";
};
&eth1 {
status = "okay";
};

View File

@ -0,0 +1,20 @@
/*
* Device Tree file for the NetModule NBHW18-V2 (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-hw14-common.dtsi"
/ {
model = "NetModule Router HW14 with Armada A385 (NB3800)";
};

View File

@ -1,7 +1,7 @@
/*
* Device Tree file for the NetModule NBHW17 (NB2800)
*
* Copyright (C) 2016 NetModule
* Copyright (C) 2021 NetModule
*
* Stefan Eichenberger <stefan.eichenberger@netmodule.com>
*
@ -21,10 +21,8 @@
/* So that mvebu u-boot can update the MAC addresses */
ethernet1 = &eth1;
ethernet2 = &eth2;
};
chosen {
stdout-path = "serial1:115200n8";
/delete-property/ gpio0; /* Causes warnings when requesting gpios */
/delete-property/ gpio1; /* Causes warnings when requesting gpios */
};
memory {
@ -37,7 +35,16 @@
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 */
MBUS_ID(0x01, 0x3e) 0 0xfd000000 0x20000>; /* FPGA (CS0) */
gpio_pins {
compatible = "nm,gpios";
wd_enable = <&gpio0 27 GPIO_ACTIVE_LOW 0>;
rst_usb_hub = <&gpio1 9 GPIO_ACTIVE_LOW 1>;
rst_fpga = <&gpio1 12 GPIO_ACTIVE_LOW 1>;
rst_eth_phy = <&gpio0 21 GPIO_ACTIVE_LOW 1>;
reset_button = <&gpio1 24 GPIO_ACTIVE_LOW 1>;
};
gpiofpga: gpio@fd0000000 {
compatible = "nm,nbhw-fpga";
@ -46,13 +53,12 @@
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 26 0>; /* FPGA reset */
fpga-cdone = <&gpio0 29 0>; /* FPGA cdone */
fpga-reset-logic = <&gpio1 12 0>; /* FPGA reset logic (after load)*/
spi-sck = <&gpio1 7 GPIO_ACTIVE_HIGH 0>; /* SCK (MPP39) */
spi-sdi = <&gpio1 8 GPIO_ACTIVE_HIGH 0>; /* SDI slave data in (MPP40) */
spi-ss = <&gpio1 5 GPIO_ACTIVE_HIGH 0>; /* SS (MPP37) */
fpga-reset = <&gpio0 26 GPIO_ACTIVE_HIGH 0>; /* FPGA config reset */
fpga-cdone = <&gpio0 29 GPIO_ACTIVE_HIGH 0>; /* FPGA cdone */
fpga-reset-logic = <&gpio1 12 GPIO_ACTIVE_HIGH 0>; /* FPGA logic reset */
};
fpga_conf: fpgaconf@0 {
@ -64,28 +70,15 @@
<&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
hold-pwr-on = <&gpiofpga 64 0 1>;
en-gps-ant = <&gpiofpga 65 0 0>;
en-mdio-phy = <&gpiofpga 66 GPIO_ACTIVE_LOW 1>;
en-mdio-ext = <&gpiofpga 67 GPIO_ACTIVE_LOW 0>;
en-sata-pwr = <&gpiofpga 68 GPIO_ACTIVE_HIGH 1>;
serdes-sel = <&gpiofpga 69 GPIO_ACTIVE_HIGH 1>;
serdes-en = <&gpiofpga 70 GPIO_ACTIVE_LOW 0>;
rst-ext = <&gpiofpga 71 GPIO_ACTIVE_LOW 1>;
rst-ext-eth = <&gpiofpga 72 GPIO_ACTIVE_LOW 1>;
rst-ext-en = <&gpiofpga 73 GPIO_ACTIVE_HIGH 0>;
};
// pcie slot 0
pcieslot@0 {
reset = <&gpiofpga 384 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 400 GPIO_ACTIVE_HIGH 0>;
wdis-out = <&gpiofpga 2053 GPIO_ACTIVE_HIGH 1>;
wdis = <&gpiofpga 2068 GPIO_ACTIVE_LOW 1>;
wdis = <&gpiofpga 2069 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 1
pcieslot@1 {
reset = <&gpiofpga 385 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 401 GPIO_ACTIVE_HIGH 0>;
@ -93,6 +86,7 @@
wdis = <&gpiofpga 4117 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 2
pcieslot@2 {
reset = <&gpiofpga 386 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 402 GPIO_ACTIVE_HIGH 0>;
@ -100,6 +94,7 @@
wdis = <&gpiofpga 6165 GPIO_ACTIVE_LOW 1>;
};
// pcie slot 3
pcieslot@3 {
reset = <&gpiofpga 387 GPIO_ACTIVE_LOW 1>;
power = <&gpiofpga 403 GPIO_ACTIVE_HIGH 0>;
@ -128,14 +123,6 @@
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>;
@ -146,8 +133,12 @@
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
u-boot,dm-pre-reloc;
status = "okay";
};
usb@58000 {
status = "okay";
};
};
pcie-controller {

View File

@ -0,0 +1,40 @@
/*
* Device Tree file for the NetModule NBHW17 (NB2800) base variant
*
* Copyright (C) 2021 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-nbhw17-common.dtsi"
/ {
model = "NetModule Router NBHW17 with Armada A385 (NB2800)";
chosen {
stdout-path = "serial1:115200n8";
};
soc {
internal-regs {
serial@12100 {
u-boot,dm-spl;
};
};
};
};
&eth1 {
status = "okay";
};
&eth2 {
status = "okay";
};

View File

@ -15,6 +15,9 @@
/ {
model = "NetModule Router NBHW17 with Armada A385 (NB2800)";
// chosen {
// stdout-path = "serial1:115200n8";
// };
};
&eth1 {

0
arch/arm/dts/armada-385-nbhw18-v2.dts Executable file → Normal file
View File

View File

@ -88,9 +88,9 @@ config TARGET_DB_88F6820_GP
bool "Support DB-88F6820-GP"
select 88F6820
config TARGET_NM_NBHW18_V1
bool "Support NBHW18 V1"
select 88F6820
config TARGET_NM_HW14
bool "Support HW14"
select 88F6820
config TARGET_NM_NBHW18_V2
bool "Support NBHW18 V2"
@ -154,6 +154,7 @@ config SYS_BOARD
default "ds414" if TARGET_DS414
default "maxbcm" if TARGET_MAXBCM
default "theadorable" if TARGET_THEADORABLE
default "hw14" if TARGET_NM_HW14
default "nbhw18_v1" if TARGET_NM_NBHW18_V1
default "nbhw18_v2" if TARGET_NM_NBHW18_V2
default "nbhw17_v1" if TARGET_NM_NBHW17_V1
@ -170,6 +171,7 @@ config SYS_CONFIG_NAME
default "maxbcm" if TARGET_MAXBCM
default "theadorable" if TARGET_THEADORABLE
default "turris_omnia" if TARGET_TURRIS_OMNIA
default "armada-385-hw14" if TARGET_NM_HW14
default "armada-385-nbhw18-v2" if TARGET_NM_NBHW18_V2
default "armada-385-nbhw17-v1" if TARGET_NM_NBHW17_V1
@ -183,6 +185,7 @@ config SYS_VENDOR
default "solidrun" if TARGET_CLEARFOG
default "Synology" if TARGET_DS414
default "CZ.NIC" if TARGET_TURRIS_OMNIA
default "nm" if TARGET_NM_HW14
default "nm" if TARGET_NM_NBHW18_V1
default "nm" if TARGET_NM_NBHW18_V2
default "nm" if TARGET_NM_NBHW17_V1

View File

@ -18,8 +18,9 @@
static struct mbus_win windows[] = {
/* SPI */
{ MBUS_SPI_BASE, MBUS_SPI_SIZE,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH },
/* @@NM@@MR@@ Conflicts with the windows for the HW14 gpio extension */
/*{ MBUS_SPI_BASE, MBUS_SPI_SIZE,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH }, */
/* NOR */
{ MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE,

View File

@ -27,7 +27,7 @@
#include "nbhw_bd.h"
static const BD_Context *bdctx_list; /* The board descriptor context */
static size_t bdctx_count = 0;
static size_t bdctx_count = 0;
void bd_register_context_list(const BD_Context *list, size_t count) {
bdctx_list = list;
@ -37,8 +37,8 @@ void bd_register_context_list(const BD_Context *list, size_t count) {
int bd_get_context(BD_Context *bdctx, uint32_t i2caddress, uint32_t offset)
{
bd_bool_t rc;
uint8_t bdHeader[8];
void* pBdData = NULL;
uint8_t bdHeader[8];
void* pBdData = NULL;
/* Read header bytes from beginning of EEPROM */
if (i2c_read( i2caddress, offset, 2, bdHeader, BD_HEADER_LENGTH )) {
printf("%s() Can't read BD header from EEPROM\n", __func__);

View File

@ -21,6 +21,7 @@ void set_console(void)
char buf[6];
char consolefile[] = "/root/boot/consoledev";
char *defaultconsole = env_get("defaultconsole");
int use_default_console = 0;
#if defined(CONFIG_PRE_CONSOLE_BUFFER)
int len = 0;
@ -28,17 +29,28 @@ void set_console(void)
read_file_set_blk_dev("mmc", "0:3", FS_TYPE_EXT);
len = get_file_size(consolefile);
if (len>=5) {
read_file(consolefile, buf, sizeof(buf));
buf[sizeof(buf)-1] = 0;
if ((strstr(buf, "tty")!=buf) || ((buf[4]<'0') && (buf[4]>'1'))) {
if (len>=4) {
memset(buf, 0x00, sizeof(buf));
read_file(consolefile, buf, sizeof(buf)-1);
if (strstr(buf, "ttyS")==buf) {
if ((buf[4]<'0') && (buf[4]>'1')) {
/* invalid tty specified */
use_default_console = 1;
} else {
/* Use retrieved ttySx */
}
} else if (strstr(buf, "none")==buf) {
/* disable console */
buf[0] = 0;
} else {
/* invalid device specified */
use_default_console = 1;
}
} else {
buf[0] = 0;
use_default_console = 1;
}
if (buf[0] == 0) {
if (use_default_console) {
strncpy(buf, defaultconsole, sizeof(buf));
}
printf("consoledev: %s\n", buf);

View File

@ -51,7 +51,9 @@ struct nbhw_fpga_priv {
struct gpio_desc ss;
struct gpio_desc sck;
struct gpio_desc sdi;
#ifdef CONFIG_FPGA_LATTICE_SSPI
struct gpio_desc sdo;
#endif
struct gpio_desc reset;
struct gpio_desc reset_logic;
struct gpio_desc cdone;
@ -72,6 +74,8 @@ void tickdelay(void)
while (get_ticks() < curtick+1); /* loop till event */
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
static inline u8 spi_read_sspi(const struct nbhw_fpga_priv *priv)
{
int i;
@ -119,6 +123,8 @@ static inline void spi_write_sspi(const struct nbhw_fpga_priv *priv, u8 data)
}
}
#endif
static inline void spi_write(const struct nbhw_fpga_priv *priv, u8 data)
{
int i;
@ -130,13 +136,13 @@ static inline void spi_write(const struct nbhw_fpga_priv *priv, u8 data)
{
data_write = (data & 0x80) ? 1 : 0;
/* Clear clk bit and put data on the line */
dm_gpio_set_value(&priv->sck, 0);
dm_gpio_set_value(&priv->sdi, data_write);
udelay(1);
dm_gpio_set_value(&priv->sck, 0);
dm_gpio_set_value(&priv->sdi, data_write);
tickdelay();
/* Read data on rising edge */
dm_gpio_set_value(&priv->sck, 1);
dm_gpio_set_value(&priv->sck, 1);
data = data << 1;
udelay(1);
tickdelay();
}
}
@ -153,19 +159,19 @@ static int fpga_verify(struct nbhw_fpga_priv *priv)
if (signature == 0xa501)
{
strcpy(fpga_type, "XC3S50A-4VQ100I top layer");
strcpy(fpga_type, "XC3S50A-4VQ100I top layer HW14");
} else if (signature == 0xa502) {
strcpy(fpga_type, "XC3S200A-4VQ100I top layer");
strcpy(fpga_type, "XC3S200A-4VQ100I top layer HW14");
} else if (signature == 0xa511) {
strcpy(fpga_type, "XC3S50A-4FTG256I bottom layer");
strcpy(fpga_type, "XC3S50A-4FTG256I bottom layer HW14");
} else if (signature == 0xa512) {
strcpy(fpga_type, "XC3S200A-4FTG256I bottom layer");
strcpy(fpga_type, "XC3S200A-4FTG256I bottom layer HW14");
} else if (signature == 0x4004) {
strcpy(fpga_type, "ICE40HX4K-CB132 NBHW17");
strcpy(fpga_type, "ICE40HX4K-CB132 HW17");
} else if (signature == 0x4184) {
strcpy(fpga_type, "ICE40HX4K-CB132 NBHW18 V1");
strcpy(fpga_type, "ICE40HX4K-CB132 HW18 V1");
} else if (signature == 0x012f) {
strcpy(fpga_type, "LFE5U-12F-6BG381I NBHW18 V2");
strcpy(fpga_type, "LFE5U-12F-6BG381I HW18 V2");
} else {
priv->signature = signature;
goto abort;
@ -183,6 +189,8 @@ abort:
return 0;
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
#define print_out_string printf
extern unsigned int a_uiRowCount;
void printError(int code){
@ -246,6 +254,8 @@ void printError(int code){
}
}
#endif
static void put_in_prog_mode(const struct nbhw_fpga_priv *priv)
{
/* Change the muxing to GPIO */
@ -255,6 +265,7 @@ static void put_in_prog_mode(const struct nbhw_fpga_priv *priv)
printf("Put FPGA in programming mode\n");
dm_gpio_set_value(&priv->ss, 1);
udelay(10);
dm_gpio_set_value(&priv->ss, 0);
dm_gpio_set_value(&priv->sck, 1);
dm_gpio_set_value(&priv->reset, 1);
@ -268,6 +279,8 @@ static void put_in_prog_mode(const struct nbhw_fpga_priv *priv)
udelay(800);
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
static void put_in_prog_mode_lattice_sspi(const struct nbhw_fpga_priv *priv)
{
/* Change the muxing to GPIO */
@ -297,13 +310,15 @@ static void put_in_prog_mode_lattice_sspi(const struct nbhw_fpga_priv *priv)
debug("Initialised Reset with pulling PROGRAM~\n");
}
#endif
static void clean_up_after_programming(const struct nbhw_fpga_priv *priv)
{
/* Change the muxing back to Devbus */
writel(0x55555555, MVEBU_MPP_BASE + 0x10);
writel(0x06605505, MVEBU_MPP_BASE + 0x14);
//dm_gpio_set_value(&priv->reset_logic, 0); //TODO : that seems wrong (AO)
dm_gpio_set_value(&priv->reset_logic, 0); //TODO : that seems wrong (AO)
udelay(100);
dm_gpio_set_value(&priv->reset_logic, 1);
udelay(100);
@ -326,13 +341,6 @@ static int fpga_load_bitstream (const struct nbhw_fpga_priv *priv, const u8* dat
debug("Configuration sent\n");
if (dm_gpio_get_value(&priv->cdone)) {
printf("Error: Fpga does not signal done\n");
return 0;
}
debug("FPGA signals done\n");
/* Send some extra clocks for startup */
for ( i=0; i<100; i++)
{
@ -344,25 +352,6 @@ static int fpga_load_bitstream (const struct nbhw_fpga_priv *priv, const u8* dat
return 1;
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
static int fpga_load_bitstream_lattice_sspi (const struct nbhw_fpga_priv *priv,
const u8* pBitstreamAddr, int pBitstreamSize,
const u8* pAlgoAddr, int pAlgoSize)
{
int siRetCode;
siRetCode = SSPIEm_preset(pAlgoAddr, pAlgoSize, pBitstreamAddr, pBitstreamSize);
siRetCode = SSPIEm(0xFFFFFFFF);
if ( siRetCode != 2 ) {
printError(siRetCode);
return 0;
}
return 1;
}
#endif
static int fpga_check_bitstream_lattice(const struct nbhw_fpga_priv *priv,
const u8* fpgadata, int dataNumBytes,
const u8** pBitstreamAddr, int* pBitstreamSize)
@ -384,6 +373,23 @@ static int fpga_check_bitstream_lattice(const struct nbhw_fpga_priv *priv,
return 0;
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
static int fpga_load_bitstream_lattice_sspi (const struct nbhw_fpga_priv *priv,
const u8* pBitstreamAddr, int pBitstreamSize,
const u8* pAlgoAddr, int pAlgoSize)
{
int siRetCode;
siRetCode = SSPIEm_preset(pAlgoAddr, pAlgoSize, pBitstreamAddr, pBitstreamSize);
siRetCode = SSPIEm(0xFFFFFFFF);
if ( siRetCode != 2 ) {
printError(siRetCode);
return 0;
}
return 1;
}
#define CHECKMARKER(index, a, b, c, d) ((fpgadata[index]==a) && (fpgadata[index+1]==b) \
&& (fpgadata[index+2]==c) && (fpgadata[index+3]==d))
@ -432,6 +438,8 @@ abort:
return -1;
}
#endif
/* Legacy Xilinx check ported from PPC, seems to work */
static int fpga_check_bitstream_xilinx(const struct nbhw_fpga_priv *priv,
const u8* fpgadata, int dataNumBytes,
@ -474,10 +482,6 @@ static int fpga_check_bitstream_xilinx(const struct nbhw_fpga_priv *priv,
printf(" design filename = \"%s\"\n", buffer);
/* verify fpga identifier */
if (priv->fpga_id == 0xFFFFFFFF) {
return 0;
}
p = strstr(buffer, "UserID=0x");
if (p) {
p += 9;
@ -496,10 +500,13 @@ static int fpga_check_bitstream_xilinx(const struct nbhw_fpga_priv *priv,
return -1;
}
}
if (fpgaid != priv->fpga_id) {
printf("%s: User identifier not matched in bitstream\n",
__FUNCTION__ );
return -1;
/* verify fpga identifier */
if (priv->fpga_id != 0xFFFFFFFF) {
if (fpgaid != priv->fpga_id) {
printf("%s: User identifier not matched in bitstream\n",
__FUNCTION__ );
return -1;
}
}
} else {
printf("%s: User identifier not found in bitstream\n",
@ -580,21 +587,24 @@ static int fpga_check_bitstream(const struct nbhw_fpga_priv *priv,
debug("check bitstream %d, %0x, %0x\n", *pBitstreamSize, fpgadata[0],
fpgadata[1]);
/* Lattice header starts with 0xFF00 followed by comment */
if (fpgadata[0] == 0xFF && fpgadata[1] == 0x00) {
return fpga_check_bitstream_lattice(priv, fpgadata, dataNumBytes, pBitstreamAddr, pBitstreamSize);
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
/* Lattice SSPI header starts with 0xae 0x00 0x00 0x01 (SEA tag) */
else if(fpgadata[0] == 0xae && fpgadata[1] == 0x00) {
return fpga_check_bitstream_lattice_sspi(priv, fpgadata, dataNumBytes,
pBitstreamAddr, pBitstreamSize,
pAlgoAddr, pAlgoSize);
}
#else
/* Xilinx header starts with 0x00 0x09 which means header with 0x09 length */
else if(fpgadata[0] == 0x00 && fpgadata[1] == 0x09) {
if(fpgadata[0] == 0x00 && fpgadata[1] == 0x09) {
return fpga_check_bitstream_xilinx(priv, fpgadata, dataNumBytes, pBitstreamAddr, pBitstreamSize);
}
#endif
printf("Unknown bitstream file format (not Xilinx nor Lattice)\n");
return -1;
}
@ -675,7 +685,7 @@ static void setup_device_bus(void)
/* Device Bus Control Interface Register */
val = readl(MV_DEV_BUS_REGS_OFFSET + 0xC0);
debug("Device Bus Control Interface Regiseter (0x104C0): 0x%08X\n", val);
debug("Device Bus Control Interface Register (0x104C0): 0x%08X\n", val);
writel(0x5FFFF, MV_DEV_BUS_REGS_OFFSET + 0xC0);
/* Device Bus Synchronous Control Register */
val = readl(MV_DEV_BUS_REGS_OFFSET + 0xC8);
@ -727,15 +737,15 @@ static int request_gpios(struct udevice *dev)
printf("Could not request spi-gpio sdi\n");
return -1;
}
#ifdef CONFIG_FPGA_LATTICE_SSPI
if (gpio_request_by_name(dev, "spi-sdo", 0, &priv->sdo, GPIOD_IS_IN) != 0) {
printf("Could not request spi-gpio sdo\n");
return -1;
}
#endif
if (gpio_request_by_name(dev, "fpga-reset", 0, &priv->reset, GPIOD_IS_OUT) != 0) {
printf("Could not request fpga-reset\n");
return -1;
debug("Could not request fpga-reset\n");
}
if (gpio_request_by_name(dev, "fpga-cdone", 0, &priv->cdone, GPIOD_IS_IN) != 0) {
@ -777,15 +787,15 @@ static int fpga_program(struct udevice *dev, unsigned long load_addr,
}
}
/* Make sure device bus works, because HW14 uses its gpios to do SPI */
setup_device_bus();
/* NBHW_BASE_ADDRESS_FPGA points to base of FPGA registers */
if (!fpga_boot_buffer(priv, (const u8*)load_addr, filesize)) {
printf ("Loading FPGA over SPI failed.\n");
return -3;
}
/* Make sure device bus works, becaus NBHW14 uses its gpios to do SPI */
setup_device_bus();
/* Verify, if FPGA is loaded successfully */
i = 0;
do {
@ -1032,6 +1042,7 @@ U_BOOT_DRIVER(gpio_nbhw_fpga) = {
.ops = &nbhw_fpga_ops,
};
#ifdef CONFIG_FPGA_LATTICE_SSPI
/* Lattice SSPI programming tool wrappers */
void FPGA_START(void) {
@ -1060,3 +1071,4 @@ void FPGA_CS_HIGH(void)
dm_gpio_set_value(&FPGA_PRIV->ss, 1);
}
#endif

View File

@ -6,16 +6,16 @@
#define FPGA_REG(x) *((volatile unsigned short*)( NBHW_BASE_ADDRESS_FPGA + ((unsigned int)x)))
typedef enum _fpga_type {
FPGA_TYPE_NONE,
FPGA_TYPE_XILINX,
FPGA_TYPE_LATTICE,
FPGA_TYPE_NONE,
FPGA_TYPE_XILINX,
FPGA_TYPE_LATTICE,
}fpga_type;
typedef struct _fpga_prog_operation {
void (*pre_programming)(void);
void (*post_programming)(void);
void (*spi_write)(u8);
int (*check_bitstream_compatibility)(fpga_type, u32);
int (*check_bitstream_compatibility)(fpga_type, u32);
} fpga_prog_operation;
int nbhw_fpga_program(void);

View File

@ -0,0 +1,130 @@
/******************************************************************************
* (c) COPYRIGHT 2020 by NetModule AG, Switzerland. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*****************************************************************************/
#undef DEBUG
#include <common.h>
#include <dm.h>
#include <dm/device.h>
#include <asm/types.h>
#include <asm/gpio.h>
#include <asm/io.h>
struct nbhw_gpio_ext_priv {
volatile u8* base_addr;
u8 value;
};
static int nbhw_gpio_ext_bind(struct udevice *dev)
{
struct nbhw_gpio_ext_priv *priv = malloc(sizeof(struct nbhw_gpio_ext_priv));
if (priv == NULL) {
puts("Can't allocate memory for nbhw gpio ext driver\n");
return -1;
}
dev->priv = priv;
/* Get memory address for gpio ext */
priv->base_addr = (u8*)devfdt_get_addr(dev);
debug("GPIO Ext address: %p\n", priv->base_addr);
priv->value = 0;
return 0;
}
static int nbhw_gpio_ext_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
"gpio-bank-name", NULL);
uc_priv->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"ngpios", 1024);
debug("%s done\n", __func__);
return 0;
}
static int nbhw_gpio_ext_get_value (struct udevice *dev, unsigned offset)
{
struct nbhw_gpio_ext_priv *priv = dev_get_priv(dev);
if (offset > 7) return -1;
return ((priv->value) >> offset) & 0x01;
}
static int nbhw_gpio_ext_set_value (struct udevice *dev, unsigned offset, int value)
{
struct nbhw_gpio_ext_priv *priv = dev_get_priv(dev);
debug("%s\n", __func__);
if (offset > 7) return -1;
priv->value &= ~(1 << offset);
priv->value |= ((value ? 1 : 0) << offset);
debug("Write 0x%x to addr 0x%x (offset:0x%x, value:0x%x)\n", priv->value, (int)priv->base_addr, offset, value);
return writeb(priv->value, priv->base_addr);
}
static int nbhw_gpio_ext_direction_input(struct udevice *dev, unsigned offset)
{
debug("%s offset:0x%x\n", __func__, offset);
return 0;
}
static int nbhw_gpio_ext_direction_output (struct udevice *dev, unsigned offset, int value)
{
debug("%s offset:%d, value:%d\n", __func__, offset, value);
nbhw_gpio_ext_set_value(dev, offset, value);
return 0;
}
static int nbhw_gpio_ext_get_function(struct udevice *dev, unsigned offset)
{
return GPIOF_OUTPUT;
}
static const struct dm_gpio_ops nbhw_gpio_ext_ops = {
.direction_input = nbhw_gpio_ext_direction_input,
.direction_output = nbhw_gpio_ext_direction_output,
.get_value = nbhw_gpio_ext_get_value,
.set_value = nbhw_gpio_ext_set_value,
.get_function = nbhw_gpio_ext_get_function,
};
static const struct udevice_id nbhw_gpio_ext_ids[] = {
{ .compatible = "nm,nbhw-gpio-ext" },
{ }
};
U_BOOT_DRIVER(gpio_nbhw_gpio_ext) = {
.name = "gpio_nbhw_gpio_ext",
.id = UCLASS_GPIO,
.of_match = nbhw_gpio_ext_ids,
.probe = nbhw_gpio_ext_probe,
.bind = nbhw_gpio_ext_bind,
.ops = &nbhw_gpio_ext_ops,
};

View File

@ -34,7 +34,7 @@ static void set_mac(int interface, uint8_t macaddress[], size_t size)
/* Serial number consists of 1st MAC address */
env_set("ethaddr", macstring);
}
/* Always set eth%daddr because newer u-boots expect it */
/* Always set eth%daddr because newer u-boots expect it */
{
char ethaddr[32];
@ -45,23 +45,20 @@ static void set_mac(int interface, uint8_t macaddress[], size_t size)
}
}
void set_mac_addresses(int interfaces) {
void set_mac_address(int interface, int mac) {
uint8_t macaddress[6];
int i;
/* If the compiler does inlining direct initialization of macaddress
* fails, this is the safer way */
/* If the compiler does inlining direct initialization of macaddress
* fails, this is the safer way */
memset(macaddress, 0x11, sizeof(macaddress));
for (i = 0; i < interfaces; i++) {
if(bd_get_mac(i, macaddress, 6) == 0)
set_mac(i, macaddress, 6);
else {
/* make temporary address */
macaddress[0] = 0;
macaddress[5] += 1;
set_mac(i, macaddress, 6);
}
if (bd_get_mac(mac, macaddress, 6) == 0)
set_mac(interface, macaddress, 6);
else {
/* make temporary address */
macaddress[0] = 0;
macaddress[5] += 1;
set_mac(interface, macaddress, 6);
}
}

View File

@ -8,6 +8,6 @@
#ifndef _NBHW_INIT_H
#define _NBHW_INIT_H
void set_mac_addresses(int interfaces);
void set_mac_address(int interface, int mac);
#endif // _NBHW_INIT_H

View File

@ -81,7 +81,7 @@ static int has_slot_wlan(int slot)
char pdValue[200];
sprintf(slotDescr, "slot=%d", slot);
for (module=0; module<4; module++) {
for (module=0; module<6; module++) {
strcpy(pdValue, "" ); /*init with an empty string*/
if (bd_get_pd_module(module, pdValue, sizeof(pdValue))==0) {
/* Wifi module needs PCIe */
@ -127,7 +127,6 @@ static int has_pcie_link_on_slot(int slot)
default:
printf("Slot %d does not support PCIE\n", slot);
}
return 1;
}
@ -227,7 +226,7 @@ static void wait_for_reset(int reset_counter)
* boot */
static int do_wlan_fixup(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
int i, j;
#define MAX_RESET_COUNT 6
int reset_counter = get_reset_counter();
int ret;
@ -244,11 +243,10 @@ static int do_wlan_fixup(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv
/* Try it for at least one second */
for (i = 0; i < 100; i++) {
ret = 3;
if (check_pcie_slot_status(0)) ret &= ~1;
if (check_pcie_slot_status(1)) ret &= ~2;
ret = 0x3f;
for (j = 0; j < 6; j++) {
if (check_pcie_slot_status(j)) ret &= ~(1 << j);
}
if (is_module_check_abort()) {
puts("Abort WLAN module check\n");
ret = 0;

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

30
board/nm/hw14/Makefile Normal file
View File

@ -0,0 +1,30 @@
#
# 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_gpio_ext.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 mvswitch.o \
../common/nbhw_sim.o nbhw_sim.o \
$(commonobj)
else
obj-y := board.o \
../common/nbhw_bd.o \
../common/nbhw_partitions.o \
../common/bdparser.o \
../common/nbhw_bd.o
endif

18
board/nm/hw14/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

839
board/nm/hw14/board.c Normal file
View File

@ -0,0 +1,839 @@
/*
* 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 "mvswitch.h"
#include "../common/nbhw_init.h"
#include "../common/nbhw_env.h"
#include "../common/nbhw_bd.h"
#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
#include <../serdes/a38x/high_speed_env_spec.h>
//#define EARLY_CONSOLE_OUTPUT
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(21))) /* 1=Input, default input */
#define GPP_OUT_ENA_MID (~(BIT(16)))
#define GPP_OUT_VAL_LOW (BIT(21))
#define GPP_OUT_VAL_MID (0x00)
#define GPP_POL_LOW 0x0
#define GPP_POL_MID 0x0
#define CP_BD_EEPROM_ADDR (0x50) /* CPU BD EEPROM (8kByte) is at 50 (A0) */
#define MC_BD_EEPROM_ADDR (0x51) /* MC BD EEPROM (8kByte) is at 51 (A0) */
#define PSE_BD_EEPROM_ADDR (0x52) /* PSE BD EEPROM (8kByte) is at 52 (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
#define DEV_CS1_BASE 0xf4000000
/* Default serdes configuration */
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 },
{ SATA1, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
{ PEX3, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 },
{ USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
{ PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 }
};
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[5]; /* The descriptor context */
static int _bd_init(void)
{
if (bd_get_context(&bdctx[0], CP_BD_EEPROM_ADDR, BD_ADDRESS) != 0) {
printf("%s() no valid cp bd found\n", __func__);
return -1;
}
if (bd_get_context(&bdctx[1], CP_BD_EEPROM_ADDR, PD_ADDRESS) != 0) {
/* Ignore that, legacy boxes don't have a pd */
}
if (bd_get_context(&bdctx[2], CP_BD_EEPROM_ADDR, PARTITION_ADDRESS) != 0) {
printf("%s() no valid partition table found\n", __func__);
}
if (bd_get_context(&bdctx[3], MC_BD_EEPROM_ADDR, BD_ADDRESS) != 0) {
printf("%s() no valid mc bd found\n", __func__);
}
if (bd_get_context(&bdctx[4], PSE_BD_EEPROM_ADDR, BD_ADDRESS) != 0) {
printf("%s() no valid pse bd 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(CP_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;
}
#define RESET_REASON_SHM_LOCATION (0x3ffff000)
extern int console_init_f(void);
#if !defined(CONFIG_SPL_BUILD)
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();
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;
}
#endif
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{
int i;
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 {
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 */
type = bd_get_serdes_type(i);
}
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;
}
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(0x11111111, MVEBU_MPP_BASE + 0x00);
writel(0x11111111, MVEBU_MPP_BASE + 0x04);
writel(0x55011111, MVEBU_MPP_BASE + 0x08);
writel(0x55550550, MVEBU_MPP_BASE + 0x0c);
writel(0x55555555, MVEBU_MPP_BASE + 0x10);
writel(0x06605505, MVEBU_MPP_BASE + 0x14);
writel(0x55550555, MVEBU_MPP_BASE + 0x18);
writel(0x00005550, 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;
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");
}
#if !defined(CONFIG_SPL_BUILD)
static void get_hw14_hw_version(BD_Context* bdctx, int *ver, int *rev)
{
static uint8_t hwver = 0;
static uint8_t hwrev = 0;
if ( !BD_GetUInt8( bdctx, BD_Hw_Ver, 0, &hwver) )
debug("%s() no Hw Version found\n", __func__);
if ( !BD_GetUInt8( bdctx, BD_Hw_Rel, 0, &hwrev) )
debug("%s() no Hw Release found\n", __func__);
*ver = hwver;
*rev = hwrev;
}
static void pass_hw_rev(void)
{
int cm_hw_ver = 0, cm_hw_rev = 0;
int mc_hw_ver = 0, mc_hw_rev = 0;
int pse_hw_ver = 0, pse_hw_rev = 0;
char *old_env;
char hw_versions[128];
char new_env[256];
get_hw14_hw_version(&bdctx[0], &cm_hw_ver, &cm_hw_rev);
get_hw14_hw_version(&bdctx[3], &mc_hw_ver, &mc_hw_rev);
get_hw14_hw_version(&bdctx[4], &pse_hw_ver, &pse_hw_rev);
snprintf(hw_versions, sizeof(hw_versions), "CP=%d.%d MC=%d.%d PSE=%d.%d",
cm_hw_ver, cm_hw_rev, mc_hw_ver, mc_hw_rev, pse_hw_ver, pse_hw_rev);
old_env = env_get("add_version_bootargs");
/* Normaly add_version_bootargs should already be set (see board include file) */
if (old_env != NULL) {
snprintf(new_env, sizeof(new_env), "%s %s", old_env, hw_versions);
}
else {
snprintf(new_env, sizeof(new_env), "setenv bootargs $bootargs %s", hw_versions);
}
env_set("add_version_bootargs", new_env);
}
#endif
int board_init(void)
{
#if defined(CONFIG_WATCHDOG)
watchdog_init();
#endif
/* address of boot parameters */
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
/* Setup the MBUS mapping for Devicebus CS0 (FPGA) */
mbus_dt_setup_win(&mbus_state, DEV_CS0_BASE, 16 << 20,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS0 /* 0x3e */);
/* Setup the MBUS mapping for Devicebus CS1 (GPIO Ext) */
/* Warning: Conflicts with the default definition for MBUS_SPI_BASE in arch/arm/mach-mvebu/cpu.c */
mbus_dt_setup_win(&mbus_state, DEV_CS1_BASE, 16 << 20,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS1 /* 0x3d */ );
if (read_eeprom() < 0)
puts("Could not get board ID.\n");
/* @@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)
{
return (get_gpio(GPIO_RESET_BUTTON) == 0);
}
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 */
static void init_rtc(void)
{
/* Enable trickle charger for rtc backup capacitor */
uchar charge_mode = 0xa5; /* No diode, 250 Ohm resistor */
if (0 != i2c_write(0x68, 0x10, 1, &charge_mode, 1))
{
puts("No RTC found\n");
}
}
#endif /* !defined(CONFIG_SPL_BUILD) */
int misc_init_r(void)
{
struct serdes_map* sm;
u8 sm_count;
#ifdef EARLY_CONSOLE_OUTPUT
init_console();
console_init_f();
#endif
/* Initialize output extension */
debug("Power on WD and other stuff\n");
set_gpio(GPIO_WD_ENABLE, 0);
set_gpio(GPIO_RST_I2C_EXP, 0);
set_gpio(GPIO_LED_DBG, 1);
/* Drive CS1 output extension pins */
debug("Enable DevBus IO Expander\n");
set_gpio(GPIO_EXT_OE, 1);
mdelay(20);
/* Enable SATA power */
debug("Enable SATA\n");
set_gpio(GPIO_EN_SATA_PWR, 1);
mdelay(10);
/* Deassert USB hub reset */
debug("Enable USB Hub\n");
set_gpio(GPIO_RST_USB_HUB, 0);
mdelay(10);
/* Enable USB bus power */
debug("Enable USB\n");
set_gpio(GPIO_USB1_DRIVE_VBUS, 1);
mdelay(10);
/* Deassert ethernet switch reset */
debug("Enable ethernet switch\n");
set_gpio(GPIO_RST_PSE_ETH, 0);
mdelay(10);
/* Determine SERDES configuration */
hws_board_topology_load(&sm, &sm_count);
#if !defined(CONFIG_SPL_BUILD)
/* Enable PMIC RTC backup charger (charge with 6mA to 3.1V) */
init_rtc();
#endif
return 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 in BD\n");
strncpy(devicetreename, "openwrt-nbhw14.dtb", sizeof(devicetreename));
if (get_mvswitch_type() != MVS_88E6060) {
strncpy(devicetreename, "openwrt-nbhw14-sgmii.dtb", sizeof(devicetreename));
}
printf ("Selected %s devicetree file based on ethernet configuration\n", devicetreename);
}
env_set("fdt_image", devicetreename);
}
#endif
int board_late_init(void)
{
#if !defined(CONFIG_SPL_BUILD)
find_and_set_active_partition();
pass_hw_rev();
run_command("run load_fpga", CMD_FLAG_ENV);
#ifndef EARLY_CONSOLE_OUTPUT
init_console();
console_init_f();
#endif
check_reset_button();
/* Set address on both MACs as RGMII and SGMII use different MACs */
set_mac_address(0, 0);
set_mac_address(1, 0);
#endif
return 0;
}
#if !defined(CONFIG_SPL_BUILD)
int board_network_enable(struct mii_dev *bus)
{
static int NETWORK_ENABLED = 0;
if (!NETWORK_ENABLED) {
configure_mvswitch();
set_devicetree_name();
NETWORK_ENABLED = 1;
}
return 0;
}
#endif
int checkboard(void)
{
debug("Board: NetModule HW14\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-hw14-spl"
#else
/* U-Boot will read /boot/consoledev and based on that it
* enables its own serial console */
#define DEFAULT_DTB_NAME "armada-385-hw14"
#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 :
if ((board_serdes_map[4].serdes_type >= PEX0) &&
(board_serdes_map[4].serdes_type <= PEX3))
{
serdes = 4;
} else {
serdes = -1;
}
break;
case 4 :
if ((board_serdes_map[5].serdes_type >= PEX0) &&
(board_serdes_map[5].serdes_type <= PEX3))
{
serdes = 5;
} else {
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;
}
}
/*******************************************************************************
Enable additional nodes in DTS depending on board descriptor
*******************************************************************************/
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)
{
char pdValue[200];
/* Enabled all components in dts depending on
current serdes configuration */
/* Enable DIOs on PSE board (NB37xx only) */
memset(pdValue, 0x00, sizeof(pdValue));
if (bd_get_prodname(pdValue, sizeof(pdValue))==0) {
if (strstr(pdValue, "37")) {
/* if it is an NB3700 series device enable
the on board DIOs on the PSE */
printf("FT: enable netbox_dio_pse\n");
ft_enable_node(blob, "/fpga_dio");
}
}
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

178
board/nm/hw14/mvswitch.c Normal file
View File

@ -0,0 +1,178 @@
#undef DEBUG
#include <common.h>
#include <miiphy.h>
#include "mvswitch.h"
static enum MvSwitchType mvSwType = MVS_UNKNOWN;
static int check_mvswitch(void)
{
const char* miidev = miiphy_get_current_dev();
unsigned short switchPortProductId;
int res;
debug ("miidev: %s\n", miidev);
res = miiphy_read(miidev, 0x10, 0x03, &switchPortProductId);
if (res) goto abort;
if ((switchPortProductId & 0xfff0) == 0x0990) {
unsigned short statusRegister;
res = miiphy_read(miidev, 0x1A, 0x00, &statusRegister);
if (res) goto abort;
/* If status register says phy is in SGMII mode */
if ((statusRegister & 0x07) == 0x6) {
printf("Detected MV88E6097 switch in SGMII mode (0x%4.4x)\n", switchPortProductId);
}
else {
printf("Detected MV88E6097 switch in RGMII mode (0x%4.4x)\n", switchPortProductId);
}
mvSwType = MVS_88E6097;
} else {
res = miiphy_read(miidev, 0x08, 0x03, &switchPortProductId);
if (res) goto abort;
if ((switchPortProductId & 0xfff0) == 0x0600) {
printf("Detected MV88E6060 switch in MII mode (0x%4.4x)\n", switchPortProductId);
mvSwType = MVS_88E6060;
}
}
return 0;
abort:
printf("Could not identify ethernet switch!");
return 1;
}
static int init_mvswitch(void)
{
const char* miidev = miiphy_get_current_dev();
unsigned short value;
unsigned short page;
int i;
debug ("miidev: %s\n", miidev);
switch (mvSwType)
{
case MVS_88E6097 :
/* Disable PPU */
miiphy_write(miidev, 0x1b, 0x0004, 0x0080);
/* Reset switch */
miiphy_write(miidev, 0x1b, 0x0004, 0x8080);
for (i = 0x10; i <= 0x1a; i++) {
/* Isolate external ports from each other */
if (i==0x1a)
{
miiphy_write(miidev, i, 0x06, 0x03ff);
} else {
miiphy_write(miidev, i, 0x06, 0x0400);
}
/* Enable forwarding & flooding of unknown addresses on all ethernet ports */
value = 0x000f;
miiphy_write(miidev, i, 0x04, value);
}
/* Power-up all ethernet phys except 10 (mii no phy) */
for (i = 0x00; i <= 0x0A; i++) {
if (i == 0x0A) continue;
miiphy_read(miidev, i, 0x00, &value);
value &= ~0x0800;
miiphy_write(miidev, i, 0x00, value);
}
/* Configure mii port 10 */
miiphy_write(miidev, 0x1a, 0x01, 0x203E);
/* Correct Clk Signal */
/* comment se: This is somehow strange, we have
* to write to switch port timing control register 0x16
* but it effects Port 0x0a (so register 0x1a would be normal). In the documentation they write
* "RGMII Timing Control (Device Offset 0x16 only)" with that
* they mean the only valid register to modify is 0x16. Below they write:
* "These RGMII timing bits affect Port 10s timing only and only if Port 10 is
* configured in RGMII mode" so it seems this is the way to go...
*/
miiphy_read(miidev, 0x16, 0x1a, &value);
value |= 0x0600;
miiphy_write(miidev, 0x16, 0x1a, value);
/* Configure external phy 8 and 9 led */
for (i = 0x08; i <= 0x09; i++) {
miiphy_read(miidev, i, 0x16, &page);
miiphy_write(miidev, i, 0x16, 0x0003);
miiphy_read(miidev, i, 0x10, &value);
value &= ~0x0F0F;
value |= 0x0E01;
miiphy_write(miidev, i, 0x10, value);
miiphy_write(miidev, i, 0x16, page);
}
/*Enable PPU*/
miiphy_write(miidev, 0x1b, 0x0004, 0x4080);
/* select eth1 */
env_set("ethact", "ethernet@30000");
break;
case MVS_88E6060 :
/* Disable bridging between external ethernet ports */
miiphy_write(miidev, 0x08, 0x06, 0x0020);
miiphy_write(miidev, 0x09, 0x06, 0x0020);
miiphy_write(miidev, 0x0a, 0x06, 0x0020);
miiphy_write(miidev, 0x0b, 0x06, 0x0020);
miiphy_write(miidev, 0x0c, 0x06, 0x0020);
miiphy_write(miidev, 0x0d, 0x06, 0x001f);
/* Enable all ethernet ports */
miiphy_write(miidev, 0x08, 0x04, 0x0003);
miiphy_write(miidev, 0x09, 0x04, 0x0003);
miiphy_write(miidev, 0x0a, 0x04, 0x0003);
miiphy_write(miidev, 0x0b, 0x04, 0x0003);
miiphy_write(miidev, 0x0c, 0x04, 0x0003);
miiphy_write(miidev, 0x0d, 0x04, 0x0003);
/* select eth0 */
env_set("ethact", "ethernet@70000");
break;
case MVS_UNKNOWN :
default :
printf("No or unknown ethernet switch detected!");
goto abort;
break;
}
return 0;
abort:
return 1;
}
int configure_mvswitch(void)
{
int res;
res = check_mvswitch();
if (res) goto abort;
res = init_mvswitch();
if (res) goto abort;
return 0;
abort:
return 1;
}
enum MvSwitchType get_mvswitch_type(void)
{
return mvSwType;
}

14
board/nm/hw14/mvswitch.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef MVSWITCH_H
#define MVSWITCH_H
enum MvSwitchType {
MVS_UNKNOWN,
MVS_88E6060,
MVS_88E6097
};
int configure_mvswitch(void);
enum MvSwitchType get_mvswitch_type(void);
#endif

View File

@ -0,0 +1,234 @@
#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"
#include "nbhw_gpio.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;
};
#define PCIE_SLOT_COUNT 8
static struct pcie_slot_gpios pcie_slots[PCIE_SLOT_COUNT];
static int pcie_slot_count = 0;
int pcie_lane_by_slot(int slot);
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_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);
pcie_slot_count++;
return 0;
}
static void configure_pcie_muxes(void)
{
/* Disable PCI clock and serdes4 routing unless
explicitly requested later. */
set_gpio(GPIO_SERDES4_MUX_EN, 0);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 0);
/* Check for PCIe on slot 1 */
if (pcie_lane_by_slot(1) >= 0) {
// PEX2 is on slot 1
// mux serdes4 to slot 1 pci pins
set_gpio(GPIO_SERDES4_MUX_SEL, 1);
set_gpio(GPIO_SERDES4_MUX_EN, 1);
// route PEX2 clock to slot 1
set_gpio(GPIO_PEX2_CLK_1_4_MUX_SEL, 1);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 1);
} else {
// mux serdes4 to slot 1 usb 3.0 pins
set_gpio(GPIO_SERDES4_MUX_SEL, 0);
set_gpio(GPIO_SERDES4_MUX_EN, 1);
}
/* Check for PCIe on slot 4 */
if (pcie_lane_by_slot(4) >= 0) {
// PEX2 is on slot 4
// route PEX2 clock to slot 4
set_gpio(GPIO_PEX2_CLK_1_4_MUX_SEL, 0);
set_gpio(GPIO_PEX2_CLK_1_4_MUX_EN, 1);
}
}
static int configure_pcie_slots(void)
{
int i;
configure_pcie_muxes();
configure_sim_slots(6);
udelay(1200000); /* 1.2 s */
/* 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);
}
/* 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);
}
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("pcieslot", name, 8)) {
add_pcie_slot(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,hw14-fpga-config" },
{ }
};
U_BOOT_DRIVER(gpio_nbhw_fpga_config) = {
.name = "hw14_fpga_config",
.id = UCLASS_ROOT,
.of_match = nbhw_fpga_config_ids,
.bind = nbhw_fpga_config_bind,
};

97
board/nm/hw14/nbhw_gpio.c Normal file
View File

@ -0,0 +1,97 @@
#include <common.h>
#include <asm/gpio.h>
#include <stdlib.h>
#include "nbhw_gpio.h"
struct gpio_node {
struct gpio_node* next;
struct gpio_desc desc;
const char* name;
int is_output;
};
static struct gpio_node* gl = NULL;
static struct gpio_desc* lookup_gpio(const char* gpio_name, int is_output) {
struct gpio_node* cur = gl;
while (cur) {
if ((strcmp(gpio_name, cur->name)==0) &&
(is_output == cur->is_output)) {
return &(cur->desc);
}
cur = cur->next;
}
return NULL;
}
static struct gpio_desc* acquire_gpio(const char* gpio_name, int is_output) {
struct gpio_node* gn = 0;
int node;
/* Check, if we already requested this gpio */
struct gpio_desc* desc = lookup_gpio(gpio_name, is_output);
if (desc) return desc;
/* If we do not have it try to request it now. */
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "nm,gpios");
if (node < 0) {
goto abort;
}
gn = (struct gpio_node*)malloc(sizeof(struct gpio_node));
if (!gn) goto abort;
if (gpio_request_by_name_nodev(offset_to_ofnode(node), gpio_name, 0, &(gn->desc), is_output ? GPIOD_IS_OUT : GPIOD_IS_IN) < 0) {
goto abort;
}
gn->name = gpio_name;
gn->is_output = is_output;
gn->next = gl;
gl = gn;
desc = &(gn->desc);
return desc;
abort:
if (gn) free(gn);
printk("Could not acquire gpio %s as %s!\n", gpio_name, is_output ? "output" : "input");
return 0;
}
int get_gpio(const char* gpio_name)
{
struct gpio_desc* d;
int res;
d = acquire_gpio(gpio_name, 0);
if (!d) goto abort;
res = dm_gpio_get_value(d);
return res;
abort:
printf("Could not set gpio %s!\n", gpio_name);
return -1;
}
int set_gpio(const char* gpio_name, int value)
{
struct gpio_desc* d;
d = acquire_gpio(gpio_name, 1);
if (!d) goto abort;
dm_gpio_set_value(d, value);
return 0;
abort:
printf("Could not set gpio %s!\n", gpio_name);
return -1;
}

42
board/nm/hw14/nbhw_gpio.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef HW14_GPIO_H
#define HW14_GPIO_H
/* GPIO definitions */
#define GPIO_WD_ENABLE "wd_enable"
#define GPIO_RST_I2C_EXP "rst_i2c_exp"
#define GPIO_LED_DBG "led_dbg"
#define GPIO_EN_SATA_PWR "en_sata_pwr"
#define GPIO_USB1_VBUS_IN "usb1_vbus_in"
#define GPIO_USB1_DRIVE_VBUS "usb1_drive_vbus"
#define GPIO_USB1_PWR_FAULT "usb1_pwr_fault"
#define GPIO_EXT_RST_EN "ext_rst_en"
#define GPIO_RST_FPGA "rst_fpga"
#define GPIO_RST_USB_HUB "rst_usb_hub"
#define GPIO_RST_PSE_ETH "rst_pse_eth"
#define GPIO_RESET_BUTTON "reset_button"
#define GPIO_EXT_OE "ext_oe"
#define GPIO_SERDES4_MUX_EN "serdes4_mux_en"
#define GPIO_SERDES4_MUX_SEL "serdes4_mux_sel"
#define GPIO_PEX2_CLK_1_4_MUX_EN "pex2_clk_1_4_mux_en"
#define GPIO_PEX2_CLK_1_4_MUX_SEL "pex2_clk_1_4_mux_sel"
int get_gpio(const char* gpio_name);
int set_gpio(const char* gpio_name, int value);
/* LED definitions */
#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

77
board/nm/hw14/nbhw_sim.c Normal file
View File

@ -0,0 +1,77 @@
#include <common.h>
#include <malloc.h>
#include "../common/nbhw_fpga_prog.h"
struct simcfg_t{
uint16_t simctrl;
uint16_t simctrlmask;
uint16_t simbusctrl;
uint16_t simbusctrlmask;
};
static struct simcfg_t get_simcfg(int sim, int simbus, int slotsel)
{
struct simcfg_t simcfg;
memset(&simcfg, 0, sizeof(simcfg));
if (sim > 4) {
printf("SIM carrier not supported for NB3800\n");
return simcfg;
}
if (simbus == -1) {
/* Clear the SIM enable flag only */
simcfg.simctrlmask = 0x1 << (sim * 2);
return simcfg;
}
if (sim < 4 && sim >= 0) {
simcfg.simctrl = (1 << (sim * 2)) | ((simbus & 1) << (1 + sim * 2)) | ((simbus & 2) << (7 + sim));
simcfg.simctrlmask = (0x1 << (sim + 8)) | (0x3 << (sim * 2));
}
switch (slotsel) {
case 0: simcfg.simbusctrl = 0x01, simcfg.simbusctrlmask = 0x3; break;
case 1: simcfg.simbusctrl = 0x03, simcfg.simbusctrlmask = 0x3; break;
case 2: simcfg.simbusctrl = 0x04, simcfg.simbusctrlmask = 0xC; break;
case 3: simcfg.simbusctrl = 0x0C, simcfg.simbusctrlmask = 0xC; break;
default: simcfg.simbusctrlmask = 0;
}
return simcfg;
}
void connect_sim_to_slot(int sim, int slot) {
struct simcfg_t simcfg;
uint16_t simctrl;
uint16_t simbusctrl;
if (sim > 4 || sim < 0) {
printf("Invalid sim %d selected, can't connect slot %d\n", sim, slot);
return;
}
/* Parser to broken FPGA register structure */
switch(slot) {
case 0: simcfg = get_simcfg(sim, 0, 0); break;
case 1: simcfg = get_simcfg(sim, 1, -1); break;
case 2: simcfg = get_simcfg(sim, 0, 1); break;
case 3: simcfg = get_simcfg(sim, 2, -1); break;
case 4: simcfg = get_simcfg(sim, 3, 2); break;
case 5: simcfg = get_simcfg(sim, 3, 3); break;
default: simcfg = get_simcfg(sim, -1, -1); break;
}
simctrl = FPGA_REG(0x0040);
simctrl &= ~simcfg.simctrlmask;
simctrl |= simcfg.simctrl;
FPGA_REG(0x0040) = simctrl;
simbusctrl = FPGA_REG(0x0042);
simbusctrl &= ~simcfg.simbusctrlmask;
simbusctrl |= simcfg.simbusctrl;
FPGA_REG(0x0042) = simbusctrl;
}

View File

@ -16,9 +16,14 @@ commonobj = ../common/bdparser.o \
ccflags-y := -I../common
ifndef CONFIG_SPL_BUILD
obj-y := board.o nbhw_gpio.o nbhw_fpga_config.o $(commonobj)
obj-y := board.o nbhw_gpio.o nbhw_fpga_config.o \
$(commonobj)
else
obj-y := board.o nbhw_gpio.o ../common/nbhw_bd.o ../common/nbhw_partitions.o
obj-y := board.o \
../common/nbhw_bd.o \
../common/nbhw_partitions.o \
../common/bdparser.o \
../common/nbhw_bd.o
endif

View File

@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define DEBUG
#undef DEBUG
#include <common.h>
#include <i2c.h>
#include <miiphy.h>
@ -15,6 +15,10 @@
#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>
@ -24,38 +28,60 @@
#include "../common/nbhw_env.h"
#include "../common/nbhw_bd.h"
#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
#include <../serdes/a38x/high_speed_env_spec.h>
//#define EARLY_CONSOLE_OUTPUT
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(7) | BIT(19) | BIT(21))) /* 1=Input, default input */
/* 21: RST_ETH_PHYS~, 26: FPGA_CFG_RESET, 27: WD_ENABLE~ */
#define GPP_OUT_ENA_LOW (~(BIT(21) | BIT(26) /*| BIT(27) */)) /* 1=Input, default input */
/* 41/9: RST_USB_HUB~, 44/12: RST_FPGA~, 47/15: WD_TRIG */
#define GPP_OUT_ENA_MID (~(BIT(9) | BIT(12) | BIT(15)))
#define GPP_OUT_ENA_MID (~(BIT(9) | BIT(12)))
#define GPP_OUT_VAL_LOW (BIT(21)) /* 1=pin on */
#define GPP_OUT_VAL_MID (0x0)
#define GPP_POL_LOW (0x0) /* 0=no inversion */
#define GPP_POL_MID (0x0)
#define GPP_OUT_VAL_LOW (~(BIT(21) | BIT(26) | BIT(27)))
#define GPP_OUT_VAL_MID (~(BIT(9) | BIT(12) | BIT(15)))
#define GPP_POL_LOW (BIT(21)) /* 1=pin on */
#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 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
/* Chip select base addresses */
#define NBHW_BASE_ADDRESS_FPGA DEV_CS0_BASE
/* Compute FPGA register addresses */
#define FPGA_REG(x) *((volatile unsigned short*)( NBHW_BASE_ADDRESS_FPGA + ((unsigned int)x)))
#define PCIE_4_PCM_GPIO_EN (0x0430)
#define PCIE_4_PCM_GPIO_DIR (0x0432)
#define PCIE_4_PCM_GPIO_DAT (0x0434)
/* TODO: These platform specific SERDES default definitions are
currently defined twice here and in by hws_board_topology_load().
Actually these platform specific defaults should only be set
in hws_board_topology_load().
The defaults should there be set also for the case where we have
a valid BD but that BD does not contain SERDES configuration
info to support old HW14 boards.
*/
static struct serdes_map board_serdes_map[] = {
{ PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 },
{ SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
{ SATA1, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
{ SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
{ PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0 },
{ USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0 }
{ USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0 }
};
enum serdes_type get_serdes_type(int index)
@ -68,8 +94,223 @@ enum serdes_type get_serdes_type(int index)
}
}
typedef struct __attribute__ ((packed)) EthPhyRegs {
int page;
int reg;
int reserved;
int data;
} EthPhyRegs;
const EthPhyRegs NB2800_ETH_PHY_REGS[] = {
{ 0x0003, 0x0010, 0, 0x1032 }, /* LED function control register */
{ 0x0003, 0x0011, 0, 0x4405 }, /* LED polarity control register */
{ 0x0003, 0x0012, 0, 0x4a08 }, /* LED timer control register */
{ -1, -1, -1, -1 }
};
const EthPhyRegs NB2810_ETH_PHY_REGS[] = {
{ 0x0003, 0x0010, 0, 0x1418 }, /* LED function control register */
{ 0x0003, 0x0011, 0, 0x442a }, /* LED polarity control register */
{ 0x0003, 0x0012, 0, 0x4a08 }, /* LED timer control register */
{ -1, -1, -1, -1 }
};
const EthPhyRegs* sSelectedPhyRegs = 0;
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;
}
#define RESET_REASON_SHM_LOCATION (0x3ffff000)
extern int console_init_f(void);
#if !defined(CONFIG_SPL_BUILD)
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();
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;
}
#endif
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
{
int i;
if (read_eeprom() < 0){
puts("Could not read board descriptor using default serdes config.\n");
board_serdes_map[0].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[0].serdes_mode = PEX_ROOT_COMPLEX_X1;
board_serdes_map[0].serdes_type = PEX0;
board_serdes_map[1].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[1].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[1].serdes_type = SGMII1;
board_serdes_map[2].serdes_speed = SERDES_SPEED_3_GBPS;
board_serdes_map[2].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[2].serdes_type = SATA1;
board_serdes_map[3].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[3].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[3].serdes_type = SGMII2;
board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[4].serdes_mode = PEX_ROOT_COMPLEX_X1;
board_serdes_map[4].serdes_type = PEX2;
board_serdes_map[5].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[5].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[5].serdes_type = USB3_HOST1;
} else {
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 */
type = bd_get_serdes_type(i);
}
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;
}
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;
@ -80,30 +321,65 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
* be used by the DDR3 init code in the SPL U-Boot version to configure
* the DDR3 controller.
*/
static struct hws_topology_map board_topology_map = {
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 */
BUS_WIDTH_16, /* memory_width */
MEM_4G, /* mem_size */
DDR_FREQ_667, /* frequency */
7, 9, /* cas_l cas_wl */
HWS_TEMP_HIGH} }, /* temperature */
5, /* Num Of Bus Per Interface*/
BUS_MASK_32BIT /* Busses mask */
{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 hws_topology_map *ddr3_get_topology_map(void)
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 */
@ -141,50 +417,22 @@ void spl_board_init(void)
int err;
struct mmc *mmcp;
err = mmc_initialize(NULL);
err = mmc_initialize(0);
if (err)
return;
puts("SPL: select partition\n");
debug("SPL: select partition\n");
mmcp = find_mmc_device(0);
mmc_init(mmcp);
printf("Partition found: %p\n", mmcp);
/* select boot0 as bootpart */
/* select boot0 as first boot partition */
mmcp->part_config &= ~(PART_ACCESS_MASK << 3);
mmcp->part_config |= (1 << 3);
puts("Partition switched to boot0\n");
debug("Boot partition set to boot0\n");
}
static BD_Context bdctx[3]; /* The descriptor context */
#if !defined(CONFIG_SPL_BUILD)
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;
}
static inline int __maybe_unused read_eeprom(void)
{
return _bd_init();
}
static void set_gpios(void)
{
init_gpios();
}
static void pass_hw_rev(void)
{
@ -205,39 +453,201 @@ static void pass_hw_rev(void)
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);
snprintf(new_env, sizeof(new_env), "setenv bootargs $bootargs %s", hw_versions);
}
env_set("add_version_bootargs", new_env);
}
#endif
int board_init(void)
{
/* adress of boot parameters */
#if defined(CONFIG_WATCHDOG)
watchdog_init();
#endif
/* address of boot parameters */
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
/* Setup the MBUS mapping for Devicebus CS0 */
/* Setup the MBUS mapping for Devicebus CS0 (FPGA) */
mbus_dt_setup_win(&mbus_state, DEV_CS0_BASE, 16 << 20,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS0);
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS0 /* 0x3e */);
if (read_eeprom() < 0)
puts("Could not get board ID.\n");
set_console();
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, INTER_REGS_BASE + 0x1108C);
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)
{
return (get_gpio(GPIO_RESET_BUTTON) == 0);
}
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;
#ifdef EARLY_CONSOLE_OUTPUT
init_console();
console_init_f();
#endif
/* Disable watchdog */
debug("Disable watchdog\n");
// set_gpio(GPIO_WD_ENABLE, 0);
/* Enable USB hub */
debug("Enable USB Hub\n");
set_gpio(GPIO_RST_USB_HUB, 0);
udelay(10000);
/* Determine SERDES configuration */
hws_board_topology_load(&sm, &sm_count);
return 0;
}
#if !defined(CONFIG_SPL_BUILD)
static void set_phy_page(const char *miidev, int phy_addr, int page)
{
miiphy_write(miidev, phy_addr, 22, page);
@ -246,20 +656,38 @@ static void set_phy_page(const char *miidev, int phy_addr, int page)
static void set_phy_fast_blink_mode(int phy_addr)
{
const char *miidev = miiphy_get_current_dev();
int numRegs = 0;
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);
while (sSelectedPhyRegs[numRegs].reserved != -1) {
set_phy_page(miidev, phy_addr, sSelectedPhyRegs[numRegs].page);
miiphy_write(miidev, phy_addr, sSelectedPhyRegs[numRegs].reg, sSelectedPhyRegs[numRegs].data);
numRegs++;
}
set_phy_page(miidev, phy_addr, 0);
}
static void set_devicetree_name(void)
{
char devicetreename[64];
if (bd_get_devicetree(devicetreename, sizeof(devicetreename)) != 0) {
printf("Devicetree name not found in BD\n");
strncpy(devicetreename, "openwrt-nbhw17.dtb", sizeof(devicetreename));
printf ("Selected default devicetree file\n");
}
env_set("fdt_image", devicetreename);
}
#endif
int board_late_init(void)
{
gpio_request(21, "RST_ETH_PHY_N");
gpio_direction_output(21, 0);
#if !defined(CONFIG_SPL_BUILD)
set_devicetree_name();
set_gpio(GPIO_RST_ETH_PHY, 1);
find_and_set_active_partition();
pass_hw_rev();
@ -267,29 +695,86 @@ int board_late_init(void)
/* Todo: It seems that something with the network is wrong */
run_command("run load_fpga", CMD_FLAG_ENV);
#ifndef EARLY_CONSOLE_OUTPUT
init_console();
console_init_f();
#endif
check_reset_button();
set_mac_addresses(2);
#endif
/* Take phy out of reset after FPGA was loaded */
gpio_set_value(21, 1);
set_gpio(GPIO_RST_ETH_PHY, 0);
return 0;
}
#if !defined(CONFIG_SPL_BUILD)
int board_network_enable(struct mii_dev *bus)
{
char prodName[20];
if (bd_get_prodname(prodName, sizeof(prodName)) != 0) {
prodName[0] = 0;
}
if (strcmp(prodName, "2810") == 0) {
/* NB2810 */
sSelectedPhyRegs = NB2810_ETH_PHY_REGS;
} else {
/* NB2800 or unknown */
sSelectedPhyRegs = NB2800_ETH_PHY_REGS;
}
set_phy_fast_blink_mode(0);
set_phy_fast_blink_mode(1);
return 0;
}
#endif
int checkboard(void)
{
puts("Board: NetModule NBHW17\n");
debug("Board: NetModule NBHW17\n");
return 0;
}
int board_fit_config_name_match(const char *name)
{
#ifdef CONFIG_SPL_BUILD
/* SPL has enabled serial1 per default and will output everything
* independend of /boot/consoledev */
#define DEFAULT_DTB_NAME "armada-385-nbhw17-v1-spl"
#else
/* U-Boot will read /boot/consoledev and based on that it
* enables its own serial console */
#define DEFAULT_DTB_NAME "armada-385-nbhw17-v1"
#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;
@ -322,3 +807,91 @@ int pcie_lane_by_slot(int slot)
return -1;
}
}
/*******************************************************************************
Enable additional nodes in DTS depending on board descriptor
*******************************************************************************/
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");
}
}
static void ft_netbox_dio_ptt_4(void *blob)
{
printf("FT: enable netbox_dio_ptt_4\n");
ft_enable_node(blob, "/netbox_dio_ptt_4");
// also reconfigure PCM lines in FPGA as GPIOs
FPGA_REG(PCIE_4_PCM_GPIO_EN) = 0x0001; /* Enable GPIO functionality for slot 4 */
FPGA_REG(PCIE_4_PCM_GPIO_DIR) = 0x0004; /* Set GPIO directions */
FPGA_REG(PCIE_4_PCM_GPIO_DAT) = 0; /* Set output to 0 */
}
void ft_set_eth_led_config(void *blob)
{
int node_ofs;
int numRegs = 0;
int i;
int phy;
EthPhyRegs* pBigEndianPhyRegs = 0;
if (!sSelectedPhyRegs) goto abort;
while (sSelectedPhyRegs[numRegs].reserved != -1) numRegs++;
/* DTS needs big endian so swap everything */
pBigEndianPhyRegs = malloc(numRegs * sizeof(NB2800_ETH_PHY_REGS));
if (!pBigEndianPhyRegs) goto abort;
memcpy(pBigEndianPhyRegs, sSelectedPhyRegs, numRegs * sizeof(EthPhyRegs));
for (i=0; i<numRegs; i++) {
pBigEndianPhyRegs[i].page = cpu_to_be32(pBigEndianPhyRegs[i].page);
pBigEndianPhyRegs[i].reg = cpu_to_be32(pBigEndianPhyRegs[i].reg);
pBigEndianPhyRegs[i].reserved = cpu_to_be32(pBigEndianPhyRegs[i].reserved);
pBigEndianPhyRegs[i].data = cpu_to_be32(pBigEndianPhyRegs[i].data);
}
for (phy=0; phy<2; phy++) {
char phyPath[60];
snprintf(phyPath, sizeof(phyPath), "/soc/internal-regs/mdio/ethernet-phy@%d", phy);
phyPath[sizeof(phyPath)-1] = 0;
node_ofs = fdt_path_offset(blob, phyPath);
if (node_ofs >= 0) {
fdt_setprop(blob, node_ofs, "marvell,reg-init",
pBigEndianPhyRegs, numRegs * sizeof(EthPhyRegs));
}
}
abort:
if (pBigEndianPhyRegs) free(pBigEndianPhyRegs);
return;
}
int ft_board_setup(void *blob, bd_t *bd)
{
int module;
char* slotDescr = "slot=3";
char pdValue[200];
for (module=0; module<4; module++) {
pdValue[0] = 0; /*init with an empty string*/
if (bd_get_pd_module(module, pdValue, sizeof(pdValue))==0) {
/* We have a PTT module with gpios in slot 4, so enable it */
if ((strstr(pdValue, slotDescr)) && (strstr(pdValue, "dio-x1")))
ft_netbox_dio_ptt_4(blob);
}
}
ft_set_eth_led_config(blob);
return 0;
}

View File

@ -31,53 +31,53 @@ typedef enum {
TYPE_PCIE,
} slot_type_t;
static slot_type_t get_pcie_slot_type(const int slot)
{
int module;
char pdValue[200];
char slotDescr[20];
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) {
if ((strstr(pdValue, slotDescr)) && (strstr(pdValue, "wlan-"))) {
/* Wifi module needs PCIe */
return TYPE_PCIE;
}
}
}
return TYPE_USB;
}
static int serdes_en_hack(struct gpio_desc *gpio)
{
slot_type_t slot_type = get_pcie_slot_type(0);
/* Lucky for us pcie slot1 has some muxes, to workaround buggy Sierra Wireless Modules */
if (slot_type == TYPE_USB) {
/* Buggy Sierra Wireless Modules don't like to have USB3 enabled
* because the TX of the USB3 Lane is attached to it's system
* reset which is the default (see dts) */
printf("Slot1: wwan\n");
}
else if (slot_type == TYPE_PCIE) {
dm_gpio_set_value(gpio, 1);
printf("Slot1: wlan\n");
}
else {
/* If once we would use other buggy Sierra Wireless modules, where they have
* decided to use USB3 too, then we have to enable the SERDES, the reset signal
* was moved away from this pins again (bravo!!!) */
printf("Slot1: wwan (usb3)\n");
}
return 0;
}
//static slot_type_t get_pcie_slot_type(const int slot)
//{
// int module;
// char pdValue[200];
// char slotDescr[20];
//
// 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) {
//
// if ((strstr(pdValue, slotDescr)) && (strstr(pdValue, "wlan-"))) {
// /* Wifi module needs PCIe */
// return TYPE_PCIE;
// }
// }
// }
//
// return TYPE_USB;
//}
//
//static int serdes_en_hack(struct gpio_desc *gpio)
//{
// slot_type_t slot_type = get_pcie_slot_type(0);
//
// /* Lucky for us pcie slot1 has some muxes, to workaround buggy Sierra Wireless Modules */
// if (slot_type == TYPE_USB) {
// /* Buggy Sierra Wireless Modules don't like to have USB3 enabled
// * because the TX of the USB3 Lane is attached to it's system
// * reset which is the default (see dts) */
// printf("Slot1: wwan\n");
// }
// else if (slot_type == TYPE_PCIE) {
// dm_gpio_set_value(gpio, 1);
// printf("Slot1: wlan\n");
// }
// else {
// /* If once we would use other buggy Sierra Wireless modules, where they have
// * decided to use USB3 too, then we have to enable the SERDES, the reset signal
// * was moved away from this pins again (bravo!!!) */
// printf("Slot1: wwan (usb3)\n");
// }
//
// return 0;
//
//}
struct pcie_slot_gpios {
struct gpio_desc reset;
@ -102,7 +102,7 @@ static int request_and_set_gpio_by_name(ofnode fdt,
if (gpio_request_by_name_nodev(fdt, name, 0, desc,
GPIOD_IS_OUT))
{
printf("Could not request gpio %s\n", name);
debug("Could not request gpio %s\n", name);
return -1;
}
@ -122,17 +122,19 @@ static int request_and_set_gpio_by_name(ofnode fdt,
static int add_pcie_slot(ofnode fdt)
{
debug("%s\n", __func__);
request_and_set_gpio_by_name(fdt, "reset",
&pcie_slots[pcie_slot_count].reset);
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);
pcie_slot_count++;
return 0;
}
@ -140,35 +142,36 @@ static int add_pcie_slot(ofnode fdt)
static int configure_pcie_slots(void)
{
int i;
udelay(1200000); /* 1.2 s */
for (i = 0; i < pcie_slot_count;i ++) {
dm_gpio_set_value(&pcie_slots[i].reset, 1);
}
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(1000); /* 1 ms */
}
/* Apply power to all PCIe slots */
for (i = 0; i < pcie_slot_count;i ++) {
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].power, 1);
udelay(200000); /* 200 ms */
}
for (i = 0; i < pcie_slot_count;i ++) {
/* Assert reset after power is enabled */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 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(1000); /* 1 ms */
udelay(2000); /* 2 ms needed by Reyax module as regulator is enabled by WDIS~*/
}
udelay(12000); /* 12 ms */
for (i = 0; i < pcie_slot_count;i ++) {
/* Deassert reset */
for (i = 0; i < pcie_slot_count; i++) {
dm_gpio_set_value(&pcie_slots[i].reset, 0);
}
pci_init_board();
return 0;
}
@ -189,112 +192,38 @@ static int configure_leds(void)
return 0;
}
struct hack_list_entry {
const char* name;
int (*fn)(struct gpio_desc *gpio);
};
struct hack_list_entry hack_list[] = {
{"serdes-en", serdes_en_hack}
};
static int exec_hack_list_fn(const char *name, struct gpio_desc *gpio)
// TODO: Check, if needed
//struct hack_list_entry {
// const char* name;
// int (*fn)(struct gpio_desc *gpio);
//};
//
//struct hack_list_entry hack_list[] = {
// {"serdes-en", serdes_en_hack}
//};
//
//static int exec_hack_list_fn(const char *name, struct gpio_desc *gpio)
//{
// int i;
// for (i = 0; i < ARRAY_SIZE(hack_list); i++) {
// if (strcmp(hack_list[i]. name, name) == 0) {
// if (hack_list[i].fn(gpio)) {
// printf("Hack for %s failed\n", name);
// return -1;
// }
// return 0;
// }
// }
//
// /* Not part of hacklist */
// return 0;
//}
//
void set_led(int index, int value)
{
int i;
for (i = 0; i < ARRAY_SIZE(hack_list); i++) {
if (strcmp(hack_list[i]. name, name) == 0) {
if (hack_list[i].fn(gpio)) {
printf("Hack for %s failed\n", name);
return -1;
}
return 0;
}
}
if ((index<0) || (index>=priv.led_count)) return;
/* Not part of hacklist */
return 0;
}
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);
if (exec_hack_list_fn(name, &gpios[i])) {
printf("Execution of hack for %s failed\n", name);
continue;
}
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;
dm_gpio_set_value(&leds[index], value);
}
int nbhw_fpga_configure(void)
@ -309,14 +238,10 @@ int nbhw_fpga_configure(void)
name = ofnode_get_name(subnode);
debug("Try to configure %s\n", name);
if (!strncmp("misc", name, 4)) {
configure_misc(subnode);
}
if (!strncmp("pcieslot", name, 4)) {
add_pcie_slot(subnode);
}
}
if (configure_leds())

View File

@ -1,144 +0,0 @@
/* #define DEBUG */
#include <nbhw.h>
#include "board/mv_ebu/common/common/mvCommon.h"
#include "board/mv_ebu/common/mv_hal/gpp/mvGpp.h"
#include "board/mv_ebu/common/uboot_oss/mvOs.h"
#include "../armada_38x_family/ctrlEnv/mvCtrlEnvLib.h"
#include "fs.h"
#include "../nbhw_fpga_prog.h"
#include "nbhw18_gpio.h"
#define SS_MPP BIT5
#define SDO_MPP BIT6 /* SDO means slave data out */
#define SCK_MPP BIT7
#define SDI_MPP BIT8 /* SDI means slave data in */
#define FPGA_RESET BIT19
#define FPGA_RESET_GROUP 0
#define SPI_GROUP 1
#define MPP_MASK_4 0xFFF00000
#define MPP_MASK_5 0x0000000F
extern int fpga_program(fpga_prog_operation *operation);
static MV_U32 mpp_group_4_init_value;
static MV_U32 mpp_group_5_init_value;
static void set_cs(int active)
{
if (active) {
mvGppValueSet(SPI_GROUP, SS_MPP, SS_MPP);
}
else {
mvGppValueSet(SPI_GROUP, SS_MPP, 0);
}
}
static void write_spi_data(MV_U8 data)
{
int i;
MV_U32 data_write = 0;
for (i=0; i<8; i++)
{
data_write = (data & 0x80) ? SDI_MPP : 0;
/* Clear clk bit and put data on the line */
mvGppValueSet(SPI_GROUP, SDI_MPP | SCK_MPP, data_write);
/* Read data on rising edge */
mvGppValueSet(SPI_GROUP, SCK_MPP, SCK_MPP);
data = data << 1;
}
}
static void put_in_prog_mode(void)
{
/* Set CS firt to 1 */
mvGppValueSet(SPI_GROUP, SS_MPP , SS_MPP);
udelay(10);
/* Set SS to 0 and SCK to 1 */
mvGppValueSet(SPI_GROUP, SS_MPP | SCK_MPP, SCK_MPP);
/* Put FPGA in reset */
mvGppValueSet(FPGA_RESET_GROUP, FPGA_RESET, 1);
/* Sleep at least 200ns according to lattice manual */
udelay(1);
/* Take FPGA out of reset */
mvGppValueSet(FPGA_RESET_GROUP, FPGA_RESET, 0);
/* Wait for at least 800 us according to lattice manual */
udelay(800);
}
static void pre_programming(void)
{
debug("NBHW18 pre programming\n");
MV_U32 reg_data;
mpp_group_4_init_value = readl(mvCtrlMppRegGet(4));
mpp_group_5_init_value = readl(mvCtrlMppRegGet(5));
/* Set MPP37, 38 and 39 to GPIO */
reg_data = (mpp_group_4_init_value & ~(MPP_MASK_4));
writel(reg_data, mvCtrlMppRegGet(4));
/* Set MPP40 to GPIO */
reg_data = (mpp_group_5_init_value & ~(MPP_MASK_5));
writel(reg_data, mvCtrlMppRegGet(5));
/* Configure outputs (default input) 0=> output */
mvGppTypeSet(SPI_GROUP, (SS_MPP | SCK_MPP | SDI_MPP), 0);
debug("NBHW18 put in progmode\n");
put_in_prog_mode();
}
static void post_programming(void)
{
int i;
if (in_fpga_cdone()) {
printf("Error: Fpga does not signalize done\n");
}
debug ("NBHW18 post programming\n");
/* At least 49 SPI_SCK Cycles rising edge to rising edge */
for (i = 0; i < 100; i++) {
write_spi_data(0);
}
set_cs(1);
/* Set MPP37, 38, 39 and 40 to inital value again */
writel(mpp_group_4_init_value, mvCtrlMppRegGet(4));
writel(mpp_group_5_init_value, mvCtrlMppRegGet(5));
/* Do a logic reset */
out_fpga_logic_reset(0);
udelay(100);
out_fpga_logic_reset(1);
udelay(100);
}
static int check_bitstream_compatibility(fpga_type type, u32 id)
{
if (type != FPGA_TYPE_LATTICE) {
return -1;
}
return 0;
}
static fpga_prog_operation operation = {
pre_programming,
post_programming,
write_spi_data,
check_bitstream_compatibility,
};
int nbhw_fpga_program(void)
{
return fpga_program(&operation);
}

View File

@ -1,773 +0,0 @@
/*******************************************************************************
*
* Register Description
*
* Automatically generated, do not edit manually
* Source: ./dd_fw_NBHW_18_Mainboard_FPGA.docx
* Date: 2017-03-22 13:44:10.255175
*
******************************************************************************/
#ifndef NBHW18_FPGA_REGS_H
#define NBHW18_FPGA_REGS_H
/*** Identification for NBHW18 ***/
#define IDENTIFICATION_REGISTER (0x0000)
/* Identification register */
#define IDENTIFICATION_REGISTER_SIGNATURE_SHIFT (0UL)
#define IDENTIFICATION_REGISTER_SIGNATURE_MASK (0xffffUL)
#define IDENTIFICATION_REGISTER_SIGNATURE_ACCESS (READ_ONLY)
/*** FPGA firmware version register ***/
#define VERSION (0x0002)
/* Minor firmware version */
#define VERSION_MINOR_VERSION_SHIFT (0UL)
#define VERSION_MINOR_VERSION_MASK (0xffUL)
#define VERSION_MINOR_VERSION_ACCESS (READ_ONLY)
/* Major firmware version */
#define VERSION_MAJOR_VERSION_SHIFT (8UL)
#define VERSION_MAJOR_VERSION_MASK (0xff00UL)
#define VERSION_MAJOR_VERSION_ACCESS (READ_ONLY)
/*** User scratch register ***/
#define SCRATCH (0x0004)
/* Scratch register */
#define SCRATCH_SCRATCH_SHIFT (0UL)
#define SCRATCH_SCRATCH_MASK (0xffffUL)
#define SCRATCH_SCRATCH_ACCESS (READ_WRITE)
/*** Main Board Inputs ***/
#define STATUS1 (0x0006)
/* 0: No SIM Card inserted in Slot 1
1: SIM Card inserted in Slot 1 */
#define STATUS1_SIM_CD1_SHIFT (10UL)
#define STATUS1_SIM_CD1_MASK (0x400UL)
#define STATUS1_SIM_CD1_ACCESS (READ_ONLY)
/* 0: No SIM Card inserted in Slot 2
1: SIM Card inserted in Slot 2 */
#define STATUS1_SIM_CD2_SHIFT (11UL)
#define STATUS1_SIM_CD2_MASK (0x800UL)
#define STATUS1_SIM_CD2_ACCESS (READ_ONLY)
/* RTC Interrupt */
#define STATUS1_RTC_N_SHIFT (12UL)
#define STATUS1_RTC_N_MASK (0x1000UL)
#define STATUS1_RTC_N_ACCESS (READ_ONLY)
/* LM75 interrupt */
#define STATUS1_LM75_N_SHIFT (13UL)
#define STATUS1_LM75_N_MASK (0x2000UL)
#define STATUS1_LM75_N_ACCESS (READ_ONLY)
/* Ethernet PHY 1 Interrupt */
#define STATUS1_IRQ_PHY1_N_SHIFT (14UL)
#define STATUS1_IRQ_PHY1_N_MASK (0x4000UL)
#define STATUS1_IRQ_PHY1_N_ACCESS (READ_ONLY)
/* Ethernet PHY 2 Interrupt */
#define STATUS1_IRQ_PHY2_N_SHIFT (15UL)
#define STATUS1_IRQ_PHY2_N_MASK (0x8000UL)
#define STATUS1_IRQ_PHY2_N_ACCESS (READ_ONLY)
/*** Main Board Inputs ***/
#define OUTPUT1 (0x0008)
/* Active I2C ext
0: disabled
1: enabled */
#define OUTPUT1_EN_I2C_EXT_N_SHIFT (0UL)
#define OUTPUT1_EN_I2C_EXT_N_MASK (0x1UL)
#define OUTPUT1_EN_I2C_EXT_N_ACCESS (READ_WRITE)
/* Active GPS Antenna Supply
0: disabled
1: enabled */
#define OUTPUT1_EN_GPS_ANT_SHIFT (1UL)
#define OUTPUT1_EN_GPS_ANT_MASK (0x2UL)
#define OUTPUT1_EN_GPS_ANT_ACCESS (READ_WRITE)
/* Reset WLAN mod
0: active
1: not active */
#define OUTPUT1_RST_WLAN_MOD_N_SHIFT (2UL)
#define OUTPUT1_RST_WLAN_MOD_N_MASK (0x4UL)
#define OUTPUT1_RST_WLAN_MOD_N_ACCESS (READ_WRITE)
/* Active 5V ext
0: disabled
1: enabled */
#define OUTPUT1_EN_5V0_EXT_SHIFT (3UL)
#define OUTPUT1_EN_5V0_EXT_MASK (0x8UL)
#define OUTPUT1_EN_5V0_EXT_ACCESS (READ_WRITE)
/* Active 1V5 ext
0: disabled
1: enabled */
#define OUTPUT1_EN_1V5_SHIFT (4UL)
#define OUTPUT1_EN_1V5_MASK (0x10UL)
#define OUTPUT1_EN_1V5_ACCESS (READ_WRITE)
/*** Interrupt Mask Register 1 ***/
#define INTMASK1 (0x0010)
/* PCM RX irq of PCM controller 1 */
#define INTMASK1_PCM1_RX_SHIFT (0UL)
#define INTMASK1_PCM1_RX_MASK (0x1UL)
#define INTMASK1_PCM1_RX_ACCESS (READ_WRITE)
/* PCM TX irq of PCM controller 1 */
#define INTMASK1_PCM1_TX_SHIFT (1UL)
#define INTMASK1_PCM1_TX_MASK (0x2UL)
#define INTMASK1_PCM1_TX_ACCESS (READ_WRITE)
/* PCM RX irq of PCM controller 2 */
#define INTMASK1_PCM2_RX_SHIFT (2UL)
#define INTMASK1_PCM2_RX_MASK (0x4UL)
#define INTMASK1_PCM2_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 2 */
#define INTMASK1_PCM2_TX_SHIFT (3UL)
#define INTMASK1_PCM2_TX_MASK (0x8UL)
#define INTMASK1_PCM2_TX_ACCESS (READ_WRITE)
/* RTC Interrupt */
#define INTMASK1_RTC_N_SHIFT (8UL)
#define INTMASK1_RTC_N_MASK (0x100UL)
#define INTMASK1_RTC_N_ACCESS (READ_WRITE)
/* LM75 interrupt */
#define INTMASK1_LM75_N_SHIFT (9UL)
#define INTMASK1_LM75_N_MASK (0x200UL)
#define INTMASK1_LM75_N_ACCESS (READ_WRITE)
/* SIM Card 1 Detect signal change interrupt */
#define INTMASK1_SIMCARD1_SHIFT (12UL)
#define INTMASK1_SIMCARD1_MASK (0x1000UL)
#define INTMASK1_SIMCARD1_ACCESS (READ_WRITE)
/* SIM Card 2 Detect signal change interrupt */
#define INTMASK1_SIMCARD2_SHIFT (13UL)
#define INTMASK1_SIMCARD2_MASK (0x2000UL)
#define INTMASK1_SIMCARD2_ACCESS (READ_WRITE)
/* Ethernet PHY 1 Interrupt */
#define INTMASK1_PHY1_N_SHIFT (14UL)
#define INTMASK1_PHY1_N_MASK (0x4000UL)
#define INTMASK1_PHY1_N_ACCESS (READ_WRITE)
/* Ethernet PHY 2 Interrupt */
#define INTMASK1_PHY2_N_SHIFT (15UL)
#define INTMASK1_PHY2_N_MASK (0x8000UL)
#define INTMASK1_PHY2_N_ACCESS (READ_WRITE)
/*** Interrupt Mask Register 2 ***/
#define INTMASK2 (0x0012)
/*** Interrupt Pending Register 1 ***/
#define INTPENDING1 (0x0014)
/* PCM RX irq of PCM controller 1
0: no interrupt
1: interrupt flag set */
#define INTPENDING1_PCM1_RX_SHIFT (0UL)
#define INTPENDING1_PCM1_RX_MASK (0x1UL)
#define INTPENDING1_PCM1_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 1 */
#define INTPENDING1_PCM1_TX_SHIFT (1UL)
#define INTPENDING1_PCM1_TX_MASK (0x2UL)
#define INTPENDING1_PCM1_TX_ACCESS (READ_WRITE)
/* PCM RX irq of PCM controller 2 */
#define INTPENDING1_PCM2_RX_SHIFT (2UL)
#define INTPENDING1_PCM2_RX_MASK (0x4UL)
#define INTPENDING1_PCM2_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 2 */
#define INTPENDING1_PCM2_TX_SHIFT (3UL)
#define INTPENDING1_PCM2_TX_MASK (0x8UL)
#define INTPENDING1_PCM2_TX_ACCESS (READ_WRITE)
/* RTC Interrupt */
#define INTPENDING1_RTC_N_SHIFT (8UL)
#define INTPENDING1_RTC_N_MASK (0x100UL)
#define INTPENDING1_RTC_N_ACCESS (READ_WRITE)
/* LM75 interrupt */
#define INTPENDING1_LM75_N_SHIFT (9UL)
#define INTPENDING1_LM75_N_MASK (0x200UL)
#define INTPENDING1_LM75_N_ACCESS (READ_WRITE)
/* SIM Card 1 Detect signal change interrupt */
#define INTPENDING1_SIMCARD1_SHIFT (12UL)
#define INTPENDING1_SIMCARD1_MASK (0x1000UL)
#define INTPENDING1_SIMCARD1_ACCESS (READ_WRITE)
/* SIM Card 2 Detect signal change interrupt */
#define INTPENDING1_SIMCARD2_SHIFT (13UL)
#define INTPENDING1_SIMCARD2_MASK (0x2000UL)
#define INTPENDING1_SIMCARD2_ACCESS (READ_WRITE)
/* Ethernet PHY 1 Interrupt */
#define INTPENDING1_PHY1_N_SHIFT (14UL)
#define INTPENDING1_PHY1_N_MASK (0x4000UL)
#define INTPENDING1_PHY1_N_ACCESS (READ_WRITE)
/* Ethernet PHY 2 Interrupt */
#define INTPENDING1_PHY2_N_SHIFT (15UL)
#define INTPENDING1_PHY2_N_MASK (0x8000UL)
#define INTPENDING1_PHY2_N_ACCESS (READ_WRITE)
/*** Interrupt Pending Register 2 ***/
#define INTPENDING2 (0x0016)
/*** Interrupt Status Register 1 ***/
#define INTSTATUS1 (0x0018)
/* PCM RX irq of PCM controller 1
0: no interrupt
1: interrupt flag set */
#define INTSTATUS1_PCM1_RX_SHIFT (0UL)
#define INTSTATUS1_PCM1_RX_MASK (0x1UL)
#define INTSTATUS1_PCM1_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 1 */
#define INTSTATUS1_PCM1_TX_SHIFT (1UL)
#define INTSTATUS1_PCM1_TX_MASK (0x2UL)
#define INTSTATUS1_PCM1_TX_ACCESS (READ_WRITE)
/* PCM RX irq of PCM controller 2 */
#define INTSTATUS1_PCM2_RX_SHIFT (2UL)
#define INTSTATUS1_PCM2_RX_MASK (0x4UL)
#define INTSTATUS1_PCM2_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 2 */
#define INTSTATUS1_PCM2_TX_SHIFT (3UL)
#define INTSTATUS1_PCM2_TX_MASK (0x8UL)
#define INTSTATUS1_PCM2_TX_ACCESS (READ_WRITE)
/* RTC Interrupt */
#define INTSTATUS1_RTC_N_SHIFT (8UL)
#define INTSTATUS1_RTC_N_MASK (0x100UL)
#define INTSTATUS1_RTC_N_ACCESS (READ_WRITE)
/* LM75 interrupt */
#define INTSTATUS1_LM75_N_SHIFT (9UL)
#define INTSTATUS1_LM75_N_MASK (0x200UL)
#define INTSTATUS1_LM75_N_ACCESS (READ_WRITE)
/* SIM Card 1 Detect signal change interrupt */
#define INTSTATUS1_SIMCARD1_SHIFT (12UL)
#define INTSTATUS1_SIMCARD1_MASK (0x1000UL)
#define INTSTATUS1_SIMCARD1_ACCESS (READ_WRITE)
/* SIM Card 2 Detect signal change interrupt */
#define INTSTATUS1_SIMCARD2_SHIFT (13UL)
#define INTSTATUS1_SIMCARD2_MASK (0x2000UL)
#define INTSTATUS1_SIMCARD2_ACCESS (READ_WRITE)
/* Ethernet PHY 1 Interrupt */
#define INTSTATUS1_PHY1_N_SHIFT (14UL)
#define INTSTATUS1_PHY1_N_MASK (0x4000UL)
#define INTSTATUS1_PHY1_N_ACCESS (READ_WRITE)
/* Ethernet PHY 2 Interrupt */
#define INTSTATUS1_PHY2_N_SHIFT (15UL)
#define INTSTATUS1_PHY2_N_MASK (0x8000UL)
#define INTSTATUS1_PHY2_N_ACCESS (READ_WRITE)
/*** Interrupt Status Register 2 ***/
#define INTSTATUS2 (0x001A)
/*** Interrupt Acknowledge Register 1 ***/
#define INTACK1 (0x0018)
/* PCM RX irq of PCM controller 1
0: no interrupt
1: interrupt flag set */
#define INTACK1_PCM1_RX_SHIFT (0UL)
#define INTACK1_PCM1_RX_MASK (0x1UL)
#define INTACK1_PCM1_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 1 */
#define INTACK1_PCM1_TX_SHIFT (1UL)
#define INTACK1_PCM1_TX_MASK (0x2UL)
#define INTACK1_PCM1_TX_ACCESS (READ_WRITE)
/* PCM RX irq of PCM controller 2 */
#define INTACK1_PCM2_RX_SHIFT (2UL)
#define INTACK1_PCM2_RX_MASK (0x4UL)
#define INTACK1_PCM2_RX_ACCESS (READ_ONLY)
/* PCM TX irq of PCM controller 2 */
#define INTACK1_PCM2_TX_SHIFT (3UL)
#define INTACK1_PCM2_TX_MASK (0x8UL)
#define INTACK1_PCM2_TX_ACCESS (READ_WRITE)
/* RTC Interrupt */
#define INTACK1_RTC_N_SHIFT (8UL)
#define INTACK1_RTC_N_MASK (0x100UL)
#define INTACK1_RTC_N_ACCESS (READ_WRITE)
/* LM75 interrupt */
#define INTACK1_LM75_N_SHIFT (9UL)
#define INTACK1_LM75_N_MASK (0x200UL)
#define INTACK1_LM75_N_ACCESS (READ_WRITE)
/* SIM Card 1 Detect signal change interrupt */
#define INTACK1_SIMCARD1_SHIFT (12UL)
#define INTACK1_SIMCARD1_MASK (0x1000UL)
#define INTACK1_SIMCARD1_ACCESS (READ_WRITE)
/* SIM Card 2 Detect signal change interrupt */
#define INTACK1_SIMCARD2_SHIFT (13UL)
#define INTACK1_SIMCARD2_MASK (0x2000UL)
#define INTACK1_SIMCARD2_ACCESS (READ_WRITE)
/* Ethernet PHY 1 Interrupt */
#define INTACK1_PHY1_N_SHIFT (14UL)
#define INTACK1_PHY1_N_MASK (0x4000UL)
#define INTACK1_PHY1_N_ACCESS (READ_WRITE)
/* Ethernet PHY 2 Interrupt */
#define INTACK1_PHY2_N_SHIFT (15UL)
#define INTACK1_PHY2_N_MASK (0x8000UL)
#define INTACK1_PHY2_N_ACCESS (READ_WRITE)
/*** Interrupt Acknowledge Register 2 ***/
#define INTACK2 (0x001A)
/*** LED Control Register ***/
#define LED (0x0020)
/* Enable LED 0 (green) */
#define LED_LED0_GREEN_SHIFT (0UL)
#define LED_LED0_GREEN_MASK (0x1UL)
#define LED_LED0_GREEN_ACCESS (READ_WRITE)
/* Enable LED 0 (red) */
#define LED_LED0_RED_SHIFT (1UL)
#define LED_LED0_RED_MASK (0x2UL)
#define LED_LED0_RED_ACCESS (READ_WRITE)
/* Enable LED 1 (green) */
#define LED_LED1_GREEN_SHIFT (2UL)
#define LED_LED1_GREEN_MASK (0x4UL)
#define LED_LED1_GREEN_ACCESS (READ_WRITE)
/* Enable LED 1 (red) */
#define LED_LED1_RED_SHIFT (3UL)
#define LED_LED1_RED_MASK (0x8UL)
#define LED_LED1_RED_ACCESS (READ_WRITE)
/* Enable LED 2 (green) */
#define LED_LED2_GREEN_SHIFT (4UL)
#define LED_LED2_GREEN_MASK (0x10UL)
#define LED_LED2_GREEN_ACCESS (READ_WRITE)
/* Enable LED 2 (red) */
#define LED_LED2_RED_SHIFT (5UL)
#define LED_LED2_RED_MASK (0x20UL)
#define LED_LED2_RED_ACCESS (READ_WRITE)
/* Enable LED 3 (green) */
#define LED_LED3_GREEN_SHIFT (6UL)
#define LED_LED3_GREEN_MASK (0x40UL)
#define LED_LED3_GREEN_ACCESS (READ_WRITE)
/* Enable LED 3 (red) */
#define LED_LED3_RED_SHIFT (7UL)
#define LED_LED3_RED_MASK (0x80UL)
#define LED_LED3_RED_ACCESS (READ_WRITE)
/* Enable LED 4 (green) */
#define LED_LED4_GREEN_SHIFT (8UL)
#define LED_LED4_GREEN_MASK (0x100UL)
#define LED_LED4_GREEN_ACCESS (READ_WRITE)
/* Enable LED 4 (red) */
#define LED_LED4_RED_SHIFT (9UL)
#define LED_LED4_RED_MASK (0x200UL)
#define LED_LED4_RED_ACCESS (READ_WRITE)
/* Enable LED 5 (green) */
#define LED_LED5_GREEN_SHIFT (10UL)
#define LED_LED5_GREEN_MASK (0x400UL)
#define LED_LED5_GREEN_ACCESS (READ_WRITE)
/* Enable LED 5 (red) */
#define LED_LED5_RED_SHIFT (11UL)
#define LED_LED5_RED_MASK (0x800UL)
#define LED_LED5_RED_ACCESS (READ_WRITE)
/*** SIM Slot Control Register ***/
#define SIM_CTRL (0x0040)
/* 000: disconnect analog switch 1
001: Connect PCie Slot 1 to SIM Chip 1
010: Connect PCie Slot 1 to SIM Chip 2
Note: If no SIM Card is inserted, the power is disable of the corresponding slot. */
#define SIM_CTRL_PCIE1_SIM_SEL_SHIFT (0UL)
#define SIM_CTRL_PCIE1_SIM_SEL_MASK (0x7UL)
#define SIM_CTRL_PCIE1_SIM_SEL_ACCESS (READ_WRITE)
/* 000: disconnect analog switch 1
001: Connect PCie Slot 2 to SIM Chip 1
010: Connect PCie Slot 2 to SIM Chip 2
Note: If no SIM Card is inserted, the power is disable of the corresponding slot. */
#define SIM_CTRL_PCIE3_SIM_SEL_SHIFT (4UL)
#define SIM_CTRL_PCIE3_SIM_SEL_MASK (0x70UL)
#define SIM_CTRL_PCIE3_SIM_SEL_ACCESS (READ_WRITE)
/*** PCIe Slot Reset ***/
#define PCIE_RESET (0x0030)
/* PCIe Slot 1 Reset
0: reset asserted */
#define PCIE_RESET_PCIE1_RST_N_SHIFT (0UL)
#define PCIE_RESET_PCIE1_RST_N_MASK (0x1UL)
#define PCIE_RESET_PCIE1_RST_N_ACCESS (READ_WRITE)
/* PCIe Slot 2 Reset
0: reset asserted */
#define PCIE_RESET_PCIE2_RST_N_SHIFT (1UL)
#define PCIE_RESET_PCIE2_RST_N_MASK (0x2UL)
#define PCIE_RESET_PCIE2_RST_N_ACCESS (READ_WRITE)
/* PCIe Slot 3 Reset
0: reset asserted */
#define PCIE_RESET_PCIE3_RST_N_SHIFT (2UL)
#define PCIE_RESET_PCIE3_RST_N_MASK (0x4UL)
#define PCIE_RESET_PCIE3_RST_N_ACCESS (READ_WRITE)
/*** PCIe Slot Power Control ***/
#define PCIE_POWER (0x0032)
/* PCIe Slot 1 Power
0: disabled */
#define PCIE_POWER_PCIE1_PWR_SHIFT (0UL)
#define PCIE_POWER_PCIE1_PWR_MASK (0x1UL)
#define PCIE_POWER_PCIE1_PWR_ACCESS (READ_WRITE)
/* PCIe Slot 2 Power
0: disabled */
#define PCIE_POWER_PCIE2_PWR_SHIFT (1UL)
#define PCIE_POWER_PCIE2_PWR_MASK (0x2UL)
#define PCIE_POWER_PCIE2_PWR_ACCESS (READ_WRITE)
/* PCIe Slot 3 Power
0: disabled */
#define PCIE_POWER_PCIE3_PWR_SHIFT (2UL)
#define PCIE_POWER_PCIE3_PWR_MASK (0x4UL)
#define PCIE_POWER_PCIE3_PWR_ACCESS (READ_WRITE)
/*** PCIe Slot SIM Clk Redriver Control ***/
#define PCIE_SIM_CLOCK (0x0034)
/* 0: Enable SIM Clock Driver of PCIe Slot 1 */
#define PCIE_SIM_CLOCK_SIM_CLK_EN1_N_SHIFT (0UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN1_N_MASK (0x1UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN1_N_ACCESS (READ_WRITE)
/* 0: Enable SIM Clock Driver of PCIe Slot 2 */
#define PCIE_SIM_CLOCK_SIM_CLK_EN2_N_SHIFT (1UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN2_N_MASK (0x2UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN2_N_ACCESS (READ_WRITE)
/* 0: Enable SIM Clock Driver of PCIe Slot 3 */
#define PCIE_SIM_CLOCK_SIM_CLK_EN3_N_SHIFT (2UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN3_N_MASK (0x4UL)
#define PCIE_SIM_CLOCK_SIM_CLK_EN3_N_ACCESS (READ_WRITE)
/*** I/O read/write ***/
#define GPIO_REGISTER (0x0070)
/* */
#define GPIO_REGISTER_IO_OUT1_SHIFT (0UL)
#define GPIO_REGISTER_IO_OUT1_MASK (0x1UL)
#define GPIO_REGISTER_IO_OUT1_ACCESS (READ_ONLY)
/* */
#define GPIO_REGISTER_IO_OUT2_SHIFT (1UL)
#define GPIO_REGISTER_IO_OUT2_MASK (0x2UL)
#define GPIO_REGISTER_IO_OUT2_ACCESS (READ_ONLY)
/* */
#define GPIO_REGISTER_IO_IN1_SHIFT (5UL)
#define GPIO_REGISTER_IO_IN1_MASK (0x20UL)
#define GPIO_REGISTER_IO_IN1_ACCESS ()
/* */
#define GPIO_REGISTER_IO_IN2_SHIFT (6UL)
#define GPIO_REGISTER_IO_IN2_MASK (0x40UL)
#define GPIO_REGISTER_IO_IN2_ACCESS ()
/*** SFP Control ***/
#define SFP_CONTROL (0x0072)
/* */
#define SFP_CONTROL_SFP_IO_TX_DIS_SHIFT (0UL)
#define SFP_CONTROL_SFP_IO_TX_DIS_MASK (0x1UL)
#define SFP_CONTROL_SFP_IO_TX_DIS_ACCESS (READ_WRITE)
/*** SFP Monitor ***/
#define SFP_MONITOR (0x0074)
/* */
#define SFP_MONITOR_SFP_IO_LOS_SHIFT (0UL)
#define SFP_MONITOR_SFP_IO_LOS_MASK (0x1UL)
#define SFP_MONITOR_SFP_IO_LOS_ACCESS (READ_ONLY)
/* */
#define SFP_MONITOR_SFP_IO_PRSNT_SHIFT (1UL)
#define SFP_MONITOR_SFP_IO_PRSNT_MASK (0x2UL)
#define SFP_MONITOR_SFP_IO_PRSNT_ACCESS (READ_ONLY)
/* */
#define SFP_MONITOR_SFP_IO_TX_FAULT_SHIFT (2UL)
#define SFP_MONITOR_SFP_IO_TX_FAULT_MASK (0x4UL)
#define SFP_MONITOR_SFP_IO_TX_FAULT_ACCESS ()
/*** I/O direction register 1 ***/
#define PCIE_1_SLOT_DIR1 (0x0100)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_COEX1_DIR_SHIFT (0UL)
#define PCIE_1_SLOT_DIR1_COEX1_DIR_MASK (0x1UL)
#define PCIE_1_SLOT_DIR1_COEX1_DIR_ACCESS (READ_WRITE)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_COEX2_DIR_SHIFT (1UL)
#define PCIE_1_SLOT_DIR1_COEX2_DIR_MASK (0x2UL)
#define PCIE_1_SLOT_DIR1_COEX2_DIR_ACCESS (READ_WRITE)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_LED_WLAN_DIR_SHIFT (2UL)
#define PCIE_1_SLOT_DIR1_LED_WLAN_DIR_MASK (0x4UL)
#define PCIE_1_SLOT_DIR1_LED_WLAN_DIR_ACCESS (READ_WRITE)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_LED_WWAN_DIR_SHIFT (3UL)
#define PCIE_1_SLOT_DIR1_LED_WWAN_DIR_MASK (0x8UL)
#define PCIE_1_SLOT_DIR1_LED_WWAN_DIR_ACCESS (READ_WRITE)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_WAKE_N_DIR_SHIFT (4UL)
#define PCIE_1_SLOT_DIR1_WAKE_N_DIR_MASK (0x10UL)
#define PCIE_1_SLOT_DIR1_WAKE_N_DIR_ACCESS (READ_WRITE)
/* Direction of I/O Signal (FPGA Pin)
0: Input (default) */
#define PCIE_1_SLOT_DIR1_WDISABLE_N_DIR_SHIFT (5UL)
#define PCIE_1_SLOT_DIR1_WDISABLE_N_DIR_MASK (0x20UL)
#define PCIE_1_SLOT_DIR1_WDISABLE_N_DIR_ACCESS (READ_WRITE)
/*** I/O direction register 1 with all signals on FPGA I/O ***/
#define PCIE_2_SLOT_DIR1 (0x0200)
/*** I/O direction register 1 with all signals on FPGA I/O ***/
#define PCIE_3_SLOT_DIR1 (0x0300)
/*** I/O control register 1 ***/
#define PCIE_1_SLOT_CTRL1 (0x0102)
/* When X DIR = 0 (Input): Value of input pin
0: Low
1: High
When X DIR = 1 (Output): Value written to output */
#define PCIE_1_SLOT_CTRL1_COEX1_SHIFT (0UL)
#define PCIE_1_SLOT_CTRL1_COEX1_MASK (0x1UL)
#define PCIE_1_SLOT_CTRL1_COEX1_ACCESS (READ_WRITE)
/* see COEX1 */
#define PCIE_1_SLOT_CTRL1_COEX2_SHIFT (1UL)
#define PCIE_1_SLOT_CTRL1_COEX2_MASK (0x2UL)
#define PCIE_1_SLOT_CTRL1_COEX2_ACCESS (READ_WRITE)
/* see COEX1 */
#define PCIE_1_SLOT_CTRL1_LED_WLAN_SHIFT (2UL)
#define PCIE_1_SLOT_CTRL1_LED_WLAN_MASK (0x4UL)
#define PCIE_1_SLOT_CTRL1_LED_WLAN_ACCESS (READ_WRITE)
/* see COEX1 */
#define PCIE_1_SLOT_CTRL1_LED_WWAN_SHIFT (3UL)
#define PCIE_1_SLOT_CTRL1_LED_WWAN_MASK (0x8UL)
#define PCIE_1_SLOT_CTRL1_LED_WWAN_ACCESS (READ_WRITE)
/* see COEX1 */
#define PCIE_1_SLOT_CTRL1_WAKE_N_SHIFT (4UL)
#define PCIE_1_SLOT_CTRL1_WAKE_N_MASK (0x10UL)
#define PCIE_1_SLOT_CTRL1_WAKE_N_ACCESS (READ_WRITE)
/* see COEX1 */
#define PCIE_1_SLOT_CTRL1_WDISABLE_N_SHIFT (5UL)
#define PCIE_1_SLOT_CTRL1_WDISABLE_N_MASK (0x20UL)
#define PCIE_1_SLOT_CTRL1_WDISABLE_N_ACCESS (READ_WRITE)
/* PCIe Power Good */
#define PCIE_1_SLOT_CTRL1_PGOOD_N_SHIFT (6UL)
#define PCIE_1_SLOT_CTRL1_PGOOD_N_MASK (0x40UL)
#define PCIE_1_SLOT_CTRL1_PGOOD_N_ACCESS (READ_ONLY)
/*** I/O control register 1 ***/
#define PCIE_2_SLOT_CTRL1 (0x0202)
/*** I/O control register 1 ***/
#define PCIE_3_SLOT_CTRL1 (0x0302)
/*** PCM I/O assignment register
PCM Slot mux control ***/
#define PCIE_PCM_IO_MUX_CONTROLLER_1 (0x0104)
/* See Table 12 */
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN45_SHIFT (0UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN45_MASK (0x3UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN45_ACCESS (READ_WRITE)
/* See Table 12 */
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN47_SHIFT (2UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN47_MASK (0xcUL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN47_ACCESS (READ_WRITE)
/* See Table 12 */
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN49_SHIFT (4UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN49_MASK (0x30UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN49_ACCESS (READ_WRITE)
/* See Table 12 */
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN51_SHIFT (6UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN51_MASK (0xc0UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PIN51_ACCESS (READ_WRITE)
/* See Table 13. */
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PCM_SLOT_CTRL_SHIFT (8UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PCM_SLOT_CTRL_MASK (0x700UL)
#define PCIE_PCM_IO_MUX_CONTROLLER_1_PCM_SLOT_CTRL_ACCESS (READ_WRITE)
/*** PCM Module ID register ***/
#define PCM_MODULE_IDENTIFIER_REGISTER (0x0106)
/* 0: default
1: Triorail TRM-5 Module
others: reserved */
#define PCM_MODULE_IDENTIFIER_REGISTER_ID_SHIFT (0UL)
#define PCM_MODULE_IDENTIFIER_REGISTER_ID_MASK (0xffffUL)
#define PCM_MODULE_IDENTIFIER_REGISTER_ID_ACCESS (READ_WRITE)
/*** PCM control register ***/
#define VCTL (0x0110)
/* Enable PCM data transmission transfer for this PCIe Slot.
0: disabled
1: transfer enabled */
#define VCTL_PCM_EN_SHIFT (0UL)
#define VCTL_PCM_EN_MASK (0x1UL)
#define VCTL_PCM_EN_ACCESS (READ_WRITE)
/* Enables PCB Data Loopback
PCM data from PCIe slot is written to TX buffer and PCM data from CPU is written to RX buffer. */
#define VCTL_LOOP_SHIFT (1UL)
#define VCTL_LOOP_MASK (0x2UL)
#define VCTL_LOOP_ACCESS (READ_WRITE)
/* Writing 1 clears RX buffer */
#define VCTL_VBCRX_SHIFT (2UL)
#define VCTL_VBCRX_MASK (0x4UL)
#define VCTL_VBCRX_ACCESS (WRITE_ONLY)
/* Writing 1 clears TX buffer */
#define VCTL_VBCTX_SHIFT (3UL)
#define VCTL_VBCTX_MASK (0x8UL)
#define VCTL_VBCTX_ACCESS (WRITE_ONLY)
/* 0: PCM stream has 8kHz samples
1: PCM stream has 16kHz samples */
#define VCTL_PCM_16KHZ_SHIFT (4UL)
#define VCTL_PCM_16KHZ_MASK (0x10UL)
#define VCTL_PCM_16KHZ_ACCESS (READ_ONLY)
/*** Voice Receive Buffer Data Register ***/
#define VRDB (0x0112)
/* Received voice data sample */
#define VRDB_RXDATA_SHIFT (0UL)
#define VRDB_RXDATA_MASK (0xffffUL)
#define VRDB_RXDATA_ACCESS (READ_ONLY)
/*** Voice Receive Buffer Fill Level Register ***/
#define VRBFL (0x0114)
/* Number of available 16-bit voice samples available to be read in the receive buffer. */
#define VRBFL_RXLEVEL_SHIFT (0UL)
#define VRBFL_RXLEVEL_MASK (0xffffUL)
#define VRBFL_RXLEVEL_ACCESS (READ_ONLY)
/*** Voice Receive Buffer Watermark Register ***/
#define VRBW (0x0116)
/* Watermark in number of 16-bit voice samples. (0xffff disables receive buffer watermark interrupts.) */
#define VRBW_RXWM_SHIFT (0UL)
#define VRBW_RXWM_MASK (0xffffUL)
#define VRBW_RXWM_ACCESS (READ_WRITE)
/*** Voice Idle Sample Transmit Register ***/
#define VRIS (0x0118)
/* 16-Bit voice sample */
#define VRIS_IDLE_SHIFT (0UL)
#define VRIS_IDLE_MASK (0xffffUL)
#define VRIS_IDLE_ACCESS (READ_WRITE)
/*** Voice Transmit Buffer Data Register ***/
#define VTDB (0x011A)
/* Received voice data sample */
#define VTDB_TXDATA_SHIFT (0UL)
#define VTDB_TXDATA_MASK (0xffffUL)
#define VTDB_TXDATA_ACCESS (WRITE_ONLY)
/*** Voice Transmit Buffer Fill Level Register ***/
#define VTBFL (0x011C)
/* Number of available 16-bit voice samples available to be read in the receive buffer. */
#define VTBFL_TXLEVEL_SHIFT (0UL)
#define VTBFL_TXLEVEL_MASK (0xffffUL)
#define VTBFL_TXLEVEL_ACCESS (READ_ONLY)
/*** Voice Transmit Buffer Watermark Register ***/
#define VTBW (0x011E)
/* Watermark in number of 16-bit voice samples. (0xffff disables transmit buffer watermark interrupts.) */
#define VTBW_TXWM_SHIFT (0UL)
#define VTBW_TXWM_MASK (0xffffUL)
#define VTBW_TXWM_ACCESS (READ_WRITE)
/*** Voice Idle Sample Transmit Register ***/
#define VTIS (0x0120)
/* 16-Bit voice sample */
#define VTIS_IDLE_SHIFT (0UL)
#define VTIS_IDLE_MASK (0xffffUL)
#define VTIS_IDLE_ACCESS (READ_WRITE)
/*** ***/
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1 (0x0130)
/* 1: use PCIe slot 1 pin 45 as GPIO
0: use PCIe slot 1 pin 45 as PCM */
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__45_ENB_SHIFT (0UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__45_ENB_MASK (0x1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__45_ENB_ACCESS (READ_WRITE)
/* 1: use PCIe slot 1 pin 47 as GPIO
0: use PCIe slot 1 pin 47 as PCM */
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__47_ENB_SHIFT (1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__47_ENB_MASK (0x2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__47_ENB_ACCESS (READ_WRITE)
/* 1: use PCIe slot 1 pin 49 as GPIO
0: use PCIe slot 1 pin 49 as PCM */
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__49_ENB_SHIFT (2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__49_ENB_MASK (0x4UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__49_ENB_ACCESS (READ_WRITE)
/* 1: use PCIe slot 1 pin 51 as GPIO
0: use PCIe slot 1 pin 51 as PCM */
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__51_ENB_SHIFT (3UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__51_ENB_MASK (0x8UL)
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_1_PCIE_PIN__51_ENB_ACCESS (READ_WRITE)
/*** Enable / disable the GPIO functionality on the PCM pins connected to PCM controller 2
For further details see "PCIe slot PCM pin GPIO EN register 1" ***/
#define PCIE_SLOT_PCM_PIN_GPIO_EN_REGISTER_2 (0x0230)
/*** Sets the direction of GPIO on the PCM pins connected to PCM controller 1
Note: only applicable if GPIO is enabled ***/
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1 (0x0132)
/* 0: PCIe slot 1 pin 45 is Input (default)
1: PCIe slot 1 pin 45 is Output */
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__45_DIR_SHIFT (0UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__45_DIR_MASK (0x1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__45_DIR_ACCESS (READ_WRITE)
/* 0: PCIe slot 1 pin 47 is Input (default)
1: PCIe slot 1 pin 47 is Output */
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__47_DIR_SHIFT (1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__47_DIR_MASK (0x2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__47_DIR_ACCESS (READ_WRITE)
/* 0: PCIe slot 1 pin 49 is Input (default)
1: PCIe slot 1 pin 49 is Output */
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__49_DIR_SHIFT (2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__49_DIR_MASK (0x4UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__49_DIR_ACCESS (READ_WRITE)
/* 0: PCIe slot 1 pin 51 is Input (default)
1: PCIe slot 1 pin 51 is Output */
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__51_DIR_SHIFT (3UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__51_DIR_MASK (0x8UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_1_PCIE_PIN__51_DIR_ACCESS (READ_WRITE)
/*** Sets the direction of GPIO on the PCM pins connected to PCM controller 2
Note: only applicable if GPIO is enabled
For further details see "PCIe slot PCM pin GPIO DIR register 1" ***/
#define PCIE_SLOT_PCM_PIN_GPIO_DIR_REGISTER_2 (0x0232)
/*** Access to the data register of GPIOs on the PCM pins connected to PCM controller 1
Note: only applicable if GPIO is enable ***/
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1 (0x0134)
/* PCIe slot 1 pin 45:
Signal level applied to the pin, when configured as input / or signal level driven on the pin, when configured as output.
0: Low
1: High */
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__45_RW_SHIFT (0UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__45_RW_MASK (0x1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__45_RW_ACCESS (READ_WRITE)
/* See PCIE_PIN _45_RW */
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__47_RW_SHIFT (1UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__47_RW_MASK (0x2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__47_RW_ACCESS (READ_WRITE)
/* See PCIE_PIN _45_RW */
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__49_RW_SHIFT (2UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__49_RW_MASK (0x4UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__49_RW_ACCESS (READ_WRITE)
/* See PCIE_PIN _45_RW */
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__51_RW_SHIFT (3UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__51_RW_MASK (0x8UL)
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_1_PCIE_PIN__51_RW_ACCESS (READ_WRITE)
/*** Access to the data register of GPIOs on the PCM pins connected to PCM controller 2
Note: only applicable if GPIO is enable
For further details see "PCIe slot PCM pin GPIO DATA register 1" ***/
#define PCIE_SLOT_PCM_PIN_GPIO_DATA_REGISTER_2 (0x0234)
#endif /* NBHW18_FPGA_REGS_H */

View File

@ -1,43 +1,97 @@
#include <common.h>
#include <asm/gpio.h>
#include <stdlib.h>
#include "nbhw_gpio.h"
#define SET_LOGIC(enable,group,bit) \
if (enable) \
mvGppValueSet(group, bit, bit); \
else \
mvGppValueSet(group, bit, 0);
struct gpio_node {
struct gpio_node* next;
struct gpio_desc desc;
const char* name;
int is_output;
};
#define GPIO_RESET_BUTTON (14)
static struct gpio_node* gl = NULL;
void init_gpios(void)
{
gpio_request(GPIO_RESET_BUTTON, "GPIO_RESET_BUTTON");
gpio_direction_input(GPIO_RESET_BUTTON);
static struct gpio_desc* lookup_gpio(const char* gpio_name, int is_output) {
struct gpio_node* cur = gl;
while (cur) {
if ((strcmp(gpio_name, cur->name)==0) &&
(is_output == cur->is_output)) {
return &(cur->desc);
}
cur = cur->next;
}
return NULL;
}
void out_usb_power(int enable)
{
// SET_LOGIC(enable, 1, BIT9);
static struct gpio_desc* acquire_gpio(const char* gpio_name, int is_output) {
struct gpio_node* gn = 0;
int node;
/* Check, if we already requested this gpio */
struct gpio_desc* desc = lookup_gpio(gpio_name, is_output);
if (desc) return desc;
/* If we do not have it try to request it now. */
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, "nm,gpios");
if (node < 0) {
goto abort;
}
gn = (struct gpio_node*)malloc(sizeof(struct gpio_node));
if (!gn) goto abort;
if (gpio_request_by_name_nodev(offset_to_ofnode(node), gpio_name, 0, &(gn->desc), is_output ? GPIOD_IS_OUT : GPIOD_IS_IN) < 0) {
goto abort;
}
gn->name = gpio_name;
gn->is_output = is_output;
gn->next = gl;
gl = gn;
desc = &(gn->desc);
return desc;
abort:
if (gn) free(gn);
printk("Could not acquire gpio %s as %s!\n", gpio_name, is_output ? "output" : "input");
return 0;
}
void out_watchdog(int enable)
int get_gpio(const char* gpio_name)
{
// SET_LOGIC(enable, 0, BIT19);
struct gpio_desc* d;
int res;
d = acquire_gpio(gpio_name, 0);
if (!d) goto abort;
res = dm_gpio_get_value(d);
return res;
abort:
printf("Could not set gpio %s!\n", gpio_name);
return -1;
}
void out_fpga_logic_reset(int enable)
int set_gpio(const char* gpio_name, int value)
{
// SET_LOGIC(enable, 1, BIT12);
struct gpio_desc* d;
d = acquire_gpio(gpio_name, 1);
if (!d) goto abort;
dm_gpio_set_value(d, value);
return 0;
abort:
printf("Could not set gpio %s!\n", gpio_name);
return -1;
}
void out_ext_reset_en(int enable)
{
// SET_LOGIC(enable, 0, BIT7);
}
int in_reset_button(void)
{
return gpio_get_value(GPIO_RESET_BUTTON);
}

View File

@ -1,14 +1,30 @@
#ifndef NBHW18_GPIO_H
#define NBHW18_GPIO_H
#include "../common/nbhw_gpio.h"
#ifndef HW17_GPIO_H
#define HW17_GPIO_H
void init_gpios(void);
/* GPIO definitions */
#define GPIO_WD_ENABLE "wd_enable"
#define GPIO_RST_USB_HUB "rst_usb_hub"
#define GPIO_RST_FPGA "rst_fpga"
#define GPIO_RST_ETH_PHY "rst_eth_phy"
#define GPIO_RESET_BUTTON "reset_button"
void out_usb_power(int enable);
void out_watchdog(int enable);
void out_fpga_logic_reset(int enable);
int get_gpio(const char* gpio_name);
int set_gpio(const char* gpio_name, int value);
int in_reset_button(void);
int in_fpga_cdone(void);
/* LED definitions */
#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

View File

@ -1,228 +0,0 @@
/******************************************************************************
* (c) COPYRIGHT 2015 by NetModule AG, Switzerland. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*****************************************************************************/
/* #define DEBUG */
#include <common.h>
#include <environment.h>
#include <asm/io.h>
#include <u-boot/md5.h>
#include "config.h"
#include "../common/nbhw_bd.h"
static void pcie_fixup_modify(u32 reg, u32 val, u32 mask)
{
u32 regval;
regval = readl(reg);
regval &= ~mask;
regval |= (val & mask);
writel(regval, reg);
}
/* We have a problem with the hardware during the detection phase this hack
* reduces the detection timeout from 4ns to 0ns so a minmal impulse will
* already trigger a detection. This is necessary to work with WLE600 modules. */
static void pcie_fixup(void)
{
/* SERDES0 PCIE0 = SLOT1 */
#define PCIE0_USB3_CONTROL_REG 0xF10A0120
/* SERDES4 PCIE2 = SLOT0 */
#define PCIE2_USB3_CONTROL_REG 0xF10A2120
#define PCIE_USB3_CONTROL_TIMING_MASK 0xC0
#define PCIE_USB3_CONTROL_TIMING_VALUE 0x00
pcie_fixup_modify(PCIE0_USB3_CONTROL_REG, PCIE_USB3_CONTROL_TIMING_VALUE, PCIE_USB3_CONTROL_TIMING_MASK);
pcie_fixup_modify(PCIE2_USB3_CONTROL_REG, PCIE_USB3_CONTROL_TIMING_VALUE, PCIE_USB3_CONTROL_TIMING_MASK);
}
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;
}
/* PCIE0 is on slot 1 (sw)*/
#define PCIE0_STATUS_REG 0xF1081A04
/* PCIE2 is on slot 0 (sw)*/
#define PCIE2_STATUS_REG 0xF1045A04
#define PCIE_DL_DOWN_MASK 0x01
static int has_pcie_link_on_slot(int slot)
{
/* If there is no module populated we say we have link (because we don't care) */
switch (slot) {
case 0:
if (readw(PCIE2_STATUS_REG) & PCIE_DL_DOWN_MASK)
return 0;
break;
case 1:
if (readw(PCIE0_STATUS_REG) & PCIE_DL_DOWN_MASK)
return 0;
break;
default:
printf("Slot %d does not support PCIE\n", slot);
}
return 1;
}
static int check_pcie_slot_status(int slot){
int ret = 1;
/* If WLAN on slot we need to check if we have link */
if (has_slot_wlan(slot)) {
ret = has_pcie_link_on_slot(slot);
}
return ret;
}
/* The reset counter is at 256 MB, make sure it is not overlapping the address of the reset-reason mechanim,
* which is located at 1GB - 512kB. The reset reason counter is necessary to not try to reset
* the system more than 3 times */
#define RESET_COUNTER_ADDRESS ((int *)0x10000000)
#define RESET_COUNTER_MD5 (RESET_COUNTER_ADDRESS + 4)
int get_reset_counter(void)
{
volatile int *reset_counter = RESET_COUNTER_ADDRESS;
unsigned char reset_counter_checksum[16];
debug("reset_counter before inc: %d\n", *reset_counter);
md5((unsigned char*) reset_counter, 4, reset_counter_checksum);
debug("md5 before inc: 0x%08X\n", *(unsigned int*)reset_counter_checksum);
/* Invalid checksum means it's the first boot. In this case we should see the counter
* as zero */
if (memcmp(reset_counter_checksum, RESET_COUNTER_MD5, 16) != 0) {
*reset_counter = 0;
}
return *reset_counter;
}
int inc_reset_counter(void)
{
volatile int *reset_counter = RESET_COUNTER_ADDRESS;
unsigned char reset_counter_checksum[16];
(*reset_counter)++;
debug("reset_counter after inc: %d\n", *reset_counter);
md5((unsigned char*) reset_counter, 4, reset_counter_checksum);
debug("md5 after inc: 0x%08X\n", *(unsigned int*)reset_counter_checksum);
memcpy(RESET_COUNTER_MD5, reset_counter_checksum, 16);
return *reset_counter;
}
int reset_reset_counter(void)
{
volatile int *reset_counter = RESET_COUNTER_ADDRESS;
/* We don't need to do anything with the checksum, because invalid checksum = 0 */
(*reset_counter) = 0;
return *reset_counter;
}
static int is_module_check_abort(void) {
char c;
/* Check for abort */
if (tstc()) {
c = getc();
if (c == 'a') {
return 1;
}
}
return 0;
}
/* Check if pcie link is detected for wlan modules, some WLE600 modules have
* even with the pcie_fixup patch a problem that they don't appear during the first
* boot */
static int do_wlan_fixup(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int i;
#define MAX_RESET_COUNT 6
int reset_counter = get_reset_counter();
int ret;
pcie_fixup();
/* If we do a reboot it can happen that reset_counter is still 3, in this case
* we need to restart the counter */
if (reset_counter >= MAX_RESET_COUNT) {
reset_counter = reset_reset_counter();
}
puts("Checking PCIe WLAN modules (abort with a)\n");
/* Try it for at least one second */
for (i = 0; i < 100; i++) {
ret = 3;
if (check_pcie_slot_status(0)) ret &= ~1;
if (check_pcie_slot_status(1)) ret &= ~2;
if (is_module_check_abort()) {
puts("Abort WLAN module check\n");
ret = 0;
}
if (ret == 0) break;
udelay(10000);
}
/* One module that should have link does not have link */
if (ret) {
reset_counter = inc_reset_counter();
if (reset_counter >= MAX_RESET_COUNT) {
printf("WLAN Modules missing but reset counter reached %d, continue\n", reset_counter);
return 0;
}
printf ("Not all WLAN Modules from the bd came up (ret=0x%08X), reset (try %d of %d)\n", ret, reset_counter, MAX_RESET_COUNT);
printf ("Wait with reset for %ds\n", reset_counter * 10);
udelay(10000000 * reset_counter);
do_reset(NULL, 0, 0, NULL);
}
/* Reset the counter in case of success */
reset_reset_counter();
return 0;
}
U_BOOT_CMD(
nbhw_wlan_fixup, 1, 1, do_wlan_fixup,
"NBHW WLAN fixup for some Wifi modules",
"Checks if WLAN modules have been detected correctly, or resets\n"
);

View File

@ -17,6 +17,7 @@ ccflags-y := -I../common
ifndef CONFIG_SPL_BUILD
obj-y := board.o nbhw_gpio.o nbhw_fpga_config.o nbhw_mvswitch.o \
../common/nbhw_sim.o nbhw_sim.o \
../common/da9063.o \
../common/lattice/core.o \
../common/lattice/hardware.o \

View File

@ -55,6 +55,7 @@ DECLARE_GLOBAL_DATA_PTR;
#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 },
{ USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0 },
@ -205,31 +206,9 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
int i;
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");
board_serdes_map[0].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[0].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[0].serdes_type = SGMII0;
board_serdes_map[1].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[1].serdes_mode = PEX_ROOT_COMPLEX_X1;
board_serdes_map[1].serdes_type = USB3_HOST0;
board_serdes_map[2].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[2].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[2].serdes_type = SGMII1;
board_serdes_map[3].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[3].serdes_mode = PEX_ROOT_COMPLEX_X1;
board_serdes_map[3].serdes_type = PEX3;
board_serdes_map[4].serdes_speed = SERDES_SPEED_5_GBPS;
board_serdes_map[4].serdes_mode = PEX_ROOT_COMPLEX_X1;
board_serdes_map[4].serdes_type = PEX2;
board_serdes_map[5].serdes_speed = SERDES_SPEED_1_25_GBPS;
board_serdes_map[5].serdes_mode = SERDES_DEFAULT_MODE;
board_serdes_map[5].serdes_type = SGMII2;
} else {
for (i = 0; i < ARRAY_SIZE(board_serdes_map); i++) {
enum serdes_type type;
@ -243,7 +222,6 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
type = bd_get_serdes_type(i);
}
/* Do not touch serdes */
if (type < LAST_SERDES_TYPE) {
if ((type >= SGMII0) && (type <= SGMII2)) {
board_serdes_map[i].serdes_speed = SERDES_SPEED_1_25_GBPS;
@ -256,7 +234,12 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
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 == DEFAULT_SERDES)) {
}
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 {
@ -653,7 +636,7 @@ static void set_phy_fast_blink_mode(int phy_addr)
static void set_devicetree_name(void)
{
char devicetreename[64];
/* add hardware versions to environment */
if (bd_get_devicetree(devicetreename, sizeof(devicetreename)) != 0) {
printf("Devicetree name not found, use legacy name\n");
strcpy(devicetreename, "armada-385-nbhw18-prod1.dtb");
@ -673,9 +656,7 @@ int board_late_init(void)
find_and_set_active_partition();
pass_hw_rev();
/* Todo: It seems that something with the network is wrong */
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 */
@ -688,7 +669,9 @@ int board_late_init(void)
set_devicetree_name();
set_mac_addresses(3);
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);

View File

@ -7,6 +7,7 @@
#include <asm/io.h>
#include <errno.h>
#include "../common/nbhw_bd.h"
#include "../common/nbhw_sim.h"
DECLARE_GLOBAL_DATA_PTR;
@ -150,6 +151,8 @@ 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++) {

View File

@ -1,14 +1,14 @@
#include <common.h>
#include <nbhw.h>
#include "../common/nbhw_fpga_prog.h"
#include "nbhw18_fpga_regs.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 > 3) {
if (sim > 1) {
printf("Invalid sim %d selected, can't connect slot %d\n", sim, slot);
return;
}
@ -32,4 +32,3 @@ void connect_sim_to_slot(int sim, int slot) {
FPGA_REG(SIM_CTRL) = sim_ctrl;
}

View File

@ -791,7 +791,9 @@ static const init_fnc_t init_sequence_f[] = {
env_init, /* initialize environment */
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
#if !defined(CONFIG_PRE_CONSOLE_BUFFER)
console_init_f, /* stage 1 init of console */
#endif
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SH) || \

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_HW14=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="armada-385-hw14-spl"
CONFIG_SMBIOS_PRODUCT_NAME="hw14"
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-hw14-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-hw14-spl armada-385-hw14"
CONFIG_MULTI_DTB_FIT=y
CONFIG_DM_GPIO=y
CONFIG_DM_PCA953X=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_CMD_EEPROM=y
CONFIG_ENV_IS_IN_EEPROM=y
CONFIG_WDT=y
CONFIG_WDT_ORION=y

View File

@ -7,11 +7,18 @@ CONFIG_TARGET_NM_NBHW17_V1=y
CONFIG_SPL_MMC_SUPPORT=y
CONFIG_SPL_SERIAL_SUPPORT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
CONFIG_DEFAULT_DEVICE_TREE="armada-385-nbhw17-v1"
CONFIG_DEFAULT_FDT_FILE="armada-385-nbhw17-v1"
CONFIG_DEFAULT_DEVICE_TREE="armada-385-nbhw17-v1-spl"
CONFIG_SMBIOS_PRODUCT_NAME="hw17"
CONFIG_FIT=y
CONFIG_FIT_ENABLE_SHA256_SUPPORT=y
CONFIG_BOOTDELAY=3
CONFIG_BOOTSTAGE_STASH_SIZE=4096
CONFIG_SYS_CONSOLE_INFO_QUIET=y
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-nbhw17-v1-spl"
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SPL=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x190
@ -19,6 +26,7 @@ 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
@ -40,17 +48,19 @@ 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-nbhw17-v1-spl armada-385-nbhw17-v1"
CONFIG_MULTI_DTB_FIT=y
CONFIG_DM_GPIO=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=y
CONFIG_DEBUG_UART_BASE=0xd0012000
CONFIG_DEBUG_UART_CLOCK=250000000
CONFIG_DEBUG_UART_SHIFT=2
# CONFIG_DEBUG_UART is not set
# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_DM_USB=y
@ -58,4 +68,7 @@ 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

@ -83,7 +83,11 @@ static int pca953x_write_single(struct udevice *dev, int reg, u8 val,
int off = offset / BANK_SZ;
int ret = 0;
#ifdef CONFIG_DM_I2C
ret = dm_i2c_write(dev, (reg << bank_shift) + off, &val, 1);
#else
ret = i2c_write(info->addr, (reg << bank_shift) + off, 1, &val, 1);
#endif
if (ret) {
dev_err(dev, "%s error\n", __func__);
return ret;
@ -101,7 +105,11 @@ static int pca953x_read_single(struct udevice *dev, int reg, u8 *val,
int ret;
u8 byte;
#ifdef CONFIG_DM_I2C
ret = dm_i2c_read(dev, (reg << bank_shift) + off, &byte, 1);
#else
ret = i2c_read(info->addr, (reg << bank_shift) + off, 1, &byte, 1);
#endif
if (ret) {
dev_err(dev, "%s error\n", __func__);
return ret;
@ -118,12 +126,24 @@ static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val)
int ret = 0;
if (info->gpio_count <= 8) {
#ifdef CONFIG_DM_I2C
ret = dm_i2c_read(dev, reg, val, 1);
#else
ret = i2c_read(info->addr, reg, 1, val, 1);
#endif
} else if (info->gpio_count <= 16) {
#ifdef CONFIG_DM_I2C
ret = dm_i2c_read(dev, reg << 1, val, info->bank_count);
#else
ret = i2c_read(info->addr, reg << 1, 1, val, info->bank_count);
#endif
} else if (info->gpio_count == 40) {
/* Auto increment */
#ifdef CONFIG_DM_I2C
ret = dm_i2c_read(dev, (reg << 3) | 0x80, val, info->bank_count);
#else
ret = i2c_read(info->addr, (reg << 3) | 0x80, 1, val, info->bank_count);
#endif
} else {
dev_err(dev, "Unsupported now\n");
return -EINVAL;

View File

@ -1372,6 +1372,8 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
case PHY_INTERFACE_MODE_RGMII_ID:
ctrl |= MVNETA_GMAC2_PORT_RGMII;
break;
case PHY_INTERFACE_MODE_MII:
break;
default:
return -EINVAL;
}

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=openwrt-nbhw14-sgmii.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; 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=ttyS0\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; run add_version_bootargs; 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 xilinx 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 */

View File

@ -43,11 +43,28 @@
/* USB/EHCI configuration */
#define CONFIG_EHCI_IS_TDI
/* Environment in SPI NOR flash */
#define CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */
#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */
#define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */
/* 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 */
@ -58,9 +75,20 @@
#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"
@ -78,14 +106,14 @@
"eth1addr=00:11:22:33:44:55\0" \
"eth2addr=00:11:22:33:44:56\0" \
"ethact=ethernet@30000\0" \
"add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 console=ttyS1,115200 rootwait\0" \
"add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 rootwait; 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 echo Load FPGA...; nbhw_wlan_fixup &&" \
"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; " \
@ -103,14 +131,15 @@
"tftptimeoutcountmax=5\0" \
"bootpretryperiod=2000\0" \
"autoload=false\0" \
"tftp_recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; setenv bootargs rdinit=/etc/preinit console=ttyO1,115200 debug; bootz $kernel_addr - $fdt_addr\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; run add_version_bootargs; 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 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
@ -134,6 +163,7 @@
#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_MALLOC_SIMPLE
#define CONFIG_OF_STDOUT_VIA_ALIAS
#endif
#define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10))
@ -165,11 +195,27 @@
/*
* 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 */

3
include/configs/armada-385-nbhw18-v2.h Executable file → Normal file
View File

@ -112,7 +112,7 @@
"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 console=$consoledev,115200 rootwait loglevel=4\0" \
"add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 rootwait 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 && " \
@ -138,6 +138,7 @@
"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" \

View File

@ -6,7 +6,8 @@
* SPDX-License-Identifier: LGPL-2.1+
*/
#ifndef _LIBFDT_ENV_H
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
#define _LIBFDT_ENV_H
#include "compiler.h"
@ -32,4 +33,4 @@ typedef __be64 fdt64_t;
/* adding a ramdisk needs 0x44 bytes in version 2008.10 */
#define FDT_RAMDISK_OVERHEAD 0x80
#endif /* _LIBFDT_ENV_H */
#endif /* LIBFDT_ENV_H */

View File

@ -12,12 +12,6 @@
#include <linux/types.h>
#include <linux/bitops.h>
/*
* deal with unrepresentable constant logarithms
*/
extern __attribute__((const, noreturn))
int ____ilog2_NaN(void);
/*
* non-constant log of base 2 calculators
* - the arch may override these in asm/bitops.h if they can be implemented
@ -40,19 +34,23 @@ int __ilog2_u64(u64 n)
}
#endif
/*
* Determine whether some value is a power of two, where zero is
/**
* is_power_of_2() - check if a value is a power of two
* @n: the value to check
*
* Determine whether some value is a power of two, where zero is
* *not* considered a power of two.
* Return: true if @n is a power of 2, otherwise false.
*/
static inline __attribute__((const))
bool is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
/*
* round up to nearest power of two
/**
* __roundup_pow_of_two() - round up to nearest power of two
* @n: value to round up
*/
static inline __attribute__((const))
unsigned long __roundup_pow_of_two(unsigned long n)
@ -60,8 +58,9 @@ unsigned long __roundup_pow_of_two(unsigned long n)
return 1UL << fls_long(n - 1);
}
/*
* round down to nearest power of two
/**
* __rounddown_pow_of_two() - round down to nearest power of two
* @n: value to round down
*/
static inline __attribute__((const))
unsigned long __rounddown_pow_of_two(unsigned long n)
@ -70,19 +69,19 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
}
/**
* ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
* @n - parameter
* ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
* @n: parameter
*
* constant-capable log of base 2 calculation
* - this can be used to initialise global variables from constant data, hence
* the massive ternary operator construction
* the massive ternary operator construction
*
* selects the appropriately-sized optimised version depending on sizeof(n)
*/
#define ilog2(n) \
( \
__builtin_constant_p(n) ? ( \
(n) < 1 ? ____ilog2_NaN() : \
(n) < 2 ? 0 : \
(n) & (1ULL << 63) ? 63 : \
(n) & (1ULL << 62) ? 62 : \
(n) & (1ULL << 61) ? 61 : \
@ -145,10 +144,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
(n) & (1ULL << 4) ? 4 : \
(n) & (1ULL << 3) ? 3 : \
(n) & (1ULL << 2) ? 2 : \
(n) & (1ULL << 1) ? 1 : \
(n) & (1ULL << 0) ? 0 : \
____ilog2_NaN() \
) : \
1) : \
(sizeof(n) <= 4) ? \
__ilog2_u32(n) : \
__ilog2_u64(n) \
@ -156,7 +152,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
/**
* roundup_pow_of_two - round the given value up to nearest power of two
* @n - parameter
* @n: parameter
*
* round the given value up to the nearest power of two
* - the result is undefined when n == 0
@ -173,7 +169,7 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
/**
* rounddown_pow_of_two - round the given value down to nearest power of two
* @n - parameter
* @n: parameter
*
* round the given value down to the nearest power of two
* - the result is undefined when n == 0
@ -186,6 +182,12 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
__rounddown_pow_of_two(n) \
)
static inline __attribute_const__
int __order_base_2(unsigned long n)
{
return n > 1 ? ilog2(n - 1) + 1 : 0;
}
/**
* order_base_2 - calculate the (rounded up) base 2 order of the argument
* @n: parameter
@ -199,7 +201,11 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
* ob2(5) = 3
* ... and so on.
*/
#define order_base_2(n) ilog2(roundup_pow_of_two(n))
#define order_base_2(n) \
( \
__builtin_constant_p(n) ? ( \
((n) == 0 || (n) == 1) ? 0 : \
ilog2((n) - 1) + 1) : \
__order_base_2(n) \
)
#endif /* _LINUX_LOG2_H */

View File

@ -1,26 +1,19 @@
#include <common.h>
#include <u-boot/sha256.h>
#include <malloc.h>
#include <linux/types.h>
/* The crypt source code was ported from busybox sources pw_crypt */
/* Used by pw_encrypt_XXX.c */
static const uint8_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static char*
to64(char *s, unsigned v, int n)
{
while (--n >= 0) {
*s++ = ascii64[v & 0x3f];
v >>= 6;
}
return s;
}
/*
* The crypt source code was ported from busybox sources pw_crypt, file
* libbb/pw_encrypt_sha.c
*
* 20191108rs: Update to Busybox commit 49ecee0 (Jan 24, 2017)
* Major cleanup, provide missing functions
*/
/* SHA256 and SHA512-based Unix crypt implementation.
* Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
*/
#include <common.h>
#include <u-boot/sha256.h>
#include <malloc.h>
#include <linux/types.h>
/* Prefix for optional rounds specification. */
static const char str_rounds[] = "rounds=%u$";
@ -33,50 +26,98 @@ static const char str_rounds[] = "rounds=%u$";
/* Maximum number of rounds. */
#define ROUNDS_MAX 999999999
char *sha_crypt(const char *key_data, const char *salt_data)
/* Missing busybox functions */
static char* to64(char *s, unsigned v, int n)
{
static const uint8_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
while (--n >= 0) {
*s++ = ascii64[v & 0x3f];
v >>= 6;
}
return s;
}
void* xzalloc(size_t size)
{
void *ptr = malloc(size);
/* note: error check left out */
memset(ptr, 0, size);
return ptr;
}
static char *xstrdup(const char *s)
{
size_t len = strlen (s) + 1;
char *ret = malloc (len);
/* note: error check left out */
memcpy (ret, s, len);
return ret;
}
#if 0 /* currently not required, see note below */
static char *xstrndup(const char *s, size_t n)
{
char *result;
size_t len = strlen (s);
if (n < len)
len = n;
printf("allocating %d bytes\n", len+1);
result = malloc (len + 1);
/* note: error check left out */
result[len] = '\0';
memcpy (result, s, len);
return (char *)result;
}
#endif
char *sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
{
void (*sha_begin)(void *ctx);
void (*sha_hash)(void *ctx, const void *buffer, size_t len);
void* (*sha_end)( void *ctx, void *resbuf);
void (*sha_end)(void *ctx, void *resbuf);
int _32or64;
char *result, *resptr;
/* btw, sha256 needs [32] and uint32_t only */
unsigned char alt_result[64] __attribute__((__aligned__(__alignof__(uint64_t))));
unsigned char temp_result[64] __attribute__((__aligned__(__alignof__(uint64_t))));
union {
sha256_context x;
#if 0
sha512_ctx_t y;
#endif
} ctx;
union {
sha256_context x;
#if 0
sha512_ctx_t y;
#endif
} alt_ctx;
struct {
unsigned char alt_result[64];
unsigned char temp_result[64];
union {
sha256_context x;
/* sha512_ctx_t y; */
} ctx;
union {
sha256_context x;
/* sha512_ctx_t y; */
} alt_ctx;
} L;
#define alt_result (L.alt_result )
#define temp_result (L.temp_result)
#define ctx (L.ctx )
#define alt_ctx (L.alt_ctx )
unsigned salt_len;
unsigned key_len;
unsigned cnt;
unsigned rounds;
char *cp;
char is_sha512;
char *tmp;
/* Analyze salt, construct already known part of result */
cnt = strlen(salt_data) + 1 + 43 + 1;
is_sha512 = salt_data[1];
if (is_sha512 == '6') {
printf("SHA-512 is not supported yet");
return 0;
/* cnt += 43; */
}
result = resptr = malloc(cnt); /* will provide NUL terminator */
memset(result, 0, cnt);
_32or64 = 32;
if (salt_data[1] == '6') { /* sha512 */
_32or64 *= 2; /*64*/
cnt += 43;
puts("SHA-512 is not supported");
return 0;
}
result = resptr = xzalloc(cnt); /* will provide NUL terminator */
*resptr++ = '$';
*resptr++ = is_sha512;
*resptr++ = salt_data[1];
*resptr++ = '$';
rounds = ROUNDS_DEFAULT;
salt_data += 3;
@ -95,50 +136,41 @@ char *sha_crypt(const char *key_data, const char *salt_data)
resptr += sprintf(resptr, str_rounds, rounds);
}
}
{
char *salt_end = strchr(salt_data, '$');
if (salt_end != 0) {
salt_len = salt_end - salt_data;
}
else {
salt_len = strnlen(salt_data, SALT_LEN_MAX);
}
}
// salt_len = (int)strchrnul(salt_data, '$') - (int)salt_data;
salt_len = (int)strchrnul(salt_data, '$') - (int)salt_data;
if (salt_len > SALT_LEN_MAX)
salt_len = SALT_LEN_MAX;
/* xstrdup assures suitable alignment; also we will use it
as a scratch space later. */
tmp = malloc(strnlen(salt_data, 128));
memcpy(tmp, salt_data, strnlen(salt_data, 128));
salt_data = tmp;
//salt_data = xstrndup(salt_data, salt_len);
/* NOTE: Something is wrong here.
* when <salt_len> bytes are reserved there is a problem later in
* the code and computations are incorrect.
* So far it is not clear what the root problem is.
* By not truncating the buffer the code works fine
*/
/* salt_data = xstrndup(salt_data, salt_len); */
salt_data = xstrdup(salt_data);
/* add "salt$" to result */
strcpy(resptr, salt_data);
resptr += salt_len;
*resptr++ = '$';
/* key data doesn't need much processing */
key_len = strlen(key_data);
tmp = malloc(strnlen(key_data, 256));
memcpy(tmp, key_data, strnlen(key_data, 256));
key_data = tmp;
// key_data = xstrdup(key_data);
key_data = xstrdup(key_data);
/* Which flavor of SHAnnn ops to use? */
sha_begin = (void*)sha256_starts;
sha_hash = (void*)sha256_update;
sha_end = (void*)sha256_finish;
_32or64 = 32;
/* Not supported */
#if 0
if (is_sha512 == '6') {
/* SHA512 not supported */
if (_32or64 != 32) {
sha_begin = (void*)sha512_begin;
sha_hash = (void*)sha512_hash;
sha_end = (void*)sha512_end;
_32or64 = 64;
}
#endif
/* Add KEY, SALT. */
sha_begin(&ctx);
sha_hash(&ctx, key_data, key_len);
@ -230,35 +262,30 @@ char *sha_crypt(const char *key_data, const char *salt_data)
sha_end(&ctx, alt_result);
}
/* Append encrypted password to result buffer */
//TODO: replace with something like
// bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64);
#define b64_from_24bit(B2, B1, B0, N) \
do { \
unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \
resptr = to64(resptr, w, N); \
do { \
unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \
resptr = to64(resptr, w, N); \
} while (0)
if (is_sha512 == '5') {
if (_32or64 == 32) { /* sha256 */
unsigned i = 0;
unsigned j = 10;
unsigned k = 20;
/* strange swap of one byte (see below why) */
unsigned char alt_result_31 = alt_result[31];
alt_result[31] = alt_result[1];
while (1) {
unsigned j = i + 10;
unsigned k = i + 20;
if (j >= 30) j -= 30;
if (k >= 30) k -= 30;
b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4);
if (i == 9)
if (k == 29)
break;
i += 21; i = (((i >> 4) & 2) + i) & 0x1f;
j += 21; j = (((j >> 4) & 2) + j) & 0x1f;
k += 21; k = (((k >> 4) & 2) + k) & 0x1f;
i = k + 1;
}
b64_from_24bit(0, alt_result_31, alt_result[30], 3);
b64_from_24bit(0, alt_result[31], alt_result[30], 3);
/* was:
b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4);
b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4);
...............................^^^^^^^^^^^^^ why [1] and not [31]?
b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4);
b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4);
b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4);
@ -271,15 +298,15 @@ do { \
*/
} else {
unsigned i = 0;
unsigned j = 21;
unsigned k = 42;
while (1) {
unsigned j = i + 21;
unsigned k = i + 42;
if (j >= 63) j -= 63;
if (k >= 63) k -= 63;
b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4);
if (i == 62)
if (j == 20)
break;
i += 22; i = ((i >> 6) + i) & 0x3f;
j += 22; j = ((j >> 6) + j) & 0x3f;
k += 22; k = ((k >> 6) + k) & 0x3f;
i = j + 1;
}
b64_from_24bit(0, 0, alt_result[63], 2);
/* was:
@ -309,21 +336,19 @@ do { \
}
/* *resptr = '\0'; - xzalloc did it */
#undef b64_from_24bit
/* Clear the buffer for the intermediate result so that people
attaching to processes or reading core dumps cannot get any
information. */
memset(temp_result, 0, sizeof(temp_result));
memset(alt_result, 0, sizeof(alt_result));
memset(&ctx, 0, sizeof(ctx));
memset(&alt_ctx, 0, sizeof(alt_ctx));
memset(&L, 0, sizeof(L)); /* [alt]_ctx and XXX_result buffers */
memset(key_data, 0, key_len); /* also p_bytes */
memset(salt_data, 0, salt_len); /* also s_bytes */
free(key_data);
free(salt_data);
#undef p_bytes
#undef s_bytes
return result;
#undef alt_result
#undef temp_result
#undef ctx
#undef alt_ctx
}

View File

@ -743,7 +743,7 @@ int conf_write(const char *name)
struct menu *menu;
const char *basename;
const char *str;
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
char dirname[PATH_MAX+1], tmpname[PATH_MAX+14], newname[PATH_MAX+8];
char *env;
dirname[0] = 0;