[U-Boot] [PATCH 0/3] mtd: spi: Add MSCC SPI flash driver

This patch series adds MSCC SPI flash driver. The VCore III SoCs can access directly the flash through memory, this direct mapping is working only for read functions. The other operations are going through SPI driver.
This improves the read performace by a factor of 4.75.
This patch series is based on u-boot-mips/next.
Horatiu Vultur (3): mtd: spi: export functions to sf_internal.h mtd: spi: add MSCC SPI flash driver mips: mscc: use MSCC SPI flash driver for Luton
MAINTAINERS | 1 + arch/mips/dts/luton_pcb090.dts | 3 +- arch/mips/dts/luton_pcb091.dts | 3 +- configs/mscc_luton_defconfig | 1 + drivers/mtd/spi/Kconfig | 8 +++++ drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/sf_internal.h | 8 +++++ drivers/mtd/spi/sf_mscc_flash.c | 76 +++++++++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 8 ++--- drivers/mtd/spi/spi_flash.c | 4 +-- 10 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 drivers/mtd/spi/sf_mscc_flash.c

Expose the following functions: clean_bar, write_bar, spi_flash_std_write, spi_flash_std_erase and spi_flash_std_probe to sf_internal.h to be able to reuse them.
Cc: Jagan Teki jagan@amarulasolutions.com Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_probe.c | 8 ++++---- drivers/mtd/spi/spi_flash.c | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 46a5044..69968c5 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -224,6 +224,14 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, size_t len, void *data);
+int clean_bar(struct spi_flash *flash); +int write_bar(struct spi_flash *flash, u32 offset); + +int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, + const void *buf); +int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len); +int spi_flash_std_probe(struct udevice *dev); + #ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 00f8558..4ddb3ce 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -100,8 +100,8 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); }
-static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) +int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, + const void *buf) { struct spi_flash *flash = dev_get_uclass_priv(dev);
@@ -117,7 +117,7 @@ static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, return spi_flash_cmd_write_ops(flash, offset, len, buf); }
-static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) +int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) { struct spi_flash *flash = dev_get_uclass_priv(dev);
@@ -131,7 +131,7 @@ static int spi_flash_std_get_sw_write_prot(struct udevice *dev) return spi_flash_cmd_get_sw_write_prot(flash); }
-static int spi_flash_std_probe(struct udevice *dev) +int spi_flash_std_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 0c2392f..536f0a1 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -133,7 +133,7 @@ int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash) * Otherwise, the BA24 bit may be left set and then after reset, the * ROM would read/write/erase SPL from 16 MiB * bank_sel address. */ -static int clean_bar(struct spi_flash *flash) +int clean_bar(struct spi_flash *flash) { u8 cmd, bank_sel = 0;
@@ -145,7 +145,7 @@ static int clean_bar(struct spi_flash *flash) return spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); }
-static int write_bar(struct spi_flash *flash, u32 offset) +int write_bar(struct spi_flash *flash, u32 offset) { u8 cmd, bank_sel; int ret;

Am 16.01.19 um 13:07 schrieb Horatiu Vultur:
Expose the following functions: clean_bar, write_bar, spi_flash_std_write, spi_flash_std_erase and spi_flash_std_probe to sf_internal.h to be able to reuse them.
Cc: Jagan Teki jagan@amarulasolutions.com Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com
drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_probe.c | 8 ++++---- drivers/mtd/spi/spi_flash.c | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-)
maybe you should wait with this series as there is on-going work to import spi-nor from Linux [1]
[1] https://lists.denx.de/pipermail/u-boot/2018-December/350565.html

Hi Daniel,
The 01/16/2019 15:07, Daniel Schwierzeck wrote:
Am 16.01.19 um 13:07 schrieb Horatiu Vultur:
Expose the following functions: clean_bar, write_bar, spi_flash_std_write, spi_flash_std_erase and spi_flash_std_probe to sf_internal.h to be able to reuse them.
Cc: Jagan Teki jagan@amarulasolutions.com Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com
drivers/mtd/spi/sf_internal.h | 8 ++++++++ drivers/mtd/spi/sf_probe.c | 8 ++++---- drivers/mtd/spi/spi_flash.c | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-)
maybe you should wait with this series as there is on-going work to import spi-nor from Linux [1]
[1] https://lists.denx.de/pipermail/u-boot/2018-December/350565.html
That is perfectly fine for me, I will submit another patch after the spi-nor series is accepted. Thank you.
--
- Daniel

The VCore III SoCs can directly access flash through memory. The SPI controller takes care of changing a memory access to a flash access. Therefore the flash can be accessed using memcpy functions.
The direct mapping is supported only by the read functions. All the other access are going through the SPI driver.
Using this driver improves the read throughput by a factor of 4.75.
Cc: Jagan Teki jagan@amarulasolutions.com Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- MAINTAINERS | 1 + drivers/mtd/spi/Kconfig | 8 +++++ drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/sf_mscc_flash.c | 76 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 drivers/mtd/spi/sf_mscc_flash.c
diff --git a/MAINTAINERS b/MAINTAINERS index 3fa5d3e..a2b100e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -527,6 +527,7 @@ F: board/mscc/ F: configs/mscc* F: drivers/gpio/mscc_sgpio.c F: drivers/spi/mscc_bb_spi.c +F: drivers/mtd/spi/sf_mscc_flash.c F: include/configs/vcoreiii.h F: drivers/pinctrl/mscc/
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 76d5a1d..0f8db82 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -34,6 +34,14 @@ config SPI_FLASH
If unsure, say N
+config MSCC_SPI_FLASH + bool "MSCC SPI Flash driver" + depends on SPI_FLASH + help + Enable MSCC SPI flash driver. This driver uses direct mapping + during read operations, regular SPI transfer otherwise. It is + using CONFIG_SPI_FLASH_BAR to access high end of +16MB flash. + config SPI_FLASH_BAR bool "SPI flash Bank/Extended address register support" depends on SPI_FLASH diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index b4c7e1c..3ae1860 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif
obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o spi_flash_ids.o sf.o +obj-$(CONFIG_MSCC_SPI_FLASH) += sf_mscc_flash.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o diff --git a/drivers/mtd/spi/sf_mscc_flash.c b/drivers/mtd/spi/sf_mscc_flash.c new file mode 100644 index 0000000..4a5376b --- /dev/null +++ b/drivers/mtd/spi/sf_mscc_flash.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Microsemi Corporation + */ + +#include <common.h> +#include <spi.h> +#include <spi_flash.h> + +#include "sf_internal.h" + +#define MSCC_FLASH_MASK GENMASK(24, 0) + +static int mscc_spi_flash_read(struct udevice *dev, u32 offset, size_t len, + void *data) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + struct spi_slave *spi = flash->spi; + u32 remain_len, read_len, read_addr; + int bank_sel = 0; + int ret = -1; + + while (len) { + read_addr = offset; + +#ifdef CONFIG_SPI_FLASH_BAR + ret = write_bar(flash, read_addr); + if (ret < 0) + return ret; + bank_sel = flash->bank_curr; +#endif + remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * + (bank_sel + 1)) - offset; + if (len < remain_len) + read_len = len; + else + read_len = remain_len; + + if (spi->max_read_size) + read_len = min(read_len, spi->max_read_size); + + memcpy(data, + flash->memory_map + (read_addr & MSCC_FLASH_MASK), + read_len); + + offset += read_len; + len -= read_len; + data += read_len; + } + +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(flash); +#endif + + return ret; +} + +static const struct dm_spi_flash_ops mscc_spi_flash_ops = { + .read = mscc_spi_flash_read, + .write = spi_flash_std_write, + .erase = spi_flash_std_erase, +}; + +static const struct udevice_id mscc_spi_flash_ids[] = { + { .compatible = "mscc,luton-spi-flash" }, + { } +}; + +U_BOOT_DRIVER(sf_mscc_flash) = { + .name = "sf_mscc_flash", + .id = UCLASS_SPI_FLASH, + .of_match = mscc_spi_flash_ids, + .probe = spi_flash_std_probe, + .priv_auto_alloc_size = sizeof(struct spi_flash), + .ops = &mscc_spi_flash_ops, +};

Update Luton DT and defconfig to use the new MSCC SPI flash driver.
Signed-off-by: Horatiu Vultur horatiu.vultur@microchip.com --- arch/mips/dts/luton_pcb090.dts | 3 ++- arch/mips/dts/luton_pcb091.dts | 3 ++- configs/mscc_luton_defconfig | 1 + 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/mips/dts/luton_pcb090.dts b/arch/mips/dts/luton_pcb090.dts index 951d8da..55cf609 100644 --- a/arch/mips/dts/luton_pcb090.dts +++ b/arch/mips/dts/luton_pcb090.dts @@ -48,7 +48,8 @@ &spi0 { status = "okay"; spi-flash@0 { - compatible = "spi-flash"; + compatible = "mscc,luton-spi-flash", "spi-flash"; + memory-map = <0x40000000 0x2000000>; spi-max-frequency = <18000000>; /* input clock */ reg = <0>; /* CS0 */ spi-cs-high; diff --git a/arch/mips/dts/luton_pcb091.dts b/arch/mips/dts/luton_pcb091.dts index bf638b2..fe1d332 100644 --- a/arch/mips/dts/luton_pcb091.dts +++ b/arch/mips/dts/luton_pcb091.dts @@ -54,7 +54,8 @@ &spi0 { status = "okay"; spi-flash@0 { - compatible = "spi-flash"; + compatible = "mscc,luton-spi-flash", "spi-flash"; + memory-map = <0x40000000 0x2000000>; spi-max-frequency = <18000000>; /* input clock */ reg = <0>; /* CS0 */ spi-cs-high; diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig index 7154e97..9e3efa1 100644 --- a/configs/mscc_luton_defconfig +++ b/configs/mscc_luton_defconfig @@ -69,3 +69,4 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_MSCC_BB_SPI=y CONFIG_LZMA=y +CONFIG_MSCC_SPI_FLASH=y
participants (2)
-
Daniel Schwierzeck
-
Horatiu Vultur