[RFC 0/5] rockchip_sfc: add support for Rockchip SFC

From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
1) I don't know the best way to upstream the XTX25F128B flash chip. This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
2) The Rockchip SFC driver itself (as it is mostly as-is from the BSP U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

From: Chris Morgan macromorgan@hotmail.com
This patch adds support for the Rockchip serial flash controller found on the PX30 SoC. It should work the same for all SoCs which use the same serial flash controller IP (referred to as the v3).
This is adapted from the SPI subsystem driver from Rockchip's BSP U-boot package. I made a few small changes to get it working on my board.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++++++++++++++++++ 3 files changed, 661 insertions(+) create mode 100644 drivers/spi/rockchip_sfc.c
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 1494c91763..bef36f2931 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -312,6 +312,14 @@ config RENESAS_RPC_SPI on Renesas RCar Gen3 SoCs. This uses driver model and requires a device tree binding to operate.
+config ROCKCHIP_SFC + bool "Rockchip SFC Driver" + help + Enable the Rockchip SFC Driver for SPI NOR flash. This device is + a limited purpose SPI controller for driving NOR flash on certain + Rockchip SoCs. This uses driver model and requires a device tree + binding to operate. + config ROCKCHIP_SPI bool "Rockchip SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index cfe4fae1d4..f02e84b5f1 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_PIC32_SPI) += pic32_spi.o obj-$(CONFIG_PL022_SPI) += pl022_spi.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_RENESAS_RPC_SPI) += renesas_rpc_spi.o +obj-$(CONFIG_ROCKCHIP_SFC) += rockchip_sfc.o obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o diff --git a/drivers/spi/rockchip_sfc.c b/drivers/spi/rockchip_sfc.c new file mode 100644 index 0000000000..d865fedc34 --- /dev/null +++ b/drivers/spi/rockchip_sfc.c @@ -0,0 +1,652 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SFC Driver for Rockchip + * + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + * Yifeng.zhao, Software Engineering, zhao0116@gmail.com. + */ + +#include <common.h> +#include <bouncebuf.h> +#include <clk.h> +#include <cpu_func.h> +#include <dm.h> +#include <dt-structs.h> +#include <errno.h> +#include <spi.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <asm/cache.h> +#include <asm/io.h> +#include <dm/pinctrl.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef SFC_DEBUG +#define SFC_DBG printf +#else +#define SFC_DBG(args...) +#endif + +struct rockchip_sfc_reg { + u32 ctrl; + u32 imr; + u32 iclr; + u32 ftlr; + u32 rcvr; + u32 ax; + u32 abit; + u32 isr; + u32 fsr; + u32 sr; + u32 risr; + u32 ver; + u32 reserved[20]; + u32 dmatr; + u32 dmaaddr; + u32 len_ctrl; + u32 len_ext; + u32 reserved1[28]; + u32 cmd; + u32 addr; + u32 data; +}; + +check_member(rockchip_sfc_reg, data, 0x108); + +/*SFC_CTRL*/ +#define SFC_DATA_WIDTH_SHIFT 12 +#define SFC_DATA_WIDTH_MASK GENMASK(13, 12) +#define SFC_ADDR_WIDTH_SHIFT 10 +#define SFC_ADDR_WIDTH_MASK GENMASK(11, 10) +#define SFC_CMD_WIDTH_SHIFT 8 +#define SFC_CMD_WIDTH_MASK GENMASK(9, 8) +#define SFC_DATA_SHIFT_NEGETIVE BIT(1) + +/*SFC_CMD*/ +#define SFC_DUMMY_BITS_SHIFT 8 +#define SFC_RW_SHIFT 12 +#define SFC_WR 1 +#define SFC_RD 0 +#define SFC_ADDR_BITS_SHIFT 14 +#define SFC_ADDR_BITS_MASK GENMASK(15, 14) +#define SFC_ADDR_0BITS 0 +#define SFC_ADDR_24BITS 1 +#define SFC_ADDR_32BITS 2 +#define SFC_ADDR_XBITS 3 +#define SFC_TRB_SHIFT (16) +#define SFC_TRB_MASK GENMASK(29, 16) + +/* Dma start trigger signal. Auto cleared after write */ +#define SFC_DMA_START BIT(0) + +#define SFC_RESET BIT(0) + +/*SFC_FSR*/ +#define SFC_RXLV_SHIFT (16) +#define SFC_RXLV_MASK GENMASK(20, 16) +#define SFC_TXLV_SHIFT (8) +#define SFC_TXLV_MASK GENMASK(12, 8) +#define SFC_RX_FULL BIT(3) /* rx fifo full */ +#define SFC_RX_EMPTY BIT(2) /* rx fifo empty */ +#define SFC_TX_EMPTY BIT(1) /* tx fifo empty */ +#define SFC_TX_FULL BIT(0) /* tx fifo full */ + +#define SFC_BUSY BIT(0) /* sfc busy flag */ + +/*SFC_RISR*/ +#define DMA_FINISH_INT BIT(7) /* dma interrupt */ +#define SPI_ERR_INT BIT(6) /* Nspi error interrupt */ +#define AHB_ERR_INT BIT(5) /* Ahb bus error interrupt */ +#define TRANS_FINISH_INT BIT(4) /* Transfer finish interrupt */ +#define TX_EMPTY_INT BIT(3) /* Tx fifo empty interrupt */ +#define TX_OF_INT BIT(2) /* Tx fifo overflow interrupt */ +#define RX_UF_INT BIT(1) /* Rx fifo underflow interrupt */ +#define RX_FULL_INT BIT(0) /* Rx fifo full interrupt */ + +/* maximum address size permitted by SFC is 16k - 1 */ +#define SFC_MAX_TRB (1024 << 3) + +#define SFC_MAX_RATE (100 * 1000 * 1000) +#define SFC_DEFAULT_RATE (80 * 1000 * 1000) +#define SFC_MIN_RATE (10 * 1000 * 1000) + +enum rockchip_sfc_if_type { + IF_TYPE_STD, + IF_TYPE_DUAL, + IF_TYPE_QUAD, +}; + +struct rockchip_sfc_platdata { + s32 frequency; + fdt_addr_t base; +}; + +struct rockchip_sfc { + struct rockchip_sfc_reg *regbase; + struct clk clk; + unsigned int max_freq; + unsigned int mode; + unsigned int speed_hz; + u32 max_iosize; + u32 cmd; + u32 addr; + u8 addr_bits; + u8 addr_xbits_ext; + u8 dummy_bits; + u8 rw; + u32 trb; + bool fifo_mode; +}; + +static int rockchip_sfc_ofdata_to_platdata(struct udevice *bus) +{ + struct rockchip_sfc_platdata *plat = dev_get_plat(bus); + struct rockchip_sfc *sfc = dev_get_priv(bus); + int ret; + + plat->base = dev_read_addr(bus); + ret = clk_get_by_index(bus, 0, &sfc->clk); + if (ret < 0) { + printf("Could not get clock for %s: %d\n", bus->name, ret); + return ret; + } + + return 0; +} + +static int rockchip_sfc_probe(struct udevice *bus) +{ + struct rockchip_sfc_platdata *plat = dev_get_plat(bus); + struct rockchip_sfc *sfc = dev_get_priv(bus); + struct rockchip_sfc_reg *regs; + struct dm_spi_bus *dm_spi_bus; + + dm_spi_bus = bus->uclass_priv_; + dm_spi_bus->max_hz = plat->frequency; + sfc->regbase = (struct rockchip_sfc_reg *)plat->base; + sfc->max_freq = SFC_MAX_RATE; + sfc->speed_hz = SFC_DEFAULT_RATE; + clk_set_rate(&sfc->clk, sfc->speed_hz); + + regs = sfc->regbase; + sfc->max_iosize = SFC_MAX_TRB; + +/* DMA causes A-TF to fail, disabling it in SPL stage */ +#ifdef CONFIG_SPL_BUILD + sfc->fifo_mode = 1; +#endif + return 0; +} + +static int rockchip_sfc_reset(struct rockchip_sfc *sfc) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + int tbase = get_timer(0); + u32 rcvr; + int ret = 0; + + writel(SFC_RESET, ®s->rcvr); + do { + rcvr = readl(®s->rcvr); + if (get_timer(tbase) > 1000) { + printf("sfc reset timeout\n"); + ret = -ETIMEDOUT; + break; + } + udelay(1); + } while (rcvr); + + writel(0xFFFFFFFF, ®s->iclr); + + debug("sfc reset\n"); + + return ret; +} + +/* The SFC_CTRL register is a global control register, + * when the controller is in busy state(SFC_SR), + * SFC_CTRL cannot be set. + */ +static int rockchip_sfc_wait_idle(struct rockchip_sfc *sfc, + u32 timeout_ms) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + unsigned long tbase = get_timer(0); + u32 sr, fsr; + + while (1) { + sr = readl(®s->sr); + fsr = readl(®s->fsr); + if ((fsr & SFC_TX_EMPTY) && + (fsr & SFC_RX_EMPTY) && + !(sr & SFC_BUSY)) + break; + if (get_timer(tbase) > timeout_ms) { + printf("wait sfc idle timeout(sr:0x%08x fsr:0x%08x)\n", + sr, fsr); + rockchip_sfc_reset(sfc); + return -ETIMEDOUT; + } + udelay(100); + } + + return 0; +} + +static u8 rockchip_sfc_get_if_type(struct rockchip_sfc *sfc) +{ + int type = IF_TYPE_STD; + + if (sfc->rw == SFC_WR) { + if (sfc->mode & SPI_TX_QUAD) + type = IF_TYPE_QUAD; + else if (sfc->mode & SPI_TX_DUAL) + type = IF_TYPE_DUAL; + else + type = IF_TYPE_STD; + } else { + if (sfc->mode & SPI_RX_QUAD) + type = IF_TYPE_QUAD; + else if (sfc->mode & SPI_RX_DUAL) + type = IF_TYPE_DUAL; + else + type = IF_TYPE_STD; + } + + return type; +} + +static void rockchip_sfc_setup_xfer(struct rockchip_sfc *sfc, u32 trb) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + u32 val; + u8 data_width = IF_TYPE_STD; + + rockchip_sfc_wait_idle(sfc, 10); + + if (sfc->addr_bits == SFC_ADDR_24BITS || + sfc->addr_bits == SFC_ADDR_32BITS) + data_width = rockchip_sfc_get_if_type(sfc); + + SFC_DBG("--- sfc.addr_bit %x\n", sfc->addr_bits); + if (sfc->addr_bits == SFC_ADDR_XBITS) + writel(sfc->addr_xbits_ext - 1, ®s->abit); + + val = 0x02; + val |= (data_width << SFC_DATA_WIDTH_SHIFT); + + SFC_DBG("--- sfc.ctrl %x\n", val); + writel(val, ®s->ctrl); + + val = sfc->cmd; + val |= (trb & 0x3fff) << SFC_TRB_SHIFT; + val |= sfc->rw << SFC_RW_SHIFT; + val |= sfc->addr_bits << SFC_ADDR_BITS_SHIFT; + val |= sfc->dummy_bits << SFC_DUMMY_BITS_SHIFT; + + SFC_DBG("--- sfc.cmd %x\n", val); + writel(val, ®s->cmd); + + if (sfc->addr_bits & SFC_ADDR_XBITS) { + SFC_DBG("--- sfc.addr %x\n", sfc->addr); + writel(sfc->addr, ®s->addr); + } +} + +static int rockchip_sfc_dma_xfer(struct rockchip_sfc *sfc, void *buffer, + size_t trb) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + struct bounce_buffer bb; + unsigned int bb_flags; + int timeout = trb * 1000; + int ret = 0; + int risr; + unsigned long tbase; + + if (sfc->rw == SFC_WR) + bb_flags = GEN_BB_READ; + else + bb_flags = GEN_BB_WRITE; + + ret = bounce_buffer_start(&bb, buffer, trb, bb_flags); + if (ret) + return ret; + + rockchip_sfc_setup_xfer(sfc, bb.len_aligned); + + writel(0xFFFFFFFF, ®s->iclr); + writel((unsigned long)bb.bounce_buffer, ®s->dmaaddr); + writel(SFC_DMA_START, ®s->dmatr); + + tbase = get_timer(0); + do { + udelay(1); + risr = readl(®s->risr); + if (get_timer(tbase) > timeout) { + debug("dma timeout\n"); + ret = -ETIMEDOUT; + break; + } + } while (!(risr & TRANS_FINISH_INT)); + + writel(0xFFFFFFFF, ®s->iclr); + + bounce_buffer_stop(&bb); + + return ret; +} + +static int rockchip_sfc_wait_fifo_ready(struct rockchip_sfc *sfc, int rw, + u32 timeout) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + unsigned long tbase = get_timer(0); + u8 level; + u32 fsr; + + do { + fsr = readl(®s->fsr); + if (rw == SFC_WR) + level = (fsr & SFC_TXLV_MASK) >> SFC_TXLV_SHIFT; + else + level = (fsr & SFC_RXLV_MASK) >> SFC_RXLV_SHIFT; + if (get_timer(tbase) > timeout) { + printf("SFC FIFO Timeout\n"); + return -ETIMEDOUT; + } + udelay(1); + } while (!level); + + return level; +} + +static int rockchip_sfc_write_fifo(struct rockchip_sfc *sfc, u32 *buf, u32 len) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + u32 bytes = len & 0x3; + u32 words = len >> 2; + int tx_level = 0; + u32 val = 0; + u8 count; + + while (words) { + tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_WR, 1000); + if (tx_level <= 0) + return tx_level; + count = min(words, (u32)tx_level); + writesl(®s->data, buf, count); + buf += count; + words -= count; + } + + /* handle the last non 4byte aligned bytes */ + if (bytes) { + tx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_WR, 1000); + if (tx_level <= 0) + return tx_level; + memcpy(&val, buf, bytes); + writel(val, ®s->data); + } + + return 0; +} + +static int rockchip_sfc_read_fifo(struct rockchip_sfc *sfc, u32 *buf, u32 len) +{ + struct rockchip_sfc_reg *regs = sfc->regbase; + u32 bytes = len & 0x3; + u32 words = len >> 2; + int rx_level = 0; + u32 count; + u32 val; + + while (words) { + rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_RD, 1000); + if (rx_level <= 0) + return rx_level; + count = min(words, (u32)rx_level); + readsl(®s->data, buf, count); + buf += count; + words -= count; + } + + /* handle the last non 4 bytes aligned bytes */ + if (bytes) { + rx_level = rockchip_sfc_wait_fifo_ready(sfc, SFC_RD, 1000); + if (rx_level <= 0) + return rx_level; + val = readl(®s->data); + memcpy(buf, &val, bytes); + } + + return 0; +} + +static int rockchip_sfc_pio_xfer(struct rockchip_sfc *sfc, void *buf, u32 len) +{ + int ret = 0; + + rockchip_sfc_setup_xfer(sfc, len); + + if (len) { + if (sfc->rw == SFC_WR) + ret = rockchip_sfc_write_fifo(sfc, (u32 *)buf, len); + else + ret = rockchip_sfc_read_fifo(sfc, (u32 *)buf, len); + } + + return ret; +} + +static int rockchip_sfc_read(struct rockchip_sfc *sfc, u32 offset, + void *buf, size_t len) +{ + u32 dma_trans; + u32 pio_trans; + u32 trb; + u32 bytes; + int ret; + + if (sfc->fifo_mode) { + pio_trans = len; + while (pio_trans) { + trb = min_t(size_t, pio_trans, sfc->max_iosize); + ret = rockchip_sfc_pio_xfer(sfc, buf, trb); + if (ret < 0) + return ret; + pio_trans -= trb; + /* if I don't bit-shift this address, it doesn't work, but I haven't figured out why yet */ + sfc->addr += (trb << 8); + buf += trb; + } + + } else { + if (len >= ARCH_DMA_MINALIGN) { + bytes = len & (ARCH_DMA_MINALIGN - 1); + dma_trans = len - bytes; + } else { + dma_trans = 0; + bytes = len; + } + + while (dma_trans) { + trb = min_t(size_t, dma_trans, sfc->max_iosize); + ret = rockchip_sfc_dma_xfer(sfc, buf, trb); + if (ret < 0) + return ret; + dma_trans -= trb; + /* bit shifting again */ + sfc->addr += (trb << 8); + buf += trb; + } + + /* + * transfer the last non dma aligned byte by pio mode + */ + if (bytes) + ret = rockchip_sfc_pio_xfer(sfc, buf, bytes); + } + + return 0; +} + +static int rockchip_sfc_write(struct rockchip_sfc *sfc, u32 offset, + void *buf, size_t len) +{ + if (len > sfc->max_iosize) { + printf("out of the max sfc trb"); + return -EINVAL; + } + + if (len && !(len & (ARCH_DMA_MINALIGN - 1)) && !sfc->fifo_mode) + return rockchip_sfc_dma_xfer(sfc, buf, len); + else + return rockchip_sfc_pio_xfer(sfc, buf, len); + + return 0; +} + +static int rockchip_sfc_do_xfer(struct rockchip_sfc *sfc, void *buf, size_t len) +{ + if (sfc->rw) + return rockchip_sfc_write(sfc, sfc->addr, buf, len); + else + return rockchip_sfc_read(sfc, sfc->addr, buf, len); +} + +static int rockchip_sfc_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct rockchip_sfc *sfc = dev_get_priv(bus); + int len = bitlen >> 3; + u8 *pcmd = (u8 *)dout; + void *data_buf; + int ret = 0; + + /* I haven't figured out why it's checking the command lengths, that said I only have + * a 128Mb NOR flash chip to test against. + */ + + if (flags & SPI_XFER_BEGIN) { + sfc->cmd = pcmd[0]; + switch (len) { + case 6: /* Nor >16MB 0x6b dummy op */ + sfc->addr_bits = SFC_ADDR_32BITS; + sfc->dummy_bits = 8; + sfc->addr = pcmd[4] | (pcmd[3] << 8) | (pcmd[2] << 16) | (pcmd[1] << 24); + break; + case 5: /* Nor <=16MB 0x6b dummy op, Nor >16MB no dummy op */ + if (sfc->cmd == 0x6b) { + sfc->addr_bits = SFC_ADDR_24BITS; + sfc->dummy_bits = 8; + sfc->addr = pcmd[3] | (pcmd[2] << 8) | (pcmd[1] << 16); + } else { + sfc->addr_bits = SFC_ADDR_32BITS; + sfc->dummy_bits = 0; + sfc->addr = pcmd[4] | (pcmd[3] << 8) | (pcmd[2] << 16) | + (pcmd[1] << 24); + } + break; + case 4: /* Nand erase and read, Nor <=16MB no dummy op */ + sfc->addr_bits = SFC_ADDR_24BITS; + sfc->dummy_bits = 0; + sfc->addr = pcmd[3] | (pcmd[2] << 8) | (pcmd[1] << 16); + break; + case 3: /* Nand prog, */ + sfc->addr_bits = SFC_ADDR_XBITS; + sfc->addr_xbits_ext = 16; + sfc->dummy_bits = 0; + sfc->addr = pcmd[2] | pcmd[1] << 8; + break; + case 2: /* Nand read/write feature */ + sfc->addr_bits = SFC_ADDR_XBITS; + sfc->addr_xbits_ext = 8; + sfc->dummy_bits = 0; + sfc->addr = pcmd[1]; + break; + default: /* Nand/Nor Read/Write status */ + sfc->addr_bits = SFC_ADDR_0BITS; + sfc->dummy_bits = 0; + sfc->addr = 0; + break; + } + SFC_DBG("%s %d %x %d %d %x\n", __func__, len, sfc->cmd, + sfc->addr_bits, sfc->dummy_bits, sfc->addr); + } + if (flags & SPI_XFER_END) { + if (din) { + sfc->rw = SFC_RD; + data_buf = din; + } else { + sfc->rw = SFC_WR; + data_buf = (void *)dout; + } + + if (flags == (SPI_XFER_BEGIN | SPI_XFER_END)) { + len = 0; + data_buf = NULL; + } + + if (sfc->cmd == 0x9f && len == 4) { + /* SPI Nand read id */ + sfc->addr_bits = SFC_ADDR_XBITS; + sfc->addr_xbits_ext = 8; + sfc->dummy_bits = 0; + sfc->addr = 0; + ((u8 *)data_buf)[0] = 0xff; + ret = rockchip_sfc_do_xfer(sfc, &((u8 *)data_buf)[1], 3); + } else { + ret = rockchip_sfc_do_xfer(sfc, data_buf, len); + } + } + + return ret; +} + +static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) +{ + struct rockchip_sfc *sfc = dev_get_priv(bus); + + if (speed > sfc->max_freq) + speed = sfc->max_freq; + + sfc->speed_hz = speed; + clk_set_rate(&sfc->clk, sfc->speed_hz); + SFC_DBG("%s clk= %ld\n", __func__, clk_get_rate(&sfc->clk)); + + return 0; +} + +static int rockchip_sfc_set_mode(struct udevice *bus, uint mode) +{ + struct rockchip_sfc *sfc = dev_get_priv(bus); + + sfc->mode = mode; + + return 0; +} + +static const struct dm_spi_ops rockchip_sfc_ops = { + .xfer = rockchip_sfc_xfer, + .set_speed = rockchip_sfc_set_speed, + .set_mode = rockchip_sfc_set_mode, +}; + +static const struct udevice_id rockchip_sfc_ids[] = { + { .compatible = "rockchip,sfc" }, + { } +}; + +U_BOOT_DRIVER(rockchip_sfc_driver) = { + .name = "rockchip_sfc", + .id = UCLASS_SPI, + .of_match = rockchip_sfc_ids, + .ops = &rockchip_sfc_ops, + .of_to_plat = rockchip_sfc_ofdata_to_platdata, + .plat_auto = sizeof(struct rockchip_sfc_platdata), + .priv_auto = sizeof(struct rockchip_sfc), + .probe = rockchip_sfc_probe, +};

From: Chris Morgan macromorgan@hotmail.com
This patch adds support for setting the correct pin configuration for the Rockchip Serial Flash Controller found on the PX30.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- arch/arm/mach-rockchip/px30/px30.c | 64 ++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c index 6fcef63c1b..8674e815da 100644 --- a/arch/arm/mach-rockchip/px30/px30.c +++ b/arch/arm/mach-rockchip/px30/px30.c @@ -51,6 +51,57 @@ struct mm_region *mem_map = px30_mem_map;
#define QOS_PRIORITY_LEVEL(h, l) ((((h) & 3) << 8) | ((l) & 3))
+/* GRF_GPIO1AL_IOMUX */ +enum { + GPIO1A3_SHIFT = 12, + GPIO1A3_MASK = 0xf << GPIO1A3_SHIFT, + GPIO1A3_GPIO = 0, + GPIO1A3_FLASH_D3, + GPIO1A3_EMMC_D3, + GPIO1A3_SFC_SIO3, + + GPIO1A2_SHIFT = 8, + GPIO1A2_MASK = 0xf << GPIO1A2_SHIFT, + GPIO1A2_GPIO = 0, + GPIO1A2_FLASH_D2, + GPIO1A2_EMMC_D2, + GPIO1A2_SFC_SIO2, + + GPIO1A1_SHIFT = 4, + GPIO1A1_MASK = 0xf << GPIO1A1_SHIFT, + GPIO1A1_GPIO = 0, + GPIO1A1_FLASH_D1, + GPIO1A1_EMMC_D1, + GPIO1A1_SFC_SIO1, + + GPIO1A0_SHIFT = 0, + GPIO1A0_MASK = 0xf << GPIO1A0_SHIFT, + GPIO1A0_GPIO = 0, + GPIO1A0_FLASH_D0, + GPIO1A0_EMMC_D0, + GPIO1A0_SFC_SIO0, +}; + +/* GRF_GPIO1AH_IOMUX */ +enum { + GPIO1A4_SHIFT = 0, + GPIO1A4_MASK = 0xf << GPIO1A4_SHIFT, + GPIO1A4_GPIO = 0, + GPIO1A4_FLASH_D4, + GPIO1A4_EMMC_D4, + GPIO1A4_SFC_CSN0, +}; + +/* GRF_GPIO1BL_IOMUX */ +enum { + GPIO1B1_SHIFT = 4, + GPIO1B1_MASK = 0xf << GPIO1B1_SHIFT, + GPIO1B1_GPIO = 0, + GPIO1B1_FLASH_RDY, + GPIO1B1_EMMC_CLKOUT, + GPIO1B1_SFC_CLK, +}; + /* GRF_GPIO1BH_IOMUX */ enum { GPIO1B7_SHIFT = 12, @@ -193,6 +244,19 @@ int arch_cpu_init(void) GPIO1D4_SDMMC_D2 << GPIO1D4_SHIFT); #endif
+#ifdef CONFIG_ROCKCHIP_SFC + rk_clrsetreg(&grf->gpio1al_iomux, + GPIO1A3_MASK | GPIO1A2_MASK | GPIO1A1_MASK | GPIO1A0_MASK, + GPIO1A3_SFC_SIO3 << GPIO1A3_SHIFT | + GPIO1A2_SFC_SIO2 << GPIO1A2_SHIFT | + GPIO1A1_SFC_SIO1 << GPIO1A1_SHIFT | + GPIO1A0_SFC_SIO0 << GPIO1A0_SHIFT); + rk_clrsetreg(&grf->gpio1ah_iomux, GPIO1A4_MASK, + GPIO1A4_SFC_CSN0 << GPIO1A4_SHIFT); + rk_clrsetreg(&grf->gpio1bl_iomux, GPIO1B1_MASK, + GPIO1B1_SFC_CLK << GPIO1B1_SHIFT); +#endif + #endif
/* Enable PD_VO (default disable at reset) */

From: Chris Morgan macromorgan@hotmail.com
Add the serial flash controller to the devicetree for the PX30.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- arch/arm/dts/px30.dtsi | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi index b6c79e7ed3..aaa8ae2235 100644 --- a/arch/arm/dts/px30.dtsi +++ b/arch/arm/dts/px30.dtsi @@ -960,6 +960,18 @@ status = "disabled"; };
+ sfc: sfc@ff3a0000 { + compatible = "rockchip,sfc"; + reg = <0x0 0xff3a0000 0x0 0x4000>; + interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_SFC>, <&cru HCLK_SFC>; + clock-names = "clk_sfc", "hclk_sfc"; + pinctrl-names = "default"; + pinctrl-0 = <&sfc_clk &sfc_cs &sfc_bus4>; + power-domains = <&power PX30_PD_MMC_NAND>; + status = "disabled"; + }; + gpu: gpu@ff400000 { compatible = "rockchip,px30-mali", "arm,mali-bifrost"; reg = <0x0 0xff400000 0x0 0x4000>; @@ -1926,6 +1938,32 @@ }; };
+ serial_flash { + sfc_bus4: sfc-bus4 { + rockchip,pins = + <1 RK_PA0 3 &pcfg_pull_none>, + <1 RK_PA1 3 &pcfg_pull_none>, + <1 RK_PA2 3 &pcfg_pull_none>, + <1 RK_PA3 3 &pcfg_pull_none>; + }; + + sfc_bus2: sfc-bus2 { + rockchip,pins = + <1 RK_PA0 3 &pcfg_pull_none>, + <1 RK_PA1 3 &pcfg_pull_none>; + }; + + sfc_cs: sfc-cs { + rockchip,pins = + <1 RK_PA4 3 &pcfg_pull_none>; + }; + + sfc_clk: sfc-clk { + rockchip,pins = + <1 RK_PB1 3 &pcfg_pull_none>; + }; + }; + lcdc { lcdc_rgb_dclk_pin: lcdc-rgb-dclk-pin { rockchip,pins =

From: Chris Morgan macromorgan@hotmail.com
Adds support for XT25F128B used on Odroid Go Advance. Unfortunately this chip uses a continuation code which I cannot seem to parse, so there are likely going to be collisions with chips that use the same manufacturer/ID.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- drivers/mtd/spi/Kconfig | 6 ++++++ drivers/mtd/spi/spi-nor-ids.c | 8 ++++++++ 2 files changed, 14 insertions(+)
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index f8db8e5213..8c797d1e03 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -162,6 +162,12 @@ config SPI_FLASH_XMC Add support for various XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) SPI flash chips (XM25xxx)
+config SPI_FLASH_XTX + bool "XTX SPI flash support" + help + Add support for various XTX (XTX Technology Limited) + SPI flash chips (XT25xxx). + endif
config SPI_FLASH_USE_4K_SECTORS diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index 2b57797954..78166f408e 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -336,6 +336,14 @@ const struct flash_info spi_nor_ids[] = { /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ { INFO("XM25QH64A", 0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("XM25QH128A", 0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif +#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 | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, #endif { }, };

From: Chris Morgan macromorgan@hotmail.com
The Odroid Go Advance uses a Rockchip Serial Flash Controller with an XT25F128B SPI NOR flash chip. This adds support for both.
Signed-off-by: Chris Morgan macromorgan@hotmail.com --- arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 8 ++++++++ arch/arm/dts/rk3326-odroid-go2.dts | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi index 00767d2abd..7527a6ed0e 100644 --- a/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi +++ b/arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi @@ -57,6 +57,14 @@ u-boot,spl-fifo-mode; };
+&sfc { + u-boot,dm-pre-reloc; +}; + +&spi_flash { + u-boot,dm-pre-reloc; +}; + &uart1 { clock-frequency = <24000000>; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/rk3326-odroid-go2.dts b/arch/arm/dts/rk3326-odroid-go2.dts index 8cd4688c49..eb8a21ce66 100644 --- a/arch/arm/dts/rk3326-odroid-go2.dts +++ b/arch/arm/dts/rk3326-odroid-go2.dts @@ -48,6 +48,14 @@ }; };
+ aliases { + i2c0 = &i2c0; + i2c1 = &i2c1; + serial1 = &uart1; + serial2 = &uart2; + spi0 = &sfc; + }; + gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; @@ -617,6 +625,20 @@ status = "okay"; };
+&sfc { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&sfc_clk &sfc_cs &sfc_bus2>; + status = "okay"; + + spi_flash: xt25f128b@0 { + reg = <0>; + compatible = "xtx,xt25f128b","jedec,spi-nor"; + spi-max-frequency = <108000000>; + }; +}; + &tsadc { status = "okay"; };

Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the signed-off.
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

Hi Chris,
On 2021/6/2 上午12:54, Chris Morgan wrote:
On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
This sounds better, then we can wait for driver with new framework.
Thanks,
- Kever
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

Hi Chris:
It's my honor to read about spi-rockchip-sfc driver from you, and your code has made a big difference to me.
Recently, we happen to be willing to submit the spi-mem rk sfc drivers, and we have tried some of them in the internal process. Compared with the RK internal code, I have the following thoughts on your code: 1) Only support spi-nor, not support spi-nand 2) Only support rx_dual, tx_quad, not support tx_dual, tx_quad 3) Some of the code may be further simplified, such as "rockchip_sfc_register_all" 4) Some of the logic may be further simplified, such as "rockchip_sfc_init" 5) Doesn't support SFC ver4 ver5 althought witch is compatibled with lower version
In order to support all these features, I adjust the drivers on the basis of your code witch is attach to these mail, these drivers have been test in linux 5.10 rk3568 board, and I'm still doing more strict tests.
So I suggest that we complete it together, or we may consider transferring it to me for submission If I have the honor.
I'm still unfamiliar with the community culture. I hope I didn't offend you. If I have, I'll say sorry in advance. Best wishes.
jon.lin@rock-chips.com
From: Kever Yang Date: 2021-06-02 09:27 To: Chris Morgan CC: u-boot; heiko.stuebner; vigneshr; jagan; sjg; Chris Morgan; 赵仪峰; 林鼎强 Subject: Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC Hi Chris,
On 2021/6/2 上午12:54, Chris Morgan wrote:
On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the
signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
This sounds better, then we can wait for driver with new framework.
Thanks,
- Kever
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

On Fri, Jun 04, 2021 at 09:42:18PM +0800, 林鼎强 wrote:
Hi Chris:
It's my honor to read about spi-rockchip-sfc driver from you, and your code has made a big difference to me.
Recently, we happen to be willing to submit the spi-mem rk sfc drivers, and we have tried some of them in the internal process. Compared with the RK internal code, I have the following thoughts on your code:
- Only support spi-nor, not support spi-nand
- Only support rx_dual, tx_quad, not support tx_dual, tx_quad
- Some of the code may be further simplified, such as "rockchip_sfc_register_all"
- Some of the logic may be further simplified, such as "rockchip_sfc_init"
- Doesn't support SFC ver4 ver5 althought witch is compatibled with lower version
In order to support all these features, I adjust the drivers on the basis of your code witch is attach to these mail, these drivers have been test in linux 5.10 rk3568 board, and I'm still doing more strict tests.
So I suggest that we complete it together, or we may consider transferring it to me for submission If I have the honor.
I'm still unfamiliar with the community culture. I hope I didn't offend you. If I have, I'll say sorry in advance. Best wishes.
I am absolutely fine with you taking this on, and will be happy to help you in any way I can. I only started working on support for this because I wanted it supported in both Linux and U-Boot mainline, and didn't see any progress being made (so I thought I would do it myself). Basically, my goal all along has been to ensure the Odroid Go Advance is fully supported in mainline Linux (and U-boot), and that requires we get the audio (done), SFC (in progress), crypto, battery, charger, and everything else (done) supported.
I trust you are better able to develop/test this than I am, as I only have access to some technical documents and a single PX30 based device to test this on.
Please CC me when you are ready to submit upstream to Linux and U-boot and I will happily test it on my hardware. If you don't have a U-boot driver in progress let me know and I can start working on one.
Thank you.
jon.lin@rock-chips.com
From: Kever Yang Date: 2021-06-02 09:27 To: Chris Morgan CC: u-boot; heiko.stuebner; vigneshr; jagan; sjg; Chris Morgan; 赵仪峰; 林鼎强 Subject: Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC Hi Chris,
On 2021/6/2 上午12:54, Chris Morgan wrote:
On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the
signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
This sounds better, then we can wait for driver with new framework.
Thanks,
- Kever
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

On 6/4/21 10:40 PM, Chris Morgan wrote:
On Fri, Jun 04, 2021 at 09:42:18PM +0800, 林鼎强 wrote:
Hi Chris:
It's my honor to read about spi-rockchip-sfc driver from you, and your code has made a big difference to me.
Recently, we happen to be willing to submit the spi-mem rk sfc drivers, and we have tried some of them in the internal process. Compared with the RK internal code, I have the following thoughts on your code:
- Only support spi-nor, not support spi-nand
- Only support rx_dual, tx_quad, not support tx_dual, tx_quad
- Some of the code may be further simplified, such as "rockchip_sfc_register_all"
- Some of the logic may be further simplified, such as "rockchip_sfc_init"
- Doesn't support SFC ver4 ver5 althought witch is compatibled with lower version
In order to support all these features, I adjust the drivers on the basis of your code witch is attach to these mail, these drivers have been test in linux 5.10 rk3568 board, and I'm still doing more strict tests.
So I suggest that we complete it together, or we may consider transferring it to me for submission If I have the honor.
I'm still unfamiliar with the community culture. I hope I didn't offend you. If I have, I'll say sorry in advance. Best wishes.
I am absolutely fine with you taking this on, and will be happy to help you in any way I can. I only started working on support for this because I wanted it supported in both Linux and U-Boot mainline, and didn't see any progress being made (so I thought I would do it myself). Basically, my goal all along has been to ensure the Odroid Go Advance is fully supported in mainline Linux (and U-boot), and that requires we get the audio (done), SFC (in progress), crypto, battery, charger, and everything else (done) supported.
I trust you are better able to develop/test this than I am, as I only have access to some technical documents and a single PX30 based device to test this on.
Please CC me when you are ready to submit upstream to Linux and U-boot and I will happily test it on my hardware. If you don't have a U-boot driver in progress let me know and I can start working on one.
Thank you.
I'm glad to receive your reply and your understanding so soon. I'll talk about my plan directly. If there is no obvious objection,I'll go on with it.
Firstly, I will submit the support for the my first version of Linux drivers next week which is base on your series submission.
After browsing your submission, there will be the following changes: 1) [RFC,v4,1/8] change with the "Rob Herring" comment 2) [RFC,v4,2/8] update driver 3) All dt patches, make a little change to compatible with RK SDK
[RFC,v4,8/8] arm64: dts: rockchip: Enable SFC for Odroid Go Advance [RFC,v4,7/8] arm64: dts: rockchip: Add SFC to RK3308 [RFC,v4,6/8] arm: dts: rockchip: Add SFC to RV1108 [RFC,v4,5/8] arm: dts: rockchip: Add SFC to RK3036 [RFC,v4,4/8] clk: rockchip: Add support for hclk_sfc on rk3036 [RFC,v4,3/8] arm64: dts: rockchip: Add SFC to PX30 [RFC,v4,2/8] spi: rockchip-sfc: add rockchip serial flash controller [RFC,v4,1/8] dt-bindings: rockchip-sfc: Bindings for Rockchip serial flash controller
Secondly, Keep devolop uboot drivers base on your serieas submission https://patchwork.ozlabs.org/project/uboot/list//?series=245724 submit the code under uboot as soon as possible.
Finally I'll keep focus on the new comments about all these linux patches,then fix it until they are merged.
Best wishes.
jon.lin@rock-chips.com
From: Kever Yang Date: 2021-06-02 09:27 To: Chris Morgan CC: u-boot; heiko.stuebner; vigneshr; jagan; sjg; Chris Morgan; 赵仪峰; 林鼎强 Subject: Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC Hi Chris,
On 2021/6/2 上午12:54, Chris Morgan wrote:
On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the
signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
This sounds better, then we can wait for driver with new framework.
Thanks,
- Kever
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c

On Sat, Jun 05, 2021 at 03:37:01PM +0800, Jon Lin wrote:
On 6/4/21 10:40 PM, Chris Morgan wrote:
On Fri, Jun 04, 2021 at 09:42:18PM +0800, 林鼎强 wrote:
Hi Chris:
It's my honor to read about spi-rockchip-sfc driver from you, and your code has made a big difference to me.
Recently, we happen to be willing to submit the spi-mem rk sfc drivers, and we have tried some of them in the internal process. Compared with the RK internal code, I have the following thoughts on your code:
- Only support spi-nor, not support spi-nand
- Only support rx_dual, tx_quad, not support tx_dual, tx_quad
- Some of the code may be further simplified, such as "rockchip_sfc_register_all"
- Some of the logic may be further simplified, such as "rockchip_sfc_init"
- Doesn't support SFC ver4 ver5 althought witch is compatibled with lower version
In order to support all these features, I adjust the drivers on the basis of your code witch is attach to these mail, these drivers have been test in linux 5.10 rk3568 board, and I'm still doing more strict tests.
So I suggest that we complete it together, or we may consider transferring it to me for submission If I have the honor.
I'm still unfamiliar with the community culture. I hope I didn't offend you. If I have, I'll say sorry in advance. Best wishes.
I am absolutely fine with you taking this on, and will be happy to help you in any way I can. I only started working on support for this because I wanted it supported in both Linux and U-Boot mainline, and didn't see any progress being made (so I thought I would do it myself). Basically, my goal all along has been to ensure the Odroid Go Advance is fully supported in mainline Linux (and U-boot), and that requires we get the audio (done), SFC (in progress), crypto, battery, charger, and everything else (done) supported.
I trust you are better able to develop/test this than I am, as I only have access to some technical documents and a single PX30 based device to test this on.
Please CC me when you are ready to submit upstream to Linux and U-boot and I will happily test it on my hardware. If you don't have a U-boot driver in progress let me know and I can start working on one.
Thank you.
I'm glad to receive your reply and your understanding so soon. I'll talk about my plan directly. If there is no obvious objection,I'll go on with it.
Firstly, I will submit the support for the my first version of Linux drivers next week which is base on your series submission.
After browsing your submission, there will be the following changes:
- [RFC,v4,1/8] change with the "Rob Herring" comment
- [RFC,v4,2/8] update driver
- All dt patches, make a little change to compatible with RK SDK
[RFC,v4,8/8] arm64: dts: rockchip: Enable SFC for Odroid Go Advance [RFC,v4,7/8] arm64: dts: rockchip: Add SFC to RK3308 [RFC,v4,6/8] arm: dts: rockchip: Add SFC to RV1108 [RFC,v4,5/8] arm: dts: rockchip: Add SFC to RK3036 [RFC,v4,4/8] clk: rockchip: Add support for hclk_sfc on rk3036 [RFC,v4,3/8] arm64: dts: rockchip: Add SFC to PX30 [RFC,v4,2/8] spi: rockchip-sfc: add rockchip serial flash controller [RFC,v4,1/8] dt-bindings: rockchip-sfc: Bindings for Rockchip serial flash controller
Secondly, Keep devolop uboot drivers base on your serieas submission https://patchwork.ozlabs.org/project/uboot/list//?series=245724 submit the code under uboot as soon as possible.
I'm actually abandoning that series of commits, in favor of one more closely related to the linux driver you're putting in place. I'd like to use the spi-mem framework for U-boot as well. I will pursue it instead and try to have something ready soon. I'm not entirely clear though from this message if you are planning on doing that as well or are asking me to pursue it. I'm entirely okay with you pursuing it, but until you tell me you are I will keep working on it so as to hopefully get something ready for the next pull window.
Finally I'll keep focus on the new comments about all these linux patches,then fix it until they are merged.
Best wishes.
Thank you. As you make changes I will test them and provide my tested-by tag. For now I only have an rk3326 to test them on, but I will do my best to be thorough.
jon.lin@rock-chips.com From: Kever Yang Date: 2021-06-02 09:27 To: Chris Morgan CC: u-boot; heiko.stuebner; vigneshr; jagan; sjg; Chris Morgan; 赵仪峰; 林鼎强 Subject: Re: [RFC 0/5] rockchip_sfc: add support for Rockchip SFC Hi Chris, On 2021/6/2 上午12:54, Chris Morgan wrote:
On Tue, Jun 01, 2021 at 08:22:09PM +0800, Kever Yang wrote:
Add Yifeng from rockchip.
Hi Chris,
First of all, I think you should remain the origin author info in the
signed-off.
Okay, I can do that. Please note that since I submitted this I was asked to redo the upstream linux proposed driver to use the spi-mem framework. I think for now honestly I'd like to abandon this patch and resubmit a little later with one that is more or less the same (using the spi-mem framework) as the Linux driver.
This sounds better, then we can wait for driver with new framework. Thanks,
- Kever
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210528170020.26219-2-...
Hi Yifeng,
Please help to review this driver.
Thanks,
- Kever
On 2021/5/26 上午5:49, Chris Morgan wrote:
From: Chris Morgan macromorgan@hotmail.com
Requesting comments for a proposed patchset for adding the Rockchip serial flash controller to u-boot. The goal of these patches is to enable it for the Odroid Go Advance so that it may eventually boot exclusively from the SFC on mainline U-boot (I have tested this and it works).
The specific help I need with this patch is:
- I don't know the best way to upstream the XTX25F128B flash chip.
This chip uses a continuation code for the manufacturer ID, however I cannot seem to find any way to actually read the continuation code. There is a risk of this driver, used as-is, to collide with another chip which has the same manufacturer ID with a different continuation code.
- The Rockchip SFC driver itself (as it is mostly as-is from the BSP
U-Boot sources) supports SPI NAND and chips of varying sizes, but my implementation only permits me to test with a single 128Mb flash chip. The driver itself does some checking on the bitlen in the routine rockchip_sfc_xfer() which is what is called for the dm_spi_ops.xfer. I'm not sure if there is a better way to do this. Additionally, I have to bit-shift the address written to the SFC as I suspect the value is meant to be left justified, but I never tested it further.
Additionally, it might be worth mentioning but I noticed the Rockchip BROM will only boot the TPL/SPL off of the SFC if I write it to address 0x10000. This is not documented and different than the address looked at for SD card booting (512 * 64 = 0x8000 for SD Card booting). Also, like the SD card driver I can confirm that if DMA is enabled at the SPL stage A-TF seems to fail silently, then when Linux loads it hangs. There is an ifdef to force FIFO mode only in the SPL stage.
Tested: Read (works) Write (works if you write to an erased sector) Erase (works) SPL Read (works if you edit the u-boot,spl-boot-order)
Chris Morgan (5): spi: rockchip_sfc: add support for Rockchip SFC rockchip: px30: Add support for using SFC rockchip: px30: add the serial flash controller mtd: spi-nor-ids: Add XTX XT25F128B rockchip: px30: add support for SFC for Odroid Go Advance
arch/arm/dts/px30.dtsi | 38 ++ arch/arm/dts/rk3326-odroid-go2-u-boot.dtsi | 10 +- arch/arm/dts/rk3326-odroid-go2.dts | 22 + arch/arm/mach-rockchip/px30/px30.c | 64 ++ drivers/mtd/spi/Kconfig | 6 + drivers/mtd/spi/spi-nor-ids.c | 8 + drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/rockchip_sfc.c | 652 +++++++++++++++++++++ 9 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/rockchip_sfc.c
participants (4)
-
Chris Morgan
-
Jon Lin
-
Kever Yang
-
林鼎强