18ef07571SSimon Glass /* 28ef07571SSimon Glass * Copyright (c) 2014 Google, Inc 38ef07571SSimon Glass * (C) Copyright 2008 48ef07571SSimon Glass * Graeme Russ, graeme.russ@gmail.com. 58ef07571SSimon Glass * 68ef07571SSimon Glass * Some portions from coreboot src/mainboard/google/link/romstage.c 78e0df066SSimon Glass * and src/cpu/intel/model_206ax/bootblock.c 88ef07571SSimon Glass * Copyright (C) 2007-2010 coresystems GmbH 98ef07571SSimon Glass * Copyright (C) 2011 Google Inc. 108ef07571SSimon Glass * 118ef07571SSimon Glass * SPDX-License-Identifier: GPL-2.0 128ef07571SSimon Glass */ 138ef07571SSimon Glass 148ef07571SSimon Glass #include <common.h> 15aad78d27SSimon Glass #include <dm.h> 162b605154SSimon Glass #include <errno.h> 172b605154SSimon Glass #include <fdtdec.h> 18858361b1SSimon Glass #include <pch.h> 198ef07571SSimon Glass #include <asm/cpu.h> 2050dd3da0SSimon Glass #include <asm/cpu_common.h> 2106d336ccSSimon Glass #include <asm/intel_regs.h> 22f5fbbe95SSimon Glass #include <asm/io.h> 233eafce05SSimon Glass #include <asm/lapic.h> 247e4a6ae6SSimon Glass #include <asm/lpc_common.h> 259e66506dSSimon Glass #include <asm/microcode.h> 26f5fbbe95SSimon Glass #include <asm/msr.h> 27f5fbbe95SSimon Glass #include <asm/mtrr.h> 286e5b12b6SSimon Glass #include <asm/pci.h> 2970a09c6cSSimon Glass #include <asm/post.h> 308ef07571SSimon Glass #include <asm/processor.h> 31f5fbbe95SSimon Glass #include <asm/arch/model_206ax.h> 322b605154SSimon Glass #include <asm/arch/pch.h> 338e0df066SSimon Glass #include <asm/arch/sandybridge.h> 348ef07571SSimon Glass 358ef07571SSimon Glass DECLARE_GLOBAL_DATA_PTR; 368ef07571SSimon Glass 37f5fbbe95SSimon Glass static int set_flex_ratio_to_tdp_nominal(void) 38f5fbbe95SSimon Glass { 39f5fbbe95SSimon Glass /* Minimum CPU revision for configurable TDP support */ 40f5fbbe95SSimon Glass if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID) 41f5fbbe95SSimon Glass return -EINVAL; 42f5fbbe95SSimon Glass 4350dd3da0SSimon Glass return cpu_set_flex_ratio_to_tdp_nominal(); 44f5fbbe95SSimon Glass } 45f5fbbe95SSimon Glass 468ef07571SSimon Glass int arch_cpu_init(void) 478ef07571SSimon Glass { 48161d2e4eSSimon Glass post_code(POST_CPU_INIT); 49161d2e4eSSimon Glass 50161d2e4eSSimon Glass return x86_cpu_init_f(); 51161d2e4eSSimon Glass } 52161d2e4eSSimon Glass 53161d2e4eSSimon Glass int arch_cpu_init_dm(void) 54161d2e4eSSimon Glass { 556e5b12b6SSimon Glass struct pci_controller *hose; 564acc83d4SSimon Glass struct udevice *bus, *dev; 578ef07571SSimon Glass int ret; 588ef07571SSimon Glass 59aad78d27SSimon Glass post_code(0x70); 60aad78d27SSimon Glass ret = uclass_get_device(UCLASS_PCI, 0, &bus); 61aad78d27SSimon Glass post_code(0x71); 628ef07571SSimon Glass if (ret) 638ef07571SSimon Glass return ret; 64aad78d27SSimon Glass post_code(0x72); 65aad78d27SSimon Glass hose = dev_get_uclass_priv(bus); 668ef07571SSimon Glass 67aad78d27SSimon Glass /* TODO(sjg@chromium.org): Get rid of gd->hose */ 68aad78d27SSimon Glass gd->hose = hose; 696e5b12b6SSimon Glass 703f603cbbSSimon Glass ret = uclass_first_device_err(UCLASS_LPC, &dev); 713f603cbbSSimon Glass if (ret) 723f603cbbSSimon Glass return ret; 734acc83d4SSimon Glass 74f5fbbe95SSimon Glass /* 75f5fbbe95SSimon Glass * We should do as little as possible before the serial console is 76f5fbbe95SSimon Glass * up. Perhaps this should move to later. Our next lot of init 77*76d1d02fSSimon Glass * happens in checkcpu() when we have a console 78f5fbbe95SSimon Glass */ 79f5fbbe95SSimon Glass ret = set_flex_ratio_to_tdp_nominal(); 80f5fbbe95SSimon Glass if (ret) 81f5fbbe95SSimon Glass return ret; 82f5fbbe95SSimon Glass 838ef07571SSimon Glass return 0; 848ef07571SSimon Glass } 858ef07571SSimon Glass 868e0df066SSimon Glass #define PCH_EHCI0_TEMP_BAR0 0xe8000000 878e0df066SSimon Glass #define PCH_EHCI1_TEMP_BAR0 0xe8000400 888e0df066SSimon Glass #define PCH_XHCI_TEMP_BAR0 0xe8001000 898e0df066SSimon Glass 908e0df066SSimon Glass /* 918e0df066SSimon Glass * Setup USB controller MMIO BAR to prevent the reference code from 928e0df066SSimon Glass * resetting the controller. 938e0df066SSimon Glass * 948e0df066SSimon Glass * The BAR will be re-assigned during device enumeration so these are only 958e0df066SSimon Glass * temporary. 968e0df066SSimon Glass * 978e0df066SSimon Glass * This is used to speed up the resume path. 988e0df066SSimon Glass */ 995213f280SSimon Glass static void enable_usb_bar(struct udevice *bus) 1008e0df066SSimon Glass { 1018e0df066SSimon Glass pci_dev_t usb0 = PCH_EHCI1_DEV; 1028e0df066SSimon Glass pci_dev_t usb1 = PCH_EHCI2_DEV; 1038e0df066SSimon Glass pci_dev_t usb3 = PCH_XHCI_DEV; 1045213f280SSimon Glass ulong cmd; 1058e0df066SSimon Glass 1068e0df066SSimon Glass /* USB Controller 1 */ 1075213f280SSimon Glass pci_bus_write_config(bus, usb0, PCI_BASE_ADDRESS_0, 1085213f280SSimon Glass PCH_EHCI0_TEMP_BAR0, PCI_SIZE_32); 1095213f280SSimon Glass pci_bus_read_config(bus, usb0, PCI_COMMAND, &cmd, PCI_SIZE_32); 1108e0df066SSimon Glass cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 1115213f280SSimon Glass pci_bus_write_config(bus, usb0, PCI_COMMAND, cmd, PCI_SIZE_32); 1128e0df066SSimon Glass 1135213f280SSimon Glass /* USB Controller 2 */ 1145213f280SSimon Glass pci_bus_write_config(bus, usb1, PCI_BASE_ADDRESS_0, 1155213f280SSimon Glass PCH_EHCI1_TEMP_BAR0, PCI_SIZE_32); 1165213f280SSimon Glass pci_bus_read_config(bus, usb1, PCI_COMMAND, &cmd, PCI_SIZE_32); 1178e0df066SSimon Glass cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 1185213f280SSimon Glass pci_bus_write_config(bus, usb1, PCI_COMMAND, cmd, PCI_SIZE_32); 1198e0df066SSimon Glass 1205213f280SSimon Glass /* USB3 Controller 1 */ 1215213f280SSimon Glass pci_bus_write_config(bus, usb3, PCI_BASE_ADDRESS_0, 1225213f280SSimon Glass PCH_XHCI_TEMP_BAR0, PCI_SIZE_32); 1235213f280SSimon Glass pci_bus_read_config(bus, usb3, PCI_COMMAND, &cmd, PCI_SIZE_32); 1248e0df066SSimon Glass cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 1255213f280SSimon Glass pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32); 1268e0df066SSimon Glass } 1278e0df066SSimon Glass 128*76d1d02fSSimon Glass int checkcpu(void) 1298ef07571SSimon Glass { 1308e0df066SSimon Glass enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE; 131f633efa3SSimon Glass struct udevice *dev, *lpc; 1328e0df066SSimon Glass uint32_t pm1_cnt; 1338e0df066SSimon Glass uint16_t pm1_sts; 13494060ff2SSimon Glass int ret; 13594060ff2SSimon Glass 1368e0df066SSimon Glass /* TODO: cmos_post_init() */ 1378e0df066SSimon Glass if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) { 1388e0df066SSimon Glass debug("soft reset detected\n"); 1398e0df066SSimon Glass boot_mode = PEI_BOOT_SOFT_RESET; 1408e0df066SSimon Glass 1418e0df066SSimon Glass /* System is not happy after keyboard reset... */ 1428e0df066SSimon Glass debug("Issuing CF9 warm reset\n"); 1435021c81fSSimon Glass reset_cpu(0); 1448e0df066SSimon Glass } 1458e0df066SSimon Glass 14650dd3da0SSimon Glass ret = cpu_common_init(); 1474cc00f06SSimon Glass if (ret) { 1484cc00f06SSimon Glass debug("%s: cpu_common_init() failed\n", __func__); 149858361b1SSimon Glass return ret; 1504cc00f06SSimon Glass } 1518e0df066SSimon Glass 1528e0df066SSimon Glass /* Check PM1_STS[15] to see if we are waking from Sx */ 1538e0df066SSimon Glass pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); 1548e0df066SSimon Glass 1558e0df066SSimon Glass /* Read PM1_CNT[12:10] to determine which Sx state */ 1568e0df066SSimon Glass pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT); 1578e0df066SSimon Glass 1588e0df066SSimon Glass if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) { 1598e0df066SSimon Glass debug("Resume from S3 detected, but disabled.\n"); 1608e0df066SSimon Glass } else { 1618e0df066SSimon Glass /* 1628e0df066SSimon Glass * TODO: An indication of life might be possible here (e.g. 1638e0df066SSimon Glass * keyboard light) 1648e0df066SSimon Glass */ 1658e0df066SSimon Glass } 1668e0df066SSimon Glass post_code(POST_EARLY_INIT); 1678e0df066SSimon Glass 1688e0df066SSimon Glass /* Enable SPD ROMs and DDR-III DRAM */ 1693f603cbbSSimon Glass ret = uclass_first_device_err(UCLASS_I2C, &dev); 1708d8f3acdSSimon Glass if (ret) { 1718d8f3acdSSimon Glass debug("%s: Failed to get I2C (ret=%d)\n", __func__, ret); 1728e0df066SSimon Glass return ret; 1738d8f3acdSSimon Glass } 1748e0df066SSimon Glass 1758e0df066SSimon Glass /* Prepare USB controller early in S3 resume */ 17650dd3da0SSimon Glass if (boot_mode == PEI_BOOT_RESUME) { 17750dd3da0SSimon Glass uclass_first_device(UCLASS_LPC, &lpc); 1785213f280SSimon Glass enable_usb_bar(pci_get_controller(lpc->parent)); 17950dd3da0SSimon Glass } 1808e0df066SSimon Glass 1818e0df066SSimon Glass gd->arch.pei_boot_mode = boot_mode; 1828e0df066SSimon Glass 183*76d1d02fSSimon Glass return 0; 184*76d1d02fSSimon Glass } 185*76d1d02fSSimon Glass 186*76d1d02fSSimon Glass int print_cpuinfo(void) 187*76d1d02fSSimon Glass { 188*76d1d02fSSimon Glass char processor_name[CPU_MAX_NAME_LEN]; 189*76d1d02fSSimon Glass const char *name; 190*76d1d02fSSimon Glass 1918ef07571SSimon Glass /* Print processor name */ 1928ef07571SSimon Glass name = cpu_get_name(processor_name); 1938ef07571SSimon Glass printf("CPU: %s\n", name); 1948ef07571SSimon Glass 1958e0df066SSimon Glass post_code(POST_CPU_INFO); 1968e0df066SSimon Glass 1978ef07571SSimon Glass return 0; 1988ef07571SSimon Glass } 1997b95252dSSimon Glass 2007b95252dSSimon Glass void board_debug_uart_init(void) 2017b95252dSSimon Glass { 2027b95252dSSimon Glass /* This enables the debug UART */ 2037b95252dSSimon Glass pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, 2047b95252dSSimon Glass PCI_SIZE_16); 2057b95252dSSimon Glass } 206