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