Hi Simon, On Wed, Nov 12, 2014 at 12:15 AM, Simon Glass <s...@chromium.org> wrote: > Hi Bin, > > On 11 November 2014 07:52, Bin Meng <bmeng...@gmail.com> wrote: >> Hi Simon, >> >> On Fri, Nov 7, 2014 at 4:20 AM, Simon Glass <s...@chromium.org> wrote: >>> Many PCH devices are hard-coded to a particular PCI address. Set these >>> up early in case they are needed. >>> >>> Signed-off-by: Simon Glass <s...@chromium.org> >>> --- >>> >>> arch/x86/cpu/ivybridge/Makefile | 1 + >>> arch/x86/cpu/ivybridge/cpu.c | 142 >>> +++++++++++++++++++++ >>> arch/x86/cpu/ivybridge/early_init.c | 145 >>> ++++++++++++++++++++++ >>> arch/x86/include/asm/arch-ivybridge/pch.h | 121 +++++++++++++++++- >>> arch/x86/include/asm/arch-ivybridge/sandybridge.h | 107 ++++++++++++++++ >>> arch/x86/include/asm/global_data.h | 8 ++ >>> arch/x86/include/asm/post.h | 2 + >>> 7 files changed, 525 insertions(+), 1 deletion(-) >>> create mode 100644 arch/x86/cpu/ivybridge/early_init.c >>> create mode 100644 arch/x86/include/asm/arch-ivybridge/sandybridge.h >>> >>> diff --git a/arch/x86/cpu/ivybridge/Makefile >>> b/arch/x86/cpu/ivybridge/Makefile >>> index a3ea566..4bfb03a 100644 >>> --- a/arch/x86/cpu/ivybridge/Makefile >>> +++ b/arch/x86/cpu/ivybridge/Makefile >>> @@ -6,6 +6,7 @@ >>> >>> obj-y += car.o >>> obj-y += cpu.o >>> +obj-y += early_init.o >>> obj-y += lpc.o >>> obj-y += microcode_intel.o >>> obj-y += sdram.o >>> diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c >>> index bd2660f..a435520 100644 >>> --- a/arch/x86/cpu/ivybridge/cpu.c >>> +++ b/arch/x86/cpu/ivybridge/cpu.c >>> @@ -4,6 +4,7 @@ >>> * Graeme Russ, graeme.r...@gmail.com. >>> * >>> * Some portions from coreboot src/mainboard/google/link/romstage.c >>> + * and src/cpu/intel/model_206ax/bootblock.c >>> * Copyright (C) 2007-2010 coresystems GmbH >>> * Copyright (C) 2011 Google Inc. >>> * >>> @@ -16,11 +17,13 @@ >>> #include <asm/io.h> >>> #include <asm/msr.h> >>> #include <asm/mtrr.h> >>> +#include <asm/pci.h> >>> #include <asm/post.h> >>> #include <asm/processor.h> >>> #include <asm/arch/model_206ax.h> >>> #include <asm/arch/microcode.h> >>> #include <asm/arch/pch.h> >>> +#include <asm/arch/sandybridge.h> >>> >>> DECLARE_GLOBAL_DATA_PTR; >>> >>> @@ -178,6 +181,83 @@ int arch_cpu_init(void) >>> return 0; >>> } >>> >>> +static int enable_smbus(void) >>> +{ >>> + pci_dev_t dev; >>> + uint16_t value; >>> + >>> + /* Set the SMBus device statically. */ >>> + dev = PCI_BDF(0x0, 0x1f, 0x3); >>> + >>> + /* Check to make sure we've got the right device. */ >>> + value = pci_read_config16(dev, 0x0); >>> + if (value != 0x8086) { >>> + printf("SMBus controller not found\n"); >>> + return -ENOSYS; >>> + } >>> + >>> + /* Set SMBus I/O base. */ >>> + pci_write_config32(dev, SMB_BASE, >>> + SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO); >>> + >>> + /* Set SMBus enable. */ >>> + pci_write_config8(dev, HOSTC, HST_EN); >>> + >>> + /* Set SMBus I/O space enable. */ >>> + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO); >>> + >>> + /* Disable interrupt generation. */ >>> + outb(0, SMBUS_IO_BASE + SMBHSTCTL); >>> + >>> + /* Clear any lingering errors, so transactions can run. */ >>> + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); >>> + debug("SMBus controller enabled\n"); >>> + >>> + return 0; >>> +} >>> + >>> +#define PCH_EHCI0_TEMP_BAR0 0xe8000000 >>> +#define PCH_EHCI1_TEMP_BAR0 0xe8000400 >>> +#define PCH_XHCI_TEMP_BAR0 0xe8001000 >>> + >>> +/* >>> + * Setup USB controller MMIO BAR to prevent the reference code from >>> + * resetting the controller. >>> + * >>> + * The BAR will be re-assigned during device enumeration so these are only >>> + * temporary. >>> + * >>> + * This is used to speed up the resume path. >>> + */ >>> +static void enable_usb_bar(void) >>> +{ >>> + pci_dev_t usb0 = PCH_EHCI1_DEV; >>> + pci_dev_t usb1 = PCH_EHCI2_DEV; >>> + pci_dev_t usb3 = PCH_XHCI_DEV; >>> + u32 cmd; >>> + >>> + /* USB Controller 1 */ >>> + pci_write_config32(usb0, PCI_BASE_ADDRESS_0, >>> + PCH_EHCI0_TEMP_BAR0); >>> + cmd = pci_read_config32(usb0, PCI_COMMAND); >>> + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; >>> + pci_write_config32(usb0, PCI_COMMAND, cmd); >>> + >>> + /* USB Controller 1 */ >>> + pci_write_config32(usb1, PCI_BASE_ADDRESS_0, >>> + PCH_EHCI1_TEMP_BAR0); >>> + cmd = pci_read_config32(usb1, PCI_COMMAND); >>> + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; >>> + pci_write_config32(usb1, PCI_COMMAND, cmd); >>> + >>> + /* USB3 Controller */ >>> + pci_write_config32(usb3, PCI_BASE_ADDRESS_0, >>> + PCH_XHCI_TEMP_BAR0); >>> + cmd = pci_read_config32(usb3, PCI_COMMAND); >>> + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; >>> + pci_write_config32(usb3, PCI_COMMAND, cmd); >>> +} >>> + >>> static int report_bist_failure(void) >>> { >>> if (gd->arch.bist != 0) { >>> @@ -190,8 +270,11 @@ static int report_bist_failure(void) >>> >>> int print_cpuinfo(void) >>> { >>> + enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE; >>> char processor_name[CPU_MAX_NAME_LEN]; >>> const char *name; >>> + uint32_t pm1_cnt; >>> + uint16_t pm1_sts; >>> int ret; >>> >>> /* Halt if there was a built in self test failure */ >>> @@ -203,9 +286,68 @@ int print_cpuinfo(void) >>> if (ret && ret != -ENOENT && ret != -EEXIST) >>> return ret; >>> >>> + /* Enable upper 128bytes of CMOS */ >>> + writel(1 << 2, RCB_REG(RC)); >>> + >>> + /* TODO: cmos_post_init() */ >>> + if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) { >>> + debug("soft reset detected\n"); >>> + boot_mode = PEI_BOOT_SOFT_RESET; >>> + >>> + /* System is not happy after keyboard reset... */ >>> + debug("Issuing CF9 warm reset\n"); >>> + outb(0x6, 0xcf9); >>> + cpu_hlt(); >>> + } >>> + >>> + /* Early chipset init required before RAM init can work */ >>> + sandybridge_early_init(SANDYBRIDGE_MOBILE); >>> + >>> + /* Check PM1_STS[15] to see if we are waking from Sx */ >>> + pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); >>> + >>> + /* Read PM1_CNT[12:10] to determine which Sx state */ >>> + pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT); >>> + >>> + if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) { >>> +#if CONFIG_HAVE_ACPI_RESUME >>> + debug("Resume from S3 detected.\n"); >>> + boot_mode = PEI_BOOT_RESUME; >>> + /* Clear SLP_TYPE. This will break stage2 but >>> + * we care for that when we get there. >>> + */ >>> + outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT); >>> +#else >>> + debug("Resume from S3 detected, but disabled.\n"); >>> +#endif >>> + } else { >>> + /* >>> + * TODO: An indication of life might be possible here (e.g. >>> + * keyboard light) >>> + */ >>> + } >>> + post_code(POST_EARLY_INIT); >>> + >>> + /* Enable SPD ROMs and DDR-III DRAM */ >>> + ret = enable_smbus(); >>> + if (ret) >>> + return ret; >>> + >>> + /* Prepare USB controller early in S3 resume */ >>> + if (boot_mode == PEI_BOOT_RESUME) >>> + enable_usb_bar(); >>> + >>> + gd->arch.pei_boot_mode = boot_mode; >>> + >>> + /* TODO: Move this to the board or driver */ >>> + pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1); >>> + pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10); >>> + >> >> Are these additional initialization needed right here? Can they be >> moved to somewhere else, so that print_cpuinfo() is just doing its job >> of printing cpu information? > > I believe it is all needed. I have already moved out quite a bit of > stuff. We could add a new init function, but for now I wanted to avoid > this, since the init list is generic.
After looking all the initialization routines in common/board_f.c, if these cannot be done in arch_cpu_init(), could we move them to board_early_init_f()? > Re the last bit (GPIO) it seems to have to happen here, or at least a > while before the GPIOs are actually used. Otherwise they fail. > > Regards, > Simon Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot