drivers/media/platform/qcom/camss/camss-csid-680.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/qcom/camss/camss-csid-680.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/qcom/camss/camss-csid-680.c
Extension
.c
Size
14056 bytes
Lines
435
Domain
Driver Families
Bucket
drivers/media
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

if (csid->phy.en_vc & BIT(i)) {
			__csid_configure_rdi_stream(csid, enable, i, 0);
			__csid_configure_rx(csid, &csid->phy, 0);
			__csid_ctrl_rdi(csid, enable, i);
		}
	}
}

/*
 * csid_reset - Trigger reset on CSID module and wait to complete
 * @csid: CSID device
 *
 * Return 0 on success or a negative error code otherwise
 */
static int csid_reset(struct csid_device *csid)
{
	unsigned long time;
	u32 val;
	int i;

	reinit_completion(&csid->reset_complete);

	writel(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);

	/* preserve registers */
	val = CSID_RESET_CFG_MODE_IMMEDIATE | CSID_RESET_CFG_LOCATION_COMPLETE;
	writel(val, csid->base + CSID_RESET_CFG);

	val = CSID_RESET_CMD_HW_RESET | CSID_RESET_CMD_SW_RESET;
	writel(val, csid->base + CSID_RESET_CMD);

	time = wait_for_completion_timeout(&csid->reset_complete,
					   msecs_to_jiffies(CSID_RESET_TIMEOUT_MS));
	if (!time) {
		dev_err(csid->camss->dev, "CSID reset timeout\n");
		return -EIO;
	}

	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
		/* Enable RUP done for the client port */
		writel(CSID_CSI2_RDIN_RUP_DONE, csid->base + CSID_CSI2_RDIN_IRQ_MASK(i));
	}

	/* Clear RDI status */
	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_CLEAR);

	/* Enable BUF_DONE bit for all write-master client ports */
	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_MASK);

	/* Unmask all TOP interrupts */
	writel(~0u, csid->base + CSID_TOP_IRQ_MASK);

	return 0;
}

static void csid_rup_complete(struct csid_device *csid, int rdi)
{
	csid_reg_update_clear(csid, rdi);
}

/*
 * csid_isr - CSID module interrupt service routine
 * @irq: Interrupt line
 * @dev: CSID device
 *
 * Return IRQ_HANDLED on success
 */
static irqreturn_t csid_isr(int irq, void *dev)
{
	struct csid_device *csid = dev;
	u32 buf_done_val, val, val_top;
	int i;

	/* Latch and clear TOP status */
	val_top = readl(csid->base + CSID_TOP_IRQ_STATUS);
	writel(val_top, csid->base + CSID_TOP_IRQ_CLEAR);

	/* Latch and clear CSID_CSI2 status */
	val = readl(csid->base + CSID_CSI2_RX_IRQ_STATUS);
	writel(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);

	/* Latch and clear top level BUF_DONE status */
	buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS);
	writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR);

	/* Process state for each RDI channel */
	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
		val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
		if (val)
			writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));

Annotation

Implementation Notes