From 17a9f3f53d644d025a1a9e6d3a61fc71adf8b9d8 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Fri, 28 Jan 2022 13:10:10 +0200 Subject: [PATCH 01/78] ARM: dts: at91: sama7g5ek: disable slew rate for GMACs non MDIO pins Non GMAC's MDIO pins should have slew rate disabled for R(G)MII modes. Set them accordingly in DT. Signed-off-by: Codrin Ciubotariu Tested-by: Eugen Hristev Reviewed-by: Claudiu Beznea --- arch/arm/dts/sama7g5ek.dts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/arm/dts/sama7g5ek.dts b/arch/arm/dts/sama7g5ek.dts index 6adb044258..ac6f23f64e 100644 --- a/arch/arm/dts/sama7g5ek.dts +++ b/arch/arm/dts/sama7g5ek.dts @@ -125,7 +125,9 @@ #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gmac0_default &pinctrl_gmac0_txc_default>; + pinctrl-0 = <&pinctrl_gmac0_default + &pinctrl_gmac0_mdio_default + &pinctrl_gmac0_txc_default>; phy-mode = "rgmii-id"; status = "okay"; @@ -138,7 +140,7 @@ #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gmac1_default>; + pinctrl-0 = <&pinctrl_gmac1_default &pinctrl_gmac1_mdio_default>; phy-mode = "rmii"; status = "okay"; @@ -235,14 +237,20 @@ , , , - , - , ; + slew-rate = <0>; + bias-disable; + }; + + pinctrl_gmac0_mdio_default: gmac0_mdio_default { + pinmux = , + ; bias-disable; }; pinctrl_gmac0_txc_default: gmac0_txc_default { pinmux = ; + slew-rate = <0>; bias-pull-up; }; @@ -254,8 +262,13 @@ , , , - , - , + ; + slew-rate = <0>; + bias-disable; + }; + + pinctrl_gmac1_mdio_default: gmac1_mdio_default { + pinmux = , ; bias-disable; }; From e145606ff29364e948c05d492732f623674d6010 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Tue, 22 Feb 2022 17:23:25 +0100 Subject: [PATCH 02/78] spi: cadence-qspi: Make reset control optional In the TI am65 device tree files there is no reset defined. Also the Linux kernel driver uses devm_reset_control_get_optional_exclusive(..) to get the reset. Lets do the same as the kernel does and make thr reset optinal. Signed-off-by: Christian Gmeiner Reviewed-by: Jagan Teki --- drivers/spi/cadence_qspi.c | 14 ++++++++------ drivers/spi/cadence_qspi.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index d1b3808c4d..db680618ee 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -201,11 +201,9 @@ static int cadence_spi_probe(struct udevice *bus) } } - ret = reset_get_bulk(bus, &priv->resets); - if (ret) - dev_warn(bus, "Can't get reset: %d\n", ret); - else - reset_deassert_bulk(&priv->resets); + priv->resets = devm_reset_bulk_get_optional(bus); + if (priv->resets) + reset_deassert_bulk(priv->resets); if (!priv->qspi_is_init) { cadence_qspi_apb_controller_init(plat); @@ -220,8 +218,12 @@ static int cadence_spi_probe(struct udevice *bus) static int cadence_spi_remove(struct udevice *dev) { struct cadence_spi_priv *priv = dev_get_priv(dev); + int ret = 0; - return reset_release_bulk(&priv->resets); + if (priv->resets) + ret = reset_release_bulk(priv->resets); + + return ret; } static int cadence_spi_set_mode(struct udevice *bus, uint mode) diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 49b401168f..19345cac5a 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -56,7 +56,7 @@ struct cadence_spi_priv { unsigned int qspi_calibrated_cs; unsigned int previous_hz; - struct reset_ctl_bulk resets; + struct reset_ctl_bulk *resets; }; /* Functions call declaration */ From d56dfc90c7bb2f29a38a98fc2e170ebba6fc6a40 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Tue, 8 Feb 2022 22:52:43 +0000 Subject: [PATCH 03/78] spi: dw: Fix broken dw_spi_mem_ops() The driver is currently using sizeof(op->cmd.opcode) in the op_len calculation. Commit d15de623013c ("spi: spi-mem: allow specifying a command's extension") changed op->cmd.opcode from one byte to two. Instead, a new struct member op->cmd.nbytes is supposed to be used. For regular commands op->cmd.nbytes will be one. Commit d15de623013c ("spi: spi-mem: allow specifying a command's extension") did update some drivers that overload the generic mem_ops() implementation, but forgot to update dw_spi_mem_ops(). Calculating op_len incorrectly causes dw_spi_mem_ops() to misbehave, since op_len is used to determine how many bytes that should be read/written. On the canaan k210 board, this causes the probe of the SPI flash to fail. Fix the op_len calculation in dw_spi_mem_ops(). Doing so results in working SPI flash on the canaan k210 board. Fixes: d15de623013c ("spi: spi-mem: allow specifying a command's extension") Signed-off-by: Niklas Cassel Reviewed-by: Pratyush Yadav Tested-by: Damien Le Moal Reviewed-by: Jagan Teki --- drivers/spi/designware_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 742121140d..fc22f540fe 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -572,7 +572,7 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) int pos, i, ret = 0; struct udevice *bus = slave->dev->parent; struct dw_spi_priv *priv = dev_get_priv(bus); - u8 op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes; + u8 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; u8 op_buf[op_len]; u32 cr0; From 2ba1bd1e11fc46dc7098e274d1c3c3ea64e7c70c Mon Sep 17 00:00:00 2001 From: Rayagonda Kokatanur Date: Wed, 9 Feb 2022 14:16:13 -0800 Subject: [PATCH 04/78] driver: spi: add bcm iproc qspi support IPROC qspi driver supports both BSPI and MSPI modes. Signed-off-by: Rayagonda Kokatanur Signed-off-by: Bharat Gooty Acked-by: Rayagonda Kokatanur Signed-off-by: Roman Bacik Reviewed-by: Jagan Teki --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/iproc_qspi.c | 576 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 583 insertions(+) create mode 100644 drivers/spi/iproc_qspi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0a6a85f9c4..423a757141 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -185,6 +185,12 @@ config ICH_SPI access the SPI NOR flash on platforms embedding this Intel ICH IP core. +config IPROC_QSPI + bool "Broadcom iProc QSPI Flash Controller driver" + help + Enable Broadcom iProc QSPI Flash Controller driver. + This driver can be used to access the SPI NOR flash. + config KIRKWOOD_SPI bool "Marvell Kirkwood SPI Driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index bea746f3e3..7f43f843ca 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o obj-$(CONFIG_FSL_ESPI) += fsl_espi.o obj-$(CONFIG_SYNQUACER_SPI) += spi-synquacer.o obj-$(CONFIG_ICH_SPI) += ich.o +obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o diff --git a/drivers/spi/iproc_qspi.c b/drivers/spi/iproc_qspi.c new file mode 100644 index 0000000000..b5c274314b --- /dev/null +++ b/drivers/spi/iproc_qspi.c @@ -0,0 +1,576 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020-2021 Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Delay required to change the mode of operation */ +#define BUSY_DELAY_US 1 +#define BUSY_TIMEOUT_US 200000 +#define DWORD_ALIGNED(a) (!(((ulong)(a)) & 3)) + +/* Chip attributes */ +#define QSPI_AXI_CLK 175000000 +#define SPBR_MIN 8U +#define SPBR_MAX 255U +#define NUM_CDRAM 16U + +#define CDRAM_PCS0 2 +#define CDRAM_CONT BIT(7) +#define CDRAM_BITS_EN BIT(6) +#define CDRAM_QUAD_MODE BIT(8) +#define CDRAM_RBIT_INPUT BIT(10) +#define MSPI_SPE BIT(6) +#define MSPI_CONT_AFTER_CMD BIT(7) +#define MSPI_MSTR BIT(7) + +/* Register fields */ +#define MSPI_SPCR0_MSB_BITS_8 0x00000020 +#define BSPI_RAF_CONTROL_START_MASK 0x00000001 +#define BSPI_RAF_STATUS_SESSION_BUSY_MASK 0x00000001 +#define BSPI_RAF_STATUS_FIFO_EMPTY_MASK 0x00000002 +#define BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT 3 +#define BSPI_STRAP_OVERRIDE_4BYTE_SHIFT 2 +#define BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT 1 +#define BSPI_STRAP_OVERRIDE_SHIFT 0 +#define BSPI_BPC_DATA_SHIFT 0 +#define BSPI_BPC_MODE_SHIFT 8 +#define BSPI_BPC_ADDR_SHIFT 16 +#define BSPI_BPC_CMD_SHIFT 24 +#define BSPI_BPP_ADDR_SHIFT 16 + +/* MSPI registers */ +#define MSPI_SPCR0_LSB_REG 0x000 +#define MSPI_SPCR0_MSB_REG 0x004 +#define MSPI_SPCR1_LSB_REG 0x008 +#define MSPI_SPCR1_MSB_REG 0x00c +#define MSPI_NEWQP_REG 0x010 +#define MSPI_ENDQP_REG 0x014 +#define MSPI_SPCR2_REG 0x018 +#define MSPI_STATUS_REG 0x020 +#define MSPI_CPTQP_REG 0x024 +#define MSPI_TX_REG 0x040 +#define MSPI_RX_REG 0x0c0 +#define MSPI_CDRAM_REG 0x140 +#define MSPI_WRITE_LOCK_REG 0x180 +#define MSPI_DISABLE_FLUSH_GEN_REG 0x184 + +/* BSPI registers */ +#define BSPI_REVISION_ID_REG 0x000 +#define BSPI_SCRATCH_REG 0x004 +#define BSPI_MAST_N_BOOT_CTRL_REG 0x008 +#define BSPI_BUSY_STATUS_REG 0x00c +#define BSPI_INTR_STATUS_REG 0x010 +#define BSPI_B0_STATUS_REG 0x014 +#define BSPI_B0_CTRL_REG 0x018 +#define BSPI_B1_STATUS_REG 0x01c +#define BSPI_B1_CTRL_REG 0x020 +#define BSPI_STRAP_OVERRIDE_CTRL_REG 0x024 +#define BSPI_FLEX_MODE_ENABLE_REG 0x028 +#define BSPI_BITS_PER_CYCLE_REG 0x02C +#define BSPI_BITS_PER_PHASE_REG 0x030 +#define BSPI_CMD_AND_MODE_BYTE_REG 0x034 +#define BSPI_FLASH_UPPER_ADDR_BYTE_REG 0x038 +#define BSPI_XOR_VALUE_REG 0x03C +#define BSPI_XOR_ENABLE_REG 0x040 +#define BSPI_PIO_MODE_ENABLE_REG 0x044 +#define BSPI_PIO_IODIR_REG 0x048 +#define BSPI_PIO_DATA_REG 0x04C + +/* RAF registers */ +#define BSPI_RAF_START_ADDRESS_REG 0x00 +#define BSPI_RAF_NUM_WORDS_REG 0x04 +#define BSPI_RAF_CTRL_REG 0x08 +#define BSPI_RAF_FULLNESS_REG 0x0C +#define BSPI_RAF_WATERMARK_REG 0x10 +#define BSPI_RAF_STATUS_REG 0x14 +#define BSPI_RAF_READ_DATA_REG 0x18 +#define BSPI_RAF_WORD_CNT_REG 0x1C +#define BSPI_RAF_CURR_ADDR_REG 0x20 + +#define XFER_DUAL BIT(30) +#define XFER_QUAD BIT(31) + +#define FLUSH_BIT BIT(0) +#define MAST_N_BOOT_BIT BIT(0) +#define WRITE_LOCK_BIT BIT(0) + +#define CEIL(m, n) (((m) + (n) - 1) / (n)) +#define UPPER_BYTE_MASK 0xFF000000 +#define SIZE_16MB 0x001000000 + +/* + * struct bcmspi_priv - qspi private structure + * + * @bspi_addr: bspi read address + * @bspi_4byte_addr: bspi 4 byte address mode + * @mspi: mspi registers block address + * @bspi: bspi registers block address + * @bspi_raf: bspi raf registers block address + */ +struct bcmspi_priv { + u32 bspi_addr; + bool bspi_4byte_addr; + fdt_addr_t mspi; + fdt_addr_t bspi; + fdt_addr_t bspi_raf; +}; + +/* BSPI mode */ + +static void bspi_flush_prefetch_buffers(struct bcmspi_priv *priv) +{ + writel(0, priv->bspi + BSPI_B0_CTRL_REG); + writel(0, priv->bspi + BSPI_B1_CTRL_REG); + writel(FLUSH_BIT, priv->bspi + BSPI_B0_CTRL_REG); + writel(FLUSH_BIT, priv->bspi + BSPI_B1_CTRL_REG); +} + +static int bspi_enable(struct bcmspi_priv *priv) +{ + /* Disable write lock */ + writel(0, priv->mspi + MSPI_WRITE_LOCK_REG); + /* Flush prefetch buffers */ + bspi_flush_prefetch_buffers(priv); + /* Switch to BSPI */ + writel(0, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG); + + return 0; +} + +static int bspi_disable(struct bcmspi_priv *priv) +{ + int ret; + uint val; + + if ((readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG) & 1) == 0) { + ret = readl_poll_timeout(priv->bspi + BSPI_BUSY_STATUS_REG, val, !(val & 1), + BUSY_TIMEOUT_US); + if (ret) { + printf("%s: Failed to disable bspi, device busy\n", __func__); + return ret; + } + + /* Switch to MSPI */ + writel(MAST_N_BOOT_BIT, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG); + udelay(BUSY_DELAY_US); + + val = readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG); + if (!(val & 1)) { + printf("%s: Failed to enable mspi\n", __func__); + return -EBUSY; + } + } + + /* Enable write lock */ + writel(WRITE_LOCK_BIT, priv->mspi + MSPI_WRITE_LOCK_REG); + + return 0; +} + +static int bspi_read_via_raf(struct bcmspi_priv *priv, u8 *rx, uint bytes) +{ + u32 status; + uint words; + int aligned; + int ret; + + /* + * Flush data from the previous session (unlikely) + * Read outstanding bits in the poll condition to empty FIFO + */ + ret = readl_poll_timeout(priv->bspi_raf + BSPI_RAF_STATUS_REG, + status, + (!readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG) && + status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK) && + !(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK), + BUSY_TIMEOUT_US); + if (ret) { + printf("%s: Failed to flush fifo\n", __func__); + return ret; + } + + /* Transfer is in words */ + words = CEIL(bytes, 4); + + /* Setup hardware */ + if (priv->bspi_4byte_addr) { + u32 val = priv->bspi_addr & UPPER_BYTE_MASK; + + if (val != readl(priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG)) { + writel(val, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG); + bspi_flush_prefetch_buffers(priv); + } + } + + writel(priv->bspi_addr & ~UPPER_BYTE_MASK, priv->bspi_raf + BSPI_RAF_START_ADDRESS_REG); + writel(words, priv->bspi_raf + BSPI_RAF_NUM_WORDS_REG); + writel(0, priv->bspi_raf + BSPI_RAF_WATERMARK_REG); + + /* Start reading */ + writel(BSPI_RAF_CONTROL_START_MASK, priv->bspi_raf + BSPI_RAF_CTRL_REG); + aligned = DWORD_ALIGNED(rx); + while (bytes) { + status = readl(priv->bspi_raf + BSPI_RAF_STATUS_REG); + if (!(status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK)) { + /* RAF is LE only, convert data to host endianness */ + u32 data = le32_to_cpu(readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG)); + + /* Check if we can use the whole word */ + if (aligned && bytes >= 4) { + *(u32 *)rx = data; + rx += 4; + bytes -= 4; + } else { + uint chunk = min(bytes, 4U); + + /* Read out bytes one by one */ + while (chunk) { + *rx++ = (u8)data; + data >>= 8; + chunk--; + bytes--; + } + } + + continue; + } + if (!(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK)) { + /* FIFO is empty and the session is done */ + break; + } + } + + return 0; +} + +static int bspi_read(struct bcmspi_priv *priv, u8 *rx, uint bytes) +{ + int ret; + + /* Transfer data */ + while (bytes > 0) { + /* Special handing since RAF cannot go across 16MB boundary */ + uint trans = bytes; + /* Divide into multiple transfers if it goes across the 16MB boundary */ + if (priv->bspi_4byte_addr && (priv->bspi_addr >> 24) != + ((priv->bspi_addr + bytes) >> 24)) + trans = SIZE_16MB - (priv->bspi_addr & ~UPPER_BYTE_MASK); + + ret = bspi_read_via_raf(priv, rx, trans); + if (ret) + return ret; + + priv->bspi_addr += trans; + rx += trans; + bytes -= trans; + } + + bspi_flush_prefetch_buffers(priv); + return 0; +} + +static void bspi_set_flex_mode(struct bcmspi_priv *priv, const struct spi_mem_op *op) +{ + int bpp = (op->dummy.nbytes * 8) / op->dummy.buswidth; + int cmd = op->cmd.opcode; + int bpc = ilog2(op->data.buswidth) << BSPI_BPC_DATA_SHIFT | + ilog2(op->addr.buswidth) << BSPI_BPC_ADDR_SHIFT | + ilog2(op->cmd.buswidth) << BSPI_BPC_CMD_SHIFT; + int so = BIT(BSPI_STRAP_OVERRIDE_SHIFT) | + (op->data.buswidth > 1) << BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT | + (op->addr.nbytes > 3) << BSPI_STRAP_OVERRIDE_4BYTE_SHIFT | + (op->data.buswidth > 3) << BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT; + + /* Disable flex mode first */ + writel(0, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG); + + /* Configure single, dual or quad mode */ + writel(bpc, priv->bspi + BSPI_BITS_PER_CYCLE_REG); + + /* Opcode */ + writel(cmd, priv->bspi + BSPI_CMD_AND_MODE_BYTE_REG); + + /* Count of dummy cycles */ + writel(bpp, priv->bspi + BSPI_BITS_PER_PHASE_REG); + + /* Enable 4-byte address */ + if (priv->bspi_4byte_addr) { + setbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT)); + } else { + clrbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT)); + writel(0, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG); + } + + /* Enable flex mode to take effect */ + writel(1, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG); + + /* Flush prefetch buffers since 32MB window BSPI could be used */ + bspi_flush_prefetch_buffers(priv); + + /* Override the strap settings */ + writel(so, priv->bspi + BSPI_STRAP_OVERRIDE_CTRL_REG); +} + +static int bspi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) +{ + struct udevice *bus = dev_get_parent(slave->dev); + struct bcmspi_priv *priv = dev_get_priv(bus); + int ret = -ENOTSUPP; + + /* BSPI read */ + if (op->data.dir == SPI_MEM_DATA_IN && + op->data.nbytes && op->addr.nbytes) { + priv->bspi_4byte_addr = (op->addr.nbytes > 3); + priv->bspi_addr = op->addr.val; + bspi_set_flex_mode(priv, op); + ret = bspi_read(priv, op->data.buf.in, op->data.nbytes); + } + + return ret; +} + +static const struct spi_controller_mem_ops bspi_mem_ops = { + .exec_op = bspi_exec_op, +}; + +/* MSPI mode */ + +static int mspi_exec(struct bcmspi_priv *priv, uint bytes, const u8 *tx, u8 *rx, ulong flags) +{ + u32 cdr = CDRAM_PCS0 | CDRAM_CONT; + bool use_16bits = !(bytes & 1); + + if (flags & XFER_QUAD) { + cdr |= CDRAM_QUAD_MODE; + + if (!tx) + cdr |= CDRAM_RBIT_INPUT; + } + + while (bytes) { + uint chunk; + uint queues; + uint i; + uint val; + int ret; + + if (use_16bits) { + chunk = min(bytes, NUM_CDRAM * 2); + queues = (chunk + 1) / 2; + bytes -= chunk; + + /* Fill CDRAMs */ + for (i = 0; i < queues; i++) + writel(cdr | CDRAM_BITS_EN, priv->mspi + MSPI_CDRAM_REG + 4 * i); + + /* Fill TXRAMs */ + for (i = 0; i < chunk; i++) + writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 4 * i); + } else { + /* Determine how many bytes to process this time */ + chunk = min(bytes, NUM_CDRAM); + queues = chunk; + bytes -= chunk; + + /* Fill CDRAMs and TXRAMS */ + for (i = 0; i < chunk; i++) { + writel(cdr, priv->mspi + MSPI_CDRAM_REG + 4 * i); + writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 8 * i); + } + } + + /* Setup queue pointers */ + writel(0, priv->mspi + MSPI_NEWQP_REG); + writel(queues - 1, priv->mspi + MSPI_ENDQP_REG); + + /* Deassert CS if requested and it's the last transfer */ + if (bytes == 0 && (flags & SPI_XFER_END)) + clrbits_le32(priv->mspi + MSPI_CDRAM_REG + ((queues - 1) << 2), CDRAM_CONT); + + /* Kick off */ + writel(0, priv->mspi + MSPI_STATUS_REG); + if (bytes == 0 && (flags & SPI_XFER_END)) + writel(MSPI_SPE, priv->mspi + MSPI_SPCR2_REG); + else + writel(MSPI_SPE | MSPI_CONT_AFTER_CMD, + priv->mspi + MSPI_SPCR2_REG); + + ret = readl_poll_timeout(priv->mspi + MSPI_STATUS_REG, val, (val & 1), + BUSY_TIMEOUT_US); + if (ret) { + printf("%s: Failed to disable bspi, device busy\n", __func__); + return ret; + } + + /* Read data out */ + if (rx) { + if (use_16bits) { + for (i = 0; i < chunk; i++) + rx[i] = readl(priv->mspi + MSPI_RX_REG + 4 * i) & 0xff; + } else { + for (i = 0; i < chunk; i++) + rx[i] = readl(priv->mspi + MSPI_RX_REG + 8 * i + 4) & 0xff; + } + } + + /* Advance pointers */ + if (tx) + tx += chunk; + if (rx) + rx += chunk; + } + + return 0; +} + +static int mspi_xfer(struct udevice *dev, uint bitlen, const void *dout, void *din, ulong flags) +{ + struct udevice *bus = dev_get_parent(dev); + struct bcmspi_priv *priv = dev_get_priv(bus); + uint bytes; + int ret = 0; + + /* we can only transfer multiples of 8 bits */ + if (bitlen % 8) + return -EPROTONOSUPPORT; + + bytes = bitlen / 8; + + if (flags & SPI_XFER_BEGIN) { + /* Switch to MSPI */ + ret = bspi_disable(priv); + if (ret) + return ret; + } + + /* MSPI: Transfer */ + if (bytes) + ret = mspi_exec(priv, bytes, dout, din, flags); + + if (flags & SPI_XFER_END) { + /* Switch back to BSPI */ + ret = bspi_enable(priv); + if (ret) + return ret; + } + + return ret; +} + +/* iProc interface */ + +static int iproc_qspi_set_speed(struct udevice *bus, uint speed) +{ + struct bcmspi_priv *priv = dev_get_priv(bus); + uint spbr; + + /* MSPI: SCK configuration */ + spbr = (QSPI_AXI_CLK - 1) / (2 * speed) + 1; + writel(max(min(spbr, SPBR_MAX), SPBR_MIN), priv->mspi + MSPI_SPCR0_LSB_REG); + + return 0; +} + +static int iproc_qspi_set_mode(struct udevice *bus, uint mode) +{ + struct bcmspi_priv *priv = dev_get_priv(bus); + + /* MSPI: set master bit and mode */ + writel(MSPI_MSTR /* Master */ | (mode & 3), priv->mspi + MSPI_SPCR0_MSB_REG); + + return 0; +} + +static int iproc_qspi_claim_bus(struct udevice *dev) +{ + /* Nothing to do */ + return 0; +} + +static int iproc_qspi_release_bus(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct bcmspi_priv *priv = dev_get_priv(bus); + + /* Make sure no operation is in progress */ + writel(0, priv->mspi + MSPI_SPCR2_REG); + udelay(BUSY_DELAY_US); + + return 0; +} + +static int iproc_qspi_of_to_plat(struct udevice *bus) +{ + struct bcmspi_priv *priv = dev_get_priv(bus); + + priv->bspi = dev_read_addr_name(bus, "bspi"); + if (IS_ERR((void *)priv->bspi)) { + printf("%s: Failed to get bspi base address\n", __func__); + return PTR_ERR((void *)priv->bspi); + } + + priv->bspi_raf = dev_read_addr_name(bus, "bspi_raf"); + if (IS_ERR((void *)priv->bspi_raf)) { + printf("%s: Failed to get bspi_raf base address\n", __func__); + return PTR_ERR((void *)priv->bspi_raf); + } + + priv->mspi = dev_read_addr_name(bus, "mspi"); + if (IS_ERR((void *)priv->mspi)) { + printf("%s: Failed to get mspi base address\n", __func__); + return PTR_ERR((void *)priv->mspi); + } + + return 0; +} + +static int iproc_qspi_probe(struct udevice *bus) +{ + struct bcmspi_priv *priv = dev_get_priv(bus); + + /* configure mspi */ + writel(0, priv->mspi + MSPI_SPCR1_LSB_REG); + writel(0, priv->mspi + MSPI_SPCR1_MSB_REG); + writel(0, priv->mspi + MSPI_NEWQP_REG); + writel(0, priv->mspi + MSPI_ENDQP_REG); + writel(0, priv->mspi + MSPI_SPCR2_REG); + + /* configure bspi */ + bspi_enable(priv); + + return 0; +} + +static const struct dm_spi_ops iproc_qspi_ops = { + .claim_bus = iproc_qspi_claim_bus, + .release_bus = iproc_qspi_release_bus, + .xfer = mspi_xfer, + .set_speed = iproc_qspi_set_speed, + .set_mode = iproc_qspi_set_mode, + .mem_ops = &bspi_mem_ops, +}; + +static const struct udevice_id iproc_qspi_ids[] = { + { .compatible = "brcm,iproc-qspi" }, + { } +}; + +U_BOOT_DRIVER(iproc_qspi) = { + .name = "iproc_qspi", + .id = UCLASS_SPI, + .of_match = iproc_qspi_ids, + .ops = &iproc_qspi_ops, + .of_to_plat = iproc_qspi_of_to_plat, + .priv_auto = sizeof(struct bcmspi_priv), + .probe = iproc_qspi_probe, +}; From 42595eb7067c6c076e1c98213438be727f883fe2 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:06:24 +0530 Subject: [PATCH 05/78] misc: add sl28cpld base driver Add a multi-function device driver which will probe its children and provides methods to access the device. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- MAINTAINERS | 5 ++ drivers/misc/Kconfig | 8 +++ drivers/misc/Makefile | 1 + drivers/misc/sl28cpld.c | 105 ++++++++++++++++++++++++++++++++++++++++ include/sl28cpld.h | 14 ++++++ 5 files changed, 133 insertions(+) create mode 100644 drivers/misc/sl28cpld.c create mode 100644 include/sl28cpld.h diff --git a/MAINTAINERS b/MAINTAINERS index fb171e0c68..8b3870ff96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1161,6 +1161,11 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git F: arch/sh/ +SL28CLPD +M: Michael Walle +S: Maintained +F: drivers/misc/sl28cpld.c + SPI M: Jagan Teki S: Maintained diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0ade3e32b0..7029bb7b5c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -512,4 +512,12 @@ config ESM_PMIC config FSL_IFC bool +config SL28CPLD + bool "Enable Kontron sl28cpld multi-function driver" + depends on DM_I2C + help + Support for the Kontron sl28cpld management controller. This is + the base driver which provides common access methods for the + sub-drivers. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bca7b24e99..f22eff601a 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -82,3 +82,4 @@ obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_ESM_PMIC) += esm_pmic.o +obj-$(CONFIG_SL28CPLD) += sl28cpld.o diff --git a/drivers/misc/sl28cpld.c b/drivers/misc/sl28cpld.c new file mode 100644 index 0000000000..01ef1c6178 --- /dev/null +++ b/drivers/misc/sl28cpld.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include + +struct sl28cpld_child_plat { + uint offset; +}; + +/* + * The access methods works either with the first argument being a child + * device or with the MFD device itself. + */ +static int sl28cpld_read_child(struct udevice *dev, uint offset) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_read(mfd, offset + plat->offset); +} + +int sl28cpld_read(struct udevice *dev, uint offset) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_read(dev, offset); + else + return sl28cpld_read_child(dev, offset); +} + +static int sl28cpld_write_child(struct udevice *dev, uint offset, + uint8_t value) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + struct udevice *mfd = dev_get_parent(dev); + + return dm_i2c_reg_write(mfd, offset + plat->offset, value); +} + +int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value) +{ + if (dev->driver == DM_DRIVER_GET(sl28cpld)) + return dm_i2c_reg_write(dev, offset, value); + else + return sl28cpld_write_child(dev, offset, value); +} + +int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear, + uint8_t set) +{ + int val; + + val = sl28cpld_read(dev, offset); + if (val < 0) + return val; + + val &= ~clear; + val |= set; + + return sl28cpld_write(dev, offset, val); +} + +static int sl28cpld_probe(struct udevice *dev) +{ + i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | + DM_I2C_CHIP_WR_ADDRESS); + + return 0; +} + +static int sl28cpld_child_post_bind(struct udevice *dev) +{ + struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev); + int offset; + + if (!dev_has_ofnode(dev)) + return 0; + + offset = dev_read_u32_default(dev, "reg", -1); + if (offset == -1) + return -EINVAL; + + plat->offset = offset; + + return 0; +} + +static const struct udevice_id sl28cpld_ids[] = { + { .compatible = "kontron,sl28cpld" }, + {} +}; + +U_BOOT_DRIVER(sl28cpld) = { + .name = "sl28cpld", + .id = UCLASS_NOP, + .of_match = sl28cpld_ids, + .probe = sl28cpld_probe, + .bind = dm_scan_fdt_dev, + .flags = DM_FLAG_PRE_RELOC, + .per_child_plat_auto = sizeof(struct sl28cpld_child_plat), + .child_post_bind = sl28cpld_child_post_bind, +}; diff --git a/include/sl28cpld.h b/include/sl28cpld.h new file mode 100644 index 0000000000..d116607cfb --- /dev/null +++ b/include/sl28cpld.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2021 Michael Walle + */ + +#ifndef __SL28CPLD_H +#define __SL28CPLD_H + +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 From f606c9a8959728f7df539e182fb799d3ccc92cc6 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:43 +0100 Subject: [PATCH 06/78] watchdog: add sl28cpld watchdog driver The watchdog timer is part of the sl28cpld management controller. The watchdog timer usually supervises the bootloader boot-up and if it bites the failsafe bootloader will be activated. Apart from that it supports the usual board level reset and one SMARC speciality: driving the WDT_TIMEOUT# signal. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- MAINTAINERS | 1 + doc/board/kontron/sl28.rst | 53 +++++++++++----- drivers/watchdog/Kconfig | 7 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sl28cpld-wdt.c | 109 ++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 drivers/watchdog/sl28cpld-wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 8b3870ff96..989ea41e2c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1165,6 +1165,7 @@ SL28CLPD M: Michael Walle S: Maintained F: drivers/misc/sl28cpld.c +F: drivers/watchdog/sl28cpld-wdt.c SPI M: Jagan Teki diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index c7b18bed10..c2cdc5e424 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -35,23 +35,6 @@ 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 - - Update image ------------ @@ -82,6 +65,42 @@ u-boot (yet). But you can use the i2c command to access it. > i2c md 4a 3.1 1 +Builtin watchdog +---------------- + +The builtin watchdog will supervise the bootloader startup. If anything +goes wrong it will reset the board and boot into the failsafe bootloader. + +Once the bootloader is started successfully, it will disable the watchdog +timer. + +wdt command flags +^^^^^^^^^^^^^^^^^ + +The `wdt start` as well as the `wdt expire` command take a flags argument. +The supported bitmask is as follows. + +| 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 ------------------------------------- diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cabac29053..f90f0ca02b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -266,6 +266,13 @@ config WDT_SBSA In the single stage mode, when the timeout is reached, your system will be reset by WS1. The first signal (WS0) is ignored. +config WDT_SL28CPLD + bool "sl28cpld watchdog timer support" + depends on WDT && SL28CPLD + help + Enable support for the watchdog timer in the Kontron sl28cpld + management controller. + config WDT_SP805 bool "SP805 watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 6d2b3822c0..a35bd559f5 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o +obj-$(CONFIG_WDT_SL28CPLD) += sl28cpld-wdt.o obj-$(CONFIG_WDT_SP805) += sp805_wdt.o obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o diff --git a/drivers/watchdog/sl28cpld-wdt.c b/drivers/watchdog/sl28cpld-wdt.c new file mode 100644 index 0000000000..af5a6b1a28 --- /dev/null +++ b/drivers/watchdog/sl28cpld-wdt.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Watchdog driver for the sl28cpld + * + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include +#include +#include + +#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, +}; From 07d6cb93781d47a8cb94c63b6419c68923b6f09d Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:10:24 +0530 Subject: [PATCH 07/78] gpio: add sl28cpld driver The gpio block is part of the sl28cpld sl28cpld management controller. There are three different flavors: the usual input and output where the direction is configurable, but also input only and output only variants. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- MAINTAINERS | 1 + drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/sl28cpld-gpio.c | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 drivers/gpio/sl28cpld-gpio.c diff --git a/MAINTAINERS b/MAINTAINERS index 989ea41e2c..0f39bc6bc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1164,6 +1164,7 @@ F: arch/sh/ SL28CLPD M: Michael Walle S: Maintained +F: drivers/gpio/sl28cpld-gpio.c F: drivers/misc/sl28cpld.c F: drivers/watchdog/sl28cpld-wdt.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8d0e47c67d..522dfc195e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -544,4 +544,10 @@ config ZYNQMP_GPIO_MODEPIN are accessed using xilinx firmware. In modepin register, [3:0] bits set direction, [7:4] bits read IO, [11:8] bits set/clear IO. +config SL28CPLD_GPIO + bool "Kontron sl28cpld GPIO driver" + depends on DM_GPIO && SL28CPLD + help + Support GPIO access on Kontron sl28cpld board management controllers. + endif diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 63e9be6034..33f7d41b7d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -70,4 +70,5 @@ obj-$(CONFIG_NX_GPIO) += nx_gpio.o obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o +obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o diff --git a/drivers/gpio/sl28cpld-gpio.c b/drivers/gpio/sl28cpld-gpio.c new file mode 100644 index 0000000000..700fc3df29 --- /dev/null +++ b/drivers/gpio/sl28cpld-gpio.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * GPIO driver for the sl28cpld + * + * Copyright (c) 2021 Michael Walle + */ + +#include +#include +#include +#include + +/* 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, +}; From fea51613222edba814d33a21d9485463cf3988f3 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:45 +0100 Subject: [PATCH 08/78] board: sl28: fix DRAM pretty print The current console output is: DRAM: 4 GiB DDR 4 GiB (DDR3, 32-bit, CL=11, ECC on) The size is printed twice and we can save one line of console output if we join both lines. The new output is as follows: DRAM: 4 GiB (DDR3, 32-bit, CL=11, ECC on) Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index e84b356918..a4ee8a1ef3 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -47,8 +47,6 @@ int checkboard(void) 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); } From d36b683a0f4d9cd22aded61595b771c88203f3ab Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:46 +0100 Subject: [PATCH 09/78] board: sl28: print CPLD version on bootup Most of the time it is very useful to have the version of the board management controller. Now that we have a driver, print it during startup. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 28 ++++++++++++++++++++++++++++ include/sl28cpld.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index a4ee8a1ef3..9cde48e61e 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include +#include #include #include #include @@ -15,6 +16,7 @@ #include #include +#include #include #include @@ -39,9 +41,35 @@ 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; } diff --git a/include/sl28cpld.h b/include/sl28cpld.h index d116607cfb..9a7c6de31f 100644 --- a/include/sl28cpld.h +++ b/include/sl28cpld.h @@ -6,6 +6,8 @@ #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, From 34502f7aa343c58c9b4a7206e9fd44e3b89b4dea Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:47 +0100 Subject: [PATCH 10/78] board: sl28: enable sl28cpld support Enable the GPIO and watchdog driver. Don't start the watchdog automatically, though. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index b61276cf1d..a0c0c3c6a1 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -42,12 +42,14 @@ 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 @@ -69,8 +71,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 +106,10 @@ 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_OF_LIBFDT_ASSUME_MASK=0x0 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_EFI_SET_TIME=y From 2ba8a446ceece208c5926b623ddfd66bd163ff27 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:48 +0100 Subject: [PATCH 11/78] board: sl28: enable SoC watchdog support The SoC provides two additional watchdogs integrated in the SoC. Enable support for these. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index a0c0c3c6a1..a4d9254815 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -110,6 +110,7 @@ CONFIG_USB_GADGET_DOWNLOAD=y # 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 From 453d1711d22c4bccd48848a8450aa95cbc5008cc Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:49 +0100 Subject: [PATCH 12/78] board: sl28: disable recovery watchdog This board has an internal watchdog which supervises the board startup. Although, the initial state of the watchdog is configurable, it is enabled by default. In board_late_init(), which means almost everything worked as expected, disable the watchdog. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- board/kontron/sl28/sl28.c | 29 +++++++++++++++++++++++++++++ doc/board/kontron/sl28.rst | 12 ++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index 9cde48e61e..3c48a9141d 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,34 @@ int checkboard(void) 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) { print_ddr_info(0); diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index c2cdc5e424..04483e1e57 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -23,17 +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. +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 ------------ From 2810da7c80ad7d25ef987d65bcaad2479f1df30e Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Mon, 15 Nov 2021 23:45:50 +0100 Subject: [PATCH 13/78] board: sl28: remove "Useful I2C tricks" section from docs They are no longer needed, because we now have proper driver support for the sl28cpld management controller. Signed-off-by: Michael Walle Reviewed-by: Priyanka Jain --- doc/board/kontron/sl28.rst | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/doc/board/kontron/sl28.rst b/doc/board/kontron/sl28.rst index 04483e1e57..44435d90c6 100644 --- a/doc/board/kontron/sl28.rst +++ b/doc/board/kontron/sl28.rst @@ -50,21 +50,6 @@ 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 ------------------ - -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. - -- reset into failsafe bootloader:: - - > i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42 - -- read board management controller version:: - - > i2c md 4a 3.1 1 - - Builtin watchdog ---------------- From 62ba0e5df6e81f0a45b589273c043d451986767c Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:18:40 +0530 Subject: [PATCH 14/78] board: sl28: disable random MAC address generation Nowadays, u-boot (when CONFIG_NET_RANDOM_ETHADDR is set) will set enetaddr to a random value if not set and then pass the randomly generated MAC address to linux. This is bad for the following reasons: (1) it makes it impossible for linux to detect this error (2) linux won't trigger any fallback mechanism for the case where it didn't find any valid MAC address (3) a saveenv will store this randomly generated MAC address in the environment Probably, the user will also be unaware that something is wrong. He will just get different MAC addresses on each reboot, asking himself why this is the case. As this board usually have a serial port, the user can just fix this by setting the MAC address manually in the environment. Also disable the netconsole just in case, because it cannot be guaranteed that it will work in any case. After all, this was just a convenience option, because the bootloader - right now - doesn't have the ability to read the MAC address, which is stored in the OTP. But it is far more important to have a clear view of whats wrong with a board and that means we can no longer use this Kconfig option. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- configs/kontron_sl28_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index a4d9254815..b743c2ba9e 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -59,8 +59,6 @@ CONFIG_OF_LIST="" 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 From 554a85313bc7bb50704c2a8d6f4857037aea2426 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Fri, 25 Feb 2022 18:21:56 +0530 Subject: [PATCH 15/78] board: sl28: use fit image generator Simplify the binman config and fdt nodes by using the "@..-SEQ" substitutions and CONFIG_OF_LIST. Signed-off-by: Michael Walle [Rebased] Signed-off-by: Priyanka Jain --- .../dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi | 128 ++---------------- configs/kontron_sl28_defconfig | 2 +- 2 files changed, 10 insertions(+), 120 deletions(-) diff --git a/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi b/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi index d4b833284e..2dcb3c2a58 100644 --- a/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi +++ b/arch/arm/dts/fsl-ls1028a-kontron-sl28-u-boot.dtsi @@ -27,6 +27,7 @@ fit { offset = ; 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"; }; }; diff --git a/configs/kontron_sl28_defconfig b/configs/kontron_sl28_defconfig index b743c2ba9e..cf8aedfdfd 100644 --- a/configs/kontron_sl28_defconfig +++ b/configs/kontron_sl28_defconfig @@ -55,7 +55,7 @@ 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 From 453db6056850e1ac1be0a12df72fcf3bd5f61bd3 Mon Sep 17 00:00:00 2001 From: Daniel Klauer Date: Wed, 9 Feb 2022 15:53:41 +0100 Subject: [PATCH 16/78] lx2160a: Fix distroboot device list for configs without USB/SCSI/etc The BOOT_TARGET_DEVICES list for distro_bootcmd was hard-coded to assume that all boot devices are available/enabled in the configuration, thus ignoring the actual config settings. The config_distro_bootcmd.h header file specifically has compile-time checks to detect such problems. To allow disabling USB, SCSI, etc. in custom lx2160a board configs, make it depend on the config settings and use only the enabled features. Signed-off-by: Daniel Klauer Reviewed-by: Priyanka Jain --- include/configs/lx2160a_common.h | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/include/configs/lx2160a_common.h b/include/configs/lx2160a_common.h index e31f8d087f..4f4b5713dc 100644 --- a/include/configs/lx2160a_common.h +++ b/include/configs/lx2160a_common.h @@ -244,12 +244,36 @@ "run distro_bootcmd;run sd2_bootcmd;" \ "env exists secureboot && esbc_halt;" +#ifdef CONFIG_CMD_USB +#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0) +#else +#define BOOT_TARGET_DEVICES_USB(func) +#endif + +#ifdef CONFIG_MMC +#define BOOT_TARGET_DEVICES_MMC(func, instance) func(MMC, mmc, instance) +#else +#define BOOT_TARGET_DEVICES_MMC(func) +#endif + +#ifdef CONFIG_SCSI +#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0) +#else +#define BOOT_TARGET_DEVICES_SCSI(func) +#endif + +#ifdef CONFIG_CMD_DHCP +#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na) +#else +#define BOOT_TARGET_DEVICES_DHCP(func) +#endif + #define BOOT_TARGET_DEVICES(func) \ - func(USB, usb, 0) \ - func(MMC, mmc, 0) \ - func(MMC, mmc, 1) \ - func(SCSI, scsi, 0) \ - func(DHCP, dhcp, na) + BOOT_TARGET_DEVICES_USB(func) \ + BOOT_TARGET_DEVICES_MMC(func, 0) \ + BOOT_TARGET_DEVICES_MMC(func, 1) \ + BOOT_TARGET_DEVICES_SCSI(func) \ + BOOT_TARGET_DEVICES_DHCP(func) #include #endif /* __LX2_COMMON_H */ From 2058967d2fe8f93142d774bc47241d80894027d5 Mon Sep 17 00:00:00 2001 From: Hou Zhiqiang Date: Thu, 17 Feb 2022 11:51:36 +0800 Subject: [PATCH 17/78] tools: pblimage: fix image header verification function The Layerscape platforms have different RCW header value from FSL PowerPC platforms, the current image header verification callback is only working on PowerPC, it will fail on Layerscape, this patch is to fix this issue. This is a historical problem and exposed by the following patch: http://patchwork.ozlabs.org/project/uboot/patch/20220114173443.9877-1-pali@kernel.org Signed-off-by: Hou Zhiqiang Reviewed-by: Priyanka Jain --- Makefile | 2 +- tools/pblimage.c | 10 ++++++++-- tools/pblimage.h | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 66d9e78cc7..4d9cda7f30 100644 --- a/Makefile +++ b/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 diff --git a/tools/pblimage.c b/tools/pblimage.c index 3c823e96cf..bd639c276f 100644 --- a/tools/pblimage.c +++ b/tools/pblimage.c @@ -230,19 +230,25 @@ static int pblimage_verify_header(unsigned char *ptr, int image_size, struct image_tool_params *params) { struct pbl_header *pbl_hdr = (struct pbl_header *) ptr; + uint32_t rcwheader; + + if (params->arch == IH_ARCH_ARM) + rcwheader = RCW_ARM_HEADER; + else + rcwheader = RCW_PPC_HEADER; /* Only a few checks can be done: search for magic numbers */ if (ENDIANNESS == 'l') { if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE)) return -FDT_ERR_BADSTRUCTURE; - if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER)) + if (pbl_hdr->rcwheader != reverse_byte(rcwheader)) return -FDT_ERR_BADSTRUCTURE; } else { if (pbl_hdr->preamble != RCW_PREAMBLE) return -FDT_ERR_BADSTRUCTURE; - if (pbl_hdr->rcwheader != RCW_HEADER) + if (pbl_hdr->rcwheader != rcwheader) return -FDT_ERR_BADSTRUCTURE; } return 0; diff --git a/tools/pblimage.h b/tools/pblimage.h index 81c5492926..0222e8067b 100644 --- a/tools/pblimage.h +++ b/tools/pblimage.h @@ -8,7 +8,8 @@ #define RCW_BYTES 64 #define RCW_PREAMBLE 0xaa55aa55 -#define RCW_HEADER 0x010e0100 +#define RCW_ARM_HEADER 0x01ee0100 +#define RCW_PPC_HEADER 0x010e0100 struct pbl_header { uint32_t preamble; From a41b88ec02ea1dbf4e5e6e895625a5fee96097c5 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Mon, 28 Feb 2022 14:53:21 -0800 Subject: [PATCH 18/78] phy: nop-phy: Fix phy reset if no reset-gpio defined Ensure there is a valid reset-gpio defined before using it. Fixes: f9852acdce02 ("phy: nop-phy: Fix enabling reset") Cc: Adam Ford Signed-off-by: Tim Harvey --- drivers/phy/nop-phy.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/phy/nop-phy.c b/drivers/phy/nop-phy.c index e2ee6e9206..d0904f4f07 100644 --- a/drivers/phy/nop-phy.c +++ b/drivers/phy/nop-phy.c @@ -45,11 +45,13 @@ static int nop_phy_init(struct phy *phy) #if CONFIG_IS_ENABLED(DM_GPIO) /* Take phy out of reset */ - ret = dm_gpio_set_value(&priv->reset_gpio, false); - if (ret) { - if (CONFIG_IS_ENABLED(CLK)) - clk_disable_bulk(&priv->bulk); - return ret; + if (dm_gpio_is_valid(&priv->reset_gpio)) { + ret = dm_gpio_set_value(&priv->reset_gpio, false); + if (ret) { + if (CONFIG_IS_ENABLED(CLK)) + clk_disable_bulk(&priv->bulk); + return ret; + } } #endif return 0; From a08b04b5c75a7e9122dfc733c66b978aa0afe4ba Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 11 Feb 2022 19:32:33 -0500 Subject: [PATCH 19/78] mach-sunxi: Add boot device detection for SUNIV/F1C100s In contrast to other Allwinner SoCs the F1C100s BROM does not store a boot source indicator in the eGON header in SRAM. This leaves the SPL guessing where we were exactly booted from, and for instance trying the SD card first, even though we booted from SPI flash. By inspecting the BROM code and by experimentation, Samuel found that the top of the BROM stack contains unique pointers for each of the boot sources, which we can use as a boot source indicator. This patch removes the existing board_boot_order bodge and replace it with a proper boot source indication function. The only caveat is that this only works in the SPL, as the SPL header gets overwritten with the exception vectors, once U-Boot proper takes over. Always return MMC0 as the boot source, when called from U-Boot proper, as a placeholder for now, until we find another way. Signed-off-by: Jesse Taube Suggested-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/spl.h | 9 ++++ arch/arm/mach-sunxi/board.c | 64 ++++++++++++++++----------- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index 58cdf806d9..b543d24e5a 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -19,6 +19,15 @@ #define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10 #define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12 +/* + * Values taken from the F1C200s BootROM stack + * to determine where we booted from. + */ +#define SUNIV_BOOTED_FROM_MMC0 0xffff40f8 +#define SUNIV_BOOTED_FROM_NAND 0xffff4114 +#define SUNIV_BOOTED_FROM_SPI 0xffff4130 +#define SUNIV_BOOTED_FROM_MMC1 0xffff4150 + #define is_boot0_magic(addr) (memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0) uint32_t sunxi_get_boot_device(void); diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 57078f7a7b..0071de19ff 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -191,12 +191,48 @@ SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image); #define SUNXI_INVALID_BOOT_SOURCE -1 +static int suniv_get_boot_source(void) +{ + /* Get the last function call from BootROM's stack. */ + u32 brom_call = *(u32 *)(uintptr_t)(fel_stash.sp - 4); + + /* translate SUNIV BootROM stack to standard SUNXI boot sources */ + switch (brom_call) { + case SUNIV_BOOTED_FROM_MMC0: + return SUNXI_BOOTED_FROM_MMC0; + case SUNIV_BOOTED_FROM_SPI: + return SUNXI_BOOTED_FROM_SPI; + case SUNIV_BOOTED_FROM_MMC1: + return SUNXI_BOOTED_FROM_MMC2; + /* SPI NAND is not supported yet. */ + case SUNIV_BOOTED_FROM_NAND: + return SUNXI_INVALID_BOOT_SOURCE; + } + /* If we get here something went wrong try to boot from FEL.*/ + printf("Unknown boot source from BROM: 0x%x\n", brom_call); + return SUNXI_INVALID_BOOT_SOURCE; +} + static int sunxi_get_boot_source(void) { + /* + * On the ARMv5 SoCs, the SPL header in SRAM is overwritten by the + * exception vectors in U-Boot proper, so we won't find any + * information there. Also the FEL stash is only valid in the SPL, + * so we can't use that either. So if this is called from U-Boot + * proper, just return MMC0 as a placeholder, for now. + */ + if (IS_ENABLED(CONFIG_MACH_SUNIV) && + !IS_ENABLED(CONFIG_SPL_BUILD)) + return SUNXI_BOOTED_FROM_MMC0; + if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */ return SUNXI_INVALID_BOOT_SOURCE; - return readb(SPL_ADDR + 0x28); + if (IS_ENABLED(CONFIG_MACH_SUNIV)) + return suniv_get_boot_source(); + else + return readb(SPL_ADDR + 0x28); } /* The sunxi internal brom will try to loader external bootloader @@ -276,36 +312,10 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc, return sector; } -#ifdef CONFIG_MACH_SUNIV -/* - * The suniv BROM does not pass the boot media type to SPL, so we try with the - * boot sequence in BROM: mmc0->spinor->fail. - * TODO: This has the slight chance of being wrong (invalid SPL signature, - * but valid U-Boot legacy image on the SD card), but this should be rare. - * It looks like we can deduce from some BROM state upon entering the SPL - * (registers, SP, or stack itself) where the BROM was coming from and use - * that here. - */ -void board_boot_order(u32 *spl_boot_list) -{ - /* - * See the comments above in sunxi_get_boot_device() for information - * about FEL boot. - */ - if (!is_boot0_magic(SPL_ADDR + 4)) { - spl_boot_list[0] = BOOT_DEVICE_BOARD; - return; - } - - spl_boot_list[0] = BOOT_DEVICE_MMC1; - spl_boot_list[1] = BOOT_DEVICE_SPI; -} -#else u32 spl_boot_device(void) { return sunxi_get_boot_device(); } -#endif __weak void sunxi_sram_init(void) { From 0dcdaff8b88e996de5d9c91141084cbfcfb01be6 Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 11 Feb 2022 19:32:34 -0500 Subject: [PATCH 20/78] mach-sunxi: Add SPL SPI boot for SUNIV The SUNIV SoCs come with a sun6i-style SPI controller at the base address of sun4i SPI controller. The module clock of the SPI controller is missing which leaves us running directly from the AHB clock, which is set to 200MHz. Signed-off-by: Icenowy Zheng [Icenowy: Original implementation] Signed-off-by: Jesse Taube [Jesse: adaptation to Upstream U-Boot] Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/include/asm/arch-sunxi/gpio.h | 1 + arch/arm/mach-sunxi/spl_spi_sunxi.c | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 7f7eb0517c..edd0fbf49f 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -160,6 +160,7 @@ enum sunxi_gpio_number { #define SUNXI_GPC_SDC2 3 #define SUN6I_GPC_SDC3 4 #define SUN50I_GPC_SPI0 4 +#define SUNIV_GPC_SPI0 2 #define SUNXI_GPD_LCD0 2 #define SUNXI_GPD_LVDS0 3 diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c index 910e805016..734c165e5d 100644 --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c @@ -90,6 +90,7 @@ #define SPI0_CLK_DIV_BY_2 0x1000 #define SPI0_CLK_DIV_BY_4 0x1001 +#define SPI0_CLK_DIV_BY_32 0x100f /*****************************************************************************/ @@ -132,7 +133,8 @@ static uintptr_t spi0_base_address(void) if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) return 0x05010000; - if (!is_sun6i_gen_spi()) + if (!is_sun6i_gen_spi() || + IS_ENABLED(CONFIG_MACH_SUNIV)) return 0x01C05000; return 0x01C68000; @@ -156,11 +158,16 @@ static void spi0_enable_clock(void) if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6)) setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0)); - /* Divide by 4 */ - writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ? - SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL)); - /* 24MHz from OSC24M */ - writel((1 << 31), CCM_SPI0_CLK); + if (IS_ENABLED(CONFIG_MACH_SUNIV)) { + /* Divide by 32, clock source is AHB clock 200MHz */ + writel(SPI0_CLK_DIV_BY_32, base + SUN6I_SPI0_CCTL); + } else { + /* Divide by 4 */ + writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ? + SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL)); + /* 24MHz from OSC24M */ + writel((1 << 31), CCM_SPI0_CLK); + } if (is_sun6i_gen_spi()) { /* Enable SPI in the master mode and do a soft reset */ @@ -191,7 +198,8 @@ static void spi0_disable_clock(void) SUN4I_CTL_ENABLE); /* Disable the SPI0 clock */ - writel(0, CCM_SPI0_CLK); + if (!IS_ENABLED(CONFIG_MACH_SUNIV)) + writel(0, CCM_SPI0_CLK); /* Close the SPI0 gate */ if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6)) @@ -212,6 +220,8 @@ static void spi0_init(void) if (IS_ENABLED(CONFIG_MACH_SUN50I) || IS_ENABLED(CONFIG_MACH_SUN50I_H6)) pin_function = SUN50I_GPC_SPI0; + else if (IS_ENABLED(CONFIG_MACH_SUNIV)) + pin_function = SUNIV_GPC_SPI0; spi0_pinmux_setup(pin_function); spi0_enable_clock(); From 640f2f3bf1d6320274b17192a1ab9d8030211302 Mon Sep 17 00:00:00 2001 From: Jesse Taube Date: Fri, 11 Feb 2022 19:32:35 -0500 Subject: [PATCH 21/78] mach-sunxi: Enable SPI boot for SUNIV and licheepi nano Enable SPI boot in SPL on SUNIV architecture and use it in the licheepi nano that uses the F1C100s. Signed-off-by: Jesse Taube Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- arch/arm/mach-sunxi/Kconfig | 2 +- configs/licheepi_nano_defconfig | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 205fe3c9d3..d1c60d2408 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -1038,7 +1038,7 @@ config SPL_STACK_R_ADDR config SPL_SPI_SUNXI bool "Support for SPI Flash on Allwinner SoCs in SPL" - depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 + depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 || MACH_SUNIV help Enable support for SPI Flash. This option allows SPL to read from sunxi SPI Flash. It uses the same method as the boot ROM, so does diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig index 2ac0ef4285..9fd1dcc995 100644 --- a/configs/licheepi_nano_defconfig +++ b/configs/licheepi_nano_defconfig @@ -9,3 +9,4 @@ CONFIG_MACH_SUNIV=y CONFIG_DRAM_CLK=156 CONFIG_DRAM_ZQ=0 # CONFIG_VIDEO_SUNXI is not set +CONFIG_SPL_SPI_SUNXI=y From c21f3d45711135179b4abbdc9462109a41060df6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 1 Mar 2022 12:21:58 +0000 Subject: [PATCH 22/78] sunxi: f1c100s: Fix FEL registers restore Commit 88998f777531 ("arm: arm926ej-s: Add sunxi code") introduced the ARM926 version of the code to save and restore some FEL state, to be able to return to the BROM FEL code after the SPL has run. However during review a change was made, that happened to mess up the register restore part, so SCTLR and CPSR ended up with the wrong values, breaking return to FEL. Use the same offset that we actually save those registers to, to make FEL booting actually work on the Lichee Pi Nano. Signed-off-by: Andre Przywara --- arch/arm/cpu/arm926ejs/sunxi/fel_utils.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S index 08be7ed11a..25924033c6 100644 --- a/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S +++ b/arch/arm/cpu/arm926ejs/sunxi/fel_utils.S @@ -25,9 +25,9 @@ ENTRY(return_to_fel) mov sp, r0 mov lr, r1 ldr r0, =fel_stash - ldr r1, [r0, #16] - mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register ldr r1, [r0, #12] + mcr p15, 0, r1, c1, c0, 0 @ Write CP15 SCTLR register + ldr r1, [r0, #8] msr cpsr, r1 @ Write CPSR bx lr ENDPROC(return_to_fel) From cfcf1952c11e6ffcbbf88eb63c49edca2acf1d5e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 2 Mar 2022 01:30:55 +0000 Subject: [PATCH 23/78] sunxi: f1c100s: Drop SYSRESET to enable reset functionality The F1C100s DT contains the wrong compatible string for the watchdog, which breaks reset functionality. Updating the DT goes via the Linux tree, but to allow reset functionality meanwhile (useful for development!), disable SYSRESET for now, to let the old-fashioned watchdog driver kick in and provide the reset_cpu() implementation. Signed-off-by: Andre Przywara --- configs/licheepi_nano_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig index 9fd1dcc995..67b7b85c49 100644 --- a/configs/licheepi_nano_defconfig +++ b/configs/licheepi_nano_defconfig @@ -10,3 +10,4 @@ CONFIG_DRAM_CLK=156 CONFIG_DRAM_ZQ=0 # CONFIG_VIDEO_SUNXI is not set CONFIG_SPL_SPI_SUNXI=y +# CONFIG_SYSRESET is not set From 7938b3be7cedcfe54e891c86e4297b0dccde0f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 18 Feb 2022 12:24:13 +0100 Subject: [PATCH 24/78] tools: kwboot: Fix quitting terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes kwboot after quitting terminal prints error message: terminal: Bad address This is caused by trying to call write() syscall with count of (size_t)-1 bytes. When quit sequence is split into more read() calls then number of input bytes (nin) at the end of cycle can underflow and be negative. Fix it. Fixes: de7514046ea5 ("tools: kwboot: Fix detection of quit esc sequence") Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 68c0ef1f1b..2d2d545d82 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -1197,7 +1197,7 @@ kwboot_term_pipe(int in, int out, const char *quit, int *s) if (buf[i] == quit[*s]) { (*s)++; if (!quit[*s]) { - nin = i - *s; + nin = (i > *s) ? (i - *s) : 0; break; } } else { @@ -1208,7 +1208,7 @@ kwboot_term_pipe(int in, int out, const char *quit, int *s) } if (i == nin) - nin -= *s; + nin -= (nin > *s) ? *s : nin; } if (kwboot_write(out, buf, nin) < 0) From 68285176a9552ba264878cdc6c7daccb5806b569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 18 Feb 2022 12:25:22 +0100 Subject: [PATCH 25/78] pci: pci_mvebu: Remove unused SELECT and lane_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Macro SELECT() is unused and struct mvebu_pcie field lane_mask is unused too. Remove them. Signed-off-by: Pali Rohár Reviewed-by: Marek Behún Reviewed-by: Stefan Roese --- drivers/pci/pci_mvebu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 5a0a59a8b9..16fe54fd36 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -30,8 +30,6 @@ #include /* PCIe unit register offsets */ -#define SELECT(x, n) ((x >> n) & 1UL) - #define PCIE_DEV_ID_OFF 0x0000 #define PCIE_CMD_OFF 0x0004 #define PCIE_DEV_REV_OFF 0x0008 @@ -77,7 +75,6 @@ struct mvebu_pcie { u32 lane; bool is_x4; int devfn; - u32 lane_mask; int sec_busno; char name[16]; unsigned int mem_target; From fc27e5df637dd4c954b67dd1415b9af144718a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 18 Feb 2022 12:25:23 +0100 Subject: [PATCH 26/78] pci: pci_mvebu: Cleanup macro names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use "MVPCIE_" prefix instead of generic "PCIE_" prefix for pci_mvebu.c specific macros. Define offset macros for Root Port registers and use standard register macros from pci.h when accessing Root Port registers. Signed-off-by: Pali Rohár Reviewed-by: Marek Behún Reviewed-by: Stefan Roese --- drivers/pci/pci_mvebu.c | 130 +++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 70 deletions(-) diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 16fe54fd36..f07669374d 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -30,35 +30,25 @@ #include /* PCIe unit register offsets */ -#define PCIE_DEV_ID_OFF 0x0000 -#define PCIE_CMD_OFF 0x0004 -#define PCIE_DEV_REV_OFF 0x0008 -#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) -#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) -#define PCIE_EXP_ROM_BAR_OFF 0x0030 -#define PCIE_CAPAB_OFF 0x0060 -#define PCIE_CTRL_STAT_OFF 0x0068 -#define PCIE_HEADER_LOG_4_OFF 0x0128 -#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4)) -#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) -#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4)) -#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4)) -#define PCIE_WIN5_CTRL_OFF 0x1880 -#define PCIE_WIN5_BASE_OFF 0x1884 -#define PCIE_WIN5_REMAP_OFF 0x188c -#define PCIE_CONF_ADDR_OFF 0x18f8 -#define PCIE_CONF_DATA_OFF 0x18fc -#define PCIE_MASK_OFF 0x1910 -#define PCIE_MASK_ENABLE_INTS (0xf << 24) -#define PCIE_CTRL_OFF 0x1a00 -#define PCIE_CTRL_X1_MODE BIT(0) -#define PCIE_CTRL_RC_MODE BIT(1) -#define PCIE_STAT_OFF 0x1a04 -#define PCIE_STAT_BUS (0xff << 8) -#define PCIE_STAT_DEV (0x1f << 16) -#define PCIE_STAT_LINK_DOWN BIT(0) -#define PCIE_DEBUG_CTRL 0x1a60 -#define PCIE_DEBUG_SOFT_RESET BIT(20) +#define MVPCIE_ROOT_PORT_PCI_CFG_OFF 0x0000 +#define MVPCIE_ROOT_PORT_PCI_EXP_OFF 0x0060 +#define MVPCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) +#define MVPCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) +#define MVPCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4)) +#define MVPCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) +#define MVPCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4)) +#define MVPCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4)) +#define MVPCIE_WIN5_CTRL_OFF 0x1880 +#define MVPCIE_WIN5_BASE_OFF 0x1884 +#define MVPCIE_WIN5_REMAP_OFF 0x188c +#define MVPCIE_CONF_ADDR_OFF 0x18f8 +#define MVPCIE_CONF_DATA_OFF 0x18fc +#define MVPCIE_CTRL_OFF 0x1a00 +#define MVPCIE_CTRL_RC_MODE BIT(1) +#define MVPCIE_STAT_OFF 0x1a04 +#define MVPCIE_STAT_BUS (0xff << 8) +#define MVPCIE_STAT_DEV (0x1f << 16) +#define MVPCIE_STAT_LINK_DOWN BIT(0) #define LINK_WAIT_RETRIES 100 #define LINK_WAIT_TIMEOUT 1000 @@ -87,8 +77,8 @@ struct mvebu_pcie { static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie) { u32 val; - val = readl(pcie->base + PCIE_STAT_OFF); - return !(val & PCIE_STAT_LINK_DOWN); + val = readl(pcie->base + MVPCIE_STAT_OFF); + return !(val & MVPCIE_STAT_LINK_DOWN); } static void mvebu_pcie_wait_for_link(struct mvebu_pcie *pcie) @@ -112,20 +102,20 @@ static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int busno) { u32 stat; - stat = readl(pcie->base + PCIE_STAT_OFF); - stat &= ~PCIE_STAT_BUS; + stat = readl(pcie->base + MVPCIE_STAT_OFF); + stat &= ~MVPCIE_STAT_BUS; stat |= busno << 8; - writel(stat, pcie->base + PCIE_STAT_OFF); + writel(stat, pcie->base + MVPCIE_STAT_OFF); } static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno) { u32 stat; - stat = readl(pcie->base + PCIE_STAT_OFF); - stat &= ~PCIE_STAT_DEV; + stat = readl(pcie->base + MVPCIE_STAT_OFF); + stat &= ~MVPCIE_STAT_DEV; stat |= devno << 16; - writel(stat, pcie->base + PCIE_STAT_OFF); + writel(stat, pcie->base + MVPCIE_STAT_OFF); } static inline struct mvebu_pcie *hose_to_pcie(struct pci_controller *hose) @@ -195,18 +185,18 @@ static int mvebu_pcie_read_config(const struct udevice *bus, pci_dev_t bdf, addr = PCI_CONF1_EXT_ADDRESS(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset); /* write address */ - writel(addr, pcie->base + PCIE_CONF_ADDR_OFF); + writel(addr, pcie->base + MVPCIE_CONF_ADDR_OFF); /* read data */ switch (size) { case PCI_SIZE_8: - data = readb(pcie->base + PCIE_CONF_DATA_OFF + (offset & 3)); + data = readb(pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 3)); break; case PCI_SIZE_16: - data = readw(pcie->base + PCIE_CONF_DATA_OFF + (offset & 2)); + data = readw(pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 2)); break; case PCI_SIZE_32: - data = readl(pcie->base + PCIE_CONF_DATA_OFF); + data = readl(pcie->base + MVPCIE_CONF_DATA_OFF); break; default: return -EINVAL; @@ -286,18 +276,18 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf, addr = PCI_CONF1_EXT_ADDRESS(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset); /* write address */ - writel(addr, pcie->base + PCIE_CONF_ADDR_OFF); + writel(addr, pcie->base + MVPCIE_CONF_ADDR_OFF); /* write data */ switch (size) { case PCI_SIZE_8: - writeb(value, pcie->base + PCIE_CONF_DATA_OFF + (offset & 3)); + writeb(value, pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 3)); break; case PCI_SIZE_16: - writew(value, pcie->base + PCIE_CONF_DATA_OFF + (offset & 2)); + writew(value, pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 2)); break; case PCI_SIZE_32: - writel(value, pcie->base + PCIE_CONF_DATA_OFF); + writel(value, pcie->base + MVPCIE_CONF_DATA_OFF); break; default: return -EINVAL; @@ -321,20 +311,20 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie) /* First, disable and clear BARs and windows. */ for (i = 1; i < 3; i++) { - writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i)); - writel(0, pcie->base + PCIE_BAR_LO_OFF(i)); - writel(0, pcie->base + PCIE_BAR_HI_OFF(i)); + writel(0, pcie->base + MVPCIE_BAR_CTRL_OFF(i)); + writel(0, pcie->base + MVPCIE_BAR_LO_OFF(i)); + writel(0, pcie->base + MVPCIE_BAR_HI_OFF(i)); } for (i = 0; i < 5; i++) { - writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i)); - writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i)); - writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); + writel(0, pcie->base + MVPCIE_WIN04_CTRL_OFF(i)); + writel(0, pcie->base + MVPCIE_WIN04_BASE_OFF(i)); + writel(0, pcie->base + MVPCIE_WIN04_REMAP_OFF(i)); } - writel(0, pcie->base + PCIE_WIN5_CTRL_OFF); - writel(0, pcie->base + PCIE_WIN5_BASE_OFF); - writel(0, pcie->base + PCIE_WIN5_REMAP_OFF); + writel(0, pcie->base + MVPCIE_WIN5_CTRL_OFF); + writel(0, pcie->base + MVPCIE_WIN5_BASE_OFF); + writel(0, pcie->base + MVPCIE_WIN5_REMAP_OFF); /* Setup windows for DDR banks. Count total DDR size on the fly. */ size = 0; @@ -342,12 +332,12 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie) const struct mbus_dram_window *cs = dram->cs + i; writel(cs->base & 0xffff0000, - pcie->base + PCIE_WIN04_BASE_OFF(i)); - writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); + pcie->base + MVPCIE_WIN04_BASE_OFF(i)); + writel(0, pcie->base + MVPCIE_WIN04_REMAP_OFF(i)); writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) | (dram->mbus_dram_target_id << 4) | 1, - pcie->base + PCIE_WIN04_CTRL_OFF(i)); + pcie->base + MVPCIE_WIN04_CTRL_OFF(i)); size += cs->size; } @@ -357,14 +347,14 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie) size = 1 << fls(size); /* Setup BAR[1] to all DRAM banks. */ - writel(dram->cs[0].base | 0xc, pcie->base + PCIE_BAR_LO_OFF(1)); - writel(0, pcie->base + PCIE_BAR_HI_OFF(1)); + writel(dram->cs[0].base | 0xc, pcie->base + MVPCIE_BAR_LO_OFF(1)); + writel(0, pcie->base + MVPCIE_BAR_HI_OFF(1)); writel(((size - 1) & 0xffff0000) | 0x1, - pcie->base + PCIE_BAR_CTRL_OFF(1)); + pcie->base + MVPCIE_BAR_CTRL_OFF(1)); /* Setup BAR[0] to internal registers. */ - writel(pcie->intregs, pcie->base + PCIE_BAR_LO_OFF(0)); - writel(0, pcie->base + PCIE_BAR_HI_OFF(0)); + writel(pcie->intregs, pcie->base + MVPCIE_BAR_LO_OFF(0)); + writel(0, pcie->base + MVPCIE_BAR_HI_OFF(0)); } /* Only enable PCIe link, do not setup it */ @@ -403,9 +393,9 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie) u32 reg; /* Setup PCIe controller to Root Complex mode */ - reg = readl(pcie->base + PCIE_CTRL_OFF); - reg |= PCIE_CTRL_RC_MODE; - writel(reg, pcie->base + PCIE_CTRL_OFF); + reg = readl(pcie->base + MVPCIE_CTRL_OFF); + reg |= MVPCIE_CTRL_RC_MODE; + writel(reg, pcie->base + MVPCIE_CTRL_OFF); /* * Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link @@ -414,10 +404,10 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie) * be set to number of SerDes PCIe lanes (1 or 4). If this register is * not set correctly then link with endpoint card is not established. */ - reg = readl(pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP); + reg = readl(pcie->base + MVPCIE_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_LNKCAP); reg &= ~PCI_EXP_LNKCAP_MLW; reg |= (pcie->is_x4 ? 4 : 1) << 4; - writel(reg, pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP); + writel(reg, pcie->base + MVPCIE_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_LNKCAP); } static int mvebu_pcie_probe(struct udevice *dev) @@ -440,7 +430,7 @@ static int mvebu_pcie_probe(struct udevice *dev) * have the same format in Marvell's specification as in PCIe * specification, but their meaning is totally different and they do * different things: they are aliased into internal mvebu registers - * (e.g. PCIE_BAR_LO_OFF) and these should not be changed or + * (e.g. MVPCIE_BAR_LO_OFF) and these should not be changed or * reconfigured by pci device drivers. * * So our driver converts Type 0 config space to Type 1 and reports @@ -448,10 +438,10 @@ static int mvebu_pcie_probe(struct udevice *dev) * Type 1 registers is redirected to the virtual cfgcache[] buffer, * which avoids changing unrelated registers. */ - reg = readl(pcie->base + PCIE_DEV_REV_OFF); + reg = readl(pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION); reg &= ~0xffffff00; reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8; - writel(reg, pcie->base + PCIE_DEV_REV_OFF); + writel(reg, pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION); /* * mvebu uses local bus number and local device number to determinate From 7f59ed68728e732062f4fb0c1e8940f5bf550ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 18 Feb 2022 17:46:25 +0100 Subject: [PATCH 27/78] arm: mvebu: turris_omnia: Enable ext4 write support in defconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable ext4 write support in Turris Omnia's defconfig. Some users find it useful. Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- configs/turris_omnia_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index 280dd55f00..5b1fdbfb2d 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -93,3 +93,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_WDT=y CONFIG_WDT_ORION=y +CONFIG_EXT4_WRITE=y From 1fd54253bca7d43d046bba4853fe5fafd034bc17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 23 Feb 2022 13:52:32 +0100 Subject: [PATCH 28/78] arm: a37xx: pci: Fix a3700_fdt_fix_pcie_regions() function again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The a3700_fdt_fix_pcie_regions() function still computes nonsense. It computes the fixup offset from the PCI address taken from the first row of the "ranges" array, which means that: - PCI address must equal CPU address (otherwise the computed fix offset will be wrong), - the first row must contain the lowest address. This is the case for the default device-tree, which is why we didn't notice it. It also adds the fixup offset to all PCI and CPU addresses, which is wrong. Instead: 1) The fixup offset must be computed from the CPU address, not PCI address. 2) The fixup offset must be computed from the row containing the lowest CPU address, which is not necessarily contained in the first row. 3) The PCI address - the address to which the PCIe controller remaps the address space as seen from the point of view of the PCIe device - must be fixed by the fix offset in the same way as the CPU address only in the special case when the CPU adn PCI addresses are the same. Same addresses means that remapping is disabled, and thus if we change the CPU address, we need also to change the PCI address so that the remapping is still disabled afterwards. Consider an example: The ranges entries contain: PCI address CPU address 70000000 EA000000 E9000000 E9000000 EB000000 EB000000 By default CPU PCIe window is at: E8000000 - F0000000 Consider the case when TF-A moves it to: F2000000 - FA000000 Until now the function would take the PCI address of the first entry: 70000000, and the new base, F2000000, to compute the fix offset: F2000000 - 70000000 = 82000000, and then add 8200000 to all addresses, resulting in PCI address CPU address F2000000 6C000000 6B000000 6B000000 6D000000 6D000000 which is complete nonsense - none of the CPU addresses is in the requested window. Now it will take the lowest CPU address, which is in second row, E9000000, and compute the fix offset F2000000 - E9000000 = 09000000, and then add it to all CPU addresses and those PCI addresses which equal to their corresponding CPU addresses, resulting in PCI address CPU address 70000000 F3000000 F2000000 F2000000 F4000000 F4000000 where all of the CPU addresses are in the needed window. Fixes: 4a82fca8e330 ("arm: a37xx: pci: Fix a3700_fdt_fix_pcie_regions() function") Signed-off-by: Pali Rohár Signed-off-by: Marek Behún Reviewed-by: Stefan Roese --- arch/arm/mach-mvebu/armada3700/cpu.c | 81 +++++++++++++++++++--------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c index 23492f49da..52b5109b73 100644 --- a/arch/arm/mach-mvebu/armada3700/cpu.c +++ b/arch/arm/mach-mvebu/armada3700/cpu.c @@ -316,8 +316,8 @@ static int fdt_setprop_inplace_u32_partial(void *blob, int node, int a3700_fdt_fix_pcie_regions(void *blob) { - int acells, pacells, scells; - u32 base, fix_offset; + u32 base, lowest_cpu_addr, fix_offset; + int pci_cells, cpu_cells, size_cells; const u32 *ranges; int node, pnode; int ret, i, len; @@ -331,51 +331,80 @@ int a3700_fdt_fix_pcie_regions(void *blob) return node; ranges = fdt_getprop(blob, node, "ranges", &len); - if (!ranges || len % sizeof(u32)) - return -ENOENT; + if (!ranges || !len || len % sizeof(u32)) + return -EINVAL; /* * The "ranges" property is an array of - * { } + * { } + * where number of PCI address cells and size cells is stored in the + * "#address-cells" and "#size-cells" properties of the same node + * containing the "ranges" property and number of CPU address cells + * is stored in the parent's "#address-cells" property. * - * All 3 elements can span a diffent number of cells. Fetch their sizes. + * All 3 elements can span a diffent number of cells. Fetch them. */ pnode = fdt_parent_offset(blob, node); - acells = fdt_address_cells(blob, node); - pacells = fdt_address_cells(blob, pnode); - scells = fdt_size_cells(blob, node); + pci_cells = fdt_address_cells(blob, node); + cpu_cells = fdt_address_cells(blob, pnode); + size_cells = fdt_size_cells(blob, node); - /* Child PCI addresses always use 3 cells */ - if (acells != 3) - return -ENOENT; + /* PCI addresses always use 3 cells */ + if (pci_cells != 3) + return -EINVAL; - /* Calculate fixup offset from first child address (in last cell) */ - fix_offset = base - fdt32_to_cpu(ranges[2]); + /* CPU addresses on Armada 37xx always use 2 cells */ + if (cpu_cells != 2) + return -EINVAL; - /* If fixup offset is zero then there is nothing to fix */ + for (i = 0; i < len / sizeof(u32); + i += pci_cells + cpu_cells + size_cells) { + /* + * Parent CPU addresses on Armada 37xx are always 32-bit, so + * check that the high word is zero. + */ + if (fdt32_to_cpu(ranges[i + pci_cells])) + return -EINVAL; + + if (i == 0 || + fdt32_to_cpu(ranges[i + pci_cells + 1]) < lowest_cpu_addr) + lowest_cpu_addr = fdt32_to_cpu(ranges[i + pci_cells + 1]); + } + + /* Calculate fixup offset from the lowest (first) CPU address */ + fix_offset = base - lowest_cpu_addr; + + /* If fixup offset is zero there is nothing to fix */ if (!fix_offset) return 0; /* - * Fix address (last cell) of each child address and each parent - * address + * Fix each CPU address and corresponding PCI address if PCI address + * is not already remapped (has the same value) */ - for (i = 0; i < len / sizeof(u32); i += acells + pacells + scells) { + for (i = 0; i < len / sizeof(u32); + i += pci_cells + cpu_cells + size_cells) { + u32 cpu_addr; + u64 pci_addr; int idx; - /* fix child address */ - idx = i + acells - 1; + /* Fix CPU address */ + idx = i + pci_cells + cpu_cells - 1; + cpu_addr = fdt32_to_cpu(ranges[idx]); ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx, - fdt32_to_cpu(ranges[idx]) + - fix_offset); + cpu_addr + fix_offset); if (ret) return ret; - /* fix parent address */ - idx = i + acells + pacells - 1; + /* Fix PCI address only if it isn't remapped (is same as CPU) */ + idx = i + pci_cells - 1; + pci_addr = ((u64)fdt32_to_cpu(ranges[idx - 1]) << 32) | + fdt32_to_cpu(ranges[idx]); + if (cpu_addr != pci_addr) + continue; + ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx, - fdt32_to_cpu(ranges[idx]) + - fix_offset); + cpu_addr + fix_offset); if (ret) return ret; } From 2454de2c34531941756d259771fd0266ea2d5d0b Mon Sep 17 00:00:00 2001 From: Francois Berder Date: Mon, 28 Feb 2022 10:31:45 +0100 Subject: [PATCH 29/78] drivers: rtc: fix null pointer access in armada38x_rtc_reset Replace null pointer by pointer to device registers when calling armada38x_rtc_write. Signed-off-by: Francois Berder Reviewed-by: Stefan Roese --- drivers/rtc/armada38x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/armada38x.c b/drivers/rtc/armada38x.c index 2d264acf77..2af64e3912 100644 --- a/drivers/rtc/armada38x.c +++ b/drivers/rtc/armada38x.c @@ -121,7 +121,7 @@ static int armada38x_rtc_reset(struct udevice *dev) armada38x_rtc_write(0, rtc, RTC_CONF_TEST); mdelay(500); armada38x_rtc_write(0, rtc, RTC_TIME); - armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS); + armada38x_rtc_write(BIT(0) | BIT(1), rtc, RTC_STATUS); } return 0; From 87724d5c905be4fb5eeed0e31384664721db4098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 28 Feb 2022 15:59:37 +0100 Subject: [PATCH 30/78] arm64: a37xx: pinctrl: Fix PWM pins indexes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 5534fb4f4833 ("arm64: a37xx: pinctrl: Correct PWM pins definitions") introduced bogus definitions os PWM pins: all 4 pins have index 11, instead of having indexes 11, 12, 13, 14. Fix this. Signed-off-by: Marek Behún Reviewed-by: Pali Rohár Reviewed-by: Stefan Roese --- drivers/pinctrl/mvebu/pinctrl-armada-37xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c index 1cf1f06f10..e76ef153e6 100644 --- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c +++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c @@ -162,11 +162,11 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = { PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"), PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3), "pwm", "led"), - PIN_GRP_GPIO_3("pwm1", 11, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4), + PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4), "pwm", "led"), - PIN_GRP_GPIO_3("pwm2", 11, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5), + PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5), "pwm", "led"), - PIN_GRP_GPIO_3("pwm3", 11, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6), + PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6), "pwm", "led"), PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"), PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"), From 0a6f0297c677946907b7ba34d34995fe03055aad Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Tue, 1 Mar 2022 13:53:23 +1300 Subject: [PATCH 31/78] ARM: mvebu: x530: clearfog: Add ODT configuration Commit 369e532691e0 ("ddr: marvell: a38x: allow board specific ODT configuration") added the odt_config member to struct mv_ddr_topology_map ahead of the clk_enable and ck_delay members. This means that any boards that configured either of clk_enable or ck_delay needed to have their board topology updated. This affects the x530 and clearfog boards. Other A38x boards don't touch any of the trailing members of mv_ddr_topology_map so don't need updating. Fixes: 369e532691e0 ("ddr: marvell: a38x: allow board specific ODT configuration") Signed-off-by: Chris Packham Acked-by: Baruch Siach Reviewed-by: Stefan Roese --- board/alliedtelesis/x530/x530.c | 1 + board/solidrun/clearfog/clearfog.c | 1 + 2 files changed, 2 insertions(+) diff --git a/board/alliedtelesis/x530/x530.c b/board/alliedtelesis/x530/x530.c index 8b31045a07..c0ec2afa30 100644 --- a/board/alliedtelesis/x530/x530.c +++ b/board/alliedtelesis/x530/x530.c @@ -73,6 +73,7 @@ static struct mv_ddr_topology_map board_topology_map = { {0}, /* timing parameters */ { {0} }, /* electrical configuration */ {0}, /* electrical parameters */ + 0, /* ODT configuration */ 0, /* Clock enable mask */ 160 /* Clock delay */ }; diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index c920cf8d6b..03adb591d8 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -147,6 +147,7 @@ static struct mv_ddr_topology_map board_topology_map = { {0}, /* timing parameters */ { {0} }, /* electrical configuration */ {0,}, /* electrical parameters */ + 0, /* ODT configuration */ 0x3, /* clock enable mask */ }; From d8865f8677c6dd43109e22bfbb85a3cd6bf6aca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:18 +0100 Subject: [PATCH 32/78] tools: kwboot: Check for return value of kwboot_tty_send() and tcflush() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Failure of kwboot_tty_send() and tcflush() functions is fatal, it does not make sense to continue. So return error back to the caller like in other places where are called these functions. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 2d2d545d82..5a7c53ce89 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -740,10 +740,8 @@ kwboot_bootmsg(int tty, void *msg) for (count = 0; count < 128; count++) { rc = kwboot_tty_send(tty, msg, 8, 0); - if (rc) { - usleep(msg_req_delay * 1000); - continue; - } + if (rc) + break; } rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); @@ -772,11 +770,19 @@ kwboot_bootmsg(int tty, void *msg) */ /* flush output queue with remaining boot message patterns */ - tcflush(tty, TCOFLUSH); + rc = tcflush(tty, TCOFLUSH); + if (rc) { + perror("Failed to flush output queue"); + return rc; + } /* send one xmodem packet with 0xff bytes to force BootROM to re-sync */ memset(&block, 0xff, sizeof(block)); - kwboot_tty_send(tty, &block, sizeof(block), 0); + rc = kwboot_tty_send(tty, &block, sizeof(block), 0); + if (rc) { + perror("Failed to send sync sequence"); + return rc; + } /* * Sending 132 bytes via 115200B/8-N-1 takes 11.45 ms, reading 132 bytes @@ -785,7 +791,11 @@ kwboot_bootmsg(int tty, void *msg) usleep(30 * 1000); /* flush remaining NAK replies from input queue */ - tcflush(tty, TCIFLUSH); + rc = tcflush(tty, TCIFLUSH); + if (rc) { + perror("Failed to flush input queue"); + return rc; + } return 0; } @@ -805,10 +815,8 @@ kwboot_debugmsg(int tty, void *msg) break; rc = kwboot_tty_send(tty, msg, 8, 0); - if (rc) { - usleep(msg_req_delay * 1000); - continue; - } + if (rc) + break; rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo); From 132016e2706affdd9e150c4e34fd2d1f5bd05749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:19 +0100 Subject: [PATCH 33/78] tools: kwboot: Remove msg_req_delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variable msg_req_delay is set but never used. So completely remove it. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 5a7c53ce89..4dfb1038b4 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -48,11 +48,9 @@ static unsigned char kwboot_msg_debug[] = { }; /* Defines known to work on Kirkwood */ -#define KWBOOT_MSG_REQ_DELAY 10 /* ms */ #define KWBOOT_MSG_RSP_TIMEO 50 /* ms */ /* Defines known to work on Armada XP */ -#define KWBOOT_MSG_REQ_DELAY_AXP 1000 /* ms */ #define KWBOOT_MSG_RSP_TIMEO_AXP 1000 /* ms */ /* @@ -285,7 +283,6 @@ static const char kwb_baud_magic[16] = "$baudratechange"; static int kwboot_verbose; -static int msg_req_delay = KWBOOT_MSG_REQ_DELAY; static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO; static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO; @@ -1725,7 +1722,6 @@ kwboot_usage(FILE *stream, char *progname) " -D : boot without preamble (Dove)\n"); fprintf(stream, " -d: enter debug mode\n"); fprintf(stream, " -a: use timings for Armada XP\n"); - fprintf(stream, " -q : use specific request-delay\n"); fprintf(stream, " -s : use specific response-timeout\n"); fprintf(stream, " -o : use specific xmodem block timeout\n"); @@ -1804,12 +1800,11 @@ main(int argc, char **argv) break; case 'a': - msg_req_delay = KWBOOT_MSG_REQ_DELAY_AXP; msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO_AXP; break; case 'q': - msg_req_delay = atoi(optarg); + /* nop, for backward compatibility */ break; case 's': From c1d911f15f81a09126f52fac3e78e2eb6cfd224b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:20 +0100 Subject: [PATCH 34/78] tools: kwboot: Cleanup bootmsg and debugmsg variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function kwboot_debugmsg() is always called with kwboot_msg_debug as msg and function kwboot_bootmsg() with kwboot_msg_debug as msg. Function kwboot_bootmsg() is never called with NULL msg. Simplify, cleanup and remove dead code. No functional change. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 4dfb1038b4..4e2acb5245 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -718,17 +718,14 @@ out: } static int -kwboot_bootmsg(int tty, void *msg) +kwboot_bootmsg(int tty) { struct kwboot_block block; int rc; char c; int count; - if (msg == NULL) - kwboot_printv("Please reboot the target into UART boot mode..."); - else - kwboot_printv("Sending boot message. Please reboot the target..."); + kwboot_printv("Sending boot message. Please reboot the target..."); do { rc = tcflush(tty, TCIOFLUSH); @@ -736,7 +733,7 @@ kwboot_bootmsg(int tty, void *msg) break; for (count = 0; count < 128; count++) { - rc = kwboot_tty_send(tty, msg, 8, 0); + rc = kwboot_tty_send(tty, kwboot_msg_boot, sizeof(kwboot_msg_boot), 0); if (rc) break; } @@ -798,7 +795,7 @@ kwboot_bootmsg(int tty, void *msg) } static int -kwboot_debugmsg(int tty, void *msg) +kwboot_debugmsg(int tty) { int rc; @@ -811,7 +808,7 @@ kwboot_debugmsg(int tty, void *msg) if (rc) break; - rc = kwboot_tty_send(tty, msg, 8, 0); + rc = kwboot_tty_send(tty, kwboot_msg_debug, sizeof(kwboot_msg_debug), 0); if (rc) break; @@ -1737,8 +1734,8 @@ main(int argc, char **argv) { const char *ttypath, *imgpath; int rv, rc, tty, term; - void *bootmsg; - void *debugmsg; + int bootmsg; + int debugmsg; void *img; size_t size; size_t after_img_rsv; @@ -1748,8 +1745,8 @@ main(int argc, char **argv) rv = 1; tty = -1; - bootmsg = NULL; - debugmsg = NULL; + bootmsg = 0; + debugmsg = 0; imgpath = NULL; img = NULL; term = 0; @@ -1771,7 +1768,7 @@ main(int argc, char **argv) case 'b': if (imgpath || bootmsg || debugmsg) goto usage; - bootmsg = kwboot_msg_boot; + bootmsg = 1; if (prev_optind == optind) goto usage; if (optind < argc - 1 && argv[optind] && argv[optind][0] != '-') @@ -1781,14 +1778,14 @@ main(int argc, char **argv) case 'D': if (imgpath || bootmsg || debugmsg) goto usage; - bootmsg = NULL; + bootmsg = 0; imgpath = optarg; break; case 'd': if (imgpath || bootmsg || debugmsg) goto usage; - debugmsg = kwboot_msg_debug; + debugmsg = 1; break; case 'p': @@ -1869,13 +1866,13 @@ main(int argc, char **argv) } if (debugmsg) { - rc = kwboot_debugmsg(tty, debugmsg); + rc = kwboot_debugmsg(tty); if (rc) { perror("debugmsg"); goto out; } } else if (bootmsg) { - rc = kwboot_bootmsg(tty, bootmsg); + rc = kwboot_bootmsg(tty); if (rc) { perror("bootmsg"); goto out; From 913866af6c97c37bbdb8165c32d8046b8ec2c5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:21 +0100 Subject: [PATCH 35/78] tools: kwboot: Use separate thread for sending boot message pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After BootROM successfully detects boot message pattern on UART it waits until host stop sending data on UART. For example Armada 385 BootROM requires that host does not send anything on UART at least 24 ms. If host is still sending something then BootROM waits (possibly infinitely). BootROM successfully detects boot message pattern if it receives it in small period of time after power on. So to ensure that host put BootROM into UART boot mode, host must send continuous stream of boot message pattern with a small gap (for A385 at least 24 ms) after series of pattern. But this gap cannot be too often or too long to ensure that it does not cover whole BootROM time window when it is detecting for boot message pattern. Therefore it is needed to do following steps in cycle without any delay: 1. send series of boot message pattern over UART 2. wait until kernel transmit all data 3. sleep small period of time At the same time, host needs to monitor input queue, data received on the UART and checking if it contains NAK byte by which BootROM informs that xmodem transfer is ready. But it is not possible to wait until kernel transmit all data on UART and at the same time in the one process to also wait for input data. This is limitation of POSIX tty API and also by linux kernel that it does not provide asynchronous function for waiting until all data are transmitted. There is only synchronous variant tcdrain(). So to correctly implement this handshake on systems with linux kernel, it is needed to use tcdrain() in separate thread. Implement sending of boot message pattern in one thread and reading of reply in the main thread. Use pthread library for threads. This change makes UART booting on Armada 385 more reliable. It is possible to start kwboot and power on board after minute and kwboot correctly put board into UART boot mode. Old implementation without separate thread has an issue that it read just one byte from UART input queue and then it send 128 message pattern to the output queue. If some noise was on UART then kwboot was not able to read BootROM response as its input queue was just overflowed and kwboot was sending more data than receiving. This change basically fixed above issue too. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/Makefile | 3 ++ tools/kwboot.c | 122 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index 5409ff2879..f8fb9fe09e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -196,6 +196,9 @@ hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl HOSTCFLAGS_mkexynosspl.o := -pedantic +HOSTCFLAGS_kwboot.o += -pthread +HOSTLDLIBS_kwboot += -pthread + ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o hostprogs-$(CONFIG_X86) += ifdtool diff --git a/tools/kwboot.c b/tools/kwboot.c index 4e2acb5245..9fd90b9bec 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef __linux__ #include "termios_linux.h" @@ -717,37 +718,120 @@ out: return rc; } +static void * +kwboot_msg_write_handler(void *arg) +{ + int tty = *(int *)((void **)arg)[0]; + const void *msg = ((void **)arg)[1]; + int rsp_timeo = msg_rsp_timeo; + int i, dummy_oldtype; + + /* allow to cancel this thread at any time */ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy_oldtype); + + while (1) { + /* write 128 samples of message pattern into the output queue without waiting */ + for (i = 0; i < 128; i++) { + if (kwboot_tty_send(tty, msg, 8, 1) < 0) { + perror("\nFailed to send message pattern"); + exit(1); + } + } + /* wait until output queue is transmitted and then make pause */ + if (tcdrain(tty) < 0) { + perror("\nFailed to send message pattern"); + exit(1); + } + /* BootROM requires pause on UART after it detects message pattern */ + usleep(rsp_timeo * 1000); + } +} + +static int +kwboot_msg_start_thread(pthread_t *thread, int *tty, void *msg) +{ + void *arg[2]; + int rc; + + arg[0] = tty; + arg[1] = msg; + rc = pthread_create(thread, NULL, kwboot_msg_write_handler, arg); + if (rc) { + errno = rc; + return -1; + } + + return 0; +} + +static int +kwboot_msg_stop_thread(pthread_t thread) +{ + int rc; + + rc = pthread_cancel(thread); + if (rc) { + errno = rc; + return -1; + } + + rc = pthread_join(thread, NULL); + if (rc) { + errno = rc; + return -1; + } + + return 0; +} + static int kwboot_bootmsg(int tty) { struct kwboot_block block; - int rc; + pthread_t write_thread; + int rc, err; char c; - int count; + + /* flush input and output queue */ + tcflush(tty, TCIOFLUSH); + + rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_boot); + if (rc) { + perror("Failed to start write thread"); + return rc; + } kwboot_printv("Sending boot message. Please reboot the target..."); - do { - rc = tcflush(tty, TCIOFLUSH); - if (rc) - break; - - for (count = 0; count < 128; count++) { - rc = kwboot_tty_send(tty, kwboot_msg_boot, sizeof(kwboot_msg_boot), 0); - if (rc) - break; - } - - rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); - + err = 0; + while (1) { kwboot_spinner(); - } while (rc || c != NAK); + rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo); + if (rc && errno == ETIMEDOUT) { + continue; + } else if (rc) { + err = errno; + break; + } + + if (c == NAK) + break; + } kwboot_printv("\n"); - if (rc) + rc = kwboot_msg_stop_thread(write_thread); + if (rc) { + perror("Failed to stop write thread"); return rc; + } + + if (err) { + errno = err; + perror("Failed to read response for boot message pattern"); + return -1; + } /* * At this stage we have sent more boot message patterns and BootROM @@ -1873,10 +1957,8 @@ main(int argc, char **argv) } } else if (bootmsg) { rc = kwboot_bootmsg(tty); - if (rc) { - perror("bootmsg"); + if (rc) goto out; - } } if (img) { From 93976af58926626077eca8b7bbd1aa592649ec01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:22 +0100 Subject: [PATCH 36/78] tools: kwboot: Fix sending and processing debug message pattern (-d option) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -d option is currently broken. In most cases BootROM does not detect this message pattern. For sending debug message pattern it is needed to do same steps as for boot message pattern. Implement sending debug message pattern via same separate thread like it is for boot message pattern. Checking if BootROM entered into UART debug mode is different than detecting UART boot mode. When in boot mode, BootROM sends xmodem NAK bytes. When in debug mode, BootROM activates console echo and reply back every written byte (extept \r\n which is interpreted as executing command and \b which is interpreting as removing the last sent byte). So in kwboot, check that BootROM send back at least 4 debug message patterns as a echo reply for debug message patterns which kwboot is sending in the loop. Then there is another observation, if host writes too many bytes (as command) then BootROM command line buffer may overflow after trying to execute such long command. To workaround this overflow, it is enough to remove bytes from the input line buffer by sending 3 \b bytes for every sent character. So do it. With this change, it is possbile to enter into the UART debug mode with kwboot -d option. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 141 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 124 insertions(+), 17 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 9fd90b9bec..3ab49e74bb 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -881,30 +881,139 @@ kwboot_bootmsg(int tty) static int kwboot_debugmsg(int tty) { - int rc; + unsigned char buf[8192]; + pthread_t write_thread; + int rc, err, i, pos; + size_t off; + + /* flush input and output queue */ + tcflush(tty, TCIOFLUSH); + + rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_debug); + if (rc) { + perror("Failed to start write thread"); + return rc; + } kwboot_printv("Sending debug message. Please reboot the target..."); + kwboot_spinner(); - do { - char buf[16]; - - rc = tcflush(tty, TCIOFLUSH); - if (rc) + err = 0; + off = 0; + while (1) { + /* Read immediately all bytes in queue without waiting */ + rc = read(tty, buf + off, sizeof(buf) - off); + if ((rc < 0 && errno == EINTR) || rc == 0) { + continue; + } else if (rc < 0) { + err = errno; break; - - rc = kwboot_tty_send(tty, kwboot_msg_debug, sizeof(kwboot_msg_debug), 0); - if (rc) - break; - - rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo); + } + off += rc - 1; kwboot_spinner(); - } while (rc); + /* + * Check if we received at least 4 debug message patterns + * (console echo from BootROM) in cyclic buffer + */ + + for (pos = 0; pos < sizeof(kwboot_msg_debug); pos++) + if (buf[off] == kwboot_msg_debug[(pos + off) % sizeof(kwboot_msg_debug)]) + break; + + for (i = off; i >= 0; i--) + if (buf[i] != kwboot_msg_debug[(pos + i) % sizeof(kwboot_msg_debug)]) + break; + + off -= i; + + if (off >= 4 * sizeof(kwboot_msg_debug)) + break; + + /* If not move valid suffix from end of the buffer to the beginning of buffer */ + memmove(buf, buf + i + 1, off); + } kwboot_printv("\n"); - return rc; + rc = kwboot_msg_stop_thread(write_thread); + if (rc) { + perror("Failed to stop write thread"); + return rc; + } + + if (err) { + errno = err; + perror("Failed to read response for debug message pattern"); + return -1; + } + + /* flush output queue with remaining debug message patterns */ + rc = tcflush(tty, TCOFLUSH); + if (rc) { + perror("Failed to flush output queue"); + return rc; + } + + kwboot_printv("Clearing input buffer...\n"); + + /* + * Wait until BootROM transmit all remaining echo characters. + * Experimentally it was measured that for Armada 385 BootROM + * it is required to wait at least 0.415s. So wait 0.5s. + */ + usleep(500 * 1000); + + /* + * In off variable is stored number of characters received after the + * successful detection of echo reply. So these characters are console + * echo for other following debug message patterns. BootROM may have in + * its output queue other echo characters which were being transmitting + * before above sleep call. So read remaining number of echo characters + * sent by the BootROM now. + */ + while ((rc = kwboot_tty_recv(tty, &buf[0], 1, 0)) == 0) + off++; + if (errno != ETIMEDOUT) { + perror("Failed to read response"); + return rc; + } + + /* + * Clear every echo character set by the BootROM by backspace byte. + * This is required prior writing any command to the BootROM debug + * because BootROM command line buffer has limited size. If length + * of the command is larger than buffer size then it looks like + * that Armada 385 BootROM crashes after sending ENTER. So erase it. + * Experimentally it was measured that for Armada 385 BootROM it is + * required to send at least 3 backspace bytes for one echo character. + * This is unknown why. But lets do it. + */ + off *= 3; + memset(buf, '\x08', sizeof(buf)); + while (off > sizeof(buf)) { + rc = kwboot_tty_send(tty, buf, sizeof(buf), 1); + if (rc) { + perror("Failed to send clear sequence"); + return rc; + } + off -= sizeof(buf); + } + rc = kwboot_tty_send(tty, buf, off, 0); + if (rc) { + perror("Failed to send clear sequence"); + return rc; + } + + usleep(msg_rsp_timeo * 1000); + rc = tcflush(tty, TCIFLUSH); + if (rc) { + perror("Failed to flush input queue"); + return rc; + } + + return 0; } static size_t @@ -1951,10 +2060,8 @@ main(int argc, char **argv) if (debugmsg) { rc = kwboot_debugmsg(tty); - if (rc) { - perror("debugmsg"); + if (rc) goto out; - } } else if (bootmsg) { rc = kwboot_bootmsg(tty); if (rc) From e8d26e8276358fcd1c2fe28293d3b4c82a735731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:23 +0100 Subject: [PATCH 37/78] tools: kwboot: Add support for backspace key in mini terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marvell BootROM recognize only '\b' byte as backspace. Use terminfo for retrieving current backspace sequence and replace any occurrence of backspace sequence by the '\b' byte. Reading terminfo database is possible via tigetstr() function from system library libtinfo.so.*. So link kwboot with -ltinfo. Normally terminfo functions are in system header file. But this header file conflicts with U-Boot "termios_linux.h" header file. So declare terminfo functions manually. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/Makefile | 2 +- tools/kwboot.c | 109 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 97 insertions(+), 14 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index f8fb9fe09e..60231c728c 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -197,7 +197,7 @@ hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl HOSTCFLAGS_mkexynosspl.o := -pedantic HOSTCFLAGS_kwboot.o += -pthread -HOSTLDLIBS_kwboot += -pthread +HOSTLDLIBS_kwboot += -pthread -ltinfo ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o hostprogs-$(CONFIG_X86) += ifdtool diff --git a/tools/kwboot.c b/tools/kwboot.c index 3ab49e74bb..26cfe6dea6 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -36,6 +36,13 @@ #include #endif +/* + * These functions are in header file, but this header file conflicts + * with "termios_linux.h" header file. So declare these functions manually. + */ +extern int setupterm(const char *, int, int *); +extern char *tigetstr(const char *); + /* * Marvell BootROM UART Sensing */ @@ -1376,37 +1383,84 @@ kwboot_xmodem(int tty, const void *_img, size_t size, int baudrate) } static int -kwboot_term_pipe(int in, int out, const char *quit, int *s) +kwboot_term_pipe(int in, int out, const char *quit, int *s, const char *kbs, int *k) { char buf[128]; - ssize_t nin; + ssize_t nin, noff; nin = read(in, buf, sizeof(buf)); if (nin <= 0) return -1; - if (quit) { + noff = 0; + + if (quit || kbs) { int i; for (i = 0; i < nin; i++) { - if (buf[i] == quit[*s]) { + if ((quit || kbs) && + (!quit || buf[i] != quit[*s]) && + (!kbs || buf[i] != kbs[*k])) { + const char *prefix; + int plen; + + if (quit && kbs) { + prefix = (*s >= *k) ? quit : kbs; + plen = (*s >= *k) ? *s : *k; + } else if (quit) { + prefix = quit; + plen = *s; + } else { + prefix = kbs; + plen = *k; + } + + if (plen > i && kwboot_write(out, prefix, plen - i) < 0) + return -1; + } + + if (quit && buf[i] == quit[*s]) { (*s)++; if (!quit[*s]) { nin = (i > *s) ? (i - *s) : 0; break; } - } else { - if (*s > i && kwboot_write(out, quit, *s - i) < 0) - return -1; + } else if (quit) { *s = 0; } + + if (kbs && buf[i] == kbs[*k]) { + (*k)++; + if (!kbs[*k]) { + if (i > *k + noff && + kwboot_write(out, buf + noff, i - *k - noff) < 0) + return -1; + /* + * Replace backspace key by '\b' (0x08) + * byte which is the only recognized + * backspace byte by Marvell BootROM. + */ + if (write(out, "\x08", 1) < 0) + return -1; + noff = i + 1; + *k = 0; + } + } else if (kbs) { + *k = 0; + } } - if (i == nin) - nin -= (nin > *s) ? *s : nin; + if (i == nin) { + i = 0; + if (quit && i < *s) + i = *s; + if (kbs && i < *k) + i = *k; + nin -= (nin > i) ? i : nin; + } } - if (kwboot_write(out, buf, nin) < 0) + if (nin > noff && kwboot_write(out, buf + noff, nin - noff) < 0) return -1; return 0; @@ -1415,7 +1469,8 @@ kwboot_term_pipe(int in, int out, const char *quit, int *s) static int kwboot_terminal(int tty) { - int rc, in, s; + int rc, in, s, k; + const char *kbs = NULL; const char *quit = "\34c"; struct termios otio, tio; @@ -1434,6 +1489,33 @@ kwboot_terminal(int tty) goto out; } + /* + * Get sequence for backspace key used by the current + * terminal. Every occurrence of this sequence will be + * replaced by '\b' byte which is the only recognized + * backspace byte by Marvell BootROM. + * + * Note that we cannot read this sequence from termios + * c_cc[VERASE] as VERASE is valid only when ICANON is + * set in termios c_lflag, which is not case for us. + * + * Also most terminals do not set termios c_cc[VERASE] + * as c_cc[VERASE] can specify only one-byte sequence + * and instead let applications to read (possible + * multi-byte) sequence for backspace key from "kbs" + * terminfo database based on $TERM env variable. + * + * So read "kbs" from terminfo database via tigetstr() + * call after successful setupterm(). Most terminals + * use byte 0x7F for backspace key, so replacement with + * '\b' is required. + */ + if (setupterm(NULL, STDOUT_FILENO, &rc) == 0) { + kbs = tigetstr("kbs"); + if (kbs == (char *)-1) + kbs = NULL; + } + kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n", quit[0] | 0100, quit[1]); } else @@ -1441,6 +1523,7 @@ kwboot_terminal(int tty) rc = 0; s = 0; + k = 0; do { fd_set rfds; @@ -1460,13 +1543,13 @@ kwboot_terminal(int tty) break; if (FD_ISSET(tty, &rfds)) { - rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL); + rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL, NULL, NULL); if (rc) break; } if (in >= 0 && FD_ISSET(in, &rfds)) { - rc = kwboot_term_pipe(in, tty, quit, &s); + rc = kwboot_term_pipe(in, tty, quit, &s, kbs, &k); if (rc) break; } From bdc4dbaefe98890cc7ec7b6aa2d4e85b086527cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:24 +0100 Subject: [PATCH 38/78] tools: kwboot: Update usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add all supported Armada SoCs and document -b and -d options in usage. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 26cfe6dea6..11aca00bf1 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -1986,14 +1986,15 @@ static void kwboot_usage(FILE *stream, char *progname) { fprintf(stream, - "Usage: %s [OPTIONS] [-b | -D ] [-B ] \n", + "Usage: %s [OPTIONS] [-b | -D | -b | -d ] [-B ] [-t] \n", progname); fprintf(stream, "\n"); fprintf(stream, - " -b : boot with preamble (Kirkwood, Armada 370/XP)\n"); + " -b : boot with preamble (Kirkwood, Armada 370/XP/375/38x/39x)\n"); fprintf(stream, " -D : boot without preamble (Dove)\n"); - fprintf(stream, " -d: enter debug mode\n"); + fprintf(stream, " -b: enter xmodem boot mode\n"); + fprintf(stream, " -d: enter console debug mode\n"); fprintf(stream, " -a: use timings for Armada XP\n"); fprintf(stream, " -s : use specific response-timeout\n"); fprintf(stream, From 787fcf5c004d3e4e9fd4b8b6e092bcfe73714cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:25 +0100 Subject: [PATCH 39/78] tools: kwboot: Update manpage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document -D, -b, -d, -q and -s options. Add common examples how to use kwboot. Add information about Armada 38x BootROM bug for debug console mode and how to workaround it. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- doc/kwboot.1 | 103 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/doc/kwboot.1 b/doc/kwboot.1 index acdea891d9..bda049bde5 100644 --- a/doc/kwboot.1 +++ b/doc/kwboot.1 @@ -1,4 +1,4 @@ -.TH KWBOOT 1 "2021-08-25" +.TH KWBOOT 1 "2022-03-02" .SH NAME kwboot \- Boot Marvell Kirkwood (and others 32-bit) SoCs over a serial link. @@ -47,6 +47,48 @@ code in it's header which may also print some output via UART (for example U-Boot SPL does this). In such a case, this output is also written to stdout after the header is sent. +.TP +.B "\-b" +Do only handshake on \fITTY\fP without uploading any file. File upload +could be done later via option \fB\-D\fP or via any other Xmodem +application, like \fBsx\fP(1). + +.TP +.B "\-d" +Do special handshake on \fITTY\fP for console debug mode. + +This will instruct BootROM to enter builtin simple console debug mode. +Should be combined with option \fB\-t\fP. + +To get a BootROM help, type this command followed by ENTER key: + +.RS 1.2i +.TP +.B ? +.RE +.IP + +Armada 38x BootROM has a bug which cause that BootROM's standard output +is turned off on UART when SPI-NOR contains valid boot image. Nevertheless +BootROM's standard input and BootROM's terminal echo are active and working +fine. To workaround this BootROM bug with standard output, it is possible +to manually overwrite BootROM variables stored in SRAM which BootROM use +for checking if standard output is enabled or not. To enable BootROM +standard output on UART, type this command folled by ENTER key: + +.RS 1.2i +.TP +.B w 0x40034100 1 +.RE + +.TP +.BI "\-D" " image" +Upload file \fIimage\fP over \fITTY\fP without initial handshake. + +This method is used primary on Dove platforms, where BootROM does +not support initial handshake for entering UART upload mode and +strapping pins (exported via e.g. buttons) are used instead. + .TP .BI "\-p" Obsolete. Does nothing. @@ -55,13 +97,33 @@ In the past, when this option was used, the program patched the header in the image prior upload, to "UART boot" type. This is now done by default. +.TP +.B "\-q" +Obsolete. Does nothing. + +It is unknown whether it did something in the past. + +.TP +.BI "\-s" " response-timeout" +Specify custom response timeout when doing handshake. Default value is 50 ms. +It is the timeout between sending two consecutive handshake patterns, meaning +how long to wait for response from BootROM. Affects only option \fB\-b\fP with +image file and option \fB\-d\fP. + +Option \fB-a\fP specify response timeout suitable for Armada XP BootROM and +currently it is 1000 ms. + +Some testing showed that specifying 24 ms as response timeout make handshake +with Armada 385 BootROM more stable. + .TP .BI "\-t" Run a terminal program, connecting standard input and output to .RB \fITTY\fP. -If used in combination with \fB-b\fP, terminal mode is entered -immediately following a successful image upload. +If used in combination with \fB\-b\fP, \fB\-D\fP or \fB\-d\fP option, +terminal mode is entered immediately following a successful image upload +or successful handshake (if not doing image upload). If standard I/O streams connect to a console, this mode will terminate after receiving \fBctrl-\e\fP followed by \fBc\fP from console input. @@ -85,9 +147,42 @@ Tested values for \fIbaudrate\fP for Armada 38x include: 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3125000, 4000000 and 5200000. +.SH "EXAMPLES" + +Instruct BootROM to enter boot Xmodem boot mode, send \fIu-boot-spl.kwb\fP +kwbimage file via Xmodem on \fI/dev/ttyUSB0\fP at 115200 Bd and run terminal +program: +.IP +.B kwboot -b u-boot-spl.kwb -t /dev/ttyUSB0 + +.PP +Instruct BootROM to enter boot Xmodem boot mode, send header of +\fIu-boot-spl.kwb\fP kwbimage file via Xmodem at 115200 Bd, then instruct +BootROM to change baudrate to 5200000 Bd, send data part of the kwbimage +file via Xmodem at high speed and finally run terminal program: +.IP +.B kwboot -b u-boot-spl.kwb -B 5200000 -t /dev/ttyUSB0 + +.PP +Only send \fIu-boot-spl.kwb\fP kwbimage file via Xmodem on \fI/dev/ttyUSB0\fP +at 115200 Bd: +.IP +.B kwboot -D u-boot-spl.kwb /dev/ttyUSB0 + +.PP +Instruct BootROM to enter console debug mode and run terminal program on +\fI/dev/ttyUSB0\fP at 115200 Bd: +.IP +.B kwboot -d -t /dev/ttyUSB0 + +.PP +Only run terminal program on \fI/dev/ttyUSB0\fP at 115200 Bd: +.IP +.B kwboot -t /dev/ttyUSB0 + .SH "SEE ALSO" .PP -\fBmkimage\fP(1) +\fBmkimage\fP(1), \fBsx\fP(1) .SH "AUTHORS" From 0b5909d3afaff4fe552cb01de3cb6e537e8bfece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:26 +0100 Subject: [PATCH 40/78] tools: kwboot: Update doc about Avanta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testes proved that current kwboot version supports also Avanta SoCs. It looks like that Avanta SoCs are using same kwbimage format as Armada. Signed-off-by: Pali Rohár Tested-by: Tony Dinh Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- doc/kwboot.1 | 2 +- tools/kwboot.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/kwboot.1 b/doc/kwboot.1 index bda049bde5..f555ff26a2 100644 --- a/doc/kwboot.1 +++ b/doc/kwboot.1 @@ -11,7 +11,7 @@ kwboot \- Boot Marvell Kirkwood (and others 32-bit) SoCs over a serial link. .SH "DESCRIPTION" The \fBkwboot\fP program boots boards based on Marvell's 32-bit -platforms including Kirkwood, Dove, A370, AXP, A375, A38x +platforms including Kirkwood, Dove, Avanta, A370, AXP, A375, A38x and A39x over their integrated UART. Boot image files will typically contain a second stage boot loader, such as U-Boot. The image file must conform to Marvell's BootROM firmware image format diff --git a/tools/kwboot.c b/tools/kwboot.c index 11aca00bf1..cd1879246a 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -1,7 +1,7 @@ /* * Boot a Marvell SoC, with Xmodem over UART0. - * supports Kirkwood, Dove, Armada 370, Armada XP, Armada 375, Armada 38x and - * Armada 39x + * supports Kirkwood, Dove, Avanta, Armada 370, Armada XP, Armada 375, + * Armada 38x and Armada 39x. * * (c) 2012 Daniel Stodden * (c) 2021 Pali Rohár @@ -1990,7 +1990,7 @@ kwboot_usage(FILE *stream, char *progname) progname); fprintf(stream, "\n"); fprintf(stream, - " -b : boot with preamble (Kirkwood, Armada 370/XP/375/38x/39x)\n"); + " -b : boot with preamble (Kirkwood, Avanta, Armada 370/XP/375/38x/39x)\n"); fprintf(stream, " -D : boot without preamble (Dove)\n"); fprintf(stream, " -b: enter xmodem boot mode\n"); From f4fa962fcdbd69589021a096f1af0690fe884279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 2 Mar 2022 11:49:27 +0100 Subject: [PATCH 41/78] tools: kwboot: Update references with public links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Public documents about BootROM of some Marvell SoCs are available in the public Web Archive. Put this information into source code. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese Tested-by: Stefan Roese --- tools/kwboot.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index cd1879246a..69d1be0f48 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -7,9 +7,34 @@ * (c) 2021 Pali Rohár * (c) 2021 Marek Behún * - * References: marvell.com, "88F6180, 88F6190, 88F6192, and 88F6281 - * Integrated Controller: Functional Specifications" December 2, - * 2008. Chapter 24.2 "BootROM Firmware". + * References: + * - "88F6180, 88F6190, 88F6192, and 88F6281: Integrated Controller: Functional + * Specifications" December 2, 2008. Chapter 24.2 "BootROM Firmware". + * https://web.archive.org/web/20130730091033/https://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf + * - "88AP510: High-Performance SoC with Integrated CPU, 2D/3D Graphics + * Processor, and High-Definition Video Decoder: Functional Specifications" + * August 3, 2011. Chapter 5 "BootROM Firmware" + * https://web.archive.org/web/20120130172443/https://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf + * - "88F6710, 88F6707, and 88F6W11: ARMADA(R) 370 SoC: Functional Specifications" + * May 26, 2014. Chapter 6 "BootROM Firmware". + * https://web.archive.org/web/20140617183701/https://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf + * - "MV78230, MV78260, and MV78460: ARMADA(R) XP Family of Highly Integrated + * Multi-Core ARMv7 Based SoC Processors: Functional Specifications" + * May 29, 2014. Chapter 6 "BootROM Firmware". + * https://web.archive.org/web/20180829171131/https://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf + * - "ARMADA(R) 375 Value-Performance Dual Core CPU System on Chip: Functional + * Specifications" Doc. No. MV-S109377-00, Rev. A. September 18, 2013. + * Chapter 7 "Boot Sequence" + * CONFIDENTIAL, no public documentation available + * - "88F6810, 88F6811, 88F6821, 88F6W21, 88F6820, and 88F6828: ARMADA(R) 38x + * Family High-Performance Single/Dual CPU System on Chip: Functional + * Specifications" Doc. No. MV-S109094-00, Rev. C. August 2, 2015. + * Chapter 7 "Boot Flow" + * CONFIDENTIAL, no public documentation available + * - "88F6920, 88F6925 and 88F6928: ARMADA(R) 39x High-Performance Dual Core CPU + * System on Chip Functional Specifications" Doc. No. MV-S109896-00, Rev. B. + * December 22, 2015. Chapter 7 "Boot Flow" + * CONFIDENTIAL, no public documentation available */ #include "kwbimage.h" From 4ff9a8c33c5f2514ee6e66788259399b6626f6b5 Mon Sep 17 00:00:00 2001 From: Romain Naour Date: Thu, 10 Feb 2022 23:13:36 +0100 Subject: [PATCH 42/78] configs: ti: use standard configuration nodes naming Currently, any u-boot bootloader for ti armv7 platforms using DEFAULT_FIT_TI_ARGS to boot with a fitimage (boot_fit = 1) doesn't boot when built with Yocto Poky (openembedded-core). ## Loading kernel from FIT Image at 90000000 ... Could not find configuration node ERROR: can't get kernel image! Arago forked the kernel-fitimage class [1] and altered the configuration nodes naming while adding the OPTEE support by using FITIMAGE_CONF_BY_NAME by default [2]. The "upstream" kernel-fitimage class from openembedded-core still add the "conf-" prefix for each configuration nodes [3]. The ITS file format (from doc/uImage.FIT/source_file_format.txt) is not really accurate with the expected naming of these nodes. But in practice the "conf-" prefix is widely used. When the FIT image support has been added for ti armv7 platforms the naming from Arago has been used [3]. Fix this issue by adding the prefix expected by the ITS file generated by kernel-fitimage class from openembedded-core. [1] http://arago-project.org/git/meta-arago.git?p=meta-arago.git;a=commitdiff;h=719ab1b2098bcdc59c249e3529fa82cb1b9130e6 [2] http://arago-project.org/git/meta-arago.git?p=meta-arago.git;a=commitdiff;h=f23f2876a0cda89241d031bb7ba0b4256ed90035 [3] https://git.openembedded.org/openembedded-core/tree/meta/classes/kernel-fitimage.bbclass?h=yocto-3.1.13#n290 [3] 1e93cc8473e4fe018aececc8ed3bf8fc2b3ff561 Signed-off-by: Romain Naour Cc: Tom Rini Reviewed-by: Denys Dmytriyenko --- include/configs/ti_armv7_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index 9733707009..7483bc821d 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -55,7 +55,7 @@ "do;" \ "setenv overlaystring ${overlaystring}'#'${overlay};" \ "done;\0" \ - "run_fit=bootm ${addr_fit}#${fdtfile}${overlaystring}\0" \ + "run_fit=bootm ${addr_fit}#conf-${fdtfile}${overlaystring}\0" \ /* * DDR information. If the CONFIG_NR_DRAM_BANKS is not defined, From f7fbe547d99729cfa36238ba1629c26589834867 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Tue, 15 Feb 2022 07:47:55 +0100 Subject: [PATCH 43/78] arm: mach-k3: am6_init: Use CONFIG_TI_I2C_BOARD_DETECT We only want to call do_board_detect() if CONFIG_TI_I2C_BOARD_DETECT is set. Same as done for am64. This makes it possible to add a custom am65 based board design to U-Boot that does not use this board detection mechanism. Signed-off-by: Christian Gmeiner --- arch/arm/mach-k3/am6_init.c | 3 ++- board/ti/am65x/evm.c | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c index ffb7aaded2..8a6b1de764 100644 --- a/arch/arm/mach-k3/am6_init.c +++ b/arch/arm/mach-k3/am6_init.c @@ -251,7 +251,8 @@ void board_init_f(ulong dummy) k3_sysfw_print_ver(); /* Perform EEPROM-based board detection */ - do_board_detect(); + if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT)) + do_board_detect(); #if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0) ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(k3_avs), diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index fbe33cbea5..7182a8cad1 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -129,6 +129,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) } #endif +#ifdef CONFIG_TI_I2C_BOARD_DETECT int do_board_detect(void) { int ret; @@ -353,23 +354,26 @@ static int probe_daughtercards(void) return 0; } +#endif int board_late_init(void) { - struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; + if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT)) { + struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA; - setup_board_eeprom_env(); + setup_board_eeprom_env(); - /* - * The first MAC address for ethernet a.k.a. ethernet0 comes from - * efuse populated via the am654 gigabit eth switch subsystem driver. - * All the other ones are populated via EEPROM, hence continue with - * an index of 1. - */ - board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt); + /* + * The first MAC address for ethernet a.k.a. ethernet0 comes from + * efuse populated via the am654 gigabit eth switch subsystem driver. + * All the other ones are populated via EEPROM, hence continue with + * an index of 1. + */ + board_ti_am6_set_ethaddr(1, ep->mac_addr_cnt); - /* Check for and probe any plugged-in daughtercards */ - probe_daughtercards(); + /* Check for and probe any plugged-in daughtercards */ + probe_daughtercards(); + } return 0; } From 4403e1a31cca73d516c2302e2950ddc8ea7d0c37 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Wed, 16 Feb 2022 11:27:24 +0530 Subject: [PATCH 44/78] configs: j721e_*_evm_a72_defconfig: Enable config for setting mmc speed mode Enable config for setting mmc speed mode from U-Boot command line. Signed-off-by: Aswath Govindraju --- configs/j721e_evm_a72_defconfig | 1 + configs/j721e_hs_evm_a72_defconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig index b843a84415..60c96f8961 100644 --- a/configs/j721e_evm_a72_defconfig +++ b/configs/j721e_evm_a72_defconfig @@ -193,3 +193,4 @@ CONFIG_UFS=y CONFIG_CADENCE_UFS=y CONFIG_TI_J721E_UFS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_MMC_SPEED_MODE_SET=y diff --git a/configs/j721e_hs_evm_a72_defconfig b/configs/j721e_hs_evm_a72_defconfig index ae184b0358..6479f9baff 100644 --- a/configs/j721e_hs_evm_a72_defconfig +++ b/configs/j721e_hs_evm_a72_defconfig @@ -162,3 +162,4 @@ CONFIG_UFS=y CONFIG_CADENCE_UFS=y CONFIG_TI_J721E_UFS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_MMC_SPEED_MODE_SET=y From 39834ccdd43f492c61c0d8b4db55988b1f47a4dc Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 16 Feb 2022 09:06:49 +0100 Subject: [PATCH 45/78] arm: dts: iot2050: Add cfg register space for ringacc and udmap Recent unrelated fixes (9876ae7db6da) revealed that we were missing bits from 2af181b53e28 in the IOT2050 dt. Add them, but only for main U-Boot. SPL loads from QSPI only, thus cannot use DMA. Signed-off-by: Jan Kiszka --- .../dts/k3-am65-iot2050-common-u-boot.dtsi | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi index 286e25f379..d80c5501d2 100644 --- a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) Siemens AG, 2018-2021 + * Copyright (c) Siemens AG, 2018-2022 * * Authors: * Le Jin @@ -27,6 +27,29 @@ &cbass_mcu { u-boot,dm-spl; + + mcu_navss: bus@28380000 { + ringacc@2b800000 { + reg = <0x0 0x2b800000 0x0 0x400000>, + <0x0 0x2b000000 0x0 0x400000>, + <0x0 0x28590000 0x0 0x100>, + <0x0 0x2a500000 0x0 0x40000>, + <0x0 0x28440000 0x0 0x40000>; + reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg"; + ti,dma-ring-reset-quirk; + }; + + dma-controller@285c0000 { + reg = <0x0 0x285c0000 0x0 0x100>, + <0x0 0x284c0000 0x0 0x4000>, + <0x0 0x2a800000 0x0 0x40000>, + <0x0 0x284a0000 0x0 0x4000>, + <0x0 0x2aa00000 0x0 0x40000>, + <0x0 0x28400000 0x0 0x2000>; + reg-names = "gcfg", "rchan", "rchanrt", "tchan", + "tchanrt", "rflow"; + }; + }; }; &cbass_wakeup { From 55fd1c442e747338604ef0075a4a888a40399ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Szymanski?= Date: Fri, 25 Feb 2022 14:48:54 +0100 Subject: [PATCH 46/78] cmd: pwm: fix typo 'eisable' -> 'disable' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed misspelled 'disable' in help text. Signed-off-by: Sébastien Szymanski --- cmd/pwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/pwm.c b/cmd/pwm.c index 7947e61aee..7e82955239 100644 --- a/cmd/pwm.c +++ b/cmd/pwm.c @@ -111,5 +111,5 @@ U_BOOT_CMD(pwm, 6, 0, do_pwm, "invert - invert polarity\n" "pwm config - config PWM\n" "pwm enable - enable PWM output\n" - "pwm disable - eisable PWM output\n" + "pwm disable - disable PWM output\n" "Note: All input values are in decimal"); From 5017f9b595da6e5c8f064a43fc6cd42cb62c082a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 1 Mar 2022 08:53:56 +0100 Subject: [PATCH 47/78] mkimage: error handling for FIT image If parameter -F is given but FIT support is missing, a NULL pointer might dereferenced (Coverity CID 350249). If incorrect parameters are given, provide a message and show usage. Signed-off-by: Heinrich Schuchardt --- tools/mkimage.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/mkimage.c b/tools/mkimage.c index 760145119d..74bd072832 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -381,6 +381,11 @@ int main(int argc, char **argv) } if (params.fflag){ + if (!tparams) { + fprintf(stderr, "%s: Missing FIT support\n", + params.cmdname); + exit (EXIT_FAILURE); + } if (tparams->fflag_handle) /* * in some cases, some additional processing needs @@ -391,7 +396,7 @@ int main(int argc, char **argv) retval = tparams->fflag_handle(¶ms); if (retval != EXIT_SUCCESS) - exit (retval); + usage("Bad parameters for FIT image type"); } if (params.lflag || params.fflag) { From 4fa4227cdd14020bb6d588293f3cb8591aeebfa0 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 1 Mar 2022 12:43:32 +0100 Subject: [PATCH 48/78] .mailmap: Record all address for main U-Boot contributor Based on looking at top contributors it was seen that top statistics from top contributors don't include all contributions from different email addresses. That's why I checked all top contributors are checked it. git shortlog -n $START..$END -e -s The patch is adding mapping for Bin Meng, Marek Vasut, Masahiro Yamada, Michal Simek, Tom Rini, Wolfgang Denk. And also use mapping for Stefan Roese and Wolfgang Denk to be properly counted. Signed-off-by: Michal Simek Acked-by: Bin Meng Reviewed-by: Stefan Roese --- .mailmap | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index b36ae66719..36fc1164a2 100644 --- a/.mailmap +++ b/.mailmap @@ -22,6 +22,7 @@ Andreas Bießmann Aneesh V Anup Patel Atish Patra +Bin Meng Boris Brezillon Boris Brezillon Dirk Behme @@ -35,7 +36,15 @@ Jagan Teki Jernej Skrabec Igor Opaniuk Igor Opaniuk +Marek Vasut +Marek Vasut +Marek Vasut Markus Klotzbuecher +Masahiro Yamada +Masahiro Yamada +Michal Simek +Michal Simek +Michal Simek Nicolas Saenz Julienne Patrice Chotard Patrick Delaunay @@ -47,10 +56,19 @@ Ricardo Ribalda Ruchika Gupta Sandeep Paulraj Shaohui Xie -Stefan Roese +Stefan Roese Stefano Babic +Tom Rini TsiChung Liew -Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk +Wolfgang Denk York Sun York Sun Łukasz Majewski From 9b5ad4f5da756939eac4123fc347af533eeb339e Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Tue, 1 Mar 2022 16:12:34 +0100 Subject: [PATCH 49/78] lib: rsa: use actual OpenSSL 1.1.0 EVP MD API Since OpenSSL 1.1.0, EVP_MD_CTX_create() is EVP_MD_CTX_new() EVP_MD_CTX_destroy() is EVP_MD_CTX_free() EVP_MD_CTX_init() is EVP_MD_CTX_reset() As there's no need to reset a newly created EVP_MD_CTX, moreover EVP_DigestSignInit() does the reset, thus call to EVP_MD_CTX_init() can be dropped. As there's no need to reset an EVP_MD_CTX before it's destroyed, as it will be reset by EVP_MD_CTX_free(), call to EVP_MD_CTX_reset() is not needed and can be dropped. Signed-off-by: Yann Droneaud --- lib/rsa/rsa-sign.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 3e7b798289..b2a21199e4 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -383,12 +383,11 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, goto err_alloc; } - context = EVP_MD_CTX_create(); + context = EVP_MD_CTX_new(); if (!context) { ret = rsa_err("EVP context creation failed"); goto err_create; } - EVP_MD_CTX_init(context); ckey = EVP_PKEY_CTX_new(pkey, NULL); if (!ckey) { @@ -425,8 +424,7 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, goto err_sign; } - EVP_MD_CTX_reset(context); - EVP_MD_CTX_destroy(context); + EVP_MD_CTX_free(context); debug("Got signature: %zu bytes, expected %d\n", size, EVP_PKEY_size(pkey)); *sigp = sig; @@ -435,7 +433,7 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, return 0; err_sign: - EVP_MD_CTX_destroy(context); + EVP_MD_CTX_free(context); err_create: free(sig); err_alloc: From a12366a807a8fbba67b6da6e842e8296af60aba0 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 13 Jan 2022 16:57:31 +0100 Subject: [PATCH 50/78] MAINTAINERS: Add watchdog maintainers entry I've been handling "inofficially" the watchdog related patches for a few years now. Let's make this official and add a tree for it and also add myself here in the MAINTAINERS file. Signed-off-by: Stefan Roese Cc: Tom Rini Cc: Harald Seiler Reviewed-by: Tom Rini --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0f39bc6bc9..82fc49e31d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1326,6 +1326,14 @@ F: include/virtio*.h F: test/dm/virtio.c F: doc/develop/driver-model/virtio.rst +WATCHDOG +M: Stefan Roese +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-watchdog.git +F: cmd/wdt.c +F: drivers/watchdog/ +F: include/watchdog*.h + X86 M: Simon Glass M: Bin Meng From a12492ebbc88dab74b1d6e27d8194a56eb1fbbff Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Thu, 10 Feb 2022 18:17:54 +0100 Subject: [PATCH 51/78] drivers: watchdog: wdt-uclass.c: add a property u-boot, noautostart Since commit 492ee6b8d0e7 ("watchdog: wdt-uclass.c: handle all DM watchdogs in watchdog_reset()"), all the watchdog are started when the config WATCHDOG_AUTOSTART. To avoid a binary choice none/all, a property u-boot,noautostart may be added in the watchdog node of the u-boot device tree to not autostart this watchdog. Signed-off-by: Philippe Reynes Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/watchdog/wdt-uclass.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/wdt-uclass.c b/drivers/watchdog/wdt-uclass.c index 6d0f473867..dbf556467d 100644 --- a/drivers/watchdog/wdt-uclass.c +++ b/drivers/watchdog/wdt-uclass.c @@ -36,6 +36,8 @@ struct wdt_priv { ulong next_reset; /* Whether watchdog_start() has been called on the device. */ bool running; + /* No autostart */ + bool noautostart; }; static void init_watchdog_dev(struct udevice *dev) @@ -52,7 +54,7 @@ static void init_watchdog_dev(struct udevice *dev) dev->name); } - if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART)) { + if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART) || priv->noautostart) { printf("WDT: Not starting %s\n", dev->name); return; } @@ -256,16 +258,19 @@ static int wdt_pre_probe(struct udevice *dev) * indicated by a hw_margin_ms property. */ ulong reset_period = 1000; + bool noautostart = false; struct wdt_priv *priv; if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) { timeout = dev_read_u32_default(dev, "timeout-sec", timeout); reset_period = dev_read_u32_default(dev, "hw_margin_ms", 4 * reset_period) / 4; + noautostart = dev_read_bool(dev, "u-boot,noautostart"); } priv = dev_get_uclass_priv(dev); priv->timeout = timeout; priv->reset_period = reset_period; + priv->noautostart = noautostart; /* * Pretend this device was last reset "long" ago so the first * watchdog_reset will actually call its ->reset method. From 65066773a3e4c3f1dfc5eac8400ca7a7268e4fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Wed, 23 Feb 2022 14:21:40 +0100 Subject: [PATCH 52/78] watchdog: armada_37xx: Probe driver also when watchdog is already running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If Armada 37xx watchdog is started before U-Boot then CNTR_CTRL_ACTIVE bit is set, U-Boot armada-37xx-wdt.c driver fails to initialize and so U-Boot is unable to use or kick this watchdog. Do not check for CNTR_CTRL_ACTIVE bit and always initialize watchdog. Same behavior is implemented in Linux kernel driver. This change allows to activate watchdog in firmware which loads U-Boot. Signed-off-by: Pali Rohár Reviewed-by: Marek Behún Reviewed-by: Stefan Roese --- drivers/watchdog/armada-37xx-wdt.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/watchdog/armada-37xx-wdt.c b/drivers/watchdog/armada-37xx-wdt.c index 2e119b9b5a..bacebbc792 100644 --- a/drivers/watchdog/armada-37xx-wdt.c +++ b/drivers/watchdog/armada-37xx-wdt.c @@ -58,13 +58,11 @@ static void counter_disable(struct a37xx_wdt *priv, int id) clrbits_le32(priv->reg + CNTR_CTRL(id), CNTR_CTRL_ENABLE); } -static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) +static void init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) { u32 reg; reg = readl(priv->reg + CNTR_CTRL(id)); - if (reg & CNTR_CTRL_ACTIVE) - return -EBUSY; reg &= ~(CNTR_CTRL_MODE_MASK | CNTR_CTRL_PRESCALE_MASK | CNTR_CTRL_TRIG_SRC_MASK); @@ -79,8 +77,6 @@ static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src) reg |= trig_src; writel(reg, priv->reg + CNTR_CTRL(id)); - - return 0; } static int a37xx_wdt_reset(struct udevice *dev) @@ -116,16 +112,9 @@ static int a37xx_wdt_expire_now(struct udevice *dev, ulong flags) static int a37xx_wdt_start(struct udevice *dev, u64 ms, ulong flags) { struct a37xx_wdt *priv = dev_get_priv(dev); - int err; - err = init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0); - if (err < 0) - return err; - - err = init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG, - CNTR_CTRL_TRIG_SRC_PREV_CNTR); - if (err < 0) - return err; + init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0); + init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG, CNTR_CTRL_TRIG_SRC_PREV_CNTR); priv->timeout = ms * priv->clk_rate / 1000 / CNTR_CTRL_PRESCALE_MIN; From 817e153fe546c2da9df8e8affc94d12036815659 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 8 Mar 2022 07:25:50 +0100 Subject: [PATCH 53/78] watchdog: rti_wdt: Add 10% safety margin to clock frequency When running against RC_OSC_32k, the watchdog may suffer from running faster than expected, expiring earlier. The Linux kernel adds a 10% margin to the timeout calculation by slowing down the read clock rate accordingly. Do the same here, also to have comparable preset values for both drivers. Along this, fix the name of the local var holding to frequency - in Hz, not kHz. Signed-off-by: Jan Kiszka Signed-off-by: Stefan Roese --- drivers/watchdog/rti_wdt.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 253286d349..8d93f19b98 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -41,7 +41,7 @@ struct rti_wdt_priv { phys_addr_t regs; - unsigned int clk_khz; + unsigned int clk_hz; }; #ifdef CONFIG_WDT_K3_RTI_LOAD_FW @@ -139,7 +139,7 @@ static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) if (ret < 0) return ret; - timer_margin = timeout_ms * priv->clk_khz / 1000; + timer_margin = timeout_ms * priv->clk_hz / 1000; timer_margin >>= WDT_PRELOAD_SHIFT; if (timer_margin > WDT_PRELOAD_MAX) timer_margin = WDT_PRELOAD_MAX; @@ -185,7 +185,15 @@ static int rti_wdt_probe(struct udevice *dev) if (ret) return ret; - priv->clk_khz = clk_get_rate(&clk); + priv->clk_hz = clk_get_rate(&clk); + + /* + * If watchdog is running at 32k clock, it is not accurate. + * Adjust frequency down in this case so that it does not expire + * earlier than expected. + */ + if (priv->clk_hz < 32768) + priv->clk_hz = priv->clk_hz * 9 / 10; return 0; } From 45eb35c1979e928a2b086b090be86ac249114e62 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 7 Mar 2022 08:41:21 +0100 Subject: [PATCH 54/78] .mailmap: Fix Heinrich's xypron.glpk@gmx.de record There is one issue with Heinrich xypron.glpk@gmx.de record which should be specifically grouped with his name. Signed-off-by: Michal Simek --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 36fc1164a2..1f88ea953c 100644 --- a/.mailmap +++ b/.mailmap @@ -28,6 +28,7 @@ Boris Brezillon Dirk Behme Fabio Estevam Heinrich Schuchardt +Heinrich Schuchardt xypron.glpk@gmx.de Jagan Teki <402jagan@gmail.com> Jagan Teki Jagan Teki From c12f9d2e5496489c22aa265725cc71697d2de0cb Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Mon, 21 Feb 2022 22:17:37 +0100 Subject: [PATCH 55/78] drivers: serial: Make sure we really return a serial device The stdout-path property in the device tree does not necessarily point at a serial device. On machines such as the Apple M1 laptops where the serial port isn't easy to access and users expect to see console output on the integrated display stdout-path may point at the device tree node for the framebuffer for example. If stdout-path does not point at a node for a serial device, the serial_check_stdout() will not find a bound device and will drop down into code that attempts to use lists_bind_fdt() to bind a device anyway. However, that fallback code does not check that the uclass of the device is UCLASS_SERIAL. So if stdout-path points at the framebuffer instead of the serial device it will return a UCLASS_VIDEO device. Since the code that calls this function expects the returned device to be a UCLASS_SERIAL device, U-Boot will crash as soon as it attempts to send output to the console. Add a check here to verify that the uclass of the bound device really is UCLASS_SERIAL. If it isn't, serial_check_stdout() will return an error and serial_find_console_or_panic() will use the serial device with sequence number 0 as the console and all is fine. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- drivers/serial/serial-uclass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 362cedd955..f30f352bd7 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -66,7 +66,8 @@ static int serial_check_stdout(const void *blob, struct udevice **devp) */ if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node), devp, NULL, false)) { - if (!device_probe(*devp)) + if (device_get_uclass_id(*devp) == UCLASS_SERIAL && + !device_probe(*devp)) return 0; } From b38fbddbaa3dca0a190f9655f753e72405290431 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Tue, 8 Mar 2022 10:37:19 +0100 Subject: [PATCH 56/78] board: .gitignore: replace dsdt.c by dsdt_generated.c Since commit 5d94cbd1dca7 ("scripts: Makefile.lib: generate dsdt_generated.c instead of dsdt.c"), the file generated is named dsdt_generated.c instead of dsdt.c. So all files .gitignore referencing dsdt.c should be upated with dsdt_generated.c. Signed-off-by: Philippe Reynes Reviewed-by: Heinrich Schuchardt --- board/advantech/som-db5800-som-6867/.gitignore | 6 +++--- board/congatec/conga-qeval20-qa3-e3845/.gitignore | 6 +++--- board/intel/bayleybay/.gitignore | 6 +++--- board/intel/edison/.gitignore | 6 +++--- board/intel/galileo/.gitignore | 6 +++--- board/intel/minnowmax/.gitignore | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/board/advantech/som-db5800-som-6867/.gitignore b/board/advantech/som-db5800-som-6867/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/advantech/som-db5800-som-6867/.gitignore +++ b/board/advantech/som-db5800-som-6867/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/congatec/conga-qeval20-qa3-e3845/.gitignore b/board/congatec/conga-qeval20-qa3-e3845/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/congatec/conga-qeval20-qa3-e3845/.gitignore +++ b/board/congatec/conga-qeval20-qa3-e3845/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/intel/bayleybay/.gitignore b/board/intel/bayleybay/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/intel/bayleybay/.gitignore +++ b/board/intel/bayleybay/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/intel/edison/.gitignore b/board/intel/edison/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/intel/edison/.gitignore +++ b/board/intel/edison/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/intel/galileo/.gitignore b/board/intel/galileo/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/intel/galileo/.gitignore +++ b/board/intel/galileo/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c diff --git a/board/intel/minnowmax/.gitignore b/board/intel/minnowmax/.gitignore index 6eb8a5481a..39e46ba0ae 100644 --- a/board/intel/minnowmax/.gitignore +++ b/board/intel/minnowmax/.gitignore @@ -1,3 +1,3 @@ -dsdt.aml -dsdt.asl.tmp -dsdt.c +dsdt_generated.aml +dsdt_generated.asl.tmp +dsdt_generated.c From 81a46c152a62a496fd1a29114c34069dc6c78c93 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 11 Jan 2022 12:46:02 +0000 Subject: [PATCH 57/78] sunxi: Kconfig: Fix up SPI configuration Commit 7945caf22c44 ("arm: sunxi: Enable SPI/SPI-FLASH support for A64") selected CONFIG_SPI by default on all Allwinner A64 boards, even though only 4 out of the 14 A64 boards have a SPI flash chip. All other SoCs had to manually select DM_SPI and friends, even though they are a platform property (the sunxi SPI driver is DM_SPI only). Clean this up to allow easy selection of SPI flash support in U-Boot proper, by selecting DM_SPI and DM_SPI_FLASH *if* CONFIG_SPI is selected, for *all* Allwinner SoCs. This simplifies the defconfig for two Libretech boards already. Also remove the forced CONFIG_SPI from the A64 Kconfig, instead let the four boards which allow SPI booting select this explicitly. Any board wishing to support SPI flash in U-Boot proper now just defines CONFIG_SPI and CONFIG_SPI_FLASH_ in its defconfig, Kconfig takes care of the rest. Signed-off-by: Andre Przywara Reviewed-by: Jagan Teki --- arch/arm/Kconfig | 2 ++ arch/arm/mach-sunxi/Kconfig | 3 --- configs/libretech_all_h3_it_h5_defconfig | 2 -- configs/libretech_all_h5_cc_h5_defconfig | 2 -- configs/oceanic_5205_5inmfd_defconfig | 1 + configs/orangepi_win_defconfig | 1 + configs/pine64-lts_defconfig | 1 + configs/sopine_baseboard_defconfig | 1 + 8 files changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 391a77c2b4..4567c183fb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1062,6 +1062,8 @@ config ARCH_SUNXI select DM_ETH select DM_GPIO select DM_I2C if I2C + select DM_SPI if SPI + select DM_SPI_FLASH if SPI select DM_KEYBOARD select DM_MMC if MMC select DM_SCSI if SCSI diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 205fe3c9d3..4dab9174c5 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -332,9 +332,6 @@ config MACH_SUN9I config MACH_SUN50I bool "sun50i (Allwinner A64)" select ARM64 - select SPI - select DM_SPI if SPI - select DM_SPI_FLASH select PHY_SUN4I_USB select SUN6I_PRCM select SUNXI_DE2 diff --git a/configs/libretech_all_h3_it_h5_defconfig b/configs/libretech_all_h3_it_h5_defconfig index 7f0e0be50b..cb7ffb4d7d 100644 --- a/configs/libretech_all_h3_it_h5_defconfig +++ b/configs/libretech_all_h3_it_h5_defconfig @@ -7,9 +7,7 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/libretech_all_h5_cc_h5_defconfig b/configs/libretech_all_h5_cc_h5_defconfig index 25bfe52b32..c3aa4b1061 100644 --- a/configs/libretech_all_h5_cc_h5_defconfig +++ b/configs/libretech_all_h5_cc_h5_defconfig @@ -7,10 +7,8 @@ CONFIG_DRAM_CLK=672 CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set -CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH_XMC=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y -CONFIG_DM_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig index 9ba115c97d..7ce63ba665 100644 --- a/configs/oceanic_5205_5inmfd_defconfig +++ b/configs/oceanic_5205_5inmfd_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC0_CD_PIN="" CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig index 8c2179ba8b..133755291a 100644 --- a/configs/orangepi_win_defconfig +++ b/configs/orangepi_win_defconfig @@ -9,5 +9,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index 6209e68e2d..75a77acc44 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -11,5 +11,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig index 0093076dc5..982f7b0b67 100644 --- a/configs/sopine_baseboard_defconfig +++ b/configs/sopine_baseboard_defconfig @@ -13,5 +13,6 @@ CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y From 2bdf213f915e29659b23844a2ef8105fbebd9566 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 11 Jan 2022 12:46:03 +0000 Subject: [PATCH 58/78] env: sunxi: Define location in SPI flash To allow loading and storing the environment from SPI flash, adjust the raw offset variables for Allwinner boards to make sense there. U-Boot (including SPL and other blobs) is loaded from the beginning of SPI flash, so move the environment location as far back as possible, to not create unnecessary limits. As those offsets are shared with (now mostly unused) raw MMC environment, we should respect the common one megabyte limit, which also makes sense on SPI flash. So limit the environment for those raw locations to 64KB, and place it just below 1MB (@960KB). Those values are currently unused, unless someone forcibly enables the raw MMC environment. In this case it would break as of now, as the current offset of 544KB is far too low for the current (arm64) U-Boot proper. Signed-off-by: Andre Przywara Reviewed-by: Jagan Teki --- env/Kconfig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/env/Kconfig b/env/Kconfig index 6dc8d8d860..45b7895047 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -536,7 +536,7 @@ config ENV_OFFSET ENV_IS_IN_SPI_FLASH default 0x3f8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC default 0x140000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH - default 0x88000 if ARCH_SUNXI + default 0xF0000 if ARCH_SUNXI default 0xE0000 if ARCH_ZYNQ default 0x1E00000 if ARCH_ZYNQMP default 0x7F40000 if ARCH_VERSAL @@ -559,7 +559,8 @@ config ENV_OFFSET_REDUND config ENV_SIZE hex "Environment Size" default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP - default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 + default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 + default 0x10000 if ARCH_SUNXI default 0x8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC default 0x2000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH default 0x8000 if ARCH_ZYNQMP || ARCH_VERSAL @@ -575,6 +576,7 @@ config ENV_SECT_SIZE default 0x40000 if ARCH_ZYNQMP || ARCH_VERSAL default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91 default 0x20000 if MICROBLAZE && ENV_IS_IN_SPI_FLASH + default 0x10000 if ARCH_SUNXI && ENV_IS_IN_SPI_FLASH help Size of the sector containing the environment. From e42dad4168fe7acae810f759078a8cdfe2cd9086 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 11 Jan 2022 12:46:04 +0000 Subject: [PATCH 59/78] sunxi: use boot source for determining environment location Currently we only support to load the environment from raw MMC or FAT locations on Allwinner boards. With the advent of SPI flash we probably also want to support using the environment there, so we need to become a bit more flexible. Change the environment priority function to take the boot source into account. When booted from eMMC or SD card, we use FAT or MMC, if configured, as before. If we are booted from SPI flash, we try to use the environment from there, if possible. The same is true for NAND flash booting, although this is somewhat theoretical right now (as untested). This way we can use the same image for SD and SPI flash booting, which allows us to simply copy a booted image from SD card to the SPI flash, for instance. Signed-off-by: Andre Przywara Reviewed-by: Jagan Teki --- board/sunxi/board.c | 51 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 82c52b28f8..a096159047 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -171,21 +171,56 @@ void i2c_init_board(void) #endif } -#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT) +/* + * Try to use the environment from the boot source first. + * For MMC, this means a FAT partition on the boot device (SD or eMMC). + * If the raw MMC environment is also enabled, this is tried next. + * SPI flash falls back to FAT (on SD card). + */ enum env_location env_get_location(enum env_operation op, int prio) { - switch (prio) { - case 0: - return ENVL_FAT; + enum env_location boot_loc = ENVL_FAT; - case 1: - return ENVL_MMC; + gd->env_load_prio = prio; + switch (sunxi_get_boot_device()) { + case BOOT_DEVICE_MMC1: + case BOOT_DEVICE_MMC2: + boot_loc = ENVL_FAT; + break; + case BOOT_DEVICE_NAND: + if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND)) + boot_loc = ENVL_NAND; + break; + case BOOT_DEVICE_SPI: + if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) + boot_loc = ENVL_SPI_FLASH; + break; + case BOOT_DEVICE_BOARD: + break; default: - return ENVL_UNKNOWN; + break; } + + /* Always try to access the environment on the boot device first. */ + if (prio == 0) + return boot_loc; + + if (prio == 1) { + switch (boot_loc) { + case ENVL_SPI_FLASH: + return ENVL_FAT; + case ENVL_FAT: + if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC)) + return ENVL_MMC; + break; + default: + break; + } + } + + return ENVL_UNKNOWN; } -#endif #ifdef CONFIG_DM_MMC static void mmc_pinmux_setup(int sdc); From 753a85fd151d28a55c6bb4d15bd3bc44dd4b5e22 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 11 Jan 2022 12:46:05 +0000 Subject: [PATCH 60/78] env: sunxi: enable ENV_IS_IN_SPI_FLASH Now that sunxi uses CONFIG_SPI more sanely, and can also now properly load the environment from SPI flash, let's enable the symbol that actually considers the SPI flash when accessing the environment. As this symbol depends on CONFIG_SPI, which we now only enable if the board has a SPI flash, we can make if "default y" for all Allwinner boards. Signed-off-by: Andre Przywara Reviewed-by: Jagan Teki --- env/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/env/Kconfig b/env/Kconfig index 45b7895047..b9d04725a3 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -320,6 +320,7 @@ config ENV_IS_IN_SPI_FLASH default y if NORTHBRIDGE_INTEL_IVYBRIDGE default y if INTEL_QUARK default y if INTEL_QUEENSBAY + default y if ARCH_SUNXI help Define this if you have a SPI Flash memory device which you want to use for the environment. From 280294c5dfe02a11c9080ee51bd85880a23d769b Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 11 Jan 2022 12:46:06 +0000 Subject: [PATCH 61/78] sunxi: boards: Enable SPI flash support in U-Boot proper Some sunxi boards ship with SPI flash, which allows booting through the BootROM. We cover this functionality by a separate SPL "mini" driver. Separately we have a proper DM_SPI driver for U-Boot proper, which provides access to the SPI flash through the "sf" command. That allows to update the firmware on the SPI flash, also to store the environment there. However only very few boards actually enable support for U-Boot proper, even though that would work and the SPL part is configured. Use the cleaned up configuration scheme to enable SPI flash on those boards which mention a SPI flash in their .dts, or which use the SPL SPI support. Out of the box this would enable storing the environment on the SPI flash, and allows people to read or write the flash from U-Boot, for instance to update the SPI flash when booted via an SD card. For this to actually work there must be a "spi0" alias in the DT, which most boards are missing. But this should be addressed separately. Signed-off-by: Andre Przywara Reviewed-by: Jagan Teki --- configs/orangepi_pc2_defconfig | 2 ++ configs/orangepi_r1_defconfig | 2 ++ configs/orangepi_win_defconfig | 1 + configs/orangepi_zero2_defconfig | 2 ++ configs/orangepi_zero_defconfig | 2 ++ configs/pine64-lts_defconfig | 1 + configs/pine_h64_defconfig | 2 ++ configs/pinecube_defconfig | 2 ++ 8 files changed, 14 insertions(+) diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig index 2eaddcf684..777af8c60e 100644 --- a/configs/orangepi_pc2_defconfig +++ b/configs/orangepi_pc2_defconfig @@ -11,9 +11,11 @@ CONFIG_SPL_SPI_SUNXI=y CONFIG_SPL_I2C=y CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SUN8I_EMAC=y CONFIG_SY8106A_POWER=y CONFIG_SY8106A_VOUT1_VOLT=1100 +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_MUSB_GADGET=y diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig index 745451c4bf..4496aa4a45 100644 --- a/configs/orangepi_r1_defconfig +++ b/configs/orangepi_r1_defconfig @@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig index 133755291a..3b78ad7e52 100644 --- a/configs/orangepi_win_defconfig +++ b/configs/orangepi_win_defconfig @@ -7,6 +7,7 @@ CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y CONFIG_MACPWR="PD14" CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig index 22563c864f..54faf6aba2 100644 --- a/configs/orangepi_zero2_defconfig +++ b/configs/orangepi_zero2_defconfig @@ -15,5 +15,7 @@ CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_PHY_REALTEK=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig index 332cd4739e..2dc69d2994 100644 --- a/configs/orangepi_zero_defconfig +++ b/configs/orangepi_zero_defconfig @@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_CONSOLE_MUX=y +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y +CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index 75a77acc44..45a9e77e0e 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -10,6 +10,7 @@ CONFIG_MMC0_CD_PIN="" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_SPL_SPI_SUNXI=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_SPI=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig index 1928509dd7..1e730dd9fa 100644 --- a/configs/pine_h64_defconfig +++ b/configs/pine_h64_defconfig @@ -11,8 +11,10 @@ CONFIG_USB3_VBUS_PIN="PL5" CONFIG_SPL_SPI_SUNXI=y # CONFIG_PSCI_RESET is not set # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPI_FLASH_WINBOND=y CONFIG_SUN8I_EMAC=y CONFIG_PHY_SUN50I_USB3=y +CONFIG_SPI=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/pinecube_defconfig b/configs/pinecube_defconfig index 0c71d59418..e779663a0d 100644 --- a/configs/pinecube_defconfig +++ b/configs/pinecube_defconfig @@ -12,8 +12,10 @@ CONFIG_SPL_SYS_I2C_LEGACY=y CONFIG_SYS_I2C_MVTWSI=y CONFIG_SYS_I2C_SLAVE=0x7f CONFIG_SYS_I2C_SPEED=400000 +CONFIG_SPI_FLASH_WINBOND=y # CONFIG_NETDEVICES is not set CONFIG_AXP209_POWER=y CONFIG_AXP_DCDC2_VOLT=1250 CONFIG_AXP_DCDC3_VOLT=3300 CONFIG_CONS_INDEX=3 +CONFIG_SPI=y From 228173d8556ee3209c3c8ea6a296b355b28c7e15 Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Thu, 3 Mar 2022 18:26:39 +0000 Subject: [PATCH 62/78] mtd: spi-nor-ids: Enable quad read for Gigadevice gd25lq128 The Gigadevice gd25lq128 serial flash exists in different versions, all which identify themselves using the same JEDEC id. gd25lq128c: https://www.gigadevice.com/datasheet/gd25lq128 gd25lq128d: https://www.gigadevice.com/datasheet/gd25lq128d However, all versions support quad read, so enable it. Tested and verified on the Sipeed MAix BiT board. Fixes: 30b9a28a3f2d ("mtd: spi-nor-ids: Add Gigadevice gd25lq128 ID") Signed-off-by: Niklas Cassel Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi-nor-ids.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index b551ebd75e..763bab04c6 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -119,7 +119,7 @@ const struct flash_info spi_nor_ids[] = { }, { INFO("gd25lq128", 0xc86018, 0, 64 * 1024, 256, - SECT_4K | SPI_NOR_DUAL_READ | + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { From bfaa51dd4adf59c1b304399381401bfb58ed4099 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 11 Feb 2022 18:11:05 +0100 Subject: [PATCH 63/78] cmd: add serial console support for the cls command Currently the cls command does not support the serial console The screen can be cleared in the video uclass, the colored frame buffer console, and the serial console by sending the same escape sequence. This reduces the cls command to a single printf() statement on most boards. Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- cmd/cls.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/cls.c b/cmd/cls.c index eab4e6993b..bdeb49786d 100644 --- a/cmd/cls.c +++ b/cmd/cls.c @@ -11,17 +11,23 @@ #include #include +#define CSI "\x1b[" + static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { -#if defined(CONFIG_DM_VIDEO) - struct udevice *dev; + __maybe_unused struct udevice *dev; + /* Send clear screen and home */ + printf(CSI "2J" CSI "1;1H"); +#if defined(CONFIG_DM_VIDEO) +#if !defined(CONFIG_VIDEO_ANSI) if (uclass_first_device_err(UCLASS_VIDEO, &dev)) return CMD_RET_FAILURE; if (video_clear(dev)) return CMD_RET_FAILURE; +#endif #elif defined(CONFIG_CFB_CONSOLE) video_clear(); #elif defined(CONFIG_LCD) From 007fdb20bbad10a361c2851547af0867afb6582e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 10 Mar 2022 11:32:49 +0100 Subject: [PATCH 64/78] doc: path to u-boot-spl.bin on SiFive Unmatched board u-boot-spl.bin is built in spl/. Signed-off-by: Heinrich Schuchardt Reviewed-by: Bin Meng --- doc/board/sifive/unmatched.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/board/sifive/unmatched.rst b/doc/board/sifive/unmatched.rst index 24a889991c..a99442277b 100644 --- a/doc/board/sifive/unmatched.rst +++ b/doc/board/sifive/unmatched.rst @@ -560,7 +560,7 @@ Write U-boot SPL and U-boot to their partitions. .. code-block:: none - dd if=u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync + dd if=spl/u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync dd if=u-boot.itb of=/dev/mtdblock0 bs=4096 seek=261 conv=sync Power off the board. From f95104825a127e9e76923336b1f755a9554e3126 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 12 Mar 2022 11:56:23 +0100 Subject: [PATCH 65/78] doc: add libgnutls28-dev to build dependencies mkeficapsule requires package libgnutls28-dev for building Signed-off-by: Heinrich Schuchardt --- doc/build/gcc.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst index b883cf73ee..470a7aa349 100644 --- a/doc/build/gcc.rst +++ b/doc/build/gcc.rst @@ -25,11 +25,12 @@ Depending on the build targets further packages maybe needed sudo apt-get install bc bison build-essential coccinelle \ device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \ - liblz4-tool libguestfs-tools libncurses-dev libpython3-dev libsdl2-dev \ - libssl-dev lz4 lzma lzma-alone openssl pkg-config python3 \ - python3-coverage python3-pkg-resources python3-pycryptodome \ - python3-pyelftools python3-pytest python3-sphinxcontrib.apidoc \ - python3-sphinx-rtd-theme python3-virtualenv swig + liblz4-tool libgnutls28-dev libguestfs-tools libncurses-dev \ + libpython3-dev libsdl2-dev libssl-dev lz4 lzma lzma-alone openssl \ + pkg-config python3 python3-coverage python3-pkg-resources \ + python3-pycryptodome python3-pyelftools python3-pytest \ + python3-sphinxcontrib.apidoc python3-sphinx-rtd-theme python3-virtualenv \ + swig SUSE based ~~~~~~~~~~ From 66028930dac08f7116b5e3cdba35c3e65676c0cd Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 9 Mar 2022 19:56:23 +0100 Subject: [PATCH 66/78] efi_loader: copy GUID in InstallProtocolInterface() InstallProtocolInterface() is called with a pointer to the protocol GUID. There is not guarantee that the memory used by the caller for the protocol GUID stays allocated. To play it safe the GUID should be copied to U-Boot's internal structures. Reported-by: Joerie de Gram Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 2 +- lib/efi_loader/efi_boottime.c | 14 +++++++------- lib/efi_loader/efi_image_loader.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index e390d323a9..110d8ae79c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -342,7 +342,7 @@ struct efi_open_protocol_info_item { */ struct efi_handler { struct list_head link; - const efi_guid_t *guid; + const efi_guid_t guid; void *protocol_interface; struct list_head open_infos; }; diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 82128ac1d5..d0f3e05e70 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -552,7 +552,7 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, struct efi_handler *protocol; protocol = list_entry(lhandle, struct efi_handler, link); - if (!guidcmp(protocol->guid, protocol_guid)) { + if (!guidcmp(&protocol->guid, protocol_guid)) { if (handler) *handler = protocol; return EFI_SUCCESS; @@ -604,7 +604,7 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle) list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) { efi_status_t ret; - ret = efi_remove_protocol(handle, protocol->guid, + ret = efi_remove_protocol(handle, &protocol->guid, protocol->protocol_interface); if (ret != EFI_SUCCESS) return ret; @@ -1131,7 +1131,7 @@ efi_status_t efi_add_protocol(const efi_handle_t handle, handler = calloc(1, sizeof(struct efi_handler)); if (!handler) return EFI_OUT_OF_RESOURCES; - handler->guid = protocol; + memcpy((void *)&handler->guid, protocol, sizeof(efi_guid_t)); handler->protocol_interface = protocol_interface; INIT_LIST_HEAD(&handler->open_infos); list_add_tail(&handler->link, &efiobj->protocols); @@ -1227,7 +1227,7 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, /* Count all driver associations */ list_for_each_entry(handler, &handle->protocols, link) { - if (protocol && guidcmp(handler->guid, protocol)) + if (protocol && guidcmp(&handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.attributes & @@ -1249,7 +1249,7 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, return EFI_OUT_OF_RESOURCES; /* Collect unique driver handles */ list_for_each_entry(handler, &handle->protocols, link) { - if (protocol && guidcmp(handler->guid, protocol)) + if (protocol && guidcmp(&handler->guid, protocol)) continue; list_for_each_entry(item, &handler->open_infos, link) { if (item->info.attributes & @@ -2446,7 +2446,7 @@ static efi_status_t EFIAPI efi_protocols_per_handle( protocol = list_entry(protocol_handle, struct efi_handler, link); - (*protocol_buffer)[j] = (void *)protocol->guid; + (*protocol_buffer)[j] = (void *)&protocol->guid; ++j; } } @@ -3094,7 +3094,7 @@ close_next: (efi_handle_t)image_obj) continue; r = EFI_CALL(efi_close_protocol - (efiobj, protocol->guid, + (efiobj, &protocol->guid, info->info.agent_handle, info->info.controller_handle )); diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 5df35939f7..9611398885 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -91,7 +91,7 @@ void efi_print_image_infos(void *pc) list_for_each_entry(efiobj, &efi_obj_list, link) { list_for_each_entry(handler, &efiobj->protocols, link) { - if (!guidcmp(handler->guid, &efi_guid_loaded_image)) { + if (!guidcmp(&handler->guid, &efi_guid_loaded_image)) { efi_print_image_info( (struct efi_loaded_image_obj *)efiobj, handler->protocol_interface, pc); From 978a8a296e699fbb0919c245f78317dea08eab8e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 12 Mar 2022 23:03:27 -0700 Subject: [PATCH 67/78] x86: Add an enum name for the GNVS firmware type This enum is currently anonymous. Add a name so it can be used in the code. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/intel_gnvs.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/intel_gnvs.h b/arch/x86/include/asm/intel_gnvs.h index fc743dc928..0b69530edb 100644 --- a/arch/x86/include/asm/intel_gnvs.h +++ b/arch/x86/include/asm/intel_gnvs.h @@ -47,7 +47,13 @@ enum { BINF_RW_B = 2 }; -enum { +/** + * enum cros_fw_type_t - Used to indicate Chromium OS firmware type + * + * Chromium OS uses a region of the GNVS starting at offset 0x100 to store + * various bits of information, including the type of firmware being booted + */ +enum cros_fw_type_t { FIRMWARE_TYPE_AUTO_DETECT = -1, FIRMWARE_TYPE_RECOVERY = 0, FIRMWARE_TYPE_NORMAL = 1, From 92a3e67ee9b0e1b2294a3d16e851b83440de2a1f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 12 Mar 2022 23:03:28 -0700 Subject: [PATCH 68/78] x86: Correct the coreboot header file in MAINTAINERS This board has its own config header file. Correct it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- board/coreboot/coreboot/MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS index a05673bb0b..ee12d32ce7 100644 --- a/board/coreboot/coreboot/MAINTAINERS +++ b/board/coreboot/coreboot/MAINTAINERS @@ -2,12 +2,12 @@ COREBOOT BOARD M: Simon Glass S: Maintained F: board/coreboot/coreboot/ -F: include/configs/chromebook_link.h +F: include/configs/coreboot.h F: configs/coreboot_defconfig COREBOOT64 BOARD M: Simon Glass S: Maintained F: board/coreboot/coreboot/ -F: include/configs/chromebook_link.h +F: include/configs/coreboot.h F: configs/coreboot64_defconfig From a79dea29127d2840277e6edc0f5c71dc1daec82b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 7 Mar 2022 19:03:07 +0100 Subject: [PATCH 69/78] tools: kwboot: Allow to specify custom baudrate only in supported operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Custom baudrate different than 115200 may be specified only when kwboot is not going to send boot/debug message pattern or when it is going to send boot message pattern with image file (in which case baudrate change happens after sending kwbimage header). BootROM detects boot/debug message pattern only at baudrate 115200. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwboot.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/kwboot.c b/tools/kwboot.c index 69d1be0f48..986f27c201 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -2133,6 +2133,12 @@ main(int argc, char **argv) if (optind != argc) goto usage; + /* boot and debug message use baudrate 115200 */ + if (((bootmsg && !imgpath) || debugmsg) && baudrate != 115200) { + fprintf(stderr, "Baudrate other than 115200 cannot be used for this operation.\n"); + goto usage; + } + tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate); if (tty < 0) { perror(ttypath); From 3782f55ae81825c6ce9f85ca4e6c6798e88087c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 7 Mar 2022 19:03:08 +0100 Subject: [PATCH 70/78] tools: kwboot: Check if baudrate value is supported before sending image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call kwboot_open_tty() which baudrate value which was specified at the command line by option -B. This function returns error if baudrate is not supported by selected tty device. Initial baudrate for image transfer is always 115200, so call kwboot_tty_change_baudrate() with value 115200 immediately after kwboot_open_tty() if baudrate specified by option -B is different than 115200. This makes kwboot fail immediately, informing that baudrate is unsupported, instead of failing only after the first part of image is already sent. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- tools/kwboot.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 986f27c201..3b45e19a30 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -2139,12 +2139,24 @@ main(int argc, char **argv) goto usage; } - tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate); + tty = kwboot_open_tty(ttypath, baudrate); if (tty < 0) { perror(ttypath); goto out; } + /* + * initial baudrate for image transfer is always 115200, + * the change to different baudrate is done only after the header is sent + */ + if (imgpath && baudrate != 115200) { + rc = kwboot_tty_change_baudrate(tty, 115200); + if (rc) { + perror(ttypath); + goto out; + } + } + if (baudrate == 115200) /* do not change baudrate during Xmodem to the same value */ baudrate = 0; From c497ae70238a743cb804f1cb9b95648a6a2bdd51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 7 Mar 2022 19:03:09 +0100 Subject: [PATCH 71/78] tools: kwboot: Allow to mix positional arguments with option -b MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9e6d71d2b55f ("tools: kwboot: Allow to use -b without image path as the last getopt() option") broke usage of kwboot with following arguments: kwboot -t -B 115200 /dev/ttyUSB0 -b u-boot-spl.kwb Fix parsing of option -b with optional argument again. Fixes: 9e6d71d2b55f ("tools: kwboot: Allow to use -b without image path as the last getopt() option") Signed-off-by: Pali Rohár Reported-by: Tony Dinh Tested-by: Tony Dinh Reviewed-by: Stefan Roese --- tools/kwboot.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/kwboot.c b/tools/kwboot.c index 3b45e19a30..9f2dd2de4e 100644 --- a/tools/kwboot.c +++ b/tools/kwboot.c @@ -2073,7 +2073,8 @@ main(int argc, char **argv) bootmsg = 1; if (prev_optind == optind) goto usage; - if (optind < argc - 1 && argv[optind] && argv[optind][0] != '-') + /* Option -b could have optional argument which specify image path */ + if (optind < argc && argv[optind] && argv[optind][0] != '-') imgpath = argv[optind++]; break; @@ -2128,10 +2129,19 @@ main(int argc, char **argv) if (!bootmsg && !term && !debugmsg && !imgpath) goto usage; - ttypath = argv[optind++]; - - if (optind != argc) + /* + * If there is no remaining argument but optional imgpath was parsed + * then it means that optional imgpath was eaten by getopt parser. + * Reassing imgpath to required ttypath argument. + */ + if (optind == argc && imgpath) { + ttypath = imgpath; + imgpath = NULL; + } else if (optind + 1 == argc) { + ttypath = argv[optind]; + } else { goto usage; + } /* boot and debug message use baudrate 115200 */ if (((bootmsg && !imgpath) || debugmsg) && baudrate != 115200) { From 037bb6e2ca7c1e2371056c8b61b00842d25ea9f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 7 Mar 2022 19:12:59 +0100 Subject: [PATCH 72/78] arm: a37xx: Remap IO space to bus address 0x0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remap PCI I/O space to the bus address 0x0 in the Armada 37xx device-tree in order to support legacy I/O port based cards which have hardcoded I/O ports in low address space. Some legacy PCI I/O based cards do not support 32-bit I/O addressing. Signed-off-by: Pali Rohár Reviewed-by: Stefan Roese --- arch/arm/dts/armada-3720-turris-mox.dts | 7 ++++++- arch/arm/dts/armada-37xx.dtsi | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index 1fc4a30d03..595b4b5abb 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -139,7 +139,9 @@ /* * U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property * contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and - * 2 size cells and also expects that the second range starts at 16 MB offset. If these + * 2 size cells and also expects that the second range starts at 16 MB offset. Also it + * expects that first range uses same address for PCI (child) and CPU (parent) cells (so + * no remapping) and that this address is the lowest from all specified ranges. If these * conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address * space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window * for IO and the rest 112 MB (64+32+16) for MEM. Controller supports 32-bit IO mapping. @@ -148,6 +150,9 @@ * https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7 * https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf * https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33 + * Bug related to requirement of same child and parent addresses for first range is fixed + * in U-Boot version 2022.04 by following commit: + * https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17 */ #address-cells = <3>; #size-cells = <2>; diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index 9fa6457fac..0bb4f60763 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -499,7 +499,7 @@ * (totaling 127 MiB) for MEM. */ ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x07f00000 /* Port 0 MEM */ - 0x81000000 0 0xeff00000 0 0xeff00000 0 0x00100000>; /* Port 0 IO*/ + 0x81000000 0 0x00000000 0 0xeff00000 0 0x00100000>; /* Port 0 IO */ interrupt-map-mask = <0 0 0 7>; interrupt-map = <0 0 0 1 &pcie_intc 0>, <0 0 0 2 &pcie_intc 1>, From ee5a284b296f31302fe2aaddd07af9b04d3ce54f Mon Sep 17 00:00:00 2001 From: Alper Nebi Yasak Date: Sat, 29 Jan 2022 01:42:37 +0300 Subject: [PATCH 73/78] rockchip: sdhci: Fix RK3399 eMMC PHY power cycling The Rockchip RK3399 eMMC PHY has to be power-cycled while changing its clock speed to some higher speeds. This is dependent on the desired SDHCI clock speed, and it looks like the PHY should be powered off while setting the SDHCI clock in these cases. Commit ac804143cfd1 ("mmc: rockchip_sdhci: add phy and clock config for rk3399") attempts to do this in the set_ios_post() hook by setting the SDHCI clock once more while the PHY is turned off/on as necessary, as the SDHCI framework does not provide a way to override how it sets its clock. However, the commit breaks reinitializing the eMMC on a few boards including chromebook_kevin and reportedly ROCKPro64. This patch reworks the power cycling to utilize the SDHCI framework slightly better (using the set_control_reg() hook to power off the PHY and set_ios_post() hook to power it back on) which happens to fix the issue, at least on a chromebook_kevin. Signed-off-by: Alper Nebi Yasak Reviewed-by: Simon Glass --- drivers/mmc/rockchip_sdhci.c | 76 +++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 278473899c..b91df05de4 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -90,9 +90,33 @@ struct rockchip_sdhc { }; struct sdhci_data { - int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock); int (*emmc_phy_init)(struct udevice *dev); int (*get_phy)(struct udevice *dev); + + /** + * set_control_reg() - Set SDHCI control registers + * + * This is the set_control_reg() SDHCI operation that should be + * used for the hardware this driver data is associated with. + * Normally, this is used to set up control registers for + * voltage level and UHS speed mode. + * + * @host: SDHCI host structure + */ + void (*set_control_reg)(struct sdhci_host *host); + + /** + * set_ios_post() - Host specific hook after set_ios() calls + * + * This is the set_ios_post() SDHCI operation that should be + * used for the hardware this driver data is associated with. + * Normally, this is a hook that is called after sdhci_set_ios() + * that does any necessary host-specific configuration. + * + * @host: SDHCI host structure + * Return: 0 if successful, -ve on error + */ + int (*set_ios_post)(struct sdhci_host *host); }; static int rk3399_emmc_phy_init(struct udevice *dev) @@ -182,15 +206,28 @@ static int rk3399_emmc_get_phy(struct udevice *dev) return 0; } -static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock) +static void rk3399_sdhci_set_control_reg(struct sdhci_host *host) { struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct mmc *mmc = host->mmc; + uint clock = mmc->tran_speed; int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ; if (cycle_phy) rk3399_emmc_phy_power_off(priv->phy); - sdhci_set_clock(host->mmc, clock); + sdhci_set_control_reg(host); +}; + +static int rk3399_sdhci_set_ios_post(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct mmc *mmc = host->mmc; + uint clock = mmc->tran_speed; + int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ; + + if (!clock) + clock = mmc->clock; if (cycle_phy) rk3399_emmc_phy_power_on(priv->phy, clock); @@ -269,10 +306,8 @@ static int rk3568_emmc_get_phy(struct udevice *dev) return 0; } -static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) +static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { - struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); - struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); struct mmc *mmc = host->mmc; uint clock = mmc->tran_speed; u32 reg; @@ -280,8 +315,7 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) if (!clock) clock = mmc->clock; - if (data->emmc_set_clock) - data->emmc_set_clock(host, clock); + rk3568_sdhci_emmc_set_clock(host, clock); if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) { reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); @@ -295,6 +329,26 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) return 0; } +static void rockchip_sdhci_set_control_reg(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); + + if (data->set_control_reg) + data->set_control_reg(host); +} + +static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) +{ + struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); + struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev); + + if (data->set_ios_post) + return data->set_ios_post(host); + + return 0; +} + static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) { struct sdhci_host *host = dev_get_priv(mmc->dev); @@ -358,6 +412,7 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) static struct sdhci_ops rockchip_sdhci_ops = { .set_ios_post = rockchip_sdhci_set_ios_post, .platform_execute_tuning = &rockchip_sdhci_execute_tuning, + .set_control_reg = rockchip_sdhci_set_control_reg, }; static int rockchip_sdhci_probe(struct udevice *dev) @@ -436,15 +491,16 @@ static int rockchip_sdhci_bind(struct udevice *dev) } static const struct sdhci_data rk3399_data = { - .emmc_set_clock = rk3399_sdhci_emmc_set_clock, .get_phy = rk3399_emmc_get_phy, .emmc_phy_init = rk3399_emmc_phy_init, + .set_control_reg = rk3399_sdhci_set_control_reg, + .set_ios_post = rk3399_sdhci_set_ios_post, }; static const struct sdhci_data rk3568_data = { - .emmc_set_clock = rk3568_sdhci_emmc_set_clock, .get_phy = rk3568_emmc_get_phy, .emmc_phy_init = rk3568_emmc_phy_init, + .set_ios_post = rk3568_sdhci_set_ios_post, }; static const struct udevice_id sdhci_ids[] = { From b78f81eb5d6ef45cfba8cc6a155da7fc661b420f Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 4 Mar 2022 17:45:25 +0530 Subject: [PATCH 74/78] phy: cadence: Sierra: Move the link operations from serdes phy to link device In commit 6f46c7441a9f ("phy: cadence: Sierra: Add a UCLASS_PHY device for links"), a separate udevice of type UCLASS_PHY was created for each link. Therefore, move the corresponding link operations under the link device. Also, change the uclass of sierra phy to UCLASS_MISC as it is no longer the phy device. Fixes: 6f46c7441a9f ("phy: cadence: Sierra: Add a UCLASS_PHY device for links") Signed-off-by: Aswath Govindraju Reviewed-by: Georgi Vlaev --- drivers/phy/cadence/phy-cadence-sierra.c | 59 ++++++++---------------- 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c index d95d4b432a..fc5044fd5d 100644 --- a/drivers/phy/cadence/phy-cadence-sierra.c +++ b/drivers/phy/cadence/phy-cadence-sierra.c @@ -358,26 +358,10 @@ static inline int cdns_reset_deassert(struct reset_control *rst) return 0; } -static inline struct cdns_sierra_inst *phy_get_drvdata(struct phy *phy) +static int cdns_sierra_link_init(struct phy *gphy) { - struct cdns_sierra_phy *sp = dev_get_priv(phy->dev); - int index; - - if (phy->id >= SIERRA_MAX_LANES) - return NULL; - - for (index = 0; index < sp->nsubnodes; index++) { - if (phy->id == sp->phys[index]->mlane) - return sp->phys[index]; - } - - return NULL; -} - -static int cdns_sierra_phy_init(struct phy *gphy) -{ - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); - struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev->parent); struct cdns_sierra_data *init_data = phy->init_data; struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals; enum cdns_sierra_phy_type phy_type = ins->phy_type; @@ -443,10 +427,11 @@ static int cdns_sierra_phy_init(struct phy *gphy) return 0; } -static int cdns_sierra_phy_on(struct phy *gphy) +static int cdns_sierra_link_on(struct phy *gphy) { - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); - struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent); + struct udevice *dev = gphy->dev; u32 val; int ret; @@ -503,16 +488,16 @@ static int cdns_sierra_phy_on(struct phy *gphy) return ret; } -static int cdns_sierra_phy_off(struct phy *gphy) +static int cdns_sierra_link_off(struct phy *gphy) { - struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); + struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev); return reset_assert_bulk(ins->lnk_rst); } -static int cdns_sierra_phy_reset(struct phy *gphy) +static int cdns_sierra_link_reset(struct phy *gphy) { - struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev); + struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent); reset_control_assert(sp->phy_rst); reset_control_deassert(sp->phy_rst); @@ -520,10 +505,10 @@ static int cdns_sierra_phy_reset(struct phy *gphy) }; static const struct phy_ops ops = { - .init = cdns_sierra_phy_init, - .power_on = cdns_sierra_phy_on, - .power_off = cdns_sierra_phy_off, - .reset = cdns_sierra_phy_reset, + .init = cdns_sierra_link_init, + .power_on = cdns_sierra_link_on, + .power_off = cdns_sierra_link_off, + .reset = cdns_sierra_link_reset, }; struct cdns_sierra_pll_mux_sel { @@ -580,7 +565,7 @@ static const struct clk_ops cdns_sierra_pll_mux_ops = { .set_parent = cdns_sierra_pll_mux_set_parent, }; -int cdns_sierra_pll_mux_probe(struct udevice *dev) +static int cdns_sierra_pll_mux_probe(struct udevice *dev) { struct cdns_sierra_pll_mux *priv = dev_get_priv(dev); struct cdns_sierra_phy *sp = dev_get_priv(dev->parent); @@ -1012,9 +997,8 @@ static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp, return 0; } -static int cdns_sierra_bind_link_nodes(struct cdns_sierra_phy *sp) +static int cdns_sierra_phy_bind(struct udevice *dev) { - struct udevice *dev = sp->dev; struct driver *link_drv; ofnode child; int rc; @@ -1079,6 +1063,7 @@ U_BOOT_DRIVER(sierra_phy_link) = { .name = "sierra_phy_link", .id = UCLASS_PHY, .probe = cdns_sierra_link_probe, + .ops = &ops, .priv_auto = sizeof(struct cdns_sierra_inst), }; @@ -1141,10 +1126,6 @@ static int cdns_sierra_phy_probe(struct udevice *dev) } sp->autoconf = dev_read_bool(dev, "cdns,autoconf"); - /* Binding link nodes as children to serdes */ - ret = cdns_sierra_bind_link_nodes(sp); - if (ret) - goto clk_disable; dev_info(dev, "sierra probed\n"); return 0; @@ -1971,10 +1952,10 @@ static const struct udevice_id cdns_sierra_id_table[] = { U_BOOT_DRIVER(sierra_phy_provider) = { .name = "cdns,sierra", - .id = UCLASS_PHY, + .id = UCLASS_MISC, .of_match = cdns_sierra_id_table, .probe = cdns_sierra_phy_probe, .remove = cdns_sierra_phy_remove, - .ops = &ops, + .bind = cdns_sierra_phy_bind, .priv_auto = sizeof(struct cdns_sierra_phy), }; From f4466ab9cc6bccaf08932a442c1711a7e508ac09 Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Fri, 4 Mar 2022 17:45:26 +0530 Subject: [PATCH 75/78] board: ti: j721e: evm.c: Fix the probing of in Sierra SerDes0 Initialization and power on operations of links have been moved under the link device in the Sierra SerDes driver. Also, the UCLASS of sierra_phy_provider has been changed to UCLASS_MISC. Therefore, fix the probing of SerDes0 instance accordingly. Signed-off-by: Aswath Govindraju Reviewed-by: Georgi Vlaev --- board/ti/j721e/evm.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c index f479197e72..e6ff54c065 100644 --- a/board/ti/j721e/evm.c +++ b/board/ti/j721e/evm.c @@ -397,36 +397,34 @@ void configure_serdes_torrent(void) void configure_serdes_sierra(void) { - struct udevice *dev, *lnk_dev; - struct phy serdes; + struct udevice *dev, *link_dev; + struct phy link; int ret, count, i; + int link_count = 0; if (!IS_ENABLED(CONFIG_PHY_CADENCE_SIERRA)) return; - ret = uclass_get_device_by_driver(UCLASS_PHY, + ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(sierra_phy_provider), &dev); if (ret) printf("Sierra init failed:%d\n", ret); - serdes.dev = dev; - serdes.id = 0; - count = device_get_child_count(dev); for (i = 0; i < count; i++) { - ret = device_get_child(dev, i, &lnk_dev); + ret = device_get_child(dev, i, &link_dev); if (ret) printf("probe of sierra child node %d failed\n", i); + if (link_dev->driver->id == UCLASS_PHY) { + link.dev = link_dev; + link.id = link_count++; + + ret = generic_phy_power_on(&link); + if (ret) + printf("phy_power_on failed !!\n"); + } } - - ret = generic_phy_init(&serdes); - if (ret) - printf("phy_init failed!!\n"); - - ret = generic_phy_power_on(&serdes); - if (ret) - printf("phy_power_on failed !!\n"); } #ifdef CONFIG_BOARD_LATE_INIT From a95f05a6edc6e4ffe1882f2796cea2ec63537ecb Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 4 Mar 2022 16:30:08 +0000 Subject: [PATCH 76/78] vexpress64: fvp: Fix automatic boot Commit 90f262a6951f ("vexpress64: Clean up BASE_FVP boot configuration") cleaned up the usage of default address variables, but missed to update the address for the kernel in the FVP's bootcmd definition. Change ${kernel_addr} to read ${kernel_addr_r} to bring back the automated boot for the fastmodel. Also use "setenv" instead of the potentially ambiguous "set" on the way. Fixes: 90f262a6951f ("vexpress64: Clean up BASE_FVP boot configuration") Signed-off-by: Andre Przywara --- configs/vexpress_aemv8a_semi_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig index 82a5b52f1e..448d012e1c 100644 --- a/configs/vexpress_aemv8a_semi_defconfig +++ b/configs/vexpress_aemv8a_semi_defconfig @@ -17,7 +17,7 @@ CONFIG_ANDROID_BOOT_IMAGE=y CONFIG_BOOTDELAY=1 CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9" -CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then set bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; set fdt_high 0xffffffffffffffff; set initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr - $fdt_addr_r; fi" +CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then setenv bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; setenv fdt_high 0xffffffffffffffff; setenv initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr_r}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr_r - $fdt_addr_r; fi" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_SYS_PROMPT="VExpress64# " From 3ec38c907ccb6cb2110b75f4c3dcd01021a98f6b Mon Sep 17 00:00:00 2001 From: Soeren Moch Date: Mon, 14 Mar 2022 09:26:25 +0100 Subject: [PATCH 77/78] board: tbs2910: Enable Link Time Optimizations in defconfig This saves about 12 kBytes image size and helps to stay within the size limit. Suggested-by: Tom Rini Signed-off-by: Soeren Moch --- configs/tbs2910_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index e1278f2e70..8a33160564 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -14,6 +14,7 @@ CONFIG_DEFAULT_DEVICE_TREE="imx6q-tbs2910" CONFIG_PRE_CON_BUF_ADDR=0x7c000000 CONFIG_CMD_HDMIDETECT=y CONFIG_AHCI=y +CONFIG_LTO=y CONFIG_SUPPORT_RAW_INITRD=y CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTCOMMAND=y From c149bf41404e34014e37de32fac332892b11bd4a Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 14 Mar 2022 16:39:08 -0400 Subject: [PATCH 78/78] Prepare v2022.04-rc4 Signed-off-by: Tom Rini --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f8f3f24641..8e2441ecb1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ VERSION = 2022 PATCHLEVEL = 04 SUBLEVEL = -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = # *DOCUMENTATION*