Commit 705b5840cde496e30dde386f980737a3beaa52e5
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
- MAINTAINERS
- Makefile
- arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi
- board/kontron/sl28/sl28.c
- configs/kontron_sl28_defconfig
- doc/board/kontron/sl28.rst
- drivers/gpio/Kconfig
- drivers/gpio/Makefile
- drivers/gpio/sl28cpld-gpio.c
- drivers/misc/Kconfig
- drivers/misc/Makefile
- drivers/misc/sl28cpld.c
- drivers/watchdog/Kconfig
- drivers/watchdog/Makefile
- drivers/watchdog/sl28cpld-wdt.c
- include/configs/lx2160a_common.h
- include/sl28cpld.h
- tools/pblimage.c
- tools/pblimage.h
MAINTAINERS
... | ... | @@ -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 |
Makefile
... | ... | @@ -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
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
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 */ |
include/sl28cpld.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 |
tools/pblimage.c
... | ... | @@ -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; |
tools/pblimage.h