drivers/spi/spi-loongson-core.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-loongson-core.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-loongson-core.c- Extension
.c- Size
- 8728 bytes
- Lines
- 280
- Domain
- Driver Families
- Bucket
- drivers/spi
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/clk.hlinux/delay.hlinux/err.hlinux/export.hlinux/init.hlinux/interrupt.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/spi/spi.hspi-loongson.h
Detected Declarations
function loongson_spi_write_regfunction loongson_spi_read_regfunction loongson_spi_set_csfunction loongson_spi_set_clkfunction loongson_spi_set_modefunction loongson_spi_update_statefunction loongson_spi_setupfunction loongson_spi_write_read_8bitfunction loongson_spi_write_readfunction loongson_spi_prepare_messagefunction loongson_spi_transfer_onefunction loongson_spi_unprepare_messagefunction loongson_spi_reginitfunction loongson_spi_init_controllerfunction loongson_spi_suspendfunction loongson_spi_resume
Annotated Snippet
// SPDX-License-Identifier: GPL-2.0+
// Loongson SPI Support
// Copyright (C) 2023 Loongson Technology Corporation Limited
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include "spi-loongson.h"
static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg,
unsigned char data)
{
writeb(data, spi->base + reg);
}
static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg)
{
return readb(spi->base + reg);
}
static void loongson_spi_set_cs(struct spi_device *spi, bool en)
{
int cs;
unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0);
unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0));
struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller);
cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG) & ~mask;
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, val | cs);
}
static void loongson_spi_set_clk(struct loongson_spi *loongson_spi, unsigned int hz)
{
unsigned char val;
unsigned int div, div_tmp;
static const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11};
div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096);
div_tmp = rdiv[fls(div - 1)];
loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0;
loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2;
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
val &= ~GENMASK(1, 0);
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val |
loongson_spi->spcr);
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG);
val &= ~GENMASK(1, 0);
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, val |
loongson_spi->sper);
loongson_spi->hz = hz;
}
static void loongson_spi_set_mode(struct loongson_spi *loongson_spi,
struct spi_device *spi)
{
unsigned char val;
val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG);
val &= ~(LOONGSON_SPI_SPCR_CPOL | LOONGSON_SPI_SPCR_CPHA);
if (spi->mode & SPI_CPOL)
val |= LOONGSON_SPI_SPCR_CPOL;
if (spi->mode & SPI_CPHA)
val |= LOONGSON_SPI_SPCR_CPHA;
loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val);
loongson_spi->mode |= spi->mode;
}
static int loongson_spi_update_state(struct loongson_spi *loongson_spi,
struct spi_device *spi, struct spi_transfer *t)
{
if (t && loongson_spi->hz != t->speed_hz)
loongson_spi_set_clk(loongson_spi, t->speed_hz);
if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK)
loongson_spi_set_mode(loongson_spi, spi);
return 0;
}
static int loongson_spi_setup(struct spi_device *spi)
Annotation
- Immediate include surface: `linux/clk.h`, `linux/delay.h`, `linux/err.h`, `linux/export.h`, `linux/init.h`, `linux/interrupt.h`, `linux/io.h`, `linux/iopoll.h`.
- Detected declarations: `function loongson_spi_write_reg`, `function loongson_spi_read_reg`, `function loongson_spi_set_cs`, `function loongson_spi_set_clk`, `function loongson_spi_set_mode`, `function loongson_spi_update_state`, `function loongson_spi_setup`, `function loongson_spi_write_read_8bit`, `function loongson_spi_write_read`, `function loongson_spi_prepare_message`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: integration 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.