drivers/spi/spi-sunplus-sp7021.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-sunplus-sp7021.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-sunplus-sp7021.c- Extension
.c- Size
- 17041 bytes
- Lines
- 563
- Domain
- Driver Families
- Bucket
- drivers/spi
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/delay.hlinux/dma-mapping.hlinux/interrupt.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_runtime.hlinux/reset.hlinux/spi/spi.h
Detected Declarations
struct sp7021_spi_ctlrfunction sp7021_spi_target_irqfunction sp7021_spi_target_abortfunction sp7021_spi_target_txfunction sp7021_spi_target_rxfunction sp7021_spi_host_rbfunction sp7021_spi_host_wbfunction sp7021_spi_host_irqfunction sp7021_prep_transferfunction sp7021_spi_controller_prepare_messagefunction sp7021_spi_setup_clkfunction sp7021_spi_host_transfer_onefunction sp7021_spi_target_transfer_onefunction sp7021_spi_reset_control_assertfunction sp7021_spi_controller_probefunction sp7021_spi_controller_removefunction sp7021_spi_controller_suspendfunction sp7021_spi_controller_resumefunction sp7021_spi_runtime_suspendfunction sp7021_spi_runtime_resume
Annotated Snippet
struct sp7021_spi_ctlr {
struct device *dev;
struct spi_controller *ctlr;
void __iomem *m_base;
void __iomem *s_base;
u32 xfer_conf;
int mode;
int m_irq;
int s_irq;
struct clk *spi_clk;
struct reset_control *rstc;
// data xfer lock
struct mutex buf_lock;
struct completion isr_done;
struct completion target_isr;
unsigned int rx_cur_len;
unsigned int tx_cur_len;
unsigned int data_unit;
const u8 *tx_buf;
u8 *rx_buf;
};
static irqreturn_t sp7021_spi_target_irq(int irq, void *dev)
{
struct sp7021_spi_ctlr *pspim = dev;
unsigned int data_status;
data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG);
data_status |= SP7021_SLAVE_CLR_INT;
writel(data_status, pspim->s_base + SP7021_DATA_RDY_REG);
complete(&pspim->target_isr);
return IRQ_HANDLED;
}
static int sp7021_spi_target_abort(struct spi_controller *ctlr)
{
struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(ctlr);
complete(&pspim->target_isr);
complete(&pspim->isr_done);
return 0;
}
static int sp7021_spi_target_tx(struct spi_device *spi, struct spi_transfer *xfer)
{
struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
u32 value;
reinit_completion(&pspim->target_isr);
value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
value = readl(pspim->s_base + SP7021_DATA_RDY_REG);
value |= SP7021_SLAVE_DATA_RDY;
writel(value, pspim->s_base + SP7021_DATA_RDY_REG);
if (wait_for_completion_interruptible(&pspim->isr_done)) {
dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__);
return -EINTR;
}
return 0;
}
static int sp7021_spi_target_rx(struct spi_device *spi, struct spi_transfer *xfer)
{
struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller);
u32 value;
reinit_completion(&pspim->isr_done);
value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3);
writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG);
writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG);
if (wait_for_completion_interruptible(&pspim->isr_done)) {
dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__);
return -EINTR;
}
writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG);
return 0;
}
static void sp7021_spi_host_rb(struct sp7021_spi_ctlr *pspim, unsigned int len)
{
int i;
for (i = 0; i < len; i++) {
pspim->rx_buf[pspim->rx_cur_len] =
readl(pspim->m_base + SP7021_FIFO_REG);
pspim->rx_cur_len++;
}
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/delay.h`, `linux/dma-mapping.h`, `linux/interrupt.h`, `linux/module.h`, `linux/of.h`, `linux/platform_device.h`.
- Detected declarations: `struct sp7021_spi_ctlr`, `function sp7021_spi_target_irq`, `function sp7021_spi_target_abort`, `function sp7021_spi_target_tx`, `function sp7021_spi_target_rx`, `function sp7021_spi_host_rb`, `function sp7021_spi_host_wb`, `function sp7021_spi_host_irq`, `function sp7021_prep_transfer`, `function sp7021_spi_controller_prepare_message`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.