blob: 947c570e16cea89c2db514f51a8c169e9ae80b19 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin76c37002012-10-30 09:03:43 -05002
Aaron Durbin76c37002012-10-30 09:03:43 -05003#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Aaron Durbin76c37002012-10-30 09:03:43 -05005#include <console/console.h>
6#include <delay.h>
Patrick Georgibd79c5e2014-11-28 22:35:36 +01007#include <halt.h>
Elyes HAOUAS249343b2021-12-31 08:40:53 +01008
Aaron Durbin76c37002012-10-30 09:03:43 -05009#include "me.h"
10#include "pch.h"
11
12static const char *me_ack_values[] = {
13 [ME_HFS_ACK_NO_DID] = "No DID Ack received",
14 [ME_HFS_ACK_RESET] = "Non-power cycle reset",
15 [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset",
16 [ME_HFS_ACK_S3] = "Go to S3",
17 [ME_HFS_ACK_S4] = "Go to S4",
18 [ME_HFS_ACK_S5] = "Go to S5",
19 [ME_HFS_ACK_GBL_RESET] = "Global Reset",
20 [ME_HFS_ACK_CONTINUE] = "Continue to boot"
21};
22
Aaron Durbin76c37002012-10-30 09:03:43 -050023void intel_early_me_status(void)
24{
Angel Pons032255c2021-11-24 14:12:38 +010025 union me_hfs hfs = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS) };
26 union me_hfs2 hfs2 = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS2) };
Aaron Durbin76c37002012-10-30 09:03:43 -050027
Angel Pons55405a32021-11-24 15:04:05 +010028 intel_me_status(hfs, hfs2);
Aaron Durbin76c37002012-10-30 09:03:43 -050029}
30
31int intel_early_me_init(void)
32{
33 int count;
Angel Pons032255c2021-11-24 14:12:38 +010034 union me_uma uma;
35 union me_hfs hfs;
Aaron Durbin76c37002012-10-30 09:03:43 -050036
37 printk(BIOS_INFO, "Intel ME early init\n");
38
39 /* Wait for ME UMA SIZE VALID bit to be set */
Aaron Durbin9aa031e2012-11-02 09:16:46 -050040 /* FIXME: ME9 BGW indicates a 5 sec poll timeout. */
Aaron Durbin76c37002012-10-30 09:03:43 -050041 for (count = ME_RETRY; count > 0; --count) {
Angel Pons032255c2021-11-24 14:12:38 +010042 uma.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_UMA);
Aaron Durbin76c37002012-10-30 09:03:43 -050043 if (uma.valid)
44 break;
45 udelay(ME_DELAY);
46 }
47 if (!count) {
Julius Wernere9665952022-01-21 17:06:20 -080048 printk(BIOS_ERR, "ME is not ready!\n");
Aaron Durbin76c37002012-10-30 09:03:43 -050049 return -1;
50 }
51
52 /* Check for valid firmware */
Angel Pons032255c2021-11-24 14:12:38 +010053 hfs.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
Aaron Durbin76c37002012-10-30 09:03:43 -050054 if (hfs.fpt_bad) {
Julius Wernere9665952022-01-21 17:06:20 -080055 printk(BIOS_WARNING, "ME has bad firmware\n");
Aaron Durbin76c37002012-10-30 09:03:43 -050056 return -1;
57 }
58
59 printk(BIOS_INFO, "Intel ME firmware is ready\n");
60 return 0;
61}
62
63int intel_early_me_uma_size(void)
64{
Angel Pons032255c2021-11-24 14:12:38 +010065 union me_uma uma = { .raw = pci_read_config32(PCH_ME_DEV, PCI_ME_UMA) };
Aaron Durbin76c37002012-10-30 09:03:43 -050066
Aaron Durbin76c37002012-10-30 09:03:43 -050067 if (uma.valid) {
68 printk(BIOS_DEBUG, "ME: Requested %uMB UMA\n", uma.size);
69 return uma.size;
70 }
71
72 printk(BIOS_DEBUG, "ME: Invalid UMA size\n");
73 return 0;
74}
75
76static inline void set_global_reset(int enable)
77{
Aaron Durbinb9ea8b32012-11-02 09:10:30 -050078 u32 pmir = pci_read_config32(PCH_LPC_DEV, PMIR);
Aaron Durbin76c37002012-10-30 09:03:43 -050079
80 /* CF9GR indicates a Global Reset */
81 if (enable)
Aaron Durbinb9ea8b32012-11-02 09:10:30 -050082 pmir |= PMIR_CF9GR;
Aaron Durbin76c37002012-10-30 09:03:43 -050083 else
Aaron Durbinb9ea8b32012-11-02 09:10:30 -050084 pmir &= ~PMIR_CF9GR;
Aaron Durbin76c37002012-10-30 09:03:43 -050085
Aaron Durbinb9ea8b32012-11-02 09:10:30 -050086 pci_write_config32(PCH_LPC_DEV, PMIR, pmir);
Aaron Durbin76c37002012-10-30 09:03:43 -050087}
88
89int intel_early_me_init_done(u8 status)
90{
91 u8 reset;
92 int count;
93 u32 mebase_l, mebase_h;
Angel Pons032255c2021-11-24 14:12:38 +010094 union me_hfs hfs;
95 union me_did did = {
Aaron Durbin76c37002012-10-30 09:03:43 -050096 .init_done = ME_INIT_DONE,
97 .status = status
98 };
99
100 /* MEBASE from MESEG_BASE[35:20] */
101 mebase_l = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_L);
102 mebase_h = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_H) & 0xf;
103 did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
104
105 /* Send message to ME */
106 printk(BIOS_DEBUG, "ME: Sending Init Done with status: %d, "
107 "UMA base: 0x%04x\n", status, did.uma_base);
108
Angel Pons032255c2021-11-24 14:12:38 +0100109 pci_write_config32(PCH_ME_DEV, PCI_ME_H_GS, did.raw);
Aaron Durbin76c37002012-10-30 09:03:43 -0500110
Aaron Durbin9aa031e2012-11-02 09:16:46 -0500111 /*
112 * The ME firmware does not respond with an ACK when NOMEM or ERROR
113 * are sent.
114 */
115 if (status == ME_INIT_STATUS_NOMEM || status == ME_INIT_STATUS_ERROR)
116 return 0;
117
Aaron Durbin76c37002012-10-30 09:03:43 -0500118 /* Must wait for ME acknowledgement */
119 for (count = ME_RETRY; count > 0; --count) {
Angel Pons032255c2021-11-24 14:12:38 +0100120 hfs.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
Aaron Durbin76c37002012-10-30 09:03:43 -0500121 if (hfs.bios_msg_ack)
122 break;
123 udelay(ME_DELAY);
124 }
125 if (!count) {
Julius Wernere9665952022-01-21 17:06:20 -0800126 printk(BIOS_ERR, "ME failed to respond\n");
Aaron Durbin76c37002012-10-30 09:03:43 -0500127 return -1;
128 }
129
130 /* Return the requested BIOS action */
131 printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n",
132 me_ack_values[hfs.ack_data]);
133
134 /* Check status after acknowledgement */
135 intel_early_me_status();
136
137 reset = 0;
138 switch (hfs.ack_data) {
139 case ME_HFS_ACK_CONTINUE:
140 /* Continue to boot */
141 return 0;
142 case ME_HFS_ACK_RESET:
143 /* Non-power cycle reset */
144 set_global_reset(0);
145 reset = 0x06;
146 break;
147 case ME_HFS_ACK_PWR_CYCLE:
148 /* Power cycle reset */
149 set_global_reset(0);
150 reset = 0x0e;
151 break;
152 case ME_HFS_ACK_GBL_RESET:
153 /* Global reset */
154 set_global_reset(1);
155 reset = 0x0e;
156 break;
157 case ME_HFS_ACK_S3:
158 case ME_HFS_ACK_S4:
159 case ME_HFS_ACK_S5:
160 break;
161 }
162
163 /* Perform the requested reset */
164 if (reset) {
165 outb(reset, 0xcf9);
Patrick Georgibd79c5e2014-11-28 22:35:36 +0100166 halt();
Aaron Durbin76c37002012-10-30 09:03:43 -0500167 }
168 return -1;
169}