Update and fixes for sl28, lx2, pblimage generation for some powerpc
products
This commit is contained in:
Tom Rini 2022-03-03 08:24:13 -05:00
commit 705b5840cd
19 changed files with 577 additions and 164 deletions

View file

@ -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

View file

@ -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

View file

@ -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";
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";
};
};

View file

@ -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);
}

View file

@ -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

View file

@ -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 board has a board management controller which is not supported in
u-boot (yet). But you can use the i2c command to access it.
The builtin watchdog will supervise the bootloader startup. If anything
goes wrong it will reset the board and boot into the failsafe bootloader.
- reset into failsafe bootloader::
Once the bootloader is started successfully, it will disable the watchdog
timer.
> i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42
wdt command flags
^^^^^^^^^^^^^^^^^
- read board management controller version::
The `wdt start` as well as the `wdt expire` command take a flags argument.
The supported bitmask is as follows.
> i2c md 4a 3.1 1
| 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
-------------------------------------

View file

@ -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

View file

@ -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

View file

@ -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,
};

View file

@ -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

View file

@ -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

105
drivers/misc/sl28cpld.c Normal file
View file

@ -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,
};

View file

@ -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

View file

@ -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

View file

@ -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,
};

View file

@ -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 */

16
include/sl28cpld.h Normal file
View file

@ -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

View file

@ -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;

View file

@ -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;