drivers/spi/spi-microchip-core-qspi.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-microchip-core-qspi.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-microchip-core-qspi.c
Extension
.c
Size
23751 bytes
Lines
834
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 mchp_coreqspi {
	void __iomem *regs;
	struct clk *clk;
	struct completion data_completion;
	struct mutex op_lock; /* lock access to the device */
	u8 *txbuf;
	u8 *rxbuf;
	int irq;
	int tx_len;
	int rx_len;
};

static int mchp_coreqspi_set_mode(struct mchp_coreqspi *qspi, const struct spi_mem_op *op)
{
	u32 control = readl_relaxed(qspi->regs + REG_CONTROL);

	/*
	 * The operating mode can be configured based on the command that needs to be send.
	 * bits[15:14]: Sets whether multiple bit SPI operates in normal, extended or full modes.
	 *		00: Normal (single DQ0 TX and single DQ1 RX lines)
	 *		01: Extended RO (command and address bytes on DQ0 only)
	 *		10: Extended RW (command byte on DQ0 only)
	 *		11: Full. (command and address are on all DQ lines)
	 * bit[13]:	Sets whether multiple bit SPI uses 2 or 4 bits of data
	 *		0: 2-bits (BSPI)
	 *		1: 4-bits (QSPI)
	 */
	if (op->data.buswidth == 4 || op->data.buswidth == 2) {
		control &= ~CONTROL_MODE12_MASK;
		if (op->cmd.buswidth == 1 && (op->addr.buswidth == 1 || op->addr.buswidth == 0))
			control |= CONTROL_MODE12_EX_RO;
		else if (op->cmd.buswidth == 1)
			control |= CONTROL_MODE12_EX_RW;
		else
			control |= CONTROL_MODE12_FULL;

		control |= CONTROL_MODE0;
	} else {
		control &= ~(CONTROL_MODE12_MASK |
			     CONTROL_MODE0);
	}

	writel_relaxed(control, qspi->regs + REG_CONTROL);

	return 0;
}

static void mchp_coreqspi_set_cs(struct spi_device *spi, bool enable)
{
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
	u32 val;

	val = readl(qspi->regs + REG_DIRECT_ACCESS);

	val &= ~DIRECT_ACCESS_OP_SSEL;
	val |= !enable << DIRECT_ACCESS_OP_SSEL_SHIFT;

	writel(val, qspi->regs + REG_DIRECT_ACCESS);
}

static int mchp_coreqspi_setup(struct spi_device *spi)
{
	struct mchp_coreqspi *qspi = spi_controller_get_devdata(spi->controller);
	u32 val;

	/*
	 * Active low devices need to be specifically set to their inactive
	 * states during probe.
	 */
	if (spi->mode & SPI_CS_HIGH)
		return 0;

	val = readl(qspi->regs + REG_DIRECT_ACCESS);
	val |= DIRECT_ACCESS_OP_SSEL;
	writel(val, qspi->regs + REG_DIRECT_ACCESS);

	return 0;
}

static void mchp_coreqspi_read_op(struct mchp_coreqspi *qspi)
{
	u32 control, data;

	if (!qspi->rx_len)
		return;

	control = readl_relaxed(qspi->regs + REG_CONTROL);

	/*
	 * Read 4-bytes from the SPI FIFO in single transaction and then read

Annotation

Implementation Notes