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 */
intel_pmc_ipc(struct pmc_ipc_cmd * ipc_cmd,struct pmc_ipc_rbuf * rbuf)37 static inline int intel_pmc_ipc(struct pmc_ipc_cmd *ipc_cmd, struct pmc_ipc_rbuf *rbuf)
38 {
39 #ifdef CONFIG_ACPI
40 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
41 union acpi_object params[PMC_IPCS_PARAM_COUNT] = {
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 {.type = ACPI_TYPE_INTEGER,},
49 };
50 struct acpi_object_list arg_list = { PMC_IPCS_PARAM_COUNT, params };
51 union acpi_object *obj;
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 obj = 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