@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
14
14
#include "spi_litex_common.h"
15
15
16
16
#define SPI_LITEX_ANY_HAS_IRQ DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts)
17
+ #define SPI_LITEX_ALL_HAS_IRQ DT_ALL_INST_HAS_PROP_STATUS_OKAY(interrupts)
18
+
19
+ #define SPI_LITEX_HAS_IRQ (SPI_LITEX_ALL_HAS_IRQ || dev_config->has_irq)
17
20
18
21
#define SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0x0
19
22
#define SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 0x1
@@ -25,6 +28,9 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
25
28
#define SPI_MAX_WORD_SIZE 32
26
29
#define SPI_MAX_CS_SIZE 4
27
30
31
+ #define SPI_LITEX_WIDTH BIT(0)
32
+ #define SPI_LITEX_MASK BIT(0)
33
+
28
34
struct spi_litex_dev_config {
29
35
uint32_t core_master_cs_addr ;
30
36
uint32_t core_master_phyconfig_addr ;
@@ -35,6 +41,7 @@ struct spi_litex_dev_config {
35
41
bool phy_clk_divisor_exists ;
36
42
#if SPI_LITEX_ANY_HAS_IRQ
37
43
bool has_irq ;
44
+ void (* irq_config_func )(const struct device * dev );
38
45
uint32_t core_master_ev_pending_addr ;
39
46
uint32_t core_master_ev_enable_addr ;
40
47
#endif
@@ -43,9 +50,7 @@ struct spi_litex_dev_config {
43
50
struct spi_litex_data {
44
51
struct spi_context ctx ;
45
52
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 */
53
+ uint8_t len ; /* length of the last transfer in bytes */
49
54
};
50
55
51
56
@@ -93,11 +98,6 @@ static int spi_config(const struct device *dev, const struct spi_config *config)
93
98
return - ENOTSUP ;
94
99
}
95
100
96
- if (config -> operation & SPI_LOCK_ON ) {
97
- LOG_ERR ("Lock On not supported" );
98
- return - ENOTSUP ;
99
- }
100
-
101
101
if (IS_ENABLED (CONFIG_SPI_EXTENDED_MODES ) &&
102
102
(config -> operation & SPI_LINES_MASK ) != SPI_LINES_SINGLE ) {
103
103
LOG_ERR ("Only supports single mode" );
@@ -144,40 +144,54 @@ static void spiflash_len_mask_width_write(uint32_t len, uint32_t width, uint32_t
144
144
litex_write32 (word , addr );
145
145
}
146
146
147
- static void spi_litex_wait_for_rx_ready (const struct device * dev )
147
+ static void spi_litex_spi_do_tx (const struct device * dev )
148
148
{
149
149
const struct spi_litex_dev_config * dev_config = dev -> config ;
150
-
151
- #if SPI_LITEX_ANY_HAS_IRQ
152
150
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 ;
151
+ struct spi_context * ctx = & data -> ctx ;
152
+ uint8_t len ;
153
+ uint32_t txd = 0U ;
154
+
155
+ len = MIN (spi_context_max_continuous_chunk (ctx ), dev_config -> core_master_rxtx_size );
156
+ if (len != data -> len ) {
157
+ spiflash_len_mask_width_write (len * 8 , SPI_LITEX_WIDTH , SPI_LITEX_MASK ,
158
+ dev_config -> core_master_phyconfig_addr );
159
+ data -> len = len ;
158
160
}
159
- #endif /* SPI_LITEX_ANY_HAS_IRQ */
160
161
161
- while (!(litex_read8 (dev_config -> core_master_status_addr ) &
162
- BIT (SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET ))) {
163
- ;
162
+ if (spi_context_tx_buf_on (ctx )) {
163
+ litex_spi_tx_put (len , & txd , ctx -> tx_buf );
164
164
}
165
+
166
+ LOG_DBG ("txd: 0x%x" , txd );
167
+ litex_write32 (txd , dev_config -> core_master_rxtx_addr );
168
+
169
+ spi_context_update_tx (ctx , data -> dfs , len / data -> dfs );
165
170
}
166
171
167
- static int spi_litex_xfer (const struct device * dev , const struct spi_config * config )
172
+ static void spi_litex_spi_do_rx (const struct device * dev )
168
173
{
169
174
const struct spi_litex_dev_config * dev_config = dev -> config ;
170
175
struct spi_litex_data * data = dev -> data ;
171
176
struct spi_context * ctx = & data -> ctx ;
172
- uint32_t txd , rxd ;
173
- int ret = 0 ;
177
+ uint32_t rxd ;
178
+
179
+ rxd = litex_read32 (dev_config -> core_master_rxtx_addr );
180
+ LOG_DBG ("rxd: 0x%x" , rxd );
174
181
175
- uint8_t len = data -> dfs ; /* SPI Xfer length*/
176
- uint8_t old_len = len ; /* old SPI Xfer length*/
177
- uint8_t width = BIT (0 ); /* SPI Xfer width*/
178
- uint8_t mask = BIT (0 ); /* SPI Xfer mask*/
182
+ if (spi_context_rx_buf_on (ctx )) {
183
+ litex_spi_rx_put (data -> len , & rxd , ctx -> rx_buf );
184
+ }
185
+
186
+ spi_context_update_rx (ctx , data -> dfs , data -> len / data -> dfs );
187
+ }
179
188
180
- spiflash_len_mask_width_write (len * 8 , width , mask , dev_config -> core_master_phyconfig_addr );
189
+ static int spi_litex_xfer (const struct device * dev , const struct spi_config * config )
190
+ {
191
+ const struct spi_litex_dev_config * dev_config = dev -> config ;
192
+ struct spi_litex_data * data = dev -> data ;
193
+ struct spi_context * ctx = & data -> ctx ;
194
+ uint32_t rxd ;
181
195
182
196
litex_write32 (BIT (config -> slave ), dev_config -> core_master_cs_addr );
183
197
@@ -188,100 +202,105 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
188
202
LOG_DBG ("flushed rxd: 0x%x" , rxd );
189
203
}
190
204
205
+ while (!(litex_read8 (dev_config -> core_master_status_addr ) &
206
+ BIT (SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET ))) {
207
+ ;
208
+ }
209
+
191
210
#if SPI_LITEX_ANY_HAS_IRQ
192
- if (dev_config -> has_irq ) {
211
+ if (SPI_LITEX_HAS_IRQ ) {
193
212
litex_write8 (BIT (0 ), dev_config -> core_master_ev_enable_addr );
194
213
litex_write8 (BIT (0 ), dev_config -> core_master_ev_pending_addr );
195
- k_sem_reset (& data -> sem_rx_ready );
214
+
215
+ spi_litex_spi_do_tx (dev );
216
+
217
+ return spi_context_wait_for_completion (ctx );
196
218
}
197
219
#endif /* SPI_LITEX_ANY_HAS_IRQ */
198
220
199
221
do {
200
- len = MIN (spi_context_max_continuous_chunk (ctx ), dev_config -> core_master_rxtx_size );
201
- if (len != old_len ) {
202
- spiflash_len_mask_width_write (len * 8 , width , mask ,
203
- dev_config -> core_master_phyconfig_addr );
204
- old_len = len ;
205
- }
206
-
207
- if (spi_context_tx_buf_on (ctx )) {
208
- litex_spi_tx_put (len , & txd , ctx -> tx_buf );
209
- } else {
210
- txd = 0U ;
211
- }
222
+ spi_litex_spi_do_tx (dev );
212
223
213
224
while (!(litex_read8 (dev_config -> core_master_status_addr ) &
214
- BIT (SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET ))) {
225
+ BIT (SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET ))) {
215
226
;
216
227
}
217
228
218
- LOG_DBG ("txd: 0x%x" , txd );
219
- litex_write32 (txd , dev_config -> core_master_rxtx_addr );
220
-
221
- spi_context_update_tx (ctx , data -> dfs , len / data -> dfs );
222
-
223
- spi_litex_wait_for_rx_ready (dev );
224
-
225
- rxd = litex_read32 (dev_config -> core_master_rxtx_addr );
226
- LOG_DBG ("rxd: 0x%x" , rxd );
227
-
228
- if (spi_context_rx_buf_on (ctx )) {
229
- litex_spi_rx_put (len , & rxd , ctx -> rx_buf );
230
- }
231
-
232
- spi_context_update_rx (ctx , data -> dfs , len / data -> dfs );
233
-
229
+ spi_litex_spi_do_rx (dev );
234
230
} while (spi_context_tx_on (ctx ) || spi_context_rx_on (ctx ));
235
231
236
232
litex_write32 (0 , dev_config -> core_master_cs_addr );
237
233
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 */
244
234
spi_context_complete (ctx , dev , 0 );
245
235
246
- return ret ;
236
+ return 0 ;
247
237
}
248
238
249
- static int spi_litex_transceive (const struct device * dev , const struct spi_config * config ,
250
- const struct spi_buf_set * tx_bufs ,
251
- const struct spi_buf_set * rx_bufs )
239
+ static int transceive (const struct device * dev ,
240
+ const struct spi_config * config ,
241
+ const struct spi_buf_set * tx_bufs ,
242
+ const struct spi_buf_set * rx_bufs ,
243
+ bool asynchronous ,
244
+ spi_callback_t cb ,
245
+ void * userdata )
252
246
{
247
+ #if SPI_LITEX_ANY_HAS_IRQ
248
+ const struct spi_litex_dev_config * dev_config = dev -> config ;
249
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
253
250
struct spi_litex_data * data = dev -> data ;
254
-
255
- int ret = spi_config (dev , config );
256
-
257
- if (ret ) {
258
- return ret ;
259
- }
251
+ int ret ;
260
252
261
253
if (!tx_bufs && !rx_bufs ) {
262
254
return 0 ;
263
255
}
256
+ #if SPI_LITEX_ANY_HAS_IRQ
257
+ if (!SPI_LITEX_HAS_IRQ && asynchronous ) {
258
+ return - ENOTSUP ;
259
+ }
260
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
261
+
262
+ spi_context_lock (& data -> ctx , asynchronous , cb , userdata , config );
263
+
264
+ ret = spi_config (dev , config );
265
+
266
+ if (ret < 0 ) {
267
+ return ret ;
268
+ }
264
269
265
270
spi_context_buffers_setup (& data -> ctx , tx_bufs , rx_bufs , data -> dfs );
266
271
267
272
ret = spi_litex_xfer (dev , config );
268
273
274
+ spi_context_release (& data -> ctx , ret );
275
+
269
276
return ret ;
270
277
}
271
278
279
+ static int spi_litex_transceive (const struct device * dev ,
280
+ const struct spi_config * config ,
281
+ const struct spi_buf_set * tx_bufs ,
282
+ const struct spi_buf_set * rx_bufs )
283
+ {
284
+ return transceive (dev , config , tx_bufs , rx_bufs , false, NULL , NULL );
285
+ }
286
+
272
287
#ifdef CONFIG_SPI_ASYNC
273
- static int spi_litex_transceive_async (const struct device * dev , const struct spi_config * config ,
288
+ static int spi_litex_transceive_async (const struct device * dev ,
289
+ const struct spi_config * config ,
274
290
const struct spi_buf_set * tx_bufs ,
275
291
const struct spi_buf_set * rx_bufs ,
276
- struct k_poll_signal * async )
292
+ spi_callback_t cb ,
293
+ void * userdata )
277
294
{
278
- return - ENOTSUP ;
295
+ return transceive ( dev , config , tx_bufs , rx_bufs , true, cb , userdata ) ;
279
296
}
280
297
#endif /* CONFIG_SPI_ASYNC */
281
298
282
299
static int spi_litex_release (const struct device * dev , const struct spi_config * config )
283
300
{
301
+ struct spi_litex_data * data = dev -> data ;
284
302
303
+ spi_context_unlock_unconditionally (& data -> ctx );
285
304
return 0 ;
286
305
}
287
306
@@ -290,16 +309,48 @@ static void spi_litex_irq_handler(const struct device *dev)
290
309
{
291
310
struct spi_litex_data * data = dev -> data ;
292
311
const struct spi_litex_dev_config * dev_config = dev -> config ;
312
+ struct spi_context * ctx = & data -> ctx ;
293
313
294
314
if (litex_read8 (dev_config -> core_master_ev_pending_addr ) & BIT (0 )) {
295
- k_sem_give ( & data -> sem_rx_ready );
315
+ spi_litex_spi_do_rx ( dev );
296
316
297
317
/* ack reader irq */
298
318
litex_write8 (BIT (0 ), dev_config -> core_master_ev_pending_addr );
319
+
320
+ if (spi_context_tx_on (ctx ) || spi_context_rx_on (ctx )) {
321
+ spi_litex_spi_do_tx (dev );
322
+ } else {
323
+ litex_write8 (0 , dev_config -> core_master_ev_enable_addr );
324
+
325
+ litex_write32 (0 , dev_config -> core_master_cs_addr );
326
+
327
+ spi_context_complete (ctx , dev , 0 );
328
+ }
299
329
}
300
330
}
301
331
#endif /* SPI_LITEX_ANY_HAS_IRQ */
302
332
333
+ static int spi_litex_init (const struct device * dev )
334
+ {
335
+ const struct spi_litex_dev_config * dev_config = dev -> config ;
336
+ struct spi_litex_data * data = dev -> data ;
337
+
338
+ #if SPI_LITEX_ANY_HAS_IRQ
339
+ if (SPI_LITEX_HAS_IRQ ) {
340
+ dev_config -> irq_config_func (dev );
341
+ }
342
+ #endif /* SPI_LITEX_ANY_HAS_IRQ */
343
+
344
+ data -> len = dev_config -> master_rxtx_size ;
345
+
346
+ spiflash_len_mask_width_write (data -> len * 8 , SPI_LITEX_WIDTH , SPI_LITEX_MASK ,
347
+ dev_config -> master_phyconfig_addr );
348
+
349
+ spi_context_unlock_unconditionally (& data -> ctx );
350
+
351
+ return 0 ;
352
+ }
353
+
303
354
/* Device Instantiation */
304
355
static DEVICE_API (spi , spi_litex_api ) = {
305
356
.transceive = spi_litex_transceive ,
@@ -316,21 +367,18 @@ static DEVICE_API(spi, spi_litex_api) = {
316
367
BUILD_ASSERT(DT_INST_REG_HAS_NAME(n, core_master_ev_pending) && \
317
368
DT_INST_REG_HAS_NAME(n, core_master_ev_enable), "registers for interrupts missing"); \
318
369
\
319
- static int spi_litex_irq_config##n(const struct device *dev) \
370
+ static void spi_litex_irq_config##n(const struct device *dev) \
320
371
{ \
321
372
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), spi_litex_irq_handler, \
322
373
DEVICE_DT_INST_GET(n), 0); \
323
374
\
324
375
irq_enable(DT_INST_IRQN(n)); \
325
- \
326
- return 0; \
327
376
};
328
377
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
378
#define SPI_LITEX_IRQ_CONFIG (n ) \
333
379
.has_irq = DT_INST_IRQ_HAS_IDX(n, 0), \
380
+ .irq_config_func = COND_CODE_1(DT_INST_IRQ_HAS_IDX(n, 0), \
381
+ (spi_litex_irq_config##n), (NULL)), \
334
382
.core_master_ev_pending_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, core_master_ev_pending, 0), \
335
383
.core_master_ev_enable_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, core_master_ev_enable, 0),
336
384
@@ -340,7 +388,6 @@ static DEVICE_API(spi, spi_litex_api) = {
340
388
static struct spi_litex_data spi_litex_data_##n = { \
341
389
SPI_CONTEXT_INIT_LOCK(spi_litex_data_##n, ctx), \
342
390
SPI_CONTEXT_INIT_SYNC(spi_litex_data_##n, ctx), \
343
- IF_ENABLED(SPI_LITEX_ANY_HAS_IRQ, (SPI_LITEX_IRQ_DATA(n))) \
344
391
}; \
345
392
\
346
393
static struct spi_litex_dev_config spi_litex_cfg_##n = { \
@@ -355,8 +402,7 @@ static DEVICE_API(spi, spi_litex_api) = {
355
402
}; \
356
403
\
357
404
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);
405
+ spi_litex_init, NULL, &spi_litex_data_##n, &spi_litex_cfg_##n, POST_KERNEL, \
406
+ CONFIG_SPI_INIT_PRIORITY, &spi_litex_api);
361
407
362
408
DT_INST_FOREACH_STATUS_OKAY (SPI_INIT )
0 commit comments