drivers/spi/spi-kspi2.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-kspi2.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-kspi2.c- Extension
.c- Size
- 10877 bytes
- Lines
- 432
- 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/iopoll.hlinux/misc/keba.hlinux/spi/spi.h
Detected Declarations
struct kspi2function kspi2_inuse_lockfunction kspi2_inuse_unlockfunction kspi2_prepare_hardwarefunction kspi2_unprepare_hardwarefunction kspi2_calc_minimal_dividerfunction kspi2_write_control_regfunction kspi2_txrx_bytefunction kspi2_process_transferfunction kspi2_setup_transferfunction spi_devicefunction kspi2_transfer_onefunction kspi2_set_csfunction kspi2_prepare_messagefunction kspi2_setupfunction kspi2_unregister_devicesfunction kspi2_register_devicesfunction kspi2_initfunction kspi2_probefunction kspi2_remove
Annotated Snippet
struct kspi2 {
struct keba_spi_auxdev *auxdev;
void __iomem *base;
struct spi_controller *host;
u32 base_speed_hz; /* SPI base clock frequency in HZ */
u8 control_shadow;
struct spi_device **device;
int device_size;
};
static int kspi2_inuse_lock(struct kspi2 *kspi)
{
u8 sts;
int ret;
/*
* The SPI controller has an IN_USE bit for locking access to the
* controller. This enables the use of the SPI controller by other none
* Linux processors.
*
* If the SPI controller is free, then the first read returns
* IN_USE == 0. After that the SPI controller is locked and further
* reads of IN_USE return 1.
*
* The SPI controller is unlocked by writing 1 into IN_USE.
*
* The IN_USE bit acts as a hardware semaphore for the SPI controller.
* Poll for semaphore, but sleep while polling to free the CPU.
*/
ret = readb_poll_timeout(kspi->base + KSPI2_STATUS_REG,
sts, (sts & KSPI2_STATUS_IN_USE) == 0,
KSPI2_INUSE_SLEEP_US, KSPI2_INUSE_TIMEOUT_US);
if (ret != 0)
dev_warn(&kspi->auxdev->auxdev.dev, "%s err!\n", __func__);
return ret;
}
static void kspi2_inuse_unlock(struct kspi2 *kspi)
{
/* unlock the controller by writing 1 into IN_USE */
iowrite8(KSPI2_STATUS_IN_USE, kspi->base + KSPI2_STATUS_REG);
}
static int kspi2_prepare_hardware(struct spi_controller *host)
{
struct kspi2 *kspi = spi_controller_get_devdata(host);
/* lock hardware semaphore before actual use of controller */
return kspi2_inuse_lock(kspi);
}
static int kspi2_unprepare_hardware(struct spi_controller *host)
{
struct kspi2 *kspi = spi_controller_get_devdata(host);
/* unlock hardware semaphore after actual use of controller */
kspi2_inuse_unlock(kspi);
return 0;
}
static u8 kspi2_calc_minimal_divider(struct kspi2 *kspi, u32 max_speed_hz)
{
u8 div;
/*
* Divider values 2, 4, 8, 16, ..., 65536 are possible. They are coded
* as 0, 1, 2, 3, ..., 15 in the CONTROL_CLK_DIV bit.
*/
for (div = 0; div < KSPI2_CONTROL_CLK_DIV_MAX; div++) {
if ((kspi->base_speed_hz >> (div + 1)) <= max_speed_hz)
return div;
}
/* return divider for slowest clock if loop fails to find one */
return KSPI2_CONTROL_CLK_DIV_MAX;
}
static void kspi2_write_control_reg(struct kspi2 *kspi, u8 val, u8 mask)
{
/* write control register only when necessary to improve performance */
if (val != (kspi->control_shadow & mask)) {
kspi->control_shadow = (kspi->control_shadow & ~mask) | val;
iowrite8(kspi->control_shadow, kspi->base + KSPI2_CONTROL_REG);
}
}
Annotation
- Immediate include surface: `linux/iopoll.h`, `linux/misc/keba.h`, `linux/spi/spi.h`.
- Detected declarations: `struct kspi2`, `function kspi2_inuse_lock`, `function kspi2_inuse_unlock`, `function kspi2_prepare_hardware`, `function kspi2_unprepare_hardware`, `function kspi2_calc_minimal_divider`, `function kspi2_write_control_reg`, `function kspi2_txrx_byte`, `function kspi2_process_transfer`, `function kspi2_setup_transfer`.
- 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.