drivers/spi/spi-ppc4xx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-ppc4xx.c
Extension
.c
Size
11819 bytes
Lines
498
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 spi_ppc4xx_regs {
	u8 mode;
	u8 rxd;
	u8 txd;
	u8 cr;
	u8 sr;
	u8 dummy;
	/*
	 * Clock divisor modulus register
	 * This uses the following formula:
	 *    SCPClkOut = OPBCLK/(4(CDM + 1))
	 * or
	 *    CDM = (OPBCLK/4*SCPClkOut) - 1
	 * bit 0 is the MSb!
	 */
	u8 cdm;
};

/* SPI Controller driver's private data. */
struct ppc4xx_spi {
	/* bitbang has to be first */
	struct spi_bitbang bitbang;
	struct completion done;

	u64 mapbase;
	u64 mapsize;
	int irqnum;
	/* need this to set the SPI clock */
	unsigned int opb_freq;

	/* for transfers */
	int len;
	int count;
	/* data buffers */
	const unsigned char *tx;
	unsigned char *rx;

	struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */
	struct spi_controller *host;
	struct device *dev;
};

/* need this so we can set the clock in the chipselect routine */
struct spi_ppc4xx_cs {
	u8 mode;
};

static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t)
{
	struct ppc4xx_spi *hw;
	u8 data;

	dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
		t->tx_buf, t->rx_buf, t->len);

	hw = spi_controller_get_devdata(spi->controller);

	hw->tx = t->tx_buf;
	hw->rx = t->rx_buf;
	hw->len = t->len;
	hw->count = 0;

	/* send the first byte */
	data = hw->tx ? hw->tx[0] : 0;
	out_8(&hw->regs->txd, data);
	out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR);
	wait_for_completion(&hw->done);

	return hw->count;
}

static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
{
	struct ppc4xx_spi *hw = spi_controller_get_devdata(spi->controller);
	struct spi_ppc4xx_cs *cs = spi->controller_state;
	int scr;
	u8 cdm = 0;
	u32 speed;

	/* Start with the generic configuration for this device. */
	speed = spi->max_speed_hz;

	/*
	 * Modify the configuration if the transfer overrides it.  Do not allow
	 * the transfer to overwrite the generic configuration with zeros.
	 */
	if (t) {
		if (t->speed_hz)
			speed = min(t->speed_hz, spi->max_speed_hz);
	}

Annotation

Implementation Notes