soc/intel/pantherlake: Remove soc_info.[hc] interface
[coreboot2.git] / src / southbridge / intel / ibexpeak / setup_heci_uma.c
blob572e5e7a76a9428763b220e69fbbe1636570a374
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/mmio.h>
5 #include <device/pci_def.h>
6 #include <device/pci_ops.h>
7 #include <northbridge/intel/ironlake/ironlake.h>
8 #include <southbridge/intel/ibexpeak/me.h>
9 #include <southbridge/intel/ibexpeak/pch.h>
10 #include <types.h>
12 #define HECIDEV PCI_DEV(0, 0x16, 0)
14 /* FIXME: add timeout. */
15 static void wait_heci_ready(void)
17 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8)) // = 0x8000000c
20 write32((DEFAULT_HECIBAR + 0x4), (read32(DEFAULT_HECIBAR + 0x4) & ~0x10) | 0xc);
23 /* FIXME: add timeout. */
24 static void wait_heci_cb_avail(int len)
26 union {
27 struct mei_csr csr;
28 u32 raw;
29 } csr;
31 while (!(read32(DEFAULT_HECIBAR + 0xc) & 8))
34 do {
35 csr.raw = read32(DEFAULT_HECIBAR + 0x4);
36 } while (len > csr.csr.buffer_depth - (csr.csr.buffer_write_ptr -
37 csr.csr.buffer_read_ptr));
40 static void send_heci_packet_dword(u8 *payload, size_t length)
42 int i;
43 for (i = 0; i < length; i += sizeof(uint32_t)) {
44 uint32_t dword = 0;
45 size_t bytes = MIN(length - i, sizeof(dword));
46 memcpy(&dword, payload + i, bytes);
47 write32(DEFAULT_HECIBAR + 0, dword);
51 static void send_heci_packet(struct mei_header *head, u8 *payload)
53 wait_heci_cb_avail(DIV_ROUND_UP(sizeof(*head) + head->length, sizeof(u32)));
55 send_heci_packet_dword((u8 *)head, sizeof(*head));
56 send_heci_packet_dword(payload, head->length);
58 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 0x4);
61 static void send_heci_message(u8 *msg, int len, u8 hostaddress, u8 clientaddress)
63 struct mei_header head;
64 int maxlen;
66 wait_heci_ready();
67 maxlen = (read32(DEFAULT_HECIBAR + 0x4) >> 24) * 4 - 4;
69 while (len) {
70 int cur = len;
71 if (cur > maxlen) {
72 cur = maxlen;
73 head.is_complete = 0;
74 } else
75 head.is_complete = 1;
76 head.length = cur;
77 head.reserved = 0;
78 head.client_address = clientaddress;
79 head.host_address = hostaddress;
80 send_heci_packet(&head, msg);
81 len -= cur;
82 msg += cur;
86 /* FIXME: Add timeout. */
87 static int recv_heci_packet(struct mei_header *head, u32 *packet, u32 *packet_size)
89 union {
90 struct mei_csr csr;
91 u32 raw;
92 } csr;
93 int i = 0;
95 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
96 do {
97 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
98 } while (csr.csr.buffer_write_ptr == csr.csr.buffer_read_ptr);
100 *(u32 *)head = read32(DEFAULT_HECIBAR + 0x8);
101 if (!head->length) {
102 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 2);
103 *packet_size = 0;
104 return 0;
106 if (head->length + 4 > 4 * csr.csr.buffer_depth || head->length > *packet_size) {
107 *packet_size = 0;
108 return -1;
111 do {
112 csr.raw = read32(DEFAULT_HECIBAR + 0xc);
113 } while (((head->length + 3) >> 2) >
114 (csr.csr.buffer_write_ptr - csr.csr.buffer_read_ptr));
116 for (i = 0; i < (head->length + 3) >> 2; i++)
117 packet[i++] = read32(DEFAULT_HECIBAR + 0x8);
118 *packet_size = head->length;
119 if (!csr.csr.ready)
120 *packet_size = 0;
121 write32(DEFAULT_HECIBAR + 0x4, read32(DEFAULT_HECIBAR + 0x4) | 4);
122 return 0;
125 union uma_reply {
126 struct {
127 u8 group_id;
128 u8 command;
129 u8 reserved;
130 u8 result;
131 u8 field2;
132 u8 unk3[0x48 - 4 - 1];
134 u32 dwords[0x48 / sizeof(u32)];
135 } __packed;
137 /* FIXME: Add timeout. */
138 static int recv_heci_message(union uma_reply *message, u32 *message_size)
140 struct mei_header head;
141 int current_position;
143 current_position = 0;
144 while (1) {
145 u32 current_size;
146 current_size = *message_size - current_position;
147 if (recv_heci_packet
148 (&head, &message->dwords[current_position / sizeof(u32)],
149 &current_size) == -1)
150 break;
151 if (!current_size)
152 break;
153 current_position += current_size;
154 if (head.is_complete) {
155 *message_size = current_position;
156 return 0;
159 if (current_position >= *message_size)
160 break;
162 *message_size = 0;
163 return -1;
166 static void send_heci_uma_message(const u64 heci_uma_addr, const unsigned int heci_uma_size)
168 union uma_reply reply;
170 struct uma_message {
171 u8 group_id;
172 u8 cmd;
173 u8 reserved;
174 u8 result;
175 u32 c2;
176 u64 heci_uma_addr;
177 u32 heci_uma_size;
178 u16 c3;
179 } __packed msg = {
180 .group_id = 0,
181 .cmd = MKHI_SET_UMA,
182 .reserved = 0,
183 .result = 0,
184 .c2 = 0x82,
185 .heci_uma_addr = heci_uma_addr,
186 .heci_uma_size = heci_uma_size,
187 .c3 = 0,
189 u32 reply_size;
191 send_heci_message((u8 *)&msg, sizeof(msg), 0, 7);
193 reply_size = sizeof(reply);
194 if (recv_heci_message(&reply, &reply_size) == -1)
195 return;
197 if (reply.command != (MKHI_SET_UMA | (1 << 7)))
198 die("HECI init failed\n");
201 void setup_heci_uma(u64 heci_uma_addr, unsigned int heci_uma_size)
203 if (!heci_uma_size && !(pci_read_config32(HECIDEV, 0x40) & 0x20))
204 return;
206 if (heci_uma_size) {
207 dmibar_clrbits32(DMIVC0RCTL, 1 << 7);
208 RCBA32(0x14) &= ~0x80;
209 dmibar_clrbits32(DMIVC1RCTL, 1 << 7);
210 RCBA32(0x20) &= ~0x80;
211 dmibar_clrbits32(DMIVCPRCTL, 1 << 7);
212 RCBA32(0x30) &= ~0x80;
213 dmibar_clrbits32(DMIVCMRCTL, 1 << 7);
214 RCBA32(0x40) &= ~0x80;
216 RCBA32(0x40) = 0x87000080; // OK
217 dmibar_write32(DMIVCMRCTL, 0x87000080); // OK
219 while ((RCBA16(0x46) & 2) && dmibar_read16(DMIVCMRSTS) & VCMNP)
223 mchbar_write32(0x24, 0x10000 + heci_uma_size);
225 send_heci_uma_message(heci_uma_addr, heci_uma_size);
227 pci_write_config32(HECIDEV, 0x10, 0x0);
228 pci_write_config8(HECIDEV, 0x4, 0x0);