@@ -78,6 +78,13 @@ struct mspi_dw_config {
7878 const struct gpio_dt_spec * ce_gpios ;
7979 uint8_t ce_gpios_len ;
8080 uint8_t tx_fifo_depth_minus_1 ;
81+ /* Maximum number of items allowed in the TX FIFO when transmitting
82+ * dummy bytes; it must be at least one less than the RX FIFO depth
83+ * to account for a byte that can be partially received (i.e. in
84+ * the shifting register) when tx_dummy_bytes() calculates how many
85+ * bytes can be written to the TX FIFO to not overflow the RX FIFO.
86+ */
87+ uint8_t max_queued_dummy_bytes ;
8188 uint8_t tx_fifo_threshold ;
8289 uint8_t rx_fifo_threshold ;
8390 DECLARE_REG_ACCESS ( );
@@ -151,7 +158,11 @@ static void tx_data(const struct device *dev,
151158
152159 if (buf_pos >= buf_end ) {
153160 /* Set the threshold to 0 to get the next interrupt
154- * when the FIFO is completely emptied.
161+ * when the FIFO is completely emptied. This also sets
162+ * the TX start level to 0, so if the transmission was
163+ * not started so far because the FIFO was not filled
164+ * up completely (the start level was set to maximum
165+ * in start_next_packet()), it will be started now.
155166 */
156167 write_txftlr (dev , 0 );
157168 break ;
@@ -170,11 +181,22 @@ static bool tx_dummy_bytes(const struct device *dev)
170181{
171182 struct mspi_dw_data * dev_data = dev -> data ;
172183 const struct mspi_dw_config * dev_config = dev -> config ;
173- uint8_t fifo_room = dev_config -> tx_fifo_depth_minus_1 + 1
184+ uint8_t fifo_room = dev_config -> max_queued_dummy_bytes
174185 - FIELD_GET (TXFLR_TXTFL_MASK , read_txflr (dev ));
186+ uint8_t rx_fifo_items = FIELD_GET (RXFLR_RXTFL_MASK , read_rxflr (dev ));
175187 uint16_t dummy_bytes = dev_data -> dummy_bytes ;
176188 const uint8_t dummy_val = 0 ;
177189
190+ /* Subtract the number of items that are already stored in the RX
191+ * FIFO to avoid overflowing it; `max_queued_dummy_bytes` accounts
192+ * that one byte that can be partially received, thus not included
193+ * in the value from the RXFLR register.
194+ */
195+ if (fifo_room <= rx_fifo_items ) {
196+ return false;
197+ }
198+ fifo_room -= rx_fifo_items ;
199+
178200 if (dummy_bytes > fifo_room ) {
179201 dev_data -> dummy_bytes = dummy_bytes - fifo_room ;
180202
@@ -189,8 +211,10 @@ static bool tx_dummy_bytes(const struct device *dev)
189211 write_dr (dev , dummy_val );
190212 } while (-- dummy_bytes );
191213
192- /* Set the threshold to 0 to get the next interrupt when the FIFO is
193- * completely emptied.
214+ /* Set the TX start level to 0, so that the transmission will be
215+ * started now if it hasn't been yet. The threshold value is also
216+ * set to 0 here, but it doesn't really matter, as the interrupt
217+ * will be anyway disabled.
194218 */
195219 write_txftlr (dev , 0 );
196220
@@ -290,12 +314,16 @@ static void mspi_dw_isr(const struct device *dev)
290314
291315 if (int_status & ISR_TXEIS_BIT ) {
292316 if (tx_dummy_bytes (dev )) {
317+ /* All the required dummy bytes were
318+ * written to the FIFO; disable the TXE
319+ * interrupt, as it's no longer needed.
320+ */
293321 write_imr (dev , IMR_RXFIM_BIT );
294322 }
295323
296324 int_status = read_isr (dev );
297325 }
298- } while (int_status );
326+ } while (int_status != 0 );
299327 }
300328
301329 if (finished ) {
@@ -923,8 +951,11 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout)
923951 * clock stretching feature does not work yet, or in Standard
924952 * SPI mode, where the clock stretching is not available at all.
925953 */
926- write_txftlr (dev , FIELD_PREP (TXFTLR_TXFTHR_MASK ,
927- dev_config -> tx_fifo_depth_minus_1 ) |
954+ uint8_t start_level = dev_data -> dummy_bytes != 0
955+ ? dev_config -> max_queued_dummy_bytes - 1
956+ : dev_config -> tx_fifo_depth_minus_1 ;
957+
958+ write_txftlr (dev , FIELD_PREP (TXFTLR_TXFTHR_MASK , start_level ) |
928959 FIELD_PREP (TXFTLR_TFT_MASK ,
929960 dev_config -> tx_fifo_threshold ));
930961 } else {
@@ -1406,6 +1437,8 @@ static DEVICE_API(mspi, drv_api) = {
14061437 TX_FIFO_DEPTH(inst))
14071438#define MSPI_DW_FIFO_PROPS (inst ) \
14081439 .tx_fifo_depth_minus_1 = TX_FIFO_DEPTH(inst) - 1, \
1440+ .max_queued_dummy_bytes = MIN(RX_FIFO_DEPTH(inst) - 1, \
1441+ TX_FIFO_DEPTH(inst)), \
14091442 .tx_fifo_threshold = \
14101443 DT_INST_PROP_OR(inst, tx_fifo_threshold, \
14111444 7 * TX_FIFO_DEPTH(inst) / 8 - 1), \
0 commit comments