dieselburner opened a new issue #1356: URL: https://github.com/apache/incubator-nuttx/issues/1356
**Issue:** Currently there's a misalignment in MTD drivers, where some drivers are written exclusively for QSPI interfaces, while others are using standard SPI. As you know, (nearly?) all QuadSPI controller implementations allows you to use QSPI in a standard SPI way, and opposite, all QSPI devices that I have seen (I've seen things you people wouldn't believe (C)) are able to operate in a standard SPI mode. **Example:** 1. [m25qxxx driver](https://github.com/apache/incubator-nuttx/blob/master/drivers/mtd/n25qxxx.c) is using QSPI_* functions, which means currently it is impossible to use this particular driver with standard SPI interface. ```c static int n25qxxx_command_write(FAR struct qspi_dev_s *qspi, uint8_t cmd, FAR const void *buffer, size_t buflen) { struct qspi_cmdinfo_s cmdinfo; finfo("CMD: %02x buflen: %lu\n", cmd, (unsigned long)buflen); cmdinfo.flags = QSPICMD_WRITEDATA; cmdinfo.addrlen = 0; cmdinfo.cmd = cmd; cmdinfo.buflen = buflen; cmdinfo.addr = 0; cmdinfo.buffer = (FAR void *)buffer; return QSPI_COMMAND(qspi, &cmdinfo); } ``` 2. [gd5d driver](https://github.com/apache/incubator-nuttx/blob/master/drivers/mtd/gd5f.c) is using SPI_* commands, which means currently it is impossible to use this particular driver with QSPI interface, even though this NAND chip supports QSPI. ```c static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv, uint32_t pageaddress) { const uint32_t row = pageaddress >> priv->pageshift; /* Select this FLASH part */ SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), true); /* Send the Program Execute instruction */ SPI_SEND(priv->dev, GD5F_PROGRAM_EXECUTE); SPI_SEND(priv->dev, (row >> 16) & 0xff); SPI_SEND(priv->dev, (row >> 8) & 0xff); SPI_SEND(priv->dev, row & 0xff); /* De-select the FLASH */ SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false); return gd5f_waitstatus(priv, GD5F_SR_P_FAIL, false); } ``` **Solution:** Ideally having some sort of a common `ops` structure that is initialized by SPI/QSPI/other_transport drivers, which then is used in MTD (and other) device drivers, by simply calling appropriate callbacks without caring what transport is being used. That's pretty much the same way how these kind of things are implemented in Linux kernel. ```c struct spi_nor_controller_ops { int (*prepare)(struct spi_nor *nor); void (*unprepare)(struct spi_nor *nor); int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, size_t len); int (*write_reg)(struct spi_nor *nor, u8 opcode, const u8 *buf, size_t len); ssize_t (*read)(struct spi_nor *nor, loff_t from, size_t len, u8 *buf); ssize_t (*write)(struct spi_nor *nor, loff_t to, size_t len, const u8 *buf); int (*erase)(struct spi_nor *nor, loff_t offs); }; ``` ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org