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>
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
)
31 while (!(read32(DEFAULT_HECIBAR
+ 0xc) & 8))
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
)
43 for (i
= 0; i
< length
; i
+= sizeof(uint32_t)) {
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
;
67 maxlen
= (read32(DEFAULT_HECIBAR
+ 0x4) >> 24) * 4 - 4;
78 head
.client_address
= clientaddress
;
79 head
.host_address
= hostaddress
;
80 send_heci_packet(&head
, msg
);
86 /* FIXME: Add timeout. */
87 static int recv_heci_packet(struct mei_header
*head
, u32
*packet
, u32
*packet_size
)
95 write32(DEFAULT_HECIBAR
+ 0x4, read32(DEFAULT_HECIBAR
+ 0x4) | 2);
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);
102 write32(DEFAULT_HECIBAR
+ 0x4, read32(DEFAULT_HECIBAR
+ 0x4) | 2);
106 if (head
->length
+ 4 > 4 * csr
.csr
.buffer_depth
|| head
->length
> *packet_size
) {
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
;
121 write32(DEFAULT_HECIBAR
+ 0x4, read32(DEFAULT_HECIBAR
+ 0x4) | 4);
132 u8 unk3
[0x48 - 4 - 1];
134 u32 dwords
[0x48 / sizeof(u32
)];
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;
146 current_size
= *message_size
- current_position
;
148 (&head
, &message
->dwords
[current_position
/ sizeof(u32
)],
149 ¤t_size
) == -1)
153 current_position
+= current_size
;
154 if (head
.is_complete
) {
155 *message_size
= current_position
;
159 if (current_position
>= *message_size
)
166 static void send_heci_uma_message(const u64 heci_uma_addr
, const unsigned int heci_uma_size
)
168 union uma_reply reply
;
185 .heci_uma_addr
= heci_uma_addr
,
186 .heci_uma_size
= heci_uma_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)
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))
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);