18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for the Intel P-Unit Mailbox IPC mechanism
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (C) Copyright 2015 Intel Corporation
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * The heart of the P-Unit is the Foxton microcontroller and its firmware,
88c2ecf20Sopenharmony_ci * which provide mailbox interface for power management usage.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/bitops.h>
128c2ecf20Sopenharmony_ci#include <linux/delay.h>
138c2ecf20Sopenharmony_ci#include <linux/device.h>
148c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
158c2ecf20Sopenharmony_ci#include <linux/io.h>
168c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
178c2ecf20Sopenharmony_ci#include <linux/module.h>
188c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <asm/intel_punit_ipc.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* IPC Mailbox registers */
238c2ecf20Sopenharmony_ci#define OFFSET_DATA_LOW		0x0
248c2ecf20Sopenharmony_ci#define OFFSET_DATA_HIGH	0x4
258c2ecf20Sopenharmony_ci/* bit field of interface register */
268c2ecf20Sopenharmony_ci#define	CMD_RUN			BIT(31)
278c2ecf20Sopenharmony_ci#define	CMD_ERRCODE_MASK	GENMASK(7, 0)
288c2ecf20Sopenharmony_ci#define	CMD_PARA1_SHIFT		8
298c2ecf20Sopenharmony_ci#define	CMD_PARA2_SHIFT		16
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define CMD_TIMEOUT_SECONDS	1
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cienum {
348c2ecf20Sopenharmony_ci	BASE_DATA = 0,
358c2ecf20Sopenharmony_ci	BASE_IFACE,
368c2ecf20Sopenharmony_ci	BASE_MAX,
378c2ecf20Sopenharmony_ci};
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_citypedef struct {
408c2ecf20Sopenharmony_ci	struct device *dev;
418c2ecf20Sopenharmony_ci	struct mutex lock;
428c2ecf20Sopenharmony_ci	int irq;
438c2ecf20Sopenharmony_ci	struct completion cmd_complete;
448c2ecf20Sopenharmony_ci	/* base of interface and data registers */
458c2ecf20Sopenharmony_ci	void __iomem *base[RESERVED_IPC][BASE_MAX];
468c2ecf20Sopenharmony_ci	IPC_TYPE type;
478c2ecf20Sopenharmony_ci} IPC_DEV;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic IPC_DEV *punit_ipcdev;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic inline u32 ipc_read_status(IPC_DEV *ipcdev, IPC_TYPE type)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	return readl(ipcdev->base[type][BASE_IFACE]);
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic inline void ipc_write_cmd(IPC_DEV *ipcdev, IPC_TYPE type, u32 cmd)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	writel(cmd, ipcdev->base[type][BASE_IFACE]);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_cistatic inline u32 ipc_read_data_low(IPC_DEV *ipcdev, IPC_TYPE type)
628c2ecf20Sopenharmony_ci{
638c2ecf20Sopenharmony_ci	return readl(ipcdev->base[type][BASE_DATA] + OFFSET_DATA_LOW);
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic inline u32 ipc_read_data_high(IPC_DEV *ipcdev, IPC_TYPE type)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	return readl(ipcdev->base[type][BASE_DATA] + OFFSET_DATA_HIGH);
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline void ipc_write_data_low(IPC_DEV *ipcdev, IPC_TYPE type, u32 data)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	writel(data, ipcdev->base[type][BASE_DATA] + OFFSET_DATA_LOW);
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic inline void ipc_write_data_high(IPC_DEV *ipcdev, IPC_TYPE type, u32 data)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	writel(data, ipcdev->base[type][BASE_DATA] + OFFSET_DATA_HIGH);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic const char *ipc_err_string(int error)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	if (error == IPC_PUNIT_ERR_SUCCESS)
848c2ecf20Sopenharmony_ci		return "no error";
858c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_INVALID_CMD)
868c2ecf20Sopenharmony_ci		return "invalid command";
878c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_INVALID_PARAMETER)
888c2ecf20Sopenharmony_ci		return "invalid parameter";
898c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_CMD_TIMEOUT)
908c2ecf20Sopenharmony_ci		return "command timeout";
918c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_CMD_LOCKED)
928c2ecf20Sopenharmony_ci		return "command locked";
938c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_INVALID_VR_ID)
948c2ecf20Sopenharmony_ci		return "invalid vr id";
958c2ecf20Sopenharmony_ci	else if (error == IPC_PUNIT_ERR_VR_ERR)
968c2ecf20Sopenharmony_ci		return "vr error";
978c2ecf20Sopenharmony_ci	else
988c2ecf20Sopenharmony_ci		return "unknown error";
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_cistatic int intel_punit_ipc_check_status(IPC_DEV *ipcdev, IPC_TYPE type)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	int loops = CMD_TIMEOUT_SECONDS * USEC_PER_SEC;
1048c2ecf20Sopenharmony_ci	int errcode;
1058c2ecf20Sopenharmony_ci	int status;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	if (ipcdev->irq) {
1088c2ecf20Sopenharmony_ci		if (!wait_for_completion_timeout(&ipcdev->cmd_complete,
1098c2ecf20Sopenharmony_ci						 CMD_TIMEOUT_SECONDS * HZ)) {
1108c2ecf20Sopenharmony_ci			dev_err(ipcdev->dev, "IPC timed out\n");
1118c2ecf20Sopenharmony_ci			return -ETIMEDOUT;
1128c2ecf20Sopenharmony_ci		}
1138c2ecf20Sopenharmony_ci	} else {
1148c2ecf20Sopenharmony_ci		while ((ipc_read_status(ipcdev, type) & CMD_RUN) && --loops)
1158c2ecf20Sopenharmony_ci			udelay(1);
1168c2ecf20Sopenharmony_ci		if (!loops) {
1178c2ecf20Sopenharmony_ci			dev_err(ipcdev->dev, "IPC timed out\n");
1188c2ecf20Sopenharmony_ci			return -ETIMEDOUT;
1198c2ecf20Sopenharmony_ci		}
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	status = ipc_read_status(ipcdev, type);
1238c2ecf20Sopenharmony_ci	errcode = status & CMD_ERRCODE_MASK;
1248c2ecf20Sopenharmony_ci	if (errcode) {
1258c2ecf20Sopenharmony_ci		dev_err(ipcdev->dev, "IPC failed: %s, IPC_STS=0x%x\n",
1268c2ecf20Sopenharmony_ci			ipc_err_string(errcode), status);
1278c2ecf20Sopenharmony_ci		return -EIO;
1288c2ecf20Sopenharmony_ci	}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	return 0;
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/**
1348c2ecf20Sopenharmony_ci * intel_punit_ipc_simple_command() - Simple IPC command
1358c2ecf20Sopenharmony_ci * @cmd:	IPC command code.
1368c2ecf20Sopenharmony_ci * @para1:	First 8bit parameter, set 0 if not used.
1378c2ecf20Sopenharmony_ci * @para2:	Second 8bit parameter, set 0 if not used.
1388c2ecf20Sopenharmony_ci *
1398c2ecf20Sopenharmony_ci * Send a IPC command to P-Unit when there is no data transaction
1408c2ecf20Sopenharmony_ci *
1418c2ecf20Sopenharmony_ci * Return:	IPC error code or 0 on success.
1428c2ecf20Sopenharmony_ci */
1438c2ecf20Sopenharmony_ciint intel_punit_ipc_simple_command(int cmd, int para1, int para2)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	IPC_DEV *ipcdev = punit_ipcdev;
1468c2ecf20Sopenharmony_ci	IPC_TYPE type;
1478c2ecf20Sopenharmony_ci	u32 val;
1488c2ecf20Sopenharmony_ci	int ret;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	mutex_lock(&ipcdev->lock);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	reinit_completion(&ipcdev->cmd_complete);
1538c2ecf20Sopenharmony_ci	type = (cmd & IPC_PUNIT_CMD_TYPE_MASK) >> IPC_TYPE_OFFSET;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	val = cmd & ~IPC_PUNIT_CMD_TYPE_MASK;
1568c2ecf20Sopenharmony_ci	val |= CMD_RUN | para2 << CMD_PARA2_SHIFT | para1 << CMD_PARA1_SHIFT;
1578c2ecf20Sopenharmony_ci	ipc_write_cmd(ipcdev, type, val);
1588c2ecf20Sopenharmony_ci	ret = intel_punit_ipc_check_status(ipcdev, type);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	mutex_unlock(&ipcdev->lock);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return ret;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(intel_punit_ipc_simple_command);
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci/**
1678c2ecf20Sopenharmony_ci * intel_punit_ipc_command() - IPC command with data and pointers
1688c2ecf20Sopenharmony_ci * @cmd:	IPC command code.
1698c2ecf20Sopenharmony_ci * @para1:	First 8bit parameter, set 0 if not used.
1708c2ecf20Sopenharmony_ci * @para2:	Second 8bit parameter, set 0 if not used.
1718c2ecf20Sopenharmony_ci * @in:		Input data, 32bit for BIOS cmd, two 32bit for GTD and ISPD.
1728c2ecf20Sopenharmony_ci * @out:	Output data.
1738c2ecf20Sopenharmony_ci *
1748c2ecf20Sopenharmony_ci * Send a IPC command to P-Unit with data transaction
1758c2ecf20Sopenharmony_ci *
1768c2ecf20Sopenharmony_ci * Return:	IPC error code or 0 on success.
1778c2ecf20Sopenharmony_ci */
1788c2ecf20Sopenharmony_ciint intel_punit_ipc_command(u32 cmd, u32 para1, u32 para2, u32 *in, u32 *out)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	IPC_DEV *ipcdev = punit_ipcdev;
1818c2ecf20Sopenharmony_ci	IPC_TYPE type;
1828c2ecf20Sopenharmony_ci	u32 val;
1838c2ecf20Sopenharmony_ci	int ret;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	mutex_lock(&ipcdev->lock);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	reinit_completion(&ipcdev->cmd_complete);
1888c2ecf20Sopenharmony_ci	type = (cmd & IPC_PUNIT_CMD_TYPE_MASK) >> IPC_TYPE_OFFSET;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (in) {
1918c2ecf20Sopenharmony_ci		ipc_write_data_low(ipcdev, type, *in);
1928c2ecf20Sopenharmony_ci		if (type == GTDRIVER_IPC || type == ISPDRIVER_IPC)
1938c2ecf20Sopenharmony_ci			ipc_write_data_high(ipcdev, type, *++in);
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	val = cmd & ~IPC_PUNIT_CMD_TYPE_MASK;
1978c2ecf20Sopenharmony_ci	val |= CMD_RUN | para2 << CMD_PARA2_SHIFT | para1 << CMD_PARA1_SHIFT;
1988c2ecf20Sopenharmony_ci	ipc_write_cmd(ipcdev, type, val);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	ret = intel_punit_ipc_check_status(ipcdev, type);
2018c2ecf20Sopenharmony_ci	if (ret)
2028c2ecf20Sopenharmony_ci		goto out;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	if (out) {
2058c2ecf20Sopenharmony_ci		*out = ipc_read_data_low(ipcdev, type);
2068c2ecf20Sopenharmony_ci		if (type == GTDRIVER_IPC || type == ISPDRIVER_IPC)
2078c2ecf20Sopenharmony_ci			*++out = ipc_read_data_high(ipcdev, type);
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ciout:
2118c2ecf20Sopenharmony_ci	mutex_unlock(&ipcdev->lock);
2128c2ecf20Sopenharmony_ci	return ret;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(intel_punit_ipc_command);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic irqreturn_t intel_punit_ioc(int irq, void *dev_id)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	IPC_DEV *ipcdev = dev_id;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	complete(&ipcdev->cmd_complete);
2218c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic int intel_punit_get_bars(struct platform_device *pdev)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	void __iomem *addr;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	/*
2298c2ecf20Sopenharmony_ci	 * The following resources are required
2308c2ecf20Sopenharmony_ci	 * - BIOS_IPC BASE_DATA
2318c2ecf20Sopenharmony_ci	 * - BIOS_IPC BASE_IFACE
2328c2ecf20Sopenharmony_ci	 */
2338c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 0);
2348c2ecf20Sopenharmony_ci	if (IS_ERR(addr))
2358c2ecf20Sopenharmony_ci		return PTR_ERR(addr);
2368c2ecf20Sopenharmony_ci	punit_ipcdev->base[BIOS_IPC][BASE_DATA] = addr;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 1);
2398c2ecf20Sopenharmony_ci	if (IS_ERR(addr))
2408c2ecf20Sopenharmony_ci		return PTR_ERR(addr);
2418c2ecf20Sopenharmony_ci	punit_ipcdev->base[BIOS_IPC][BASE_IFACE] = addr;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	/*
2448c2ecf20Sopenharmony_ci	 * The following resources are optional
2458c2ecf20Sopenharmony_ci	 * - ISPDRIVER_IPC BASE_DATA
2468c2ecf20Sopenharmony_ci	 * - ISPDRIVER_IPC BASE_IFACE
2478c2ecf20Sopenharmony_ci	 * - GTDRIVER_IPC BASE_DATA
2488c2ecf20Sopenharmony_ci	 * - GTDRIVER_IPC BASE_IFACE
2498c2ecf20Sopenharmony_ci	 */
2508c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 2);
2518c2ecf20Sopenharmony_ci	if (!IS_ERR(addr))
2528c2ecf20Sopenharmony_ci		punit_ipcdev->base[ISPDRIVER_IPC][BASE_DATA] = addr;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 3);
2558c2ecf20Sopenharmony_ci	if (!IS_ERR(addr))
2568c2ecf20Sopenharmony_ci		punit_ipcdev->base[ISPDRIVER_IPC][BASE_IFACE] = addr;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 4);
2598c2ecf20Sopenharmony_ci	if (!IS_ERR(addr))
2608c2ecf20Sopenharmony_ci		punit_ipcdev->base[GTDRIVER_IPC][BASE_DATA] = addr;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	addr = devm_platform_ioremap_resource(pdev, 5);
2638c2ecf20Sopenharmony_ci	if (!IS_ERR(addr))
2648c2ecf20Sopenharmony_ci		punit_ipcdev->base[GTDRIVER_IPC][BASE_IFACE] = addr;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return 0;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic int intel_punit_ipc_probe(struct platform_device *pdev)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	int irq, ret;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	punit_ipcdev = devm_kzalloc(&pdev->dev,
2748c2ecf20Sopenharmony_ci				    sizeof(*punit_ipcdev), GFP_KERNEL);
2758c2ecf20Sopenharmony_ci	if (!punit_ipcdev)
2768c2ecf20Sopenharmony_ci		return -ENOMEM;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, punit_ipcdev);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	irq = platform_get_irq_optional(pdev, 0);
2818c2ecf20Sopenharmony_ci	if (irq < 0) {
2828c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "Invalid IRQ, using polling mode\n");
2838c2ecf20Sopenharmony_ci	} else {
2848c2ecf20Sopenharmony_ci		ret = devm_request_irq(&pdev->dev, irq, intel_punit_ioc,
2858c2ecf20Sopenharmony_ci				       IRQF_NO_SUSPEND, "intel_punit_ipc",
2868c2ecf20Sopenharmony_ci				       &punit_ipcdev);
2878c2ecf20Sopenharmony_ci		if (ret) {
2888c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Failed to request irq: %d\n", irq);
2898c2ecf20Sopenharmony_ci			return ret;
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci		punit_ipcdev->irq = irq;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	ret = intel_punit_get_bars(pdev);
2958c2ecf20Sopenharmony_ci	if (ret)
2968c2ecf20Sopenharmony_ci		return ret;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	punit_ipcdev->dev = &pdev->dev;
2998c2ecf20Sopenharmony_ci	mutex_init(&punit_ipcdev->lock);
3008c2ecf20Sopenharmony_ci	init_completion(&punit_ipcdev->cmd_complete);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	return 0;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic int intel_punit_ipc_remove(struct platform_device *pdev)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	return 0;
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic const struct acpi_device_id punit_ipc_acpi_ids[] = {
3118c2ecf20Sopenharmony_ci	{ "INT34D4", 0 },
3128c2ecf20Sopenharmony_ci	{ }
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, punit_ipc_acpi_ids);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic struct platform_driver intel_punit_ipc_driver = {
3178c2ecf20Sopenharmony_ci	.probe = intel_punit_ipc_probe,
3188c2ecf20Sopenharmony_ci	.remove = intel_punit_ipc_remove,
3198c2ecf20Sopenharmony_ci	.driver = {
3208c2ecf20Sopenharmony_ci		.name = "intel_punit_ipc",
3218c2ecf20Sopenharmony_ci		.acpi_match_table = punit_ipc_acpi_ids,
3228c2ecf20Sopenharmony_ci	},
3238c2ecf20Sopenharmony_ci};
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic int __init intel_punit_ipc_init(void)
3268c2ecf20Sopenharmony_ci{
3278c2ecf20Sopenharmony_ci	return platform_driver_register(&intel_punit_ipc_driver);
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic void __exit intel_punit_ipc_exit(void)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	platform_driver_unregister(&intel_punit_ipc_driver);
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ciMODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
3368c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel P-Unit IPC driver");
3378c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci/* Some modules are dependent on this, so init earlier */
3408c2ecf20Sopenharmony_cifs_initcall(intel_punit_ipc_init);
3418c2ecf20Sopenharmony_cimodule_exit(intel_punit_ipc_exit);
342