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