aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/lib/peripherals
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2016-06-04 12:29:54 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2016-06-04 12:29:54 +0000
commitec871b0ef13545688ddd140520bb49baacb4283a (patch)
treeee54c9d047f2bdb675017abb8bed434d4e91a359 /os/hal/lib/peripherals
parentf8f2ea1763d1494c0f51fe941e4ee324eeb0a572 (diff)
downloadChibiOS-ec871b0ef13545688ddd140520bb49baacb4283a.tar.gz
ChibiOS-ec871b0ef13545688ddd140520bb49baacb4283a.tar.bz2
ChibiOS-ec871b0ef13545688ddd140520bb49baacb4283a.zip
M25Q driver works over QSPI.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9568 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/lib/peripherals')
-rw-r--r--os/hal/lib/peripherals/flash/hal_jesd216_flash.c277
-rw-r--r--os/hal/lib/peripherals/flash/hal_jesd216_flash.h113
2 files changed, 375 insertions, 15 deletions
diff --git a/os/hal/lib/peripherals/flash/hal_jesd216_flash.c b/os/hal/lib/peripherals/flash/hal_jesd216_flash.c
index 7687a4aa7..07d4aad80 100644
--- a/os/hal/lib/peripherals/flash/hal_jesd216_flash.c
+++ b/os/hal/lib/peripherals/flash/hal_jesd216_flash.c
@@ -46,4 +46,281 @@
/* Driver exported functions. */
/*===========================================================================*/
+void jesd216_cmd(BUSDriver *busp, uint8_t cmd) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES;
+#endif
+ mode.addr = 0U;
+ mode.alt = 0U;
+ qspiCommand(busp, &mode);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiUnselect(busp);
+#endif
+}
+
+void jesd216_cmd_receive(BUSDriver *busp,
+ uint8_t cmd,
+ size_t n,
+ uint8_t *p) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_DATA_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_DATA_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_DATA_MODE_FOUR_LINES;
+
+#endif
+ mode.addr = 0U;
+ mode.alt = 0U;
+ qspiReceive(busp, &mode, n, p);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiReceive(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+void jesd216_cmd_send(BUSDriver *busp,
+ uint8_t cmd,
+ size_t n,
+ const uint8_t *p) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_DATA_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_DATA_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_DATA_MODE_FOUR_LINES;
+
+#endif
+ mode.addr = 0U;
+ mode.alt = 0U;
+ qspiSend(busp, &mode, n, p);
+#else
+ uint8_t buf[1];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ spiSend(busp, 1, buf);
+ spiSend(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+void jesd216_cmd_addr(BUSDriver *busp,
+ uint8_t cmd,
+ flash_address_t addr) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_SIZE_24;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_SIZE_24;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_SIZE_24;
+
+#endif
+ mode.addr = addr;
+ mode.alt = 0U;
+ qspiCommand(busp, &mode);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(addr >> 16);
+ buf[2] = (uint8_t)(addr >> 8);
+ buf[3] = (uint8_t)(addr >> 0);
+ spiSend(busp, 4, buf);
+ spiUnselect(busp);
+#endif
+}
+
+void jesd216_cmd_addr_send(BUSDriver *busp,
+ uint8_t cmd,
+ flash_address_t addr,
+ size_t n,
+ const uint8_t *p) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_FOUR_LINES;
+
+#endif
+ mode.addr = addr;
+ mode.alt = 0U;
+ qspiSend(busp, &mode, n, p);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(addr >> 16);
+ buf[2] = (uint8_t)(addr >> 8);
+ buf[3] = (uint8_t)(addr >> 0);
+ spiSend(busp, 4, buf);
+ spiSend(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+void jesd216_cmd_addr_receive(BUSDriver *busp,
+ uint8_t cmd,
+ flash_address_t addr,
+ size_t n,
+ uint8_t *p) {
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DATA_MODE_FOUR_LINES;
+
+#endif
+ mode.addr = addr;
+ mode.alt = 0U;
+ qspiReceive(busp, &mode, n, p);
+#else
+ uint8_t buf[4];
+
+ spiSelect(busp);
+ buf[0] = cmd;
+ buf[1] = (uint8_t)(addr >> 16);
+ buf[2] = (uint8_t)(addr >> 8);
+ buf[3] = (uint8_t)(addr >> 0);
+ spiSend(busp, 4, buf);
+ spiReceive(busp, n, p);
+ spiUnselect(busp);
+#endif
+}
+
+#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
+void jesd216_cmd_addr_dummy_receive(BUSDriver *busp,
+ uint8_t cmd,
+ flash_address_t addr,
+ uint8_t dummy,
+ size_t n,
+ uint8_t *p) {
+ qspi_command_t mode;
+
+ mode.cfg = QSPI_CFG_CMD(cmd) |
+#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L
+ QSPI_CFG_CMD_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_MODE_ONE_LINE |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DUMMY_CYCLES(dummy) |
+ QSPI_CFG_DATA_MODE_ONE_LINE;
+#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L
+ QSPI_CFG_CMD_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_MODE_TWO_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DUMMY_CYCLES(dummy) |
+ QSPI_CFG_DATA_MODE_TWO_LINES;
+#else
+ QSPI_CFG_CMD_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_MODE_FOUR_LINES |
+ QSPI_CFG_ADDR_SIZE_24 |
+ QSPI_CFG_DUMMY_CYCLES(dummy) |
+ QSPI_CFG_DATA_MODE_FOUR_LINES;
+#endif
+ mode.addr = addr;
+ mode.alt = 0U;
+ qspiReceive(busp, &mode, n, p);
+}
+#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
+
+#if ((JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \
+ (JESD216_SHARED_BUS == TRUE)) || defined(__DOXYGEN__)
+void jesd216_bus_acquire(BUSDriver *busp) {
+
+ qspiAcquireBus(busp);
+}
+
+void jesd216_bus_release(BUSDriver *busp) {
+
+ qspiReleaseBus(busp);
+}
+#elif (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
+ (JESD216_SHARED_BUS == TRUE)
+static void jesd216_bus_acquire(BUSDriver *busp) {
+
+ spiAcquireBus(busp);
+ spiStart(busp, busp->config->spicfg);
+}
+
+static void jesd216_bus_release(BUSDriver *busp) {
+
+ spiReleaseBus(busp);
+}
+#else
+#define jesd216_bus_acquire(busp)
+#define jesd216_bus_release(busp)
+#endif
+
/** @} */
diff --git a/os/hal/lib/peripherals/flash/hal_jesd216_flash.h b/os/hal/lib/peripherals/flash/hal_jesd216_flash.h
index 8e46f71e8..69d8a8533 100644
--- a/os/hal/lib/peripherals/flash/hal_jesd216_flash.h
+++ b/os/hal/lib/peripherals/flash/hal_jesd216_flash.h
@@ -35,40 +35,108 @@
* @name Common command codes
* @{
*/
-#define JESD216_CMD_READ_ID 0x9F
-#define JESD216_CMD_READ 0x03
-#define JESD216_CMD_WRITE_ENABLE 0x06
-#define JESD216_CMD_WRITE_DISABLE 0x04
-#define JESD216_CMD_READ_STATUS_REGISTER 0x05
-#define JESD216_CMD_WRITE_STATUS_REGISTER 0x01
-#define JESD216_CMD_PAGE_PROGRAM 0x02
-#define JESD216_CMD_ERASE_4K 0x20
-#define JESD216_CMD_ERASE_BULK 0xC7
-#define JESD216_CMD_PROGRAM_ERASE_RESUME 0x7A
-#define JESD216_CMD_PROGRAM_ERASE_SUSPEND 0x75
-#define JESD216_CMD_READ_OTP_ARRAY 0x4B
-#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42
+#define JESD216_CMD_READ_ID 0x9F
+#define JESD216_CMD_READ 0x03
+#define JESD216_CMD_WRITE_ENABLE 0x06
+#define JESD216_CMD_WRITE_DISABLE 0x04
+#define JESD216_CMD_READ_STATUS_REGISTER 0x05
+#define JESD216_CMD_WRITE_STATUS_REGISTER 0x01
+#define JESD216_CMD_PAGE_PROGRAM 0x02
+#define JESD216_CMD_ERASE_4K 0x20
+#define JESD216_CMD_ERASE_BULK 0xC7
+#define JESD216_CMD_PROGRAM_ERASE_RESUME 0x7A
+#define JESD216_CMD_PROGRAM_ERASE_SUSPEND 0x75
+#define JESD216_CMD_READ_OTP_ARRAY 0x4B
+#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42
+/** @} */
+
+/**
+ * @name Bus interface.
+ * @{
+ */
+#define JESD216_BUS_MODE_SPI 0
+#define JESD216_BUS_MODE_QSPI1L 1
+#define JESD216_BUS_MODE_QSPI2L 2
+#define JESD216_BUS_MODE_QSPI4L 4
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
+/**
+ * @name Configuration options
+ * @{
+ */
+/**
+ * @brief Physical transport interface.
+ */
+#if !defined(JESD216_USE_SPI) || defined(__DOXYGEN__)
+#define JESD216_BUS_MODE JESD216_BUS_MODE_QSPI4L
+#endif
+
+/**
+ * @brief Shared bus switch.
+ * @details If set to @p TRUE the device acquires bus ownership
+ * on each transaction.
+ * @note Requires @p SPI_USE_MUTUAL_EXCLUSION or
+ * @p SPI_USE_MUTUAL_EXCLUSION.
+ */
+#if !defined(JESD216_SHARED_BUS) || defined(__DOXYGEN__)
+#define JESD216_SHARED_BUS TRUE
+#endif
+/** @} */
+
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
+#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && (HAL_USE_SPI == FALSE)
+#error "JESD216_BUS_MODE_SPI requires HAL_USE_SPI"
+#endif
+
+#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (HAL_USE_QSPI == FALSE)
+#error "JESD216_BUS_MODE_QSPIxL requires HAL_USE_QSPI"
+#endif
+
+#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \
+ (JESD216_SHARED_SPI == TRUE) && \
+ (SPI_USE_MUTUAL_EXCLUSION == FALSE)
+#error "JESD216_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION"
+#endif
+
+#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \
+ (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI1L) && \
+ (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI2L) && \
+ (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI4L)
+#error "invalid JESD216_BUS_MODE selected"
+#endif
+
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
+#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__)
+#define BUSConfig QSPIConfig
+#define BUSDriver QSPIDriver
+#else
+#define BUSConfig SPIConfig
+#define BUSDriver SPIDriver
+#endif
+
+#define _jesd216_config \
+ BUSDriver *busp; \
+ const BUSConfig *buscfg;
+
/**
* @brief @p JESD215Flash specific methods.
* @note No methods so far, just a common ancestor interface.
*/
#define _jesd216_flash_methods_alone \
/* Read SFDP.*/ \
- flash_error_t (*read_id)(void *instance, uint8_t *rp, size_t max);
+ flash_error_t (*read_sfdp)(void *instance, uint8_t *rp, \
+ flash_address_t addr, \
+ size_t n);
/**
* @brief @p JESD215Flash specific methods with inherited ones.
@@ -116,7 +184,22 @@ typedef struct {
#ifdef __cplusplus
extern "C" {
#endif
-
+ void jesd216_cmd(BUSDriver *busp, uint8_t cmd);
+ void jesd216_cmd_receive(BUSDriver *busp, uint8_t cmd, size_t n, uint8_t *p);
+ void jesd216_cmd_send(BUSDriver *busp, uint8_t cmd, size_t n, const uint8_t *p);
+ void jesd216_cmd_addr(BUSDriver *busp, uint8_t cmd, flash_address_t addr);
+ void jesd216_cmd_addr_send(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
+ size_t n, const uint8_t *p);
+ void jesd216_cmd_addr_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
+ size_t n, uint8_t *p);
+#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI
+ void jesd216_cmd_addr_dummy_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr,
+ uint8_t dummy, size_t n, uint8_t *p);
+#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */
+#if JESD216_SHARED_BUS == TRUE
+ void jesd216_bus_acquire(BUSDriver *busp);
+ void jesd216_bus_release(BUSDriver *busp);
+#endif
#ifdef __cplusplus
}
#endif