diff options
29 files changed, 2105 insertions, 188 deletions
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 0000000000..22caf3539c --- /dev/null +++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz> + * + * 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 0000000000..28eede180e --- /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 <uwe@kleine-koenig.org> + * Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com> + * + * 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 <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#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 = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; + + 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"; +}; diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3e48d58fcc..01d700bf2e 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 0000000000..f2ae50654f --- /dev/null +++ b/board/CZ.NIC/turris_omnia/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2017 Marek Behun <marek.behun@nic.cz> +# +# 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 0000000000..cc05792556 --- /dev/null +++ b/board/CZ.NIC/turris_omnia/kwbimage.cfg @@ -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 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 0000000000..86926f8050 --- /dev/null +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -0,0 +1,530 @@ +/* + * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz> + * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz> + * + * Derived from the code for + * Marvell/db-88f6820-gp by Stefan Roese <sr@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#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 <dm/uclass.h> +#include <fdt_support.h> +#include <time.h> + +#ifdef CONFIG_ATSHA204A +# include <atsha204a-i2c.h> +#endif + +#ifdef CONFIG_WDT_ORION +# include <wdt.h> +#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/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c index cade99c8d7..40fa599865 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 e700781103..a1974cb4bd 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 f0efb53447..32168d3576 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 3a8257cac3..8906636f76 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/board/solidrun/clearfog/kwbimage.cfg b/board/solidrun/clearfog/kwbimage.cfg index c650c2c65e..f41d25a8a1 100644 --- a/board/solidrun/clearfog/kwbimage.cfg +++ b/board/solidrun/clearfog/kwbimage.cfg @@ -2,7 +2,7 @@ # Copyright (C) 2015 Stefan Roese <sr@denx.de> # -# Armada XP uses version 1 image format +# Armada 38x use version 1 image format VERSION 1 # Boot Media configurations diff --git a/configs/mvebu_db-88f7040-nand_defconfig b/configs/mvebu_db-88f7040-nand_defconfig deleted file mode 100644 index 2aba8de0b0..0000000000 --- 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 28af6431ea..0000000000 --- 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_armada8k_defconfig index 7f36eda665..7f36eda665 100644 --- a/configs/mvebu_db-88f8040_defconfig +++ b/configs/mvebu_db_armada8k_defconfig diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig new file mode 100644 index 0000000000..512b9da74d --- /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/doc/README.marvell b/doc/README.marvell new file mode 100644 index 0000000000..336461745c --- /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 <defconfig_file> + + - 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=<name> + + 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 + diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index 7e0749fde3..e70ca4b425 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 f8894e828a..229c3a127a 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 { diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index 1a6761858c..383f72f552 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 }, { } }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 92f348f409..d1ddbbe157 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 ea64677c33..10265c8fb4 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 0000000000..934ba5e6b8 --- /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 <common.h> +#include <dm.h> +#include <i2c.h> +#include <errno.h> +#include <atsha204a-i2c.h> + +#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/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b911233db3..d360a17d4d 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 4b19e4ccf6..3230cbb2ad 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 0000000000..a0df02d103 --- /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 <tmshlvck@gmail.com> + * Sylver Bruneau <sylver.bruneau@googlemail.com> + * Marek Behun <marek.behun@nic.cz> + * + * 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 <common.h> +#include <dm.h> +#include <wdt.h> +#include <asm/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +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, +}; diff --git a/include/atsha204a-i2c.h b/include/atsha204a-i2c.h new file mode 100644 index 0000000000..344fd8ace7 --- /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_ */ diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h new file mode 100644 index 0000000000..4ad603d2fb --- /dev/null +++ b/include/configs/turris_omnia.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz> + * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz> + * + * 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 <config_distro_defaults.h> + +#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 <config_distro_bootcmd.h> + +#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 */ diff --git a/tools/kwbimage.c b/tools/kwbimage.c index 5830549d26..ccecf87185 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 */ diff --git a/tools/kwbimage.h b/tools/kwbimage.h index 20f4d0d9dd..2160c8f997 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 { @@ -70,25 +70,25 @@ 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 */ - 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 */ }; /* |