blob: 2582abb680e1f5901a4116067e850dfd94c45b84 [file] [log] [blame]
Angel Pons182dbde2020-04-02 23:49:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07002
3#include <arch/io.h>
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02004#include <device/pci_ops.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07005#include <console/console.h>
6#include <delay.h>
Nicola Corna14604da2018-05-15 17:15:03 +02007#include <device/pci_def.h>
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -07008#include <halt.h>
Angel Pons20a609f2021-02-06 23:22:33 +01009#include <southbridge/intel/common/me.h>
Elyes HAOUAS249343b2021-12-31 08:40:53 +010010
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070011#include "me.h"
12#include "pch.h"
13
14static const char *me_ack_values[] = {
15 [ME_HFS_ACK_NO_DID] = "No DID Ack received",
16 [ME_HFS_ACK_RESET] = "Non-power cycle reset",
17 [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset",
18 [ME_HFS_ACK_S3] = "Go to S3",
19 [ME_HFS_ACK_S4] = "Go to S4",
20 [ME_HFS_ACK_S5] = "Go to S5",
21 [ME_HFS_ACK_GBL_RESET] = "Global Reset",
22 [ME_HFS_ACK_CONTINUE] = "Continue to boot"
23};
24
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070025void intel_early_me_status(void)
26{
Angel Pons3f7bb7d2021-01-27 13:03:20 +010027 union me_hfs hfs;
28 union me_gmes gmes;
Nicola Corna14604da2018-05-15 17:15:03 +020029 u32 id = pci_read_config32(PCH_ME_DEV, PCI_VENDOR_ID);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070030
Nicola Corna14604da2018-05-15 17:15:03 +020031 if ((id == 0xffffffff) || (id == 0x00000000) ||
32 (id == 0x0000ffff) || (id == 0xffff0000)) {
33 printk(BIOS_DEBUG, "Missing Intel ME PCI device.\n");
34 } else {
Angel Pons3f7bb7d2021-01-27 13:03:20 +010035 hfs.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
36 gmes.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_GMES);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070037
Nicola Corna14604da2018-05-15 17:15:03 +020038 intel_me_status(&hfs, &gmes);
39 }
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070040}
41
42int intel_early_me_init(void)
43{
44 int count;
Angel Pons3f7bb7d2021-01-27 13:03:20 +010045 union me_uma uma;
46 union me_hfs hfs;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070047
48 printk(BIOS_INFO, "Intel ME early init\n");
49
50 /* Wait for ME UMA SIZE VALID bit to be set */
51 for (count = ME_RETRY; count > 0; --count) {
Angel Pons3f7bb7d2021-01-27 13:03:20 +010052 uma.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_UMA);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070053 if (uma.valid)
54 break;
55 udelay(ME_DELAY);
56 }
57 if (!count) {
58 printk(BIOS_ERR, "ERROR: ME is not ready!\n");
59 return -1;
60 }
61
62 /* Check for valid firmware */
Angel Pons3f7bb7d2021-01-27 13:03:20 +010063 hfs.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070064 if (hfs.fpt_bad) {
65 printk(BIOS_WARNING, "WARNING: ME has bad firmware\n");
66 return -1;
67 }
68
69 printk(BIOS_INFO, "Intel ME firmware is ready\n");
70 return 0;
71}
72
73int intel_early_me_uma_size(void)
74{
Angel Pons3f7bb7d2021-01-27 13:03:20 +010075 union me_uma uma;
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070076
Angel Pons3f7bb7d2021-01-27 13:03:20 +010077 uma.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_UMA);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070078 if (uma.valid) {
79 printk(BIOS_DEBUG, "ME: Requested %uMB UMA\n", uma.size);
80 return uma.size;
81 }
82
83 printk(BIOS_DEBUG, "ME: Invalid UMA size\n");
84 return 0;
85}
86
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070087int intel_early_me_init_done(u8 status)
88{
89 u8 reset;
90 int count;
91 u32 mebase_l, mebase_h;
Angel Pons3f7bb7d2021-01-27 13:03:20 +010092 union me_hfs hfs;
93 union me_did did = {
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -070094 .init_done = ME_INIT_DONE,
95 .status = status
96 };
97
98 /* MEBASE from MESEG_BASE[35:20] */
99 mebase_l = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_L);
100 mebase_h = pci_read_config32(PCI_CPU_DEVICE, PCI_CPU_MEBASE_H) & 0xf;
101 did.uma_base = (mebase_l >> 20) | (mebase_h << 12);
102
103 /* Send message to ME */
104 printk(BIOS_DEBUG, "ME: Sending Init Done with status: %d, "
105 "UMA base: 0x%04x\n", status, did.uma_base);
106
Angel Pons3f7bb7d2021-01-27 13:03:20 +0100107 pci_write_config32(PCH_ME_DEV, PCI_ME_H_GS, did.raw);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700108
109 /* Must wait for ME acknowledgement */
110 for (count = ME_RETRY; count > 0; --count) {
Angel Pons3f7bb7d2021-01-27 13:03:20 +0100111 hfs.raw = pci_read_config32(PCH_ME_DEV, PCI_ME_HFS);
Alexandru Gagniucecf2eb42015-09-28 21:39:12 -0700112 if (hfs.bios_msg_ack)
113 break;
114 udelay(ME_DELAY);
115 }
116 if (!count) {
117 printk(BIOS_ERR, "ERROR: ME failed to respond\n");
118 return -1;
119 }
120
121 /* Return the requested BIOS action */
122 printk(BIOS_NOTICE, "ME: Requested BIOS Action: %s\n",
123 me_ack_values[hfs.ack_data]);
124
125 /* Check status after acknowledgement */
126 intel_early_me_status();
127
128 reset = 0;
129 switch (hfs.ack_data) {
130 case ME_HFS_ACK_CONTINUE:
131 /* Continue to boot */
132 return 0;
133 case ME_HFS_ACK_RESET:
134 /* Non-power cycle reset */
135 set_global_reset(0);
136 reset = 0x06;
137 break;
138 case ME_HFS_ACK_PWR_CYCLE:
139 /* Power cycle reset */
140 set_global_reset(0);
141 reset = 0x0e;
142 break;
143 case ME_HFS_ACK_GBL_RESET:
144 /* Global reset */
145 set_global_reset(1);
146 reset = 0x0e;
147 break;
148 case ME_HFS_ACK_S3:
149 case ME_HFS_ACK_S4:
150 case ME_HFS_ACK_S5:
151 break;
152 }
153
154 /* Perform the requested reset */
155 if (reset) {
156 outb(reset, 0xcf9);
157 halt();
158 }
159 return -1;
160}