drivers/spi/spi-spacemit-k1.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-spacemit-k1.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-spacemit-k1.c- Extension
.c- Size
- 22078 bytes
- Lines
- 790
- 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/bitfield.hlinux/clk.hlinux/device.hlinux/dma-mapping.hlinux/dmaengine.hlinux/interrupt.hlinux/kernel.hlinux/of.hlinux/platform_device.hlinux/reset.hlinux/scatterlist.hlinux/sizes.hlinux/spi/spi.hlinux/units.hinternals.h
Detected Declarations
struct k1_spi_driver_datafunction k1_spi_register_resetfunction modefunction k1_spi_cleanupfunction k1_spi_can_dmafunction k1_spi_dma_callbackfunction k1_spi_dma_prepfunction k1_spi_dma_onefunction k1_spi_prepare_messagefunction k1_spi_set_csfunction k1_spi_set_speedfunction k1_spi_transfer_onefunction k1_spi_handle_errfunction k1_spi_write_wordfunction k1_spi_writefunction k1_spi_read_wordfunction k1_spi_readfunction k1_spi_ssp_isrfunction k1_spi_dma_setupfunction k1_spi_dma_cleanupfunction devm_k1_spi_dma_setupfunction k1_spi_probe
Annotated Snippet
struct k1_spi_driver_data {
struct spi_controller *host;
void __iomem *base;
phys_addr_t base_addr;
unsigned long bus_rate;
struct clk *clk;
unsigned long rate;
int irq;
/* Current transfer information; not valid if message is null */
u32 bytes; /* Bytes used for bits_per_word */
unsigned int rx_resid; /* RX bytes left in transfer */
unsigned int tx_resid; /* TX bytes left in transfer */
struct spi_transfer *transfer; /* Current transfer */
bool dma_enabled;
};
/* Set our registers to a known initial state */
static void
k1_spi_register_reset(struct k1_spi_driver_data *drv_data, bool initial)
{
u32 val = 0;
writel(0, drv_data->base + SSP_TOP_CTRL);
if (initial) {
/*
* The TX and RX FIFO thresholds are the same no matter
* what the speed or bits per word, so we can just set
* them once. The thresholds are one more than the values
* in the register.
*/
val = FIELD_PREP(FIFO_RFT_MASK, K1_SPI_THRESH - 1);
val |= FIELD_PREP(FIFO_TFT_MASK, K1_SPI_THRESH - 1);
}
writel(val, drv_data->base + SSP_FIFO_CTRL);
writel(0, drv_data->base + SSP_INT_EN);
writel(0, drv_data->base + SSP_TIMEOUT);
/* Clear any pending interrupt conditions */
writel(~0, drv_data->base + SSP_STATUS);
}
/*
* The client can call the setup function multiple times, and each call
* can specify a different SPI mode (and transfer speed). Each transfer
* can specify its own speed though, and the core code ensures each
* transfer's speed is set to something nonzero and supported by both
* the controller and the device. We just set the speed for each transfer.
*/
static int k1_spi_setup(struct spi_device *spi)
{
struct k1_spi_driver_data *drv_data;
u32 val;
drv_data = spi_controller_get_devdata(spi->controller);
/*
* Configure the message format for this device. We only
* support Motorola SPI format in master mode.
*/
val = FIELD_PREP(TOP_FRF_MASK, TOP_FRF_MOTOROLA);
/* Translate the mode into the value used to program the hardware. */
if (spi->mode & SPI_CPHA)
val |= TOP_SPH; /* 1/2 cycle */
if (spi->mode & SPI_CPOL)
val |= TOP_SPO; /* active low */
if (spi->mode & SPI_LOOP)
val |= TOP_LBM; /* enable loopback */
writel(val, drv_data->base + SSP_TOP_CTRL);
return 0;
}
static void k1_spi_cleanup(struct spi_device *spi)
{
struct k1_spi_driver_data *drv_data;
drv_data = spi_controller_get_devdata(spi->controller);
k1_spi_register_reset(drv_data, false);
}
static bool k1_spi_can_dma(struct spi_controller *host, struct spi_device *spi,
struct spi_transfer *transfer)
{
struct k1_spi_driver_data *drv_data = spi_controller_get_devdata(host);
u32 burst_size;
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/device.h`, `linux/dma-mapping.h`, `linux/dmaengine.h`, `linux/interrupt.h`, `linux/kernel.h`, `linux/of.h`.
- Detected declarations: `struct k1_spi_driver_data`, `function k1_spi_register_reset`, `function mode`, `function k1_spi_cleanup`, `function k1_spi_can_dma`, `function k1_spi_dma_callback`, `function k1_spi_dma_prep`, `function k1_spi_dma_one`, `function k1_spi_prepare_message`, `function k1_spi_set_cs`.
- 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.