Skip to content

Commit 3a14073

Browse files
committed
WIP: use async
Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
1 parent cbb48a2 commit 3a14073

File tree

1 file changed

+113
-77
lines changed

1 file changed

+113
-77
lines changed

drivers/spi/spi_litex_litespi.c

Lines changed: 113 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
1414
#include "spi_litex_common.h"
1515

1616
#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)
1720

1821
#define SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0x0
1922
#define SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 0x1
@@ -25,6 +28,9 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
2528
#define SPI_MAX_WORD_SIZE 32
2629
#define SPI_MAX_CS_SIZE 4
2730

31+
#define SPI_LITEX_WIDTH BIT(0)
32+
#define SPI_LITEX_MASK BIT(0)
33+
2834
struct spi_litex_dev_config {
2935
uint32_t core_master_cs_addr;
3036
uint32_t core_master_phyconfig_addr;
@@ -43,9 +49,7 @@ struct spi_litex_dev_config {
4349
struct spi_litex_data {
4450
struct spi_context ctx;
4551
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 */
52+
uint8_t len; /* length of the last transfer in bytes */
4953
};
5054

5155

@@ -93,11 +97,6 @@ static int spi_config(const struct device *dev, const struct spi_config *config)
9397
return -ENOTSUP;
9498
}
9599

96-
if (config->operation & SPI_LOCK_ON) {
97-
LOG_ERR("Lock On not supported");
98-
return -ENOTSUP;
99-
}
100-
101100
if (IS_ENABLED(CONFIG_SPI_EXTENDED_MODES) &&
102101
(config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) {
103102
LOG_ERR("Only supports single mode");
@@ -144,40 +143,63 @@ static void spiflash_len_mask_width_write(uint32_t len, uint32_t width, uint32_t
144143
litex_write32(word, addr);
145144
}
146145

147-
static void spi_litex_wait_for_rx_ready(const struct device *dev)
146+
static void spi_litex_spi_do_tx(const struct device *dev)
148147
{
149148
const struct spi_litex_dev_config *dev_config = dev->config;
150-
151-
#if SPI_LITEX_ANY_HAS_IRQ
152149
struct spi_litex_data *data = dev->data;
150+
struct spi_context *ctx = &data->ctx;
151+
uint8_t len;
152+
uint32_t txd = 0U;
153+
154+
len = MIN(spi_context_max_continuous_chunk(ctx), dev_config->core_master_rxtx_size);
155+
if (len != data->len) {
156+
spiflash_len_mask_width_write(len * 8, SPI_LITEX_WIDTH, SPI_LITEX_MASK,
157+
dev_config->core_master_phyconfig_addr);
158+
data->len = len;
159+
}
153160

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;
161+
if (spi_context_tx_buf_on(ctx)) {
162+
litex_spi_tx_put(len, &txd, ctx->tx_buf);
158163
}
159-
#endif /* SPI_LITEX_ANY_HAS_IRQ */
160164

161-
while (!(litex_read8(dev_config->core_master_status_addr) &
162-
BIT(SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET))) {
163-
;
165+
LOG_DBG("txd: 0x%x", txd);
166+
litex_write32(txd, dev_config->core_master_rxtx_addr);
167+
168+
spi_context_update_tx(ctx, data->dfs, len / data->dfs);
169+
}
170+
171+
static void spi_litex_spi_do_rx(const struct device *dev)
172+
{
173+
const struct spi_litex_dev_config *dev_config = dev->config;
174+
struct spi_litex_data *data = dev->data;
175+
struct spi_context *ctx = &data->ctx;
176+
uint32_t rxd;
177+
178+
rxd = litex_read32(dev_config->core_master_rxtx_addr);
179+
LOG_DBG("rxd: 0x%x", rxd);
180+
181+
if (spi_context_rx_buf_on(ctx)) {
182+
litex_spi_rx_put(data->len, &rxd, ctx->rx_buf);
164183
}
184+
185+
spi_context_update_rx(ctx, data->dfs, data->len / data->dfs);
165186
}
166187

167188
static int spi_litex_xfer(const struct device *dev, const struct spi_config *config)
168189
{
169190
const struct spi_litex_dev_config *dev_config = dev->config;
170191
struct spi_litex_data *data = dev->data;
171192
struct spi_context *ctx = &data->ctx;
172-
uint32_t txd, rxd;
193+
uint32_t rxd;
173194
int ret = 0;
174195

175-
uint8_t len = data->dfs; /* SPI Xfer length*/
176-
uint8_t old_len = len; /* old SPI Xfer length*/
177196
uint8_t width = BIT(0); /* SPI Xfer width*/
178197
uint8_t mask = BIT(0); /* SPI Xfer mask*/
179198

180-
spiflash_len_mask_width_write(len * 8, width, mask, dev_config->core_master_phyconfig_addr);
199+
data->len = MIN(spi_context_max_continuous_chunk(ctx), dev_config->core_master_rxtx_size);
200+
201+
spiflash_len_mask_width_write(data->len * 8, SPI_LITEX_WIDTH, SPI_LITEX_MASK,
202+
dev_config->core_master_phyconfig_addr);
181203

182204
litex_write32(BIT(config->slave), dev_config->core_master_cs_addr);
183205

@@ -188,79 +210,71 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
188210
LOG_DBG("flushed rxd: 0x%x", rxd);
189211
}
190212

213+
while (!(litex_read8(dev_config->core_master_status_addr) &
214+
BIT(SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET))) {
215+
;
216+
}
217+
191218
#if SPI_LITEX_ANY_HAS_IRQ
192-
if (dev_config->has_irq) {
219+
if (SPI_LITEX_HAS_IRQ) {
193220
litex_write8(BIT(0), dev_config->core_master_ev_enable_addr);
194221
litex_write8(BIT(0), dev_config->core_master_ev_pending_addr);
195-
k_sem_reset(&data->sem_rx_ready);
222+
223+
spi_litex_spi_do_tx(dev);
224+
225+
ret = spi_context_wait_for_completion(ctx);
226+
227+
spi_context_release(ctx, ret);
228+
229+
return ret;
196230
}
197231
#endif /* SPI_LITEX_ANY_HAS_IRQ */
198232

199233
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-
}
234+
spi_litex_spi_do_tx(dev);
212235

213236
while (!(litex_read8(dev_config->core_master_status_addr) &
214-
BIT(SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET))) {
237+
BIT(SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET))) {
215238
;
216239
}
217240

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-
241+
spi_litex_spi_do_rx(dev);
234242
} while (spi_context_tx_on(ctx) || spi_context_rx_on(ctx));
235243

236244
litex_write32(0, dev_config->core_master_cs_addr);
237245

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 */
244246
spi_context_complete(ctx, dev, 0);
245247

246248
return ret;
247249
}
248250

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)
251+
static int transceive(const struct device *dev,
252+
const struct spi_config *config,
253+
const struct spi_buf_set *tx_bufs,
254+
const struct spi_buf_set *rx_bufs,
255+
bool asynchronous,
256+
spi_callback_t cb,
257+
void *userdata)
252258
{
253259
struct spi_litex_data *data = dev->data;
254-
255-
int ret = spi_config(dev, config);
256-
257-
if (ret) {
258-
return ret;
259-
}
260+
int ret;
260261

261262
if (!tx_bufs && !rx_bufs) {
262263
return 0;
263264
}
265+
#if SPI_LITEX_ANY_HAS_IRQ
266+
if (!SPI_LITEX_HAS_IRQ && asynchronous) {
267+
return -ENOTSUP;
268+
}
269+
#endif /* SPI_LITEX_ANY_HAS_IRQ */
270+
271+
spi_context_lock(&data->ctx, asynchronous, cb, userdata, config);
272+
273+
ret = spi_config(dev, config);
274+
275+
if (ret < 0) {
276+
return ret;
277+
}
264278

265279
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, data->dfs);
266280

@@ -269,19 +283,31 @@ static int spi_litex_transceive(const struct device *dev, const struct spi_confi
269283
return ret;
270284
}
271285

286+
static int spi_litex_transceive(const struct device *dev,
287+
const struct spi_config *config,
288+
const struct spi_buf_set *tx_bufs,
289+
const struct spi_buf_set *rx_bufs)
290+
{
291+
return transceive(dev, config, tx_bufs, rx_bufs, false, NULL, NULL);
292+
}
293+
272294
#ifdef CONFIG_SPI_ASYNC
273-
static int spi_litex_transceive_async(const struct device *dev, const struct spi_config *config,
295+
static int spi_litex_transceive_async(const struct device *dev,
296+
const struct spi_config *config,
274297
const struct spi_buf_set *tx_bufs,
275298
const struct spi_buf_set *rx_bufs,
276-
struct k_poll_signal *async)
299+
spi_callback_t cb,
300+
void *userdata)
277301
{
278-
return -ENOTSUP;
302+
return transceive(dev, config, tx_bufs, rx_bufs, true, cb, userdata);
279303
}
280304
#endif /* CONFIG_SPI_ASYNC */
281305

282306
static int spi_litex_release(const struct device *dev, const struct spi_config *config)
283307
{
308+
struct spi_litex_data *data = dev->data;
284309

310+
spi_context_unlock_unconditionally(&data->ctx);
285311
return 0;
286312
}
287313

@@ -290,12 +316,26 @@ static void spi_litex_irq_handler(const struct device *dev)
290316
{
291317
struct spi_litex_data *data = dev->data;
292318
const struct spi_litex_dev_config *dev_config = dev->config;
319+
struct spi_context *ctx = &data->ctx;
320+
uint32_t txd, rxd;
321+
uint8_t len;
322+
uint8_t old_len;
293323

294324
if (litex_read8(dev_config->core_master_ev_pending_addr) & BIT(0)) {
295-
k_sem_give(&data->sem_rx_ready);
325+
spi_litex_spi_do_rx(dev);
296326

297327
/* ack reader irq */
298328
litex_write8(BIT(0), dev_config->core_master_ev_pending_addr);
329+
330+
if (spi_context_tx_on(ctx) || spi_context_rx_on(ctx)) {
331+
spi_litex_spi_do_tx(dev);
332+
} else {
333+
litex_write8(0, dev_config->core_master_ev_enable_addr);
334+
335+
litex_write32(0, dev_config->core_master_cs_addr);
336+
337+
spi_context_complete(ctx, dev, 0);
338+
}
299339
}
300340
}
301341
#endif /* SPI_LITEX_ANY_HAS_IRQ */
@@ -326,9 +366,6 @@ static DEVICE_API(spi, spi_litex_api) = {
326366
return 0; \
327367
};
328368

329-
#define SPI_LITEX_IRQ_DATA(n) \
330-
.sem_rx_ready = Z_SEM_INITIALIZER(spi_litex_data_##n.sem_rx_ready, 0, 1),
331-
332369
#define SPI_LITEX_IRQ_CONFIG(n) \
333370
.has_irq = DT_INST_IRQ_HAS_IDX(n, 0), \
334371
.core_master_ev_pending_addr = DT_INST_REG_ADDR_BY_NAME_OR(n, core_master_ev_pending, 0), \
@@ -340,7 +377,6 @@ static DEVICE_API(spi, spi_litex_api) = {
340377
static struct spi_litex_data spi_litex_data_##n = { \
341378
SPI_CONTEXT_INIT_LOCK(spi_litex_data_##n, ctx), \
342379
SPI_CONTEXT_INIT_SYNC(spi_litex_data_##n, ctx), \
343-
IF_ENABLED(SPI_LITEX_ANY_HAS_IRQ, (SPI_LITEX_IRQ_DATA(n))) \
344380
}; \
345381
\
346382
static struct spi_litex_dev_config spi_litex_cfg_##n = { \

0 commit comments

Comments
 (0)