2018-06-27 13:29:53

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 0/6] New QuadSPI driver for Atmel SAMA5D2

Hello,

Atmel SAMA5D2 is equipped with two QSPI interfaces. These interfaces can
work as in SPI-compatible mode or use two / four lines to improve
communication speed. At the moment there is QSPI driver strongly tied to
NOR-flash memory and MTD subsystem.
Intention of this change is to provide new driver which will not be tied
to MTD and allows using QSPI with NAND-flash memory or other peripherals
New spi-mem API provides abstraction layer which can disconnect QSPI
from MTD. This driver doesn't support regular SPI interface, it should
be used with spi-mem interface only.
Unfortunately SAMA5D2 hardware by default supports only NOR-flash
memory. It allows 24- and 32-bit addressing while NAND-flash requires
16-bit long. To workaround hardware limitation driver is a bit more
complicated.

Request to spi-mem contains three fiels: opcode (command), address,
dummy bytes. SAMA5D2 QSPI hardware supports opcode, address, dummy and
option byte where address field can only be 24- or 32- bytes long.
Handling 8-bits long addresses is done using option field. For 16-bits
address behaviour depends of number of requested dummy bits. If there
are 8 or more dummy cycles, address is shifted and sent with first dummy
byte. Otherwise opcode is disabled and first byte of address contains
command opcode (works only if opcode and address use the same buswidth).
The limitation is when 16-bit address is used without enough dummy
cycles and opcode is using different buswidth than address. Other modes
are supported with described workaround.

It looks like hardware has some limitation in performance. The same issue
exists in current QSPI driver (MTD/nor-flash) and soft-pack (bare-metal
library from Atmel). Without using DMA read speed is much worse than
maximum bandwidth (efficiency 30-40%). Any help with performance
improvement is highly welcome, especially for NAND-flash memories which
offers higher capacity than NOR-flash used with previous driver.

Best Regards,
Piotr

v2 changes:
- driver is now replacement of existing atmel-quadspi
- code was re-written to follow original code structure
- deinitialization order fixed
- empty atmel_qspi_adjust_op_size function removed
- code formatting fixes
- use spi_device->max_speed_hz to get spi speed
- spi freqency set in spi_controller->setup() hook
- address range checkng for 4-bytes addressing
- use timeout to avoid infinite waiting

Piotr Bugalski (6):
mtd: spi-nor: atmel-quaspi: Typo fix
mtd: spi-nor: atmel-quadspi: Add spi-mem support to atmel-quadspi
mtd: spi-nor: atmel-quadspi: Use spi-mem interface for atmel-quadspi
driver
mtd: spi-nor: atmel-quadspi: Remove unused code from atmel-quadspi
driver
spi: Add QuadSPI driver for Atmel SAMA5D2
dt-bindings: spi: QuadSPI driver for Atmel SAMA5D2

.../bindings/{mtd => spi}/atmel-quadspi.txt | 0
drivers/mtd/spi-nor/Kconfig | 9 -
drivers/mtd/spi-nor/Makefile | 1 -
drivers/spi/Kconfig | 9 +
drivers/spi/Makefile | 1 +
drivers/{mtd/spi-nor => spi}/atmel-quadspi.c | 529 ++++++---------------
6 files changed, 155 insertions(+), 394 deletions(-)
rename Documentation/devicetree/bindings/{mtd => spi}/atmel-quadspi.txt (100%)
rename drivers/{mtd/spi-nor => spi}/atmel-quadspi.c (52%)

--
2.11.0



2018-06-27 13:28:14

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 6/6] dt-bindings: spi: QuadSPI driver for Atmel SAMA5D2

Atmel SAMA5D2 QuadSPI driver was moved from mtd to spi subsystem,
this change is just moving DT-binding documentation.

Suggested-by: Boris Brezillon <[email protected]>
Signed-off-by: Piotr Bugalski <[email protected]>
---
Documentation/devicetree/bindings/{mtd => spi}/atmel-quadspi.txt | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename Documentation/devicetree/bindings/{mtd => spi}/atmel-quadspi.txt (100%)

diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt b/Documentation/devicetree/bindings/spi/atmel-quadspi.txt
similarity index 100%
rename from Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
rename to Documentation/devicetree/bindings/spi/atmel-quadspi.txt
--
2.11.0


2018-06-27 13:28:34

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

Kernel contains QSPI driver strongly tied to MTD and nor-flash memory.
New spi-mem interface allows usage also other memory types, especially
much larger NAND with SPI interface. This driver works as SPI controller
and is not related to MTD, however can work with NAND-flash or other
peripherals using spi-mem interface.

Suggested-by: Boris Brezillon <[email protected]>
Signed-off-by: Piotr Bugalski <[email protected]>
---
drivers/mtd/spi-nor/Kconfig | 9 ---------
drivers/mtd/spi-nor/Makefile | 1 -
drivers/spi/Kconfig | 9 +++++++++
drivers/spi/Makefile | 1 +
drivers/{mtd/spi-nor => spi}/atmel-quadspi.c | 0
5 files changed, 10 insertions(+), 10 deletions(-)
rename drivers/{mtd/spi-nor => spi}/atmel-quadspi.c (100%)

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 6cc9c929ff57..44fe8018733c 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -39,15 +39,6 @@ config SPI_ASPEED_SMC
and support for the SPI flash memory controller (SPI) for
the host firmware. The implementation only supports SPI NOR.

-config SPI_ATMEL_QUADSPI
- tristate "Atmel Quad SPI Controller"
- depends on ARCH_AT91 || (ARM && COMPILE_TEST)
- depends on OF && HAS_IOMEM
- help
- This enables support for the Quad SPI controller in master mode.
- This driver does not support generic SPI. The implementation only
- supports SPI NOR.
-
config SPI_CADENCE_QUADSPI
tristate "Cadence Quad SPI controller"
depends on OF && (ARM || ARM64 || COMPILE_TEST)
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index f4c61d282abd..a552efd22958 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_ASPEED_SMC) += aspeed-smc.o
-obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index ad5d68e1dab7..88f9c007d825 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -83,6 +83,15 @@ config SPI_ATMEL
This selects a driver for the Atmel SPI Controller, present on
many AT91 ARM chips.

+config SPI_ATMEL_QUADSPI
+ tristate "Atmel Quad SPI Controller"
+ depends on ARCH_AT91 || (ARM && COMPILE_TEST)
+ depends on OF && HAS_IOMEM
+ help
+ This enables support for the Quad SPI controller in master mode.
+ This driver does not support generic SPI. The implementation only
+ supports spi-mem interface.
+
config SPI_AU1550
tristate "Au1550/Au1200/Au1300 SPI Controller"
depends on MIPS_ALCHEMY
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index cb1f4378b87c..1a08e5bfcee9 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o
obj-$(CONFIG_SPI_ALTERA) += spi-altera.o
obj-$(CONFIG_SPI_ARMADA_3700) += spi-armada-3700.o
obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o
+obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_AXI_SPI_ENGINE) += spi-axi-spi-engine.o
diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
similarity index 100%
rename from drivers/mtd/spi-nor/atmel-quadspi.c
rename to drivers/spi/atmel-quadspi.c
--
2.11.0


2018-06-27 13:30:02

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 3/6] mtd: spi-nor: atmel-quadspi: Use spi-mem interface for atmel-quadspi driver

Previously added spi-mem interface is now used instead of older approach.

Suggested-by: Boris Brezillon <[email protected]>
Signed-off-by: Piotr Bugalski <[email protected]>
---
drivers/mtd/spi-nor/atmel-quadspi.c | 91 ++++++++-----------------------------
1 file changed, 18 insertions(+), 73 deletions(-)

diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/mtd/spi-nor/atmel-quadspi.c
index c36fcecd569a..3c98a3ee480a 100644
--- a/drivers/mtd/spi-nor/atmel-quadspi.c
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -760,27 +760,9 @@ static ssize_t atmel_qspi_read(struct spi_nor *nor, loff_t from, size_t len,

static int atmel_qspi_init(struct atmel_qspi *aq)
{
- unsigned long src_rate;
- u32 mr, scr, scbr;
-
/* Reset the QSPI controller */
qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST);

- /* Set the QSPI controller in Serial Memory Mode */
- mr = QSPI_MR_NBBITS(8) | QSPI_MR_SMM;
- qspi_writel(aq, QSPI_MR, mr);
-
- src_rate = clk_get_rate(aq->clk);
- if (!src_rate)
- return -EINVAL;
-
- /* Compute the QSPI baudrate */
- scbr = DIV_ROUND_UP(src_rate, aq->clk_rate);
- if (scbr > 0)
- scbr--;
- scr = QSPI_SCR_SCBR(scbr);
- qspi_writel(aq, QSPI_SCR, scr);
-
/* Enable the QSPI controller */
qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIEN);

@@ -808,38 +790,25 @@ static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)

static int atmel_qspi_probe(struct platform_device *pdev)
{
- const struct spi_nor_hwcaps hwcaps = {
- .mask = SNOR_HWCAPS_READ |
- SNOR_HWCAPS_READ_FAST |
- SNOR_HWCAPS_READ_1_1_2 |
- SNOR_HWCAPS_READ_1_2_2 |
- SNOR_HWCAPS_READ_2_2_2 |
- SNOR_HWCAPS_READ_1_1_4 |
- SNOR_HWCAPS_READ_1_4_4 |
- SNOR_HWCAPS_READ_4_4_4 |
- SNOR_HWCAPS_PP |
- SNOR_HWCAPS_PP_1_1_4 |
- SNOR_HWCAPS_PP_1_4_4 |
- SNOR_HWCAPS_PP_4_4_4,
- };
- struct device_node *child, *np = pdev->dev.of_node;
+ struct spi_controller *ctrl;
struct atmel_qspi *aq;
struct resource *res;
- struct spi_nor *nor;
- struct mtd_info *mtd;
int irq, err = 0;

- if (of_get_child_count(np) != 1)
- return -ENODEV;
- child = of_get_next_child(np, NULL);
+ ctrl = spi_alloc_master(&pdev->dev, sizeof(*aq));
+ if (!ctrl)
+ return -ENOMEM;

- aq = devm_kzalloc(&pdev->dev, sizeof(*aq), GFP_KERNEL);
- if (!aq) {
- err = -ENOMEM;
- goto exit;
- }
+ ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD;
+ ctrl->setup = atmel_qspi_setup;
+ ctrl->bus_num = -1;
+ ctrl->mem_ops = &atmel_qspi_mem_ops;
+ ctrl->num_chipselect = 1;
+ ctrl->dev.of_node = pdev->dev.of_node;
+ platform_set_drvdata(pdev, ctrl);
+
+ aq = spi_controller_get_devdata(ctrl);

- platform_set_drvdata(pdev, aq);
init_completion(&aq->cmd_completion);
aq->pdev = pdev;

@@ -888,54 +857,30 @@ static int atmel_qspi_probe(struct platform_device *pdev)
if (err)
goto disable_clk;

- /* Setup the spi-nor */
- nor = &aq->nor;
- mtd = &nor->mtd;
-
- nor->dev = &pdev->dev;
- spi_nor_set_flash_node(nor, child);
- nor->priv = aq;
- mtd->priv = nor;
-
- nor->read_reg = atmel_qspi_read_reg;
- nor->write_reg = atmel_qspi_write_reg;
- nor->read = atmel_qspi_read;
- nor->write = atmel_qspi_write;
- nor->erase = atmel_qspi_erase;
-
- err = of_property_read_u32(child, "spi-max-frequency", &aq->clk_rate);
- if (err < 0)
- goto disable_clk;
-
err = atmel_qspi_init(aq);
if (err)
goto disable_clk;

- err = spi_nor_scan(nor, NULL, &hwcaps);
- if (err)
- goto disable_clk;
-
- err = mtd_device_register(mtd, NULL, 0);
+ err = spi_register_controller(ctrl);
if (err)
goto disable_clk;

- of_node_put(child);
-
return 0;

disable_clk:
clk_disable_unprepare(aq->clk);
exit:
- of_node_put(child);
+ spi_controller_put(ctrl);

return err;
}

static int atmel_qspi_remove(struct platform_device *pdev)
{
- struct atmel_qspi *aq = platform_get_drvdata(pdev);
+ struct spi_controller *ctrl = platform_get_drvdata(pdev);
+ struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);

- mtd_device_unregister(&aq->nor.mtd);
+ spi_unregister_controller(ctrl);
qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIDIS);
clk_disable_unprepare(aq->clk);
return 0;
--
2.11.0


2018-06-27 13:31:04

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 1/6] mtd: spi-nor: atmel-quaspi: Typo fix

Just minor typo fix. Fixed in preparation of new driver.

Signed-off: Piotr Bugalski <[email protected]>
---
drivers/mtd/spi-nor/atmel-quadspi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/mtd/spi-nor/atmel-quadspi.c
index 6c5708bacad8..bdbfaa632dbf 100644
--- a/drivers/mtd/spi-nor/atmel-quadspi.c
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -67,7 +67,7 @@
#define QSPI_CR_LASTXFER BIT(24)

/* Bitfields in QSPI_MR (Mode Register) */
-#define QSPI_MR_SSM BIT(0)
+#define QSPI_MR_SMM BIT(0)
#define QSPI_MR_LLB BIT(1)
#define QSPI_MR_WDRBT BIT(2)
#define QSPI_MR_SMRM BIT(3)
@@ -563,7 +563,7 @@ static int atmel_qspi_init(struct atmel_qspi *aq)
qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST);

/* Set the QSPI controller in Serial Memory Mode */
- mr = QSPI_MR_NBBITS(8) | QSPI_MR_SSM;
+ mr = QSPI_MR_NBBITS(8) | QSPI_MR_SMM;
qspi_writel(aq, QSPI_MR, mr);

src_rate = clk_get_rate(aq->clk);
--
2.11.0


2018-06-27 14:10:11

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 4/6] mtd: spi-nor: atmel-quadspi: Remove unused code from atmel-quadspi driver

Code used for previous interface is no longer needed.
This change just removes obsolete code.

Suggested-by: Boris Brezillon <[email protected]>
Signed-off-by: Piotr Bugalski <[email protected]>
---
drivers/mtd/spi-nor/atmel-quadspi.c | 389 ------------------------------------
1 file changed, 389 deletions(-)

diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/mtd/spi-nor/atmel-quadspi.c
index 3c98a3ee480a..f7accccc1e9f 100644
--- a/drivers/mtd/spi-nor/atmel-quadspi.c
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -29,14 +29,8 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/spi-nor.h>
-#include <linux/platform_data/atmel.h>
#include <linux/of.h>
-
#include <linux/io.h>
-#include <linux/gpio.h>
#include <linux/spi/spi-mem.h>

/* QSPI register offsets */
@@ -160,35 +154,9 @@ struct atmel_qspi {
struct clk *clk;
struct platform_device *pdev;
u32 pending;
-
- struct spi_nor nor;
- u32 clk_rate;
struct completion cmd_completion;
};

-struct atmel_qspi_command {
- union {
- struct {
- u32 instruction:1;
- u32 address:3;
- u32 mode:1;
- u32 dummy:1;
- u32 data:1;
- u32 reserved:25;
- } bits;
- u32 word;
- } enable;
- u8 instruction;
- u8 mode;
- u8 num_mode_cycles;
- u8 num_dummy_cycles;
- u32 address;
-
- size_t buf_len;
- const void *tx_buf;
- void *rx_buf;
-};
-
struct qspi_mode {
u8 cmd_buswidth;
u8 addr_buswidth;
@@ -401,363 +369,6 @@ static int atmel_qspi_setup(struct spi_device *spi)
return 0;
}

-static int atmel_qspi_run_transfer(struct atmel_qspi *aq,
- const struct atmel_qspi_command *cmd)
-{
- void __iomem *ahb_mem;
-
- /* Then fallback to a PIO transfer (memcpy() DOES NOT work!) */
- ahb_mem = aq->mem;
- if (cmd->enable.bits.address)
- ahb_mem += cmd->address;
- if (cmd->tx_buf)
- _memcpy_toio(ahb_mem, cmd->tx_buf, cmd->buf_len);
- else
- _memcpy_fromio(cmd->rx_buf, ahb_mem, cmd->buf_len);
-
- return 0;
-}
-
-#ifdef DEBUG
-static void atmel_qspi_debug_command(struct atmel_qspi *aq,
- const struct atmel_qspi_command *cmd,
- u32 ifr)
-{
- u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
- size_t len = 0;
- int i;
-
- if (cmd->enable.bits.instruction)
- cmd_buf[len++] = cmd->instruction;
-
- for (i = cmd->enable.bits.address-1; i >= 0; --i)
- cmd_buf[len++] = (cmd->address >> (i << 3)) & 0xff;
-
- if (cmd->enable.bits.mode)
- cmd_buf[len++] = cmd->mode;
-
- if (cmd->enable.bits.dummy) {
- int num = cmd->num_dummy_cycles;
-
- switch (ifr & QSPI_IFR_WIDTH_MASK) {
- case QSPI_IFR_WIDTH_SINGLE_BIT_SPI:
- case QSPI_IFR_WIDTH_DUAL_OUTPUT:
- case QSPI_IFR_WIDTH_QUAD_OUTPUT:
- num >>= 3;
- break;
- case QSPI_IFR_WIDTH_DUAL_IO:
- case QSPI_IFR_WIDTH_DUAL_CMD:
- num >>= 2;
- break;
- case QSPI_IFR_WIDTH_QUAD_IO:
- case QSPI_IFR_WIDTH_QUAD_CMD:
- num >>= 1;
- break;
- default:
- return;
- }
-
- for (i = 0; i < num; ++i)
- cmd_buf[len++] = 0;
- }
-
- /* Dump the SPI command */
- print_hex_dump(KERN_DEBUG, "qspi cmd: ", DUMP_PREFIX_NONE,
- 32, 1, cmd_buf, len, false);
-
-#ifdef VERBOSE_DEBUG
- /* If verbose debug is enabled, also dump the TX data */
- if (cmd->enable.bits.data && cmd->tx_buf)
- print_hex_dump(KERN_DEBUG, "qspi tx : ", DUMP_PREFIX_NONE,
- 32, 1, cmd->tx_buf, cmd->buf_len, false);
-#endif
-}
-#else
-#define atmel_qspi_debug_command(aq, cmd, ifr)
-#endif
-
-static int atmel_qspi_run_command(struct atmel_qspi *aq,
- const struct atmel_qspi_command *cmd,
- u32 ifr_tfrtyp, enum spi_nor_protocol proto)
-{
- u32 iar, icr, ifr, sr;
- int err = 0;
-
- iar = 0;
- icr = 0;
- ifr = ifr_tfrtyp;
-
- /* Set the SPI protocol */
- switch (proto) {
- case SNOR_PROTO_1_1_1:
- ifr |= QSPI_IFR_WIDTH_SINGLE_BIT_SPI;
- break;
-
- case SNOR_PROTO_1_1_2:
- ifr |= QSPI_IFR_WIDTH_DUAL_OUTPUT;
- break;
-
- case SNOR_PROTO_1_1_4:
- ifr |= QSPI_IFR_WIDTH_QUAD_OUTPUT;
- break;
-
- case SNOR_PROTO_1_2_2:
- ifr |= QSPI_IFR_WIDTH_DUAL_IO;
- break;
-
- case SNOR_PROTO_1_4_4:
- ifr |= QSPI_IFR_WIDTH_QUAD_IO;
- break;
-
- case SNOR_PROTO_2_2_2:
- ifr |= QSPI_IFR_WIDTH_DUAL_CMD;
- break;
-
- case SNOR_PROTO_4_4_4:
- ifr |= QSPI_IFR_WIDTH_QUAD_CMD;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Compute instruction parameters */
- if (cmd->enable.bits.instruction) {
- icr |= QSPI_ICR_INST(cmd->instruction);
- ifr |= QSPI_IFR_INSTEN;
- }
-
- /* Compute address parameters */
- switch (cmd->enable.bits.address) {
- case 4:
- ifr |= QSPI_IFR_ADDRL;
- /* fall through to the 24bit (3 byte) address case. */
- case 3:
- iar = (cmd->enable.bits.data) ? 0 : cmd->address;
- ifr |= QSPI_IFR_ADDREN;
- break;
- case 0:
- break;
- default:
- return -EINVAL;
- }
-
- /* Compute option parameters */
- if (cmd->enable.bits.mode && cmd->num_mode_cycles) {
- u32 mode_cycle_bits, mode_bits;
-
- icr |= QSPI_ICR_OPT(cmd->mode);
- ifr |= QSPI_IFR_OPTEN;
-
- switch (ifr & QSPI_IFR_WIDTH_MASK) {
- case QSPI_IFR_WIDTH_SINGLE_BIT_SPI:
- case QSPI_IFR_WIDTH_DUAL_OUTPUT:
- case QSPI_IFR_WIDTH_QUAD_OUTPUT:
- mode_cycle_bits = 1;
- break;
- case QSPI_IFR_WIDTH_DUAL_IO:
- case QSPI_IFR_WIDTH_DUAL_CMD:
- mode_cycle_bits = 2;
- break;
- case QSPI_IFR_WIDTH_QUAD_IO:
- case QSPI_IFR_WIDTH_QUAD_CMD:
- mode_cycle_bits = 4;
- break;
- default:
- return -EINVAL;
- }
-
- mode_bits = cmd->num_mode_cycles * mode_cycle_bits;
- switch (mode_bits) {
- case 1:
- ifr |= QSPI_IFR_OPTL_1BIT;
- break;
-
- case 2:
- ifr |= QSPI_IFR_OPTL_2BIT;
- break;
-
- case 4:
- ifr |= QSPI_IFR_OPTL_4BIT;
- break;
-
- case 8:
- ifr |= QSPI_IFR_OPTL_8BIT;
- break;
-
- default:
- return -EINVAL;
- }
- }
-
- /* Set number of dummy cycles */
- if (cmd->enable.bits.dummy)
- ifr |= QSPI_IFR_NBDUM(cmd->num_dummy_cycles);
-
- /* Set data enable */
- if (cmd->enable.bits.data) {
- ifr |= QSPI_IFR_DATAEN;
-
- /* Special case for Continuous Read Mode */
- if (!cmd->tx_buf && !cmd->rx_buf)
- ifr |= QSPI_IFR_CRM;
- }
-
- /* Clear pending interrupts */
- (void)qspi_readl(aq, QSPI_SR);
-
- /* Set QSPI Instruction Frame registers */
- atmel_qspi_debug_command(aq, cmd, ifr);
- qspi_writel(aq, QSPI_IAR, iar);
- qspi_writel(aq, QSPI_ICR, icr);
- qspi_writel(aq, QSPI_IFR, ifr);
-
- /* Skip to the final steps if there is no data */
- if (!cmd->enable.bits.data)
- goto no_data;
-
- /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
- (void)qspi_readl(aq, QSPI_IFR);
-
- /* Stop here for continuous read */
- if (!cmd->tx_buf && !cmd->rx_buf)
- return 0;
- /* Send/Receive data */
- err = atmel_qspi_run_transfer(aq, cmd);
-
- /* Release the chip-select */
- qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER);
-
- if (err)
- return err;
-
-#if defined(DEBUG) && defined(VERBOSE_DEBUG)
- /*
- * If verbose debug is enabled, also dump the RX data in addition to
- * the SPI command previously dumped by atmel_qspi_debug_command()
- */
- if (cmd->rx_buf)
- print_hex_dump(KERN_DEBUG, "qspi rx : ", DUMP_PREFIX_NONE,
- 32, 1, cmd->rx_buf, cmd->buf_len, false);
-#endif
-no_data:
- /* Poll INSTRuction End status */
- sr = qspi_readl(aq, QSPI_SR);
- if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
- return err;
-
- /* Wait for INSTRuction End interrupt */
- reinit_completion(&aq->cmd_completion);
- aq->pending = sr & QSPI_SR_CMD_COMPLETED;
- qspi_writel(aq, QSPI_IER, QSPI_SR_CMD_COMPLETED);
- if (!wait_for_completion_timeout(&aq->cmd_completion,
- msecs_to_jiffies(1000)))
- err = -ETIMEDOUT;
- qspi_writel(aq, QSPI_IDR, QSPI_SR_CMD_COMPLETED);
-
- return err;
-}
-
-static int atmel_qspi_read_reg(struct spi_nor *nor, u8 opcode,
- u8 *buf, int len)
-{
- struct atmel_qspi *aq = nor->priv;
- struct atmel_qspi_command cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.enable.bits.instruction = 1;
- cmd.enable.bits.data = 1;
- cmd.instruction = opcode;
- cmd.rx_buf = buf;
- cmd.buf_len = len;
- return atmel_qspi_run_command(aq, &cmd, QSPI_IFR_TFRTYP_TRSFR_READ,
- nor->reg_proto);
-}
-
-static int atmel_qspi_write_reg(struct spi_nor *nor, u8 opcode,
- u8 *buf, int len)
-{
- struct atmel_qspi *aq = nor->priv;
- struct atmel_qspi_command cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.enable.bits.instruction = 1;
- cmd.enable.bits.data = (buf != NULL && len > 0);
- cmd.instruction = opcode;
- cmd.tx_buf = buf;
- cmd.buf_len = len;
- return atmel_qspi_run_command(aq, &cmd, QSPI_IFR_TFRTYP_TRSFR_WRITE,
- nor->reg_proto);
-}
-
-static ssize_t atmel_qspi_write(struct spi_nor *nor, loff_t to, size_t len,
- const u_char *write_buf)
-{
- struct atmel_qspi *aq = nor->priv;
- struct atmel_qspi_command cmd;
- ssize_t ret;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.enable.bits.instruction = 1;
- cmd.enable.bits.address = nor->addr_width;
- cmd.enable.bits.data = 1;
- cmd.instruction = nor->program_opcode;
- cmd.address = (u32)to;
- cmd.tx_buf = write_buf;
- cmd.buf_len = len;
- ret = atmel_qspi_run_command(aq, &cmd, QSPI_IFR_TFRTYP_TRSFR_WRITE_MEM,
- nor->write_proto);
- return (ret < 0) ? ret : len;
-}
-
-static int atmel_qspi_erase(struct spi_nor *nor, loff_t offs)
-{
- struct atmel_qspi *aq = nor->priv;
- struct atmel_qspi_command cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.enable.bits.instruction = 1;
- cmd.enable.bits.address = nor->addr_width;
- cmd.instruction = nor->erase_opcode;
- cmd.address = (u32)offs;
- return atmel_qspi_run_command(aq, &cmd, QSPI_IFR_TFRTYP_TRSFR_WRITE,
- nor->reg_proto);
-}
-
-static ssize_t atmel_qspi_read(struct spi_nor *nor, loff_t from, size_t len,
- u_char *read_buf)
-{
- struct atmel_qspi *aq = nor->priv;
- struct atmel_qspi_command cmd;
- u8 num_mode_cycles, num_dummy_cycles;
- ssize_t ret;
-
- if (nor->read_dummy >= 2) {
- num_mode_cycles = 2;
- num_dummy_cycles = nor->read_dummy - 2;
- } else {
- num_mode_cycles = nor->read_dummy;
- num_dummy_cycles = 0;
- }
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.enable.bits.instruction = 1;
- cmd.enable.bits.address = nor->addr_width;
- cmd.enable.bits.mode = (num_mode_cycles > 0);
- cmd.enable.bits.dummy = (num_dummy_cycles > 0);
- cmd.enable.bits.data = 1;
- cmd.instruction = nor->read_opcode;
- cmd.address = (u32)from;
- cmd.mode = 0xff; /* This value prevents from entering the 0-4-4 mode */
- cmd.num_mode_cycles = num_mode_cycles;
- cmd.num_dummy_cycles = num_dummy_cycles;
- cmd.rx_buf = read_buf;
- cmd.buf_len = len;
- ret = atmel_qspi_run_command(aq, &cmd, QSPI_IFR_TFRTYP_TRSFR_READ_MEM,
- nor->read_proto);
- return (ret < 0) ? ret : len;
-}
-
static int atmel_qspi_init(struct atmel_qspi *aq)
{
/* Reset the QSPI controller */
--
2.11.0


2018-06-27 14:58:24

by Piotr Bugalski

[permalink] [raw]
Subject: [RFC PATCH v2 2/6] mtd: spi-nor: atmel-quadspi: Add spi-mem support to atmel-quadspi

This patch adds new interface to existing driver. New code is not used yet,
it will be enabled later.
Changes are prepared in small steps to keep patches readable.

Suggested-by: Boris Brezillon <[email protected]>
Signed-off-by: Piotr Bugalski <[email protected]>
---
drivers/mtd/spi-nor/atmel-quadspi.c | 205 ++++++++++++++++++++++++++++++++++++
1 file changed, 205 insertions(+)

diff --git a/drivers/mtd/spi-nor/atmel-quadspi.c b/drivers/mtd/spi-nor/atmel-quadspi.c
index bdbfaa632dbf..c36fcecd569a 100644
--- a/drivers/mtd/spi-nor/atmel-quadspi.c
+++ b/drivers/mtd/spi-nor/atmel-quadspi.c
@@ -2,8 +2,10 @@
* Driver for Atmel QSPI Controller
*
* Copyright (C) 2015 Atmel Corporation
+ * Copyright (C) 2018 Cryptera A/S
*
* Author: Cyrille Pitchen <[email protected]>
+ * Author: Piotr Bugalski <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -35,6 +37,7 @@

#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/spi/spi-mem.h>

/* QSPI register offsets */
#define QSPI_CR 0x0000 /* Control Register */
@@ -186,6 +189,23 @@ struct atmel_qspi_command {
void *rx_buf;
};

+struct qspi_mode {
+ u8 cmd_buswidth;
+ u8 addr_buswidth;
+ u8 data_buswidth;
+ u32 config;
+};
+
+static const struct qspi_mode sama5d2_qspi_modes[] = {
+ { 1, 1, 1, QSPI_IFR_WIDTH_SINGLE_BIT_SPI },
+ { 1, 1, 2, QSPI_IFR_WIDTH_DUAL_OUTPUT },
+ { 1, 1, 4, QSPI_IFR_WIDTH_QUAD_OUTPUT },
+ { 1, 2, 2, QSPI_IFR_WIDTH_DUAL_IO },
+ { 1, 4, 4, QSPI_IFR_WIDTH_QUAD_IO },
+ { 2, 2, 2, QSPI_IFR_WIDTH_DUAL_CMD },
+ { 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD },
+};
+
/* Register access functions */
static inline u32 qspi_readl(struct atmel_qspi *aq, u32 reg)
{
@@ -197,6 +217,190 @@ static inline void qspi_writel(struct atmel_qspi *aq, u32 reg, u32 value)
writel_relaxed(value, aq->regs + reg);
}

+static inline bool is_compatible(const struct spi_mem_op *op,
+ const struct qspi_mode *mode)
+{
+ if (op->cmd.buswidth != mode->cmd_buswidth)
+ return false;
+
+ if (op->addr.nbytes && op->addr.buswidth != mode->addr_buswidth)
+ return false;
+
+ if (op->data.nbytes && op->data.buswidth != mode->data_buswidth)
+ return false;
+
+ return true;
+}
+
+static int find_mode(const struct spi_mem_op *op)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(sama5d2_qspi_modes); i++)
+ if (is_compatible(op, &sama5d2_qspi_modes[i]))
+ return i;
+
+ return -1;
+}
+
+static bool atmel_qspi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ if (find_mode(op) < 0)
+ return false;
+
+ /* special case not supported by hardware */
+ if (op->addr.nbytes == 2 && op->cmd.buswidth != op->addr.buswidth &&
+ op->dummy.nbytes == 0)
+ return false;
+
+ return true;
+}
+
+static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+ struct atmel_qspi *aq = spi_controller_get_devdata(mem->spi->master);
+ int mode;
+ u32 dummy_cycles = 0;
+ u32 iar, icr, ifr, sr;
+ int err = 0;
+
+ iar = 0;
+ icr = QSPI_ICR_INST(op->cmd.opcode);
+ ifr = QSPI_IFR_INSTEN;
+
+ qspi_writel(aq, QSPI_MR, QSPI_MR_SMM);
+
+ mode = find_mode(op);
+ if (mode < 0)
+ return -ENOTSUPP;
+
+ ifr |= sama5d2_qspi_modes[mode].config;
+
+ if (op->dummy.buswidth && op->dummy.nbytes)
+ dummy_cycles = op->dummy.nbytes * 8 / op->dummy.buswidth;
+
+ if (op->addr.buswidth) {
+ switch (op->addr.nbytes) {
+ case 0:
+ break;
+ case 1:
+ ifr |= QSPI_IFR_OPTEN | QSPI_IFR_OPTL_8BIT;
+ icr |= QSPI_ICR_OPT(op->addr.val & 0xff);
+ break;
+ case 2:
+ if (dummy_cycles < 8 / op->addr.buswidth) {
+ ifr &= ~QSPI_IFR_INSTEN;
+ ifr |= QSPI_IFR_ADDREN;
+ iar = (op->cmd.opcode << 16) |
+ (op->addr.val & 0xffff);
+ } else {
+ ifr |= QSPI_IFR_ADDREN;
+ iar = (op->addr.val << 8) & 0xffffff;
+ dummy_cycles -= 8 / op->addr.buswidth;
+ }
+ break;
+ case 3:
+ ifr |= QSPI_IFR_ADDREN;
+ iar = op->addr.val & 0xffffff;
+ break;
+ case 4:
+ ifr |= QSPI_IFR_ADDREN | QSPI_IFR_ADDRL;
+ iar = op->addr.val & 0x7ffffff;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ }
+
+ /* Set number of dummy cycles */
+ if (dummy_cycles)
+ ifr |= QSPI_IFR_NBDUM(dummy_cycles);
+
+ /* Set data enable */
+ if (op->data.nbytes)
+ ifr |= QSPI_IFR_DATAEN;
+
+ if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes)
+ ifr |= QSPI_IFR_TFRTYP_TRSFR_READ;
+ else
+ ifr |= QSPI_IFR_TFRTYP_TRSFR_WRITE;
+
+ /* Clear pending interrupts */
+ (void)qspi_readl(aq, QSPI_SR);
+
+ /* Set QSPI Instruction Frame registers */
+ qspi_writel(aq, QSPI_IAR, iar);
+ qspi_writel(aq, QSPI_ICR, icr);
+ qspi_writel(aq, QSPI_IFR, ifr);
+
+ /* Skip to the final steps if there is no data */
+ if (op->data.nbytes) {
+ /* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
+ (void)qspi_readl(aq, QSPI_IFR);
+
+ /* Send/Receive data */
+ if (op->data.dir == SPI_MEM_DATA_IN)
+ _memcpy_fromio(op->data.buf.in,
+ aq->mem + iar, op->data.nbytes);
+ else
+ _memcpy_toio(aq->mem + iar,
+ op->data.buf.out, op->data.nbytes);
+
+ /* Release the chip-select */
+ qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER);
+ }
+
+ /* Poll INSTRuction End status */
+ sr = qspi_readl(aq, QSPI_SR);
+ if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
+ return err;
+
+ /* Wait for INSTRuction End interrupt */
+ reinit_completion(&aq->cmd_completion);
+ aq->pending = sr & QSPI_SR_CMD_COMPLETED;
+ qspi_writel(aq, QSPI_IER, QSPI_SR_CMD_COMPLETED);
+ if (!wait_for_completion_timeout(&aq->cmd_completion,
+ msecs_to_jiffies(1000)))
+ err = -ETIMEDOUT;
+ qspi_writel(aq, QSPI_IDR, QSPI_SR_CMD_COMPLETED);
+
+ return err;
+}
+
+static const struct spi_controller_mem_ops atmel_qspi_mem_ops = {
+ .supports_op = atmel_qspi_supports_op,
+ .exec_op = atmel_qspi_exec_op
+};
+
+static int atmel_qspi_setup(struct spi_device *spi)
+{
+ struct spi_controller *ctrl = spi->master;
+ struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
+ unsigned long src_rate;
+ u32 scr, scbr;
+
+ if (ctrl->busy)
+ return -EBUSY;
+
+ if (!spi->max_speed_hz)
+ return -EINVAL;
+
+ src_rate = clk_get_rate(aq->clk);
+ if (!src_rate)
+ return -EINVAL;
+
+ /* Compute the QSPI baudrate */
+ scbr = DIV_ROUND_UP(src_rate, spi->max_speed_hz);
+ if (scbr > 0)
+ scbr--;
+
+ scr = QSPI_SCR_SCBR(scbr);
+ qspi_writel(aq, QSPI_SCR, scr);
+
+ return 0;
+}
+
static int atmel_qspi_run_transfer(struct atmel_qspi *aq,
const struct atmel_qspi_command *cmd)
{
@@ -756,5 +960,6 @@ static struct platform_driver atmel_qspi_driver = {
module_platform_driver(atmel_qspi_driver);

MODULE_AUTHOR("Cyrille Pitchen <[email protected]>");
+MODULE_AUTHOR("Piotr Bugalski <[email protected]");
MODULE_DESCRIPTION("Atmel QSPI Controller driver");
MODULE_LICENSE("GPL v2");
--
2.11.0


2018-07-03 12:53:30

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [RFC PATCH v2 1/6] mtd: spi-nor: atmel-quaspi: Typo fix

Hi,

On 27/06/2018 15:16:04+0200, Piotr Bugalski wrote:
> Just minor typo fix. Fixed in preparation of new driver.
>
> Signed-off: Piotr Bugalski <[email protected]>

This SoB line must match the author. It doesn't matter which one you
change. note that you can still submit your patch from an address
different from your work address if necessary (git format-patch will
insert the proper From line).

--
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com

2018-07-03 22:47:02

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [RFC PATCH v2 6/6] dt-bindings: spi: QuadSPI driver for Atmel SAMA5D2

On Wed, Jun 27, 2018 at 03:16:09PM +0200, Piotr Bugalski wrote:
> Atmel SAMA5D2 QuadSPI driver was moved from mtd to spi subsystem,
> this change is just moving DT-binding documentation.
>
> Suggested-by: Boris Brezillon <[email protected]>
> Signed-off-by: Piotr Bugalski <[email protected]>
> ---
> Documentation/devicetree/bindings/{mtd => spi}/atmel-quadspi.txt | 0
> 1 file changed, 0 insertions(+), 0 deletions(-)
> rename Documentation/devicetree/bindings/{mtd => spi}/atmel-quadspi.txt (100%)

Acked-by: Rob Herring <[email protected]>

>
> diff --git a/Documentation/devicetree/bindings/mtd/atmel-quadspi.txt b/Documentation/devicetree/bindings/spi/atmel-quadspi.txt
> similarity index 100%
> rename from Documentation/devicetree/bindings/mtd/atmel-quadspi.txt
> rename to Documentation/devicetree/bindings/spi/atmel-quadspi.txt
> --
> 2.11.0
>

2018-07-05 07:27:44

by Piotr Bugalski

[permalink] [raw]
Subject: Re: [RFC PATCH v2 1/6] mtd: spi-nor: atmel-quaspi: Typo fix


Hi Alexandre,

Thank you for you comment.

On Tue, 3 Jul 2018, Alexandre Belloni wrote:

> Hi,
>
> On 27/06/2018 15:16:04+0200, Piotr Bugalski wrote:
>> Just minor typo fix. Fixed in preparation of new driver.
>>
>> Signed-off: Piotr Bugalski <[email protected]>
>
> This SoB line must match the author. It doesn't matter which one you
> change. note that you can still submit your patch from an address
> different from your work address if necessary (git format-patch will
> insert the proper From line).
>

I didn't notice this issue, I'll fix it in next release.

> --
> Alexandre Belloni, Bootlin (formerly Free Electrons)
> Embedded Linux and Kernel engineering
> https://bootlin.com
>

Best Regards,
Piotr

2018-08-01 17:44:34

by Mark Brown

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

On Wed, Jun 27, 2018 at 03:16:08PM +0200, Piotr Bugalski wrote:
> Kernel contains QSPI driver strongly tied to MTD and nor-flash memory.
> New spi-mem interface allows usage also other memory types, especially
> much larger NAND with SPI interface. This driver works as SPI controller
> and is not related to MTD, however can work with NAND-flash or other
> peripherals using spi-mem interface.

This is fine from a SPI point of view but I'd like to apply it directly
to the SPI tree rather than ack it for merge via the MTD tree - can we
work something out with a shared branch or something?


Attachments:
(No filename) (603.00 B)
signature.asc (499.00 B)
Download all attachments

2018-08-01 19:58:48

by Boris Brezillon

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

Hi Mark,

On Wed, 1 Aug 2018 18:27:47 +0100
Mark Brown <[email protected]> wrote:

> On Wed, Jun 27, 2018 at 03:16:08PM +0200, Piotr Bugalski wrote:
> > Kernel contains QSPI driver strongly tied to MTD and nor-flash memory.
> > New spi-mem interface allows usage also other memory types, especially
> > much larger NAND with SPI interface. This driver works as SPI controller
> > and is not related to MTD, however can work with NAND-flash or other
> > peripherals using spi-mem interface.
>
> This is fine from a SPI point of view

Cool. There are still 2 things I think should be addressed before
merging the driver:
1/ Fixing the SoB tag to match the author (problem reported by
Alexandre)
2/ Getting this patch [1] merged and implementing the ->get_name() hook
in this driver so that SPI NOR devs declared to the MTD layer keep
the same name after the transition to spi-mem and mtdparts= passed on
the cmdline keep working. Without this in place we're likely to
break a few setups :-/.

> but I'd like to apply it directly
> to the SPI tree rather than ack it for merge via the MTD tree - can we
> work something out with a shared branch or something?

Sure, I can provide an immutable tag for you to pull and I'll add my
acks on those patches once the 2 things I mentioned above are
addressed.

Regards,

Boris

[1]https://patchwork.kernel.org/patch/10508693/


2018-08-02 10:19:10

by Mark Brown

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

On Wed, Aug 01, 2018 at 09:57:33PM +0200, Boris Brezillon wrote:
> Mark Brown <[email protected]> wrote:

> 2/ Getting this patch [1] merged and implementing the ->get_name() hook
> in this driver so that SPI NOR devs declared to the MTD layer keep
> the same name after the transition to spi-mem and mtdparts= passed on
> the cmdline keep working. Without this in place we're likely to
> break a few setups :-/.

> [1]https://patchwork.kernel.org/patch/10508693/

I don't seem to have a copy of this patch... not sure it was sent to
me?


Attachments:
(No filename) (566.00 B)
signature.asc (499.00 B)
Download all attachments

2018-08-02 10:47:57

by Frieder Schrempf

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

Hi Mark,

On 02.08.2018 12:17, Mark Brown wrote:
> On Wed, Aug 01, 2018 at 09:57:33PM +0200, Boris Brezillon wrote:
>> Mark Brown <[email protected]> wrote:
>
>> 2/ Getting this patch [1] merged and implementing the ->get_name() hook
>> in this driver so that SPI NOR devs declared to the MTD layer keep
>> the same name after the transition to spi-mem and mtdparts= passed on
>> the cmdline keep working. Without this in place we're likely to
>> break a few setups :-/.
>
>> [1]https://patchwork.kernel.org/patch/10508693/
>
> I don't seem to have a copy of this patch... not sure it was sent to
> me?

When I sent the patch I put you in cc. So if nothing went wrong you
should have it.
It is part of the SPI MEM conversion series for the FSL QSPI driver [1].

Boris made some remarks on documentation in v2, that I have fixed, but
not sent out yet, as we have some blocking issues with the driver itself.

So if you want I could send the patch separately so it can be applied
with the Atmel driver.

Regards,
Frieder

[1] https://patchwork.ozlabs.org/cover/939864/

2018-08-02 11:49:40

by Boris Brezillon

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

On Thu, 2 Aug 2018 12:46:36 +0200
Frieder Schrempf <[email protected]> wrote:

> Hi Mark,
>
> On 02.08.2018 12:17, Mark Brown wrote:
> > On Wed, Aug 01, 2018 at 09:57:33PM +0200, Boris Brezillon wrote:
> >> Mark Brown <[email protected]> wrote:
> >
> >> 2/ Getting this patch [1] merged and implementing the ->get_name() hook
> >> in this driver so that SPI NOR devs declared to the MTD layer keep
> >> the same name after the transition to spi-mem and mtdparts= passed on
> >> the cmdline keep working. Without this in place we're likely to
> >> break a few setups :-/.
> >
> >> [1]https://patchwork.kernel.org/patch/10508693/
> >
> > I don't seem to have a copy of this patch... not sure it was sent to
> > me?
>
> When I sent the patch I put you in cc. So if nothing went wrong you
> should have it.
> It is part of the SPI MEM conversion series for the FSL QSPI driver [1].
>
> Boris made some remarks on documentation in v2, that I have fixed, but
> not sent out yet, as we have some blocking issues with the driver itself.

I don't remember where we were stuck. Are you still waiting answers
from Yogesh? Probably a good time to ping him if that's the case ;-).

>
> So if you want I could send the patch separately so it can be applied
> with the Atmel driver.

Yes please, send a v3 for patch 1 and 2.

2018-08-02 12:25:34

by Mark Brown

[permalink] [raw]
Subject: Re: [RFC PATCH v2 5/6] spi: Add QuadSPI driver for Atmel SAMA5D2

On Thu, Aug 02, 2018 at 12:46:36PM +0200, Frieder Schrempf wrote:
> On 02.08.2018 12:17, Mark Brown wrote:

> > I don't seem to have a copy of this patch... not sure it was sent to
> > me?

> When I sent the patch I put you in cc. So if nothing went wrong you should
> have it.
> It is part of the SPI MEM conversion series for the FSL QSPI driver [1].

Well, I can't find any references to it anywhere so yeah.

> So if you want I could send the patch separately so it can be applied with
> the Atmel driver.

I'm going to need a copy to review it.


Attachments:
(No filename) (567.00 B)
signature.asc (499.00 B)
Download all attachments

2018-10-31 13:44:31

by Boris Brezillon

[permalink] [raw]
Subject: Re: [RFC PATCH v2 0/6] New QuadSPI driver for Atmel SAMA5D2

Hi Piotr, Tudor,

On Wed, 27 Jun 2018 15:16:03 +0200
Piotr Bugalski <[email protected]> wrote:

> Hello,
>
> Atmel SAMA5D2 is equipped with two QSPI interfaces. These interfaces can
> work as in SPI-compatible mode or use two / four lines to improve
> communication speed. At the moment there is QSPI driver strongly tied to
> NOR-flash memory and MTD subsystem.
> Intention of this change is to provide new driver which will not be tied
> to MTD and allows using QSPI with NAND-flash memory or other peripherals
> New spi-mem API provides abstraction layer which can disconnect QSPI
> from MTD. This driver doesn't support regular SPI interface, it should
> be used with spi-mem interface only.
> Unfortunately SAMA5D2 hardware by default supports only NOR-flash
> memory. It allows 24- and 32-bit addressing while NAND-flash requires
> 16-bit long. To workaround hardware limitation driver is a bit more
> complicated.
>
> Request to spi-mem contains three fiels: opcode (command), address,
> dummy bytes. SAMA5D2 QSPI hardware supports opcode, address, dummy and
> option byte where address field can only be 24- or 32- bytes long.
> Handling 8-bits long addresses is done using option field. For 16-bits
> address behaviour depends of number of requested dummy bits. If there
> are 8 or more dummy cycles, address is shifted and sent with first dummy
> byte. Otherwise opcode is disabled and first byte of address contains
> command opcode (works only if opcode and address use the same buswidth).
> The limitation is when 16-bit address is used without enough dummy
> cycles and opcode is using different buswidth than address. Other modes
> are supported with described workaround.
>
> It looks like hardware has some limitation in performance. The same issue
> exists in current QSPI driver (MTD/nor-flash) and soft-pack (bare-metal
> library from Atmel). Without using DMA read speed is much worse than
> maximum bandwidth (efficiency 30-40%). Any help with performance
> improvement is highly welcome, especially for NAND-flash memories which
> offers higher capacity than NOR-flash used with previous driver.
>
> Best Regards,
> Piotr
>
> v2 changes:
> - driver is now replacement of existing atmel-quadspi
> - code was re-written to follow original code structure
> - deinitialization order fixed
> - empty atmel_qspi_adjust_op_size function removed
> - code formatting fixes
> - use spi_device->max_speed_hz to get spi speed
> - spi freqency set in spi_controller->setup() hook
> - address range checkng for 4-bytes addressing
> - use timeout to avoid infinite waiting

IIRC, this version was almost ready to be merged except for the missing
->get_name() implementation which should be easy to add.

Can one of you post a new version of this patchset?

Thanks,

Boris