drivers/spi/spi-dln2.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-dln2.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-dln2.c
Extension
.c
Size
20939 bytes
Lines
877
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dln2_spi {
	struct platform_device *pdev;
	struct spi_controller *host;
	u8 port;

	/*
	 * This buffer will be used mainly for read/write operations. Since
	 * they're quite large, we cannot use the stack. Protection is not
	 * needed because all SPI communication is serialized by the SPI core.
	 */
	void *buf;

	u8 bpw;
	u32 speed;
	u16 mode;
	u8 cs;
};

/*
 * Enable/Disable SPI module. The disable command will wait for transfers to
 * complete first.
 */
static int dln2_spi_enable(struct dln2_spi *dln2, bool enable)
{
	u16 cmd;
	struct {
		u8 port;
		u8 wait_for_completion;
	} tx;
	unsigned len = sizeof(tx);

	tx.port = dln2->port;

	if (enable) {
		cmd = DLN2_SPI_ENABLE;
		len -= sizeof(tx.wait_for_completion);
	} else {
		tx.wait_for_completion = DLN2_TRANSFERS_WAIT_COMPLETE;
		cmd = DLN2_SPI_DISABLE;
	}

	return dln2_transfer_tx(dln2->pdev, cmd, &tx, len);
}

/*
 * Select/unselect multiple CS lines. The selected lines will be automatically
 * toggled LOW/HIGH by the board firmware during transfers, provided they're
 * enabled first.
 *
 * Ex: cs_mask = 0x03 -> CS0 & CS1 will be selected and the next WR/RD operation
 *                       will toggle the lines LOW/HIGH automatically.
 */
static int dln2_spi_cs_set(struct dln2_spi *dln2, u8 cs_mask)
{
	struct {
		u8 port;
		u8 cs;
	} tx;

	tx.port = dln2->port;

	/*
	 * According to Diolan docs, "a slave device can be selected by changing
	 * the corresponding bit value to 0". The rest must be set to 1. Hence
	 * the bitwise NOT in front.
	 */
	tx.cs = ~cs_mask;

	return dln2_transfer_tx(dln2->pdev, DLN2_SPI_SET_SS, &tx, sizeof(tx));
}

/*
 * Select one CS line. The other lines will be un-selected.
 */
static int dln2_spi_cs_set_one(struct dln2_spi *dln2, u8 cs)
{
	return dln2_spi_cs_set(dln2, BIT(cs));
}

/*
 * Enable/disable CS lines for usage. The module has to be disabled first.
 */
static int dln2_spi_cs_enable(struct dln2_spi *dln2, u8 cs_mask, bool enable)
{
	struct {
		u8 port;
		u8 cs;
	} tx;
	u16 cmd;

Annotation

Implementation Notes