소스 검색

[DeviceDriver] Add QSPI device driver support for SFUD.

armink 6 년 전
부모
커밋
3a3da42738
1개의 변경된 파일116개의 추가작업 그리고 20개의 파일을 삭제
  1. 116 20
      components/drivers/spi/spi_flash_sfud.c

+ 116 - 20
components/drivers/spi/spi_flash_sfud.c

@@ -23,11 +23,21 @@
 
 #ifndef RT_SFUD_DEFAULT_SPI_CFG
 /* read the JEDEC SFDP command must run at 50 MHz or less */
-#define RT_SFUD_DEFAULT_SPI_CFG                 \
-{                                               \
-    .mode = RT_SPI_MODE_0 | RT_SPI_MSB,         \
-    .data_width = 8,                            \
-    .max_hz = 50 * 1000 * 1000,                 \
+#define RT_SFUD_DEFAULT_SPI_CFG                  \
+{                                                \
+    .mode = RT_SPI_MODE_0 | RT_SPI_MSB,          \
+    .data_width = 8,                             \
+    .max_hz = 50 * 1000 * 1000,                  \
+}
+#endif
+
+#ifdef SFUD_USING_QSPI
+#define RT_SFUD_DEFAULT_QSPI_CFG                 \
+{                                                \
+    RT_SFUD_DEFAULT_SPI_CFG,                     \
+    .medium_size = 0x800000,                     \
+    .ddr_mode = 0,                               \
+    .qspi_dl_width = 4,                          \
 }
 #endif
 
@@ -116,31 +126,90 @@ static sfud_err spi_write_read(const sfud_spi *spi, const uint8_t *write_buf, si
     sfud_err result = SFUD_SUCCESS;
     sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
     struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
-
+#ifdef SFUD_USING_QSPI
+    struct rt_qspi_device *qspi_dev = RT_NULL;
+#endif
     if (write_size) {
         RT_ASSERT(write_buf);
     }
     if (read_size) {
         RT_ASSERT(read_buf);
     }
-
-    if (write_size && read_size) {
-        if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
-            result = SFUD_ERR_TIMEOUT;
-        }
-    } else if (write_size) {
-        if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) {
-            result = SFUD_ERR_TIMEOUT;
+#ifdef SFUD_USING_QSPI
+    if(rtt_dev->rt_spi_device->bus->mode & RT_SPI_BUS_MODE_QSPI) {
+        qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
+        if (write_size && read_size) {
+            if (rt_qspi_send_then_recv(qspi_dev, write_buf, write_size, read_buf, read_size) == 0) {
+                result = SFUD_ERR_TIMEOUT;
+            }
+        } else if (write_size) {
+            if (rt_qspi_send(qspi_dev, write_buf, write_size) == 0) {
+                result = SFUD_ERR_TIMEOUT;
+            }
         }
-    } else {
-        if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) {
-            result = SFUD_ERR_TIMEOUT;
+    }
+    else
+#endif
+    {
+        if (write_size && read_size) {
+            if (rt_spi_send_then_recv(rtt_dev->rt_spi_device, write_buf, write_size, read_buf, read_size) != RT_EOK) {
+                result = SFUD_ERR_TIMEOUT;
+            }
+        } else if (write_size) {
+            if (rt_spi_send(rtt_dev->rt_spi_device, write_buf, write_size) == 0) {
+                result = SFUD_ERR_TIMEOUT;
+            }
+        } else {
+            if (rt_spi_recv(rtt_dev->rt_spi_device, read_buf, read_size) == 0) {
+                result = SFUD_ERR_TIMEOUT;
+            }
         }
     }
 
     return result;
 }
 
+#ifdef SFUD_USING_QSPI
+/**
+ * QSPI fast read data
+ */
+static sfud_err qspi_read(const struct __sfud_spi *spi, uint32_t addr, sfud_qspi_read_cmd_format *qspi_read_cmd_format, uint8_t *read_buf, size_t read_size) {
+    struct rt_qspi_message message;
+    sfud_err result = SFUD_SUCCESS;
+
+    sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
+    struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
+    struct rt_qspi_device *qspi_dev = (struct rt_qspi_device *) (rtt_dev->rt_spi_device);
+                             
+    /* set message struct */
+    message.instruction.content = qspi_read_cmd_format->instruction;
+    message.instruction.qspi_lines = qspi_read_cmd_format->instruction_lines;
+
+    message.address.content = addr;
+    message.address.size = qspi_read_cmd_format->address_size;
+    message.address.qspi_lines = qspi_read_cmd_format->address_lines;
+
+    message.alternate_bytes.content = 0;
+    message.alternate_bytes.size = 0;
+    message.alternate_bytes.qspi_lines = 0;
+
+    message.dummy_cycles = qspi_read_cmd_format->dummy_cycles;
+
+    message.parent.send_buf = RT_NULL;
+    message.parent.recv_buf = read_buf;
+    message.parent.length = read_size;
+    message.parent.cs_release = 1;
+    message.parent.cs_take = 1;
+    message.qspi_data_lines = qspi_read_cmd_format->data_lines;
+    
+    if (rt_qspi_transfer_message(qspi_dev, &message) != read_size) {
+        result = SFUD_ERR_TIMEOUT;
+    }
+    
+    return result;
+}
+#endif
+
 static void spi_lock(const sfud_spi *spi) {
     sfud_flash *sfud_dev = (sfud_flash *) (spi->user_data);
     struct spi_flash_device *rtt_dev = (struct spi_flash_device *) (sfud_dev->user_data);
@@ -203,6 +272,9 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
 
     /* port SPI device interface */
     flash->spi.wr = spi_write_read;
+#ifdef SFUD_USING_QSPI
+    flash->spi.qspi_read = qspi_read;
+#endif
     flash->spi.lock = spi_lock;
     flash->spi.unlock = spi_unlock;
     flash->spi.user_data = flash;
@@ -213,8 +285,7 @@ sfud_err sfud_spi_port_init(sfud_flash *flash) {
     flash->retry.delay = retry_delay_100us;
     /* 60 seconds timeout */
     flash->retry.times = 60 * 10000;
-
-
+    
     return result;
 }
 
@@ -246,6 +317,10 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
      * @note you also can change the SPI to other configuration after initialized finish */
     struct rt_spi_configuration cfg = RT_SFUD_DEFAULT_SPI_CFG;
     extern sfud_err sfud_device_init(sfud_flash *flash);
+#ifdef SFUD_USING_QSPI
+    struct rt_qspi_configuration qspi_cfg = RT_SFUD_DEFAULT_QSPI_CFG;
+    struct rt_qspi_device *qspi_dev = RT_NULL;
+#endif
 
     RT_ASSERT(spi_flash_dev_name);
     RT_ASSERT(spi_dev_name);
@@ -277,7 +352,17 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
                 goto error;
             }
             sfud_dev->spi.name = spi_dev_name_bak;
-            rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
+
+#ifdef SFUD_USING_QSPI
+            /* set the qspi line number and configure the QSPI bus */
+            if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
+                qspi_dev = (struct rt_qspi_device *)rtt_dev->rt_spi_device;
+                qspi_cfg.qspi_dl_width = qspi_dev->config.qspi_dl_width;
+                rt_qspi_configure(qspi_dev, &qspi_cfg);
+            }
+            else
+#endif                
+                rt_spi_configure(rtt_dev->rt_spi_device, &cfg);
         }
         /* SFUD flash device initialize */
         {
@@ -296,6 +381,17 @@ rt_spi_flash_device_t rt_sfud_flash_probe(const char *spi_flash_dev_name, const
             rtt_dev->geometry.sector_count = sfud_dev->chip.capacity / sfud_dev->chip.erase_gran;
             rtt_dev->geometry.bytes_per_sector = sfud_dev->chip.erase_gran;
             rtt_dev->geometry.block_size = sfud_dev->chip.erase_gran;
+#ifdef SFUD_USING_QSPI
+            /* reconfigure the QSPI bus for medium size */
+            if(rtt_dev->rt_spi_device->bus->mode &RT_SPI_BUS_MODE_QSPI) {
+                qspi_cfg.medium_size = sfud_dev->chip.capacity;
+                rt_qspi_configure(qspi_dev, &qspi_cfg);
+                if(qspi_dev->enter_qspi_mode != RT_NULL)
+                    qspi_dev->enter_qspi_mode(qspi_dev);
+            }
+            /* set data lines width */
+            sfud_qspi_fast_read_enable(sfud_dev, qspi_dev->config.qspi_dl_width);
+#endif /* SFUD_USING_QSPI */
         }
 
         /* register device */