drivers/spi/spi-ep93xx.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-ep93xx.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-ep93xx.c- Extension
.c- Size
- 18820 bytes
- Lines
- 740
- 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.
- 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/io.hlinux/clk.hlinux/err.hlinux/delay.hlinux/device.hlinux/dma-direction.hlinux/dma-mapping.hlinux/dmaengine.hlinux/bitops.hlinux/interrupt.hlinux/module.hlinux/property.hlinux/platform_device.hlinux/sched.hlinux/scatterlist.hlinux/spi/spi.h
Detected Declarations
struct ep93xx_spifunction ep93xx_spi_calc_divisorsfunction ep93xx_spi_chip_setupfunction ep93xx_do_writefunction ep93xx_do_readfunction ep93xx_spi_read_writefunction ep93xx_dma_data_to_trans_dirfunction ep93xx_spi_dma_preparefunction ep93xx_spi_dma_finishfunction ep93xx_spi_dma_callbackfunction ep93xx_spi_dma_transferfunction ep93xx_spi_interruptfunction RORfunction RXfunction ep93xx_spi_transfer_onefunction ep93xx_spi_prepare_messagefunction ep93xx_spi_prepare_hardwarefunction ep93xx_spi_unprepare_hardwarefunction ep93xx_spi_setup_dmafunction ep93xx_spi_release_dmafunction ep93xx_spi_probefunction ep93xx_spi_remove
Annotated Snippet
struct ep93xx_spi {
struct clk *clk;
void __iomem *mmio;
unsigned long sspdr_phys;
size_t tx;
size_t rx;
size_t fifo_level;
struct dma_chan *dma_rx;
struct dma_chan *dma_tx;
struct sg_table rx_sgt;
struct sg_table tx_sgt;
void *zeropage;
};
/* converts bits per word to CR0.DSS value */
#define bits_per_word_to_dss(bpw) ((bpw) - 1)
/**
* ep93xx_spi_calc_divisors() - calculates SPI clock divisors
* @host: SPI host
* @rate: desired SPI output clock rate
* @div_cpsr: pointer to return the cpsr (pre-scaler) divider
* @div_scr: pointer to return the scr divider
*/
static int ep93xx_spi_calc_divisors(struct spi_controller *host,
u32 rate, u8 *div_cpsr, u8 *div_scr)
{
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
unsigned long spi_clk_rate = clk_get_rate(espi->clk);
int cpsr, scr;
/*
* Make sure that max value is between values supported by the
* controller.
*/
rate = clamp(rate, host->min_speed_hz, host->max_speed_hz);
/*
* Calculate divisors so that we can get speed according the
* following formula:
* rate = spi_clock_rate / (cpsr * (1 + scr))
*
* cpsr must be even number and starts from 2, scr can be any number
* between 0 and 255.
*/
for (cpsr = 2; cpsr <= 254; cpsr += 2) {
for (scr = 0; scr <= 255; scr++) {
if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
*div_scr = (u8)scr;
*div_cpsr = (u8)cpsr;
return 0;
}
}
}
return -EINVAL;
}
static int ep93xx_spi_chip_setup(struct spi_controller *host,
struct spi_device *spi,
struct spi_transfer *xfer)
{
struct ep93xx_spi *espi = spi_controller_get_devdata(host);
u8 dss = bits_per_word_to_dss(xfer->bits_per_word);
u8 div_cpsr = 0;
u8 div_scr = 0;
u16 cr0;
int err;
err = ep93xx_spi_calc_divisors(host, xfer->speed_hz,
&div_cpsr, &div_scr);
if (err)
return err;
cr0 = div_scr << SSPCR0_SCR_SHIFT;
if (spi->mode & SPI_CPOL)
cr0 |= SSPCR0_SPO;
if (spi->mode & SPI_CPHA)
cr0 |= SSPCR0_SPH;
cr0 |= dss;
dev_dbg(&host->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
spi->mode, div_cpsr, div_scr, dss);
dev_dbg(&host->dev, "setup: cr0 %#x\n", cr0);
writel(div_cpsr, espi->mmio + SSPCPSR);
writel(cr0, espi->mmio + SSPCR0);
return 0;
}
Annotation
- Immediate include surface: `linux/io.h`, `linux/clk.h`, `linux/err.h`, `linux/delay.h`, `linux/device.h`, `linux/dma-direction.h`, `linux/dma-mapping.h`, `linux/dmaengine.h`.
- Detected declarations: `struct ep93xx_spi`, `function ep93xx_spi_calc_divisors`, `function ep93xx_spi_chip_setup`, `function ep93xx_do_write`, `function ep93xx_do_read`, `function ep93xx_spi_read_write`, `function ep93xx_dma_data_to_trans_dir`, `function ep93xx_spi_dma_prepare`, `function ep93xx_spi_dma_finish`, `function ep93xx_spi_dma_callback`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
- 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.