From 30b6cd264769e040c8e5eca44c3ff1237bf6e29f Mon Sep 17 00:00:00 2001 From: Julien Panis Date: Mon, 22 Jan 2024 19:57:38 +0200 Subject: [PATCH] drivers: spi_dw: Manage MMIO and 64 bit platforms This patch manages DW SPI driver MMIO region. As a result, the driver now runs properly on 64 bit platforms. Signed-off-by: Julien Panis --- drivers/spi/spi_dw.c | 78 ++++++++++++++++++++------------------- drivers/spi/spi_dw.h | 59 ++++++++++++++++------------- drivers/spi/spi_dw_regs.h | 2 +- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/drivers/spi/spi_dw.c b/drivers/spi/spi_dw.c index 7126cac00a8..7f1620589d2 100644 --- a/drivers/spi/spi_dw.c +++ b/drivers/spi/spi_dw.c @@ -48,7 +48,6 @@ static inline bool spi_dw_is_slave(struct spi_dw_data *spi) static void completed(const struct device *dev, int error) { - const struct spi_dw_config *info = dev->config; struct spi_dw_data *spi = dev->data; struct spi_context *ctx = &spi->ctx; @@ -63,19 +62,19 @@ static void completed(const struct device *dev, int error) out: /* need to give time for FIFOs to drain before issuing more commands */ - while (test_bit_sr_busy(info)) { + while (test_bit_sr_busy(dev)) { } /* Disabling interrupts */ - write_imr(info, DW_SPI_IMR_MASK); + write_imr(dev, DW_SPI_IMR_MASK); /* Disabling the controller */ - clear_bit_ssienr(info); + clear_bit_ssienr(dev); if (!spi_dw_is_slave(spi)) { if (spi_cs_is_gpio(ctx->config)) { spi_context_cs_control(ctx, false); } else { - write_ser(info, 0); + write_ser(dev, 0); } } @@ -93,13 +92,13 @@ static void push_data(const struct device *dev) uint32_t f_tx; if (spi_context_rx_on(&spi->ctx)) { - f_tx = info->fifo_depth - read_txflr(info) - - read_rxflr(info); + f_tx = info->fifo_depth - read_txflr(dev) - + read_rxflr(dev); if ((int)f_tx < 0) { f_tx = 0U; /* if rx-fifo is full, hold off tx */ } } else { - f_tx = info->fifo_depth - read_txflr(info); + f_tx = info->fifo_depth - read_txflr(dev); } while (f_tx) { @@ -132,7 +131,7 @@ static void push_data(const struct device *dev) break; } - write_dr(info, data); + write_dr(dev, data); spi_context_update_tx(&spi->ctx, spi->dfs, 1); spi->fifo_diff++; @@ -142,7 +141,7 @@ static void push_data(const struct device *dev) if (!spi_context_tx_on(&spi->ctx)) { /* prevents any further interrupts demanding TX fifo fill */ - write_txftlr(info, 0); + write_txftlr(dev, 0); } } @@ -151,8 +150,8 @@ static void pull_data(const struct device *dev) const struct spi_dw_config *info = dev->config; struct spi_dw_data *spi = dev->data; - while (read_rxflr(info)) { - uint32_t data = read_dr(info); + while (read_rxflr(dev)) { + uint32_t data = read_dr(dev); if (spi_context_rx_buf_on(&spi->ctx)) { switch (spi->dfs) { @@ -173,16 +172,17 @@ static void pull_data(const struct device *dev) } if (!spi->ctx.rx_len && spi->ctx.tx_len < info->fifo_depth) { - write_rxftlr(info, spi->ctx.tx_len - 1); - } else if (read_rxftlr(info) >= spi->ctx.rx_len) { - write_rxftlr(info, spi->ctx.rx_len - 1); + write_rxftlr(dev, spi->ctx.tx_len - 1); + } else if (read_rxftlr(dev) >= spi->ctx.rx_len) { + write_rxftlr(dev, spi->ctx.rx_len - 1); } } -static int spi_dw_configure(const struct spi_dw_config *info, +static int spi_dw_configure(const struct device *dev, struct spi_dw_data *spi, const struct spi_config *config) { + const struct spi_dw_config *info = dev->config; uint32_t ctrlr0 = 0U; LOG_DBG("%p (prev %p)", config, spi->ctx.config); @@ -248,15 +248,15 @@ static int spi_dw_configure(const struct spi_dw_config *info, } /* Installing the configuration */ - write_ctrlr0(info, ctrlr0); + write_ctrlr0(dev, ctrlr0); /* At this point, it's mandatory to set this on the context! */ spi->ctx.config = config; if (!spi_dw_is_slave(spi)) { /* Baud rate and Slave select, for master only */ - write_baudr(info, SPI_DW_CLK_DIVIDER(info->clock_frequency, - config->frequency)); + write_baudr(dev, SPI_DW_CLK_DIVIDER(info->clock_frequency, + config->frequency)); } if (spi_dw_is_slave(spi)) { @@ -309,9 +309,10 @@ error: return UINT32_MAX; } -static void spi_dw_update_txftlr(const struct spi_dw_config *info, +static void spi_dw_update_txftlr(const struct device *dev, struct spi_dw_data *spi) { + const struct spi_dw_config *info = dev->config; uint32_t dw_spi_txftlr_dflt = (info->fifo_depth * 1) / 2; uint32_t reg_data = dw_spi_txftlr_dflt; @@ -325,7 +326,7 @@ static void spi_dw_update_txftlr(const struct spi_dw_config *info, LOG_DBG("TxFTLR: %u", reg_data); - write_txftlr(info, reg_data); + write_txftlr(dev, reg_data); } static int transceive(const struct device *dev, @@ -352,7 +353,7 @@ static int transceive(const struct device *dev, #endif /* CONFIG_PM_DEVICE */ /* Configure */ - ret = spi_dw_configure(info, spi, config); + ret = spi_dw_configure(dev, spi, config); if (ret) { goto out; } @@ -375,9 +376,9 @@ static int transceive(const struct device *dev, goto out; } - write_ctrlr1(info, reg_data); + write_ctrlr1(dev, reg_data); } else { - write_ctrlr1(info, 0); + write_ctrlr1(dev, 0); } if (spi_dw_is_slave(spi)) { @@ -390,11 +391,11 @@ static int transceive(const struct device *dev, } /* Updating TMOD in CTRLR0 register */ - reg_data = read_ctrlr0(info); + reg_data = read_ctrlr0(dev); reg_data &= ~DW_SPI_CTRLR0_TMOD_RESET; reg_data |= tmod; - write_ctrlr0(info, reg_data); + write_ctrlr0(dev, reg_data); /* Set buffers info */ spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs); @@ -402,7 +403,7 @@ static int transceive(const struct device *dev, spi->fifo_diff = 0U; /* Tx Threshold */ - spi_dw_update_txftlr(info, spi); + spi_dw_update_txftlr(dev, spi); /* Does Rx thresholds needs to be lower? */ reg_data = dw_spi_rxftlr_dflt; @@ -419,25 +420,25 @@ static int transceive(const struct device *dev, } /* Rx Threshold */ - write_rxftlr(info, reg_data); + write_rxftlr(dev, reg_data); /* Enable interrupts */ reg_data = !rx_bufs ? DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX : DW_SPI_IMR_UNMASK; - write_imr(info, reg_data); + write_imr(dev, reg_data); if (!spi_dw_is_slave(spi)) { /* if cs is not defined as gpio, use hw cs */ if (spi_cs_is_gpio(config)) { spi_context_cs_control(&spi->ctx, true); } else { - write_ser(info, BIT(config->slave)); + write_ser(dev, BIT(config->slave)); } } LOG_DBG("Enabling controller"); - set_bit_ssienr(info); + set_bit_ssienr(dev); ret = spi_context_wait_for_completion(&spi->ctx); @@ -495,14 +496,13 @@ static int spi_dw_release(const struct device *dev, void spi_dw_isr(const struct device *dev) { - const struct spi_dw_config *info = dev->config; uint32_t int_status; int error; - int_status = read_isr(info); + int_status = read_isr(dev); LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status, - read_txflr(info), read_rxflr(info)); + read_txflr(dev), read_rxflr(dev)); if (int_status & DW_SPI_ISR_ERRORS_MASK) { error = -EIO; @@ -520,7 +520,7 @@ void spi_dw_isr(const struct device *dev) } out: - clear_interrupts(info); + clear_interrupts(dev); completed(dev, error); } @@ -542,11 +542,13 @@ int spi_dw_init(const struct device *dev) pinctrl_apply_state(info->pcfg, PINCTRL_STATE_DEFAULT); #endif + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + info->config_func(); /* Masking interrupt and making sure controller is disabled */ - write_imr(info, DW_SPI_IMR_MASK); - clear_bit_ssienr(info); + write_imr(dev, DW_SPI_IMR_MASK); + clear_bit_ssienr(dev); LOG_DBG("Designware SPI driver initialized on device: %p", dev); @@ -595,7 +597,7 @@ COND_CODE_1(IS_EQ(DT_NUM_IRQS(DT_DRV_INST(inst)), 1), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx) \ }; \ static const struct spi_dw_config spi_dw_config_##inst = { \ - .regs = DT_INST_REG_ADDR(inst), \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ .clock_frequency = COND_CODE_1( \ DT_NODE_HAS_PROP(DT_INST_PHANDLE(inst, clocks), clock_frequency), \ (DT_INST_PROP_BY_PHANDLE(inst, clocks, clock_frequency)), \ diff --git a/drivers/spi/spi_dw.h b/drivers/spi/spi_dw.h index 54eeaa1ece1..d6383bc4ed2 100644 --- a/drivers/spi/spi_dw.h +++ b/drivers/spi/spi_dw.h @@ -11,6 +11,7 @@ #define ZEPHYR_DRIVERS_SPI_SPI_DW_H_ #include +#include #include #include "spi_context.h" @@ -20,15 +21,15 @@ extern "C" { #endif typedef void (*spi_dw_config_t)(void); -typedef uint32_t (*spi_dw_read_t)(uint8_t size, uint32_t addr, uint32_t off); -typedef void (*spi_dw_write_t)(uint8_t size, uint32_t data, uint32_t addr, uint32_t off); -typedef void (*spi_dw_set_bit_t)(uint8_t bit, uint32_t addr, uint32_t off); -typedef void (*spi_dw_clear_bit_t)(uint8_t bit, uint32_t addr, uint32_t off); -typedef int (*spi_dw_test_bit_t)(uint8_t bit, uint32_t addr, uint32_t off); +typedef uint32_t (*spi_dw_read_t)(uint8_t size, mm_reg_t addr, uint32_t off); +typedef void (*spi_dw_write_t)(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off); +typedef void (*spi_dw_set_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off); +typedef void (*spi_dw_clear_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off); +typedef int (*spi_dw_test_bit_t)(uint8_t bit, mm_reg_t addr, uint32_t off); /* Private structures */ struct spi_dw_config { - uint32_t regs; + DEVICE_MMIO_ROM; uint32_t clock_frequency; spi_dw_config_t config_func; bool serial_target; @@ -45,6 +46,7 @@ struct spi_dw_config { }; struct spi_dw_data { + DEVICE_MMIO_RAM; struct spi_context ctx; uint8_t dfs; /* dfs in bytes: 1,2 or 4 */ uint8_t fifo_diff; /* cannot be bigger than FIFO depth */ @@ -62,36 +64,36 @@ struct spi_dw_data { (DT_INST_FOREACH_STATUS_OKAY_VARGS(DT_INST_NODE_PROP_AND_OR, prop) 0) #if DT_ANY_INST_PROP_STATUS_OKAY(aux_reg) -static uint32_t aux_reg_read(uint8_t size, uint32_t addr, uint32_t off) +static uint32_t aux_reg_read(uint8_t size, mm_reg_t addr, uint32_t off) { ARG_UNUSED(size); return sys_in32(addr + off/4); } -static void aux_reg_write(uint8_t size, uint32_t data, uint32_t addr, uint32_t off) +static void aux_reg_write(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off) { ARG_UNUSED(size); sys_out32(data, addr + off/4); } -static void aux_reg_set_bit(uint8_t bit, uint32_t addr, uint32_t off) +static void aux_reg_set_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { sys_io_set_bit(addr + off/4, bit); } -static void aux_reg_clear_bit(uint8_t bit, uint32_t addr, uint32_t off) +static void aux_reg_clear_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { sys_io_clear_bit(addr + off/4, bit); } -static int aux_reg_test_bit(uint8_t bit, uint32_t addr, uint32_t off) +static int aux_reg_test_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { return sys_io_test_bit(addr + off/4, bit); } #endif #if DT_ANY_INST_NOT_PROP_STATUS_OKAY(aux_reg) -static uint32_t reg_read(uint8_t size, uint32_t addr, uint32_t off) +static uint32_t reg_read(uint8_t size, mm_reg_t addr, uint32_t off) { switch (size) { case 8: @@ -105,7 +107,7 @@ static uint32_t reg_read(uint8_t size, uint32_t addr, uint32_t off) } } -static void reg_write(uint8_t size, uint32_t data, uint32_t addr, uint32_t off) +static void reg_write(uint8_t size, uint32_t data, mm_reg_t addr, uint32_t off) { switch (size) { case 8: @@ -119,17 +121,17 @@ static void reg_write(uint8_t size, uint32_t data, uint32_t addr, uint32_t off) } } -static void reg_set_bit(uint8_t bit, uint32_t addr, uint32_t off) +static void reg_set_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { sys_set_bit(addr + off, bit); } -static void reg_clear_bit(uint8_t bit, uint32_t addr, uint32_t off) +static void reg_clear_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { sys_clear_bit(addr + off, bit); } -static int reg_test_bit(uint8_t bit, uint32_t addr, uint32_t off) +static int reg_test_bit(uint8_t bit, mm_reg_t addr, uint32_t off) { return sys_test_bit(addr + off, bit); } @@ -141,32 +143,37 @@ static int reg_test_bit(uint8_t bit, uint32_t addr, uint32_t off) ((clock_freq / ssi_clk_hz) & 0xFFFF) #define DEFINE_MM_REG_READ(__reg, __off, __sz) \ - static inline uint32_t read_##__reg(const struct spi_dw_config *info) \ + static inline uint32_t read_##__reg(const struct device *dev) \ { \ - return info->read_func(__sz, info->regs, __off); \ + const struct spi_dw_config *info = dev->config; \ + return info->read_func(__sz, (mm_reg_t)DEVICE_MMIO_GET(dev), __off); \ } #define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \ - static inline void write_##__reg(const struct spi_dw_config *info, uint32_t data)\ + static inline void write_##__reg(const struct device *dev, uint32_t data)\ { \ - info->write_func(__sz, data, info->regs, __off); \ + const struct spi_dw_config *info = dev->config; \ + info->write_func(__sz, data, (mm_reg_t)DEVICE_MMIO_GET(dev), __off); \ } #define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline void set_bit_##__reg_bit(const struct spi_dw_config *info) \ + static inline void set_bit_##__reg_bit(const struct device *dev) \ { \ - info->set_bit_func(__bit, info->regs, __reg_off); \ + const struct spi_dw_config *info = dev->config; \ + info->set_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \ } #define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline void clear_bit_##__reg_bit(const struct spi_dw_config *info)\ + static inline void clear_bit_##__reg_bit(const struct device *dev)\ { \ - info->clear_bit_func(__bit, info->regs, __reg_off); \ + const struct spi_dw_config *info = dev->config; \ + info->clear_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \ } #define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \ - static inline int test_bit_##__reg_bit(const struct spi_dw_config *info)\ + static inline int test_bit_##__reg_bit(const struct device *dev)\ { \ - return info->test_bit_func(__bit, info->regs, __reg_off); \ + const struct spi_dw_config *info = dev->config; \ + return info->test_bit_func(__bit, (mm_reg_t)DEVICE_MMIO_GET(dev), __reg_off); \ } /* Common registers settings, bits etc... */ diff --git a/drivers/spi/spi_dw_regs.h b/drivers/spi/spi_dw_regs.h index 4bb64eff1bd..711c6690091 100644 --- a/drivers/spi/spi_dw_regs.h +++ b/drivers/spi/spi_dw_regs.h @@ -64,7 +64,7 @@ DEFINE_MM_REG_WRITE(ser, DW_SPI_REG_SER, 8) /* ICR is on a unique bit */ DEFINE_TEST_BIT_OP(icr, DW_SPI_REG_ICR, DW_SPI_SR_ICR_BIT) -#define clear_interrupts(info) test_bit_icr(info) +#define clear_interrupts(dev) test_bit_icr(dev) #ifdef __cplusplus }