drivers/spi/spi-fsl-cpm.c

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

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-fsl-cpm.c
Extension
.c
Size
10615 bytes
Lines
420
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.

Dependency Surface

Detected Declarations

Annotated Snippet

if (mspi->flags & SPI_CPM1) {
			iowrite32be(0, &mspi->pram->rstate);
			iowrite16be(ioread16be(&mspi->pram->rbase),
				    &mspi->pram->rbptr);
			iowrite32be(0, &mspi->pram->tstate);
			iowrite16be(ioread16be(&mspi->pram->tbase),
				    &mspi->pram->tbptr);
		} else {
			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
		}
	}
}
EXPORT_SYMBOL_GPL(fsl_spi_cpm_reinit_txrx);

static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
{
	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
	unsigned int xfer_ofs;
	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;

	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;

	if (mspi->rx_dma == mspi->dma_dummy_rx)
		iowrite32be(mspi->rx_dma, &rx_bd->cbd_bufaddr);
	else
		iowrite32be(mspi->rx_dma + xfer_ofs, &rx_bd->cbd_bufaddr);
	iowrite16be(0, &rx_bd->cbd_datlen);
	iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP, &rx_bd->cbd_sc);

	if (mspi->tx_dma == mspi->dma_dummy_tx)
		iowrite32be(mspi->tx_dma, &tx_bd->cbd_bufaddr);
	else
		iowrite32be(mspi->tx_dma + xfer_ofs, &tx_bd->cbd_bufaddr);
	iowrite16be(xfer_len, &tx_bd->cbd_datlen);
	iowrite16be(BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST,
		    &tx_bd->cbd_sc);

	/* start transfer */
	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
}

int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t)
{
	struct device *dev = mspi->dev;
	struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;

	mspi->map_tx_dma = 1;
	mspi->map_rx_dma = 1;

	if (!t->tx_buf) {
		mspi->tx_dma = mspi->dma_dummy_tx;
		mspi->map_tx_dma = 0;
	}

	if (!t->rx_buf) {
		mspi->rx_dma = mspi->dma_dummy_rx;
		mspi->map_rx_dma = 0;
	}
	if (t->bits_per_word == 16 && t->tx_buf) {
		const u16 *src = t->tx_buf;
		__le16 *dst;
		int i;

		dst = kmalloc(t->len, GFP_KERNEL);
		if (!dst)
			return -ENOMEM;

		for (i = 0; i < t->len >> 1; i++)
			dst[i] = cpu_to_le16p(src + i);

		mspi->tx = dst;
		mspi->map_tx_dma = 1;
	}

	if (mspi->map_tx_dma) {
		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */

		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
					      DMA_TO_DEVICE);
		if (dma_mapping_error(dev, mspi->tx_dma)) {
			dev_err(dev, "unable to map tx dma\n");
			return -ENOMEM;
		}
	} else if (t->tx_buf) {
		mspi->tx_dma = 0;
	}

	if (mspi->map_rx_dma) {

Annotation

Implementation Notes