drivers/staging/media/ipu7/ipu7-boot.c

Source file repositories/reference/linux-study-clean/drivers/staging/media/ipu7/ipu7-boot.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/media/ipu7/ipu7-boot.c
Extension
.c
Size
13120 bytes
Lines
431
Domain
Driver Families
Bucket
drivers/staging
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

struct ipu7_boot_context {
	u32 base;
	u32 dmem_address;
	u32 status_ctrl_reg;
	u32 fw_start_address_reg;
	u32 fw_code_base_reg;
};

static const struct ipu7_boot_context contexts[IPU_SUBSYS_NUM] = {
	{
		/* ISYS */
		.dmem_address = IPU_ISYS_DMEM_OFFSET,
		.status_ctrl_reg = BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS,
		.fw_start_address_reg = BUTTRESS_REG_DRV_IS_UCX_START_ADDR,
		.fw_code_base_reg = IS_UC_CTRL_BASE
	},
	{
		/* PSYS */
		.dmem_address = IPU_PSYS_DMEM_OFFSET,
		.status_ctrl_reg = BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS,
		.fw_start_address_reg = BUTTRESS_REG_DRV_PS_UCX_START_ADDR,
		.fw_code_base_reg = PS_UC_CTRL_BASE
	}
};

static u32 get_fw_boot_reg_addr(const struct ipu7_bus_device *adev,
				enum ia_gofo_buttress_reg_id reg)
{
	u32 base = (adev->subsys == IPU_IS) ? 0U : (u32)IA_GOFO_FW_BOOT_ID_MAX;

	return BUTTRESS_FW_BOOT_PARAMS_ENTRY(base + (u32)reg);
}

static void write_fw_boot_param(const struct ipu7_bus_device *adev,
				enum ia_gofo_buttress_reg_id reg,
				u32 val)
{
	void __iomem *base = adev->isp->base;

	dev_dbg(&adev->auxdev.dev,
		"write boot param reg: %d addr: %x val: 0x%x\n",
		reg, get_fw_boot_reg_addr(adev, reg), val);
	writel(val, base + get_fw_boot_reg_addr(adev, reg));
}

static u32 read_fw_boot_param(const struct ipu7_bus_device *adev,
			      enum ia_gofo_buttress_reg_id reg)
{
	void __iomem *base = adev->isp->base;

	return readl(base + get_fw_boot_reg_addr(adev, reg));
}

static int ipu7_boot_cell_reset(const struct ipu7_bus_device *adev)
{
	const struct ipu7_boot_context *ctx = &contexts[adev->subsys];
	const struct device *dev = &adev->auxdev.dev;
	u32 ucx_ctrl_status = ctx->status_ctrl_reg;
	u32 timeout = IPU_BOOT_CELL_RESET_TIMEOUT;
	void __iomem *base = adev->isp->base;
	u32 val, val2;
	int ret;

	dev_dbg(dev, "cell enter reset...\n");
	val = readl(base + ucx_ctrl_status);
	dev_dbg(dev, "cell_ctrl_reg addr = 0x%x, val = 0x%x\n",
		ucx_ctrl_status, val);

	dev_dbg(dev, "force cell reset...\n");
	val |= UCX_CTL_RESET;
	val &= ~UCX_CTL_RUN;

	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",
		ucx_ctrl_status, val);
	writel(val, base + ucx_ctrl_status);

	ret = readl_poll_timeout(base + ucx_ctrl_status, val2,
				 (val2 & 0x3U) == (val & 0x3U), 100, timeout);
	if (ret) {
		dev_err(dev, "cell enter reset timeout. status: 0x%x\n", val2);
		return -ETIMEDOUT;
	}

	dev_dbg(dev, "cell exit reset...\n");
	val = readl(base + ucx_ctrl_status);
	WARN((!(val & UCX_CTL_RESET) || val & UCX_CTL_RUN),
	     "cell status 0x%x", val);

	val &= ~(UCX_CTL_RESET | UCX_CTL_RUN);
	dev_dbg(dev, "write status_ctrl_reg(0x%x) to 0x%x\n",

Annotation

Implementation Notes