[U-Boot] [PATCH u-boot-marvell v2 00/15] Fixes for Turris Omnia

Hi, this is the second version of my fixes for Turris Omnia. I removed the patches which were already applied or provided a better fix. The other patches I shall describe now here as if this was the first version.
1. removes redundant code done by I2C mvtwsi driver from board file 2. adds XHCI support to defconfig 3. in compliance with driver model use AHCI, SATA and SCSI 4. remove legacy macros from config header 5. move I2C dependencies from header file to Kconfig for TARGET_TURRIS_OMNIA 6. add SCSI as boot target 7. board code refactoring 8. fix checkpatch warnings 9. add ATSHA204A dependency to Kconfig for TARGET_TURRIS_OMNIA 10. more board code refactoring 11. print board information in the same way Turris Mox does 12. remove watchdog header include (in Turris Mox board file as well) 13. fix setting of the regdomain environment variable used on Omnia 14. add code for handling the button on the back side of Omnia, the purpose of which is factory reset 15. fix I2C driver, which sometimes breaks the I2C controller until the device is powered off
Marek
Marek Behún (15): arm: mvebu: turris_omnia: remove redundant code arm: mvebu: turris_omnia: add XHCI to defconfig arm: mvebu: turris_omnia: use AHCI and SATA driver model arm: mvebu: turris_omnia: remove legacy macros from board header arm: mvebu: turris_omnia: move I2C dependencies to Kconfig arm: mvebu: turris_omnia: add SCSI as boot target arm: mvebu: turris_omnia: refactor I2C accessing code arm: mvebu: turris_omnia: fix checkpatch warnings arm: mvebu: turris_omnia: move ATSHA204A from defconfig to Kconfig arm: mvebu: turris_omnia: refactor more code arm: mvebu: turris_omnia: print board info as Turris Mox arm: mvebu: turris_*: remove watchdog include arm: mvebu: turris_omnia: fix regdomain env var setting arm: mvebu: turris_omnia: add RESET button handling i2c: mvtwsi: fix reading status register after interrupt
arch/arm/mach-mvebu/Kconfig | 49 ++++ board/CZ.NIC/turris_mox/turris_mox.c | 4 - board/CZ.NIC/turris_omnia/turris_omnia.c | 333 ++++++++++++----------- configs/turris_omnia_defconfig | 10 +- drivers/i2c/mvtwsi.c | 1 + include/configs/turris_omnia.h | 32 +-- 6 files changed, 236 insertions(+), 193 deletions(-)

The i2c slave disabling is done by mvtwsi driver and is not needed here.
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 13 ------------- 1 file changed, 13 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 4c08f810a2..055ebad000 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -50,8 +50,6 @@ DECLARE_GLOBAL_DATA_PTR; #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" @@ -297,8 +295,6 @@ static int set_regdomain(void)
int board_early_init_f(void) { - u32 i2c_debug_reg; - /* Configure MPP */ writel(0x11111111, MVEBU_MPP_BASE + 0x00); writel(0x11111111, MVEBU_MPP_BASE + 0x04); @@ -321,15 +317,6 @@ int board_early_init_f(void) 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. - * Note: that would be redundant once Turris Omnia migrates to DM_I2C, - * because the mvtwsi driver includes equivalent code. - */ - 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; }

Hello Marek,
Am 30.04.2019 um 03:48 schrieb Marek Behún:
The i2c slave disabling is done by mvtwsi driver and is not needed here.
Signed-off-by: Marek Behún marek.behun@nic.cz
board/CZ.NIC/turris_omnia/turris_omnia.c | 13 ------------- 1 file changed, 13 deletions(-)
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko

On 30.04.19 03:48, Marek Behún wrote:
The i2c slave disabling is done by mvtwsi driver and is not needed here.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Add XHCI_HOST and XHCI_MVEBU to defconfig, so that user's can by default boot from USB on Turris Omnia.
Signed-off-by: Marek Behún marek.behun@nic.cz --- configs/turris_omnia_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index a528a9b5bc..2ad2f6e431 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -58,5 +58,7 @@ CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y CONFIG_WDT=y CONFIG_WDT_ORION=y

On 30.04.19 03:48, Marek Behún wrote:
Add XHCI_HOST and XHCI_MVEBU to defconfig, so that user's can by default boot from USB on Turris Omnia.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Enable AHCI, SCSI and SATA for compliance with the driver model migration.
Signed-off-by: Marek Behún marek.behun@nic.cz --- configs/turris_omnia_defconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 2ad2f6e431..5086da13a5 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -26,6 +26,8 @@ CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y +CONFIG_CMD_SATA=y +CONFIG_CMD_SCSI=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y @@ -39,6 +41,11 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SPL_OF_TRANSLATE=y +CONFIG_AHCI=y +CONFIG_AHCI_PCI=y +CONFIG_AHCI_MVEBU=y +CONFIG_SATA=y +CONFIG_SCSI=y CONFIG_SCSI_AHCI=y CONFIG_ATSHA204A=y CONFIG_DM_MMC=y

On 30.04.19 03:48, Marek Behún wrote:
Enable AHCI, SCSI and SATA for compliance with the driver model migration.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

These are not needed if MMC and SCSI DM drivers are used.
Signed-off-by: Marek Behún marek.behun@nic.cz --- include/configs/turris_omnia.h | 14 -------------- 1 file changed, 14 deletions(-)
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h index 0e65a12345..5e692e6829 100644 --- a/include/configs/turris_omnia.h +++ b/include/configs/turris_omnia.h @@ -29,20 +29,6 @@ #define CONFIG_SPL_I2C_MUX #define CONFIG_SYS_I2C_MVTWSI
-/* - * SDIO/MMC Card Configuration - */ -#define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE - -/* - * SATA/SCSI/AHCI configuration - */ -#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) - /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI

On 30.04.19 03:48, Marek Behún wrote:
These are not needed if MMC and SCSI DM drivers are used.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

The I2C dependencies are defined in include/configs/turris_omnia.h, because Turris Omnia won't boot correctly without I2C support.
Move these dependencies to Kconfig, so that they are selected if Turris Omnia is selected as target.
Signed-off-by: Marek Behún marek.behun@nic.cz --- arch/arm/mach-mvebu/Kconfig | 5 +++++ include/configs/turris_omnia.h | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index f99bd3bf65..2bf829d10a 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -116,6 +116,11 @@ config TARGET_DB_88F6820_AMC config TARGET_TURRIS_OMNIA bool "Support Turris Omnia" select 88F6820 + select DM_I2C + select I2C_MUX + select I2C_MUX_PCA954x + select SPL_I2C_MUX + select SYS_I2C_MVTWSI
config TARGET_TURRIS_MOX bool "Support Turris Mox" diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h index 5e692e6829..5a7539c9be 100644 --- a/include/configs/turris_omnia.h +++ b/include/configs/turris_omnia.h @@ -18,17 +18,6 @@ */ #define CONFIG_SYS_TCLK 250000000 /* 250MHz */
-/* - * Commands configuration - */ - -/* 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 - /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI

Hello Marek,
Am 30.04.2019 um 03:48 schrieb Marek Behún:
The I2C dependencies are defined in include/configs/turris_omnia.h, because Turris Omnia won't boot correctly without I2C support.
Move these dependencies to Kconfig, so that they are selected if Turris Omnia is selected as target.
Signed-off-by: Marek Behún marek.behun@nic.cz
arch/arm/mach-mvebu/Kconfig | 5 +++++ include/configs/turris_omnia.h | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-)
Reviewed-by: Heiko Schocher hs@denx.de
bye, Heiko

On 30.04.19 03:48, Marek Behún wrote:
The I2C dependencies are defined in include/configs/turris_omnia.h, because Turris Omnia won't boot correctly without I2C support.
Move these dependencies to Kconfig, so that they are selected if Turris Omnia is selected as target.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

If SCSI is enabled, U-Boot should try to boot also from SCSI device on Turris Omnia.
Signed-off-by: Marek Behún marek.behun@nic.cz --- include/configs/turris_omnia.h | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h index 5a7539c9be..5b9639e050 100644 --- a/include/configs/turris_omnia.h +++ b/include/configs/turris_omnia.h @@ -90,9 +90,16 @@ #define BOOT_TARGET_DEVICES_USB(func) #endif
+#ifdef CONFIG_SCSI +#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0) +#else +#define BOOT_TARGET_DEVICES_SCSI(func) +#endif + #define BOOT_TARGET_DEVICES(func) \ BOOT_TARGET_DEVICES_MMC(func) \ BOOT_TARGET_DEVICES_USB(func) \ + BOOT_TARGET_DEVICES_SCSI(func) \ func(PXE, pxe, na) \ func(DHCP, dhcp, na)

On 30.04.19 03:48, Marek Behún wrote:
If SCSI is enabled, U-Boot should try to boot also from SCSI device on Turris Omnia.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Refactor code which accesses the microcontroller and EEPROM via I2C.
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 205 ++++++++++++----------- 1 file changed, 109 insertions(+), 96 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 055ebad000..6b8fa53c98 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -32,18 +32,25 @@
DECLARE_GLOBAL_DATA_PTR;
-#define OMNIA_I2C_EEPROM_DM_NAME "i2c@11000->i2cmux@70->i2c@0" -#define OMNIA_I2C_EEPROM 0x54 -#define OMNIA_I2C_EEPROM_CONFIG_ADDR 0x0 -#define OMNIA_I2C_EEPROM_ADDRLEN 2 +#define OMNIA_I2C_BUS_NAME "i2c@11000->i2cmux@70->i2c@0" + +#define OMNIA_I2C_MCU_CHIP_ADDR 0x2a +#define OMNIA_I2C_MCU_CHIP_LEN 1 + +#define OMNIA_I2C_EEPROM_CHIP_ADDR 0x54 +#define OMNIA_I2C_EEPROM_CHIP_LEN 2 #define OMNIA_I2C_EEPROM_MAGIC 0x0341a034
-#define OMNIA_I2C_MCU_DM_NAME "i2c@11000->i2cmux@70->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 +enum mcu_commands { + CMD_GET_STATUS_WORD = 0x01, + CMD_GET_RESET = 0x09, + CMD_WATCHDOG_STATE = 0x0b, +}; + +enum status_word_bits { + CARD_DET_STSBIT = 0x0010, + MSATA_IND_STSBIT = 0x0020, +};
#define OMNIA_ATSHA204_OTP_VERSION 0 #define OMNIA_ATSHA204_OTP_SERIAL 1 @@ -85,48 +92,97 @@ static struct serdes_map board_serdes_map_sata[] = { {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0} };
-static bool omnia_detect_sata(void) +static struct udevice *omnia_get_i2c_chip(const char *name, uint addr, + uint offset_len) { struct udevice *bus, *dev; - int ret, retry = 3; - u16 mode; - - puts("SERDES0 card detect: "); + int ret;
- if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) { - puts("Cannot find MCU bus!\n"); - return false; + ret = uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_BUS_NAME, &bus); + if (ret) { + printf("Cannot get I2C bus %s: uclass_get_device_by_name failed: %i\n", + OMNIA_I2C_BUS_NAME, ret); + return NULL; }
- ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev); + ret = i2c_get_chip(bus, addr, offset_len, &dev); if (ret) { - puts("Cannot get MCU chip!\n"); - return false; + printf("Cannot get %s I2C chip: i2c_get_chip failed: %i\n", + name, ret); + return NULL; }
- for (; retry > 0; --retry) { - ret = dm_i2c_read(dev, OMNIA_I2C_MCU_ADDR_STATUS, (uchar *) &mode, 2); - if (!ret) - break; - } + return dev; +} + +static int omnia_mcu_read(u8 cmd, void *buf, int len) +{ + struct udevice *chip; + + chip = omnia_get_i2c_chip("MCU", OMNIA_I2C_MCU_CHIP_ADDR, + OMNIA_I2C_MCU_CHIP_LEN); + if (!chip) + return -ENODEV; + + return dm_i2c_read(chip, cmd, buf, len); +}
- if (!retry) { - puts("I2C read failed! Default PEX\n"); +#ifndef CONFIG_SPL_BUILD +static int omnia_mcu_write(u8 cmd, const void *buf, int len) +{ + struct udevice *chip; + + chip = omnia_get_i2c_chip("MCU", OMNIA_I2C_MCU_CHIP_ADDR, + OMNIA_I2C_MCU_CHIP_LEN); + if (!chip) + return -ENODEV; + + return dm_i2c_write(chip, cmd, buf, len); +} + +static bool disable_mcu_watchdog(void) +{ + int ret; + + puts("Disabling MCU watchdog... "); + + ret = omnia_mcu_write(CMD_WATCHDOG_STATE, "\x00", 1); + if (ret) { + printf("omnia_mcu_write failed: %i\n", ret); return false; }
- if (!(mode & OMNIA_I2C_MCU_CARDDET)) { - puts("NONE\n"); + puts("disabled\n"); + + return true; +} +#endif + +static bool omnia_detect_sata(void) +{ + int ret; + u16 stsword; + + puts("MiniPCIe/mSATA card detection... "); + + ret = omnia_mcu_read(CMD_GET_STATUS_WORD, &stsword, sizeof(stsword)); + if (ret) { + printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe card\n", + ret); return false; }
- if (mode & OMNIA_I2C_MCU_SATA) { - puts("SATA\n"); - return true; - } else { - puts("PEX\n"); + if (!(stsword & CARD_DET_STSBIT)) { + puts("none\n"); return false; } + + if (stsword & MSATA_IND_STSBIT) + puts("mSATA\n"); + else + puts("MiniPCIe\n"); + + return stsword & MSATA_IND_STSBIT ? true : false; }
int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) @@ -151,42 +207,32 @@ struct omnia_eeprom {
static bool omnia_read_eeprom(struct omnia_eeprom *oep) { - struct udevice *bus, *dev; - int ret, crc, retry = 3; + struct udevice *chip; + u32 crc; + int ret; + + chip = omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR, + OMNIA_I2C_EEPROM_CHIP_LEN);
- if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_EEPROM_DM_NAME, &bus)) { - puts("Cannot find EEPROM bus\n"); + if (!chip) return false; - }
- ret = i2c_get_chip(bus, OMNIA_I2C_EEPROM, OMNIA_I2C_EEPROM_ADDRLEN, &dev); + ret = dm_i2c_read(chip, 0, (void *)oep, sizeof(*oep)); if (ret) { - puts("Cannot get EEPROM chip\n"); + printf("dm_i2c_read failed: %i, cannot read EEPROM\n", ret); 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 (oep->magic != OMNIA_I2C_EEPROM_MAGIC) { + printf("bad EEPROM magic number (%08x, should be %08x)\n", + oep->magic, OMNIA_I2C_EEPROM_MAGIC); + return false; }
- if (!retry) { - puts("I2C EEPROM read failed!\n"); + crc = crc32(0, (void *)oep, sizeof(*oep) - 4); + if (crc != oep->crc) { + printf("bad EEPROM CRC (stored %08x, computed %08x)\n", + oep->crc, crc); return false; }
@@ -320,46 +366,13 @@ int board_early_init_f(void) 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 - int board_init(void) { /* adress of boot parameters */ gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
#ifndef CONFIG_SPL_BUILD - if (disable_mcu_watchdog()) - puts("Disabled MCU startup watchdog.\n"); - + disable_mcu_watchdog(); set_regdomain(); #endif

On 30.04.19 03:48, Marek Behún wrote:
Refactor code which accesses the microcontroller and EEPROM via I2C.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 6b8fa53c98..d4fb89f15f 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -290,12 +290,12 @@ static struct mv_ddr_topology_map board_topology_map_2g = {
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { - static int mem = 0; + static int mem; struct omnia_eeprom oep;
/* Get the board config from EEPROM */ - if (mem == 0) { - if(!omnia_read_eeprom(&oep)) + if (!mem) { + if (!omnia_read_eeprom(&oep)) goto out;
printf("Memory config in EEPROM: 0x%02x\n", oep.ramsize); @@ -368,7 +368,7 @@ int board_early_init_f(void)
int board_init(void) { - /* adress of boot parameters */ + /* address of boot parameters */ gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
#ifndef CONFIG_SPL_BUILD @@ -391,9 +391,9 @@ int board_late_init(void) #ifdef CONFIG_ATSHA204A static struct udevice *get_atsha204a_dev(void) { - static struct udevice *dev = NULL; + static struct udevice *dev;
- if (dev != NULL) + if (dev) return dev;
if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) { @@ -420,13 +420,13 @@ int checkboard(void)
err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, OMNIA_ATSHA204_OTP_VERSION, - (u8 *) &version_num); + (u8 *)&version_num); if (err) goto out;
err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false, OMNIA_ATSHA204_OTP_SERIAL, - (u8 *) &serial_num); + (u8 *)&serial_num); if (err) goto out;

On 30.04.19 03:48, Marek Behún wrote:
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

This driver is required for Turris Omnia to read ethernet addresses. Move the dependency from turris_omnia_defconfig to Kconfig.
Signed-off-by: Marek Behún marek.behun@nic.cz --- arch/arm/mach-mvebu/Kconfig | 1 + board/CZ.NIC/turris_omnia/turris_omnia.c | 11 ----------- configs/turris_omnia_defconfig | 1 - 3 files changed, 1 insertion(+), 12 deletions(-)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 2bf829d10a..fc29c3b084 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -121,6 +121,7 @@ config TARGET_TURRIS_OMNIA select I2C_MUX_PCA954x select SPL_I2C_MUX select SYS_I2C_MVTWSI + select ATSHA204A
config TARGET_TURRIS_MOX bool "Support Turris Mox" diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index d4fb89f15f..640ee2a2a3 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -18,10 +18,7 @@ #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> @@ -388,7 +385,6 @@ int board_late_init(void) return 0; }
-#ifdef CONFIG_ATSHA204A static struct udevice *get_atsha204a_dev(void) { static struct udevice *dev; @@ -403,14 +399,12 @@ static struct udevice *get_atsha204a_dev(void)
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) { @@ -434,8 +428,6 @@ int checkboard(void) }
out: -#endif - if (err) printf("Board: Turris Omnia (ver N/A). SN: N/A\n"); else @@ -458,7 +450,6 @@ static void increment_mac(u8 *mac)
int misc_init_r(void) { -#ifdef CONFIG_ATSHA204A int err; struct udevice *dev = get_atsha204a_dev(); u8 mac0[4], mac1[4], mac[6]; @@ -503,8 +494,6 @@ int misc_init_r(void) eth_env_set_enetaddr("eth2addr", mac);
out: -#endif - return 0; }
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 5086da13a5..5a09dc3033 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -47,7 +47,6 @@ CONFIG_AHCI_MVEBU=y CONFIG_SATA=y CONFIG_SCSI=y CONFIG_SCSI_AHCI=y -CONFIG_ATSHA204A=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y

On 30.04.19 03:48, Marek Behún wrote:
This driver is required for Turris Omnia to read ethernet addresses. Move the dependency from turris_omnia_defconfig to Kconfig.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Refactor RAM size reading from EEPROM in preparation for next patch.
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 58 ++++++++++++------------ 1 file changed, 28 insertions(+), 30 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 640ee2a2a3..8571541b0a 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -236,6 +236,31 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep) return true; }
+static int omnia_get_ram_size_gb(void) +{ + static int ram_size; + struct omnia_eeprom oep; + + if (!ram_size) { + /* Get the board config from EEPROM */ + if (omnia_read_eeprom(&oep)) { + debug("Memory config in EEPROM: 0x%02x\n", oep.ramsize); + + if (oep.ramsize == 0x2) + ram_size = 2; + else + ram_size = 1; + } else { + /* Hardcoded fallback */ + puts("Memory config from EEPROM read failed!\n"); + puts("Falling back to default 1 GiB!\n"); + ram_size = 1; + } + } + + return ram_size; +} + /* * 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 @@ -287,37 +312,10 @@ static struct mv_ddr_topology_map board_topology_map_2g = {
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { - static int mem; - struct omnia_eeprom oep; - - /* Get the board config from EEPROM */ - if (!mem) { - 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) + if (omnia_get_ram_size_gb() == 2) return &board_topology_map_2g; - - return &board_topology_map_1g; + else + return &board_topology_map_1g; }
#ifndef CONFIG_SPL_BUILD

On 30.04.19 03:48, Marek Behún wrote:
Refactor RAM size reading from EEPROM in preparation for next patch.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Unify the way how Omnia and Mox print board information (RAM size and serial number).
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 8571541b0a..54efd2d4c9 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -426,11 +426,13 @@ int checkboard(void) }
out: + printf("Turris Omnia:\n"); + printf(" RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024); if (err) - printf("Board: Turris Omnia (ver N/A). SN: N/A\n"); + printf(" Serial Number: unknown\n"); else - printf("Board: Turris Omnia SNL %08X%08X\n", - be32_to_cpu(version_num), be32_to_cpu(serial_num)); + printf(" Serial Number: %08X%08X\n", be32_to_cpu(version_num), + be32_to_cpu(serial_num));
return 0; }

On 30.04.19 03:48, Marek Behún wrote:
Unify the way how Omnia and Mox print board information (RAM size and serial number).
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

Since board watchdog is now unified and not handled in board files, remove the unnecessary includes.
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_mox/turris_mox.c | 4 ---- board/CZ.NIC/turris_omnia/turris_omnia.c | 4 ---- 2 files changed, 8 deletions(-)
diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 8a4872343b..3818e3752a 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -16,10 +16,6 @@ #include <fdt_support.h> #include <environment.h>
-#ifdef CONFIG_WDT_ARMADA_37XX -#include <wdt.h> -#endif - #include "mox_sp.h"
#define MAX_MOX_MODULES 10 diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 54efd2d4c9..b073a985a5 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -20,10 +20,6 @@ #include <time.h> # include <atsha204a-i2c.h>
-#ifdef CONFIG_WDT_ORION -# include <wdt.h> -#endif - #include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h>

On 30.04.19 03:48, Marek Behún wrote:
Since board watchdog is now unified and not handled in board files, remove the unnecessary includes.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

The regdomain environment variable is set according to value read from EEPROM. This has to be done in board_late_init, after the environment variables are read from SPI. Select CONFIG_BOARD_LATE_INIT in Kconfig for the Turris Omnia target.
Signed-off-by: Marek Behún marek.behun@nic.cz --- board/CZ.NIC/turris_omnia/turris_omnia.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index b073a985a5..af43ee23d9 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -364,7 +364,6 @@ int board_init(void)
#ifndef CONFIG_SPL_BUILD disable_mcu_watchdog(); - set_regdomain(); #endif
return 0;

On 30.04.19 03:48, Marek Behún wrote:
The regdomain environment variable is set according to value read from EEPROM. This has to be done in board_late_init, after the environment variables are read from SPI. Select CONFIG_BOARD_LATE_INIT in Kconfig for the Turris Omnia target.
Signed-off-by: Marek Behún marek.behun@nic.cz
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan

There is a Factory RESET button on the back side of the Turris Omnia router. When user presses this button before powering the device up and keeps it pressed, the microcontroller prevents the main CPU from booting and counts how long the RESET button is being pressed (and indicates this by lighting up front LEDs).
The idea behind this is that the user can boot the device into several Factory RESET modes.
This patch adds support for U-Boot to read into which Factory RESET mode the user booted the device. The value is an integer stored into the omnia_reset environment variable. It is 0 if the button was not pressed at all during power up, otherwise it is the number identifying the Factory RESET mode.
This patch also adds support for configuring (via Kconfig) if the bootcmd environment variable should be overwritten if this Factory RESET button was pressed during device powerup, and if this configuration option is enabled, the value by which bootcmd should be overwritten with is also a configurable option. The default value sets the colors of all the LEDs on the front panel to green, then loads the rescue system image from the SPI flash memory and then boots it.
Signed-off-by: Marek Behún marek.behun@nic.cz --- arch/arm/mach-mvebu/Kconfig | 43 ++++++++++++++++++++++++ board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++++++++++++ 2 files changed, 66 insertions(+)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index fc29c3b084..4229a505d1 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -116,6 +116,7 @@ config TARGET_DB_88F6820_AMC config TARGET_TURRIS_OMNIA bool "Support Turris Omnia" select 88F6820 + select BOARD_LATE_INIT select DM_I2C select I2C_MUX select I2C_MUX_PCA954x @@ -165,6 +166,48 @@ config TARGET_DB_XC3_24G4XG
endchoice
+if TARGET_TURRIS_OMNIA + +config TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD + bool "Turris Omnia RESET button overwrites bootcmd" + default y + help + There is a RESET button on the back side of the Turris Omnia router, + which is read by the microcontroller before the main CPU is booted. + If this button is pressed during device poweron, the CPU is only + booted after the button is released. + + The CPU can then read how long the RESET button was pressed (in time + intervals of cca 2 seconds, at most 12 different values), and U-Boot + stores this value into omnia_reset environment variable. + The microcontroller also lights up one front LED every time interval, + so that users can see the value they are forcing. + + If this option is enabled, the board code will also overwrite the + bootcmd variable with a constant configurable in this configuration + (config TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE) if the RESET button was + pressed for at least one time interval. + + Otherwise only the omnia_reset environment variable is set. + +config TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE + string "Turris Omnia RESET button bootcmd value" + default "i2c dev 2; i2c mw 0x2a.1 0x3 0x1c 1; i2c mw 0x2a.1 0x4 0x1c 1; mw.l 0x01000000 0x00ff000c; i2c write 0x01000000 0x2a.1 0x5 4 -s; setenv bootargs \"$bootargs omniarescue=$omnia_reset\"; sf probe; sf read 0x1000000 0x100000 0x700000; bootm 0x1000000; bootz 0x1000000" + depends on TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD + help + If the RESET button is pressed during device poweron and released at + least after cca 2 seconds, the bootcmd will be overwritten with this + value. + + You can use the omnia_reset environment variable in this command to + detect how long the reset button was pressed (or pass this value to + Linux as a boot parameter). + + The default value of this command set the front LEDs to green color + and then tries to boot rescue system from SPI memory. + +endif + config SYS_BOARD default "clearfog" if TARGET_CLEARFOG default "helios4" if TARGET_HELIOS4 diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index af43ee23d9..91fce6370c 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -328,6 +328,28 @@ static int set_regdomain(void) printf("Regdomain set to %s\n", rd); return env_set("regdomain", rd); } + +static void handle_reset_button(void) +{ + int ret; + u8 reset_status; + + ret = omnia_mcu_read(CMD_GET_RESET, &reset_status, 1); + if (ret) { + printf("omnia_mcu_read failed: %i, reset status unknown!\n", + ret); + return; + } + + env_set_ulong("omnia_reset", reset_status); + +#ifdef CONFIG_TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD + if (reset_status) { + printf("RESET button was pressed, overwriting bootcmd!\n"); + env_set("bootcmd", CONFIG_TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE); + } +#endif +} #endif
int board_early_init_f(void) @@ -373,6 +395,7 @@ int board_late_init(void) { #ifndef CONFIG_SPL_BUILD set_regdomain(); + handle_reset_button(); #endif
return 0;

On 30.04.19 03:48, Marek Behún wrote:
There is a Factory RESET button on the back side of the Turris Omnia router. When user presses this button before powering the device up and keeps it pressed, the microcontroller prevents the main CPU from booting and counts how long the RESET button is being pressed (and indicates this by lighting up front LEDs).
The idea behind this is that the user can boot the device into several Factory RESET modes.
This patch adds support for U-Boot to read into which Factory RESET mode the user booted the device. The value is an integer stored into the omnia_reset environment variable. It is 0 if the button was not pressed at all during power up, otherwise it is the number identifying the Factory RESET mode.
This patch also adds support for configuring (via Kconfig) if the bootcmd environment variable should be overwritten if this Factory RESET button was pressed during device powerup, and if this configuration option is enabled, the value by which bootcmd should be overwritten with is also a configurable option. The default value sets the colors of all the LEDs on the front panel to green, then loads the rescue system image from the SPI flash memory and then boots it.
Signed-off-by: Marek Behún marek.behun@nic.cz
arch/arm/mach-mvebu/Kconfig | 43 ++++++++++++++++++++++++ board/CZ.NIC/turris_omnia/turris_omnia.c | 23 +++++++++++++ 2 files changed, 66 insertions(+)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index fc29c3b084..4229a505d1 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -116,6 +116,7 @@ config TARGET_DB_88F6820_AMC config TARGET_TURRIS_OMNIA bool "Support Turris Omnia" select 88F6820
- select BOARD_LATE_INIT select DM_I2C select I2C_MUX select I2C_MUX_PCA954x
@@ -165,6 +166,48 @@ config TARGET_DB_XC3_24G4XG
endchoice
+if TARGET_TURRIS_OMNIA
+config TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD
- bool "Turris Omnia RESET button overwrites bootcmd"
- default y
- help
There is a RESET button on the back side of the Turris Omnia router,
which is read by the microcontroller before the main CPU is booted.
If this button is pressed during device poweron, the CPU is only
booted after the button is released.
The CPU can then read how long the RESET button was pressed (in time
intervals of cca 2 seconds, at most 12 different values), and U-Boot
stores this value into omnia_reset environment variable.
The microcontroller also lights up one front LED every time interval,
so that users can see the value they are forcing.
If this option is enabled, the board code will also overwrite the
bootcmd variable with a constant configurable in this configuration
(config TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE) if the RESET button was
pressed for at least one time interval.
Otherwise only the omnia_reset environment variable is set.
+config TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE
- string "Turris Omnia RESET button bootcmd value"
- default "i2c dev 2; i2c mw 0x2a.1 0x3 0x1c 1; i2c mw 0x2a.1 0x4 0x1c 1; mw.l 0x01000000 0x00ff000c; i2c write 0x01000000 0x2a.1 0x5 4 -s; setenv bootargs \"$bootargs omniarescue=$omnia_reset\"; sf probe; sf read 0x1000000 0x100000 0x700000; bootm 0x1000000; bootz 0x1000000"
- depends on TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD
- help
If the RESET button is pressed during device poweron and released at
least after cca 2 seconds, the bootcmd will be overwritten with this
value.
You can use the omnia_reset environment variable in this command to
detect how long the reset button was pressed (or pass this value to
Linux as a boot parameter).
The default value of this command set the front LEDs to green color
and then tries to boot rescue system from SPI memory.
+endif
I fail to see a real reason to introduce these Kconfig options. Is TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD enabled for your board? If not it just adds dead code, as no other board will ever enable it. So do you plan to add 2 Omnia build targets, one with and one w/o this option enabled? Or what is your plan here?
Thanks, Stefan
- config SYS_BOARD default "clearfog" if TARGET_CLEARFOG default "helios4" if TARGET_HELIOS4
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index af43ee23d9..91fce6370c 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -328,6 +328,28 @@ static int set_regdomain(void) printf("Regdomain set to %s\n", rd); return env_set("regdomain", rd); }
+static void handle_reset_button(void) +{
- int ret;
- u8 reset_status;
- ret = omnia_mcu_read(CMD_GET_RESET, &reset_status, 1);
- if (ret) {
printf("omnia_mcu_read failed: %i, reset status unknown!\n",
ret);
return;
- }
- env_set_ulong("omnia_reset", reset_status);
+#ifdef CONFIG_TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD
- if (reset_status) {
printf("RESET button was pressed, overwriting bootcmd!\n");
env_set("bootcmd", CONFIG_TURRIS_OMNIA_RSTBTN_BOOTCMD_VALUE);
- }
+#endif +} #endif
int board_early_init_f(void) @@ -373,6 +395,7 @@ int board_late_init(void) { #ifndef CONFIG_SPL_BUILD set_regdomain();
handle_reset_button(); #endif
return 0;
Viele Grüße, Stefan

On Thu, 2 May 2019 08:10:36 +0200 Stefan Roese sr@denx.de wrote:
I fail to see a real reason to introduce these Kconfig options. Is TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD enabled for your board? If not it just adds dead code, as no other board will ever enable it. So do you plan to add 2 Omnia build targets, one with and one w/o this option enabled? Or what is your plan here?
Thanks, Stefan
My idea was that the users should be able to disable this functionality, if they are compiling u-boot themselves, but we are going to ship Omnias with this config enabled.
I can of course remove the Kconfig options and enable this reset button handling all times.
Marek

On 02.05.19 11:39, Marek Behun wrote:
On Thu, 2 May 2019 08:10:36 +0200 Stefan Roese sr@denx.de wrote:
I fail to see a real reason to introduce these Kconfig options. Is TURRIS_OMNIA_RSTBTN_OVERWRITE_BOOTCMD enabled for your board? If not it just adds dead code, as no other board will ever enable it. So do you plan to add 2 Omnia build targets, one with and one w/o this option enabled? Or what is your plan here?
Thanks, Stefan
My idea was that the users should be able to disable this functionality, if they are compiling u-boot themselves, but we are going to ship Omnias with this config enabled.
Understood, thanks.
I can of course remove the Kconfig options and enable this reset button handling all times.
Please do so. If someone whats to disable this functionality or change the reset button bootcmd, then he/she/it must do some changes (defconfig or code).
Thanks, Stefan

On Thu, 2 May 2019 11:43:12 +0200 Stefan Roese sr@denx.de wrote:
Please do so. If someone whats to disable this functionality or change the reset button bootcmd, then he/she/it must do some changes (defconfig or code).
So should I remove the options from Kconfig or enable them by default?
BTW: We are going to ship omnia with several other options enabled? Should I push them also to defconfig?
They are:
CONFIG_FIT=y CONFIG_FIT_ENABLE_SHA256_SUPPORT=y CONFIG_FIT_VERBOSE=y CONFIG_CMD_LZMADEC=y CONFIG_CMD_AES=y CONFIG_CMD_HASH=y CONFIG_CMD_SHA1SUM=y
Marek

On 02.05.19 13:53, Marek Behún wrote:
On Thu, 2 May 2019 11:43:12 +0200 Stefan Roese sr@denx.de wrote:
Please do so. If someone whats to disable this functionality or change the reset button bootcmd, then he/she/it must do some changes (defconfig or code).
So should I remove the options from Kconfig or enable them by default?
Yes.
BTW: We are going to ship omnia with several other options enabled? Should I push them also to defconfig?
Yes please. Or why would it make sense to have a stripped down version of this board port in mainline?
They are:
CONFIG_FIT=y CONFIG_FIT_ENABLE_SHA256_SUPPORT=y CONFIG_FIT_VERBOSE=y CONFIG_CMD_LZMADEC=y CONFIG_CMD_AES=y CONFIG_CMD_HASH=y CONFIG_CMD_SHA1SUM=y
Marek
Thanks, Stefan

The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register.
On our device this sometimes causes bad value being read from status register, as if the value was not yet updated.
My theory is that the controller does approximately this: 1. sets interrupt flag in control register, 2. sets the value of status register, 3. causes an interrupt
In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2.
The bug does not appear if I add a small delay before reading status register.
Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register.
Signed-off-by: Marek Behún marek.behun@nic.cz Cc: Mario Six mario.six@gdsys.cc Cc: Stefan Roese sr@denx.de Cc: Baruch Siach baruch@tkos.co.il Cc: Heiko Schocher hs@denx.de --- drivers/i2c/mvtwsi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 74ac0a4aa7..483a71ba12 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -271,6 +271,7 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) { + ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0;

Hello Marek,
Am 30.04.2019 um 03:48 schrieb Marek Behún:
The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register.
On our device this sometimes causes bad value being read from status register, as if the value was not yet updated.
My theory is that the controller does approximately this:
- sets interrupt flag in control register,
- sets the value of status register,
- causes an interrupt
In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2.
The bug does not appear if I add a small delay before reading status register.
Strange.
Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register.
Signed-off-by: Marek Behún marek.behun@nic.cz Cc: Mario Six mario.six@gdsys.cc Cc: Stefan Roese sr@denx.de Cc: Baruch Siach baruch@tkos.co.il Cc: Heiko Schocher hs@denx.de
drivers/i2c/mvtwsi.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 74ac0a4aa7..483a71ba12 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -271,6 +271,7 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) {
ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0;
Can you please add a comment in the code too?
Beside of that:
Acked-by: Heiko Schocher hs@denx.de
bye, Heiko

The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register.
On our device this sometimes causes bad value being read from status register, as if the value was not yet updated.
My theory is that the controller does approximately this: 1. sets interrupt flag in control register, 2. sets the value of status register, 3. causes an interrupt
In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2.
The bug does not appear if I add a small delay before reading status register.
Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register.
Signed-off-by: Marek Behún marek.behun@nic.cz Acked-by: Heiko Schocher hs@denx.de Cc: Mario Six mario.six@gdsys.cc Cc: Stefan Roese sr@denx.de Cc: Baruch Siach baruch@tkos.co.il --- drivers/i2c/mvtwsi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 74ac0a4aa7..0a2dafcec6 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -271,6 +271,17 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) { + /* + * On Armada 38x it seems that the controller works as + * if it first set the MVTWSI_CONTROL_IFLAG in the + * control register and only after that it changed the + * status register. + * This sometimes caused weird bugs which only appeared + * on selected I2C speeds and even then only sometimes. + * We therefore add here a simple ndealy(100), which + * seems to fix this weird bug. + */ + ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0;

Hello Marek,
Am 01.05.2019 um 23:09 schrieb Marek Behún:
The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register.
On our device this sometimes causes bad value being read from status register, as if the value was not yet updated.
My theory is that the controller does approximately this:
- sets interrupt flag in control register,
- sets the value of status register,
- causes an interrupt
In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2.
The bug does not appear if I add a small delay before reading status register.
Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register.
Signed-off-by: Marek Behún marek.behun@nic.cz Acked-by: Heiko Schocher hs@denx.de Cc: Mario Six mario.six@gdsys.cc Cc: Stefan Roese sr@denx.de Cc: Baruch Siach baruch@tkos.co.il
drivers/i2c/mvtwsi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
Thanks for adding the comment
Reviewed-by: Heiko Schocher hs@denx.de
bye, Heiko

On 01.05.19 23:09, Marek Behún wrote:
The twsi_wait function reads the control register for interrupt flag, and if interrupt flag is present, it immediately reads status register.
On our device this sometimes causes bad value being read from status register, as if the value was not yet updated.
My theory is that the controller does approximately this:
- sets interrupt flag in control register,
- sets the value of status register,
- causes an interrupt
In U-Boot we do not use interrupts, so I think that it is possible that sometimes the status register in the twsi_wait function is read between points 1 and 2.
The bug does not appear if I add a small delay before reading status register.
Wait 100ns (which in U-Boot currently means 1 us, because ndelay(i) function calls udelay(DIV_ROUND_UP(i, 1000))) before reading the status register.
Signed-off-by: Marek Behún marek.behun@nic.cz Acked-by: Heiko Schocher hs@denx.de Cc: Mario Six mario.six@gdsys.cc Cc: Stefan Roese sr@denx.de Cc: Baruch Siach baruch@tkos.co.il
drivers/i2c/mvtwsi.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c index 74ac0a4aa7..0a2dafcec6 100644 --- a/drivers/i2c/mvtwsi.c +++ b/drivers/i2c/mvtwsi.c @@ -271,6 +271,17 @@ static int twsi_wait(struct mvtwsi_registers *twsi, int expected_status, do { control = readl(&twsi->control); if (control & MVTWSI_CONTROL_IFLG) {
/*
* On Armada 38x it seems that the controller works as
* if it first set the MVTWSI_CONTROL_IFLAG in the
* control register and only after that it changed the
* status register.
* This sometimes caused weird bugs which only appeared
* on selected I2C speeds and even then only sometimes.
* We therefore add here a simple ndealy(100), which
* seems to fix this weird bug.
*/
ndelay(100); status = readl(&twsi->status); if (status == expected_status) return 0;
This still looks a bit strange. Looking at the Linux driver, there is no delay after reading the control register. But its using interrupts and therefore an implicit delay is added before this interrupt service routine is called (instead of the busy loop here in the U-Boot driver).
So since I don't have a better idea:
Reviewed-by: Stefan Roese sr@denx.de
BTW: Whats the value of "tick" in twsi_wait() in your case?
Thanks, Stefan

This still looks a bit strange. Looking at the Linux driver, there is no delay after reading the control register. But its using interrupts and therefore an implicit delay is added before this interrupt service routine is called (instead of the busy loop here in the U-Boot driver).
Exactly my opinion as well.
BTW: Whats the value of "tick" in twsi_wait() in your case?
requested I2C freq is 100000 Hz, actual 97656 Hz (nearest lower possible). This calculates the tick to 10340 ns with calc_tick, and u-boot sleeps for 11 ms (DIV_ROUND_UP).
When tick was 10 ms this bug did not occur, because of the different timing when the control value was read it already was set for a while by the controller, it seems.
Btw should I sent these first 14 patches with Reviewed-by tags?
Marek

On 02.05.19 11:36, Marek Behun wrote:
This still looks a bit strange. Looking at the Linux driver, there is no delay after reading the control register. But its using interrupts and therefore an implicit delay is added before this interrupt service routine is called (instead of the busy loop here in the U-Boot driver).
Exactly my opinion as well.
BTW: Whats the value of "tick" in twsi_wait() in your case?
requested I2C freq is 100000 Hz, actual 97656 Hz (nearest lower possible). This calculates the tick to 10340 ns with calc_tick, and u-boot sleeps for 11 ms (DIV_ROUND_UP).
When tick was 10 ms this bug did not occur, because of the different timing when the control value was read it already was set for a while by the controller, it seems.
Btw should I sent these first 14 patches with Reviewed-by tags?
No need for that, thanks. Patchwork will pick up the tags automatically.
Next time, please switch to v3 instead of v2.1 though.
Thanks, Stefan
participants (4)
-
Heiko Schocher
-
Marek Behun
-
Marek Behún
-
Stefan Roese