drivers/spi/spi-ar934x.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-ar934x.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-ar934x.c- Extension
.c- Size
- 5944 bytes
- Lines
- 234
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/spi/spi.h
Detected Declarations
struct ar934x_spifunction ar934x_spi_clk_divfunction ar934x_spi_setupfunction ar934x_spi_transfer_one_messagefunction ar934x_spi_probefunction ar934x_spi_remove
Annotated Snippet
struct ar934x_spi {
struct spi_controller *ctlr;
void __iomem *base;
struct clk *clk;
unsigned int clk_freq;
};
static inline int ar934x_spi_clk_div(struct ar934x_spi *sp, unsigned int freq)
{
int div = DIV_ROUND_UP(sp->clk_freq, freq * 2) - 1;
if (div < 0)
return 0;
else if (div > AR934X_SPI_CLK_MASK)
return -EINVAL;
else
return div;
}
static int ar934x_spi_setup(struct spi_device *spi)
{
struct ar934x_spi *sp = spi_controller_get_devdata(spi->controller);
if ((spi->max_speed_hz == 0) ||
(spi->max_speed_hz > (sp->clk_freq / 2))) {
spi->max_speed_hz = sp->clk_freq / 2;
} else if (spi->max_speed_hz < (sp->clk_freq / 128)) {
dev_err(&spi->dev, "spi clock is too low\n");
return -EINVAL;
}
return 0;
}
static int ar934x_spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *m)
{
struct ar934x_spi *sp = spi_controller_get_devdata(ctlr);
struct spi_transfer *t = NULL;
struct spi_device *spi = m->spi;
unsigned long trx_done, trx_cur;
int stat = 0;
u8 bpw, term = 0;
int div, i;
u32 reg;
const u8 *tx_buf;
u8 *buf;
m->actual_length = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->bits_per_word >= 8 && t->bits_per_word < 32)
bpw = t->bits_per_word >> 3;
else
bpw = 4;
if (t->speed_hz)
div = ar934x_spi_clk_div(sp, t->speed_hz);
else
div = ar934x_spi_clk_div(sp, spi->max_speed_hz);
if (div < 0) {
stat = -EIO;
goto msg_done;
}
reg = ioread32(sp->base + AR934X_SPI_REG_CTRL);
reg &= ~AR934X_SPI_CLK_MASK;
reg |= div;
iowrite32(reg, sp->base + AR934X_SPI_REG_CTRL);
iowrite32(0, sp->base + AR934X_SPI_DATAOUT);
for (trx_done = 0; trx_done < t->len; trx_done += bpw) {
trx_cur = t->len - trx_done;
if (trx_cur > bpw)
trx_cur = bpw;
else if (list_is_last(&t->transfer_list, &m->transfers))
term = 1;
if (t->tx_buf) {
tx_buf = t->tx_buf + trx_done;
reg = tx_buf[0];
for (i = 1; i < trx_cur; i++)
reg = reg << 8 | tx_buf[i];
iowrite32(reg, sp->base + AR934X_SPI_DATAOUT);
}
reg = AR934X_SPI_SHIFT_VAL(spi_get_chipselect(spi, 0), term,
trx_cur * 8);
iowrite32(reg, sp->base + AR934X_SPI_REG_SHIFT_CTRL);
stat = readl_poll_timeout(
sp->base + AR934X_SPI_REG_SHIFT_CTRL, reg,
Annotation
- Immediate include surface: `linux/clk.h`, `linux/io.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/module.h`, `linux/of.h`, `linux/platform_device.h`, `linux/spi/spi.h`.
- Detected declarations: `struct ar934x_spi`, `function ar934x_spi_clk_div`, `function ar934x_spi_setup`, `function ar934x_spi_transfer_one_message`, `function ar934x_spi_probe`, `function ar934x_spi_remove`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
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.