drivers/spi/spi-sn-f-ospi.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-sn-f-ospi.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-sn-f-ospi.c- Extension
.c- Size
- 16917 bytes
- Lines
- 674
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/io.hlinux/iopoll.hlinux/module.hlinux/mutex.hlinux/of.hlinux/platform_device.hlinux/spi/spi.hlinux/spi/spi-mem.h
Detected Declarations
struct f_ospifunction f_ospi_get_dummy_cyclefunction f_ospi_clear_irqfunction f_ospi_enable_irq_statusfunction f_ospi_disable_irq_statusfunction f_ospi_disable_irq_outputfunction f_ospi_prepare_configfunction f_ospi_unprepare_configfunction f_ospi_config_clkfunction f_ospi_config_dllfunction f_ospi_config_indir_protocolfunction f_ospi_indir_prepare_opfunction f_ospi_indir_start_xferfunction f_ospi_indir_stop_xferfunction f_ospi_indir_wait_xfer_completefunction f_ospi_indir_readfunction f_ospi_indir_writefunction f_ospi_exec_opfunction f_ospi_supports_op_widthfunction f_ospi_supports_opfunction f_ospi_adjust_op_sizefunction f_ospi_initfunction f_ospi_probe
Annotated Snippet
struct f_ospi {
void __iomem *base;
struct device *dev;
struct clk *clk;
struct mutex mlock;
};
static u32 f_ospi_get_dummy_cycle(const struct spi_mem_op *op)
{
if (!op->dummy.nbytes)
return 0;
return (op->dummy.nbytes * 8) / op->dummy.buswidth;
}
static void f_ospi_clear_irq(struct f_ospi *ospi)
{
writel(OSPI_IRQ_CS_DEASSERT | OSPI_IRQ_CS_TRANS_COMP,
ospi->base + OSPI_IRQ);
}
static void f_ospi_enable_irq_status(struct f_ospi *ospi, u32 irq_bits)
{
u32 val;
val = readl(ospi->base + OSPI_IRQ_STAT_EN);
val |= irq_bits;
writel(val, ospi->base + OSPI_IRQ_STAT_EN);
}
static void f_ospi_disable_irq_status(struct f_ospi *ospi, u32 irq_bits)
{
u32 val;
val = readl(ospi->base + OSPI_IRQ_STAT_EN);
val &= ~irq_bits;
writel(val, ospi->base + OSPI_IRQ_STAT_EN);
}
static void f_ospi_disable_irq_output(struct f_ospi *ospi, u32 irq_bits)
{
u32 val;
val = readl(ospi->base + OSPI_IRQ_SIG_EN);
val &= ~irq_bits;
writel(val, ospi->base + OSPI_IRQ_SIG_EN);
}
static int f_ospi_prepare_config(struct f_ospi *ospi)
{
u32 val, stat0, stat1;
/* G4: Disable internal clock */
val = readl(ospi->base + OSPI_CLK_CTL);
val &= ~(OSPI_CLK_CTL_BOOT_INT_CLK_EN | OSPI_CLK_CTL_INT_CLK_EN);
writel(val, ospi->base + OSPI_CLK_CTL);
/* G5: Wait for stop */
stat0 = OSPI_STAT_IS_AXI_WRITING | OSPI_STAT_IS_AXI_READING;
stat1 = OSPI_STAT_IS_SPI_IDLE | OSPI_STAT_IS_SPI_INT_CLK_STOP;
return readl_poll_timeout(ospi->base + OSPI_STAT,
val, (val & (stat0 | stat1)) == stat1,
0, OSPI_WAIT_MAX_MSEC);
}
static int f_ospi_unprepare_config(struct f_ospi *ospi)
{
u32 val;
/* G11: Enable internal clock */
val = readl(ospi->base + OSPI_CLK_CTL);
val |= OSPI_CLK_CTL_BOOT_INT_CLK_EN | OSPI_CLK_CTL_INT_CLK_EN;
writel(val, ospi->base + OSPI_CLK_CTL);
/* G12: Wait for clock to start */
return readl_poll_timeout(ospi->base + OSPI_STAT,
val, !(val & OSPI_STAT_IS_SPI_INT_CLK_STOP),
0, OSPI_WAIT_MAX_MSEC);
}
static void f_ospi_config_clk(struct f_ospi *ospi, u32 device_hz)
{
long rate_hz = clk_get_rate(ospi->clk);
u32 div = DIV_ROUND_UP(rate_hz, device_hz);
u32 div_reg;
u32 val;
if (rate_hz < device_hz) {
dev_warn(ospi->dev, "Device frequency too large: %d\n",
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/io.h`, `linux/iopoll.h`, `linux/module.h`, `linux/mutex.h`, `linux/of.h`, `linux/platform_device.h`.
- Detected declarations: `struct f_ospi`, `function f_ospi_get_dummy_cycle`, `function f_ospi_clear_irq`, `function f_ospi_enable_irq_status`, `function f_ospi_disable_irq_status`, `function f_ospi_disable_irq_output`, `function f_ospi_prepare_config`, `function f_ospi_unprepare_config`, `function f_ospi_config_clk`, `function f_ospi_config_dll`.
- 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.
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.