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