From 90bcc3d38d2b1159e1b80da050f6163e5c3f575d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:40 +0200 Subject: driver/ddr: Add support for setting timing in hws_topology_map The DDR3 training code for Marvell A38X currently computes 1t timing when given board topology map of the Turris Omnia, but Omnia needs 2t. This patch adds support for enforcing the 2t timing in struct hws_topology_map, through a new enum hws_timing, which can assume following values: HWS_TIM_DEFAULT - default behaviour, compute whether to enable 2t from the number of CSs HWS_TIM_1T - enforce 1t HWS_TIM_2T - enforce 2t This patch also sets all the board topology maps (db-88f6820-amc, db-88f6820-gp, controlcenterdc and clearfog) to have timing set to HWS_TIM_DEFAULT. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese diff --git a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c index cade99c..40fa599 100644 --- a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c +++ b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c @@ -69,7 +69,8 @@ static struct hws_topology_map board_topology_map = { MEM_4G, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_l cas_wl */ - HWS_TEMP_LOW} }, /* temperature */ + HWS_TEMP_LOW, /* temperature */ + HWS_TIM_DEFAULT} }, /* timing */ 5, /* Num Of Bus Per Interface*/ BUS_MASK_32BIT /* Busses mask */ }; diff --git a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c index e700781..a1974cb 100644 --- a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c +++ b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c @@ -90,7 +90,8 @@ static struct hws_topology_map board_topology_map = { MEM_4G, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_l cas_wl */ - HWS_TEMP_LOW} }, /* temperature */ + HWS_TEMP_LOW, /* temperature */ + HWS_TIM_DEFAULT} }, /* timing */ 5, /* Num Of Bus Per Interface*/ BUS_MASK_32BIT /* Busses mask */ }; diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c index f0efb53..32168d3 100644 --- a/board/gdsys/a38x/controlcenterdc.c +++ b/board/gdsys/a38x/controlcenterdc.c @@ -53,7 +53,8 @@ static struct hws_topology_map ddr_topology_map = { MEM_4G, /* mem_size */ DDR_FREQ_533, /* frequency */ 0, 0, /* cas_l cas_wl */ - HWS_TEMP_LOW} }, /* temperature */ + HWS_TEMP_LOW, /* temperature */ + HWS_TIM_DEFAULT} }, /* timing */ 5, /* Num Of Bus Per Interface*/ BUS_MASK_32BIT /* Busses mask */ }; diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index 3a8257c..8906636 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -83,7 +83,8 @@ static struct hws_topology_map board_topology_map = { MEM_4G, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_l cas_wl */ - HWS_TEMP_LOW} }, /* temperature */ + HWS_TEMP_LOW, /* temperature */ + HWS_TIM_DEFAULT} }, /* timing */ 5, /* Num Of Bus Per Interface*/ BUS_MASK_32BIT /* Busses mask */ }; diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index 7e0749f..e70ca4b 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training.c +++ b/drivers/ddr/marvell/a38x/ddr3_training.c @@ -308,6 +308,7 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ enum hws_speed_bin speed_bin_index = SPEED_BIN_DDR_2133N; enum hws_mem_size memory_size = MEM_2G; enum hws_ddr_freq freq = init_freq; + enum hws_timing timing; u32 cs_mask = 0; u32 cl_value = 0, cwl_val = 0; u32 refresh_interval_cnt = 0, bus_cnt = 0, adll_tap = 0; @@ -569,8 +570,13 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ DUNIT_CONTROL_HIGH_REG, (init_cntr_prm->msys_init << 7), (1 << 7))); + timing = tm->interface_params[if_id].timing; + if (mode2_t != 0xff) { t2t = mode2_t; + } else if (timing != HWS_TIM_DEFAULT) { + /* Board topology map is forcing timing */ + t2t = (timing == HWS_TIM_2T) ? 1 : 0; } else { /* calculate number of CS (per interface) */ CHECK_STATUS(calc_cs_num diff --git a/drivers/ddr/marvell/a38x/ddr_topology_def.h b/drivers/ddr/marvell/a38x/ddr_topology_def.h index f8894e8..229c3a1 100644 --- a/drivers/ddr/marvell/a38x/ddr_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr_topology_def.h @@ -37,6 +37,12 @@ enum hws_mem_size { MEM_SIZE_LAST }; +enum hws_timing { + HWS_TIM_DEFAULT, + HWS_TIM_1T, + HWS_TIM_2T +}; + struct bus_params { /* Chip Select (CS) bitmask (bits 0-CS0, bit 1- CS1 ...) */ u8 cs_bitmask; @@ -84,6 +90,9 @@ struct if_params { /* operation temperature */ enum hws_temperature interface_temp; + + /* 2T vs 1T mode (by default computed from number of CSs) */ + enum hws_timing timing; }; struct hws_topology_map { -- cgit v0.10.2 From 2ab7704a6d2b27f86c334b52745e940042f8cd6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:41 +0200 Subject: orion_wdt: Support for the Orion Watchdog The Orion watchdog can be found on some Marvell Armada chips. This driver is based on the code by Tomas Hlavacek in the CZ.NIC turris-omnia-uboot repository, which can be found at https://gitlab.labs.nic.cz/turris/turris-omnia-uboot, and that one is based on code by Sylver Bruneau. His code is already in mainline Linux kernel. The code uses the new driver model API. Signed-off-by: Tomas Hlavacek Signed-off-by: Marek Behun create mode 100644 drivers/watchdog/orion_wdt.c Signed-off-by: Stefan Roese diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b911233..d360a17 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -62,4 +62,11 @@ config WDT_BCM6345 The watchdog timer is stopped when initialized. It performs full SoC reset. +config WDT_ORION + bool "Orion watchdog timer support" + depends on WDT + help + Select this to enable Orion watchdog timer, which can be found on some + Marvell Armada chips. + endmenu diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 4b19e4c..3230cbb 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o +obj-$(CONFIG_WDT_ORION) += orion_wdt.o diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c new file mode 100644 index 0000000..a0df02d --- /dev/null +++ b/drivers/watchdog/orion_wdt.c @@ -0,0 +1,177 @@ +/* + * drivers/watchdog/orion_wdt.c + * + * Watchdog driver for Orion/Kirkwood processors + * + * Authors: Tomas Hlavacek + * Sylver Bruneau + * Marek Behun + * + * 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 +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct orion_wdt_priv { + void __iomem *reg; + int wdt_counter_offset; + void __iomem *rstout; + void __iomem *rstout_mask; + u32 timeout; +}; + +#define RSTOUT_ENABLE_BIT BIT(8) +#define RSTOUT_MASK_BIT BIT(10) +#define WDT_ENABLE_BIT BIT(8) + +#define TIMER_CTRL 0x0000 +#define TIMER_A370_STATUS 0x04 + +#define WDT_AXP_FIXED_ENABLE_BIT BIT(10) +#define WDT_A370_EXPIRED BIT(31) + +static int orion_wdt_reset(struct udevice *dev) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + + /* Reload watchdog duration */ + writel(priv->timeout, priv->reg + priv->wdt_counter_offset); + + return 0; +} + +static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + u32 reg; + + priv->timeout = (u32) timeout; + + /* Enable the fixed watchdog clock input */ + reg = readl(priv->reg + TIMER_CTRL); + reg |= WDT_AXP_FIXED_ENABLE_BIT; + writel(reg, priv->reg + TIMER_CTRL); + + /* Set watchdog duration */ + writel(priv->timeout, priv->reg + priv->wdt_counter_offset); + + /* Clear the watchdog expiration bit */ + reg = readl(priv->reg + TIMER_A370_STATUS); + reg &= ~WDT_A370_EXPIRED; + writel(reg, priv->reg + TIMER_A370_STATUS); + + /* Enable watchdog timer */ + reg = readl(priv->reg + TIMER_CTRL); + reg |= WDT_ENABLE_BIT; + writel(reg, priv->reg + TIMER_CTRL); + + /* Enable reset on watchdog */ + reg = readl(priv->rstout); + reg |= RSTOUT_ENABLE_BIT; + writel(reg, priv->rstout); + + reg = readl(priv->rstout_mask); + reg &= ~RSTOUT_MASK_BIT; + writel(reg, priv->rstout_mask); + + return 0; +} + +static int orion_wdt_stop(struct udevice *dev) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + u32 reg; + + /* Disable reset on watchdog */ + reg = readl(priv->rstout_mask); + reg |= RSTOUT_MASK_BIT; + writel(reg, priv->rstout_mask); + + reg = readl(priv->rstout); + reg &= ~RSTOUT_ENABLE_BIT; + writel(reg, priv->rstout); + + /* Disable watchdog timer */ + reg = readl(priv->reg + TIMER_CTRL); + reg &= ~WDT_ENABLE_BIT; + writel(reg, priv->reg + TIMER_CTRL); + + return 0; +} + +static inline bool save_reg_from_ofdata(struct udevice *dev, int index, + void __iomem **reg, int *offset) +{ + fdt_addr_t addr; + fdt_size_t off; + + addr = fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true); + + if (addr == FDT_ADDR_T_NONE) + return false; + + *reg = (void __iomem *) addr; + if (offset) + *offset = off; + + return true; +} + +static int orion_wdt_ofdata_to_platdata(struct udevice *dev) +{ + struct orion_wdt_priv *priv = dev_get_priv(dev); + + if (!save_reg_from_ofdata(dev, 0, &priv->reg, + &priv->wdt_counter_offset)) + goto err; + + if (!save_reg_from_ofdata(dev, 1, &priv->rstout, NULL)) + goto err; + + if (!save_reg_from_ofdata(dev, 2, &priv->rstout_mask, NULL)) + goto err; + + return 0; +err: + debug("%s: Could not determine Orion wdt IO addresses\n", __func__); + return -ENXIO; +} + +static int orion_wdt_probe(struct udevice *dev) +{ + debug("%s: Probing wdt%u\n", __func__, dev->seq); + orion_wdt_stop(dev); + + return 0; +} + +static const struct wdt_ops orion_wdt_ops = { + .start = orion_wdt_start, + .reset = orion_wdt_reset, + .stop = orion_wdt_stop, +}; + +static const struct udevice_id orion_wdt_ids[] = { + { .compatible = "marvell,armada-380-wdt" }, + {} +}; + +U_BOOT_DRIVER(orion_wdt) = { + .name = "orion_wdt", + .id = UCLASS_WDT, + .of_match = orion_wdt_ids, + .probe = orion_wdt_probe, + .priv_auto_alloc_size = sizeof(struct orion_wdt_priv), + .ofdata_to_platdata = orion_wdt_ofdata_to_platdata, + .ops = &orion_wdt_ops, +}; -- cgit v0.10.2 From c2502e7b82b68945ef89569e7555add30189e976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:42 +0200 Subject: arch/arm/dts: Add Turris Omnia device tree This device tree is taken from mainline Linux kernel commit 7b7db5ab. Added is also a -u-boot.dtsi file with these additions: - aliases for I2C and SPI devices are added, because i2cmux and SPI flash doesn't work otherwise - spi_flash node has been added so that the new DM API works - the ATSHA204A node is added in the i2c@5 node - "u-boot,dm-pre-reloc"s are added in needed nodes for SPL build to work correctly Signed-off-by: Marek Behun create mode 100644 arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi create mode 100644 arch/arm/dts/armada-385-turris-omnia.dts Signed-off-by: Stefan Roese diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi new file mode 100644 index 0000000..22caf35 --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Marek Behun + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + aliases { + i2c0 = &i2c0; + i2c1 = &i2cmux; + spi0 = &spi0; + }; +}; + +&i2c0 { + u-boot,dm-pre-reloc; + + i2cmux: i2cmux@70 { + u-boot,dm-pre-reloc; + + i2c@0 { + u-boot,dm-pre-reloc; + }; + + i2c@1 { + u-boot,dm-pre-reloc; + }; + + i2c@5 { + u-boot,dm-pre-reloc; + + /* ATSHA204A at address 0x64 */ + atsha204a@64 { + u-boot,dm-pre-reloc; + compatible = "atmel,atsha204a"; + reg = <0x64>; + }; + }; + }; +}; + +&spi0 { + u-boot,dm-pre-reloc; + + spi-flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <40000000>; + u-boot,dm-pre-reloc; + }; +}; + +&uart0 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts new file mode 100644 index 0000000..28eede1 --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia.dts @@ -0,0 +1,392 @@ +/* + * Device Tree file for the Turris Omnia + * + * Copyright (C) 2016 Uwe Kleine-König + * Copyright (C) 2016 Tomas Hlavacek + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf + */ + +/dts-v1/; + +#include +#include +#include "armada-385.dtsi" + +/ { + model = "Turris Omnia"; + compatible = "cznic,turris-omnia", "marvell,armada385", "marvell,armada380"; + + chosen { + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1024 MB */ + }; + + soc { + ranges = ; + + internal-regs { + + /* USB part of the PCIe2/USB 2.0 port */ + usb@58000 { + status = "okay"; + }; + + sata@a8000 { + status = "okay"; + }; + + sdhci@d8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + status = "okay"; + + bus-width = <8>; + no-1-8-v; + non-removable; + }; + + usb3@f0000 { + status = "okay"; + }; + + usb3@f8000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + + pcie@3,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + }; + }; +}; + +/* Connected to 88E6176 switch, port 6 */ +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +/* Connected to 88E6176 switch, port 5 */ +ð1 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +/* WAN port */ +ð2 { + status = "okay"; + phy-mode = "sgmii"; + phy = <&phy1>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + i2cmux@70 { + compatible = "nxp,pca9547"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + status = "okay"; + + i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + /* STM32F0 command interface at address 0x2a */ + /* leds device (in STM32F0) at address 0x2b */ + + eeprom@54 { + compatible = "at,24c64"; + reg = <0x54>; + + /* The EEPROM contains data for bootloader. + * Contents: + * struct omnia_eeprom { + * u32 magic; (=0x0341a034 in LE) + * u32 ramsize; (in GiB) + * char regdomain[4]; + * u32 crc32; + * }; + */ + }; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + /* routed to PCIe0/mSATA connector (CN7A) */ + }; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; + + /* routed to PCIe1/USB2 connector (CN61A) */ + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + /* routed to PCIe2 connector (CN62A) */ + }; + + i2c@4 { + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; + + /* routed to SFP+ */ + }; + + i2c@5 { + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; + + /* ATSHA204A at address 0x64 */ + }; + + i2c@6 { + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; + + /* exposed on pin header */ + }; + + i2c@7 { + #address-cells = <1>; + #size-cells = <0>; + reg = <7>; + + pcawan: gpio@71 { + /* + * GPIO expander for SFP+ signals and + * and phy irq + */ + compatible = "nxp,pca9538"; + reg = <0x71>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcawan_pins>; + + interrupt-parent = <&gpio1>; + interrupts = <14 IRQ_TYPE_LEVEL_LOW>; + + gpio-controller; + #gpio-cells = <2>; + }; + }; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + phy1: phy@1 { + status = "okay"; + compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22"; + reg = <1>; + + /* irq is connected to &pcawan pin 7 */ + }; + + /* Switch MV88E6176 at address 0x10 */ + switch@10 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + dsa,member = <0 0>; + + reg = <0x10>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + ports@0 { + reg = <0>; + label = "lan0"; + }; + + ports@1 { + reg = <1>; + label = "lan1"; + }; + + ports@2 { + reg = <2>; + label = "lan2"; + }; + + ports@3 { + reg = <3>; + label = "lan3"; + }; + + ports@4 { + reg = <4>; + label = "lan4"; + }; + + ports@5 { + reg = <5>; + label = "cpu"; + ethernet = <ð1>; + phy-mode = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + /* port 6 is connected to eth0 */ + }; + }; +}; + +&pinctrl { + pcawan_pins: pcawan-pins { + marvell,pins = "mpp46"; + marvell,function = "gpio"; + }; + + spi0cs0_pins: spi0cs0-pins { + marvell,pins = "mpp25"; + marvell,function = "spi0"; + }; + + spi0cs1_pins: spi0cs1-pins { + marvell,pins = "mpp26"; + marvell,function = "spi0"; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins &spi0cs0_pins>; + status = "okay"; + + spi-nor@0 { + compatible = "spansion,s25fl164k", "jedec,spi-nor"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x00100000>; + label = "U-Boot"; + }; + + partition@100000 { + reg = <0x00100000 0x00700000>; + label = "Rescue system"; + }; + }; + }; + + /* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */ +}; + +&uart0 { + /* Pin header CN10 */ + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&uart1 { + /* Pin header CN11 */ + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; -- cgit v0.10.2 From 8e6eda7cda6c06e173eb5d6430dbe2fec732caf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:43 +0200 Subject: drivers/i2c/muxes/pca954x: Add pca9547 I2C mux support This I2C mux is found, for example, on the Turris Omnia board. Signed-off-by: Marek Behun Reviewed-by: Heiko Schocher Signed-off-by: Stefan Roese diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index 1a67618..383f72f 100644 --- a/drivers/i2c/muxes/pca954x.c +++ b/drivers/i2c/muxes/pca954x.c @@ -13,11 +13,40 @@ DECLARE_GLOBAL_DATA_PTR; +enum pca_type { + PCA9544, + PCA9547, + PCA9548 +}; + +struct chip_desc { + u8 enable; + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi, + } muxtype; +}; + struct pca954x_priv { u32 addr; /* I2C mux address */ u32 width; /* I2C mux width - number of busses */ }; +static const struct chip_desc chips[] = { + [PCA9544] = { + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [PCA9547] = { + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [PCA9548] = { + .enable = 0x8, + .muxtype = pca954x_isswi, + }, +}; + static int pca954x_deselect(struct udevice *mux, struct udevice *bus, uint channel) { @@ -31,7 +60,13 @@ static int pca954x_select(struct udevice *mux, struct udevice *bus, uint channel) { struct pca954x_priv *priv = dev_get_priv(mux); - uchar byte = 1 << channel; + const struct chip_desc *chip = &chips[dev_get_driver_data(mux)]; + uchar byte; + + if (chip->muxtype == pca954x_ismux) + byte = channel | chip->enable; + else + byte = 1 << channel; return dm_i2c_write(mux, priv->addr, &byte, 1); } @@ -42,8 +77,9 @@ static const struct i2c_mux_ops pca954x_ops = { }; static const struct udevice_id pca954x_ids[] = { - { .compatible = "nxp,pca9548", .data = (ulong)8 }, - { .compatible = "nxp,pca9544", .data = (ulong)4 }, + { .compatible = "nxp,pca9544", .data = PCA9544 }, + { .compatible = "nxp,pca9547", .data = PCA9547 }, + { .compatible = "nxp,pca9548", .data = PCA9548 }, { } }; -- cgit v0.10.2 From aa5eb9a3acb7552e715aad48ed0105b7c3d6ed51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:44 +0200 Subject: drivers/misc: Add basic support for ATSHA204A Crypto module This module can be found on the Turris Omnia board connected via the I2C interface. Among some cryptographic functions, the chip has a 512 bit One Time Programmable memory, 88 byte configuration memory and 512 byte general purpose memory. The Turris Omnia stores serial number and device MAC address in the OTP memory. This commit adds basic support for reading the EEPROM and also exposes the chips Random Number Generator. The driver is based on code by Josh Datko, Cryptotronix, jbd@cryptotronix.com and also Tomas Hlavacek, CZ.NIC, tomas.hlavacek@nic.cz Signed-off-by: Tomas Hlavacek Signed-off-by: Marek Behun create mode 100644 drivers/misc/atsha204a-i2c.c create mode 100644 include/atsha204a-i2c.h Signed-off-by: Stefan Roese diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 92f348f..d1ddbbe 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -20,6 +20,14 @@ config ALTERA_SYSID Select this to enable a sysid for Altera devices. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config ATSHA204A + bool "Support for Atmel ATSHA204A module" + depends on MISC + help + Enable support for I2C connected Atmel's ATSHA204A + CryptoAuthentication module found for example on the Turris Omnia + board. + config ROCKCHIP_EFUSE bool "Rockchip e-fuse support" depends on MISC diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index ea64677..10265c8 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_MISC) += misc-uclass.o obj-$(CONFIG_ALI152X) += ali512x.o obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o +obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o obj-$(CONFIG_DS4510) += ds4510.o obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o ifndef CONFIG_SPL_BUILD diff --git a/drivers/misc/atsha204a-i2c.c b/drivers/misc/atsha204a-i2c.c new file mode 100644 index 0000000..934ba5e --- /dev/null +++ b/drivers/misc/atsha204a-i2c.c @@ -0,0 +1,408 @@ +/* + * I2C Driver for Atmel ATSHA204 over I2C + * + * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com + * 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com + * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#define ATSHA204A_TWLO 60 +#define ATSHA204A_TRANSACTION_TIMEOUT 100000 +#define ATSHA204A_TRANSACTION_RETRY 5 +#define ATSHA204A_EXECTIME 5000 + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The ATSHA204A uses an (to me) unknown CRC-16 algorithm. + * The Reveng CRC-16 catalogue does not contain it. + * + * Because in Atmel's documentation only a primitive implementation + * can be found, I have implemented this one with lookup table. + */ + +/* + * This is the code that computes the table below: + * + * int i, j; + * for (i = 0; i < 256; ++i) { + * u8 c = 0; + * for (j = 0; j < 8; ++j) { + * c = (c << 1) | ((i >> j) & 1); + * } + * bitreverse_table[i] = c; + * } + */ + +static u8 const bitreverse_table[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +/* + * This is the code that computes the table below: + * + * int i, j; + * for (i = 0; i < 256; ++i) { + * u16 c = i << 8; + * for (j = 0; j < 8; ++j) { + * int b = c >> 15; + * c <<= 1; + * if (b) + * c ^= 0x8005; + * } + * crc16_table[i] = c; + * } + */ +static u16 const crc16_table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202, +}; + +static inline u16 crc16_byte(u16 crc, const u8 data) +{ + u16 t = crc16_table[((crc >> 8) ^ bitreverse_table[data]) & 0xff]; + return ((crc << 8) ^ t); +} + +static u16 atsha204a_crc16(const u8 *buffer, size_t len) +{ + u16 crc = 0; + + while (len--) + crc = crc16_byte(crc, *buffer++); + + return cpu_to_le16(crc); +} + +static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len) +{ + fdt_addr_t *priv = dev_get_priv(dev); + struct i2c_msg msg; + + msg.addr = *priv; + msg.flags = I2C_M_STOP; + msg.len = len; + msg.buf = (u8 *) buf; + + return dm_i2c_xfer(dev, &msg, 1); +} + +static int atsha204a_recv(struct udevice *dev, u8 *buf, u8 len) +{ + fdt_addr_t *priv = dev_get_priv(dev); + struct i2c_msg msg; + + msg.addr = *priv; + msg.flags = I2C_M_RD | I2C_M_STOP; + msg.len = len; + msg.buf = (u8 *) buf; + + return dm_i2c_xfer(dev, &msg, 1); +} + +static int atsha204a_recv_resp(struct udevice *dev, + struct atsha204a_resp *resp) +{ + int res; + u16 resp_crc, computed_crc; + u8 *p = (u8 *) resp; + + res = atsha204a_recv(dev, p, 4); + if (res) + return res; + + if (resp->length > 4) { + if (resp->length > sizeof(*resp)) + return -EMSGSIZE; + + res = atsha204a_recv(dev, p + 4, resp->length - 4); + if (res) + return res; + } + + resp_crc = (u16) p[resp->length - 2] + | (((u16) p[resp->length - 1]) << 8); + computed_crc = atsha204a_crc16(p, resp->length - 2); + + if (resp_crc != computed_crc) { + debug("Invalid checksum in ATSHA204A response\n"); + return -EBADMSG; + } + + return 0; +} + +int atsha204a_wakeup(struct udevice *dev) +{ + u8 req[4]; + struct atsha204a_resp resp; + int try, res; + + debug("Waking up ATSHA204A\n"); + + for (try = 1; try <= 10; ++try) { + debug("Try %i... ", try); + + memset(req, 0, 4); + res = atsha204a_send(dev, req, 4); + if (res) { + debug("failed on I2C send, trying again\n"); + continue; + } + + udelay(ATSHA204A_TWLO); + + res = atsha204a_recv_resp(dev, &resp); + if (res) { + debug("failed on receiving response, ending\n"); + return res; + } + + if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) { + debug ("failed (responce code = %02x), ending\n", + resp.code); + return -EBADMSG; + } + + debug("success\n"); + break; + } + + return 0; +} + +int atsha204a_idle(struct udevice *dev) +{ + int res; + u8 req = ATSHA204A_FUNC_IDLE; + + res = atsha204a_send(dev, &req, 1); + if (res) + debug("Failed putting ATSHA204A idle\n"); + return res; +} + +int atsha204a_sleep(struct udevice *dev) +{ + int res; + u8 req = ATSHA204A_FUNC_IDLE; + + res = atsha204a_send(dev, &req, 1); + if (res) + debug("Failed putting ATSHA204A to sleep\n"); + return res; +} + +static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req, + struct atsha204a_resp *resp) +{ + int res, timeout = ATSHA204A_TRANSACTION_TIMEOUT; + + res = atsha204a_send(dev, (u8 *) req, req->length + 1); + if (res) { + debug("ATSHA204A transaction send failed\n"); + return -EBUSY; + } + + do { + res = atsha204a_recv_resp(dev, resp); + if (!res || res == -EMSGSIZE || res == -EBADMSG) + break; + + debug("ATSHA204A transaction polling for response " + "(timeout = %d)\n", timeout); + + udelay(ATSHA204A_EXECTIME); + timeout -= ATSHA204A_EXECTIME; + } while (timeout > 0); + + if (timeout <= 0) { + debug("ATSHA204A transaction timed out\n"); + return -ETIMEDOUT; + } + + return res; +} + +static void atsha204a_req_crc32(struct atsha204a_req *req) +{ + u8 *p = (u8 *) req; + u16 computed_crc; + u16 *crc_ptr = (u16 *) &p[req->length - 1]; + + /* The buffer to crc16 starts at byte 1, not 0 */ + computed_crc = atsha204a_crc16(p + 1, req->length - 2); + + *crc_ptr = cpu_to_le16(computed_crc); +} + +int atsha204a_read(struct udevice *dev, enum atsha204a_zone zone, bool read32, + u16 addr, u8 *buffer) +{ + int res, retry = ATSHA204A_TRANSACTION_RETRY; + struct atsha204a_req req; + struct atsha204a_resp resp; + + req.function = ATSHA204A_FUNC_COMMAND; + req.length = 7; + req.command = ATSHA204A_CMD_READ; + + req.param1 = (u8) zone; + if (read32) + req.param1 |= 0x80; + + req.param2 = cpu_to_le16(addr); + + atsha204a_req_crc32(&req); + + do { + res = atsha204a_transaction(dev, &req, &resp); + if (!res) + break; + + debug("ATSHA204A read retry (%d)\n", retry); + retry--; + atsha204a_wakeup(dev); + } while (retry >= 0); + + if (res) { + debug("ATSHA204A read failed\n"); + return res; + } + + if (resp.length != (read32 ? 32 : 4) + 3) { + debug("ATSHA204A read bad response length (%d)\n", + resp.length); + return -EBADMSG; + } + + memcpy(buffer, ((u8 *) &resp) + 1, read32 ? 32 : 4); + + return 0; +} + +int atsha204a_get_random(struct udevice *dev, u8 *buffer, size_t max) +{ + int res; + struct atsha204a_req req; + struct atsha204a_resp resp; + + req.function = ATSHA204A_FUNC_COMMAND; + req.length = 7; + req.command = ATSHA204A_CMD_RANDOM; + + req.param1 = 1; + req.param2 = 0; + + /* We do not have to compute the checksum dynamically */ + req.data[0] = 0x27; + req.data[1] = 0x47; + + res = atsha204a_transaction(dev, &req, &resp); + if (res) { + debug("ATSHA204A random transaction failed\n"); + return res; + } + + memcpy(buffer, ((u8 *) &resp) + 1, max >= 32 ? 32 : max); + return 0; +} + +static int atsha204a_ofdata_to_platdata(struct udevice *dev) +{ + fdt_addr_t *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg"); + if (addr == FDT_ADDR_T_NONE) { + debug("Can't get ATSHA204A I2C base address\n"); + return -ENXIO; + } + + *priv = addr; + return 0; +} + +static const struct udevice_id atsha204a_ids[] = { + { .compatible = "atmel,atsha204a" }, + { } +}; + +U_BOOT_DRIVER(atsha204) = { + .name = "atsha204", + .id = UCLASS_MISC, + .of_match = atsha204a_ids, + .ofdata_to_platdata = atsha204a_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(fdt_addr_t), +}; diff --git a/include/atsha204a-i2c.h b/include/atsha204a-i2c.h new file mode 100644 index 0000000..344fd8a --- /dev/null +++ b/include/atsha204a-i2c.h @@ -0,0 +1,69 @@ +/* + * I2C Driver for Atmel ATSHA204 over I2C + * + * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com + * 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com + * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ATSHA204_I2C_H_ +#define _ATSHA204_I2C_H_ + +enum atsha204a_zone +{ + ATSHA204A_ZONE_CONFIG = 0, + ATSHA204A_ZONE_OTP = 1, + ATSHA204A_ZONE_DATA = 2, +}; + +enum atsha204a_status +{ + ATSHA204A_STATUS_SUCCESS = 0x00, + ATSHA204A_STATUS_MISCOMPARE = 0x01, + ATSHA204A_STATUS_PARSE_ERROR = 0x03, + ATSHA204A_STATUS_EXEC_ERROR = 0x0F, + ATSHA204A_STATUS_AFTER_WAKE = 0x11, + ATSHA204A_STATUS_CRC_ERROR = 0xFF, +}; + +enum atsha204a_func +{ + ATSHA204A_FUNC_RESET = 0x00, + ATSHA204A_FUNC_SLEEP = 0x01, + ATSHA204A_FUNC_IDLE = 0x02, + ATSHA204A_FUNC_COMMAND = 0x03, +}; + +enum atsha204a_cmd +{ + ATSHA204A_CMD_READ = 0x02, + ATSHA204A_CMD_RANDOM = 0x1B, +}; + +struct atsha204a_resp +{ + u8 length; + u8 code; + u8 data[82]; +} __attribute__ ((packed)); + +struct atsha204a_req +{ + u8 function; + u8 length; + u8 command; + u8 param1; + u16 param2; + u8 data[78]; +} __attribute__ ((packed)); + +int atsha204a_wakeup(struct udevice *); +int atsha204a_idle(struct udevice *); +int atsha204a_sleep(struct udevice *); +int atsha204a_read(struct udevice *, enum atsha204a_zone, bool, u16, u8 *); +int atsha204a_get_random(struct udevice *, u8 *, size_t); + +#endif /* _ATSHA204_I2C_H_ */ -- cgit v0.10.2 From b6ee860b87d8accedfb7a1fd5414f7c483603234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Jun 2017 19:28:45 +0200 Subject: marvell: armada385: Add the Turris Omnia board The Turris Omnia is a open-source router created by CZ.NIC. The code is based on the Marvell/db-88f6820-gp by Stefan Roese with modifications from Tomas Hlavacek in the CZ.NIC turris-omnia-uboot repository, which can be found at https://gitlab.labs.nic.cz/turris/turris-omnia-uboot By default, the Turris Omnia uses btrfs as the main and only filesystem, and also loads kernel and device tree from this filesystem. Since U-Boot does not yet support btrfs, you should not flash your Turris Omnia board with this unless you know what you are doing. Signed-off-by: Tomas Hlavacek Signed-off-by: Marek Behun create mode 100644 board/CZ.NIC/turris_omnia/Makefile create mode 100644 board/CZ.NIC/turris_omnia/kwbimage.cfg create mode 100644 board/CZ.NIC/turris_omnia/turris_omnia.c create mode 100644 configs/turris_omnia_defconfig create mode 100644 include/configs/turris_omnia.h Signed-off-by: Stefan Roese diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3e48d58..01d700b 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -92,6 +92,10 @@ config TARGET_DB_88F6820_AMC bool "Support DB-88F6820-AMC" select 88F6820 +config TARGET_TURRIS_OMNIA + bool "Support Turris Omnia" + select 88F6820 + config TARGET_MVEBU_ARMADA_8K bool "Support Armada 7k/8k platforms" select ARMADA_8K @@ -128,6 +132,7 @@ config SYS_BOARD default "db-88f6720" if TARGET_DB_88F6720 default "db-88f6820-gp" if TARGET_DB_88F6820_GP default "db-88f6820-amc" if TARGET_DB_88F6820_AMC + default "turris_omnia" if TARGET_TURRIS_OMNIA default "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 @@ -145,6 +150,7 @@ config SYS_CONFIG_NAME default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM default "theadorable" if TARGET_THEADORABLE + default "turris_omnia" if TARGET_TURRIS_OMNIA config SYS_VENDOR default "Marvell" if TARGET_DB_MV784MP_GP @@ -155,10 +161,26 @@ config SYS_VENDOR default "Marvell" if TARGET_MVEBU_ARMADA_8K default "solidrun" if TARGET_CLEARFOG default "Synology" if TARGET_DS414 + default "CZ.NIC" if TARGET_TURRIS_OMNIA config SYS_SOC default "mvebu" +if TARGET_TURRIS_OMNIA + +choice + prompt "Turris Omnia boot method" + +config TURRIS_OMNIA_SPL_BOOT_DEVICE_SPI + bool "SPI NOR flash" + +config TURRIS_OMNIA_SPL_BOOT_DEVICE_MMC + bool "SDIO/MMC card" + +endchoice + +endif + config MVEBU_EFUSE bool "Enable eFuse support" default n diff --git a/board/CZ.NIC/turris_omnia/Makefile b/board/CZ.NIC/turris_omnia/Makefile new file mode 100644 index 0000000..f2ae506 --- /dev/null +++ b/board/CZ.NIC/turris_omnia/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2017 Marek Behun +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := turris_omnia.o diff --git a/board/CZ.NIC/turris_omnia/kwbimage.cfg b/board/CZ.NIC/turris_omnia/kwbimage.cfg new file mode 100644 index 0000000..cc05792 --- /dev/null +++ b/board/CZ.NIC/turris_omnia/kwbimage.cfg @@ -0,0 +1,12 @@ +# +# Copyright (C) 2014 Stefan Roese +# + +# Armada XP uses version 1 image format +VERSION 1 + +# Boot Media configurations +BOOT_FROM spi + +# Binary Header (bin_hdr) with DDR3 training code +BINARY spl/u-boot-spl.bin 0000005b 00000068 diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c new file mode 100644 index 0000000..86926f8 --- /dev/null +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2017 Marek Behun + * Copyright (C) 2016 Tomas Hlavacek + * + * Derived from the code for + * Marvell/db-88f6820-gp by Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_ATSHA204A +# include +#endif + +#ifdef CONFIG_WDT_ORION +# include +#endif + +#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include <../serdes/a38x/high_speed_env_spec.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define OMNIA_I2C_EEPROM_DM_NAME "i2c@0" +#define OMNIA_I2C_EEPROM 0x54 +#define OMNIA_I2C_EEPROM_CONFIG_ADDR 0x0 +#define OMNIA_I2C_EEPROM_ADDRLEN 2 +#define OMNIA_I2C_EEPROM_MAGIC 0x0341a034 + +#define OMNIA_I2C_MCU_DM_NAME "i2c@0" +#define OMNIA_I2C_MCU_ADDR_STATUS 0x1 +#define OMNIA_I2C_MCU_SATA 0x20 +#define OMNIA_I2C_MCU_CARDDET 0x10 +#define OMNIA_I2C_MCU 0x2a +#define OMNIA_I2C_MCU_WDT_ADDR 0x0b + +#define OMNIA_ATSHA204_OTP_VERSION 0 +#define OMNIA_ATSHA204_OTP_SERIAL 1 +#define OMNIA_ATSHA204_OTP_MAC0 3 +#define OMNIA_ATSHA204_OTP_MAC1 4 + +#define MVTWSI_ARMADA_DEBUG_REG 0x8c + +/* + * Those values and defines are taken from the Marvell U-Boot version + * "u-boot-2013.01-2014_T3.0" + */ +#define OMNIA_GPP_OUT_ENA_LOW \ + (~(BIT(1) | BIT(4) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | \ + BIT(10) | BIT(11) | BIT(19) | BIT(22) | BIT(23) | BIT(25) | \ + BIT(26) | BIT(27) | BIT(29) | BIT(30) | BIT(31))) +#define OMNIA_GPP_OUT_ENA_MID \ + (~(BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(15) | \ + BIT(16) | BIT(17) | BIT(18))) + +#define OMNIA_GPP_OUT_VAL_LOW 0x0 +#define OMNIA_GPP_OUT_VAL_MID 0x0 +#define OMNIA_GPP_POL_LOW 0x0 +#define OMNIA_GPP_POL_MID 0x0 + +static struct serdes_map board_serdes_map_pex[] = { + {PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0} +}; + +static struct serdes_map board_serdes_map_sata[] = { + {SATA0, SERDES_SPEED_6_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, + {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, + {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0} +}; + +static bool omnia_detect_sata(void) +{ + struct udevice *bus, *dev; + int ret; + u16 mode; + + puts("SERDES0 card detect: "); + + if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) { + puts("Cannot find MCU bus!\n"); + return false; + } + + ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev); + if (ret) { + puts("Cannot get MCU chip!\n"); + return false; + } + + ret = dm_i2c_read(dev, OMNIA_I2C_MCU_ADDR_STATUS, (uchar *) &mode, 2); + if (ret) { + puts("I2C read failed! Default PEX\n"); + return false; + } + + if (!(mode & OMNIA_I2C_MCU_CARDDET)) { + puts("NONE\n"); + return false; + } + + if (mode & OMNIA_I2C_MCU_SATA) { + puts("SATA\n"); + return true; + } else { + puts("PEX\n"); + return false; + } +} + +int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) +{ + if (omnia_detect_sata()) { + *serdes_map_array = board_serdes_map_sata; + *count = ARRAY_SIZE(board_serdes_map_sata); + } else { + *serdes_map_array = board_serdes_map_pex; + *count = ARRAY_SIZE(board_serdes_map_pex); + } + + return 0; +} + +struct omnia_eeprom { + u32 magic; + u32 ramsize; + char region[4]; + u32 crc; +}; + +static bool omnia_read_eeprom(struct omnia_eeprom *oep) +{ + struct udevice *bus, *dev; + int ret, crc, retry = 3; + + if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_EEPROM_DM_NAME, &bus)) { + puts("Cannot find EEPROM bus\n"); + return false; + } + + ret = i2c_get_chip(bus, OMNIA_I2C_EEPROM, OMNIA_I2C_EEPROM_ADDRLEN, &dev); + if (ret) { + puts("Cannot get EEPROM chip\n"); + return false; + } + + for (; retry > 0; --retry) { + ret = dm_i2c_read(dev, OMNIA_I2C_EEPROM_CONFIG_ADDR, (uchar *) oep, sizeof(struct omnia_eeprom)); + if (ret) + continue; + + if (oep->magic != OMNIA_I2C_EEPROM_MAGIC) { + puts("I2C EEPROM missing magic number!\n"); + continue; + } + + crc = crc32(0, (unsigned char *) oep, + sizeof(struct omnia_eeprom) - 4); + if (crc == oep->crc) { + break; + } else { + printf("CRC of EEPROM memory config failed! " + "calc=0x%04x saved=0x%04x\n", crc, oep->crc); + } + } + + if (!retry) { + puts("I2C EEPROM read failed!\n"); + return false; + } + + return true; +} + +/* + * 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 hws_topology_map board_topology_map_1g = { + 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_800, /* frequency */ + 0, 0, /* cas_l cas_wl */ + HWS_TEMP_NORMAL, /* temperature */ + HWS_TIM_2T} }, /* timing (force 2t) */ + 5, /* Num Of Bus Per Interface*/ + BUS_MASK_32BIT /* Busses mask */ +}; + +static struct hws_topology_map board_topology_map_2g = { + 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_8G, /* mem_size */ + DDR_FREQ_800, /* frequency */ + 0, 0, /* cas_l cas_wl */ + HWS_TEMP_NORMAL, /* temperature */ + HWS_TIM_2T} }, /* timing (force 2t) */ + 5, /* Num Of Bus Per Interface*/ + BUS_MASK_32BIT /* Busses mask */ +}; + +struct hws_topology_map *ddr3_get_topology_map(void) +{ + static int mem = 0; + struct omnia_eeprom oep; + + /* Get the board config from EEPROM */ + if (mem == 0) { + if(!omnia_read_eeprom(&oep)) + goto out; + + printf("Memory config in EEPROM: 0x%02x\n", oep.ramsize); + + if (oep.ramsize == 0x2) + mem = 2; + else + mem = 1; + } + +out: + /* Hardcoded fallback */ + if (mem == 0) { + puts("WARNING: Memory config from EEPROM read failed.\n"); + puts("Falling back to default 1GiB map.\n"); + mem = 1; + } + + /* Return the board topology as defined in the board code */ + if (mem == 1) + return &board_topology_map_1g; + if (mem == 2) + return &board_topology_map_2g; + + return &board_topology_map_1g; +} + +#ifndef CONFIG_SPL_BUILD +static int set_regdomain(void) +{ + struct omnia_eeprom oep; + char rd[3] = {' ', ' ', 0}; + + if (omnia_read_eeprom(&oep)) + memcpy(rd, &oep.region, 2); + else + puts("EEPROM regdomain read failed.\n"); + + printf("Regdomain set to %s\n", rd); + return setenv("regdomain", rd); +} +#endif + +int board_early_init_f(void) +{ + u32 i2c_debug_reg; + + /* Configure MPP */ + writel(0x11111111, MVEBU_MPP_BASE + 0x00); + writel(0x11111111, MVEBU_MPP_BASE + 0x04); + writel(0x11244011, MVEBU_MPP_BASE + 0x08); + writel(0x22222111, MVEBU_MPP_BASE + 0x0c); + writel(0x22200002, MVEBU_MPP_BASE + 0x10); + writel(0x30042022, MVEBU_MPP_BASE + 0x14); + writel(0x55550555, MVEBU_MPP_BASE + 0x18); + writel(0x00005550, MVEBU_MPP_BASE + 0x1c); + + /* Set GPP Out value */ + writel(OMNIA_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00); + writel(OMNIA_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00); + + /* Set GPP Polarity */ + writel(OMNIA_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c); + writel(OMNIA_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c); + + /* Set GPP Out Enable */ + writel(OMNIA_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04); + writel(OMNIA_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04); + + /* Disable I2C debug mode blocking 0x64 I2C address */ + i2c_debug_reg = readl(MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG); + i2c_debug_reg &= ~(1<<18); + writel(i2c_debug_reg, MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG); + + return 0; +} + +#ifndef CONFIG_SPL_BUILD +static bool disable_mcu_watchdog(void) +{ + struct udevice *bus, *dev; + int ret, retry = 3; + uchar buf[1] = {0x0}; + + if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) { + puts("Cannot find MCU bus! Can not disable MCU WDT.\n"); + return false; + } + + ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev); + if (ret) { + puts("Cannot get MCU chip! Can not disable MCU WDT.\n"); + return false; + } + + for (; retry > 0; --retry) + if (!dm_i2c_write(dev, OMNIA_I2C_MCU_WDT_ADDR, (uchar *) buf, 1)) + break; + + if (retry <= 0) { + puts("I2C MCU watchdog failed to disable!\n"); + return false; + } + + return true; +} +#endif + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION) +static struct udevice *watchdog_dev = NULL; +#endif + +int board_init(void) +{ + /* adress of boot parameters */ + gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100; + +#ifndef CONFIG_SPL_BUILD +# ifdef CONFIG_WDT_ORION + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Cannot find Armada 385 watchdog!\n"); + } else { + puts("Enabling Armada 385 watchdog.\n"); + wdt_start(watchdog_dev, (u32) 25000000 * 120, 0); + } +# endif + + if (disable_mcu_watchdog()) + puts("Disabled MCU startup watchdog.\n"); + + set_regdomain(); +#endif + + return 0; +} + +#ifdef CONFIG_WATCHDOG +/* Called by macro WATCHDOG_RESET */ +void watchdog_reset(void) +{ +# if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION) + static ulong next_reset = 0; + ulong now; + + if (!watchdog_dev) + return; + + now = timer_get_us(); + + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 1000; + } +# endif +} +#endif + +int board_late_init(void) +{ +#ifndef CONFIG_SPL_BUILD + set_regdomain(); +#endif + + return 0; +} + +#ifdef CONFIG_ATSHA204A +static struct udevice *get_atsha204a_dev(void) +{ + static struct udevice *dev = NULL; + + if (dev != NULL) + return dev; + + if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) { + puts("Cannot find ATSHA204A on I2C bus!\n"); + dev = NULL; + } + + return dev; +} +#endif + +int checkboard(void) +{ + u32 version_num, serial_num; + int err = 1; + +#ifdef CONFIG_ATSHA204A + struct udevice *dev = get_atsha204a_dev(); + + if (dev) { + err = atsha204a_wakeup(dev); + if (err) + goto out; + + err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, + OMNIA_ATSHA204_OTP_VERSION, + (u8 *) &version_num); + if (err) + goto out; + + err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, + OMNIA_ATSHA204_OTP_SERIAL, + (u8 *) &serial_num); + if (err) + goto out; + + atsha204a_sleep(dev); + } + +out: +#endif + + if (err) + printf("Board: Turris Omnia (ver N/A). SN: N/A\n"); + else + printf("Board: Turris Omnia SNL %08X%08X\n", + be32_to_cpu(version_num), be32_to_cpu(serial_num)); + + return 0; +} + +static void increment_mac(u8 *mac) +{ + int i; + + for (i = 5; i >= 3; i--) { + mac[i] += 1; + if (mac[i]) + break; + } +} + +int misc_init_r(void) +{ +#ifdef CONFIG_ATSHA204A + int err; + struct udevice *dev = get_atsha204a_dev(); + u8 mac0[4], mac1[4], mac[6]; + + if (!dev) + goto out; + + err = atsha204a_wakeup(dev); + if (err) + goto out; + + err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, + OMNIA_ATSHA204_OTP_MAC0, mac0); + if (err) + goto out; + + err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, + OMNIA_ATSHA204_OTP_MAC1, mac1); + if (err) + goto out; + + atsha204a_sleep(dev); + + mac[0] = mac0[1]; + mac[1] = mac0[2]; + mac[2] = mac0[3]; + mac[3] = mac1[1]; + mac[4] = mac1[2]; + mac[5] = mac1[3]; + + if (is_valid_ethaddr(mac)) + eth_setenv_enetaddr("ethaddr", mac); + + increment_mac(mac); + + if (is_valid_ethaddr(mac)) + eth_setenv_enetaddr("eth1addr", mac); + + increment_mac(mac); + + if (is_valid_ethaddr(mac)) + eth_setenv_enetaddr("eth2addr", mac); + +out: +#endif + + return 0; +} + diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig new file mode 100644 index 0000000..512b9da --- /dev/null +++ b/configs/turris_omnia_defconfig @@ -0,0 +1,62 @@ +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_TURRIS_OMNIA=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_BOOT_DEVICE_SPI=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_DEFAULT_DEVICE_TREE="armada-385-turris-omnia" +CONFIG_BOOTDELAY=3 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_SPL=y +CONFIG_SPL_I2C_SUPPORT=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_GO=y +CONFIG_CMD_RUN=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_LOADS=y +CONFIG_CMD_MEMORY=y +CONFIG_CMD_ECHO=y +CONFIG_CMD_SETEXPR=y +# CONFIG_PARTITION_UUIDS is not set +# CONFIG_SPL_PARTITION_UUIDS is not set +CONFIG_DOS_PARTITION=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_MISC=y +CONFIG_ATSHA204A=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_NS16550=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=250000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_MV=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI=y +CONFIG_USB_EHCI_MARVELL=y +CONFIG_USB_STORAGE=y +CONFIG_WDT=y +CONFIG_WDT_ORION=y +CONFIG_ARCH_MISC_INIT=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_CMDLINE=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="=> " +# CONFIG_DISPLAY_BOARDINFO is not set diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h new file mode 100644 index 0000000..4ad603d --- /dev/null +++ b/include/configs/turris_omnia.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2017 Marek Behun + * Copyright (C) 2016 Tomas Hlavacek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CONFIG_TURRIS_OMNIA_H +#define _CONFIG_TURRIS_OMNIA_H + +/* + * High Level Configuration Options (easy to change) + */ + +#define CONFIG_MISC_INIT_R +#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 support */ +#define CONFIG_DM_I2C +#define CONFIG_I2C_MUX +#define CONFIG_I2C_MUX_PCA954x +#define CONFIG_SPL_I2C_MUX +#define CONFIG_SYS_I2C_MVTWSI + +/* Watchdog support */ +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION) +# define CONFIG_WATCHDOG +#endif + +/* SPI NOR flash default params, used by sf commands */ +#define CONFIG_SF_DEFAULT_SPEED 1000000 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_SPANSION + +/* + * SDIO/MMC Card Configuration + */ +#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE + +/* + * SATA/SCSI/AHCI configuration + */ +#define CONFIG_LIBATA +#define CONFIG_SCSI_AHCI +#define CONFIG_SCSI_AHCI_PLAT +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 +#define CONFIG_SYS_SCSI_MAX_LUN 1 +#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ + CONFIG_SYS_SCSI_MAX_LUN) + +/* Additional FS support/configuration */ +#define CONFIG_SUPPORT_VFAT + +/* USB/EHCI configuration */ +#define CONFIG_EHCI_IS_TDI + +/* Environment in SPI NOR flash */ +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET (3*(1 << 18)) /* 768KiB in */ +#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ +#define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */ + +#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 + +#define CONFIG_SYS_ALT_MEMTEST + +/* Keep device tree and initrd in lower memory so the kernel can access them */ +#define RELOCATION_LIMITS_ENV_SETTINGS \ + "fdt_high=0x10000000\0" \ + "initrd_high=0x10000000\0" + +/* Defines for SPL */ +#define CONFIG_SPL_FRAMEWORK +#define CONFIG_SPL_SIZE (140 << 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 +#endif + +#define CONFIG_SPL_STACK (0x40000000 + ((192 - 16) << 10)) +#define CONFIG_SPL_BOOTROM_SAVE (CONFIG_SPL_STACK + 4) +#define CONFIG_SPL_DRIVERS_MISC_SUPPORT + +#ifdef CONFIG_TURRIS_OMNIA_SPL_BOOT_DEVICE_SPI +/* 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 + +#ifdef CONFIG_TURRIS_OMNIA_SPL_BOOT_DEVICE_MMC +/* SPL related MMC defines */ +# define CONFIG_SYS_MMC_U_BOOT_OFFS (160 << 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 +#endif + +/* + * mv-common.h should be defined after CMD configs since it used them + * to enable certain macros + */ +#include "mv-common.h" + +/* Include the common distro boot environment */ +#ifndef CONFIG_SPL_BUILD +#include + +#ifdef CONFIG_MMC +#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0) +#else +#define BOOT_TARGET_DEVICES_MMC(func) +#endif + +#ifdef CONFIG_USB_STORAGE +#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0) +#else +#define BOOT_TARGET_DEVICES_USB(func) +#endif + +#define BOOT_TARGET_DEVICES(func) \ + BOOT_TARGET_DEVICES_MMC(func) \ + BOOT_TARGET_DEVICES_USB(func) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) + +#define KERNEL_ADDR_R __stringify(0x1000000) +#define FDT_ADDR_R __stringify(0x2000000) +#define RAMDISK_ADDR_R __stringify(0x2200000) +#define SCRIPT_ADDR_R __stringify(0x1800000) +#define PXEFILE_ADDR_R __stringify(0x1900000) + +#define LOAD_ADDRESS_ENV_SETTINGS \ + "kernel_addr_r=" KERNEL_ADDR_R "\0" \ + "fdt_addr_r=" FDT_ADDR_R "\0" \ + "ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \ + "scriptaddr=" SCRIPT_ADDR_R "\0" \ + "pxefile_addr_r=" PXEFILE_ADDR_R "\0" + +#include + +#define CONFIG_EXTRA_ENV_SETTINGS \ + RELOCATION_LIMITS_ENV_SETTINGS \ + LOAD_ADDRESS_ENV_SETTINGS \ + "fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \ + "console=ttyS0,115200\0" \ + BOOTENV + +#endif /* CONFIG_SPL_BUILD */ + +#endif /* _CONFIG_TURRIS_OMNIA_H */ -- cgit v0.10.2 From b6518b1ea3b40ec1dec786fb942dc47bb164d987 Mon Sep 17 00:00:00 2001 From: Igal Liberman Date: Tue, 13 Jun 2017 10:35:44 +0300 Subject: arm64: mvebu: use single defconfig for Armada8K development boards Currently, Marvell Armada8k development board use 3 different defconfigs: mvebu_db-88f7040-nand_defconfig mvebu_db-88f7040_defconfig mvebu_db-88f8040_defconfig Having 3 different defconfigs makes maintenance difficult. This patch removes the defconfigs mentioned above and introduce a new defconfig which represents the Armada8k family. NOTE: In order not to break automatic tools compilation, a default device-tree is set in the defconfig (armada-8040-db). However, when compiling u-boot, the user MUST explicitly export the DEVICE_TREE for the requested board because using A80x0 device-tree on A70x0 might break the device. For more information, refer to "doc/README.marvell" (intoduced in this patch). Change-Id: I98515b6306498358f3722ecf7ac4c87f236ebbd8 Signed-off-by: Igal Liberman Signed-off-by: Stefan Roese diff --git a/configs/mvebu_db-88f7040-nand_defconfig b/configs/mvebu_db-88f7040-nand_defconfig deleted file mode 100644 index 2aba8de..0000000 --- a/configs/mvebu_db-88f7040-nand_defconfig +++ /dev/null @@ -1,72 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_MVEBU=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_TARGET_MVEBU_ARMADA_8K=y -CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db-nand" -CONFIG_SMBIOS_PRODUCT_NAME="" -CONFIG_DEBUG_UART=y -CONFIG_AHCI=y -# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_SYS_CONSOLE_INFO_QUIET=y -# CONFIG_DISPLAY_CPUINFO is not set -# CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_ARCH_EARLY_INIT_R=y -CONFIG_BOARD_EARLY_INIT_F=y -CONFIG_HUSH_PARSER=y -# CONFIG_CMD_IMLS is not set -# CONFIG_CMD_FLASH is not set -CONFIG_CMD_MMC=y -CONFIG_CMD_NAND=y -CONFIG_CMD_PART=y -CONFIG_CMD_SF=y -CONFIG_CMD_SPI=y -CONFIG_CMD_I2C=y -CONFIG_CMD_USB=y -# CONFIG_CMD_FPGA is not set -# 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_MVEBU_BUBT=y -CONFIG_MVEBU_NAND_BOOT=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_EXT4_WRITE=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y -CONFIG_MAC_PARTITION=y -CONFIG_ISO_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_BLOCK_CACHE=y -CONFIG_DM_I2C=y -CONFIG_SYS_I2C_MVTWSI=y -CONFIG_MISC=y -CONFIG_DM_MMC=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_XENON=y -CONFIG_NAND_PXA3XX=y -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_MACRONIX=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHYLIB=y -CONFIG_PCI=y -CONFIG_DM_PCI=y -CONFIG_PCIE_DW_MVEBU=y -CONFIG_MVEBU_COMPHY_SUPPORT=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_ARMADA_8K=y -# CONFIG_SPL_SERIAL_PRESENT is not set -CONFIG_DEBUG_UART_BASE=0xf0512000 -CONFIG_DEBUG_UART_CLOCK=200000000 -CONFIG_DEBUG_UART_SHIFT=2 -CONFIG_DEBUG_UART_ANNOUNCE=y -CONFIG_SYS_NS16550=y -CONFIG_USB=y -CONFIG_DM_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_SMBIOS_MANUFACTURER="" diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig deleted file mode 100644 index 28af643..0000000 --- a/configs/mvebu_db-88f7040_defconfig +++ /dev/null @@ -1,70 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_MVEBU=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_TARGET_MVEBU_ARMADA_8K=y -CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db" -CONFIG_SMBIOS_PRODUCT_NAME="" -CONFIG_DEBUG_UART=y -CONFIG_AHCI=y -# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_SYS_CONSOLE_INFO_QUIET=y -# CONFIG_DISPLAY_CPUINFO is not set -# CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_ARCH_EARLY_INIT_R=y -CONFIG_BOARD_EARLY_INIT_F=y -CONFIG_HUSH_PARSER=y -# CONFIG_CMD_IMLS is not set -# CONFIG_CMD_FLASH is not set -CONFIG_CMD_MMC=y -CONFIG_CMD_PART=y -CONFIG_CMD_SF=y -CONFIG_CMD_SPI=y -CONFIG_CMD_I2C=y -CONFIG_CMD_USB=y -# CONFIG_CMD_FPGA is not set -# 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_MVEBU_BUBT=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_EXT4_WRITE=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y -CONFIG_MAC_PARTITION=y -CONFIG_ISO_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_BLOCK_CACHE=y -CONFIG_DM_I2C=y -CONFIG_SYS_I2C_MVTWSI=y -CONFIG_MISC=y -CONFIG_DM_MMC=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_XENON=y -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_MACRONIX=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHY_MARVELL=y -CONFIG_MVPP2=y -CONFIG_PCI=y -CONFIG_DM_PCI=y -CONFIG_PCIE_DW_MVEBU=y -CONFIG_MVEBU_COMPHY_SUPPORT=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_ARMADA_8K=y -# CONFIG_SPL_SERIAL_PRESENT is not set -CONFIG_DEBUG_UART_BASE=0xf0512000 -CONFIG_DEBUG_UART_CLOCK=200000000 -CONFIG_DEBUG_UART_SHIFT=2 -CONFIG_DEBUG_UART_ANNOUNCE=y -CONFIG_SYS_NS16550=y -CONFIG_USB=y -CONFIG_DM_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_SMBIOS_MANUFACTURER="" diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig deleted file mode 100644 index 7f36eda..0000000 --- a/configs/mvebu_db-88f8040_defconfig +++ /dev/null @@ -1,70 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_MVEBU=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 -CONFIG_TARGET_MVEBU_ARMADA_8K=y -CONFIG_DEFAULT_DEVICE_TREE="armada-8040-db" -CONFIG_SMBIOS_PRODUCT_NAME="" -CONFIG_DEBUG_UART=y -CONFIG_AHCI=y -# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_SYS_CONSOLE_INFO_QUIET=y -# CONFIG_DISPLAY_CPUINFO is not set -# CONFIG_DISPLAY_BOARDINFO is not set -CONFIG_ARCH_EARLY_INIT_R=y -CONFIG_BOARD_EARLY_INIT_F=y -CONFIG_HUSH_PARSER=y -# CONFIG_CMD_IMLS is not set -# CONFIG_CMD_FLASH is not set -CONFIG_CMD_MMC=y -CONFIG_CMD_PART=y -CONFIG_CMD_SF=y -CONFIG_CMD_SPI=y -CONFIG_CMD_I2C=y -CONFIG_CMD_USB=y -# CONFIG_CMD_FPGA is not set -# 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_MVEBU_BUBT=y -CONFIG_CMD_EXT4=y -CONFIG_CMD_EXT4_WRITE=y -CONFIG_CMD_FAT=y -CONFIG_CMD_FS_GENERIC=y -CONFIG_MAC_PARTITION=y -CONFIG_ISO_PARTITION=y -CONFIG_EFI_PARTITION=y -CONFIG_BLOCK_CACHE=y -CONFIG_DM_I2C=y -CONFIG_SYS_I2C_MVTWSI=y -CONFIG_MISC=y -CONFIG_DM_MMC=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC_SDHCI_XENON=y -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_MACRONIX=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_PHY_MARVELL=y -CONFIG_MVPP2=y -CONFIG_PCI=y -CONFIG_DM_PCI=y -CONFIG_PCIE_DW_MVEBU=y -CONFIG_MVEBU_COMPHY_SUPPORT=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_ARMADA_8K=y -# CONFIG_SPL_SERIAL_PRESENT is not set -CONFIG_DEBUG_UART_BASE=0xf0512000 -CONFIG_DEBUG_UART_CLOCK=200000000 -CONFIG_DEBUG_UART_SHIFT=2 -CONFIG_DEBUG_UART_ANNOUNCE=y -CONFIG_SYS_NS16550=y -CONFIG_USB=y -CONFIG_DM_USB=y -CONFIG_USB_XHCI_HCD=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_SMBIOS_MANUFACTURER="" diff --git a/configs/mvebu_db_armada8k_defconfig b/configs/mvebu_db_armada8k_defconfig new file mode 100644 index 0000000..7f36eda --- /dev/null +++ b/configs/mvebu_db_armada8k_defconfig @@ -0,0 +1,70 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_MVEBU_ARMADA_8K=y +CONFIG_DEFAULT_DEVICE_TREE="armada-8040-db" +CONFIG_SMBIOS_PRODUCT_NAME="" +CONFIG_DEBUG_UART=y +CONFIG_AHCI=y +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_ARCH_EARLY_INIT_R=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +# CONFIG_CMD_FPGA is not set +# 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_MVEBU_BUBT=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_MAC_PARTITION=y +CONFIG_ISO_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_BLOCK_CACHE=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_PHY_MARVELL=y +CONFIG_MVPP2=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_PCIE_DW_MVEBU=y +CONFIG_MVEBU_COMPHY_SUPPORT=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_8K=y +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_DEBUG_UART_BASE=0xf0512000 +CONFIG_DEBUG_UART_CLOCK=200000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_SMBIOS_MANUFACTURER="" diff --git a/doc/README.marvell b/doc/README.marvell new file mode 100644 index 0000000..3364617 --- /dev/null +++ b/doc/README.marvell @@ -0,0 +1,53 @@ +Marvell U-Boot Build Instructions +================================= + +This document describes how to compile the U-Boot and how to change U-Boot configuration + +Build Procedure +---------------- +1. Install required packages: + + # sudo apt-get install libssl-dev + # sudo apt-get install device-tree-compiler + # sudo apt-get install swig libpython-dev + +2. Set the cross compiler: + + # export CROSS_COMPILE=/path/to/toolchain/aarch64-marvell-linux-gnu- + +3. Clean-up old residuals: + + # make mrproper + +4. Configure the U-Boot: + + # make + + - For the Armada-70x0/80x0 DB board use "mvebu_db_armada8k_defconfig" + - For the Armada-80x0 MacchiatoBin use "make mvebu_mcbin-88f8040_defconfig" + - For the Armada-3700 DB board use "make mvebu_db-88f3720_defconfig" + - For the Armada-3700 EsspressoBin use "make mvebu_espressobin-88f3720_defconfig" + +5. Configure the device-tree and build the U-Boot image: + + Compile u-boot and set the required device-tree using: + + # make DEVICE_TREE= + + NOTE: + Compilation with "mvebu_db_armada8k_defconfig" requires explicitly exporting DEVICE_TREE + for the requested board. + By default, u-boot is compiled with armada-8040-db device-tree. + Using A80x0 device-tree on A70x0 might break the device. + In order to prevent this, the required device-tree MUST be set during compilation. + All device-tree files are located in ./arch/arm/dts/ folder. + + NOTE: + The u-boot.bin should not be used as a stand-alone image. + The ARM Trusted Firmware (ATF) build process uses this image to generate the + flash image. + +Configuration update +--------------------- + To update the U-Boot configuration, please refer to doc/README.kconfig + -- cgit v0.10.2 From ed72741d9f6819dc0f4705ddecd28b1a676854b0 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 4 Jul 2017 20:23:38 +0300 Subject: tools/kwbimage: update the list of SoCs using v1 header Armada 38x also uses image header v1. Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 20f4d0d..893083e 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -70,7 +70,7 @@ struct kwb_header { struct ext_hdr_v0 kwb_exthdr; }; -/* Structure of the main header, version 1 (Armada 370, Armada XP) */ +/* Structure of the main header, version 1 (Armada 370/38x/XP) */ struct main_hdr_v1 { uint8_t blockid; /* 0 */ uint8_t flags; /* 1 */ -- cgit v0.10.2 From 37d108b64fabc625ae829bc6ee419c163d523c3b Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 4 Jul 2017 20:23:39 +0300 Subject: tools/kwbimage.h: make offset marks style consistent The offset marking in kwbimage.h is inconsistent. main_hdr_v0 uses decimals, main_hdr_v1 uses hex without '0x' prefix, secure_hdr_v1 uses hex with '0x' prefix. Make all offset marks hex with '0x' prefix. Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 893083e..2160c8f 100644 --- a/tools/kwbimage.h +++ b/tools/kwbimage.h @@ -34,20 +34,20 @@ /* Structure of the main header, version 0 (Kirkwood, Dove) */ struct main_hdr_v0 { - uint8_t blockid; /*0 */ - uint8_t nandeccmode; /*1 */ - uint16_t nandpagesize; /*2-3 */ - uint32_t blocksize; /*4-7 */ - uint32_t rsvd1; /*8-11 */ - uint32_t srcaddr; /*12-15 */ - uint32_t destaddr; /*16-19 */ - uint32_t execaddr; /*20-23 */ - uint8_t satapiomode; /*24 */ - uint8_t rsvd3; /*25 */ - uint16_t ddrinitdelay; /*26-27 */ - uint16_t rsvd2; /*28-29 */ - uint8_t ext; /*30 */ - uint8_t checksum; /*31 */ + uint8_t blockid; /* 0x0 */ + uint8_t nandeccmode; /* 0x1 */ + uint16_t nandpagesize; /* 0x2-0x3 */ + uint32_t blocksize; /* 0x4-0x7 */ + uint32_t rsvd1; /* 0x8-0xB */ + uint32_t srcaddr; /* 0xC-0xF */ + uint32_t destaddr; /* 0x10-0x13 */ + uint32_t execaddr; /* 0x14-0x17 */ + uint8_t satapiomode; /* 0x18 */ + uint8_t rsvd3; /* 0x19 */ + uint16_t ddrinitdelay; /* 0x1A-0x1B */ + uint16_t rsvd2; /* 0x1C-0x1D */ + uint8_t ext; /* 0x1E */ + uint8_t checksum; /* 0x1F */ }; struct ext_hdr_v0_reg { @@ -72,23 +72,23 @@ struct kwb_header { /* Structure of the main header, version 1 (Armada 370/38x/XP) */ struct main_hdr_v1 { - uint8_t blockid; /* 0 */ - uint8_t flags; /* 1 */ - uint16_t reserved2; /* 2-3 */ - uint32_t blocksize; /* 4-7 */ - uint8_t version; /* 8 */ - uint8_t headersz_msb; /* 9 */ - uint16_t headersz_lsb; /* A-B */ - uint32_t srcaddr; /* C-F */ - uint32_t destaddr; /* 10-13 */ - uint32_t execaddr; /* 14-17 */ - uint8_t options; /* 18 */ - uint8_t nandblocksize; /* 19 */ - uint8_t nandbadblklocation; /* 1A */ - uint8_t reserved4; /* 1B */ - uint16_t reserved5; /* 1C-1D */ - uint8_t ext; /* 1E */ - uint8_t checksum; /* 1F */ + uint8_t blockid; /* 0x0 */ + uint8_t flags; /* 0x1 */ + uint16_t reserved2; /* 0x2-0x3 */ + uint32_t blocksize; /* 0x4-0x7 */ + uint8_t version; /* 0x8 */ + uint8_t headersz_msb; /* 0x9 */ + uint16_t headersz_lsb; /* 0xA-0xB */ + uint32_t srcaddr; /* 0xC-0xF */ + uint32_t destaddr; /* 0x10-0x13 */ + uint32_t execaddr; /* 0x14-0x17 */ + uint8_t options; /* 0x18 */ + uint8_t nandblocksize; /* 0x19 */ + uint8_t nandbadblklocation; /* 0x1A */ + uint8_t reserved4; /* 0x1B */ + uint16_t reserved5; /* 0x1C-0x1D */ + uint8_t ext; /* 0x1E */ + uint8_t checksum; /* 0x1F */ }; /* -- cgit v0.10.2 From db7cd4ed33d6724937c747a7339810b77d6989da Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 4 Jul 2017 20:23:40 +0300 Subject: tools/kwbimage: fix v1 header verification The verify_header callback in kwbimage.c only verifies v0 headers checksum. Running 'mkimage -l' on a v1 image gives the following misleading output: GP Header: Size ae000000 LoadAddr 34160600 Implement support for v1 headers. For that, factor out the header checksum code to a separate main_hdr_checksum_ok() routine. This routine relies on the fact that the checksum field offset is the same in both v0 and v1 headers. With this patch applied 'mkimage -l' correctly identifies the image: Image Type: MVEBU Boot from sdio Image Image version:1 Data Size: 398904 Bytes = 389.55 KiB = 0.38 MiB Load Address: 007fffc0 Entry Point: 00800000 Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 5830549..ccecf87 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -290,6 +290,33 @@ static uint8_t image_checksum8(void *start, uint32_t len) return csum; } +size_t kwbimage_header_size(unsigned char *ptr) +{ + if (image_version((void *)ptr) == 0) + return sizeof(struct main_hdr_v0); + else + return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr); +} + +/* + * Verify checksum over a complete header that includes the checksum field. + * Return 1 when OK, otherwise 0. + */ +static int main_hdr_checksum_ok(void *hdr) +{ + /* Offsets of checksum in v0 and v1 headers are the same */ + struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr; + uint8_t checksum; + + checksum = image_checksum8(hdr, kwbimage_header_size(hdr)); + /* Calculated checksum includes the header checksum field. Compensate + * for that. + */ + checksum -= main_hdr->checksum; + + return checksum == main_hdr->checksum; +} + static uint32_t image_checksum32(void *start, uint32_t len) { uint32_t csum = 0; @@ -1587,14 +1614,9 @@ static int kwbimage_check_image_types(uint8_t type) static int kwbimage_verify_header(unsigned char *ptr, int image_size, struct image_tool_params *params) { - struct main_hdr_v0 *main_hdr; uint8_t checksum; - main_hdr = (struct main_hdr_v0 *)ptr; - checksum = image_checksum8(ptr, - sizeof(struct main_hdr_v0) - - sizeof(uint8_t)); - if (checksum != main_hdr->checksum) + if (!main_hdr_checksum_ok(ptr)) return -FDT_ERR_BADSTRUCTURE; /* Only version 0 extended header has checksum */ -- cgit v0.10.2 From 172b2e0b561a50a3d8c4275be4ed24b0c8e18896 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 4 Jul 2017 20:23:41 +0300 Subject: arm: mvebu: clearfog: fix chip name comment The clearfog uses Armada 388. Cc: Stefan Roese Signed-off-by: Baruch Siach Signed-off-by: Stefan Roese diff --git a/board/solidrun/clearfog/kwbimage.cfg b/board/solidrun/clearfog/kwbimage.cfg index c650c2c..f41d25a 100644 --- a/board/solidrun/clearfog/kwbimage.cfg +++ b/board/solidrun/clearfog/kwbimage.cfg @@ -2,7 +2,7 @@ # Copyright (C) 2015 Stefan Roese # -# Armada XP uses version 1 image format +# Armada 38x use version 1 image format VERSION 1 # Boot Media configurations -- cgit v0.10.2