1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Intel Core SoC Power Management Controller Header File
4  *
5  * Copyright (c) 2025, Intel Corporation.
6  * All Rights Reserved.
7  *
8  */
9 #ifndef INTEL_PMC_IPC_H
10 #define INTEL_PMC_IPC_H
11 #include <linux/acpi.h>
12 
13 #define IPC_SOC_REGISTER_ACCESS			0xAA
14 #define IPC_SOC_SUB_CMD_READ			0x00
15 #define IPC_SOC_SUB_CMD_WRITE			0x01
16 #define PMC_IPCS_PARAM_COUNT			7
17 #define VALID_IPC_RESPONSE			5
18 
19 struct pmc_ipc_cmd {
20 	u32 cmd;
21 	u32 sub_cmd;
22 	u32 size;
23 	u32 wbuf[4];
24 };
25 
26 struct pmc_ipc_rbuf {
27 	u32 buf[4];
28 };
29 
30 /**
31  * intel_pmc_ipc() - PMC IPC Mailbox accessor
32  * @ipc_cmd:  Prepared input command to send
33  * @rbuf:     Allocated array for returned IPC data
34  *
35  * Return: 0 on success. Non-zero on mailbox error
36  */
37 static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf *rbuf)
38 {
39 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
40 	union acpi_object params[PMC_IPCS_PARAM_COUNT] = {
41 		{.type = ACPI_TYPE_INTEGER,},
42 		{.type = ACPI_TYPE_INTEGER,},
43 		{.type = ACPI_TYPE_INTEGER,},
44 		{.type = ACPI_TYPE_INTEGER,},
45 		{.type = ACPI_TYPE_INTEGER,},
46 		{.type = ACPI_TYPE_INTEGER,},
47 		{.type = ACPI_TYPE_INTEGER,},
48 	};
49 	struct acpi_object_list arg_list = { PMC_IPCS_PARAM_COUNT, params };
50 	union acpi_object *obj;
51 	int status;
52 
53 	if (!ipc_cmd || !rbuf)
54 		return -EINVAL;
55 
56 	/*
57 	 * 0: IPC Command
58 	 * 1: IPC Sub Command
59 	 * 2: Size
60 	 * 3-6: Write Buffer for offset
61 	 */
62 	params[0].integer.value = ipc_cmd->cmd;
63 	params[1].integer.value = ipc_cmd->sub_cmd;
64 	params[2].integer.value = ipc_cmd->size;
65 	params[3].integer.value = ipc_cmd->wbuf[0];
66 	params[4].integer.value = ipc_cmd->wbuf[1];
67 	params[5].integer.value = ipc_cmd->wbuf[2];
68 	params[6].integer.value = ipc_cmd->wbuf[3];
69 
70 	status = acpi_evaluate_object(NULL, "\\IPCS", &arg_list, &buffer);
71 	if (ACPI_FAILURE(status))
72 		return -ENODEV;
73 
74 	obj = buffer.pointer;
75 
76 	if (obj && obj->type == ACPI_TYPE_PACKAGE &&
77 	    obj->package.count == VALID_IPC_RESPONSE) {
78 		const union acpi_object *objs = obj->package.elements;
79 
80 		if ((u8)objs[0].integer.value != 0)
81 			return -EINVAL;
82 
83 		rbuf->buf[0] = objs[1].integer.value;
84 		rbuf->buf[1] = objs[2].integer.value;
85 		rbuf->buf[2] = objs[3].integer.value;
86 		rbuf->buf[3] = objs[4].integer.value;
87 	} else {
88 		return -EINVAL;
89 	}
90 
91 	return 0;
92 }
93 
94 #endif /* INTEL_PMC_IPC_H */
95