From 42595eb7067c6c076e1c98213438be727f883fe2 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:06:24 +0530 Subject: [PATCH 01/13] misc: add sl28cpld base driver Add a multi-function device driver which will probe its children and provides methods to access the device. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- MAINTAINERS | 5 ++ drivers/misc/Kconfig | 8 +++ drivers/misc/Makefile | 1 + drivers/misc/sl28cpld.c | 105 ++++++++++++++++++++++++++++++++++++++++ include/sl28cpld.h | 14 ++++++ 5 files changed, 133 insertions(+) create mode 100644 drivers/misc/sl28cpld.c create mode 100644 include/sl28cpld.h diff --git a/MAINTAINERS b/MAINTAINERS index fb171e0c687..8b3870ff964 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1161,6 +1161,11 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git F: arch/sh/ +SL28CLPD +M: Michael Walle +S: Maintained +F: drivers/misc/sl28cpld.c + SPI M: Jagan Teki S: Maintained diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0ade3e32b0e..7029bb7b5c5 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -512,4 +512,12 @@ config ESM_PMIC config FSL_IFC bool +config SL28CPLD + bool "Enable Kontron sl28cpld multi-function driver" + depends on DM_I2C + help + Support for the Kontron sl28cpld management controller. This is + the base driver which provides common access methods for the + sub-drivers. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bca7b24e99a..f22eff601a1 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -82,3 +82,4 @@ obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_ESM_PMIC) += esm_pmic.o +obj-$(CONFIG_SL28CPLD) += sl28cpld.o diff --git a/drivers/misc/sl28cpld.c b/drivers/misc/sl28cpld.c new file mode 100644 index 00000000000..01ef1c6178f --- /dev/null +++ b/drivers/misc/sl28cpld.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include + +struct sl28cpld_child_plat { + uint offset; +}; + +/* + * The access methods works either with the first argument being a child + * device or with the MFD device itself. + */ +static int sl28cpld_read_child(struct udevice *dev, uint offset) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_read(mfd, offset + plat->offset); +} + +int sl28cpld_read(struct udevice *dev, uint offset) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_read(dev, offset); + else + return sl28cpld_read_child(dev, offset); +} + +static int sl28cpld_write_child(struct udevice *dev, uint offset, + uint8_t value) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_write(mfd, offset + plat->offset, value); +} + +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_write(dev, offset, value); + else + return sl28cpld_write_child(dev, offset, value); +} + +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, + uint8_t set) +{ + int val; + + val = sl28cpld_read(dev, offset); + if (val < 0) + return val; + + val &= ~clear; + val |= set; + + return sl28cpld_write(dev, offset, val); +} + +static int sl28cpld_probe(struct udevice *dev) +{ + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | + DM_I2C_CHIP_WR_ADDRESS); + + return 0; +} + +static int sl28cpld_child_post_bind(struct udevice *dev) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + int offset; + + if (!dev_has_ofnode(dev)) + return 0; + + offset = dev_read_u32_default(dev, "reg", -1); + if (offset == -1) + return -EINVAL; + + plat->offset = offset; + + return 0; +} + +static const struct udevice_id sl28cpld_ids[] = { + { .compatible = "kontron,sl28cpld" }, + {} +}; + +U_BOOT_DRIVER(sl28cpld) = { + .name = "sl28cpld", + .id = UCLASS_NOP, + .of_match = sl28cpld_ids, + .probe = sl28cpld_probe, + .bind = dm_scan_fdt_dev, + .flags = DM_FLAG_PRE_RELOC, + .per_child_plat_auto = sizeof(struct sl28cpld_child_plat), + .child_post_bind = sl28cpld_child_post_bind, +}; diff --git a/include/sl28cpld.h b/include/sl28cpld.h new file mode 100644 index 00000000000..d116607cfb1 --- /dev/null +++ b/include/sl28cpld.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Michael Walle + */ + +#ifndef __SL28CPLD_H +#define __SL28CPLD_H + +int sl28cpld_read(struct udevice *dev, uint offset); +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value); +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, + uint8_t set); + +#endif From f606c9a8959728f7df539e182fb799d3ccc92cc6 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:43 +0100 Subject: [PATCH 02/13] watchdog: add sl28cpld watchdog driver The watchdog timer is part of the sl28cpld management controller. The watchdog timer usually supervises the bootloader boot-up and if it bites the failsafe bootloader will be activated. Apart from that it supports the usual board level reset and one SMARC speciality: driving the WDT_TIMEOUT# signal. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- MAINTAINERS | 1 + doc/board/kontron/sl28.rst | 53 +++++++++++----- drivers/watchdog/Kconfig | 7 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sl28cpld-wdt.c | 109 ++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 drivers/watchdog/sl28cpld-wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 8b3870ff964..989ea41e2c3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1165,6 +1165,7 @@ SL28CLPD M: Michael Walle S: Maintained F: drivers/misc/sl28cpld.c +F: drivers/watchdog/sl28cpld-wdt.c SPI M: Jagan Teki diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index c7b18bed10c..c2cdc5e4241 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -35,23 +35,6 @@ The board is fully failsafe, you can't break anything. But because you've disabled the builtin watchdog you might have to manually enter failsafe mode by asserting the ``FORCE_RECOV#`` line during board reset. -Disable the builtin watchdog -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -- boot into the failsafe bootloader, either by asserting the - ``FORCE_RECOV#`` line or if you still have the original bootloader - installed you can use the command:: - - > wdt dev cpld_watchdog@4a; wdt expire 1 - -- in the failsafe bootloader use the "sl28 nvm" command to disable - the automatic start of the builtin watchdog:: - - > sl28 nvm 0008 - -- power-cycle the board - - Update image ------------ @@ -82,6 +65,42 @@ u-boot (yet). But you can use the i2c command to access it. > i2c md 4a 3.1 1 +Builtin watchdog +---------------- + +The builtin watchdog will supervise the bootloader startup. If anything +goes wrong it will reset the board and boot into the failsafe bootloader. + +Once the bootloader is started successfully, it will disable the watchdog +timer. + +wdt command flags +^^^^^^^^^^^^^^^^^ + +The `wdt start` as well as the `wdt expire` command take a flags argument. +The supported bitmask is as follows. + +| Bit | Description | +| --- | ----------------------------- | +| 0 | Enable failsafe mode | +| 1 | Lock the control register | +| 2 | Disable board reset | +| 3 | Enable WDT_TIME_OUT# line | + +For example, you can use `wdt expire 1` to issue a reset and boot into the +failsafe bootloader. + +Disable the builtin watchdog +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If for some reason, this isn't a desired behavior, the watchdog can also +be configured to not be enabled on board reset. It's configuration is saved +in the non-volatile board configuration bits. To change these you can use +the `sl28 nvm` command. + +For more information on the non-volatile board configuration bits, see the +following section. + Non-volatile Board Configuration Bits ------------------------------------- diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cabac290539..f90f0ca02bc 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -266,6 +266,13 @@ config WDT_SBSA In the single stage mode, when the timeout is reached, your system will be reset by WS1. The first signal (WS0) is ignored. +config WDT_SL28CPLD + bool "sl28cpld watchdog timer support" + depends on WDT && SL28CPLD + help + Enable support for the watchdog timer in the Kontron sl28cpld + management controller. + config WDT_SP805 bool "SP805 watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 6d2b3822c06..a35bd559f51 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o +obj-$(CONFIG_WDT_SL28CPLD) += sl28cpld-wdt.o obj-$(CONFIG_WDT_SP805) += sp805_wdt.o obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o diff --git a/drivers/watchdog/sl28cpld-wdt.c b/drivers/watchdog/sl28cpld-wdt.c new file mode 100644 index 00000000000..af5a6b1a28a --- /dev/null +++ b/drivers/watchdog/sl28cpld-wdt.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Watchdog driver for the sl28cpld + * + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include +#include +#include + +#define SL28CPLD_WDT_CTRL 0x00 +#define WDT_CTRL_EN0 BIT(0) +#define WDT_CTRL_EN1 BIT(1) +#define WDT_CTRL_EN_MASK GENMASK(1, 0) +#define WDT_CTRL_LOCK BIT(2) +#define WDT_CTRL_ASSERT_SYS_RESET BIT(6) +#define WDT_CTRL_ASSERT_WDT_TIMEOUT BIT(7) +#define SL28CPLD_WDT_TIMEOUT 0x01 +#define SL28CPLD_WDT_KICK 0x02 +#define WDT_KICK_VALUE 0x6b + +static int sl28cpld_wdt_reset(struct udevice *dev) +{ + return sl28cpld_write(dev, SL28CPLD_WDT_KICK, WDT_KICK_VALUE); +} + +static int sl28cpld_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + int ret, val; + + val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL); + if (val < 0) + return val; + + /* (1) disable watchdog */ + val &= ~WDT_CTRL_EN_MASK; + ret = sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val); + if (ret) + return ret; + + /* (2) set timeout */ + ret = sl28cpld_write(dev, SL28CPLD_WDT_TIMEOUT, lldiv(timeout, 1000)); + if (ret) + return ret; + + /* (3) kick it, will reset timer to the timeout value */ + ret = sl28cpld_wdt_reset(dev); + if (ret) + return ret; + + /* (4) enable either recovery or normal one */ + if (flags & BIT(0)) + val |= WDT_CTRL_EN1; + else + val |= WDT_CTRL_EN0; + + if (flags & BIT(1)) + val |= WDT_CTRL_LOCK; + + if (flags & BIT(2)) + val &= ~WDT_CTRL_ASSERT_SYS_RESET; + else + val |= WDT_CTRL_ASSERT_SYS_RESET; + + if (flags & BIT(3)) + val |= WDT_CTRL_ASSERT_WDT_TIMEOUT; + else + val &= ~WDT_CTRL_ASSERT_WDT_TIMEOUT; + + return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val); +} + +static int sl28cpld_wdt_stop(struct udevice *dev) +{ + int val; + + val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL); + if (val < 0) + return val; + + return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val & ~WDT_CTRL_EN_MASK); +} + +static int sl28cpld_wdt_expire_now(struct udevice *dev, ulong flags) +{ + return sl28cpld_wdt_start(dev, 0, flags); +} + +static const struct wdt_ops sl28cpld_wdt_ops = { + .start = sl28cpld_wdt_start, + .reset = sl28cpld_wdt_reset, + .stop = sl28cpld_wdt_stop, + .expire_now = sl28cpld_wdt_expire_now, +}; + +static const struct udevice_id sl28cpld_wdt_ids[] = { + { .compatible = "kontron,sl28cpld-wdt", }, + {} +}; + +U_BOOT_DRIVER(sl28cpld_wdt) = { + .name = "sl28cpld-wdt", + .id = UCLASS_WDT, + .of_match = sl28cpld_wdt_ids, + .ops = &sl28cpld_wdt_ops, +}; From 07d6cb93781d47a8cb94c63b6419c68923b6f09d Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:10:24 +0530 Subject: [PATCH 03/13] gpio: add sl28cpld driver The gpio block is part of the sl28cpld sl28cpld management controller. There are three different flavors: the usual input and output where the direction is configurable, but also input only and output only variants. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- MAINTAINERS | 1 + drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/sl28cpld-gpio.c | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 drivers/gpio/sl28cpld-gpio.c diff --git a/MAINTAINERS b/MAINTAINERS index 989ea41e2c3..0f39bc6bc92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1164,6 +1164,7 @@ F: arch/sh/ SL28CLPD M: Michael Walle S: Maintained +F: drivers/gpio/sl28cpld-gpio.c F: drivers/misc/sl28cpld.c F: drivers/watchdog/sl28cpld-wdt.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8d0e47c67d9..522dfc195ec 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -544,4 +544,10 @@ config ZYNQMP_GPIO_MODEPIN are accessed using xilinx firmware. In modepin register, [3:0] bits set direction, [7:4] bits read IO, [11:8] bits set/clear IO. +config SL28CPLD_GPIO + bool "Kontron sl28cpld GPIO driver" + depends on DM_GPIO && SL28CPLD + help + Support GPIO access on Kontron sl28cpld board management controllers. + endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 63e9be6034f..33f7d41b7db 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -70,4 +70,5 @@ obj-$(CONFIG_NX_GPIO) += nx_gpio.o obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o +obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o diff --git a/drivers/gpio/sl28cpld-gpio.c b/drivers/gpio/sl28cpld-gpio.c new file mode 100644 index 00000000000..700fc3df298 --- /dev/null +++ b/drivers/gpio/sl28cpld-gpio.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * GPIO driver for the sl28cpld + * + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include +#include + +/* GPIO flavor */ +#define SL28CPLD_GPIO_DIR 0x00 +#define SL28CPLD_GPIO_OUT 0x01 +#define SL28CPLD_GPIO_IN 0x02 + +/* input-only flavor */ +#define SL28CPLD_GPI_IN 0x00 + +/* output-only flavor */ +#define SL28CPLD_GPO_OUT 0x00 + +enum { + SL28CPLD_GPIO, + SL28CPLD_GPI, + SL28CPLD_GPO, +}; + +static int sl28cpld_gpio_get_value(struct udevice *dev, unsigned int gpio) +{ + ulong type = dev_get_driver_data(dev); + int val, reg; + + switch (type) { + case SL28CPLD_GPIO: + reg = SL28CPLD_GPIO_IN; + break; + case SL28CPLD_GPI: + reg = SL28CPLD_GPI_IN; + break; + case SL28CPLD_GPO: + /* we are output only, thus just return the output value */ + reg = SL28CPLD_GPO_OUT; + break; + default: + return -EINVAL; + } + + val = sl28cpld_read(dev, reg); + + return val < 0 ? val : !!(val & BIT(gpio)); +} + +static int sl28cpld_gpio_set_value(struct udevice *dev, unsigned int gpio, + int value) +{ + ulong type = dev_get_driver_data(dev); + uint reg; + + switch (type) { + case SL28CPLD_GPIO: + reg = SL28CPLD_GPIO_OUT; + break; + case SL28CPLD_GPO: + reg = SL28CPLD_GPO_OUT; + break; + case SL28CPLD_GPI: + default: + return -EINVAL; + } + + if (value) + return sl28cpld_update(dev, reg, 0, BIT(gpio)); + else + return sl28cpld_update(dev, reg, BIT(gpio), 0); +} + +static int sl28cpld_gpio_direction_input(struct udevice *dev, unsigned int gpio) +{ + ulong type = dev_get_driver_data(dev); + + switch (type) { + case SL28CPLD_GPI: + return 0; + case SL28CPLD_GPIO: + return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, BIT(gpio), 0); + case SL28CPLD_GPO: + default: + return -EINVAL; + } +} + +static int sl28cpld_gpio_direction_output(struct udevice *dev, + unsigned int gpio, int value) +{ + ulong type = dev_get_driver_data(dev); + int ret; + + /* set_value() will report an error if we are input-only */ + ret = sl28cpld_gpio_set_value(dev, gpio, value); + if (ret) + return ret; + + if (type == SL28CPLD_GPIO) + return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, 0, BIT(gpio)); + + return 0; +} + +static int sl28cpld_gpio_get_function(struct udevice *dev, unsigned int gpio) +{ + ulong type = dev_get_driver_data(dev); + int val; + + switch (type) { + case SL28CPLD_GPIO: + val = sl28cpld_read(dev, SL28CPLD_GPIO_DIR); + if (val < 0) + return val; + if (val & BIT(gpio)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; + case SL28CPLD_GPI: + return GPIOF_INPUT; + case SL28CPLD_GPO: + return GPIOF_OUTPUT; + default: + return -EINVAL; + } +} + +static const struct dm_gpio_ops sl28cpld_gpio_ops = { + .direction_input = sl28cpld_gpio_direction_input, + .direction_output = sl28cpld_gpio_direction_output, + .get_value = sl28cpld_gpio_get_value, + .set_value = sl28cpld_gpio_set_value, + .get_function = sl28cpld_gpio_get_function, +}; + +static int sl28cpld_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->gpio_count = 8; + uc_priv->bank_name = dev_read_name(dev); + + return 0; +} + +static const struct udevice_id sl28cpld_gpio_ids[] = { + { .compatible = "kontron,sl28cpld-gpio", .data = SL28CPLD_GPIO}, + { .compatible = "kontron,sl28cpld-gpo", .data = SL28CPLD_GPO}, + { .compatible = "kontron,sl28cpld-gpi", .data = SL28CPLD_GPI}, + { } +}; + +U_BOOT_DRIVER(sl28cpld_gpio) = { + .name = "sl28cpld_gpio", + .id = UCLASS_GPIO, + .of_match = sl28cpld_gpio_ids, + .probe = sl28cpld_gpio_probe, + .ops = &sl28cpld_gpio_ops, +}; From fea51613222edba814d33a21d9485463cf3988f3 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:45 +0100 Subject: [PATCH 04/13] board: sl28: fix DRAM pretty print The current console output is: DRAM: 4 GiB DDR 4 GiB (DDR3, 32-bit, CL=11, ECC on) The size is printed twice and we can save one line of console output if we join both lines. The new output is as follows: DRAM: 4 GiB (DDR3, 32-bit, CL=11, ECC on) Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index e84b3569186..a4ee8a1ef3e 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -47,8 +47,6 @@ int checkboard(void) void detail_board_ddr_info(void) { - puts("\nDDR "); - print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); print_ddr_info(0); } From d36b683a0f4d9cd22aded61595b771c88203f3ab Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:46 +0100 Subject: [PATCH 05/13] board: sl28: print CPLD version on bootup Most of the time it is very useful to have the version of the board management controller. Now that we have a driver, print it during startup. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 28 ++++++++++++++++++++++++++++ include/sl28cpld.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index a4ee8a1ef3e..9cde48e61ef 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include +#include #include #include @@ -39,9 +41,35 @@ int board_eth_init(struct bd_info *bis) return pci_eth_init(bis); } +static int __sl28cpld_read(uint reg) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_NOP, + DM_DRIVER_GET(sl28cpld), &dev); + if (ret) + return ret; + + return sl28cpld_read(dev, reg); +} + +static void print_cpld_version(void) +{ + int version = __sl28cpld_read(SL28CPLD_VERSION); + + if (version < 0) + printf("CPLD: error reading version (%d)\n", version); + else + printf("CPLD: v%d\n", version); +} + int checkboard(void) { printf("EL: %d\n", current_el()); + if (CONFIG_IS_ENABLED(SL28CPLD)) + print_cpld_version(); + return 0; } diff --git a/include/sl28cpld.h b/include/sl28cpld.h index d116607cfb1..9a7c6de31f5 100644 --- a/include/sl28cpld.h +++ b/include/sl28cpld.h @@ -6,6 +6,8 @@ #ifndef __SL28CPLD_H #define __SL28CPLD_H +#define SL28CPLD_VERSION 0x03 + int sl28cpld_read(struct udevice *dev, uint offset); int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value); int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, From 34502f7aa343c58c9b4a7206e9fd44e3b89b4dea Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:47 +0100 Subject: [PATCH 06/13] board: sl28: enable sl28cpld support Enable the GPIO and watchdog driver. Don't start the watchdog automatically, though. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index b61276cf1dd..a0c0c3c6a19 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -42,12 +42,14 @@ CONFIG_CMD_GREPENV=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_DFU=y CONFIG_CMD_DM=y +CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_WDT=y CONFIG_CMD_CACHE=y CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_RNG=y @@ -69,8 +71,10 @@ CONFIG_DDR_ECC=y CONFIG_ECC_INIT_VIA_DDRCONTROLLER=y CONFIG_DFU_MMC=y CONFIG_DFU_SF=y +CONFIG_SL28CPLD_GPIO=y CONFIG_I2C_SET_DEFAULT_BUS_NUM=y CONFIG_I2C_MUX=y +CONFIG_SL28CPLD=y CONFIG_MMC_HS400_SUPPORT=y CONFIG_FSL_ESDHC=y CONFIG_FSL_ESDHC_SUPPORT_ADMA2=y @@ -102,6 +106,10 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_LAYERSCAPE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DOWNLOAD=y +# CONFIG_WATCHDOG is not set +# CONFIG_WATCHDOG_AUTOSTART is not set +CONFIG_WDT=y +CONFIG_WDT_SL28CPLD=y CONFIG_OF_LIBFDT_ASSUME_MASK=0x0 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_EFI_SET_TIME=y From 2ba8a446ceece208c5926b623ddfd66bd163ff27 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:48 +0100 Subject: [PATCH 07/13] board: sl28: enable SoC watchdog support The SoC provides two additional watchdogs integrated in the SoC. Enable support for these. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index a0c0c3c6a19..a4d9254815a 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -110,6 +110,7 @@ CONFIG_USB_GADGET_DOWNLOAD=y # CONFIG_WATCHDOG_AUTOSTART is not set CONFIG_WDT=y CONFIG_WDT_SL28CPLD=y +CONFIG_WDT_SP805=y CONFIG_OF_LIBFDT_ASSUME_MASK=0x0 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_EFI_SET_TIME=y From 453d1711d22c4bccd48848a8450aa95cbc5008cc Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:49 +0100 Subject: [PATCH 08/13] board: sl28: disable recovery watchdog This board has an internal watchdog which supervises the board startup. Although, the initial state of the watchdog is configurable, it is enabled by default. In board_late_init(), which means almost everything worked as expected, disable the watchdog. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 29 +++++++++++++++++++++++++++++ doc/board/kontron/sl28.rst | 12 ++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index 9cde48e61ef..3c48a9141d0 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,34 @@ int checkboard(void) return 0; } +static void stop_recovery_watchdog(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_WDT, + DM_DRIVER_GET(sl28cpld_wdt), &dev); + if (!ret) + wdt_stop(dev); +} + +int fsl_board_late_init(void) +{ + /* + * Usually, the after a board reset, the watchdog is enabled by + * default. This is to supervise the bootloader boot-up. Therefore, + * to prevent a watchdog reset if we don't actively kick it, we have + * to disable it. + * + * If the watchdog isn't enabled at reset (which is a configuration + * option) disabling it doesn't hurt either. + */ + if (!CONFIG_IS_ENABLED(WATCHDOG_AUTOSTART)) + stop_recovery_watchdog(); + + return 0; +} + void detail_board_ddr_info(void) { print_ddr_info(0); diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index c2cdc5e4241..04483e1e573 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -23,17 +23,17 @@ Copy u-boot.rom to a TFTP server. Install the bootloader on the board ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Please note, this bootloader doesn't support the builtin watchdog (yet), -therefore you have to disable it, see below. Otherwise you'll end up in -the failsafe bootloader on every reset:: +To install the bootloader binary use the following command:: > tftp path/to/u-boot.rom > sf probe 0 > sf update $fileaddr 0x210000 $filesize -The board is fully failsafe, you can't break anything. But because you've -disabled the builtin watchdog you might have to manually enter failsafe -mode by asserting the ``FORCE_RECOV#`` line during board reset. +The board is fully failsafe, you can't break anything. If builtin watchdog +is enabled, you'll automatically end up in the failsafe bootloader if +something goes wrong. If the watchdog is disabled, you have to manually +enter failsafe mode by asserting the ``FORCE_RECOV#`` line during board +reset. Update image ------------ From 2810da7c80ad7d25ef987d65bcaad2479f1df30e Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:50 +0100 Subject: [PATCH 09/13] board: sl28: remove "Useful I2C tricks" section from docs They are no longer needed, because we now have proper driver support for the sl28cpld management controller. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- doc/board/kontron/sl28.rst | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index 04483e1e573..44435d90c62 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -50,21 +50,6 @@ Afterward you can copy this file to your ESP into the /EFI/UpdateCapsule/ folder. On the next EFI boot this will automatically update your bootloader. -Useful I2C tricks ------------------ - -The board has a board management controller which is not supported in -u-boot (yet). But you can use the i2c command to access it. - -- reset into failsafe bootloader:: - - > i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42 - -- read board management controller version:: - - > i2c md 4a 3.1 1 - - Builtin watchdog ---------------- From 62ba0e5df6e81f0a45b589273c043d451986767c Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:18:40 +0530 Subject: [PATCH 10/13] board: sl28: disable random MAC address generation Nowadays, u-boot (when CONFIG_NET_RANDOM_ETHADDR is set) will set enetaddr to a random value if not set and then pass the randomly generated MAC address to linux. This is bad for the following reasons: (1) it makes it impossible for linux to detect this error (2) linux won't trigger any fallback mechanism for the case where it didn't find any valid MAC address (3) a saveenv will store this randomly generated MAC address in the environment Probably, the user will also be unaware that something is wrong. He will just get different MAC addresses on each reboot, asking himself why this is the case. As this board usually have a serial port, the user can just fix this by setting the MAC address manually in the environment. Also disable the netconsole just in case, because it cannot be guaranteed that it will work in any case. After all, this was just a convenience option, because the bootloader - right now - doesn't have the ability to read the MAC address, which is stored in the OTP. But it is far more important to have a clear view of whats wrong with a board and that means we can no longer use this Kconfig option. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index a4d9254815a..b743c2ba9e7 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -59,8 +59,6 @@ CONFIG_OF_LIST="" CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_NETCONSOLE=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SATA=y CONFIG_SCSI_AHCI=y From 554a85313bc7bb50704c2a8d6f4857037aea2426 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:21:56 +0530 Subject: [PATCH 11/13] board: sl28: use fit image generator Simplify the binman config and fdt nodes by using the "@..-SEQ" substitutions and CONFIG_OF_LIST. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- .../dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi | 128 ++---------------- configs/kontron_sl28_defconfig | 2 +- 2 files changed, 10 insertions(+), 120 deletions(-) diff --git a/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi b/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi index d4b833284e2..2dcb3c2a58f 100644 --- a/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi +++ b/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi @@ -27,6 +27,7 @@ fit { offset = ; description = "FIT image with multiple configurations"; + fit,fdt-list = "of-list"; images { uboot { @@ -41,95 +42,20 @@ }; }; - fdt-1 { - description = "fsl-ls1028a-kontron-sl28"; + @fdt-SEQ { + description = "NAME"; type = "flat_dt"; - arch = "arm"; compression = "none"; - - blob { - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28.dtb"; - }; - }; - - fdt-2 { - description = "fsl-ls1028a-kontron-sl28-var1"; - type = "flat_dt"; - arch = "arm"; - compression = "none"; - - blob { - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var1.dtb"; - }; - }; - - fdt-3 { - description = "fsl-ls1028a-kontron-sl28-var2"; - type = "flat_dt"; - arch = "arm"; - compression = "none"; - - blob { - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var2.dtb"; - }; - }; - - fdt-4 { - description = "fsl-ls1028a-kontron-sl28-var3"; - type = "flat_dt"; - arch = "arm"; - compression = "none"; - - blob { - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var3.dtb"; - }; - }; - - fdt-5 { - description = "fsl-ls1028a-kontron-sl28-var4"; - type = "flat_dt"; - arch = "arm"; - compression = "none"; - - blob { - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var4.dtb"; - }; }; }; configurations { - default = "conf-1"; + default = "@config-DEFAULT-SEQ"; - conf-1 { - description = "fsl-ls1028a-kontron-sl28"; + @config-SEQ { + description = "NAME"; firmware = "uboot"; - fdt = "fdt-1"; - }; - - conf-2 { - description = "fsl-ls1028a-kontron-sl28-var1"; - firmware = "uboot"; - fdt = "fdt-2"; - }; - - conf-3 { - description = "fsl-ls1028a-kontron-sl28-var2"; - firmware = "uboot"; - fdt = "fdt-3"; - }; - - conf-4 { - description = "fsl-ls1028a-kontron-sl28-var3"; - firmware = "uboot"; - loadables = "uboot"; - fdt = "fdt-4"; - }; - - conf-5 { - description = "fsl-ls1028a-kontron-sl28-var4"; - firmware = "uboot"; - loadables = "uboot"; - fdt = "fdt-5"; + fdt = "fdt-SEQ"; }; }; }; @@ -189,27 +115,7 @@ }; configurations { - conf-1 { - firmware = "bl31"; - loadables = "uboot"; - }; - - conf-2 { - firmware = "bl31"; - loadables = "uboot"; - }; - - conf-3 { - firmware = "bl31"; - loadables = "uboot"; - }; - - conf-4 { - firmware = "bl31"; - loadables = "uboot"; - }; - - conf-5 { + @config-SEQ { firmware = "bl31"; loadables = "uboot"; }; @@ -238,23 +144,7 @@ }; configurations { - conf-1 { - loadables = "uboot", "bl32"; - }; - - conf-2 { - loadables = "uboot", "bl32"; - }; - - conf-3 { - loadables = "uboot", "bl32"; - }; - - conf-4 { - loadables = "uboot", "bl32"; - }; - - conf-5 { + @config-SEQ { loadables = "uboot", "bl32"; }; }; diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index b743c2ba9e7..cf8aedfdfd7 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -55,7 +55,7 @@ CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_RNG=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y -CONFIG_OF_LIST="" +CONFIG_OF_LIST="fsl-ls1028a-kontron-sl28 fsl-ls1028a-kontron-sl28-var1 fsl-ls1028a-kontron-sl28-var2 fsl-ls1028a-kontron-sl28-var3 fsl-ls1028a-kontron-sl28-var4" CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y From 453db6056850e1ac1be0a12df72fcf3bd5f61bd3 Mon Sep 17 00:00:00 2001 From: Daniel Klauer Date: Wed, 9 Feb 2022 15:53:41 +0100 Subject: [PATCH 12/13] lx2160a: Fix distroboot device list for configs without USB/SCSI/etc The BOOT_TARGET_DEVICES list for distro_bootcmd was hard-coded to assume that all boot devices are available/enabled in the configuration, thus ignoring the actual config settings. The config_distro_bootcmd.h header file specifically has compile-time checks to detect such problems. To allow disabling USB, SCSI, etc. in custom lx2160a board configs, make it depend on the config settings and use only the enabled features. Signed-off-by: Daniel Klauer Reviewed-by: Priyanka Jain --- include/configs/lx2160a_common.h | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h index e31f8d087f7..4f4b5713dc7 100644 --- a/include/configs/lx2160a_common.h +++ b/include/configs/lx2160a_common.h @@ -244,12 +244,36 @@ "run distro_bootcmd;run sd2_bootcmd;" \ "env exists secureboot && esbc_halt;" +#ifdef CONFIG_CMD_USB +#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0) +#else +#define BOOT_TARGET_DEVICES_USB(func) +#endif + +#ifdef CONFIG_MMC +#define BOOT_TARGET_DEVICES_MMC(func, instance) func(MMC, mmc, instance) +#else +#define BOOT_TARGET_DEVICES_MMC(func) +#endif + +#ifdef CONFIG_SCSI +#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0) +#else +#define BOOT_TARGET_DEVICES_SCSI(func) +#endif + +#ifdef CONFIG_CMD_DHCP +#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na) +#else +#define BOOT_TARGET_DEVICES_DHCP(func) +#endif + #define BOOT_TARGET_DEVICES(func) \ - func(USB, usb, 0) \ - func(MMC, mmc, 0) \ - func(MMC, mmc, 1) \ - func(SCSI, scsi, 0) \ - func(DHCP, dhcp, na) + BOOT_TARGET_DEVICES_USB(func) \ + BOOT_TARGET_DEVICES_MMC(func, 0) \ + BOOT_TARGET_DEVICES_MMC(func, 1) \ + BOOT_TARGET_DEVICES_SCSI(func) \ + BOOT_TARGET_DEVICES_DHCP(func) #include #endif /* __LX2_COMMON_H */ From 2058967d2fe8f93142d774bc47241d80894027d5 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 17 Feb 2022 11:51:36 +0800 Subject: [PATCH 13/13] tools: pblimage: fix image header verification function The Layerscape platforms have different RCW header value from FSL PowerPC platforms, the current image header verification callback is only working on PowerPC, it will fail on Layerscape, this patch is to fix this issue. This is a historical problem and exposed by the following patch: http://patchwork.ozlabs.org/project/uboot/patch/20220114173443.9877-1-pali@kernel.org Signed-off-by: Hou Zhiqiang Reviewed-by: Priyanka Jain --- Makefile | 2 +- tools/pblimage.c | 10 ++++++++-- tools/pblimage.h | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 66d9e78cc77..4d9cda7f305 100644 --- a/Makefile +++ b/Makefile @@ -1411,7 +1411,7 @@ MKIMAGEFLAGS_u-boot-spl.kwb = -n $(KWD_CONFIG_FILE) \ $(if $(KEYDIR),-k $(KEYDIR)) MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \ - -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage + -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -A $(ARCH) -T pblimage ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy) UBOOT_BIN := u-boot-with-dtb.bin diff --git a/tools/pblimage.c b/tools/pblimage.c index 3c823e96cf1..bd639c276f9 100644 --- a/tools/pblimage.c +++ b/tools/pblimage.c @@ -230,19 +230,25 @@ static int pblimage_verify_header(unsigned char *ptr, int image_size, struct image_tool_params *params) { struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; + uint32_t rcwheader; + + if (params->arch == IH_ARCH_ARM) + rcwheader = RCW_ARM_HEADER; + else + rcwheader = RCW_PPC_HEADER; /* Only a few checks can be done: search for magic numbers */ if (ENDIANNESS == 'l') { if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) return -FDT_ERR_BADSTRUCTURE; - if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER)) + if (pbl_hdr->rcwheader != reverse_byte(rcwheader)) return -FDT_ERR_BADSTRUCTURE; } else { if (pbl_hdr->preamble != RCW_PREAMBLE) return -FDT_ERR_BADSTRUCTURE; - if (pbl_hdr->rcwheader != RCW_HEADER) + if (pbl_hdr->rcwheader != rcwheader) return -FDT_ERR_BADSTRUCTURE; } return 0; diff --git a/tools/pblimage.h b/tools/pblimage.h index 81c5492926b..0222e8067b4 100644 --- a/tools/pblimage.h +++ b/tools/pblimage.h @@ -8,7 +8,8 @@ #define RCW_BYTES 64 #define RCW_PREAMBLE 0xaa55aa55 -#define RCW_HEADER 0x010e0100 +#define RCW_ARM_HEADER 0x01ee0100 +#define RCW_PPC_HEADER 0x010e0100 struct pbl_header { uint32_t preamble;