1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef SOC_INTEL_COMMON_BLOCK_PMC_IPC_H
4 #define SOC_INTEL_COMMON_BLOCK_PMC_IPC_H
5
6 #include <types.h>
7
8 #define PMC_IPC_BUF_COUNT 4
9
10 #define PMC_IPC_CMD_COMMAND_SHIFT 0
11 #define PMC_IPC_CMD_COMMAND_MASK 0xff
12 #define PMC_IPC_CMD_MSI_SHIFT 8
13 #define PMC_IPC_CMD_MSI_MASK 0x01
14 #define PMC_IPC_CMD_SUB_COMMAND_SHIFT 12
15 #define PMC_IPC_CMD_SUB_COMMAND_MASK 0x0f
16 #define PMC_IPC_CMD_SIZE_SHIFT 16
17 #define PMC_IPC_CMD_SIZE_MASK 0xff
18
19 /* IPC command to control FIVR Configuration */
20 #define PMC_IPC_CMD_COMMAND_FIVR 0xA3
21 /* IPC subcommand to read FIVR Register */
22 #define PMC_IPC_CMD_CMD_ID_FIVR_READ 0x00
23 /* IPC subcommand to write FIVR Register */
24 #define PMC_IPC_CMD_CMD_ID_FIVR_WRITE 0x01
25 /* IPC subcommand to control RFI Control 0 register logic write */
26 #define PMC_IPC_SUBCMD_RFI_CTRL0_LOGIC 0
27 /* IPC subcommand to control RFI Control 4 register logic write */
28 #define PMC_IPC_SUBCMD_RFI_CTRL4_LOGIC 1
29 /* IPC subcommand to control EMI Control 0 register logic write */
30 #define PMC_IPC_SUBCMD_EMI_CTRL0_LOGIC 2
31 /* IPC subcommand to control FFFC_FAULT_STATUS register logic read */
32 #define PMC_IPC_SUBCMD_FFFC_FAULT_STATUS 3
33 /* IPC subcommand to control FFFC_RFI_STATUS register logic read */
34 #define PMC_IPC_SUBCMD_FFFC_RFI_STATUS 4
35
36 #define PMC_IPC_CMD_FIELD(name, val) \
37 ((((val) & PMC_IPC_CMD_##name##_MASK) << PMC_IPC_CMD_##name##_SHIFT))
38
39 #define PMC_IPC_CMD_NO_MSI 0
40
41 /* IPC command for reading PMC registers */
42 #define PMC_IPC_CMD_RD_PMC_REG 0xA0
43 #define PMC_IPC_CMD_SUBCMD_RD_PMC_REG 0x02
44
45 /* IPC command to enable/disable PCIe SRCCLK */
46 #define PMC_IPC_CMD_ID_SET_PCIE_CLOCK 0xAC
47
48 /* IPC return values */
49 #define PMC_IPC_SUCCESS 0
50 #define PMC_IPC_ERROR 1
51 #define PMC_IPC_TIMEOUT 2
52
53 /*
54 * Create the IPC CMD to send to PMC
55 */
pmc_make_ipc_cmd(uint32_t cmd,uint32_t subcmd,uint32_t size)56 static inline uint32_t pmc_make_ipc_cmd(uint32_t cmd, uint32_t subcmd,
57 uint32_t size)
58 {
59 return PMC_IPC_CMD_FIELD(COMMAND, cmd) |
60 PMC_IPC_CMD_FIELD(SUB_COMMAND, subcmd) |
61 PMC_IPC_CMD_FIELD(MSI, PMC_IPC_CMD_NO_MSI) |
62 PMC_IPC_CMD_FIELD(SIZE, size);
63 }
64
65 /*
66 * Buffer for holding write and read buffers of IPC commands
67 */
68 struct pmc_ipc_buffer {
69 uint32_t buf[PMC_IPC_BUF_COUNT];
70 };
71
72 /*
73 * Send PMC IPC command
74 */
75 enum cb_err pmc_send_ipc_cmd(uint32_t cmd, const struct pmc_ipc_buffer *wbuf,
76 struct pmc_ipc_buffer *rbuf);
77
78 /*
79 * Provides an ACPI method in the SSDT to read/write to the IPC mailbox which is
80 * defined in the PMC device MMIO address space.
81 *
82 * One possible use of this method is to enable/disable the clock for a
83 * particular PCIe root port at runtime when the device is in D3 state.
84 *
85 * The ACPI method takes 7 arguments:
86 * IPCW (COMMAND, SUB_ID, SIZE, DATA0, DATA1, DATA2, DATA3)
87 *
88 * And will return a package with 5 elements:
89 * 0 = Return code
90 * PMC_IPC_SUCCESS
91 * PMC_IPC_ERROR
92 * PMC_IPC_TIMEOUT
93 * 1..4 = Data read from IPC if return code is PMC_IPC_SUCCESS
94 */
95 void pmc_ipc_acpi_fill_ssdt(void);
96
97 /*
98 * Call the ACPI method to write to the IPC mailbox and enable/disable the
99 * specified clock pin connected to the specified PCIe root port.
100 */
101 void pmc_ipc_acpi_set_pci_clock(unsigned int pcie_rp, unsigned int clock_pin, bool enable);
102
103 #endif /* SOC_INTEL_COMMON_BLOCK_PMC_IPC_H */
104