Skip to content

Commit c4afaaa

Browse files
taltenbachkartben
authored andcommitted
drivers: flash: stm32_qspi: Fix status register access for dual-flash
When dual-flash mode is enabled, two identical flash memories are connected to the QUADSPI peripheral, each having its own set of registers. This means that when reading or writing a flash register, this has to be made for both flash memories. For example, when reading a status register (1 byte), the QUADSPI peripheral must be configured to read two bytes of data, which correspond respectively to the value of the register in the first and second flash memory. Same thing when writing. Before this commit, when dual-flash mode was enabled, only the register of the first flash memory was considered, which means the second flash memory could be incorrectly configured and that any write/erase operation could be considered as completed too early, if the operation takes more time to complete for the second flash memory. Signed-off-by: Thomas Altenbach <[email protected]>
1 parent f9f6b24 commit c4afaaa

File tree

1 file changed

+113
-24
lines changed

1 file changed

+113
-24
lines changed

drivers/flash/flash_stm32_qspi.c

Lines changed: 113 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,92 @@ LOG_MODULE_REGISTER(flash_stm32_qspi, CONFIG_FLASH_LOG_LEVEL);
6565
/* In dual-flash mode, total size is twice the size of one flash component */
6666
#define STM32_QSPI_DOUBLE_FLASH DT_PROP(DT_NODELABEL(quadspi), dual_flash)
6767

68+
#if STM32_QSPI_DOUBLE_FLASH
69+
#define FLASH_REG_FMT "%04x"
70+
#else
71+
#define FLASH_REG_FMT "%02x"
72+
#endif /* STM32_QSPI_DOUBLE_FLASH */
73+
74+
/*
75+
* A register of the flash device, such as a status register.
76+
*
77+
* When dual-flash mode is enabled, this structure contains the value of the actual register of both
78+
* flash memories. For example, if an instance of this structure is used to hold the value of the
79+
* status register, 'flash0_val' and 'flash1_val' will be equal respectively to the value of the
80+
* status register of the first and second flash memory.
81+
*
82+
* This structure is packed as it is directly sent/received over the QSPI bus.
83+
*/
84+
struct flash_reg {
85+
uint8_t flash0_val;
86+
#if STM32_QSPI_DOUBLE_FLASH
87+
uint8_t flash1_val;
88+
#endif /* STM32_QSPI_DOUBLE_FLASH */
89+
} __packed;
90+
91+
/*
92+
* Sets a bit in a flash register.
93+
*
94+
* In dual-flash mode, the value is updated for both flash memories.
95+
*/
96+
static inline void flash_reg_set_for_all(struct flash_reg *reg, uint8_t bitmask)
97+
{
98+
reg->flash0_val |= bitmask;
99+
#if STM32_QSPI_DOUBLE_FLASH
100+
reg->flash1_val |= bitmask;
101+
#endif /* STM32_QSPI_DOUBLE_FLASH */
102+
}
103+
104+
/*
105+
* Checks if a bit is set in a flash register.
106+
*
107+
* In dual-flash mode, this routine returns true if and only if the bit is set for both flash
108+
* memories.
109+
*/
110+
static inline bool flash_reg_is_set_for_all(struct flash_reg *reg, uint8_t bitmask)
111+
{
112+
bool is_set = (reg->flash0_val & bitmask) != 0U;
113+
114+
#if STM32_QSPI_DOUBLE_FLASH
115+
is_set = is_set && ((reg->flash1_val & bitmask) != 0U);
116+
#endif /* STM32_QSPI_DOUBLE_FLASH */
117+
118+
return is_set;
119+
}
120+
121+
/*
122+
* Checks if a bit is clear in a flash register.
123+
*
124+
* In dual-flash mode, this routine returns true if and only if the bit is clear for both flash
125+
* memories.
126+
*/
127+
static inline bool flash_reg_is_clear_for_all(struct flash_reg *reg, uint8_t bitmask)
128+
{
129+
bool is_clear = (reg->flash0_val & bitmask) == 0U;
130+
131+
#if STM32_QSPI_DOUBLE_FLASH
132+
is_clear = is_clear && ((reg->flash1_val & bitmask) == 0U);
133+
#endif /* STM32_QSPI_DOUBLE_FLASH */
134+
135+
return is_clear;
136+
}
137+
138+
/*
139+
* Gets the raw representation of a flash register, as a uint16_t value where the lower byte is the
140+
* value for the first flash memory and the upper byte is the value for the second flash memory, if
141+
* any.
142+
*/
143+
static inline uint16_t flash_reg_to_raw(const struct flash_reg *reg)
144+
{
145+
uint16_t raw = reg->flash0_val;
146+
147+
#if STM32_QSPI_DOUBLE_FLASH
148+
raw |= reg->flash1_val << 8;
149+
#endif /* STM32_QSPI_DOUBLE_FLASH */
150+
151+
return raw;
152+
}
153+
68154
#if STM32_QSPI_USE_DMA
69155
static const uint32_t table_m_size[] = {
70156
LL_DMA_MDATAALIGN_BYTE,
@@ -580,7 +666,8 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
580666
return ret;
581667
}
582668

583-
static int qspi_read_status_register(const struct device *dev, uint8_t reg_num, uint8_t *reg)
669+
static int qspi_read_status_register(const struct device *dev, uint8_t reg_num,
670+
struct flash_reg *reg)
584671
{
585672
QSPI_CommandTypeDef cmd = {
586673
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
@@ -601,15 +688,16 @@ static int qspi_read_status_register(const struct device *dev, uint8_t reg_num,
601688
return -EINVAL;
602689
}
603690

604-
return qspi_read_access(dev, &cmd, reg, sizeof(*reg));
691+
return qspi_read_access(dev, &cmd, (uint8_t *)reg, sizeof(*reg));
605692
}
606693

607-
static int qspi_write_status_register(const struct device *dev, uint8_t reg_num, uint8_t reg)
694+
static int qspi_write_status_register(const struct device *dev, uint8_t reg_num,
695+
struct flash_reg *reg)
608696
{
609697
struct flash_stm32_qspi_data *dev_data = dev->data;
610698
size_t size;
611-
uint8_t regs[4] = { 0 };
612-
uint8_t *regs_p;
699+
struct flash_reg regs[4] = {0};
700+
struct flash_reg *regs_p;
613701
int ret;
614702

615703
QSPI_CommandTypeDef cmd = {
@@ -619,21 +707,21 @@ static int qspi_write_status_register(const struct device *dev, uint8_t reg_num,
619707
};
620708

621709
if (reg_num == 1U) {
622-
size = 1U;
623-
regs[0] = reg;
710+
size = sizeof(struct flash_reg);
711+
memcpy(&regs[0], reg, sizeof(struct flash_reg));
624712
regs_p = &regs[0];
625713
/* 1 byte write clears SR2, write SR2 as well */
626714
if (dev_data->qer_type == JESD216_DW15_QER_S2B1v1) {
627715
ret = qspi_read_status_register(dev, 2, &regs[1]);
628716
if (ret < 0) {
629717
return ret;
630718
}
631-
size = 2U;
719+
size += sizeof(struct flash_reg);
632720
}
633721
} else if (reg_num == 2U) {
634722
cmd.Instruction = SPI_NOR_CMD_WRSR2;
635-
size = 1U;
636-
regs[1] = reg;
723+
size = sizeof(struct flash_reg);
724+
memcpy(&regs[1], reg, sizeof(struct flash_reg));
637725
regs_p = &regs[1];
638726
/* if SR2 write needs SR1 */
639727
if ((dev_data->qer_type == JESD216_DW15_QER_VAL_S2B1v1) ||
@@ -644,29 +732,29 @@ static int qspi_write_status_register(const struct device *dev, uint8_t reg_num,
644732
return ret;
645733
}
646734
cmd.Instruction = SPI_NOR_CMD_WRSR;
647-
size = 2U;
735+
size += sizeof(struct flash_reg);
648736
regs_p = &regs[0];
649737
}
650738
} else if (reg_num == 3U) {
651739
cmd.Instruction = SPI_NOR_CMD_WRSR3;
652-
size = 1U;
653-
regs[2] = reg;
740+
size = sizeof(struct flash_reg);
741+
memcpy(&regs[2], reg, sizeof(struct flash_reg));
654742
regs_p = &regs[2];
655743
} else {
656744
return -EINVAL;
657745
}
658746

659-
return qspi_write_access(dev, &cmd, regs_p, size);
747+
return qspi_write_access(dev, &cmd, (uint8_t *)regs_p, size);
660748
}
661749

662750
static int qspi_wait_until_ready(const struct device *dev)
663751
{
664-
uint8_t reg;
752+
struct flash_reg reg;
665753
int ret;
666754

667755
do {
668756
ret = qspi_read_status_register(dev, 1, &reg);
669-
} while (!ret && (reg & SPI_NOR_WIP_BIT));
757+
} while (!ret && !flash_reg_is_clear_for_all(&reg, SPI_NOR_WIP_BIT));
670758

671759
return ret;
672760
}
@@ -1163,7 +1251,7 @@ static int qspi_program_addr_4b(const struct device *dev, bool write_enable)
11631251

11641252
static int qspi_write_enable(const struct device *dev)
11651253
{
1166-
uint8_t reg;
1254+
struct flash_reg reg;
11671255
int ret;
11681256

11691257
ret = qspi_send_cmd(dev, &cmd_write_en);
@@ -1173,7 +1261,7 @@ static int qspi_write_enable(const struct device *dev)
11731261

11741262
do {
11751263
ret = qspi_read_status_register(dev, 1U, &reg);
1176-
} while (!ret && !(reg & SPI_NOR_WEL_BIT));
1264+
} while (!ret && !flash_reg_is_set_for_all(&reg, SPI_NOR_WEL_BIT));
11771265

11781266
return ret;
11791267
}
@@ -1183,7 +1271,7 @@ static int qspi_program_quad_io(const struct device *dev)
11831271
struct flash_stm32_qspi_data *data = dev->data;
11841272
uint8_t qe_reg_num;
11851273
uint8_t qe_bit;
1186-
uint8_t reg;
1274+
struct flash_reg reg;
11871275
int ret;
11881276

11891277
switch (data->qer_type) {
@@ -1218,18 +1306,18 @@ static int qspi_program_quad_io(const struct device *dev)
12181306
}
12191307

12201308
/* exit early if QE bit is already set */
1221-
if ((reg & qe_bit) != 0U) {
1309+
if (flash_reg_is_set_for_all(&reg, qe_bit)) {
12221310
return 0;
12231311
}
12241312

1225-
reg |= qe_bit;
1313+
flash_reg_set_for_all(&reg, qe_bit);
12261314

12271315
ret = qspi_write_enable(dev);
12281316
if (ret < 0) {
12291317
return ret;
12301318
}
12311319

1232-
ret = qspi_write_status_register(dev, qe_reg_num, reg);
1320+
ret = qspi_write_status_register(dev, qe_reg_num, &reg);
12331321
if (ret < 0) {
12341322
return ret;
12351323
}
@@ -1245,8 +1333,9 @@ static int qspi_program_quad_io(const struct device *dev)
12451333
return ret;
12461334
}
12471335

1248-
if ((reg & qe_bit) == 0U) {
1249-
LOG_ERR("Status Register %u [0x%02x] not set", qe_reg_num, reg);
1336+
if (!flash_reg_is_set_for_all(&reg, qe_bit)) {
1337+
LOG_ERR("Status Register %u [0x" FLASH_REG_FMT "] not set", qe_reg_num,
1338+
flash_reg_to_raw(&reg));
12501339
return -EIO;
12511340
}
12521341

0 commit comments

Comments
 (0)