Skip to content

Commit ea1b19b

Browse files
committed
drivers: spi: litex: litespi: support interrupts
support interrupts for rx_ready, so we can use the time we are waiting for other stuff. Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
1 parent 2894d51 commit ea1b19b

File tree

1 file changed

+98
-13
lines changed

1 file changed

+98
-13
lines changed

drivers/spi/spi_litex_litespi.c

Lines changed: 98 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ LOG_MODULE_REGISTER(spi_litex_litespi);
1313
#include <zephyr/sys/byteorder.h>
1414
#include "spi_litex_common.h"
1515

16+
#define SPI_LITEX_ANY_HAS_IRQ DT_ANY_INST_HAS_PROP_STATUS_OKAY(interrupts)
17+
1618
#define SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0x0
1719
#define SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 0x1
1820
#define SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_OFFSET 0x2
@@ -31,11 +33,19 @@ struct spi_litex_dev_config {
3133
uint32_t core_master_status_addr;
3234
uint32_t phy_clk_divisor_addr;
3335
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
3441
};
3542

3643
struct spi_litex_data {
3744
struct spi_context ctx;
3845
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 */
3949
};
4050

4151

@@ -134,6 +144,26 @@ static void spiflash_len_mask_width_write(uint32_t len, uint32_t width, uint32_t
134144
litex_write32(word, addr);
135145
}
136146

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+
137167
static int spi_litex_xfer(const struct device *dev, const struct spi_config *config)
138168
{
139169
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
158188
LOG_DBG("flushed rxd: 0x%x", rxd);
159189
}
160190

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+
161199
do {
162200
len = MIN(spi_context_max_continuous_chunk(ctx), dev_config->core_master_rxtx_size);
163201
if (len != old_len) {
@@ -182,10 +220,7 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
182220

183221
spi_context_update_tx(ctx, data->dfs, len / data->dfs);
184222

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);
189224

190225
rxd = litex_read32(dev_config->core_master_rxtx_addr);
191226
LOG_DBG("rxd: 0x%x", rxd);
@@ -200,6 +235,12 @@ static int spi_litex_xfer(const struct device *dev, const struct spi_config *con
200235

201236
litex_write32(0, dev_config->core_master_cs_addr);
202237

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

205246
return ret;
@@ -244,6 +285,21 @@ static int spi_litex_release(const struct device *dev, const struct spi_config *
244285
return 0;
245286
}
246287

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+
247303
/* Device Instantiation */
248304
static DEVICE_API(spi, spi_litex_api) = {
249305
.transceive = spi_litex_transceive,
@@ -256,22 +312,51 @@ static DEVICE_API(spi, spi_litex_api) = {
256312
.release = spi_litex_release,
257313
};
258314

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+
\
264346
static struct spi_litex_dev_config spi_litex_cfg_##n = { \
265347
.core_master_cs_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_cs), \
266348
.core_master_phyconfig_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_phyconfig), \
267349
.core_master_rxtx_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_rxtx), \
268350
.core_master_rxtx_size = DT_INST_REG_SIZE_BY_NAME(n, core_master_rxtx), \
269351
.core_master_status_addr = DT_INST_REG_ADDR_BY_NAME(n, core_master_status), \
270352
.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))) \
273355
}; \
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);
276361

277362
DT_INST_FOREACH_STATUS_OKAY(SPI_INIT)

0 commit comments

Comments
 (0)