[PATCH 0/4] mtd: spi: arm: rk3399: rock-pi-4: u-boot/next Support SPI NOR Flash in Rock Pi 4 (XTX xt25f32b)

The Radxa Rock Pi 4 board is sold from revision 1.4 with a soldered 4Mb SPI NOR Flash. This series allows to use it from U-Boot and boot from it.
This series applies to u-boot/next. I have patches for master I can send if requested. I can for custodian trees, but i'd need to adapt and retest.
I'm not sure other people will need all of the patches. It may depend on what other components are in use. I needed them and I'm sending them thinking they'd improve U-Boot, but I'm new here so it's likely I'm overseeing something. You may of course take all, some or none of them.
I've tested with flashrom on linux-libre 5.15.42 (/dev/mtd0) with this patch applied to the kernel. (not all of it would be needed, just for "full disclosure" on tests)
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi index 100a76916..7fdb22a85 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi @@ -14,6 +14,13 @@ aliases { mmc0 = &sdmmc; mmc1 = &sdhci; + spi0 = &spi0; + spi1 = &spi1; + spi2 = &spi2; + spi3 = &spi3; + spi4 = &spi4; + spi5 = &spi5; + };
chosen { @@ -128,6 +135,12 @@ regulator-max-microvolt = <1400000>; vin-supply = <&vcc5v0_sys>; }; + + sound { + compatible = "audio-graph-card"; + label = "rockchip,rk33999"; + dais = <&i2s0_p0>; + }; };
&cpu_l0 { @@ -419,9 +432,28 @@ };
&i2c1 { - i2c-scl-rising-time-ns = <300>; i2c-scl-falling-time-ns = <15>; - status = "okay"; + i2c-scl-rising-time-ns = <300>; + status = "okay"; + + es8316: codec@11 { + compatible = "everest,es8316"; + reg = <0x11>; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + pinctrl-names = "default"; + pinctrl-0 = <&hp_det_pin>; + interrupt-parent = <&gpio1>; + interrupts = <RK_PA1 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s0_p0_0>; + }; + }; + }; + };
&i2c3 { @@ -441,6 +473,15 @@ rockchip,capture-channels = <2>; rockchip,playback-channels = <2>; status = "okay"; + + i2s0_p0: port { + i2s0_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; + };
&i2s1 { @@ -481,6 +522,7 @@ vpcie1v8-supply = <&vcc_1v8>; vpcie3v3-supply = <&vcc3v3_pcie>; status = "okay"; + max-link-speed = <2>; };
&pinctrl { @@ -500,7 +542,7 @@
pcie { pcie_pwr_en: pcie-pwr-en { - rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up_20ma>; }; };
@@ -556,6 +598,20 @@ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + es8316 { + hp_det_pin: hp-det-pin { + rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + i2s0 { + i2s_8ch_mclk_pin: i2s-8ch-mclk-pin { + rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>; + }; + }; + + };
&pwm2 { @@ -596,6 +652,7 @@ };
&sdhci { + max-frequency = <150000000>; bus-width = <8>; mmc-hs400-1_8v; mmc-hs400-enhanced-strobe; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts index 6c63e6170..c04fee0f5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4b.dts @@ -44,3 +44,29 @@ pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>; }; }; + +&spi1 { + max-freq = <40000000>; + status = "okay"; + + spiflash: spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <40000000>; + spi-cpol; + spi-cpha; + + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + + loader@0 { + label = "loader"; + reg = <0x0 0x400000>; + }; + }; + }; +}; \ No newline at end of file diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index 6b904e439..e344077e3 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -17,6 +17,7 @@ spi-nor-objs += sst.o spi-nor-objs += winbond.o spi-nor-objs += xilinx.o spi-nor-objs += xmc.o +spi-nor-objs += xtx.o obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_MTD_SPI_NOR) += controllers/ diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index cc08bd707..7ab768309 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -1846,6 +1846,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = { &spi_nor_winbond, &spi_nor_xilinx, &spi_nor_xmc, + &spi_nor_xtx, };
static const struct flash_info * diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 3348e1dd1..fd2771fbe 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -489,6 +489,7 @@ extern const struct spi_nor_manufacturer spi_nor_sst; extern const struct spi_nor_manufacturer spi_nor_winbond; extern const struct spi_nor_manufacturer spi_nor_xilinx; extern const struct spi_nor_manufacturer spi_nor_xmc; +extern const struct spi_nor_manufacturer spi_nor_xtx;
extern const struct attribute_group *spi_nor_sysfs_groups[];
diff --git a/drivers/mtd/spi-nor/xtx.c b/drivers/mtd/spi-nor/xtx.c new file mode 100644 index 000000000..3db8bfd93 --- /dev/null +++ b/drivers/mtd/spi-nor/xtx.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022, Xavier Drudis Ferran + * (based on eon.c from this directory + * and drivers/mtd/spi-nor/spi-nor.c from https://github.com/radxa/kernel.git ) + */ + +#include <linux/mtd/spi-nor.h> + +#include "core.h" + +static const struct flash_info xtx_parts[] = { + /* XTX -- xt25xxx */ + { "xt25f32b", INFO(0x0b4016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ) }, + { "xt25f128b", INFO(0x0b4018, 0, 64 * 1024, 256, SECT_4K) }, +}; + +const struct spi_nor_manufacturer spi_nor_xtx = { + .name = "xtx", + .parts = xtx_parts, + .nparts = ARRAY_SIZE(xtx_parts), +};

Radxa Rock Pi 4B from version 1.4 on carries a 4MiB XTX Technology Inc 25F32B SPI NOR Flash. (previous versions had pads where users could solder different chips).
Add its parameters to spi-nor-ids.c so U-Boot can discover it and (after further changes) we can boot from SPI.
Note that the Flash is declared to be dual and quad capable because the datasheet [4] says so but I couldn't try it because in Rock Pi 4 it is not wired for QuadSPI, and rk3399 does not seem to support dual SPI either (or I couldn't find any register to configure spi1tx and spi1rx as bidirectional).
But the same Flash part could be used as in quad or dual model in some other board.
Likewise locks are in the datasheet but untested.
The part has been added to downstream U-Boot [1] and linux [2] [3].
Cc: Jagan Teki jagan@amarulasolutions.com Cc: Vignesh R vigneshr@ti.com
Link: [1] https://github.com/armbian/build/commit/c41cb4c454570127ad3238f6b901fbf3aa77... Link: [2] https://github.com/radxa/kernel/blob/release-4.4-rockpi4/drivers/mtd/spi-nor... Link: [3] https://github.com/radxa/kernel/commit/8216f17965de7bc7ced7092aab0e2bfe16838... Link: [4] https://www.xtxtech.com/download/?AId=157
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat --- drivers/mtd/spi/spi-nor-ids.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 20cd4d7fc9..e65c8e7dfc 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -388,6 +388,9 @@ const struct flash_info spi_nor_ids[] = { #ifdef CONFIG_SPI_FLASH_XTX /* XTX Technology (Shenzhen) Limited */ { INFO("xt25f128b", 0x0b4018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { INFO("xt25f32b", 0x0b4016, 0, 64 * 1024, 64, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ + | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_SST26LOCK) }, #endif { }, };

Configure Rock Pi 4 to boot from SPI NOR Flash.
Based on flash chip, board documentation and tests, this is the fastest I could use it.
This seems to be the minimum necessary configuration for Rock Pi 4 to be able to boot from SPI NOR Flash.
With the next patch, it works to sf probe 1:0, sf read, sf erase, sf write, sf read and then boot linux and flashrom can write to it. Sometimes flashrom seems to fail to write when at U-Boot stage there was no sf read or write, not sure why.
Cc: Simon Glass sjg@chromium.org Cc: Philipp Tomsich philipp.tomsich@vrull.eu Cc: Kever Yang kever.yang@rock-chips.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat --- arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi | 18 ++++++++++++++++++ configs/rock-pi-4-rk3399_defconfig | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+)
diff --git a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi index c17e769f64..0755fa4ed6 100644 --- a/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi +++ b/arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi @@ -15,3 +15,21 @@ &vdd_log { regulator-init-microvolt = <950000>; }; + +&spi1 { + status = "okay"; + spi-max-frequency = <40000000>; + spi-activate-delay = <12000>; /* 12 ms */ + + norflash: flash@0 { + compatible = "rockchip,spidev", "jedec,spi-nor"; + reg = <0>; + + spi-max-frequency = <40000000>; + spi-cpha; + spi-cpol; + + status = "okay"; + u-boot,dm-pre-reloc; + }; +}; \ No newline at end of file diff --git a/configs/rock-pi-4-rk3399_defconfig b/configs/rock-pi-4-rk3399_defconfig index eb5778dc17..7c3a2a3c5c 100644 --- a/configs/rock-pi-4-rk3399_defconfig +++ b/configs/rock-pi-4-rk3399_defconfig @@ -13,6 +13,8 @@ CONFIG_BOOTSTAGE_STASH_ADDR=0x3fbd0000 CONFIG_DEBUG_UART_BASE=0xFF1A0000 CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_ENV_OFFSET_REDUND=0x3e0000 +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI=y CONFIG_SYS_LOAD_ADDR=0x800800 CONFIG_DEBUG_UART=y CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y @@ -36,6 +38,12 @@ CONFIG_SPL_BSS_MAX_SIZE=0x2000 CONFIG_SPL_STACK=0x400000 CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 +CONFIG_SPL_MTD_SUPPORT=y +# CONFIG_SPL_SPI_FLASH_TINY is not set +CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y +CONFIG_SPL_SPI_FLASH_MTD=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SYS_SPI_U_BOOT_OFFS=0xb0000 CONFIG_TPL=y CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y @@ -57,21 +65,35 @@ CONFIG_MMC_DW=y CONFIG_MMC_DW_ROCKCHIP=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_MTD=y +CONFIG_DM_MTD=y +CONFIG_SF_DEFAULT_MODE=0x3 +CONFIG_SF_DEFAULT_SPEED=40000000 +CONFIG_SPI_FLASH_SFDP_SUPPORT=y +CONFIG_SPI_FLASH_SOFT_RESET=y +CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y +CONFIG_SPI_FLASH_XTX=y +CONFIG_SPI_FLASH_MTD=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y CONFIG_NVME_PCI=y CONFIG_PCI=y +CONFIG_SPL_PHY=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_DM_PMIC_FAN53555=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y +CONFIG_SPL_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_GPIO=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM_RK3399_LPDDR4=y CONFIG_DM_RESET=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_ROCKCHIP_SPI=y CONFIG_SYSRESET=y CONFIG_USB=y CONFIG_USB_XHCI_HCD=y

This Flash part does not use octal mode. But soft reset seems to be required to boot from SPI NOR Flash in Rock Pi 4B.
Cc: Jagan Teki jagan@amarulasolutions.com Cc: Vignesh R vigneshr@ti.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat --- drivers/mtd/spi/spi-nor-core.c | 54 ++++++++++++++++++++++++++++++---- include/linux/mtd/spi-nor.h | 5 ++++ 2 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 3b7c817c02..d6e7067320 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3526,6 +3526,19 @@ static struct spi_nor_fixups mt35xu512aba_fixups = { }; #endif /* CONFIG_SPI_FLASH_MT35XU */
+#ifdef CONFIG_SPI_FLASH_XTX +static void xtx25f32b_post_sfdp_fixup(struct spi_nor *nor, + struct spi_nor_flash_parameter *params) +{ + nor->flags |= SNOR_F_SOFT_RESET; + nor->reset_proto = SNOR_PROTO_1_1_1; /* at least for Rock Pi 4 */ +} + +static struct spi_nor_fixups xtx25f32b_fixups = { + .post_sfdp = xtx25f32b_post_sfdp_fixup, +}; +#endif + /** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed * @nor: pointer to a 'struct spi_nor' * @@ -3625,7 +3638,7 @@ static int spi_nor_soft_reset(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DATA); - spi_nor_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR); + spi_nor_setup_op(nor, &op, nor->reset_proto ? nor->reset_proto : SNOR_PROTO_8_8_8_DTR); ret = spi_mem_exec_op(nor->spi, &op); if (ret) { dev_warn(nor->dev, "Software reset enable failed: %d\n", ret); @@ -3636,7 +3649,7 @@ static int spi_nor_soft_reset(struct spi_nor *nor) SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DATA); - spi_nor_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR); + spi_nor_setup_op(nor, &op, nor->reset_proto ? nor->reset_proto : SNOR_PROTO_8_8_8_DTR); ret = spi_mem_exec_op(nor->spi, &op); if (ret) { dev_warn(nor->dev, "Software reset failed: %d\n", ret); @@ -3656,16 +3669,34 @@ out: } #endif /* CONFIG_SPI_FLASH_SOFT_RESET */
+#ifdef CONFIG_SPI_FLASH_SOFT_RESET +static bool flash_supports_proto(const struct flash_info *flash, enum spi_nor_protocol proto) +{ + switch (spi_nor_get_protocol_data_nbits(proto)) { + case 8: + return flash->flags & (spi_nor_protocol_is_dtr(proto) + ? SPI_NOR_OCTAL_DTR_READ + : SPI_NOR_OCTAL_READ); + case 4: return flash->flags & SPI_NOR_QUAD_READ; + case 2: return flash->flags & SPI_NOR_DUAL_READ; + default: + return 1; + } +} + int spi_nor_remove(struct spi_nor *nor) { -#ifdef CONFIG_SPI_FLASH_SOFT_RESET - if (nor->info->flags & SPI_NOR_OCTAL_DTR_READ && + if (flash_supports_proto(nor->info, nor->reset_proto) && nor->flags & SNOR_F_SOFT_RESET) return spi_nor_soft_reset(nor); -#endif - return 0; } +#else +int spi_nor_remove(struct spi_nor *nor) +{ + return 0; +} +#endif
void spi_nor_set_fixups(struct spi_nor *nor) { @@ -3696,6 +3727,11 @@ void spi_nor_set_fixups(struct spi_nor *nor) if (!strcmp(nor->info->name, "mt35xu512aba")) nor->fixups = &mt35xu512aba_fixups; #endif + +#ifdef CONFIG_SPI_FLASH_XTX + if (!strcmp(nor->info->name, "xt25f32b")) + nor->fixups = &xtx25f32b_fixups; +#endif }
int spi_nor_scan(struct spi_nor *nor) @@ -3715,6 +3751,12 @@ int spi_nor_scan(struct spi_nor *nor) nor->reg_proto = SNOR_PROTO_1_1_1; nor->read_proto = SNOR_PROTO_1_1_1; nor->write_proto = SNOR_PROTO_1_1_1; + /** + * XTX25F32B in RockPi 4 seems to need soft reset and can't do octal, + * but we don't know yet whether we have it, and it seems to tolerate + * it until we do. We'll change it later. + */ + nor->reset_proto = SNOR_PROTO_8_8_8_DTR; nor->read = spi_nor_read_data; nor->write = spi_nor_write_data; nor->read_reg = spi_nor_read_reg; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 4ceeae623d..a0d6c19468 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -490,6 +490,8 @@ struct spi_flash { * @read_proto: the SPI protocol for read operations * @write_proto: the SPI protocol for write operations * @reg_proto the SPI protocol for read_reg/write_reg/erase operations + * @reset_proto: The SPI protocol for soft reset to return to state expected + * by OS before running the OS (at remove time) * @cmd_buf: used by the write_reg * @cmd_ext_type: the command opcode extension for DTR mode. * @fixups: flash-specific fixup hooks. @@ -535,6 +537,9 @@ struct spi_nor { enum spi_nor_protocol read_proto; enum spi_nor_protocol write_proto; enum spi_nor_protocol reg_proto; +#if !CONFIG_IS_ENABLED(SPI_FLASH_TINY) + enum spi_nor_protocol reset_proto; +#endif bool sst_write_second; u32 flags; u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];

Trying to boot my Rock Pi 4B from its XTX SPI NOR Flash failed when my custom compiled TF-A had a load address of 0.
The same TF-A booted correctly from MMC.
Add a local variable to spi_mem_exec_op() to determine operation direction, instead of testing rx_buf or tx_buf for null value, so that a buffer at RAM address 0 is accepted.
This commit also cuts short a debug dump of the image loaded to show only the first 0x1000 and the last 0x100 bytes, and not swamping the serial log. When adding the #define DEBUG to the .c file one can change these limits at the same time if they don't fit.
Cc: Jagan Teki jagan@amarulasolutions.com
Signed-off-by: Xavier Drudis Ferran xdrudis@tinet.cat --- drivers/spi/spi-mem.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 9c1ede1b61..4dc90addb3 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -21,6 +21,8 @@ #include <spi.h> #include <spi-mem.h> #include <dm/device_compat.h> +#define DEBUG_DUMP_START_LENGTH 0x1000 +#define DEBUG_DUMP_END_LENGTH 0x100 #endif
#ifndef __UBOOT__ @@ -373,12 +375,21 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) if (msg.actual_length != totalxferlen) return -EIO; #else + enum spi_mem_data_dir dir = SPI_MEM_NO_DATA;
if (op->data.nbytes) { - if (op->data.dir == SPI_MEM_DATA_IN) + dir = op->data.dir; + if (dir == SPI_MEM_DATA_IN) { rx_buf = op->data.buf.in; - else + } else { tx_buf = op->data.buf.out; + /** + * keep old behaviour, to assume SPI_MEM_DATA_OUT + * if ever data.nbytes!=0 but data.dir==SPI_MEM_NO_DATA + * (hopefully never) + */ + dir = SPI_MEM_DATA_OUT; + } }
op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes; @@ -410,7 +421,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) /* 1st transfer: opcode + address + dummy cycles */ flag = SPI_XFER_BEGIN; /* Make sure to set END bit if no tx or rx data messages follow */ - if (!tx_buf && !rx_buf) + if (dir == SPI_MEM_NO_DATA) flag |= SPI_XFER_END;
ret = spi_xfer(slave, op_len * 8, op_buf, NULL, flag); @@ -418,7 +429,7 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) return ret;
/* 2nd transfer: rx or tx data path */ - if (tx_buf || rx_buf) { + if (dir != SPI_MEM_NO_DATA) { ret = spi_xfer(slave, op->data.nbytes * 8, tx_buf, rx_buf, SPI_XFER_END); if (ret) @@ -430,10 +441,17 @@ int spi_mem_exec_op(struct spi_slave *slave, const struct spi_mem_op *op) for (i = 0; i < pos; i++) debug("%02x ", op_buf[i]); debug("| [%dB %s] ", - tx_buf || rx_buf ? op->data.nbytes : 0, - tx_buf || rx_buf ? (tx_buf ? "out" : "in") : "-"); - for (i = 0; i < op->data.nbytes; i++) - debug("%02x ", tx_buf ? tx_buf[i] : rx_buf[i]); + op->data.nbytes, + dir == SPI_MEM_DATA_IN ? "in" : (dir == SPI_MEM_DATA_OUT ? "out" : "-")); + for (i = 0; i < op->data.nbytes && i < DEBUG_DUMP_START_LENGTH ; i++) + debug("%02x ", dir == SPI_MEM_DATA_OUT ? tx_buf[i] : rx_buf[i]); + if (op->data.nbytes > DEBUG_DUMP_END_LENGTH && op->data.nbytes > DEBUG_DUMP_START_LENGTH && + i < op->data.nbytes - DEBUG_DUMP_END_LENGTH) { + debug(" ... "); + i = op->data.nbytes - DEBUG_DUMP_END_LENGTH; + } + for (; i < op->data.nbytes ; i++) + debug("%02x ", dir == SPI_MEM_DATA_OUT ? tx_buf[i] : rx_buf[i]); debug("[ret %d]\n", ret);
if (ret < 0)

El Wed, Jun 22, 2022 at 10:47:31AM +0200, Xavier Drudis Ferran deia:
The Radxa Rock Pi 4 board is sold from revision 1.4 with a soldered 4Mb SPI NOR Flash. This series allows to use it from U-Boot and boot from it.
Hello. Is there any interest in this ?
This weekend I did a v2 on next. But I don't know whether I should send it or just save you all the trouble.
I can boot from SPI (I mean, bootrom loads TPL from SPI, TPL return to bootrom, bootrom loads SPL from SPI, SPL loading U-Boot from SPI, then U-Boot loads linux and dtb from SDMMC) and can stop U-Boot and read, erase and write from SPI, But once I boot linux,
flashrom -V --programmer linux_mtd --write /boot/spi.rom [...] get_mtd_info: device_name: "loader", is_writeable: 1, numeraseregions: 0, total_size: 4194304, erasesize: 4096 Opened /dev/mtd0 successfully The following protocols are supported: Programmer-specific. Probing for Programmer Opaque flash chip, 0 kB: Found Programmer flash chip "Opaque flash chip" (4096 kB, Programmer-specific) on linux_mtd. Found Programmer flash chip "Opaque flash chip" (4096 kB, Programmer-specific). Reading old flash chip contents... done. Erasing and writing flash chip... Trying erase function 0... 0x000000-0x000fff:WCannot write 0x001000 bytes at 0x000000 [...]
If I boot from SDMMC (shorting spiclk to ground) then linux doesn't have a /dev/mtd0 device. But that's easy to fix. If I boot from SDMMC, stop U-boot, disconnect spiclk from gnd, sf probe 1:0 and continue boot then I can write /dev/mtd0 from flashrom in linux without a problem. I can also read, erase and write SPI from U-Boot.
So there's something when booting from SPI that stops linux from writing to it, despite U-Boot can. I tested also sf protect unlock 0 0x400000 but it doesn't help.
So should I send v2 ? wait until I understand what happens when booting from SPI but not writing to /dev/mtd0 ? Forget it ?

On Tue, Jul 12, 2022 at 2:41 PM Xavier Drudis Ferran xdrudis@tinet.cat wrote:
El Wed, Jun 22, 2022 at 10:47:31AM +0200, Xavier Drudis Ferran deia:
The Radxa Rock Pi 4 board is sold from revision 1.4 with a soldered 4Mb SPI NOR Flash. This series allows to use it from U-Boot and boot from it.
Hello. Is there any interest in this ?
This weekend I did a v2 on next. But I don't know whether I should send it or just save you all the trouble.
I can boot from SPI (I mean, bootrom loads TPL from SPI, TPL return to bootrom, bootrom loads SPL from SPI, SPL loading U-Boot from SPI, then U-Boot loads linux and dtb from SDMMC) and can stop U-Boot and read, erase and write from SPI, But once I boot linux,
flashrom -V --programmer linux_mtd --write /boot/spi.rom [...] get_mtd_info: device_name: "loader", is_writeable: 1, numeraseregions: 0, total_size: 4194304, erasesize: 4096 Opened /dev/mtd0 successfully The following protocols are supported: Programmer-specific. Probing for Programmer Opaque flash chip, 0 kB: Found Programmer flash chip "Opaque flash chip" (4096 kB, Programmer-specific) on linux_mtd. Found Programmer flash chip "Opaque flash chip" (4096 kB, Programmer-specific). Reading old flash chip contents... done. Erasing and writing flash chip... Trying erase function 0... 0x000000-0x000fff:WCannot write 0x001000 bytes at 0x000000 [...]
If I boot from SDMMC (shorting spiclk to ground) then linux doesn't have a /dev/mtd0 device. But that's easy to fix. If I boot from SDMMC, stop U-boot, disconnect spiclk from gnd, sf probe 1:0 and continue boot then I can write /dev/mtd0 from flashrom in linux without a problem. I can also read, erase and write SPI from U-Boot.
So there's something when booting from SPI that stops linux from writing to it, despite U-Boot can. I tested also sf protect unlock 0 0x400000 but it doesn't help.
So should I send v2 ? wait until I understand what happens when booting from SPI but not writing to /dev/mtd0 ? Forget it ?
We have SPI flash boot tested on existing boards, so please send the associate patches if you want to support for rock-pi-4.
Thanks, Jagan.
participants (2)
-
Jagan Teki
-
Xavier Drudis Ferran