drivers/spi/spi-amlogic-spifc-a1.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-amlogic-spifc-a1.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-amlogic-spifc-a1.c- Extension
.c- Size
- 12817 bytes
- Lines
- 466
- 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/bitfield.hlinux/clk.hlinux/device.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_runtime.hlinux/spi/spi.hlinux/spi/spi-mem.hlinux/types.h
Detected Declarations
struct amlogic_spifc_a1function amlogic_spifc_a1_requestfunction amlogic_spifc_a1_drain_bufferfunction amlogic_spifc_a1_fill_bufferfunction amlogic_spifc_a1_user_initfunction amlogic_spifc_a1_set_cmdfunction amlogic_spifc_a1_set_addrfunction amlogic_spifc_a1_set_dummyfunction amlogic_spifc_a1_readfunction amlogic_spifc_a1_writefunction amlogic_spifc_a1_set_freqfunction amlogic_spifc_a1_exec_opfunction amlogic_spifc_a1_adjust_op_sizefunction amlogic_spifc_a1_hw_initfunction amlogic_spifc_a1_probefunction amlogic_spifc_a1_suspendfunction amlogic_spifc_a1_resumefunction amlogic_spifc_a1_runtime_suspendfunction amlogic_spifc_a1_runtime_resume
Annotated Snippet
struct amlogic_spifc_a1 {
struct spi_controller *ctrl;
struct clk *clk;
struct device *dev;
void __iomem *base;
u32 curr_speed_hz;
};
static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read)
{
u32 mask = SPIFC_A1_USER_REQUEST_FINISH |
(read ? SPIFC_A1_USER_DATA_UPDATED : 0);
u32 val;
writel(SPIFC_A1_USER_REQUEST_ENABLE,
spifc->base + SPIFC_A1_USER_CTRL0_REG);
return readl_poll_timeout(spifc->base + SPIFC_A1_USER_CTRL0_REG,
val, (val & mask) == mask, 0,
200 * USEC_PER_MSEC);
}
static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc,
char *buf, u32 len)
{
u32 data;
const u32 count = len / sizeof(data);
const u32 pad = len % sizeof(data);
writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
spifc->base + SPIFC_A1_DBUF_CTRL_REG);
ioread32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);
if (pad) {
data = readl(spifc->base + SPIFC_A1_DBUF_DATA_REG);
memcpy(buf + len - pad, &data, pad);
}
}
static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1 *spifc,
const char *buf, u32 len)
{
u32 data;
const u32 count = len / sizeof(data);
const u32 pad = len % sizeof(data);
writel(SPIFC_A1_DBUF_DIR | SPIFC_A1_DBUF_AUTO_UPDATE_ADDR,
spifc->base + SPIFC_A1_DBUF_CTRL_REG);
iowrite32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count);
if (pad) {
memcpy(&data, buf + len - pad, pad);
writel(data, spifc->base + SPIFC_A1_DBUF_DATA_REG);
}
}
static void amlogic_spifc_a1_user_init(struct amlogic_spifc_a1 *spifc)
{
writel(0, spifc->base + SPIFC_A1_USER_CTRL0_REG);
writel(0, spifc->base + SPIFC_A1_USER_CTRL1_REG);
writel(0, spifc->base + SPIFC_A1_USER_CTRL2_REG);
writel(0, spifc->base + SPIFC_A1_USER_CTRL3_REG);
}
static void amlogic_spifc_a1_set_cmd(struct amlogic_spifc_a1 *spifc,
u32 cmd_cfg)
{
u32 val;
val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
val &= ~(SPIFC_A1_USER_CMD_MODE | SPIFC_A1_USER_CMD_CODE);
val |= cmd_cfg;
writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
}
static void amlogic_spifc_a1_set_addr(struct amlogic_spifc_a1 *spifc, u32 addr,
u32 addr_cfg)
{
u32 val;
writel(addr, spifc->base + SPIFC_A1_USER_ADDR_REG);
val = readl(spifc->base + SPIFC_A1_USER_CTRL1_REG);
val &= ~(SPIFC_A1_USER_ADDR_MODE | SPIFC_A1_USER_ADDR_BYTES);
val |= addr_cfg;
writel(val, spifc->base + SPIFC_A1_USER_CTRL1_REG);
}
static void amlogic_spifc_a1_set_dummy(struct amlogic_spifc_a1 *spifc,
u32 dummy_cfg)
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/device.h`, `linux/io.h`, `linux/iopoll.h`, `linux/kernel.h`, `linux/module.h`, `linux/of.h`.
- Detected declarations: `struct amlogic_spifc_a1`, `function amlogic_spifc_a1_request`, `function amlogic_spifc_a1_drain_buffer`, `function amlogic_spifc_a1_fill_buffer`, `function amlogic_spifc_a1_user_init`, `function amlogic_spifc_a1_set_cmd`, `function amlogic_spifc_a1_set_addr`, `function amlogic_spifc_a1_set_dummy`, `function amlogic_spifc_a1_read`, `function amlogic_spifc_a1_write`.
- 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.