drivers: spi: add Data Fusion Subsystem SPI driver
Introduce DesignWare ARC Data Fusion IP Subsystem(DFSS) SPI driver for ARC boards, i.e. EMSDP, which uses DW SPI to controll SPI-Flash and DFSS SPI to connect external devices. Both drivers share most source code, but DFSS uses ARC auxiliary registers. Move FIFO depth setting to device tree. Signed-off-by: Siyuan Cheng <siyuanc@synopsys.com>
This commit is contained in:
parent
37aad05883
commit
cbdd2f38da
|
@ -19,14 +19,4 @@ config I2C_DW_CLOCK_SPEED
|
|||
|
||||
endif # I2C_DW
|
||||
|
||||
if SPI_DW
|
||||
|
||||
config SPI_DW_FIFO_DEPTH
|
||||
default 32
|
||||
|
||||
config SPI_DW_ARC_AUX_REGS
|
||||
default n
|
||||
|
||||
endif # SPI_DW
|
||||
|
||||
endif # BOARD_EM_STARTERKIT
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_ARC_MPU_ENABLE arc_mpu_regions.c)
|
||||
zephyr_sources(platform.c)
|
||||
|
|
|
@ -21,16 +21,6 @@ if SPI
|
|||
config SPI_DW
|
||||
default y
|
||||
|
||||
if SPI_DW
|
||||
|
||||
config SPI_DW_FIFO_DEPTH
|
||||
default 32
|
||||
|
||||
config SPI_DW_ARC_AUX_REGS
|
||||
default n
|
||||
|
||||
endif # SPI_DW
|
||||
|
||||
endif # SPI
|
||||
|
||||
endif # BOARD_EMSDP
|
||||
|
|
23
boards/arc/emsdp/platform.c
Normal file
23
boards/arc/emsdp/platform.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Synopsys
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/arch/cpu.h>
|
||||
#include <zephyr/init.h>
|
||||
|
||||
#define DFSS_SPI0_BASE 0x80010000
|
||||
#define DFSS_SPI1_BASE 0x80010100
|
||||
#define REG_CLK_ENA_OFFSET (0x16) /* DFSS only */
|
||||
|
||||
/* Enable clock for DFSS SPI0 controller & DFSS SPI1 controller */
|
||||
static int emsdp_dfss_clock_init(void)
|
||||
{
|
||||
sys_out32(1, DFSS_SPI0_BASE + REG_CLK_ENA_OFFSET);
|
||||
sys_out32(1, DFSS_SPI1_BASE + REG_CLK_ENA_OFFSET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(emsdp_dfss_clock_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
|
@ -18,12 +18,6 @@ endif # GPIO
|
|||
|
||||
if SPI_DW
|
||||
|
||||
config SPI_DW_FIFO_DEPTH
|
||||
default 32
|
||||
|
||||
config SPI_DW_ARC_AUX_REGS
|
||||
default n
|
||||
|
||||
config SPI_DW_ACCESS_WORD_ONLY
|
||||
default y
|
||||
|
||||
|
|
|
@ -21,11 +21,6 @@ config USB_DEVICE_DRIVER
|
|||
default y
|
||||
endif # USB_DEVICE_STACK
|
||||
|
||||
if SPI_DW
|
||||
config SPI_DW_FIFO_DEPTH
|
||||
default 256
|
||||
endif # SPI_DW
|
||||
|
||||
if NETWORKING
|
||||
|
||||
config NET_L2_ETHERNET
|
||||
|
|
|
@ -18,22 +18,6 @@ menuconfig SPI_DW
|
|||
|
||||
if SPI_DW
|
||||
|
||||
config SPI_DW_ARC_AUX_REGS
|
||||
bool "Registers are part of ARC auxiliary registers"
|
||||
depends on ARC
|
||||
default y
|
||||
help
|
||||
SPI IP block registers are part of user extended auxiliary
|
||||
registers and thus their access is different than memory
|
||||
mapped registers.
|
||||
|
||||
config SPI_DW_FIFO_DEPTH
|
||||
int "RX and TX FIFO Depth"
|
||||
help
|
||||
Corresponds to the SSI_TX_FIFO_DEPTH and
|
||||
SSI_RX_FIFO_DEPTH of the DesignWare Synchronous
|
||||
Serial Interface. Depth ranges from 2-256.
|
||||
|
||||
config SPI_DW_ACCESS_WORD_ONLY
|
||||
bool "DesignWare SPI only allows word access"
|
||||
help
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
* Copyright (c) 2023 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -47,6 +48,10 @@ LOG_MODULE_REGISTER(spi_dw);
|
|||
#include "spi_dw.h"
|
||||
#include "spi_context.h"
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#endif
|
||||
|
||||
static inline bool spi_dw_is_slave(struct spi_dw_data *spi)
|
||||
{
|
||||
return (IS_ENABLED(CONFIG_SPI_SLAVE) &&
|
||||
|
@ -69,13 +74,13 @@ 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->regs)) {
|
||||
while (test_bit_sr_busy(info)) {
|
||||
}
|
||||
|
||||
/* Disabling interrupts */
|
||||
write_imr(DW_SPI_IMR_MASK, info->regs);
|
||||
write_imr(info, DW_SPI_IMR_MASK);
|
||||
/* Disabling the controller */
|
||||
clear_bit_ssienr(info->regs);
|
||||
clear_bit_ssienr(info);
|
||||
|
||||
spi_context_cs_control(&spi->ctx, false);
|
||||
|
||||
|
@ -95,13 +100,13 @@ static void push_data(const struct device *dev)
|
|||
DBG_COUNTER_INIT();
|
||||
|
||||
if (spi_context_rx_on(&spi->ctx)) {
|
||||
f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs) -
|
||||
read_rxflr(info->regs);
|
||||
f_tx = info->fifo_depth - read_txflr(info) -
|
||||
read_rxflr(info);
|
||||
if ((int)f_tx < 0) {
|
||||
f_tx = 0U; /* if rx-fifo is full, hold off tx */
|
||||
}
|
||||
} else {
|
||||
f_tx = DW_SPI_FIFO_DEPTH - read_txflr(info->regs);
|
||||
f_tx = info->fifo_depth - read_txflr(info);
|
||||
}
|
||||
|
||||
while (f_tx) {
|
||||
|
@ -136,7 +141,7 @@ static void push_data(const struct device *dev)
|
|||
break;
|
||||
}
|
||||
|
||||
write_dr(data, info->regs);
|
||||
write_dr(info, data);
|
||||
|
||||
spi_context_update_tx(&spi->ctx, spi->dfs, 1);
|
||||
spi->fifo_diff++;
|
||||
|
@ -148,7 +153,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(0, info->regs);
|
||||
write_txftlr(info, 0);
|
||||
}
|
||||
|
||||
LOG_DBG("Pushed: %d", DBG_COUNTER_RESULT());
|
||||
|
@ -161,8 +166,8 @@ static void pull_data(const struct device *dev)
|
|||
|
||||
DBG_COUNTER_INIT();
|
||||
|
||||
while (read_rxflr(info->regs)) {
|
||||
uint32_t data = read_dr(info->regs);
|
||||
while (read_rxflr(info)) {
|
||||
uint32_t data = read_dr(info);
|
||||
|
||||
DBG_COUNTER_INC();
|
||||
|
||||
|
@ -186,10 +191,10 @@ static void pull_data(const struct device *dev)
|
|||
spi->fifo_diff--;
|
||||
}
|
||||
|
||||
if (!spi->ctx.rx_len && spi->ctx.tx_len < DW_SPI_FIFO_DEPTH) {
|
||||
write_rxftlr(spi->ctx.tx_len - 1, info->regs);
|
||||
} else if (read_rxftlr(info->regs) >= spi->ctx.rx_len) {
|
||||
write_rxftlr(spi->ctx.rx_len - 1, info->regs);
|
||||
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);
|
||||
}
|
||||
|
||||
LOG_DBG("Pulled: %d", DBG_COUNTER_RESULT());
|
||||
|
@ -254,16 +259,16 @@ static int spi_dw_configure(const struct spi_dw_config *info,
|
|||
}
|
||||
|
||||
/* Installing the configuration */
|
||||
write_ctrlr0(ctrlr0, info->regs);
|
||||
write_ctrlr0(info, 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(SPI_DW_CLK_DIVIDER(info->clock_frequency,
|
||||
config->frequency), info->regs);
|
||||
write_ser(1 << config->slave, info->regs);
|
||||
write_baudr(info, SPI_DW_CLK_DIVIDER(info->clock_frequency,
|
||||
config->frequency));
|
||||
write_ser(info, 1 << config->slave);
|
||||
}
|
||||
|
||||
if (spi_dw_is_slave(spi)) {
|
||||
|
@ -319,19 +324,20 @@ error:
|
|||
static void spi_dw_update_txftlr(const struct spi_dw_config *info,
|
||||
struct spi_dw_data *spi)
|
||||
{
|
||||
uint32_t reg_data = DW_SPI_TXFTLR_DFLT;
|
||||
uint32_t dw_spi_txftlr_dflt = (info->fifo_depth * 1) / 2;
|
||||
uint32_t reg_data = dw_spi_txftlr_dflt;
|
||||
|
||||
if (spi_dw_is_slave(spi)) {
|
||||
if (!spi->ctx.tx_len) {
|
||||
reg_data = 0U;
|
||||
} else if (spi->ctx.tx_len < DW_SPI_TXFTLR_DFLT) {
|
||||
} else if (spi->ctx.tx_len < dw_spi_txftlr_dflt) {
|
||||
reg_data = spi->ctx.tx_len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("TxFTLR: %u", reg_data);
|
||||
|
||||
write_txftlr(reg_data, info->regs);
|
||||
write_txftlr(info, reg_data);
|
||||
}
|
||||
|
||||
static int transceive(const struct device *dev,
|
||||
|
@ -345,6 +351,7 @@ static int transceive(const struct device *dev,
|
|||
const struct spi_dw_config *info = dev->config;
|
||||
struct spi_dw_data *spi = dev->data;
|
||||
uint32_t tmod = DW_SPI_CTRLR0_TMOD_TX_RX;
|
||||
uint32_t dw_spi_rxftlr_dflt = (info->fifo_depth * 5) / 8;
|
||||
uint32_t reg_data;
|
||||
int ret;
|
||||
|
||||
|
@ -380,9 +387,9 @@ static int transceive(const struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
write_ctrlr1(reg_data, info->regs);
|
||||
write_ctrlr1(info, reg_data);
|
||||
} else {
|
||||
write_ctrlr1(0, info->regs);
|
||||
write_ctrlr1(info, 0);
|
||||
}
|
||||
|
||||
if (spi_dw_is_slave(spi)) {
|
||||
|
@ -395,11 +402,11 @@ static int transceive(const struct device *dev,
|
|||
}
|
||||
|
||||
/* Updating TMOD in CTRLR0 register */
|
||||
reg_data = read_ctrlr0(info->regs);
|
||||
reg_data = read_ctrlr0(info);
|
||||
reg_data &= ~DW_SPI_CTRLR0_TMOD_RESET;
|
||||
reg_data |= tmod;
|
||||
|
||||
write_ctrlr0(reg_data, info->regs);
|
||||
write_ctrlr0(info, reg_data);
|
||||
|
||||
/* Set buffers info */
|
||||
spi_context_buffers_setup(&spi->ctx, tx_bufs, rx_bufs, spi->dfs);
|
||||
|
@ -410,32 +417,32 @@ static int transceive(const struct device *dev,
|
|||
spi_dw_update_txftlr(info, spi);
|
||||
|
||||
/* Does Rx thresholds needs to be lower? */
|
||||
reg_data = DW_SPI_RXFTLR_DFLT;
|
||||
reg_data = dw_spi_rxftlr_dflt;
|
||||
|
||||
if (spi_dw_is_slave(spi)) {
|
||||
if (spi->ctx.rx_len &&
|
||||
spi->ctx.rx_len < DW_SPI_RXFTLR_DFLT) {
|
||||
spi->ctx.rx_len < dw_spi_rxftlr_dflt) {
|
||||
reg_data = spi->ctx.rx_len - 1;
|
||||
}
|
||||
} else {
|
||||
if (spi->ctx.rx_len && spi->ctx.rx_len < DW_SPI_FIFO_DEPTH) {
|
||||
if (spi->ctx.rx_len && spi->ctx.rx_len < info->fifo_depth) {
|
||||
reg_data = spi->ctx.rx_len - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rx Threshold */
|
||||
write_rxftlr(reg_data, info->regs);
|
||||
write_rxftlr(info, reg_data);
|
||||
|
||||
/* Enable interrupts */
|
||||
reg_data = !rx_bufs ?
|
||||
DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_RX :
|
||||
DW_SPI_IMR_UNMASK;
|
||||
write_imr(reg_data, info->regs);
|
||||
DW_SPI_IMR_UNMASK & DW_SPI_IMR_MASK_TX;
|
||||
write_imr(info, reg_data);
|
||||
|
||||
spi_context_cs_control(&spi->ctx, true);
|
||||
|
||||
LOG_DBG("Enabling controller");
|
||||
set_bit_ssienr(info->regs);
|
||||
set_bit_ssienr(info);
|
||||
|
||||
ret = spi_context_wait_for_completion(&spi->ctx);
|
||||
out:
|
||||
|
@ -490,10 +497,10 @@ void spi_dw_isr(const struct device *dev)
|
|||
uint32_t int_status;
|
||||
int error;
|
||||
|
||||
int_status = read_isr(info->regs);
|
||||
int_status = read_isr(info);
|
||||
|
||||
LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev,
|
||||
int_status, read_txflr(info->regs), read_rxflr(info->regs));
|
||||
LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status,
|
||||
read_txflr(info), read_rxflr(info));
|
||||
|
||||
if (int_status & DW_SPI_ISR_ERRORS_MASK) {
|
||||
error = -EIO;
|
||||
|
@ -511,7 +518,7 @@ void spi_dw_isr(const struct device *dev)
|
|||
}
|
||||
|
||||
out:
|
||||
clear_interrupts(info->regs);
|
||||
clear_interrupts(info);
|
||||
completed(dev, error);
|
||||
}
|
||||
|
||||
|
@ -529,11 +536,15 @@ int spi_dw_init(const struct device *dev)
|
|||
const struct spi_dw_config *info = dev->config;
|
||||
struct spi_dw_data *spi = dev->data;
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
pinctrl_apply_state(info->pcfg, PINCTRL_STATE_DEFAULT);
|
||||
#endif
|
||||
|
||||
info->config_func();
|
||||
|
||||
/* Masking interrupt and making sure controller is disabled */
|
||||
write_imr(DW_SPI_IMR_MASK, info->regs);
|
||||
clear_bit_ssienr(info->regs);
|
||||
write_imr(info, DW_SPI_IMR_MASK);
|
||||
clear_bit_ssienr(info);
|
||||
|
||||
LOG_DBG("Designware SPI driver initialized on device: %p", dev);
|
||||
|
||||
|
@ -565,11 +576,31 @@ struct spi_dw_data spi_dw_data_port_0 = {
|
|||
DT_INST_PROP(0, clock_frequency)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
PINCTRL_DT_INST_DEFINE(0);
|
||||
#endif
|
||||
const struct spi_dw_config spi_dw_config_0 = {
|
||||
.regs = DT_INST_REG_ADDR(0),
|
||||
.clock_frequency = INST_0_SNPS_DESIGNWARE_SPI_CLOCK_FREQ,
|
||||
.config_func = spi_config_0_irq,
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER,
|
||||
.fifo_depth = DT_INST_PROP(0, fifo_depth),
|
||||
#ifdef CONFIG_PINCTRL
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
|
||||
#endif
|
||||
#if DT_INST_PROP(0, aux_reg)
|
||||
.read_func = aux_reg_read,
|
||||
.write_func = aux_reg_write,
|
||||
.set_bit_func = aux_reg_set_bit,
|
||||
.clear_bit_func = aux_reg_clear_bit,
|
||||
.test_bit_func = aux_reg_test_bit
|
||||
#else
|
||||
.read_func = reg_read,
|
||||
.write_func = reg_write,
|
||||
.set_bit_func = reg_set_bit,
|
||||
.clear_bit_func = reg_clear_bit,
|
||||
.test_bit_func = reg_test_bit
|
||||
#endif
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, spi_dw_init, NULL,
|
||||
|
@ -592,17 +623,17 @@ void spi_config_0_irq(void)
|
|||
irq_enable(DT_INST_IRQN(0));
|
||||
#else
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, rx_avail, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, rx_avail_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, rx_avail, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(0),
|
||||
DT_INST_IRQ_BY_NAME(0, rx_avail, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, tx_req, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, tx_req_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, tx_req, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(0),
|
||||
DT_INST_IRQ_BY_NAME(0, tx_req, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, err_int, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, err_int_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(0, err_int, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(0),
|
||||
DT_INST_IRQ_BY_NAME(0, err_int, flags));
|
||||
0);
|
||||
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(0, rx_avail, irq));
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(0, tx_req, irq));
|
||||
|
@ -629,11 +660,31 @@ struct spi_dw_data spi_dw_data_port_1 = {
|
|||
DT_INST_PROP(1, clock_frequency)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
PINCTRL_DT_INST_DEFINE(1);
|
||||
#endif
|
||||
static const struct spi_dw_config spi_dw_config_1 = {
|
||||
.regs = DT_INST_REG_ADDR(1),
|
||||
.clock_frequency = INST_1_SNPS_DESIGNWARE_SPI_CLOCK_FREQ,
|
||||
.config_func = spi_config_1_irq,
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER,
|
||||
.fifo_depth = DT_INST_PROP(1, fifo_depth),
|
||||
#ifdef CONFIG_PINCTRL
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(1),
|
||||
#endif
|
||||
#if DT_INST_PROP(1, aux_reg)
|
||||
.read_func = aux_reg_read,
|
||||
.write_func = aux_reg_write,
|
||||
.set_bit_func = aux_reg_set_bit,
|
||||
.clear_bit_func = aux_reg_clear_bit,
|
||||
.test_bit_func = aux_reg_test_bit
|
||||
#else
|
||||
.read_func = reg_read,
|
||||
.write_func = reg_write,
|
||||
.set_bit_func = reg_set_bit,
|
||||
.clear_bit_func = reg_clear_bit,
|
||||
.test_bit_func = reg_test_bit
|
||||
#endif
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(1, spi_dw_init, NULL,
|
||||
|
@ -656,17 +707,17 @@ void spi_config_1_irq(void)
|
|||
irq_enable(DT_INST_IRQN(1));
|
||||
#else
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(1, rx_avail, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, rx_avail_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, rx_avail, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(1),
|
||||
DT_INST_IRQ_BY_NAME(1, rx_avail, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(1, tx_req, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, tx_req_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, tx_req, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(1),
|
||||
DT_INST_IRQ_BY_NAME(1, tx_req, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(1, err_int, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, err_int_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(1, err_int, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(1),
|
||||
DT_INST_IRQ_BY_NAME(1, err_int, flags));
|
||||
0);
|
||||
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(1, rx_avail, irq));
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(1, tx_req, irq));
|
||||
|
@ -693,11 +744,31 @@ struct spi_dw_data spi_dw_data_port_2 = {
|
|||
DT_INST_PROP(2, clock_frequency)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
PINCTRL_DT_INST_DEFINE(2);
|
||||
#endif
|
||||
static const struct spi_dw_config spi_dw_config_2 = {
|
||||
.regs = DT_INST_REG_ADDR(2),
|
||||
.clock_frequency = INST_2_SNPS_DESIGNWARE_SPI_CLOCK_FREQ,
|
||||
.config_func = spi_config_2_irq,
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER,
|
||||
.fifo_depth = DT_INST_PROP(2, fifo_depth),
|
||||
#ifdef CONFIG_PINCTRL
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(2),
|
||||
#endif
|
||||
#if DT_INST_PROP(2, aux_reg)
|
||||
.read_func = aux_reg_read,
|
||||
.write_func = aux_reg_write,
|
||||
.set_bit_func = aux_reg_set_bit,
|
||||
.clear_bit_func = aux_reg_clear_bit,
|
||||
.test_bit_func = aux_reg_test_bit
|
||||
#else
|
||||
.read_func = reg_read,
|
||||
.write_func = reg_write,
|
||||
.set_bit_func = reg_set_bit,
|
||||
.clear_bit_func = reg_clear_bit,
|
||||
.test_bit_func = reg_test_bit
|
||||
#endif
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(2, spi_dw_init, NULL,
|
||||
|
@ -720,17 +791,17 @@ void spi_config_2_irq(void)
|
|||
irq_enable(DT_INST_IRQN(2));
|
||||
#else
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(2, rx_avail, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, rx_avail_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, rx_avail, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(2),
|
||||
DT_INST_IRQ_BY_NAME(2, rx_avail, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(2, tx_req, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, tx_req_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, tx_req, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(2),
|
||||
DT_INST_IRQ_BY_NAME(2, tx_req, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(2, err_int, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, err_int_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(2, err_int, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(2),
|
||||
DT_INST_IRQ_BY_NAME(2, err_int, flags));
|
||||
0);
|
||||
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(2, rx_avail, irq));
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(2, tx_req, irq));
|
||||
|
@ -757,11 +828,31 @@ struct spi_dw_data spi_dw_data_port_3 = {
|
|||
DT_INST_PROP(3, clock_frequency)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PINCTRL
|
||||
PINCTRL_DT_INST_DEFINE(3);
|
||||
#endif
|
||||
static const struct spi_dw_config spi_dw_config_3 = {
|
||||
.regs = DT_INST_REG_ADDR(3),
|
||||
.clock_frequency = INST_3_SNPS_DESIGNWARE_SPI_CLOCK_FREQ,
|
||||
.config_func = spi_config_3_irq,
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER
|
||||
.op_modes = SPI_CTX_RUNTIME_OP_MODE_MASTER,
|
||||
.fifo_depth = DT_INST_PROP(3, fifo_depth),
|
||||
#ifdef CONFIG_PINCTRL
|
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(3),
|
||||
#endif
|
||||
#if DT_INST_PROP(3, aux_reg)
|
||||
.read_func = aux_reg_read,
|
||||
.write_func = aux_reg_write,
|
||||
.set_bit_func = aux_reg_set_bit,
|
||||
.clear_bit_func = aux_reg_clear_bit,
|
||||
.test_bit_func = aux_reg_test_bit
|
||||
#else
|
||||
.read_func = reg_read,
|
||||
.write_func = reg_write,
|
||||
.set_bit_func = reg_set_bit,
|
||||
.clear_bit_func = reg_clear_bit,
|
||||
.test_bit_func = reg_test_bit
|
||||
#endif
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(3, spi_dw_init, NULL,
|
||||
|
@ -784,17 +875,17 @@ void spi_config_3_irq(void)
|
|||
irq_enable(DT_INST_IRQN(3));
|
||||
#else
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(3, rx_avail, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, rx_avail_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, rx_avail, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(3),
|
||||
DT_INST_IRQ_BY_NAME(3, rx_avail, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(3, tx_req, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, tx_req_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, tx_req, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(3),
|
||||
DT_INST_IRQ_BY_NAME(3, tx_req, flags));
|
||||
0);
|
||||
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(3, err_int, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, err_int_pri, irq),
|
||||
DT_INST_IRQ_BY_NAME(3, err_int, priority),
|
||||
spi_dw_isr, DEVICE_DT_INST_GET(3),
|
||||
DT_INST_IRQ_BY_NAME(3, err_int, flags));
|
||||
0);
|
||||
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(3, rx_avail, irq));
|
||||
irq_enable(DT_INST_IRQ_BY_NAME(3, tx_req, irq));
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
* Copyright (c) 2023 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -19,6 +20,11 @@ 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);
|
||||
|
||||
/* Private structures */
|
||||
struct spi_dw_config {
|
||||
|
@ -26,6 +32,15 @@ struct spi_dw_config {
|
|||
uint32_t clock_frequency;
|
||||
spi_dw_config_t config_func;
|
||||
uint8_t op_modes;
|
||||
uint8_t fifo_depth;
|
||||
#ifdef CONFIG_PINCTRL
|
||||
const struct pinctrl_dev_config *pcfg;
|
||||
#endif
|
||||
spi_dw_read_t read_func;
|
||||
spi_dw_write_t write_func;
|
||||
spi_dw_set_bit_t set_bit_func;
|
||||
spi_dw_clear_bit_t clear_bit_func;
|
||||
spi_dw_test_bit_t test_bit_func;
|
||||
};
|
||||
|
||||
struct spi_dw_data {
|
||||
|
@ -35,52 +50,123 @@ struct spi_dw_data {
|
|||
uint16_t _unused;
|
||||
};
|
||||
|
||||
/* Register operation functions */
|
||||
#define DT_INST_NODE_PROP_NOT_OR(inst, prop) \
|
||||
!DT_INST_PROP(inst, prop) ||
|
||||
#define DT_ANY_INST_NOT_PROP_STATUS_OKAY(prop) \
|
||||
(DT_INST_FOREACH_STATUS_OKAY_VARGS(DT_INST_NODE_PROP_NOT_OR, prop) 0)
|
||||
|
||||
#define DT_INST_NODE_PROP_AND_OR(inst, prop) \
|
||||
DT_INST_PROP(inst, prop) ||
|
||||
#define DT_ANY_INST_PROP_STATUS_OKAY(prop) \
|
||||
(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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ARG_UNUSED(size);
|
||||
sys_out32(data, addr + off/4);
|
||||
}
|
||||
|
||||
static void aux_reg_set_bit(uint8_t bit, uint32_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)
|
||||
{
|
||||
sys_io_clear_bit(addr + off/4, bit);
|
||||
}
|
||||
|
||||
static int aux_reg_test_bit(uint8_t bit, uint32_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)
|
||||
{
|
||||
switch (size) {
|
||||
case 8:
|
||||
return sys_read8(addr + off);
|
||||
case 16:
|
||||
return sys_read16(addr + off);
|
||||
case 32:
|
||||
return sys_read32(addr + off);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void reg_write(uint8_t size, uint32_t data, uint32_t addr, uint32_t off)
|
||||
{
|
||||
switch (size) {
|
||||
case 8:
|
||||
sys_write8(data, addr + off); break;
|
||||
case 16:
|
||||
sys_write16(data, addr + off); break;
|
||||
case 32:
|
||||
sys_write32(data, addr + off); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void reg_set_bit(uint8_t bit, uint32_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)
|
||||
{
|
||||
sys_clear_bit(addr + off, bit);
|
||||
}
|
||||
|
||||
static int reg_test_bit(uint8_t bit, uint32_t addr, uint32_t off)
|
||||
{
|
||||
return sys_test_bit(addr + off, bit);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Helper macros */
|
||||
|
||||
#define SPI_DW_CLK_DIVIDER(clock_freq, ssi_clk_hz) \
|
||||
((clock_freq / ssi_clk_hz) & 0xFFFF)
|
||||
|
||||
#ifdef CONFIG_SPI_DW_ARC_AUX_REGS
|
||||
#define Z_REG_READ(__sz) sys_in##__sz
|
||||
#define Z_REG_WRITE(__sz) sys_out##__sz
|
||||
#define Z_REG_SET_BIT sys_io_set_bit
|
||||
#define Z_REG_CLEAR_BIT sys_io_clear_bit
|
||||
#define Z_REG_TEST_BIT sys_io_test_bit
|
||||
#else
|
||||
#define Z_REG_READ(__sz) sys_read##__sz
|
||||
#define Z_REG_WRITE(__sz) sys_write##__sz
|
||||
#define Z_REG_SET_BIT sys_set_bit
|
||||
#define Z_REG_CLEAR_BIT sys_clear_bit
|
||||
#define Z_REG_TEST_BIT sys_test_bit
|
||||
#endif /* CONFIG_SPI_DW_ARC_AUX_REGS */
|
||||
|
||||
#define DEFINE_MM_REG_READ(__reg, __off, __sz) \
|
||||
static inline uint32_t read_##__reg(uint32_t addr) \
|
||||
static inline uint32_t read_##__reg(const struct spi_dw_config *info) \
|
||||
{ \
|
||||
return Z_REG_READ(__sz)(addr + __off); \
|
||||
return info->read_func(__sz, info->regs, __off); \
|
||||
}
|
||||
#define DEFINE_MM_REG_WRITE(__reg, __off, __sz) \
|
||||
static inline void write_##__reg(uint32_t data, uint32_t addr) \
|
||||
static inline void write_##__reg(const struct spi_dw_config *info, uint32_t data)\
|
||||
{ \
|
||||
Z_REG_WRITE(__sz)(data, addr + __off); \
|
||||
info->write_func(__sz, data, info->regs, __off); \
|
||||
}
|
||||
|
||||
#define DEFINE_SET_BIT_OP(__reg_bit, __reg_off, __bit) \
|
||||
static inline void set_bit_##__reg_bit(uint32_t addr) \
|
||||
static inline void set_bit_##__reg_bit(const struct spi_dw_config *info) \
|
||||
{ \
|
||||
Z_REG_SET_BIT(addr + __reg_off, __bit); \
|
||||
info->set_bit_func(__bit, info->regs, __reg_off); \
|
||||
}
|
||||
|
||||
#define DEFINE_CLEAR_BIT_OP(__reg_bit, __reg_off, __bit) \
|
||||
static inline void clear_bit_##__reg_bit(uint32_t addr) \
|
||||
static inline void clear_bit_##__reg_bit(const struct spi_dw_config *info)\
|
||||
{ \
|
||||
Z_REG_CLEAR_BIT(addr + __reg_off, __bit); \
|
||||
info->clear_bit_func(__bit, info->regs, __reg_off); \
|
||||
}
|
||||
|
||||
#define DEFINE_TEST_BIT_OP(__reg_bit, __reg_off, __bit) \
|
||||
static inline int test_bit_##__reg_bit(uint32_t addr) \
|
||||
static inline int test_bit_##__reg_bit(const struct spi_dw_config *info)\
|
||||
{ \
|
||||
return Z_REG_TEST_BIT(addr + __reg_off, __bit); \
|
||||
return info->test_bit_func(__bit, info->regs, __reg_off); \
|
||||
}
|
||||
|
||||
/* Common registers settings, bits etc... */
|
||||
|
@ -126,6 +212,9 @@ struct spi_dw_data {
|
|||
/* SSIENR bits */
|
||||
#define DW_SPI_SSIENR_SSIEN_BIT (0)
|
||||
|
||||
/* CLK_ENA bits */
|
||||
#define DW_SPI_CLK_ENA_BIT (0)
|
||||
|
||||
/* SR bits and values */
|
||||
#define DW_SPI_SR_BUSY_BIT (0)
|
||||
#define DW_SPI_SR_TFNF_BIT (1)
|
||||
|
@ -163,23 +252,23 @@ struct spi_dw_data {
|
|||
/* ICR Bit */
|
||||
#define DW_SPI_SR_ICR_BIT (0)
|
||||
|
||||
/* Threshold defaults */
|
||||
#define DW_SPI_FIFO_DEPTH CONFIG_SPI_DW_FIFO_DEPTH
|
||||
#define DW_SPI_TXFTLR_DFLT ((DW_SPI_FIFO_DEPTH * 1) / 2) /* 50% */
|
||||
#define DW_SPI_RXFTLR_DFLT ((DW_SPI_FIFO_DEPTH * 5) / 8)
|
||||
|
||||
/* Interrupt mask (IMR) */
|
||||
#define DW_SPI_IMR_MASK (0x0)
|
||||
#define DW_SPI_IMR_UNMASK (DW_SPI_IMR_TXEIM | \
|
||||
DW_SPI_IMR_TXOIM | \
|
||||
DW_SPI_IMR_RXUIM | \
|
||||
DW_SPI_IMR_RXOIM | \
|
||||
DW_SPI_IMR_RXFIM)
|
||||
#define DW_SPI_IMR_MASK_TX (~(DW_SPI_IMR_TXEIM | \
|
||||
DW_SPI_IMR_TXOIM))
|
||||
#define DW_SPI_IMR_MASK_RX (~(DW_SPI_IMR_RXUIM | \
|
||||
DW_SPI_IMR_RXFIM | \
|
||||
DW_SPI_IMR_MSTIM)
|
||||
#define DW_SPI_IMR_MASK_TX (~(DW_SPI_IMR_RXUIM | \
|
||||
DW_SPI_IMR_TXOIM | \
|
||||
DW_SPI_IMR_RXOIM | \
|
||||
DW_SPI_IMR_RXFIM))
|
||||
DW_SPI_IMR_MSTIM))
|
||||
#define DW_SPI_IMR_MASK_RX (~(DW_SPI_IMR_TXEIM |\
|
||||
DW_SPI_IMR_RXUIM | \
|
||||
DW_SPI_IMR_TXOIM | \
|
||||
DW_SPI_IMR_RXOIM | \
|
||||
DW_SPI_IMR_MSTIM))
|
||||
|
||||
/*
|
||||
* Including the right register definition file
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
* Copyright (c) 2023 Synopsys, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -63,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(addr) test_bit_icr(addr)
|
||||
#define clear_interrupts(info) test_bit_icr(info)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0020000 0x100>;
|
||||
interrupts = <40 1>;
|
||||
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -194,6 +194,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0021000 0x100>;
|
||||
interrupts = <41 1>;
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -203,6 +204,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0022000 0x100>;
|
||||
interrupts = <42 1>;
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0020000 0x1000>;
|
||||
interrupts = <40 1>;
|
||||
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -194,6 +194,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0021000 0x1000>;
|
||||
interrupts = <41 1>;
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -203,6 +204,7 @@
|
|||
#size-cells = <0>;
|
||||
reg = <0xf0022000 0x1000>;
|
||||
interrupts = <42 1>;
|
||||
fifo-depth = <32>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
compatible = "snps,designware-spi";
|
||||
reg = <0xf0008000 0x1000>;
|
||||
clocks = <&spiclk>;
|
||||
fifo-depth = <32>;
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -105,6 +106,7 @@
|
|||
compatible = "snps,designware-spi";
|
||||
reg = <0xf1000000 0x1000>;
|
||||
clocks = <&spiclk>;
|
||||
fifo-depth = <32>;
|
||||
interrupt-parent = <&intc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
reg = <0xf0006000 0x1000>;
|
||||
clocks = <&sysclk>;
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
fifo-depth = <32>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
@ -158,7 +158,7 @@
|
|||
reg = <0xf0007000 0x1000>;
|
||||
clocks = <&sysclk>;
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
fifo-depth = <32>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
|
|
|
@ -243,6 +243,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfff00000 0x1000>;
|
||||
fifo-depth = <256>;
|
||||
interrupts = <0 154 4 IRQ_DEFAULT_PRIORITY>;
|
||||
clock-frequency = <200000000>;
|
||||
status = "okay";
|
||||
|
@ -253,6 +254,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfff01000 0x1000>;
|
||||
fifo-depth = <256>;
|
||||
interrupts = <0 155 4 IRQ_DEFAULT_PRIORITY>;
|
||||
clock-frequency = <200000000>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -5,7 +5,7 @@ description: Synopsys DesignWare SPI node
|
|||
|
||||
compatible: "snps,designware-spi"
|
||||
|
||||
include: spi-controller.yaml
|
||||
include: [spi-controller.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
|
@ -13,3 +13,16 @@ properties:
|
|||
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
aux_reg:
|
||||
description: |
|
||||
This value is used for auxiliary register access. For
|
||||
other platform, this value should be default 0.
|
||||
type: boolean
|
||||
|
||||
fifo-depth:
|
||||
type: int
|
||||
description: |
|
||||
RX/TX FIFO depth. Corresponds to the SSI_TX_FIFO_DEPTH
|
||||
and SSI_RX_FIFO_DEPTH of the DesignWare Synchronous
|
||||
Serial Interface. Depth ranges from 2-256.
|
||||
|
|
Loading…
Reference in a new issue