drivers/platform/x86/intel/punit_ipc.c

Source file repositories/reference/linux-study-clean/drivers/platform/x86/intel/punit_ipc.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/x86/intel/punit_ipc.c
Extension
.c
Size
7466 bytes
Lines
303
Domain
Driver Families
Bucket
drivers/platform
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 (!loops) {
			dev_err(ipcdev->dev, "IPC timed out\n");
			return -ETIMEDOUT;
		}
	}

	status = ipc_read_status(ipcdev, type);
	errcode = status & CMD_ERRCODE_MASK;
	if (errcode) {
		dev_err(ipcdev->dev, "IPC failed: %s, IPC_STS=0x%x\n",
			ipc_err_string(errcode), status);
		return -EIO;
	}

	return 0;
}

/**
 * intel_punit_ipc_command() - IPC command with data and pointers
 * @cmd:	IPC command code.
 * @para1:	First 8bit parameter, set 0 if not used.
 * @para2:	Second 8bit parameter, set 0 if not used.
 * @in:		Input data, 32bit for BIOS cmd, two 32bit for GTD and ISPD.
 * @out:	Output data.
 *
 * Send a IPC command to P-Unit with data transaction
 *
 * Return:	IPC error code or 0 on success.
 */
int intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out)
{
	IPC_DEV *ipcdev = punit_ipcdev;
	IPC_TYPE type;
	u32 val;
	int ret;

	mutex_lock(&ipcdev->lock);

	reinit_completion(&ipcdev->cmd_complete);
	type = (cmd & IPC_PUNIT_CMD_TYPE_MASK) >> IPC_TYPE_OFFSET;

	if (in) {
		ipc_write_data_low(ipcdev, type, *in);
		if (type == GTDRIVER_IPC || type == ISPDRIVER_IPC)
			ipc_write_data_high(ipcdev, type, *++in);
	}

	val = cmd & ~IPC_PUNIT_CMD_TYPE_MASK;
	val |= CMD_RUN | para2 << CMD_PARA2_SHIFT | para1 << CMD_PARA1_SHIFT;
	ipc_write_cmd(ipcdev, type, val);

	ret = intel_punit_ipc_check_status(ipcdev, type);
	if (ret)
		goto out;

	if (out) {
		*out = ipc_read_data_low(ipcdev, type);
		if (type == GTDRIVER_IPC || type == ISPDRIVER_IPC)
			*++out = ipc_read_data_high(ipcdev, type);
	}

out:
	mutex_unlock(&ipcdev->lock);
	return ret;
}
EXPORT_SYMBOL_GPL(intel_punit_ipc_command);

static irqreturn_t intel_punit_ioc(int irq, void *dev_id)
{
	IPC_DEV *ipcdev = dev_id;

	complete(&ipcdev->cmd_complete);
	return IRQ_HANDLED;
}

static int intel_punit_get_bars(struct platform_device *pdev)
{
	void __iomem *addr;

	/*
	 * The following resources are required
	 * - BIOS_IPC BASE_DATA
	 * - BIOS_IPC BASE_IFACE
	 */
	addr = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(addr))
		return PTR_ERR(addr);
	punit_ipcdev->base[BIOS_IPC][BASE_DATA] = addr;

	addr = devm_platform_ioremap_resource(pdev, 1);

Annotation

Implementation Notes