mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
Update and fixes for sl28, lx2, pblimage generation for some powerpc products
This commit is contained in:
commit
705b5840cd
19 changed files with 577 additions and 164 deletions
|
@ -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
|
||||
|
|
2
Makefile
2
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
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
165
drivers/gpio/sl28cpld-gpio.c
Normal file
165
drivers/gpio/sl28cpld-gpio.c
Normal 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,
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
105
drivers/misc/sl28cpld.c
Normal 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,
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
109
drivers/watchdog/sl28cpld-wdt.c
Normal file
109
drivers/watchdog/sl28cpld-wdt.c
Normal 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,
|
||||
};
|
|
@ -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
16
include/sl28cpld.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue