1 /* 2 * Copyright (c) 2014 Google, Inc 3 * (C) Copyright 2008 4 * Graeme Russ, graeme.russ@gmail.com. 5 * 6 * Some portions from coreboot src/mainboard/google/link/romstage.c 7 * and src/cpu/intel/model_206ax/bootblock.c 8 * Copyright (C) 2007-2010 coresystems GmbH 9 * Copyright (C) 2011 Google Inc. 10 * 11 * SPDX-License-Identifier: GPL-2.0 12 */ 13 14 #include <common.h> 15 #include <dm.h> 16 #include <errno.h> 17 #include <fdtdec.h> 18 #include <pch.h> 19 #include <asm/cpu.h> 20 #include <asm/cpu_common.h> 21 #include <asm/intel_regs.h> 22 #include <asm/io.h> 23 #include <asm/lapic.h> 24 #include <asm/lpc_common.h> 25 #include <asm/microcode.h> 26 #include <asm/msr.h> 27 #include <asm/mtrr.h> 28 #include <asm/pci.h> 29 #include <asm/post.h> 30 #include <asm/processor.h> 31 #include <asm/arch/model_206ax.h> 32 #include <asm/arch/pch.h> 33 #include <asm/arch/sandybridge.h> 34 35 DECLARE_GLOBAL_DATA_PTR; 36 37 static int set_flex_ratio_to_tdp_nominal(void) 38 { 39 /* Minimum CPU revision for configurable TDP support */ 40 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID) 41 return -EINVAL; 42 43 return cpu_set_flex_ratio_to_tdp_nominal(); 44 } 45 46 int arch_cpu_init(void) 47 { 48 post_code(POST_CPU_INIT); 49 50 return x86_cpu_init_f(); 51 } 52 53 int arch_cpu_init_dm(void) 54 { 55 struct pci_controller *hose; 56 struct udevice *bus, *dev; 57 int ret; 58 59 post_code(0x70); 60 ret = uclass_get_device(UCLASS_PCI, 0, &bus); 61 post_code(0x71); 62 if (ret) 63 return ret; 64 post_code(0x72); 65 hose = dev_get_uclass_priv(bus); 66 67 /* TODO(sjg@chromium.org): Get rid of gd->hose */ 68 gd->hose = hose; 69 70 ret = uclass_first_device_err(UCLASS_LPC, &dev); 71 if (ret) 72 return ret; 73 74 /* 75 * We should do as little as possible before the serial console is 76 * up. Perhaps this should move to later. Our next lot of init 77 * happens in print_cpuinfo() when we have a console 78 */ 79 ret = set_flex_ratio_to_tdp_nominal(); 80 if (ret) 81 return ret; 82 83 return 0; 84 } 85 86 #define PCH_EHCI0_TEMP_BAR0 0xe8000000 87 #define PCH_EHCI1_TEMP_BAR0 0xe8000400 88 #define PCH_XHCI_TEMP_BAR0 0xe8001000 89 90 /* 91 * Setup USB controller MMIO BAR to prevent the reference code from 92 * resetting the controller. 93 * 94 * The BAR will be re-assigned during device enumeration so these are only 95 * temporary. 96 * 97 * This is used to speed up the resume path. 98 */ 99 static void enable_usb_bar(struct udevice *bus) 100 { 101 pci_dev_t usb0 = PCH_EHCI1_DEV; 102 pci_dev_t usb1 = PCH_EHCI2_DEV; 103 pci_dev_t usb3 = PCH_XHCI_DEV; 104 ulong cmd; 105 106 /* USB Controller 1 */ 107 pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0, 108 PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32); 109 pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32); 110 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 111 pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32); 112 113 /* USB Controller 2 */ 114 pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0, 115 PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32); 116 pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32); 117 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 118 pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32); 119 120 /* USB3 Controller 1 */ 121 pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0, 122 PCH_XHCI_TEMP_BAR0, PCI_SIZE_32); 123 pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32); 124 cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 125 pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32); 126 } 127 128 int print_cpuinfo(void) 129 { 130 enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE; 131 char processor_name[CPU_MAX_NAME_LEN]; 132 struct udevice *dev, *lpc; 133 const char *name; 134 uint32_t pm1_cnt; 135 uint16_t pm1_sts; 136 int ret; 137 138 /* TODO: cmos_post_init() */ 139 if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) { 140 debug("soft reset detected\n"); 141 boot_mode = PEI_BOOT_SOFT_RESET; 142 143 /* System is not happy after keyboard reset... */ 144 debug("Issuing CF9 warm reset\n"); 145 reset_cpu(0); 146 } 147 148 ret = cpu_common_init(); 149 if (ret) { 150 debug("%s: cpu_common_init() failed\n", __func__); 151 return ret; 152 } 153 154 /* Check PM1_STS[15] to see if we are waking from Sx */ 155 pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); 156 157 /* Read PM1_CNT[12:10] to determine which Sx state */ 158 pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT); 159 160 if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) { 161 debug("Resume from S3 detected, but disabled.\n"); 162 } else { 163 /* 164 * TODO: An indication of life might be possible here (e.g. 165 * keyboard light) 166 */ 167 } 168 post_code(POST_EARLY_INIT); 169 170 /* Enable SPD ROMs and DDR-III DRAM */ 171 ret = uclass_first_device_err(UCLASS_I2C, &dev); 172 if (ret) { 173 debug("%s: Failed to get I2C (ret=%d)\n", __func__, ret); 174 return ret; 175 } 176 177 /* Prepare USB controller early in S3 resume */ 178 if (boot_mode == PEI_BOOT_RESUME) { 179 uclass_first_device(UCLASS_LPC, &lpc); 180 enable_usb_bar(pci_get_controller(lpc->parent)); 181 } 182 183 gd->arch.pei_boot_mode = boot_mode; 184 185 /* Print processor name */ 186 name = cpu_get_name(processor_name); 187 printf("CPU: %s\n", name); 188 189 post_code(POST_CPU_INFO); 190 191 return 0; 192 } 193 194 void board_debug_uart_init(void) 195 { 196 /* This enables the debug UART */ 197 pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, 198 PCI_SIZE_16); 199 } 200