1 /* 2 * From Coreboot src/southbridge/intel/bd82x6x/early_me.c 3 * 4 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. 5 * 6 * SPDX-License-Identifier: GPL-2.0 7 */ 8 9 #include <common.h> 10 #include <errno.h> 11 #include <asm/pci.h> 12 #include <asm/processor.h> 13 #include <asm/arch/me.h> 14 #include <asm/arch/pch.h> 15 #include <asm/io.h> 16 17 static const char *const me_ack_values[] = { 18 [ME_HFS_ACK_NO_DID] = "No DID Ack received", 19 [ME_HFS_ACK_RESET] = "Non-power cycle reset", 20 [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset", 21 [ME_HFS_ACK_S3] = "Go to S3", 22 [ME_HFS_ACK_S4] = "Go to S4", 23 [ME_HFS_ACK_S5] = "Go to S5", 24 [ME_HFS_ACK_GBL_RESET] = "Global Reset", 25 [ME_HFS_ACK_CONTINUE] = "Continue to boot" 26 }; 27 28 static inline void pci_read_dword_ptr(void *ptr, int offset) 29 { 30 u32 dword; 31 32 dword = x86_pci_read_config32(PCH_ME_DEV, offset); 33 memcpy(ptr, &dword, sizeof(dword)); 34 } 35 36 static inline void pci_write_dword_ptr(void *ptr, int offset) 37 { 38 u32 dword = 0; 39 memcpy(&dword, ptr, sizeof(dword)); 40 x86_pci_write_config32(PCH_ME_DEV, offset, dword); 41 } 42 43 void intel_early_me_status(void) 44 { 45 struct me_hfs hfs; 46 struct me_gmes gmes; 47 48 pci_read_dword_ptr(&hfs, PCI_ME_HFS); 49 pci_read_dword_ptr(&gmes, PCI_ME_GMES); 50 51 intel_me_status(&hfs, &gmes); 52 } 53 54 int intel_early_me_init(void) 55 { 56 int count; 57 struct me_uma uma; 58 struct me_hfs hfs; 59 60 debug("Intel ME early init\n"); 61 62 /* Wait for ME UMA SIZE VALID bit to be set */ 63 for (count = ME_RETRY; count > 0; --count) { 64 pci_read_dword_ptr(&uma, PCI_ME_UMA); 65 if (uma.valid) 66 break; 67 udelay(ME_DELAY); 68 } 69 if (!count) { 70 printf("ERROR: ME is not ready!\n"); 71 return -EBUSY; 72 } 73 74 /* Check for valid firmware */ 75 pci_read_dword_ptr(&hfs, PCI_ME_HFS); 76 if (hfs.fpt_bad) { 77 printf("WARNING: ME has bad firmware\n"); 78 return -EBADF; 79 } 80 81 debug("Intel ME firmware is ready\n"); 82 83 return 0; 84 } 85 86 int intel_early_me_uma_size(void) 87 { 88 struct me_uma uma; 89 90 pci_read_dword_ptr(&uma, PCI_ME_UMA); 91 if (uma.valid) { 92 debug("ME: Requested %uMB UMA\n", uma.size); 93 return uma.size; 94 } 95 96 debug("ME: Invalid UMA size\n"); 97 return -EINVAL; 98 } 99 100 static inline void set_global_reset(int enable) 101 { 102 u32 etr3; 103 104 etr3 = x86_pci_read_config32(PCH_LPC_DEV, ETR3); 105 106 /* Clear CF9 Without Resume Well Reset Enable */ 107 etr3 &= ~ETR3_CWORWRE; 108 109 /* CF9GR indicates a Global Reset */ 110 if (enable) 111 etr3 |= ETR3_CF9GR; 112 else 113 etr3 &= ~ETR3_CF9GR; 114 115 x86_pci_write_config32(PCH_LPC_DEV, ETR3, etr3); 116 } 117 118 int intel_early_me_init_done(u8 status) 119 { 120 int count; 121 u32 mebase_l, mebase_h; 122 struct me_hfs hfs; 123 struct me_did did = { 124 .init_done = ME_INIT_DONE, 125 .status = status 126 }; 127 128 /* MEBASE from MESEG_BASE[35:20] */ 129 mebase_l = x86_pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_L); 130 mebase_h = x86_pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_H); 131 mebase_h &= 0xf; 132 did.uma_base = (mebase_l >> 20) | (mebase_h << 12); 133 134 /* Send message to ME */ 135 debug("ME: Sending Init Done with status: %d, UMA base: 0x%04x\n", 136 status, did.uma_base); 137 138 pci_write_dword_ptr(&did, PCI_ME_H_GS); 139 140 /* Must wait for ME acknowledgement */ 141 for (count = ME_RETRY; count > 0; --count) { 142 pci_read_dword_ptr(&hfs, PCI_ME_HFS); 143 if (hfs.bios_msg_ack) 144 break; 145 udelay(ME_DELAY); 146 } 147 if (!count) { 148 printf("ERROR: ME failed to respond\n"); 149 return -1; 150 } 151 152 /* Return the requested BIOS action */ 153 debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]); 154 155 /* Check status after acknowledgement */ 156 intel_early_me_status(); 157 158 switch (hfs.ack_data) { 159 case ME_HFS_ACK_CONTINUE: 160 /* Continue to boot */ 161 return 0; 162 case ME_HFS_ACK_RESET: 163 /* Non-power cycle reset */ 164 set_global_reset(0); 165 reset_cpu(0); 166 break; 167 case ME_HFS_ACK_PWR_CYCLE: 168 /* Power cycle reset */ 169 set_global_reset(0); 170 x86_full_reset(); 171 break; 172 case ME_HFS_ACK_GBL_RESET: 173 /* Global reset */ 174 set_global_reset(1); 175 x86_full_reset(); 176 break; 177 case ME_HFS_ACK_S3: 178 case ME_HFS_ACK_S4: 179 case ME_HFS_ACK_S5: 180 break; 181 } 182 183 return -1; 184 } 185