diff options
author | Tom Rini <trini@konsulko.com> | 2022-03-03 08:24:13 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-03-03 08:24:13 -0500 |
commit | 705b5840cde496e30dde386f980737a3beaa52e5 (patch) | |
tree | 76ba8bb47cadaf79fc8bbf76da7e9496010d5987 | |
parent | f64aac4a69007771963eaa52a86e733071f9fdd4 (diff) | |
parent | 2058967d2fe8f93142d774bc47241d80894027d5 (diff) | |
download | u-boot-705b5840cde496e30dde386f980737a3beaa52e5.tar.gz u-boot-705b5840cde496e30dde386f980737a3beaa52e5.tar.bz2 u-boot-705b5840cde496e30dde386f980737a3beaa52e5.zip |
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq
Update and fixes for sl28, lx2, pblimage generation for some powerpc
products
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi | 128 | ||||
-rw-r--r-- | board/kontron/sl28/sl28.c | 59 | ||||
-rw-r--r-- | configs/kontron_sl28_defconfig | 13 | ||||
-rw-r--r-- | doc/board/kontron/sl28.rst | 66 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 6 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/sl28cpld-gpio.c | 165 | ||||
-rw-r--r-- | drivers/misc/Kconfig | 8 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/sl28cpld.c | 105 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 7 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/sl28cpld-wdt.c | 109 | ||||
-rw-r--r-- | include/configs/lx2160a_common.h | 34 | ||||
-rw-r--r-- | include/sl28cpld.h | 16 | ||||
-rw-r--r-- | tools/pblimage.c | 10 | ||||
-rw-r--r-- | tools/pblimage.h | 3 |
19 files changed, 577 insertions, 164 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fb171e0c68..0f39bc6bc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1161,6 +1161,13 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git F: arch/sh/ +SL28CLPD +M: Michael Walle <michael@walle.cc> +S: Maintained +F: drivers/gpio/sl28cpld-gpio.c +F: drivers/misc/sl28cpld.c +F: drivers/watchdog/sl28cpld-wdt.c + SPI M: Jagan Teki <jagan@amarulasolutions.com> S: Maintained @@ -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/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi b/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi index d4b833284e..2dcb3c2a58 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 = <CONFIG_SPL_PAD_TO>; 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"; - - conf-1 { - description = "fsl-ls1028a-kontron-sl28"; - 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"; - }; + default = "@config-DEFAULT-SEQ"; - conf-5 { - description = "fsl-ls1028a-kontron-sl28-var4"; + @config-SEQ { + description = "NAME"; 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/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index e84b356918..3c48a9141d 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include <common.h> +#include <dm.h> #include <malloc.h> #include <errno.h> #include <fsl_ddr.h> @@ -14,7 +15,9 @@ #include <asm/arch/soc.h> #include <fsl_immap.h> #include <netdev.h> +#include <wdt.h> +#include <sl28cpld.h> #include <fdtdec.h> #include <miiphy.h> @@ -39,16 +42,68 @@ 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; +} + +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) { - puts("\nDDR "); - print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); print_ddr_info(0); } diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index b61276cf1d..cf8aedfdfd 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -42,23 +42,23 @@ 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 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 -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_NETCONSOLE=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SATA=y CONFIG_SCSI_AHCI=y @@ -69,8 +69,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 +104,11 @@ 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_WDT_SP805=y CONFIG_OF_LIBFDT_ASSUME_MASK=0x0 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_EFI_SET_TIME=y diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index c7b18bed10..44435d90c6 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -23,34 +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. - -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 - +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 ------------ @@ -67,20 +50,41 @@ 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 ------------------ +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. -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. +wdt command flags +^^^^^^^^^^^^^^^^^ -- reset into failsafe bootloader:: +The `wdt start` as well as the `wdt expire` command take a flags argument. +The supported bitmask is as follows. - > i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42 +| Bit | Description | +| --- | ----------------------------- | +| 0 | Enable failsafe mode | +| 1 | Lock the control register | +| 2 | Disable board reset | +| 3 | Enable WDT_TIME_OUT# line | -- read board management controller version:: +For example, you can use `wdt expire 1` to issue a reset and boot into the +failsafe bootloader. + +Disable the builtin watchdog +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - > i2c md 4a 3.1 1 +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/gpio/Kconfig b/drivers/gpio/Kconfig index 8d0e47c67d..522dfc195e 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 63e9be6034..33f7d41b7d 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 0000000000..700fc3df29 --- /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 <michael@walle.cc> + */ + +#include <common.h> +#include <dm.h> +#include <asm/gpio.h> +#include <sl28cpld.h> + +/* 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, +}; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0ade3e32b0..7029bb7b5c 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 bca7b24e99..f22eff601a 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 0000000000..01ef1c6178 --- /dev/null +++ b/drivers/misc/sl28cpld.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Michael Walle <michael@walle.cc> + */ + +#include <common.h> +#include <dm.h> +#include <i2c.h> + +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/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cabac29053..f90f0ca02b 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 6d2b3822c0..a35bd559f5 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 0000000000..af5a6b1a28 --- /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 <michael@walle.cc> + */ + +#include <common.h> +#include <dm.h> +#include <wdt.h> +#include <sl28cpld.h> +#include <div64.h> + +#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, +}; diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h index e31f8d087f..4f4b5713dc 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 <config_distro_bootcmd.h> #endif /* __LX2_COMMON_H */ diff --git a/include/sl28cpld.h b/include/sl28cpld.h new file mode 100644 index 0000000000..9a7c6de31f --- /dev/null +++ b/include/sl28cpld.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Michael Walle <michael@walle.cc> + */ + +#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, + uint8_t set); + +#endif diff --git a/tools/pblimage.c b/tools/pblimage.c index 3c823e96cf..bd639c276f 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 81c5492926..0222e8067b 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; |