@@ -13,6 +13,8 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
13
13
#include <zephyr/sys/byteorder.h>
14
14
#include "spi_litex_common.h"
15
15
16
+ #define SPI_LITEX_ANY_HAS_IRQ DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts)
17
+
16
18
#define SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0x0
17
19
#define SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 0x1
18
20
#define SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_OFFSET 0x2
@@ -31,11 +33,19 @@ struct spi_litex_dev_config {
31
33
uint32_t core_master_status_addr ;
32
34
uint32_t phy_clk_divisor_addr ;
33
35
bool phy_clk_divisor_exists ;
36
+ #if SPI_LITEX_ANY_HAS_IRQ
37
+ bool has_irq ;
38
+ uint32_t core_master_ev_pending_addr ;
39
+ uint32_t core_master_ev_enable_addr ;
40
+ #endif
34
41
};
35
42
36
43
struct spi_litex_data {
37
44
struct spi_context ctx ;
38
45
uint8_t dfs ; /* dfs in bytes: 1,2 or 4 */
46
+ #if SPI_LITEX_ANY_HAS_IRQ
47
+ struct k_sem sem_rx_ready ;
48
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
39
49
};
40
50
41
51
@@ -134,6 +144,26 @@ static void spiflash_len_mask_width_write(uint32_t len, uint32_t width, uint32_t
134
144
litex_write32 (word , addr );
135
145
}
136
146
147
+ static void spi_litex_wait_for_rx_ready (const struct device * dev )
148
+ {
149
+ const struct spi_litex_dev_config * dev_config = dev -> config ;
150
+
151
+ #if SPI_LITEX_ANY_HAS_IRQ
152
+ struct spi_litex_data * data = dev -> data ;
153
+
154
+ if (dev_config -> has_irq ) {
155
+ /* Wait for the RX ready event */
156
+ k_sem_take (& data -> sem_rx_ready , K_FOREVER );
157
+ return ;
158
+ }
159
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
160
+
161
+ while (!(litex_read8 (dev_config -> core_master_status_addr ) &
162
+ BIT (SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET ))) {
163
+ ;
164
+ }
165
+ }
166
+
137
167
static int spi_litex_xfer (const struct device * dev , const struct spi_config * config )
138
168
{
139
169
const struct spi_litex_dev_config * dev_config = dev -> config ;
@@ -158,6 +188,14 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
158
188
LOG_DBG ("flushed rxd: 0x%x" , rxd );
159
189
}
160
190
191
+ #if SPI_LITEX_ANY_HAS_IRQ
192
+ if (dev_config -> has_irq ) {
193
+ litex_write8 (BIT (0 ), dev_config -> core_master_ev_enable_addr );
194
+ litex_write8 (BIT (0 ), dev_config -> core_master_ev_pending_addr );
195
+ k_sem_reset (& data -> sem_rx_ready );
196
+ }
197
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
198
+
161
199
do {
162
200
len = MIN (spi_context_max_continuous_chunk (ctx ), dev_config -> core_master_rxtx_size );
163
201
if (len != old_len ) {
@@ -182,10 +220,7 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
182
220
183
221
spi_context_update_tx (ctx , data -> dfs , len / data -> dfs );
184
222
185
- while (!(litex_read8 (dev_config -> core_master_status_addr ) &
186
- BIT (SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET ))) {
187
- ;
188
- }
223
+ spi_litex_wait_for_rx_ready (dev );
189
224
190
225
rxd = litex_read32 (dev_config -> core_master_rxtx_addr );
191
226
LOG_DBG ("rxd: 0x%x" , rxd );
@@ -200,6 +235,12 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
200
235
201
236
litex_write32 (0 , dev_config -> core_master_cs_addr );
202
237
238
+ #if SPI_LITEX_ANY_HAS_IRQ
239
+ if (dev_config -> has_irq ) {
240
+ /* Wait for the RX ready event */
241
+ litex_write8 (0 , dev_config -> core_master_ev_enable_addr );
242
+ }
243
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
203
244
spi_context_complete (ctx , dev , 0 );
204
245
205
246
return ret ;
@@ -244,6 +285,21 @@ static int spi_litex_release(const struct device *dev, const struct spi_config *
244
285
return 0 ;
245
286
}
246
287
288
+ #if SPI_LITEX_ANY_HAS_IRQ
289
+ static void spi_litex_irq_handler (const struct device * dev )
290
+ {
291
+ struct spi_litex_data * data = dev -> data ;
292
+ const struct spi_litex_dev_config * dev_config = dev -> config ;
293
+
294
+ if (litex_read8 (dev_config -> core_master_ev_pending_addr ) & BIT (0 )) {
295
+ k_sem_give (& data -> sem_rx_ready );
296
+
297
+ /* ack reader irq */
298
+ litex_write8 (BIT (0 ), dev_config -> core_master_ev_pending_addr );
299
+ }
300
+ }
301
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
302
+
247
303
/* Device Instantiation */
248
304
static DEVICE_API (spi , spi_litex_api ) = {
249
305
.transceive = spi_litex_transceive ,
@@ -256,22 +312,51 @@ static DEVICE_API(spi, spi_litex_api) = {
256
312
.release = spi_litex_release ,
257
313
};
258
314
259
- #define SPI_INIT (n ) \
260
- static struct spi_litex_data spi_litex_data_##n = { \
261
- SPI_CONTEXT_INIT_LOCK(spi_litex_data_##n, ctx), \
262
- SPI_CONTEXT_INIT_SYNC(spi_litex_data_##n, ctx), \
263
- }; \
315
+ #define SPI_LITEX_IRQ (n ) \
316
+ BUILD_ASSERT(DT_INST_REG_HAS_NAME(n, core_master_ev_pending) && \
317
+ DT_INST_REG_HAS_NAME(n, core_master_ev_enable), "registers for interrupts missing"); \
318
+ \
319
+ static int spi_litex_irq_config##n(const struct device *dev) \
320
+ { \
321
+ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), spi_litex_irq_handler, \
322
+ DEVICE_DT_INST_GET(n), 0); \
323
+ \
324
+ irq_enable(DT_INST_IRQN(n)); \
325
+ \
326
+ return 0; \
327
+ };
328
+
329
+ #define SPI_LITEX_IRQ_DATA (n ) \
330
+ .sem_rx_ready = Z_SEM_INITIALIZER(spi_litex_data_##n.sem_rx_ready, 0, 1),
331
+
332
+ #define SPI_LITEX_IRQ_CONFIG (n ) \
333
+ .has_irq = DT_INST_IRQ_HAS_IDX(n, 0), \
334
+ .core_master_ev_pending_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, core_master_ev_pending, 0), \
335
+ .core_master_ev_enable_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, core_master_ev_enable, 0),
336
+
337
+ #define SPI_INIT (n ) \
338
+ IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (SPI_LITEX_IRQ(n))) \
339
+ \
340
+ static struct spi_litex_data spi_litex_data_##n = { \
341
+ SPI_CONTEXT_INIT_LOCK(spi_litex_data_##n, ctx), \
342
+ SPI_CONTEXT_INIT_SYNC(spi_litex_data_##n, ctx), \
343
+ IF_ENABLED(SPI_LITEX_ANY_HAS_IRQ, (SPI_LITEX_IRQ_DATA(n))) \
344
+ }; \
345
+ \
264
346
static struct spi_litex_dev_config spi_litex_cfg_##n = { \
265
347
.core_master_cs_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_cs), \
266
348
.core_master_phyconfig_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_phyconfig), \
267
349
.core_master_rxtx_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_rxtx), \
268
350
.core_master_rxtx_size = DT_INST_REG_SIZE_BY_NAME(n, core_master_rxtx), \
269
351
.core_master_status_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_status), \
270
352
.phy_clk_divisor_exists = DT_INST_REG_HAS_NAME(n, phy_clk_divisor), \
271
- .phy_clk_divisor_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, phy_clk_divisor, 0) \
272
- \
353
+ .phy_clk_divisor_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, phy_clk_divisor, 0), \
354
+ IF_ENABLED(SPI_LITEX_ANY_HAS_IRQ, (SPI_LITEX_IRQ_CONFIG(n))) \
273
355
}; \
274
- SPI_DEVICE_DT_INST_DEFINE(n, NULL, NULL, &spi_litex_data_##n, &spi_litex_cfg_##n, \
275
- POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_litex_api);
356
+ \
357
+ SPI_DEVICE_DT_INST_DEFINE(n, \
358
+ COND_CODE_1(DT_INST_IRQ_HAS_IDX(n, 0), (spi_litex_irq_config##n), (NULL)), NULL, \
359
+ &spi_litex_data_##n, &spi_litex_cfg_##n, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \
360
+ &spi_litex_api);
276
361
277
362
DT_INST_FOREACH_STATUS_OKAY (SPI_INIT )
0 commit comments