Commit 705b5840cde496e30dde386f980737a3beaa52e5

Authored by Tom Rini
Exists in emb_lf_v2022.04

Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq

Update and fixes for sl28, lx2, pblimage generation for some powerpc
products

Showing 19 changed files Side-by-side Diff

... ... @@ -1161,6 +1161,13 @@
1161 1161 T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git
1162 1162 F: arch/sh/
1163 1163  
  1164 +SL28CLPD
  1165 +M: Michael Walle <michael@walle.cc>
  1166 +S: Maintained
  1167 +F: drivers/gpio/sl28cpld-gpio.c
  1168 +F: drivers/misc/sl28cpld.c
  1169 +F: drivers/watchdog/sl28cpld-wdt.c
  1170 +
1164 1171 SPI
1165 1172 M: Jagan Teki <jagan@amarulasolutions.com>
1166 1173 S: Maintained
... ... @@ -1411,7 +1411,7 @@
1411 1411 $(if $(KEYDIR),-k $(KEYDIR))
1412 1412  
1413 1413 MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
1414   - -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
  1414 + -R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -A $(ARCH) -T pblimage
1415 1415  
1416 1416 ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy)
1417 1417 UBOOT_BIN := u-boot-with-dtb.bin
arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi
... ... @@ -27,6 +27,7 @@
27 27 fit {
28 28 offset = <CONFIG_SPL_PAD_TO>;
29 29 description = "FIT image with multiple configurations";
  30 + fit,fdt-list = "of-list";
30 31  
31 32 images {
32 33 uboot {
33 34  
34 35  
35 36  
36 37  
37 38  
38 39  
39 40  
... ... @@ -41,96 +42,21 @@
41 42 };
42 43 };
43 44  
44   - fdt-1 {
45   - description = "fsl-ls1028a-kontron-sl28";
  45 + @fdt-SEQ {
  46 + description = "NAME";
46 47 type = "flat_dt";
47   - arch = "arm";
48 48 compression = "none";
49   -
50   - blob {
51   - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28.dtb";
52   - };
53 49 };
54   -
55   - fdt-2 {
56   - description = "fsl-ls1028a-kontron-sl28-var1";
57   - type = "flat_dt";
58   - arch = "arm";
59   - compression = "none";
60   -
61   - blob {
62   - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var1.dtb";
63   - };
64   - };
65   -
66   - fdt-3 {
67   - description = "fsl-ls1028a-kontron-sl28-var2";
68   - type = "flat_dt";
69   - arch = "arm";
70   - compression = "none";
71   -
72   - blob {
73   - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var2.dtb";
74   - };
75   - };
76   -
77   - fdt-4 {
78   - description = "fsl-ls1028a-kontron-sl28-var3";
79   - type = "flat_dt";
80   - arch = "arm";
81   - compression = "none";
82   -
83   - blob {
84   - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var3.dtb";
85   - };
86   - };
87   -
88   - fdt-5 {
89   - description = "fsl-ls1028a-kontron-sl28-var4";
90   - type = "flat_dt";
91   - arch = "arm";
92   - compression = "none";
93   -
94   - blob {
95   - filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var4.dtb";
96   - };
97   - };
98 50 };
99 51  
100 52 configurations {
101   - default = "conf-1";
  53 + default = "@config-DEFAULT-SEQ";
102 54  
103   - conf-1 {
104   - description = "fsl-ls1028a-kontron-sl28";
  55 + @config-SEQ {
  56 + description = "NAME";
105 57 firmware = "uboot";
106   - fdt = "fdt-1";
  58 + fdt = "fdt-SEQ";
107 59 };
108   -
109   - conf-2 {
110   - description = "fsl-ls1028a-kontron-sl28-var1";
111   - firmware = "uboot";
112   - fdt = "fdt-2";
113   - };
114   -
115   - conf-3 {
116   - description = "fsl-ls1028a-kontron-sl28-var2";
117   - firmware = "uboot";
118   - fdt = "fdt-3";
119   - };
120   -
121   - conf-4 {
122   - description = "fsl-ls1028a-kontron-sl28-var3";
123   - firmware = "uboot";
124   - loadables = "uboot";
125   - fdt = "fdt-4";
126   - };
127   -
128   - conf-5 {
129   - description = "fsl-ls1028a-kontron-sl28-var4";
130   - firmware = "uboot";
131   - loadables = "uboot";
132   - fdt = "fdt-5";
133   - };
134 60 };
135 61 };
136 62 };
137 63  
... ... @@ -189,30 +115,10 @@
189 115 };
190 116  
191 117 configurations {
192   - conf-1 {
  118 + @config-SEQ {
193 119 firmware = "bl31";
194 120 loadables = "uboot";
195 121 };
196   -
197   - conf-2 {
198   - firmware = "bl31";
199   - loadables = "uboot";
200   - };
201   -
202   - conf-3 {
203   - firmware = "bl31";
204   - loadables = "uboot";
205   - };
206   -
207   - conf-4 {
208   - firmware = "bl31";
209   - loadables = "uboot";
210   - };
211   -
212   - conf-5 {
213   - firmware = "bl31";
214   - loadables = "uboot";
215   - };
216 122 };
217 123 };
218 124 };
... ... @@ -238,23 +144,7 @@
238 144 };
239 145  
240 146 configurations {
241   - conf-1 {
242   - loadables = "uboot", "bl32";
243   - };
244   -
245   - conf-2 {
246   - loadables = "uboot", "bl32";
247   - };
248   -
249   - conf-3 {
250   - loadables = "uboot", "bl32";
251   - };
252   -
253   - conf-4 {
254   - loadables = "uboot", "bl32";
255   - };
256   -
257   - conf-5 {
  147 + @config-SEQ {
258 148 loadables = "uboot", "bl32";
259 149 };
260 150 };
board/kontron/sl28/sl28.c
1 1 // SPDX-License-Identifier: GPL-2.0+
2 2  
3 3 #include <common.h>
  4 +#include <dm.h>
4 5 #include <malloc.h>
5 6 #include <errno.h>
6 7 #include <fsl_ddr.h>
7 8  
... ... @@ -14,7 +15,9 @@
14 15 #include <asm/arch/soc.h>
15 16 #include <fsl_immap.h>
16 17 #include <netdev.h>
  18 +#include <wdt.h>
17 19  
  20 +#include <sl28cpld.h>
18 21 #include <fdtdec.h>
19 22 #include <miiphy.h>
20 23  
21 24  
22 25  
23 26  
... ... @@ -39,16 +42,68 @@
39 42 return pci_eth_init(bis);
40 43 }
41 44  
  45 +static int __sl28cpld_read(uint reg)
  46 +{
  47 + struct udevice *dev;
  48 + int ret;
  49 +
  50 + ret = uclass_get_device_by_driver(UCLASS_NOP,
  51 + DM_DRIVER_GET(sl28cpld), &dev);
  52 + if (ret)
  53 + return ret;
  54 +
  55 + return sl28cpld_read(dev, reg);
  56 +}
  57 +
  58 +static void print_cpld_version(void)
  59 +{
  60 + int version = __sl28cpld_read(SL28CPLD_VERSION);
  61 +
  62 + if (version < 0)
  63 + printf("CPLD: error reading version (%d)\n", version);
  64 + else
  65 + printf("CPLD: v%d\n", version);
  66 +}
  67 +
42 68 int checkboard(void)
43 69 {
44 70 printf("EL: %d\n", current_el());
  71 + if (CONFIG_IS_ENABLED(SL28CPLD))
  72 + print_cpld_version();
  73 +
45 74 return 0;
46 75 }
47 76  
  77 +static void stop_recovery_watchdog(void)
  78 +{
  79 + struct udevice *dev;
  80 + int ret;
  81 +
  82 + ret = uclass_get_device_by_driver(UCLASS_WDT,
  83 + DM_DRIVER_GET(sl28cpld_wdt), &dev);
  84 + if (!ret)
  85 + wdt_stop(dev);
  86 +}
  87 +
  88 +int fsl_board_late_init(void)
  89 +{
  90 + /*
  91 + * Usually, the after a board reset, the watchdog is enabled by
  92 + * default. This is to supervise the bootloader boot-up. Therefore,
  93 + * to prevent a watchdog reset if we don't actively kick it, we have
  94 + * to disable it.
  95 + *
  96 + * If the watchdog isn't enabled at reset (which is a configuration
  97 + * option) disabling it doesn't hurt either.
  98 + */
  99 + if (!CONFIG_IS_ENABLED(WATCHDOG_AUTOSTART))
  100 + stop_recovery_watchdog();
  101 +
  102 + return 0;
  103 +}
  104 +
48 105 void detail_board_ddr_info(void)
49 106 {
50   - puts("\nDDR ");
51   - print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
52 107 print_ddr_info(0);
53 108 }
54 109  
configs/kontron_sl28_defconfig
... ... @@ -42,23 +42,23 @@
42 42 CONFIG_CMD_NVEDIT_EFI=y
43 43 CONFIG_CMD_DFU=y
44 44 CONFIG_CMD_DM=y
  45 +CONFIG_CMD_GPIO=y
45 46 CONFIG_CMD_GPT=y
46 47 CONFIG_CMD_I2C=y
47 48 CONFIG_CMD_MMC=y
48 49 CONFIG_CMD_PCI=y
49 50 CONFIG_CMD_USB=y
50 51 CONFIG_CMD_USB_MASS_STORAGE=y
  52 +CONFIG_CMD_WDT=y
51 53 CONFIG_CMD_CACHE=y
52 54 CONFIG_CMD_EFIDEBUG=y
53 55 CONFIG_CMD_RNG=y
54 56 CONFIG_OF_CONTROL=y
55 57 CONFIG_SPL_OF_CONTROL=y
56   -CONFIG_OF_LIST=""
  58 +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"
57 59 CONFIG_ENV_OVERWRITE=y
58 60 CONFIG_ENV_IS_IN_SPI_FLASH=y
59 61 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
60   -CONFIG_NET_RANDOM_ETHADDR=y
61   -CONFIG_NETCONSOLE=y
62 62 CONFIG_SPL_DM_SEQ_ALIAS=y
63 63 CONFIG_SATA=y
64 64 CONFIG_SCSI_AHCI=y
65 65  
... ... @@ -69,8 +69,10 @@
69 69 CONFIG_ECC_INIT_VIA_DDRCONTROLLER=y
70 70 CONFIG_DFU_MMC=y
71 71 CONFIG_DFU_SF=y
  72 +CONFIG_SL28CPLD_GPIO=y
72 73 CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
73 74 CONFIG_I2C_MUX=y
  75 +CONFIG_SL28CPLD=y
74 76 CONFIG_MMC_HS400_SUPPORT=y
75 77 CONFIG_FSL_ESDHC=y
76 78 CONFIG_FSL_ESDHC_SUPPORT_ADMA2=y
... ... @@ -102,6 +104,11 @@
102 104 CONFIG_USB_DWC3_LAYERSCAPE=y
103 105 CONFIG_USB_GADGET=y
104 106 CONFIG_USB_GADGET_DOWNLOAD=y
  107 +# CONFIG_WATCHDOG is not set
  108 +# CONFIG_WATCHDOG_AUTOSTART is not set
  109 +CONFIG_WDT=y
  110 +CONFIG_WDT_SL28CPLD=y
  111 +CONFIG_WDT_SP805=y
105 112 CONFIG_OF_LIBFDT_ASSUME_MASK=0x0
106 113 CONFIG_OF_LIBFDT_OVERLAY=y
107 114 CONFIG_EFI_SET_TIME=y
doc/board/kontron/sl28.rst
... ... @@ -23,35 +23,18 @@
23 23 Install the bootloader on the board
24 24 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 25  
26   -Please note, this bootloader doesn't support the builtin watchdog (yet),
27   -therefore you have to disable it, see below. Otherwise you'll end up in
28   -the failsafe bootloader on every reset::
  26 +To install the bootloader binary use the following command::
29 27  
30 28 > tftp path/to/u-boot.rom
31 29 > sf probe 0
32 30 > sf update $fileaddr 0x210000 $filesize
33 31  
34   -The board is fully failsafe, you can't break anything. But because you've
35   -disabled the builtin watchdog you might have to manually enter failsafe
36   -mode by asserting the ``FORCE_RECOV#`` line during board reset.
  32 +The board is fully failsafe, you can't break anything. If builtin watchdog
  33 +is enabled, you'll automatically end up in the failsafe bootloader if
  34 +something goes wrong. If the watchdog is disabled, you have to manually
  35 +enter failsafe mode by asserting the ``FORCE_RECOV#`` line during board
  36 +reset.
37 37  
38   -Disable the builtin watchdog
39   -^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40   -
41   -- boot into the failsafe bootloader, either by asserting the
42   - ``FORCE_RECOV#`` line or if you still have the original bootloader
43   - installed you can use the command::
44   -
45   - > wdt dev cpld_watchdog@4a; wdt expire 1
46   -
47   -- in the failsafe bootloader use the "sl28 nvm" command to disable
48   - the automatic start of the builtin watchdog::
49   -
50   - > sl28 nvm 0008
51   -
52   -- power-cycle the board
53   -
54   -
55 38 Update image
56 39 ------------
57 40  
58 41  
59 42  
60 43  
61 44  
62 45  
63 46  
... ... @@ -67,20 +50,41 @@
67 50 folder. On the next EFI boot this will automatically update your
68 51 bootloader.
69 52  
70   -Useful I2C tricks
71   ------------------
  53 +Builtin watchdog
  54 +----------------
72 55  
73   -The board has a board management controller which is not supported in
74   -u-boot (yet). But you can use the i2c command to access it.
  56 +The builtin watchdog will supervise the bootloader startup. If anything
  57 +goes wrong it will reset the board and boot into the failsafe bootloader.
75 58  
76   -- reset into failsafe bootloader::
  59 +Once the bootloader is started successfully, it will disable the watchdog
  60 +timer.
77 61  
78   - > i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42
  62 +wdt command flags
  63 +^^^^^^^^^^^^^^^^^
79 64  
80   -- read board management controller version::
  65 +The `wdt start` as well as the `wdt expire` command take a flags argument.
  66 +The supported bitmask is as follows.
81 67  
82   - > i2c md 4a 3.1 1
  68 +| Bit | Description |
  69 +| --- | ----------------------------- |
  70 +| 0 | Enable failsafe mode |
  71 +| 1 | Lock the control register |
  72 +| 2 | Disable board reset |
  73 +| 3 | Enable WDT_TIME_OUT# line |
83 74  
  75 +For example, you can use `wdt expire 1` to issue a reset and boot into the
  76 +failsafe bootloader.
  77 +
  78 +Disable the builtin watchdog
  79 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  80 +
  81 +If for some reason, this isn't a desired behavior, the watchdog can also
  82 +be configured to not be enabled on board reset. It's configuration is saved
  83 +in the non-volatile board configuration bits. To change these you can use
  84 +the `sl28 nvm` command.
  85 +
  86 +For more information on the non-volatile board configuration bits, see the
  87 +following section.
84 88  
85 89 Non-volatile Board Configuration Bits
86 90 -------------------------------------
drivers/gpio/Kconfig
... ... @@ -544,5 +544,11 @@
544 544 are accessed using xilinx firmware. In modepin register, [3:0] bits
545 545 set direction, [7:4] bits read IO, [11:8] bits set/clear IO.
546 546  
  547 +config SL28CPLD_GPIO
  548 + bool "Kontron sl28cpld GPIO driver"
  549 + depends on DM_GPIO && SL28CPLD
  550 + help
  551 + Support GPIO access on Kontron sl28cpld board management controllers.
  552 +
547 553 endif
drivers/gpio/Makefile
... ... @@ -70,5 +70,6 @@
70 70 obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
71 71 obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
72 72 obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
  73 +obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
73 74 obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
drivers/gpio/sl28cpld-gpio.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * GPIO driver for the sl28cpld
  4 + *
  5 + * Copyright (c) 2021 Michael Walle <michael@walle.cc>
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <dm.h>
  10 +#include <asm/gpio.h>
  11 +#include <sl28cpld.h>
  12 +
  13 +/* GPIO flavor */
  14 +#define SL28CPLD_GPIO_DIR 0x00
  15 +#define SL28CPLD_GPIO_OUT 0x01
  16 +#define SL28CPLD_GPIO_IN 0x02
  17 +
  18 +/* input-only flavor */
  19 +#define SL28CPLD_GPI_IN 0x00
  20 +
  21 +/* output-only flavor */
  22 +#define SL28CPLD_GPO_OUT 0x00
  23 +
  24 +enum {
  25 + SL28CPLD_GPIO,
  26 + SL28CPLD_GPI,
  27 + SL28CPLD_GPO,
  28 +};
  29 +
  30 +static int sl28cpld_gpio_get_value(struct udevice *dev, unsigned int gpio)
  31 +{
  32 + ulong type = dev_get_driver_data(dev);
  33 + int val, reg;
  34 +
  35 + switch (type) {
  36 + case SL28CPLD_GPIO:
  37 + reg = SL28CPLD_GPIO_IN;
  38 + break;
  39 + case SL28CPLD_GPI:
  40 + reg = SL28CPLD_GPI_IN;
  41 + break;
  42 + case SL28CPLD_GPO:
  43 + /* we are output only, thus just return the output value */
  44 + reg = SL28CPLD_GPO_OUT;
  45 + break;
  46 + default:
  47 + return -EINVAL;
  48 + }
  49 +
  50 + val = sl28cpld_read(dev, reg);
  51 +
  52 + return val < 0 ? val : !!(val & BIT(gpio));
  53 +}
  54 +
  55 +static int sl28cpld_gpio_set_value(struct udevice *dev, unsigned int gpio,
  56 + int value)
  57 +{
  58 + ulong type = dev_get_driver_data(dev);
  59 + uint reg;
  60 +
  61 + switch (type) {
  62 + case SL28CPLD_GPIO:
  63 + reg = SL28CPLD_GPIO_OUT;
  64 + break;
  65 + case SL28CPLD_GPO:
  66 + reg = SL28CPLD_GPO_OUT;
  67 + break;
  68 + case SL28CPLD_GPI:
  69 + default:
  70 + return -EINVAL;
  71 + }
  72 +
  73 + if (value)
  74 + return sl28cpld_update(dev, reg, 0, BIT(gpio));
  75 + else
  76 + return sl28cpld_update(dev, reg, BIT(gpio), 0);
  77 +}
  78 +
  79 +static int sl28cpld_gpio_direction_input(struct udevice *dev, unsigned int gpio)
  80 +{
  81 + ulong type = dev_get_driver_data(dev);
  82 +
  83 + switch (type) {
  84 + case SL28CPLD_GPI:
  85 + return 0;
  86 + case SL28CPLD_GPIO:
  87 + return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, BIT(gpio), 0);
  88 + case SL28CPLD_GPO:
  89 + default:
  90 + return -EINVAL;
  91 + }
  92 +}
  93 +
  94 +static int sl28cpld_gpio_direction_output(struct udevice *dev,
  95 + unsigned int gpio, int value)
  96 +{
  97 + ulong type = dev_get_driver_data(dev);
  98 + int ret;
  99 +
  100 + /* set_value() will report an error if we are input-only */
  101 + ret = sl28cpld_gpio_set_value(dev, gpio, value);
  102 + if (ret)
  103 + return ret;
  104 +
  105 + if (type == SL28CPLD_GPIO)
  106 + return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, 0, BIT(gpio));
  107 +
  108 + return 0;
  109 +}
  110 +
  111 +static int sl28cpld_gpio_get_function(struct udevice *dev, unsigned int gpio)
  112 +{
  113 + ulong type = dev_get_driver_data(dev);
  114 + int val;
  115 +
  116 + switch (type) {
  117 + case SL28CPLD_GPIO:
  118 + val = sl28cpld_read(dev, SL28CPLD_GPIO_DIR);
  119 + if (val < 0)
  120 + return val;
  121 + if (val & BIT(gpio))
  122 + return GPIOF_OUTPUT;
  123 + else
  124 + return GPIOF_INPUT;
  125 + case SL28CPLD_GPI:
  126 + return GPIOF_INPUT;
  127 + case SL28CPLD_GPO:
  128 + return GPIOF_OUTPUT;
  129 + default:
  130 + return -EINVAL;
  131 + }
  132 +}
  133 +
  134 +static const struct dm_gpio_ops sl28cpld_gpio_ops = {
  135 + .direction_input = sl28cpld_gpio_direction_input,
  136 + .direction_output = sl28cpld_gpio_direction_output,
  137 + .get_value = sl28cpld_gpio_get_value,
  138 + .set_value = sl28cpld_gpio_set_value,
  139 + .get_function = sl28cpld_gpio_get_function,
  140 +};
  141 +
  142 +static int sl28cpld_gpio_probe(struct udevice *dev)
  143 +{
  144 + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
  145 +
  146 + uc_priv->gpio_count = 8;
  147 + uc_priv->bank_name = dev_read_name(dev);
  148 +
  149 + return 0;
  150 +}
  151 +
  152 +static const struct udevice_id sl28cpld_gpio_ids[] = {
  153 + { .compatible = "kontron,sl28cpld-gpio", .data = SL28CPLD_GPIO},
  154 + { .compatible = "kontron,sl28cpld-gpo", .data = SL28CPLD_GPO},
  155 + { .compatible = "kontron,sl28cpld-gpi", .data = SL28CPLD_GPI},
  156 + { }
  157 +};
  158 +
  159 +U_BOOT_DRIVER(sl28cpld_gpio) = {
  160 + .name = "sl28cpld_gpio",
  161 + .id = UCLASS_GPIO,
  162 + .of_match = sl28cpld_gpio_ids,
  163 + .probe = sl28cpld_gpio_probe,
  164 + .ops = &sl28cpld_gpio_ops,
  165 +};
drivers/misc/Kconfig
... ... @@ -512,5 +512,13 @@
512 512 config FSL_IFC
513 513 bool
514 514  
  515 +config SL28CPLD
  516 + bool "Enable Kontron sl28cpld multi-function driver"
  517 + depends on DM_I2C
  518 + help
  519 + Support for the Kontron sl28cpld management controller. This is
  520 + the base driver which provides common access methods for the
  521 + sub-drivers.
  522 +
515 523 endmenu
drivers/misc/Makefile
... ... @@ -82,4 +82,5 @@
82 82 obj-$(CONFIG_K3_AVS0) += k3_avs.o
83 83 obj-$(CONFIG_ESM_K3) += k3_esm.o
84 84 obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
  85 +obj-$(CONFIG_SL28CPLD) += sl28cpld.o
drivers/misc/sl28cpld.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Copyright (c) 2021 Michael Walle <michael@walle.cc>
  4 + */
  5 +
  6 +#include <common.h>
  7 +#include <dm.h>
  8 +#include <i2c.h>
  9 +
  10 +struct sl28cpld_child_plat {
  11 + uint offset;
  12 +};
  13 +
  14 +/*
  15 + * The access methods works either with the first argument being a child
  16 + * device or with the MFD device itself.
  17 + */
  18 +static int sl28cpld_read_child(struct udevice *dev, uint offset)
  19 +{
  20 + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
  21 + struct udevice *mfd = dev_get_parent(dev);
  22 +
  23 + return dm_i2c_reg_read(mfd, offset + plat->offset);
  24 +}
  25 +
  26 +int sl28cpld_read(struct udevice *dev, uint offset)
  27 +{
  28 + if (dev->driver == DM_DRIVER_GET(sl28cpld))
  29 + return dm_i2c_reg_read(dev, offset);
  30 + else
  31 + return sl28cpld_read_child(dev, offset);
  32 +}
  33 +
  34 +static int sl28cpld_write_child(struct udevice *dev, uint offset,
  35 + uint8_t value)
  36 +{
  37 + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
  38 + struct udevice *mfd = dev_get_parent(dev);
  39 +
  40 + return dm_i2c_reg_write(mfd, offset + plat->offset, value);
  41 +}
  42 +
  43 +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value)
  44 +{
  45 + if (dev->driver == DM_DRIVER_GET(sl28cpld))
  46 + return dm_i2c_reg_write(dev, offset, value);
  47 + else
  48 + return sl28cpld_write_child(dev, offset, value);
  49 +}
  50 +
  51 +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear,
  52 + uint8_t set)
  53 +{
  54 + int val;
  55 +
  56 + val = sl28cpld_read(dev, offset);
  57 + if (val < 0)
  58 + return val;
  59 +
  60 + val &= ~clear;
  61 + val |= set;
  62 +
  63 + return sl28cpld_write(dev, offset, val);
  64 +}
  65 +
  66 +static int sl28cpld_probe(struct udevice *dev)
  67 +{
  68 + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
  69 + DM_I2C_CHIP_WR_ADDRESS);
  70 +
  71 + return 0;
  72 +}
  73 +
  74 +static int sl28cpld_child_post_bind(struct udevice *dev)
  75 +{
  76 + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
  77 + int offset;
  78 +
  79 + if (!dev_has_ofnode(dev))
  80 + return 0;
  81 +
  82 + offset = dev_read_u32_default(dev, "reg", -1);
  83 + if (offset == -1)
  84 + return -EINVAL;
  85 +
  86 + plat->offset = offset;
  87 +
  88 + return 0;
  89 +}
  90 +
  91 +static const struct udevice_id sl28cpld_ids[] = {
  92 + { .compatible = "kontron,sl28cpld" },
  93 + {}
  94 +};
  95 +
  96 +U_BOOT_DRIVER(sl28cpld) = {
  97 + .name = "sl28cpld",
  98 + .id = UCLASS_NOP,
  99 + .of_match = sl28cpld_ids,
  100 + .probe = sl28cpld_probe,
  101 + .bind = dm_scan_fdt_dev,
  102 + .flags = DM_FLAG_PRE_RELOC,
  103 + .per_child_plat_auto = sizeof(struct sl28cpld_child_plat),
  104 + .child_post_bind = sl28cpld_child_post_bind,
  105 +};
drivers/watchdog/Kconfig
... ... @@ -266,6 +266,13 @@
266 266 In the single stage mode, when the timeout is reached, your system
267 267 will be reset by WS1. The first signal (WS0) is ignored.
268 268  
  269 +config WDT_SL28CPLD
  270 + bool "sl28cpld watchdog timer support"
  271 + depends on WDT && SL28CPLD
  272 + help
  273 + Enable support for the watchdog timer in the Kontron sl28cpld
  274 + management controller.
  275 +
269 276 config WDT_SP805
270 277 bool "SP805 watchdog timer support"
271 278 depends on WDT
drivers/watchdog/Makefile
... ... @@ -35,6 +35,7 @@
35 35 obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
36 36 obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o
37 37 obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o
  38 +obj-$(CONFIG_WDT_SL28CPLD) += sl28cpld-wdt.o
38 39 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
39 40 obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
40 41 obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o
drivers/watchdog/sl28cpld-wdt.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Watchdog driver for the sl28cpld
  4 + *
  5 + * Copyright (c) 2021 Michael Walle <michael@walle.cc>
  6 + */
  7 +
  8 +#include <common.h>
  9 +#include <dm.h>
  10 +#include <wdt.h>
  11 +#include <sl28cpld.h>
  12 +#include <div64.h>
  13 +
  14 +#define SL28CPLD_WDT_CTRL 0x00
  15 +#define WDT_CTRL_EN0 BIT(0)
  16 +#define WDT_CTRL_EN1 BIT(1)
  17 +#define WDT_CTRL_EN_MASK GENMASK(1, 0)
  18 +#define WDT_CTRL_LOCK BIT(2)
  19 +#define WDT_CTRL_ASSERT_SYS_RESET BIT(6)
  20 +#define WDT_CTRL_ASSERT_WDT_TIMEOUT BIT(7)
  21 +#define SL28CPLD_WDT_TIMEOUT 0x01
  22 +#define SL28CPLD_WDT_KICK 0x02
  23 +#define WDT_KICK_VALUE 0x6b
  24 +
  25 +static int sl28cpld_wdt_reset(struct udevice *dev)
  26 +{
  27 + return sl28cpld_write(dev, SL28CPLD_WDT_KICK, WDT_KICK_VALUE);
  28 +}
  29 +
  30 +static int sl28cpld_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
  31 +{
  32 + int ret, val;
  33 +
  34 + val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL);
  35 + if (val < 0)
  36 + return val;
  37 +
  38 + /* (1) disable watchdog */
  39 + val &= ~WDT_CTRL_EN_MASK;
  40 + ret = sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val);
  41 + if (ret)
  42 + return ret;
  43 +
  44 + /* (2) set timeout */
  45 + ret = sl28cpld_write(dev, SL28CPLD_WDT_TIMEOUT, lldiv(timeout, 1000));
  46 + if (ret)
  47 + return ret;
  48 +
  49 + /* (3) kick it, will reset timer to the timeout value */
  50 + ret = sl28cpld_wdt_reset(dev);
  51 + if (ret)
  52 + return ret;
  53 +
  54 + /* (4) enable either recovery or normal one */
  55 + if (flags & BIT(0))
  56 + val |= WDT_CTRL_EN1;
  57 + else
  58 + val |= WDT_CTRL_EN0;
  59 +
  60 + if (flags & BIT(1))
  61 + val |= WDT_CTRL_LOCK;
  62 +
  63 + if (flags & BIT(2))
  64 + val &= ~WDT_CTRL_ASSERT_SYS_RESET;
  65 + else
  66 + val |= WDT_CTRL_ASSERT_SYS_RESET;
  67 +
  68 + if (flags & BIT(3))
  69 + val |= WDT_CTRL_ASSERT_WDT_TIMEOUT;
  70 + else
  71 + val &= ~WDT_CTRL_ASSERT_WDT_TIMEOUT;
  72 +
  73 + return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val);
  74 +}
  75 +
  76 +static int sl28cpld_wdt_stop(struct udevice *dev)
  77 +{
  78 + int val;
  79 +
  80 + val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL);
  81 + if (val < 0)
  82 + return val;
  83 +
  84 + return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val & ~WDT_CTRL_EN_MASK);
  85 +}
  86 +
  87 +static int sl28cpld_wdt_expire_now(struct udevice *dev, ulong flags)
  88 +{
  89 + return sl28cpld_wdt_start(dev, 0, flags);
  90 +}
  91 +
  92 +static const struct wdt_ops sl28cpld_wdt_ops = {
  93 + .start = sl28cpld_wdt_start,
  94 + .reset = sl28cpld_wdt_reset,
  95 + .stop = sl28cpld_wdt_stop,
  96 + .expire_now = sl28cpld_wdt_expire_now,
  97 +};
  98 +
  99 +static const struct udevice_id sl28cpld_wdt_ids[] = {
  100 + { .compatible = "kontron,sl28cpld-wdt", },
  101 + {}
  102 +};
  103 +
  104 +U_BOOT_DRIVER(sl28cpld_wdt) = {
  105 + .name = "sl28cpld-wdt",
  106 + .id = UCLASS_WDT,
  107 + .of_match = sl28cpld_wdt_ids,
  108 + .ops = &sl28cpld_wdt_ops,
  109 +};
include/configs/lx2160a_common.h
... ... @@ -244,12 +244,36 @@
244 244 "run distro_bootcmd;run sd2_bootcmd;" \
245 245 "env exists secureboot && esbc_halt;"
246 246  
  247 +#ifdef CONFIG_CMD_USB
  248 +#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
  249 +#else
  250 +#define BOOT_TARGET_DEVICES_USB(func)
  251 +#endif
  252 +
  253 +#ifdef CONFIG_MMC
  254 +#define BOOT_TARGET_DEVICES_MMC(func, instance) func(MMC, mmc, instance)
  255 +#else
  256 +#define BOOT_TARGET_DEVICES_MMC(func)
  257 +#endif
  258 +
  259 +#ifdef CONFIG_SCSI
  260 +#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
  261 +#else
  262 +#define BOOT_TARGET_DEVICES_SCSI(func)
  263 +#endif
  264 +
  265 +#ifdef CONFIG_CMD_DHCP
  266 +#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na)
  267 +#else
  268 +#define BOOT_TARGET_DEVICES_DHCP(func)
  269 +#endif
  270 +
247 271 #define BOOT_TARGET_DEVICES(func) \
248   - func(USB, usb, 0) \
249   - func(MMC, mmc, 0) \
250   - func(MMC, mmc, 1) \
251   - func(SCSI, scsi, 0) \
252   - func(DHCP, dhcp, na)
  272 + BOOT_TARGET_DEVICES_USB(func) \
  273 + BOOT_TARGET_DEVICES_MMC(func, 0) \
  274 + BOOT_TARGET_DEVICES_MMC(func, 1) \
  275 + BOOT_TARGET_DEVICES_SCSI(func) \
  276 + BOOT_TARGET_DEVICES_DHCP(func)
253 277 #include <config_distro_bootcmd.h>
254 278  
255 279 #endif /* __LX2_COMMON_H */
  1 +/* SPDX-License-Identifier: GPL-2.0+ */
  2 +/*
  3 + * Copyright (c) 2021 Michael Walle <michael@walle.cc>
  4 + */
  5 +
  6 +#ifndef __SL28CPLD_H
  7 +#define __SL28CPLD_H
  8 +
  9 +#define SL28CPLD_VERSION 0x03
  10 +
  11 +int sl28cpld_read(struct udevice *dev, uint offset);
  12 +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value);
  13 +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear,
  14 + uint8_t set);
  15 +
  16 +#endif
... ... @@ -230,19 +230,25 @@
230 230 struct image_tool_params *params)
231 231 {
232 232 struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
  233 + uint32_t rcwheader;
233 234  
  235 + if (params->arch == IH_ARCH_ARM)
  236 + rcwheader = RCW_ARM_HEADER;
  237 + else
  238 + rcwheader = RCW_PPC_HEADER;
  239 +
234 240 /* Only a few checks can be done: search for magic numbers */
235 241 if (ENDIANNESS == 'l') {
236 242 if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
237 243 return -FDT_ERR_BADSTRUCTURE;
238 244  
239   - if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
  245 + if (pbl_hdr->rcwheader != reverse_byte(rcwheader))
240 246 return -FDT_ERR_BADSTRUCTURE;
241 247 } else {
242 248 if (pbl_hdr->preamble != RCW_PREAMBLE)
243 249 return -FDT_ERR_BADSTRUCTURE;
244 250  
245   - if (pbl_hdr->rcwheader != RCW_HEADER)
  251 + if (pbl_hdr->rcwheader != rcwheader)
246 252 return -FDT_ERR_BADSTRUCTURE;
247 253 }
248 254 return 0;
... ... @@ -8,7 +8,8 @@
8 8  
9 9 #define RCW_BYTES 64
10 10 #define RCW_PREAMBLE 0xaa55aa55
11   -#define RCW_HEADER 0x010e0100
  11 +#define RCW_ARM_HEADER 0x01ee0100
  12 +#define RCW_PPC_HEADER 0x010e0100
12 13  
13 14 struct pbl_header {
14 15 uint32_t preamble;