Skip to content

Commit 587dd5d

Browse files
Tomasz BursztykaAnas Nashif
authored andcommitted
drivers/spi: Add support for async call in DW driver in a generic way
All is done through the generic spi_context driver's API as it will be generic to all SPI drivers. Signed-off-by: Tomasz Bursztyka <[email protected]>
1 parent 761a1d9 commit 587dd5d

File tree

2 files changed

+71
-12
lines changed

2 files changed

+71
-12
lines changed

drivers/spi/spi_context.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ struct spi_context {
2525
struct k_sem lock;
2626
struct k_sem sync;
2727

28+
#ifdef CONFIG_POLL
29+
struct k_poll_signal *signal;
30+
bool asynchronous;
31+
#endif
2832
const struct spi_buf **current_tx;
2933
struct spi_buf **current_rx;
3034

@@ -46,24 +50,55 @@ static inline bool spi_context_configured(struct spi_context *ctx,
4650
return !!(ctx->config == config);
4751
}
4852

49-
static inline void spi_context_lock(struct spi_context *ctx)
53+
static inline void spi_context_lock(struct spi_context *ctx,
54+
bool asynchronous,
55+
struct k_poll_signal *signal)
5056
{
5157
k_sem_take(&ctx->lock, K_FOREVER);
58+
59+
#ifdef CONFIG_POLL
60+
ctx->asynchronous = asynchronous;
61+
ctx->signal = signal;
62+
#endif
5263
}
5364

54-
static inline void spi_context_release(struct spi_context *ctx)
65+
static inline void spi_context_release(struct spi_context *ctx, int status)
5566
{
67+
#ifdef CONFIG_POLL
68+
if (!ctx->asynchronous || status) {
69+
k_sem_give(&ctx->lock);
70+
}
71+
#else
5672
k_sem_give(&ctx->lock);
73+
#endif
5774
}
5875

5976
static inline void spi_context_wait_for_completion(struct spi_context *ctx)
6077
{
78+
#ifdef CONFIG_POLL
79+
if (!ctx->asynchronous) {
80+
k_sem_take(&ctx->sync, K_FOREVER);
81+
}
82+
#else
6183
k_sem_take(&ctx->sync, K_FOREVER);
84+
#endif
6285
}
6386

64-
static inline void spi_context_complete(struct spi_context *ctx)
87+
static inline void spi_context_complete(struct spi_context *ctx, int status)
6588
{
89+
#ifdef CONFIG_POLL
90+
if (!ctx->asynchronous) {
91+
k_sem_give(&ctx->sync);
92+
} else {
93+
if (ctx->signal) {
94+
k_poll_signal(ctx->signal, status);
95+
}
96+
97+
k_sem_give(&ctx->lock);
98+
}
99+
#else
66100
k_sem_give(&ctx->sync);
101+
#endif
67102
}
68103

69104
static inline void spi_context_cs_configure(struct spi_context *ctx)

drivers/spi/spi_dw.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static void completed(struct device *dev, uint8_t error)
7575
SYS_LOG_DBG("SPI transaction completed %s error",
7676
error ? "with" : "without");
7777

78-
spi_context_complete(&spi->ctx);
78+
spi_context_complete(&spi->ctx, error ? -EIO : 0);
7979
}
8080

8181
static void push_data(struct device *dev)
@@ -250,25 +250,25 @@ static int spi_dw_configure(const struct spi_dw_config *info,
250250
return 0;
251251
}
252252

253-
static int spi_dw_transceive(struct spi_config *config,
254-
const struct spi_buf **tx_bufs,
255-
struct spi_buf **rx_bufs)
253+
static int transceive(struct spi_config *config,
254+
const struct spi_buf **tx_bufs,
255+
struct spi_buf **rx_bufs,
256+
bool asynchronous,
257+
struct k_poll_signal *signal)
256258
{
257259
const struct spi_dw_config *info = config->dev->config->config_info;
258260
struct spi_dw_data *spi = config->dev->driver_data;
259261
u32_t rx_thsld = DW_SPI_RXFTLR_DFLT;
260262
u32_t imask = DW_SPI_IMR_UNMASK;
261263
int ret = 0;
262264

263-
SYS_LOG_DBG("%p, %p, %p", config->dev, tx_bufs, rx_bufs);
264-
265265
/* Check status */
266266
if (test_bit_ssienr(info->regs) || test_bit_sr_busy(info->regs)) {
267267
SYS_LOG_DBG("Controller is busy");
268268
return -EBUSY;
269269
}
270270

271-
spi_context_lock(&spi->ctx);
271+
spi_context_lock(&spi->ctx, asynchronous, signal);
272272

273273
/* Configure */
274274
ret = spi_dw_configure(info, spi, config);
@@ -311,11 +311,32 @@ static int spi_dw_transceive(struct spi_config *config,
311311
ret = -EIO;
312312
}
313313
out:
314-
spi_context_release(&spi->ctx);
314+
spi_context_release(&spi->ctx, ret);
315315

316316
return ret;
317317
}
318318

319+
static int spi_dw_transceive(struct spi_config *config,
320+
const struct spi_buf **tx_bufs,
321+
struct spi_buf **rx_bufs)
322+
{
323+
SYS_LOG_DBG("%p, %p, %p", config->dev, tx_bufs, rx_bufs);
324+
325+
return transceive(config, tx_bufs, rx_bufs, false, NULL);
326+
}
327+
328+
#ifdef CONFIG_POLL
329+
static int spi_dw_transceive_async(struct spi_config *config,
330+
const struct spi_buf **tx_bufs,
331+
struct spi_buf **rx_bufs,
332+
struct k_poll_signal *async)
333+
{
334+
SYS_LOG_DBG("%p, %p, %p, %p", config->dev, tx_bufs, rx_bufs, async);
335+
336+
return transceive(config, tx_bufs, rx_bufs, true, async);
337+
}
338+
#endif /* CONFIG_POLL */
339+
319340
void spi_dw_isr(struct device *dev)
320341
{
321342
const struct spi_dw_config *info = dev->config->config_info;
@@ -349,6 +370,9 @@ void spi_dw_isr(struct device *dev)
349370

350371
static const struct spi_driver_api dw_spi_api = {
351372
.transceive = spi_dw_transceive,
373+
#ifdef CONFIG_POLL
374+
.transceive_async = spi_dw_transceive_async,
375+
#endif
352376
};
353377

354378
int spi_dw_init(struct device *dev)
@@ -367,7 +391,7 @@ int spi_dw_init(struct device *dev)
367391

368392
SYS_LOG_DBG("Designware SPI driver initialized on device: %p", dev);
369393

370-
spi_context_release(&spi->ctx);
394+
spi_context_release(&spi->ctx, 0);
371395

372396
return 0;
373397
}

0 commit comments

Comments
 (0)