[U-Boot] [PATCH v2 0/30] x86: Add additional system setup for ivybridge

This series adds full support for the LPC (Low Pin Count) bridge, the PCH (Platform Controller Hub), PCI devices like USB and SATA and more CPU init support (turbo mode, etc.)
With this series, chromebook_link can use SATA and USB at the command line.
Changes in v2: - Adjust rtc_init() call to remove the parameter - Change 'not' to 'no' since it reads better - Drop WIP commit for u-boot.srec as it is not needed now - Drop the part of the commit message that talks about using build date - Fix 'AT' value in link script - Move CLEAR_CMOS up to the top, indicated to be manually changed - Move common SATA init to a function to reduce duplication - Remove ISA DMA init which isn't needed in U-Boot - Remove i8259 patch and just update the existing interrupt code - Remove the parameter from rtc_init() and simplify the code - Remove use of __PRE_RAM__ define - Rename functions to pci_read_bar32() and pci_write_bar32() - Use .rel* instead of .rel.* to catch more cases - Use existing lapic_setup() code instead of duplicating it - Use i8259 init in pcat_interrupts.c - Use interrupt.h header instead of i8259.h - Use pci_write_bar32() to write to BARs
Simon Glass (30): Align embedded device tree correctly Add ALIGN_DOWN() to find next smallest alignment pci: Update pci_ids.h to include some missing IDs x86: Remove board_early_init_r() x86: Panic if there is no relocation data x86: Ensure that all relocation data is included in the image x86: Factor out common values in the link script rtc: mc146818: Set up RTC at start of day x86: Add ioapic.h header x86: pci: Add handlers before and after a PCI hose scan x86: config: Enable plug-and-play for link PCI pci: Add functions to read and write a BAR address x86: Set up edge triggering on interrupt 9 x86: ivybridge: Add support for BD82x6x PCH x86: Add a simple header file for ACPI x86: ivybridge: Add PCH init x86: ivybridge: Add additional LPC init x86: dts: Move PCI peripherals into a pci node x86: dts: Add LPC settings for link x86: ivybridge: Add SATA init x86: dts: Add SATA settings for link x86: ivybridge: Set up EHCI USB x86: config: Enable USB on link x86: ivybridge: Set up XHCI USB x86: Add Intel speedstep and turbo mode code x86: Add LAPIC setup code x86: Add init for model 206AX CPU x86: Drop some msr functions that we don't support x86: ivybridge: Add northbridge init functions x86: config: Enable SPI for chromebook_link
arch/x86/cpu/Makefile | 2 + arch/x86/cpu/config.mk | 5 +- arch/x86/cpu/coreboot/coreboot.c | 11 - arch/x86/cpu/ivybridge/Makefile | 7 + arch/x86/cpu/ivybridge/bd82x6x.c | 135 ++++++ arch/x86/cpu/ivybridge/lpc.c | 523 +++++++++++++++++++++- arch/x86/cpu/ivybridge/model_206ax.c | 514 +++++++++++++++++++++ arch/x86/cpu/ivybridge/northbridge.c | 188 ++++++++ arch/x86/cpu/ivybridge/pch.c | 123 +++++ arch/x86/cpu/ivybridge/pci.c | 40 ++ arch/x86/cpu/ivybridge/sata.c | 225 ++++++++++ arch/x86/cpu/ivybridge/usb_ehci.c | 29 ++ arch/x86/cpu/ivybridge/usb_xhci.c | 32 ++ arch/x86/cpu/lapic.c | 62 +++ arch/x86/cpu/pci.c | 12 + arch/x86/cpu/turbo.c | 98 ++++ arch/x86/cpu/u-boot.lds | 18 +- arch/x86/dts/link.dts | 41 +- arch/x86/include/asm/acpi.h | 24 + arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 21 + arch/x86/include/asm/arch-ivybridge/model_206ax.h | 4 + arch/x86/include/asm/arch-ivybridge/pch.h | 120 +++++ arch/x86/include/asm/arch-ivybridge/sandybridge.h | 13 +- arch/x86/include/asm/interrupt.h | 11 + arch/x86/include/asm/ioapic.h | 38 ++ arch/x86/include/asm/lapic.h | 125 +++++- arch/x86/include/asm/msr-index.h | 2 + arch/x86/include/asm/msr.h | 11 - arch/x86/include/asm/pci.h | 3 + arch/x86/include/asm/post.h | 1 + arch/x86/include/asm/speedstep.h | 89 ++++ arch/x86/include/asm/turbo.h | 31 ++ arch/x86/lib/pcat_interrupts.c | 38 ++ arch/x86/lib/relocate.c | 3 + board/google/chromebook_link/link.c | 5 - common/board_r.c | 3 - doc/device-tree-bindings/ata/intel-sata.txt | 26 ++ doc/device-tree-bindings/misc/intel-lpc.txt | 47 +- drivers/pci/pci.c | 24 +- drivers/rtc/mc146818.c | 43 +- include/common.h | 15 + include/configs/chromebook_link.h | 11 +- include/fdtdec.h | 2 + include/pci.h | 23 + include/pci_ids.h | 187 +++++++- include/rtc.h | 5 + lib/fdtdec.c | 2 + scripts/Makefile.lib | 2 + 48 files changed, 2915 insertions(+), 79 deletions(-) create mode 100644 arch/x86/cpu/ivybridge/bd82x6x.c create mode 100644 arch/x86/cpu/ivybridge/model_206ax.c create mode 100644 arch/x86/cpu/ivybridge/northbridge.c create mode 100644 arch/x86/cpu/ivybridge/pch.c create mode 100644 arch/x86/cpu/ivybridge/sata.c create mode 100644 arch/x86/cpu/ivybridge/usb_ehci.c create mode 100644 arch/x86/cpu/ivybridge/usb_xhci.c create mode 100644 arch/x86/cpu/lapic.c create mode 100644 arch/x86/cpu/turbo.c create mode 100644 arch/x86/include/asm/acpi.h create mode 100644 arch/x86/include/asm/arch-ivybridge/bd82x6x.h create mode 100644 arch/x86/include/asm/ioapic.h create mode 100644 arch/x86/include/asm/speedstep.h create mode 100644 arch/x86/include/asm/turbo.h create mode 100644 doc/device-tree-bindings/ata/intel-sata.txt

Device trees must be aligned to a 4-byte boundary. This was dropped in the Kbuild conversion. Bring it back, and use 16-byte alignment for good measure.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
scripts/Makefile.lib | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9d1383a..13af604 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -260,11 +260,13 @@ quiet_cmd_dt_S_dtb= DTB $@ cmd_dt_S_dtb= \ ( \ echo '.section .dtb.init.rodata,"a"'; \ + echo '.balign 16'; \ echo '.global __dtb_$(*F)_begin'; \ echo '__dtb_$(*F)_begin:'; \ echo '.incbin "$<" '; \ echo '__dtb_$(*F)_end:'; \ echo '.global __dtb_$(*F)_end'; \ + echo '.balign 16'; \ ) > $@
$(obj)/%.dtb.S: $(obj)/%.dtb

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Device trees must be aligned to a 4-byte boundary. This was dropped in the Kbuild conversion. Bring it back, and use 16-byte alignment for good measure.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
scripts/Makefile.lib | 2 ++ 1 file changed, 2 insertions(+)
Applied to u-boot-x86.

We have an ALIGN() macro - add a comment as to what this does. Also add a new ALIGN_DOWN() macro, which aligns a value to the next smallest multiple.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/common.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/include/common.h b/include/common.h index ecf7fca..28fba79 100644 --- a/include/common.h +++ b/include/common.h @@ -970,9 +970,24 @@ static inline phys_addr_t map_to_sysmem(const void *ptr) } \ )
+/** + * ALIGN() - return an aligned value not less than the given value + * + * @x: Value to align + * @a: Alignment to use, e.g. 4 to align to multiples of 4 + */ #define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) + #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+/** + * ALIGN_DOWN() - return an aligned value not greater than the given value + * + * @x: Value to align + * @a: Alignment to use, e.g. 4 to align to multiples of 4 + */ +#define ALIGN_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1UL)) + /* * ARCH_DMA_MINALIGN is defined in asm/cache.h for each architecture. It * is used to align DMA buffers.

Hi,
On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
We have an ALIGN() macro - add a comment as to what this does. Also add a new ALIGN_DOWN() macro, which aligns a value to the next smallest multiple.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/common.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/include/common.h b/include/common.h index ecf7fca..28fba79 100644 --- a/include/common.h +++ b/include/common.h @@ -970,9 +970,24 @@ static inline phys_addr_t map_to_sysmem(const void *ptr) } \ )
+/**
- ALIGN() - return an aligned value not less than the given value
- @x: Value to align
- @a: Alignment to use, e.g. 4 to align to multiples of 4
- */
#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+/**
- ALIGN_DOWN() - return an aligned value not greater than the given value
- @x: Value to align
- @a: Alignment to use, e.g. 4 to align to multiples of 4
- */
+#define ALIGN_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1UL))
/*
- ARCH_DMA_MINALIGN is defined in asm/cache.h for each architecture. It
- is used to align DMA buffers.
I'm going to drop this patch, since Masahiro's clean-up has been applied.
Regards, Simon

This was taken from Linux 3.18 with some additional IDs from Chrome OS Coreboot commit 688ef385.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/pci_ids.h | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 6 deletions(-)
diff --git a/include/pci_ids.h b/include/pci_ids.h index f84c13a..ee98bee 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -526,7 +526,19 @@ #define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 -#define PCI_DEVICE_ID_AMD_15H_NB_MISC 0x1603 +#define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403 +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d +#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e +#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 +#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 +#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 +#define PCI_DEVICE_ID_AMD_15H_NB_F3 0x1603 +#define PCI_DEVICE_ID_AMD_15H_NB_F4 0x1604 +#define PCI_DEVICE_ID_AMD_15H_NB_F5 0x1605 +#define PCI_DEVICE_ID_AMD_16H_NB_F3 0x1533 +#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534 +#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F3 0x1583 +#define PCI_DEVICE_ID_AMD_16H_M30H_NB_F4 0x1584 #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 @@ -569,8 +581,9 @@ #define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A #define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 #define PCI_DEVICE_ID_AMD_LX_AES 0x2082 -#define PCI_DEVICE_ID_AMD_HUDSON2_IDE 0x780c #define PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE 0x7800 +#define PCI_DEVICE_ID_AMD_HUDSON2_SMBUS 0x780b +#define PCI_DEVICE_ID_AMD_HUDSON2_IDE 0x780c
#define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 @@ -616,6 +629,8 @@ #define PCI_DEVICE_ID_MATROX_G550 0x2527 #define PCI_DEVICE_ID_MATROX_VIA 0x4536
+#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS 0x14f2 + #define PCI_VENDOR_ID_CT 0x102c #define PCI_DEVICE_ID_CT_69000 0x00c0 #define PCI_DEVICE_ID_CT_65545 0x00d8 @@ -724,6 +739,7 @@ #define PCI_DEVICE_ID_SI_7018 0x7018
#define PCI_VENDOR_ID_HP 0x103c +#define PCI_VENDOR_ID_HP_3PAR 0x1590 #define PCI_DEVICE_ID_HP_VISUALIZE_EG 0x1005 #define PCI_DEVICE_ID_HP_VISUALIZE_FX6 0x1006 #define PCI_DEVICE_ID_HP_VISUALIZE_FX4 0x1008 @@ -755,6 +771,8 @@ #define PCI_DEVICE_ID_HP_CISSD 0x3238 #define PCI_DEVICE_ID_HP_CISSE 0x323a #define PCI_DEVICE_ID_HP_CISSF 0x323b +#define PCI_DEVICE_ID_HP_CISSH 0x323c +#define PCI_DEVICE_ID_HP_CISSI 0x3239 #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
#define PCI_VENDOR_ID_PCTECH 0x1042 @@ -779,6 +797,29 @@ #define PCI_DEVICE_ID_ELSA_QS3000 0x3000
#define PCI_VENDOR_ID_STMICRO 0x104A +#define PCI_DEVICE_ID_STMICRO_USB_HOST 0xCC00 +#define PCI_DEVICE_ID_STMICRO_USB_OHCI 0xCC01 +#define PCI_DEVICE_ID_STMICRO_USB_OTG 0xCC02 +#define PCI_DEVICE_ID_STMICRO_UART_HWFC 0xCC03 +#define PCI_DEVICE_ID_STMICRO_UART_NO_HWFC 0xCC04 +#define PCI_DEVICE_ID_STMICRO_SOC_DMA 0xCC05 +#define PCI_DEVICE_ID_STMICRO_SATA 0xCC06 +#define PCI_DEVICE_ID_STMICRO_I2C 0xCC07 +#define PCI_DEVICE_ID_STMICRO_SPI_HS 0xCC08 +#define PCI_DEVICE_ID_STMICRO_MAC 0xCC09 +#define PCI_DEVICE_ID_STMICRO_SDIO_EMMC 0xCC0A +#define PCI_DEVICE_ID_STMICRO_SDIO 0xCC0B +#define PCI_DEVICE_ID_STMICRO_GPIO 0xCC0C +#define PCI_DEVICE_ID_STMICRO_VIP 0xCC0D +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA 0xCC0E +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_SRCS 0xCC0F +#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS 0xCC10 +#define PCI_DEVICE_ID_STMICRO_CAN 0xCC11 +#define PCI_DEVICE_ID_STMICRO_MLB 0xCC12 +#define PCI_DEVICE_ID_STMICRO_DBP 0xCC13 +#define PCI_DEVICE_ID_STMICRO_SATA_PHY 0xCC14 +#define PCI_DEVICE_ID_STMICRO_ESRAM 0xCC15 +#define PCI_DEVICE_ID_STMICRO_VIC 0xCC16
#define PCI_VENDOR_ID_BUSLOGIC 0x104B #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 @@ -1294,6 +1335,8 @@ #define PCI_VENDOR_ID_TUNDRA 0x10e3 #define PCI_DEVICE_ID_TUNDRA_CA91C042 0x0000
+#define PCI_VENDOR_ID_AMCC 0x10e8 + #define PCI_VENDOR_ID_INTERG 0x10ea #define PCI_DEVICE_ID_INTERG_1682 0x1682 #define PCI_DEVICE_ID_INTERG_2000 0x2000 @@ -1322,6 +1365,7 @@ #define PCI_SUBDEVICE_ID_CREATIVE_SB08801 0x0041 #define PCI_SUBDEVICE_ID_CREATIVE_SB08802 0x0042 #define PCI_SUBDEVICE_ID_CREATIVE_SB08803 0x0043 +#define PCI_SUBDEVICE_ID_CREATIVE_SB1270 0x0062 #define PCI_SUBDEVICE_ID_CREATIVE_HENDRIX 0x6000
#define PCI_VENDOR_ID_ECTIVA 0x1102 /* duplicate: CREATIVE */ @@ -1411,6 +1455,7 @@ #define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581 #define PCI_DEVICE_ID_VIA_VX800 0x8353 #define PCI_DEVICE_ID_VIA_VX855 0x8409 +#define PCI_DEVICE_ID_VIA_VX900 0x8410 #define PCI_DEVICE_ID_VIA_8371_1 0x8391 #define PCI_DEVICE_ID_VIA_82C598_1 0x8598 #define PCI_DEVICE_ID_VIA_838X_1 0xB188 @@ -1551,6 +1596,8 @@ #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 #define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5CE822 0xe822 +#define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 #define PCI_DEVICE_ID_RICOH_R5C832 0x0832 #define PCI_DEVICE_ID_RICOH_R5C843 0x0843
@@ -1586,6 +1633,7 @@ #define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334
#define PCI_VENDOR_ID_MARVELL 0x11ab +#define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b #define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 @@ -1798,6 +1846,8 @@ #define PCI_VENDOR_ID_ESDGMBH 0x12fe #define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
+#define PCI_VENDOR_ID_CB 0x1307 /* Measurement Computing */ + #define PCI_VENDOR_ID_SIIG 0x131f #define PCI_SUBVENDOR_ID_SIIG 0x131f #define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000 @@ -1860,8 +1910,23 @@ #define PCI_VENDOR_ID_QUATECH 0x135C #define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 #define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 +#define PCI_DEVICE_ID_QUATECH_DSC200 0x0030 +#define PCI_DEVICE_ID_QUATECH_QSC200 0x0040 #define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050 #define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060 +#define PCI_DEVICE_ID_QUATECH_QSCP100 0x0120 +#define PCI_DEVICE_ID_QUATECH_DSCP100 0x0130 +#define PCI_DEVICE_ID_QUATECH_QSCP200 0x0140 +#define PCI_DEVICE_ID_QUATECH_DSCP200 0x0150 +#define PCI_DEVICE_ID_QUATECH_QSCLP100 0x0170 +#define PCI_DEVICE_ID_QUATECH_DSCLP100 0x0180 +#define PCI_DEVICE_ID_QUATECH_DSC100E 0x0181 +#define PCI_DEVICE_ID_QUATECH_SSCLP100 0x0190 +#define PCI_DEVICE_ID_QUATECH_QSCLP200 0x01A0 +#define PCI_DEVICE_ID_QUATECH_DSCLP200 0x01B0 +#define PCI_DEVICE_ID_QUATECH_DSC200E 0x01B1 +#define PCI_DEVICE_ID_QUATECH_SSCLP200 0x01C0 +#define PCI_DEVICE_ID_QUATECH_ESCLP100 0x01E0 #define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
#define PCI_VENDOR_ID_SEALEVEL 0x135e @@ -1978,6 +2043,9 @@ #define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 #define PCI_DEVICE_ID_EXAR_XR17C154 0x0154 #define PCI_DEVICE_ID_EXAR_XR17C158 0x0158 +#define PCI_DEVICE_ID_EXAR_XR17V352 0x0352 +#define PCI_DEVICE_ID_EXAR_XR17V354 0x0354 +#define PCI_DEVICE_ID_EXAR_XR17V358 0x0358
#define PCI_VENDOR_ID_MICROGATE 0x13c0 #define PCI_DEVICE_ID_MICROGATE_USC 0x0010 @@ -2002,6 +2070,10 @@ #define PCI_DEVICE_ID_CMEDIA_CM8738 0x0111 #define PCI_DEVICE_ID_CMEDIA_CM8738B 0x0112
+#define PCI_VENDOR_ID_ADVANTECH 0x13fe + +#define PCI_VENDOR_ID_MEILHAUS 0x1402 + #define PCI_VENDOR_ID_LAVA 0x1407 #define PCI_DEVICE_ID_LAVA_DSERIAL 0x0100 /* 2x 16550 */ #define PCI_DEVICE_ID_LAVA_QUATRO_A 0x0101 /* 2x 16550, half of 4 port */ @@ -2047,6 +2119,8 @@
#define PCI_VENDOR_ID_CHELSIO 0x1425
+#define PCI_VENDOR_ID_ADLINK 0x144a + #define PCI_VENDOR_ID_SAMSUNG 0x144d
#define PCI_VENDOR_ID_GIGABYTE 0x1458 @@ -2080,6 +2154,8 @@ #define PCI_DEVICE_ID_AFAVLAB_P030 0x2182 #define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150
+#define PCI_VENDOR_ID_AMPLICON 0x14dc + #define PCI_VENDOR_ID_BCM_GVC 0x14a4 #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 @@ -2100,19 +2176,25 @@ #define PCI_DEVICE_ID_NX2_57711E 0x1650 #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 +#define PCI_DEVICE_ID_TIGON3_5719 0x1657 #define PCI_DEVICE_ID_TIGON3_5721 0x1659 #define PCI_DEVICE_ID_TIGON3_5722 0x165a #define PCI_DEVICE_ID_TIGON3_5723 0x165b #define PCI_DEVICE_ID_TIGON3_5705M 0x165d #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e +#define PCI_DEVICE_ID_NX2_57712 0x1662 +#define PCI_DEVICE_ID_NX2_57712E 0x1663 +#define PCI_DEVICE_ID_NX2_57712_MF 0x1663 #define PCI_DEVICE_ID_TIGON3_5714 0x1668 #define PCI_DEVICE_ID_TIGON3_5714S 0x1669 #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e +#define PCI_DEVICE_ID_NX2_57712_VF 0x166f #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 #define PCI_DEVICE_ID_TIGON3_5755M 0x1673 #define PCI_DEVICE_ID_TIGON3_5756 0x1674 +#define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 @@ -2124,6 +2206,9 @@ #define PCI_DEVICE_ID_TIGON3_5761E 0x1680 #define PCI_DEVICE_ID_TIGON3_5761 0x1681 #define PCI_DEVICE_ID_TIGON3_5764 0x1684 +#define PCI_DEVICE_ID_NX2_57800 0x168a +#define PCI_DEVICE_ID_NX2_57840 0x168d +#define PCI_DEVICE_ID_NX2_57810 0x168e #define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 #define PCI_DEVICE_ID_TIGON3_5784 0x1698 @@ -2131,11 +2216,19 @@ #define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c #define PCI_DEVICE_ID_TIGON3_5789 0x169d +#define PCI_DEVICE_ID_NX2_57840_4_10 0x16a1 +#define PCI_DEVICE_ID_NX2_57840_2_20 0x16a2 +#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 +#define PCI_DEVICE_ID_NX2_57800_MF 0x16a5 #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 +#define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 #define PCI_DEVICE_ID_NX2_5706S 0x16aa #define PCI_DEVICE_ID_NX2_5708S 0x16ac +#define PCI_DEVICE_ID_NX2_57840_VF 0x16ad +#define PCI_DEVICE_ID_NX2_57810_MF 0x16ae +#define PCI_DEVICE_ID_NX2_57810_VF 0x16af #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd @@ -2307,6 +2400,8 @@
#define PCI_VENDOR_ID_TOPSPIN 0x1867
+#define PCI_VENDOR_ID_COMMTECH 0x18f7 + #define PCI_VENDOR_ID_SILAN 0x1904
#define PCI_VENDOR_ID_RENESAS 0x1912 @@ -2316,6 +2411,11 @@ #define PCI_DEVICE_ID_RENESAS_SH7785 0x0007 #define PCI_DEVICE_ID_RENESAS_SH7786 0x0010
+#define PCI_VENDOR_ID_SOLARFLARE 0x1924 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0 0x0703 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1 0x6703 +#define PCI_DEVICE_ID_SOLARFLARE_SFC4000B 0x0710 + #define PCI_VENDOR_ID_TDI 0x192E #define PCI_DEVICE_ID_TDI_EHCI 0x0101
@@ -2414,6 +2514,11 @@
#define PCI_VENDOR_ID_AZWAVE 0x1a3b
+#define PCI_VENDOR_ID_ASMEDIA 0x1b21 + +#define PCI_VENDOR_ID_CIRCUITCO 0x1cc8 +#define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001 + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
@@ -2463,6 +2568,9 @@
#define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_EESSC 0x0008 +#define PCI_DEVICE_ID_INTEL_SNB_IMC 0x0100 +#define PCI_DEVICE_ID_INTEL_IVB_IMC 0x0154 +#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00 #define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 #define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 #define PCI_DEVICE_ID_INTEL_PXH_0 0x0329 @@ -2485,6 +2593,7 @@ #define PCI_DEVICE_ID_INTEL_MRST_SD2 0x084F #define PCI_DEVICE_ID_INTEL_I960 0x0960 #define PCI_DEVICE_ID_INTEL_I960RM 0x0962 +#define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60 #define PCI_DEVICE_ID_INTEL_82541ER 0x1078 #define PCI_DEVICE_ID_INTEL_82541GI_LF 0x107c #define PCI_DEVICE_ID_INTEL_82542 0x1000 @@ -2564,13 +2673,50 @@ #define PCI_DEVICE_ID_INTEL_COUGARPOINT_HDA 0x1c20 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Z68 0x1c44 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_P67 0x1c46 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_UM67 0x1c47 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_HM65 0x1c49 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_H67 0x1c4a +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_HM67 0x1c4b +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Q65 0x1c4c +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_QS67 0x1c4d +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_Q67 0x1c4e +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_QM67 0x1c4f +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_B65 0x1c50 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C202 0x1c52 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C204 0x1c54 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_C206 0x1c56 +#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_H61 0x1c5c #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE 0x1e03 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA 0x1e20 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e41 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC 0x1d40 +#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 +#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE 0x1e03 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_HDA 0x1e20 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI 0x1e31 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN 0x1e41 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_B75 0x1e49 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_C216 0x1e53 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_H77 0x1e4A +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM70 0x1e5e +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM75 0x1e5d +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM76 0x1e59 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_HM77 0x1e57 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MBL_SAMPLE 0x1e42 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_NM70 0x1e5f +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Q75 0x1e48 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Q77 0x1e47 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_QM77 0x1e55 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_QS77 0x1e56 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_SFF_SAMPLE 0x1e43 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_UM77 0x1e58 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Z75 0x1e46 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_Z77 0x1e44 +#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX 0x1e5f +#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 +#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 @@ -2783,8 +2929,30 @@ #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN 0x3b00 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX 0x3b1f #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB3 0x3c23 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB4 0x3c24 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB5 0x3c25 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB6 0x3c26 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27 +#define PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e +#define PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f +#define PCI_DEVICE_ID_INTEL_UNC_HA 0x3c46 +#define PCI_DEVICE_ID_INTEL_UNC_IMC0 0x3cb0 +#define PCI_DEVICE_ID_INTEL_UNC_IMC1 0x3cb1 +#define PCI_DEVICE_ID_INTEL_UNC_IMC2 0x3cb4 +#define PCI_DEVICE_ID_INTEL_UNC_IMC3 0x3cb5 +#define PCI_DEVICE_ID_INTEL_UNC_QPI0 0x3c41 +#define PCI_DEVICE_ID_INTEL_UNC_QPI1 0x3c42 +#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44 +#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45 +#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX 0x3ce0 #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f #define PCI_DEVICE_ID_INTEL_5100_16 0x65f0 +#define PCI_DEVICE_ID_INTEL_5100_19 0x65f3 #define PCI_DEVICE_ID_INTEL_5100_21 0x65f5 #define PCI_DEVICE_ID_INTEL_5100_22 0x65f6 #define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 @@ -2823,6 +2991,7 @@ #define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601 #define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119 #define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a +#define PCI_DEVICE_ID_INTEL_ITC_LPC 0x8186 #define PCI_DEVICE_ID_INTEL_82454GX 0x84c4 #define PCI_DEVICE_ID_INTEL_82450GX 0x84c5 #define PCI_DEVICE_ID_INTEL_82451NX 0x84ca @@ -2905,7 +3074,11 @@ #define PCI_DEVICE_ID_NETMOS_9845 0x9845 #define PCI_DEVICE_ID_NETMOS_9855 0x9855 #define PCI_DEVICE_ID_NETMOS_9865 0x9865 +#define PCI_DEVICE_ID_NETMOS_9900 0x9900 #define PCI_DEVICE_ID_NETMOS_9901 0x9901 +#define PCI_DEVICE_ID_NETMOS_9904 0x9904 +#define PCI_DEVICE_ID_NETMOS_9912 0x9912 +#define PCI_DEVICE_ID_NETMOS_9922 0x9922
#define PCI_VENDOR_ID_3COM_2 0xa727
@@ -2927,3 +3100,5 @@
#define PCI_VENDOR_ID_XEN 0x5853 #define PCI_DEVICE_ID_XEN_PLATFORM 0x0001 + +#define PCI_VENDOR_ID_OCZ 0x1b85

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
This was taken from Linux 3.18 with some additional IDs from Chrome OS Coreboot commit 688ef385.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/pci_ids.h | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 6 deletions(-)
Applied to u-boot-x86.

This function is not needed. Remove it to improve the generic init sequence slightly.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
arch/x86/cpu/coreboot/coreboot.c | 11 ----------- board/google/chromebook_link/link.c | 5 ----- common/board_r.c | 3 --- include/configs/chromebook_link.h | 1 - 4 files changed, 20 deletions(-)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 2df7288..cfacc05 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -39,17 +39,6 @@ int board_early_init_f(void) return 0; }
-int board_early_init_r(void) -{ - /* CPU Speed to 100MHz */ - gd->cpu_clk = 100000000; - - /* Crystal is 33.000MHz */ - gd->bus_clk = 33000000; - - return 0; -} - int print_cpuinfo(void) { return default_print_cpuinfo(); diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c index 88cee05..0a1ae61 100644 --- a/board/google/chromebook_link/link.c +++ b/board/google/chromebook_link/link.c @@ -12,11 +12,6 @@ int arch_early_init_r(void) return 0; }
-int board_early_init_r(void) -{ - return 0; -} - static const struct pch_gpio_set1 pch_gpio_set1_mode = { .gpio0 = GPIO_MODE_GPIO, /* NMI_DBG# */ .gpio3 = GPIO_MODE_GPIO, /* ALS_INT# */ diff --git a/common/board_r.c b/common/board_r.c index 7c33900..8625a90 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -837,9 +837,6 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_CMD_KGDB initr_kgdb, #endif -#ifdef CONFIG_X86 - board_early_init_r, -#endif interrupt_init, #if defined(CONFIG_ARM) || defined(CONFIG_x86) initr_enable_interrupts, diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 8caeca6..cd4a8a0 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -21,7 +21,6 @@ #define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_SYS_X86_START16 0xfffff800 #define CONFIG_BOARD_EARLY_INIT_F -#define CONFIG_BOARD_EARLY_INIT_R #define CONFIG_DISPLAY_CPUINFO
#define CONFIG_X86_RESET_VECTOR

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
This function is not needed. Remove it to improve the generic init sequence slightly.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/coreboot/coreboot.c | 11 ----------- board/google/chromebook_link/link.c | 5 ----- common/board_r.c | 3 --- include/configs/chromebook_link.h | 1 - 4 files changed, 20 deletions(-)
Applied to u-boot-x86.

This normally indicates a problem which will prevent relocation from functioning, resulting in a hang. Panic in this case to make it easier to debug.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: - Change 'not' to 'no' since it reads better
arch/x86/lib/relocate.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index faca38f..b33586b 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -76,6 +76,9 @@ int do_elf_reloc_fixups(void) /* The size of the region of u-boot that runs out of RAM. */ uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
+ if (re_src == re_end) + panic("No relocation data"); + do { /* Get the location from the relocation entry */ offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
This normally indicates a problem which will prevent relocation from functioning, resulting in a hang. Panic in this case to make it easier to debug.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- Change 'not' to 'no' since it reads better
arch/x86/lib/relocate.c | 3 +++ 1 file changed, 3 insertions(+)
Applied to u-boot-x86.

Some toolchains put the relocation data into separate sections. Adjust the linker script to catch this case. Without relocation data, U-Boot will not boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Use .rel* instead of .rel.* to catch more cases
arch/x86/cpu/u-boot.lds | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index f48bff5..124a361 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -44,7 +44,9 @@ SECTIONS
. = ALIGN(4); __rel_dyn_start = .; - .rel.dyn : { *(.rel.dyn) } + .rel.dyn : { + *(.rel*) + } __rel_dyn_end = .; . = ALIGN(4); _end = .;

On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Some toolchains put the relocation data into separate sections. Adjust the linker script to catch this case. Without relocation data, U-Boot will not boot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Use .rel* instead of .rel.* to catch more cases
arch/x86/cpu/u-boot.lds | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index f48bff5..124a361 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -44,7 +44,9 @@ SECTIONS
. = ALIGN(4); __rel_dyn_start = .;
.rel.dyn : { *(.rel.dyn) }
.rel.dyn : {
*(.rel*)
} __rel_dyn_end = .; . = ALIGN(4); _end = .;
--
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 14 November 2014 at 20:29, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Some toolchains put the relocation data into separate sections. Adjust the linker script to catch this case. Without relocation data, U-Boot will not boot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Use .rel* instead of .rel.* to catch more cases
Applied to u-boot-x86.

Define the reset base in config.mk so that it does not need to be calculated twice in the link script. Also tidy up the START_16 and RESET_VEC_LOC values to fit with this new approach.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Drop WIP commit for u-boot.srec as it is not needed now - Fix 'AT' value in link script
arch/x86/cpu/config.mk | 5 +++-- arch/x86/cpu/u-boot.lds | 14 +++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk index f7b01d3..84aeaf3 100644 --- a/arch/x86/cpu/config.mk +++ b/arch/x86/cpu/config.mk @@ -12,5 +12,6 @@ PLATFORM_CPPFLAGS += -D__I386__ -Werror # DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! LDPPFLAGS += -DRESET_SEG_START=0xffff0000 LDPPFLAGS += -DRESET_SEG_SIZE=0x10000 -LDPPFLAGS += -DRESET_VEC_LOC=0xfff0 -LDPPFLAGS += -DSTART_16=0xf800 +LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0 +LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16) +LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)" diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 124a361..b0d8531 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -66,15 +66,19 @@ SECTIONS /DISCARD/ : { *(.gnu*) }
#ifdef CONFIG_X86_RESET_VECTOR - /* * The following expressions place the 16-bit Real-Mode code and * Reset Vector at the end of the Flash ROM */ - . = START_16; - .start16 : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + START_16)) { KEEP(*(.start16)); } + . = START_16 - RESET_SEG_START; + .start16 : AT (START_16) { + KEEP(*(.start16)); + }
- . = RESET_VEC_LOC; - .resetvec : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + RESET_VEC_LOC)) { KEEP(*(.resetvec)); } + . = RESET_VEC_LOC - RESET_SEG_START; + .resetvec : AT (RESET_VEC_LOC) { + KEEP(*(.resetvec)); + } #endif + }

On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Define the reset base in config.mk so that it does not need to be calculated twice in the link script. Also tidy up the START_16 and RESET_VEC_LOC values to fit with this new approach.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop WIP commit for u-boot.srec as it is not needed now
- Fix 'AT' value in link script
arch/x86/cpu/config.mk | 5 +++-- arch/x86/cpu/u-boot.lds | 14 +++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk index f7b01d3..84aeaf3 100644 --- a/arch/x86/cpu/config.mk +++ b/arch/x86/cpu/config.mk @@ -12,5 +12,6 @@ PLATFORM_CPPFLAGS += -D__I386__ -Werror # DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! LDPPFLAGS += -DRESET_SEG_START=0xffff0000 LDPPFLAGS += -DRESET_SEG_SIZE=0x10000 -LDPPFLAGS += -DRESET_VEC_LOC=0xfff0 -LDPPFLAGS += -DSTART_16=0xf800 +LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0 +LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16) +LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)" diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 124a361..b0d8531 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -66,15 +66,19 @@ SECTIONS /DISCARD/ : { *(.gnu*) }
#ifdef CONFIG_X86_RESET_VECTOR
/* * The following expressions place the 16-bit Real-Mode code and * Reset Vector at the end of the Flash ROM */
. = START_16;
.start16 : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + START_16)) { KEEP(*(.start16)); }
. = START_16 - RESET_SEG_START;
.start16 : AT (START_16) {
KEEP(*(.start16));
}
. = RESET_VEC_LOC;
.resetvec : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + RESET_VEC_LOC)) { KEEP(*(.resetvec)); }
. = RESET_VEC_LOC - RESET_SEG_START;
.resetvec : AT (RESET_VEC_LOC) {
KEEP(*(.resetvec));
}
#endif
}
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 14 November 2014 at 20:34, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Define the reset base in config.mk so that it does not need to be calculated twice in the link script. Also tidy up the START_16 and RESET_VEC_LOC values to fit with this new approach.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop WIP commit for u-boot.srec as it is not needed now
- Fix 'AT' value in link script
arch/x86/cpu/config.mk | 5 +++-- arch/x86/cpu/u-boot.lds | 14 +++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-)
Applied to u-boot-x86.

Provide a function to set up the RTC ready for use.
Signed-off-by: Simon Glass sjg@chromium.org
---
Changes in v2: - Drop the part of the commit message that talks about using build date - Move CLEAR_CMOS up to the top, indicated to be manually changed - Remove the parameter from rtc_init() and simplify the code
drivers/rtc/mc146818.c | 43 +++++++++++++++++++++++++++++++++++++++---- include/rtc.h | 5 +++++ 2 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index f7cf106..39e6041 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -14,6 +14,7 @@ #include <common.h> #include <command.h> #include <rtc.h> +#include <version.h>
#if defined(__I386__) || defined(CONFIG_MALTA) #include <asm/io.h> @@ -23,6 +24,9 @@
#if defined(CONFIG_CMD_DATE)
+/* Set this to 1 to clear the CMOS RAM */ +#define CLEAR_CMOS 0 + static uchar rtc_read (uchar reg); static void rtc_write (uchar reg, uchar val);
@@ -41,7 +45,14 @@ static void rtc_write (uchar reg, uchar val); #define RTC_CONFIG_B 0x0B #define RTC_CONFIG_C 0x0C #define RTC_CONFIG_D 0x0D +#define RTC_REG_SIZE 0x80 + +#define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) +#define RTC_CONFIG_A_RATE_1024HZ 6
+#define RTC_CONFIG_B_24H (1 << 1) + +#define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80
/* ------------------------------------------------------------------------- */
@@ -128,25 +139,49 @@ void rtc_reset (void) */ static uchar rtc_read (uchar reg) { - return(in8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg)); + return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg); }
static void rtc_write (uchar reg, uchar val) { - out8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg, val); + out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val); } #else static uchar rtc_read (uchar reg) { out8(RTC_PORT_MC146818,reg); - return(in8(RTC_PORT_MC146818+1)); + return in8(RTC_PORT_MC146818 + 1); }
static void rtc_write (uchar reg, uchar val) { out8(RTC_PORT_MC146818,reg); - out8(RTC_PORT_MC146818+1,val); + out8(RTC_PORT_MC146818+1, val); } #endif
+void rtc_init(void) +{ +#if CLEAR_CMOS + int i; + + rtc_write(RTC_SECONDS_ALARM, 0); + rtc_write(RTC_MINUTES_ALARM, 0); + rtc_write(RTC_HOURS_ALARM, 0); + for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++) + rtc_write(i, 0); + printf("RTC: zeroing CMOS RAM\n"); +#endif + + /* Setup the real time clock */ + rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H); + /* Setup the frequency it operates at */ + rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ | + RTC_CONFIG_A_RATE_1024HZ); + /* Ensure all reserved bits are 0 in register D */ + rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME); + + /* Clear any pending interrupts */ + rtc_read(RTC_CONFIG_C); +} #endif diff --git a/include/rtc.h b/include/rtc.h index c034966..d11aa8b 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -50,4 +50,9 @@ void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+/** + * rtc_init() - Set up the real time clock ready for use + */ +void rtc_init(void); + #endif /* _RTC_H_ */

On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Provide a function to set up the RTC ready for use.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop the part of the commit message that talks about using build date
- Move CLEAR_CMOS up to the top, indicated to be manually changed
- Remove the parameter from rtc_init() and simplify the code
drivers/rtc/mc146818.c | 43 +++++++++++++++++++++++++++++++++++++++---- include/rtc.h | 5 +++++ 2 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index f7cf106..39e6041 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -14,6 +14,7 @@ #include <common.h> #include <command.h> #include <rtc.h> +#include <version.h>
#if defined(__I386__) || defined(CONFIG_MALTA) #include <asm/io.h> @@ -23,6 +24,9 @@
#if defined(CONFIG_CMD_DATE)
+/* Set this to 1 to clear the CMOS RAM */ +#define CLEAR_CMOS 0
static uchar rtc_read (uchar reg); static void rtc_write (uchar reg, uchar val);
@@ -41,7 +45,14 @@ static void rtc_write (uchar reg, uchar val); #define RTC_CONFIG_B 0x0B #define RTC_CONFIG_C 0x0C #define RTC_CONFIG_D 0x0D +#define RTC_REG_SIZE 0x80
+#define RTC_CONFIG_A_REF_CLCK_32KHZ (1 << 5) +#define RTC_CONFIG_A_RATE_1024HZ 6
+#define RTC_CONFIG_B_24H (1 << 1)
+#define RTC_CONFIG_D_VALID_RAM_AND_TIME 0x80
/* ------------------------------------------------------------------------- */
@@ -128,25 +139,49 @@ void rtc_reset (void) */ static uchar rtc_read (uchar reg) {
return(in8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg));
return in8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg);
}
static void rtc_write (uchar reg, uchar val) {
out8(CONFIG_SYS_RTC_REG_BASE_ADDR+reg, val);
out8(CONFIG_SYS_RTC_REG_BASE_ADDR + reg, val);
} #else static uchar rtc_read (uchar reg) { out8(RTC_PORT_MC146818,reg);
return(in8(RTC_PORT_MC146818+1));
return in8(RTC_PORT_MC146818 + 1);
}
static void rtc_write (uchar reg, uchar val) { out8(RTC_PORT_MC146818,reg);
out8(RTC_PORT_MC146818+1,val);
out8(RTC_PORT_MC146818+1, val);
} #endif
+void rtc_init(void) +{ +#if CLEAR_CMOS
int i;
rtc_write(RTC_SECONDS_ALARM, 0);
rtc_write(RTC_MINUTES_ALARM, 0);
rtc_write(RTC_HOURS_ALARM, 0);
for (i = RTC_CONFIG_A; i < RTC_REG_SIZE; i++)
rtc_write(i, 0);
printf("RTC: zeroing CMOS RAM\n");
+#endif
/* Setup the real time clock */
rtc_write(RTC_CONFIG_B, RTC_CONFIG_B_24H);
/* Setup the frequency it operates at */
rtc_write(RTC_CONFIG_A, RTC_CONFIG_A_REF_CLCK_32KHZ |
RTC_CONFIG_A_RATE_1024HZ);
/* Ensure all reserved bits are 0 in register D */
rtc_write(RTC_CONFIG_D, RTC_CONFIG_D_VALID_RAM_AND_TIME);
/* Clear any pending interrupts */
rtc_read(RTC_CONFIG_C);
+} #endif diff --git a/include/rtc.h b/include/rtc.h index c034966..d11aa8b 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -50,4 +50,9 @@ void to_tm (int, struct rtc_time *); unsigned long mktime (unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int);
+/**
- rtc_init() - Set up the real time clock ready for use
- */
+void rtc_init(void);
#endif /* _RTC_H_ */
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 14 November 2014 at 20:37, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Provide a function to set up the RTC ready for use.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop the part of the commit message that talks about using build date
- Move CLEAR_CMOS up to the top, indicated to be manually changed
- Remove the parameter from rtc_init() and simplify the code
drivers/rtc/mc146818.c | 43 +++++++++++++++++++++++++++++++++++++++---- include/rtc.h | 5 +++++ 2 files changed, 44 insertions(+), 4 deletions(-)
Applied to u-boot-x86.

On 24 November 2014 at 19:47, Simon Glass sjg@chromium.org wrote:
On 14 November 2014 at 20:37, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Provide a function to set up the RTC ready for use.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop the part of the commit message that talks about using build date
- Move CLEAR_CMOS up to the top, indicated to be manually changed
- Remove the parameter from rtc_init() and simplify the code
drivers/rtc/mc146818.c | 43 +++++++++++++++++++++++++++++++++++++++---- include/rtc.h | 5 +++++ 2 files changed, 44 insertions(+), 4 deletions(-)
Applied to u-boot-x86.
But with a small fix that I missed earlier - I had to remove 'static' from the definition in drivers/rtc/bfin_rtc since it conflicts, unfortunately.

Add definitions for the I/O Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/ioapic.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 arch/x86/include/asm/ioapic.h
diff --git a/arch/x86/include/asm/ioapic.h b/arch/x86/include/asm/ioapic.h new file mode 100644 index 0000000..699160f --- /dev/null +++ b/arch/x86/include/asm/ioapic.h @@ -0,0 +1,38 @@ +/* + * From coreboot file of the same name + * + * Copyright (C) 2010 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __ASM_IOAPIC_H +#define __ASM_IOAPIC_H + +#define IO_APIC_ADDR 0xfec00000 +#define IO_APIC_INDEX IO_APIC_ADDR +#define IO_APIC_DATA (IO_APIC_ADDR + 0x10) +#define IO_APIC_INTERRUPTS 24 + +#define ALL (0xff << 24) +#define NONE 0 +#define DISABLED (1 << 16) +#define ENABLED (0 << 16) +#define TRIGGER_EDGE (0 << 15) +#define TRIGGER_LEVEL (1 << 15) +#define POLARITY_HIGH (0 << 13) +#define POLARITY_LOW (1 << 13) +#define PHYSICAL_DEST (0 << 11) +#define LOGICAL_DEST (1 << 11) +#define ExtINT (7 << 8) +#define NMI (4 << 8) +#define SMI (2 << 8) +#define INT (1 << 8) + +u32 io_apic_read(u32 ioapic_base, u32 reg); +void io_apic_write(u32 ioapic_base, u32 reg, u32 value); +void set_ioapic_id(u32 ioapic_base, u8 ioapic_id); +void setup_ioapic(u32 ioapic_base, u8 ioapic_id); +void clear_ioapic(u32 ioapic_base); + +#endif

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add definitions for the I/O Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/ioapic.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 arch/x86/include/asm/ioapic.h
Applied to u-boot-x86.

Some boards will want to do some setup before and after a PCI hose is scanned.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
arch/x86/cpu/pci.c | 12 ++++++++++++ arch/x86/include/asm/pci.h | 3 +++ 2 files changed, 15 insertions(+)
diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index e399388..f3492c3 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -33,6 +33,16 @@ int pci_early_init_hose(struct pci_controller **hosep) return 0; }
+__weak int board_pci_pre_scan(struct pci_controller *hose) +{ + return 0; +} + +__weak int board_pci_post_scan(struct pci_controller *hose) +{ + return 0; +} + void pci_init_board(void) { struct pci_controller *hose = &x86_hose; @@ -44,7 +54,9 @@ void pci_init_board(void) pci_setup_type1(hose); pci_register_hose(hose);
+ board_pci_pre_scan(hose); hose->last_busno = pci_hose_scan(hose); + board_pci_post_scan(hose); }
static struct pci_controller *get_hose(void) diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 98817aa..ac1a808 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -34,6 +34,9 @@ void board_pci_setup_hose(struct pci_controller *hose); */ int pci_early_init_hose(struct pci_controller **hosep);
+int board_pci_pre_scan(struct pci_controller *hose); +int board_pci_post_scan(struct pci_controller *hose); + /* * Simple PCI access routines - these work from either the early PCI hose * or the 'real' one, created after U-Boot has memory available

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Some boards will want to do some setup before and after a PCI hose is scanned.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
arch/x86/cpu/pci.c | 12 ++++++++++++ arch/x86/include/asm/pci.h | 3 +++ 2 files changed, 15 insertions(+)
Applied to u-boot-x86.

Enable this option so that we can configure the available PCI devices. Also make sure that PCI is available early after relocation as we use it for several other subsystems.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/chromebook_link.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index cd4a8a0..055b3ac 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -66,6 +66,9 @@ #define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS #define CONFIG_PCI_IO_SIZE 0xefff
+#define CONFIG_SYS_EARLY_PCI_INIT +#define CONFIG_PCI_PNP + #define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \ "stdout=vga,serial\0" \ "stderr=vga,serial\0"

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Enable this option so that we can configure the available PCI devices. Also make sure that PCI is available early after relocation as we use it for several other subsystems.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/configs/chromebook_link.h | 3 +++ 1 file changed, 3 insertions(+)
Applied to u-boot-x86.

Some PCI functions cannot be auto-configured. Add a function to set up a fixed BAR which can be used in these situations. Also add a function to read the current address of a BAR.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Rename functions to pci_read_bar32() and pci_write_bar32()
drivers/pci/pci.c | 24 +++++++++++++++++++++--- include/pci.h | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60c333e..332df61 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -363,9 +363,27 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, return phys_addr; }
-/* - * - */ +void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum, + u32 addr_and_ctrl) +{ + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl); +} + +u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum) +{ + u32 addr; + int bar; + + bar = PCI_BASE_ADDRESS_0 + barnum * 4; + pci_hose_read_config_dword(hose, dev, bar, &addr); + if (addr & PCI_BASE_ADDRESS_SPACE_IO) + return addr & PCI_BASE_ADDRESS_IO_MASK; + else + return addr & PCI_BASE_ADDRESS_MEM_MASK; +}
int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, diff --git a/include/pci.h b/include/pci.h index 2ff7365..ccda2c5 100644 --- a/include/pci.h +++ b/include/pci.h @@ -677,5 +677,28 @@ extern void pci_mpc824x_init (struct pci_controller *hose); extern void pci_mpc85xx_init (struct pci_controller *hose); #endif
+/** + * pci_write_bar32() - Write the address of a BAR including control bits + * + * This writes a raw address (with control bits) to a bar + * + * @hose: PCI hose to use + * @dev: PCI device to update + * @barnum: BAR number (0-5) + * @addr: BAR address with control bits + */ +void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum, + u32 addr_and_ctrl); + +/** + * pci_read_bar32() - read the address of a bar + * + * @hose: PCI hose to use + * @dev: PCI device to inspect + * @barnum: BAR number (0-5) + * @return address of the bar, masking out any control bits + * */ +u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum); + #endif /* __ASSEMBLY__ */ #endif /* _PCI_H */

On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Some PCI functions cannot be auto-configured. Add a function to set up a fixed BAR which can be used in these situations. Also add a function to read the current address of a BAR.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename functions to pci_read_bar32() and pci_write_bar32()
drivers/pci/pci.c | 24 +++++++++++++++++++++--- include/pci.h | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60c333e..332df61 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -363,9 +363,27 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, return phys_addr; }
-/*
- */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
u32 addr_and_ctrl)
+{
int bar;
bar = PCI_BASE_ADDRESS_0 + barnum * 4;
pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
+}
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum) +{
u32 addr;
int bar;
bar = PCI_BASE_ADDRESS_0 + barnum * 4;
pci_hose_read_config_dword(hose, dev, bar, &addr);
if (addr & PCI_BASE_ADDRESS_SPACE_IO)
return addr & PCI_BASE_ADDRESS_IO_MASK;
else
return addr & PCI_BASE_ADDRESS_MEM_MASK;
+}
int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, diff --git a/include/pci.h b/include/pci.h index 2ff7365..ccda2c5 100644 --- a/include/pci.h +++ b/include/pci.h @@ -677,5 +677,28 @@ extern void pci_mpc824x_init (struct pci_controller *hose); extern void pci_mpc85xx_init (struct pci_controller *hose); #endif
+/**
- pci_write_bar32() - Write the address of a BAR including control bits
- This writes a raw address (with control bits) to a bar
- @hose: PCI hose to use
- @dev: PCI device to update
- @barnum: BAR number (0-5)
- @addr: BAR address with control bits
- */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
u32 addr_and_ctrl);
+/**
- pci_read_bar32() - read the address of a bar
- @hose: PCI hose to use
- @dev: PCI device to inspect
- @barnum: BAR number (0-5)
- @return address of the bar, masking out any control bits
- */
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
#endif /* __ASSEMBLY__ */
#endif /* _PCI_H */
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 14 November 2014 at 20:39, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Some PCI functions cannot be auto-configured. Add a function to set up a fixed BAR which can be used in these situations. Also add a function to read the current address of a BAR.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Rename functions to pci_read_bar32() and pci_write_bar32()
drivers/pci/pci.c | 24 +++++++++++++++++++++--- include/pci.h | 23 +++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60c333e..332df61 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -363,9 +363,27 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose, return phys_addr; }
-/*
- */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
u32 addr_and_ctrl)
+{
int bar;
bar = PCI_BASE_ADDRESS_0 + barnum * 4;
pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
+}
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum) +{
u32 addr;
int bar;
bar = PCI_BASE_ADDRESS_0 + barnum * 4;
pci_hose_read_config_dword(hose, dev, bar, &addr);
if (addr & PCI_BASE_ADDRESS_SPACE_IO)
return addr & PCI_BASE_ADDRESS_IO_MASK;
else
return addr & PCI_BASE_ADDRESS_MEM_MASK;
+}
int pci_hose_config_device(struct pci_controller *hose, pci_dev_t dev, diff --git a/include/pci.h b/include/pci.h index 2ff7365..ccda2c5 100644 --- a/include/pci.h +++ b/include/pci.h @@ -677,5 +677,28 @@ extern void pci_mpc824x_init (struct pci_controller *hose); extern void pci_mpc85xx_init (struct pci_controller *hose); #endif
+/**
- pci_write_bar32() - Write the address of a BAR including control bits
- This writes a raw address (with control bits) to a bar
- @hose: PCI hose to use
- @dev: PCI device to update
- @barnum: BAR number (0-5)
- @addr: BAR address with control bits
- */
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
u32 addr_and_ctrl);
+/**
- pci_read_bar32() - read the address of a bar
- @hose: PCI hose to use
- @dev: PCI device to inspect
- @barnum: BAR number (0-5)
- @return address of the bar, masking out any control bits
- */
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
#endif /* __ASSEMBLY__ */
#endif /* _PCI_H */
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Applied to u-boot-x86.

Add this additional init in case it is needed by the OS.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Remove i8259 patch and just update the existing interrupt code
arch/x86/include/asm/interrupt.h | 11 +++++++++++ arch/x86/lib/pcat_interrupts.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/arch/x86/include/asm/interrupt.h b/arch/x86/include/asm/interrupt.h index 3f46e09..25abde7 100644 --- a/arch/x86/include/asm/interrupt.h +++ b/arch/x86/include/asm/interrupt.h @@ -27,4 +27,15 @@ void specific_eoi(int irq);
extern char exception_stack[];
+/** + * configure_irq_trigger() - Configure IRQ triggering + * + * Switch the given interrupt to be level / edge triggered + * + * @param int_num legacy interrupt number (3-7, 9-15) + * @param is_level_triggered true for level triggered interrupt, false for + * edge triggered interrupt + */ +void configure_irq_trigger(int int_num, bool is_level_triggered); + #endif diff --git a/arch/x86/lib/pcat_interrupts.c b/arch/x86/lib/pcat_interrupts.c index 4c86f7f..2dc2fbd 100644 --- a/arch/x86/lib/pcat_interrupts.c +++ b/arch/x86/lib/pcat_interrupts.c @@ -62,6 +62,9 @@ int interrupt_init(void) */ unmask_irq(2);
+ /* Interrupt 9 should be level triggered (SCI). The OS might do this */ + configure_irq_trigger(9, true); + enable_interrupts();
return 0; @@ -114,3 +117,38 @@ void specific_eoi(int irq)
outb(OCW2_SEOI | irq, MASTER_PIC + OCW2); } + +#define ELCR1 0x4d0 +#define ELCR2 0x4d1 + +void configure_irq_trigger(int int_num, bool is_level_triggered) +{ + u16 int_bits = inb(ELCR1) | (((u16)inb(ELCR2)) << 8); + + debug("%s: current interrupts are 0x%x\n", __func__, int_bits); + if (is_level_triggered) + int_bits |= (1 << int_num); + else + int_bits &= ~(1 << int_num); + + /* Write new values */ + debug("%s: try to set interrupts 0x%x\n", __func__, int_bits); + outb((u8)(int_bits & 0xff), ELCR1); + outb((u8)(int_bits >> 8), ELCR2); + +#ifdef PARANOID_IRQ_TRIGGERS + /* + * Try reading back the new values. This seems like an error but is + * not + */ + if (inb(ELCR1) != (int_bits & 0xff)) { + printf("%s: lower order bits are wrong: want 0x%x, got 0x%x\n", + __func__, (int_bits & 0xff), inb(ELCR1)); + } + + if (inb(ELCR2) != (int_bits >> 8)) { + printf("%s: higher order bits are wrong: want 0x%x, got 0x%x\n", + __func__, (int_bits>>8), inb(ELCR2)); + } +#endif +}

On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add this additional init in case it is needed by the OS.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove i8259 patch and just update the existing interrupt code
arch/x86/include/asm/interrupt.h | 11 +++++++++++ arch/x86/lib/pcat_interrupts.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+)
diff --git a/arch/x86/include/asm/interrupt.h b/arch/x86/include/asm/interrupt.h index 3f46e09..25abde7 100644 --- a/arch/x86/include/asm/interrupt.h +++ b/arch/x86/include/asm/interrupt.h @@ -27,4 +27,15 @@ void specific_eoi(int irq);
extern char exception_stack[];
+/**
- configure_irq_trigger() - Configure IRQ triggering
- Switch the given interrupt to be level / edge triggered
- @param int_num legacy interrupt number (3-7, 9-15)
- @param is_level_triggered true for level triggered interrupt, false for
edge triggered interrupt
- */
+void configure_irq_trigger(int int_num, bool is_level_triggered);
#endif diff --git a/arch/x86/lib/pcat_interrupts.c b/arch/x86/lib/pcat_interrupts.c index 4c86f7f..2dc2fbd 100644 --- a/arch/x86/lib/pcat_interrupts.c +++ b/arch/x86/lib/pcat_interrupts.c @@ -62,6 +62,9 @@ int interrupt_init(void) */ unmask_irq(2);
/* Interrupt 9 should be level triggered (SCI). The OS might do this */
configure_irq_trigger(9, true);
enable_interrupts(); return 0;
@@ -114,3 +117,38 @@ void specific_eoi(int irq)
outb(OCW2_SEOI | irq, MASTER_PIC + OCW2);
}
+#define ELCR1 0x4d0 +#define ELCR2 0x4d1
+void configure_irq_trigger(int int_num, bool is_level_triggered) +{
u16 int_bits = inb(ELCR1) | (((u16)inb(ELCR2)) << 8);
debug("%s: current interrupts are 0x%x\n", __func__, int_bits);
if (is_level_triggered)
int_bits |= (1 << int_num);
else
int_bits &= ~(1 << int_num);
/* Write new values */
debug("%s: try to set interrupts 0x%x\n", __func__, int_bits);
outb((u8)(int_bits & 0xff), ELCR1);
outb((u8)(int_bits >> 8), ELCR2);
+#ifdef PARANOID_IRQ_TRIGGERS
/*
* Try reading back the new values. This seems like an error but is
* not
*/
if (inb(ELCR1) != (int_bits & 0xff)) {
printf("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
__func__, (int_bits & 0xff), inb(ELCR1));
}
if (inb(ELCR2) != (int_bits >> 8)) {
printf("%s: higher order bits are wrong: want 0x%x, got 0x%x\n",
__func__, (int_bits>>8), inb(ELCR2));
}
+#endif
+}
Reviewed-by: Bin Meng bmeng.cn@gmail.com

On 14 November 2014 at 20:57, Bin Meng bmeng.cn@gmail.com wrote:
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add this additional init in case it is needed by the OS.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove i8259 patch and just update the existing interrupt code
Applied to u-boot-x86.

Add basic setup for the PCH.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 99 +++++++++++++++++++++++++++ arch/x86/cpu/ivybridge/pci.c | 40 +++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 14 ++++ arch/x86/include/asm/arch-ivybridge/pch.h | 13 ++++ 5 files changed, 167 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/bd82x6x.c create mode 100644 arch/x86/include/asm/arch-ivybridge/bd82x6x.h
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 721b37e..b37fb8f 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -4,6 +4,7 @@ # SPDX-License-Identifier: GPL-2.0+ #
+obj-y += bd82x6x.o obj-y += car.o obj-y += cpu.o obj-y += early_init.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c new file mode 100644 index 0000000..fab7c53 --- /dev/null +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/lapic.h> +#include <asm/pci.h> +#include <asm/arch/bd82x6x.h> +#include <asm/arch/model_206ax.h> +#include <asm/arch/pch.h> +#include <asm/arch/sandybridge.h> + +void bd82x6x_pci_init(pci_dev_t dev) +{ + u16 reg16; + u8 reg8; + + debug("bd82x6x PCI init.\n"); + /* Enable Bus Master */ + reg16 = pci_read_config16(dev, PCI_COMMAND); + reg16 |= PCI_COMMAND_MASTER; + pci_write_config16(dev, PCI_COMMAND, reg16); + + /* This device has no interrupt */ + pci_write_config8(dev, INTR, 0xff); + + /* disable parity error response and SERR */ + reg16 = pci_read_config16(dev, BCTRL); + reg16 &= ~(1 << 0); + reg16 &= ~(1 << 1); + pci_write_config16(dev, BCTRL, reg16); + + /* Master Latency Count must be set to 0x04! */ + reg8 = pci_read_config8(dev, SMLT); + reg8 &= 0x07; + reg8 |= (0x04 << 3); + pci_write_config8(dev, SMLT, reg8); + + /* Will this improve throughput of bus masters? */ + pci_write_config8(dev, PCI_MIN_GNT, 0x06); + + /* Clear errors in status registers */ + reg16 = pci_read_config16(dev, PSTS); + /* reg16 |= 0xf900; */ + pci_write_config16(dev, PSTS, reg16); + + reg16 = pci_read_config16(dev, SECSTS); + /* reg16 |= 0xf900; */ + pci_write_config16(dev, SECSTS, reg16); +} + +#define PCI_BRIDGE_UPDATE_COMMAND +void bd82x6x_pci_dev_enable_resources(pci_dev_t dev) +{ + uint16_t command; + + command = pci_read_config16(dev, PCI_COMMAND); + command |= PCI_COMMAND_IO; +#ifdef PCI_BRIDGE_UPDATE_COMMAND + /* + * If we write to PCI_COMMAND, on some systems this will cause the + * ROM and APICs to become invisible. + */ + debug("%x cmd <- %02x\n", dev, command); + pci_write_config16(dev, PCI_COMMAND, command); +#else + printf("%s cmd <- %02x (NOT WRITTEN!)\n", dev_path(dev), command); +#endif +} + +void bd82x6x_pci_bus_enable_resources(pci_dev_t dev) +{ + uint16_t ctrl; + + ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL); + ctrl |= PCI_COMMAND_IO; + ctrl |= PCI_BRIDGE_CTL_VGA; + debug("%x bridge ctrl <- %04x\n", dev, ctrl); + pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl); + + bd82x6x_pci_dev_enable_resources(dev); +} + +int bd82x6x_init_pci_devices(void) +{ + return 0; +} + +int bd82x6x_init(void) +{ + bd82x6x_pci_init(PCH_DEV); + + return 0; +} diff --git a/arch/x86/cpu/ivybridge/pci.c b/arch/x86/cpu/ivybridge/pci.c index c1ae658..452d1c3 100644 --- a/arch/x86/cpu/ivybridge/pci.c +++ b/arch/x86/cpu/ivybridge/pci.c @@ -12,6 +12,8 @@ #include <common.h> #include <pci.h> #include <asm/pci.h> +#include <asm/arch/bd82x6x.h> +#include <asm/arch/pch.h>
static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev, struct pci_config_table *table) @@ -58,3 +60,41 @@ void board_pci_setup_hose(struct pci_controller *hose)
hose->region_count = 3; } + +int board_pci_pre_scan(struct pci_controller *hose) +{ + pci_dev_t dev; + u16 reg16; + + bd82x6x_init(); + + reg16 = 0xff; + dev = PCH_DEV; + reg16 = pci_read_config16(dev, PCI_COMMAND); + reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config16(dev, PCI_COMMAND, reg16); + + /* + * Clear non-reserved bits in status register. + */ + pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + + pci_write_bar32(hose, dev, 0, 0xf0000000); + + return 0; +} + +int board_pci_post_scan(struct pci_controller *hose) +{ + int ret; + + ret = bd82x6x_init_pci_devices(); + if (ret) { + printf("bd82x6x_init_pci_devices() failed: %d\n", ret); + return ret; + } + + return 0; +} diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h new file mode 100644 index 0000000..e02520c --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ASM_ARCH_BD82X6X_H +#define _ASM_ARCH_BD82X6X_H + +void bd82x6x_pci_init(pci_dev_t dev); +int bd82x6x_init_pci_devices(void); +int bd82x6x_init(void); + +#endif diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index c6efdb8..aa626ad 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -19,6 +19,16 @@
#define SMBUS_IO_BASE 0x0400
+/* PCI Configuration Space (D30:F0): PCI2PCI */ +#define PSTS 0x06 +#define SMLT 0x1b +#define SECSTS 0x1e +#define INTR 0x3c +#define BCTRL 0x3e +#define SBR (1 << 6) +#define SEE (1 << 1) +#define PERE (1 << 0) + #define PCH_EHCI1_DEV PCI_BDF(0, 0x1d, 0) #define PCH_EHCI2_DEV PCI_BDF(0, 0x1a, 0) #define PCH_XHCI_DEV PCI_BDF(0, 0x14, 0) @@ -343,6 +353,9 @@ #define DMISCI_STS (1 << 9) #define TCO2_STS 0x66
+int lpc_init(struct pci_controller *hose, pci_dev_t dev); +void lpc_enable(pci_dev_t dev); + /** * lpc_early_init() - set up LPC serial ports and other early things *

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add basic setup for the PCH.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 99 +++++++++++++++++++++++++++ arch/x86/cpu/ivybridge/pci.c | 40 +++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 14 ++++ arch/x86/include/asm/arch-ivybridge/pch.h | 13 ++++ 5 files changed, 167 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/bd82x6x.c create mode 100644 arch/x86/include/asm/arch-ivybridge/bd82x6x.h
Applied to u-boot-x86.

We don't use many features yet, so this only has a few declarations. It will be expanded as needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/acpi.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 arch/x86/include/asm/acpi.h
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h new file mode 100644 index 0000000..4872b92 --- /dev/null +++ b/arch/x86/include/asm/acpi.h @@ -0,0 +1,24 @@ +/* + * From coreboot + * + * Copyright (C) 2004 SUSE LINUX AG + * Copyright (C) 2004 Nick Barker + * Copyright (C) 2008-2009 coresystems GmbH + * (Written by Stefan Reinauer stepan@coresystems.de) + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef __ASM_ACPI_H +#define __ASM_ACPI_H + +#define RSDP_SIG "RSD PTR " /* RSDT pointer signature */ +#define ACPI_TABLE_CREATOR "U-BootAC" /* Must be exactly 8 bytes long! */ +#define OEM_ID "U-Boot" /* Must be exactly 6 bytes long! */ +#define ASLC "U-Bo" /* Must be exactly 4 bytes long! */ + +/* 0 = S0, 1 = S1 ...*/ +int acpi_get_slp_type(void); +void apci_set_slp_type(int type); + +#endif

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
We don't use many features yet, so this only has a few declarations. It will be expanded as needed.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/include/asm/acpi.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 arch/x86/include/asm/acpi.h
Applied to u-boot-x86.

Add required init for the Intel Platform Controller Hub in ivybridge.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/pch.c | 123 ++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/pch.h | 49 ++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/pch.c
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index b37fb8f..479e446 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -12,6 +12,7 @@ obj-y += early_me.o obj-y += lpc.o obj-y += me_status.o obj-y += microcode_intel.o +obj-y += pch.o obj-y += pci.o obj-y += report_platform.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/pch.c b/arch/x86/cpu/ivybridge/pch.c new file mode 100644 index 0000000..fa04d48 --- /dev/null +++ b/arch/x86/cpu/ivybridge/pch.c @@ -0,0 +1,123 @@ +/* + * From Coreboot + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> + +static int pch_revision_id = -1; +static int pch_type = -1; + +int pch_silicon_revision(void) +{ + pci_dev_t dev; + + dev = PCH_LPC_DEV; + + if (pch_revision_id < 0) + pch_revision_id = pci_read_config8(dev, PCI_REVISION_ID); + return pch_revision_id; +} + +int pch_silicon_type(void) +{ + pci_dev_t dev; + + dev = PCH_LPC_DEV; + + if (pch_type < 0) + pch_type = pci_read_config8(dev, PCI_DEVICE_ID + 1); + return pch_type; +} + +int pch_silicon_supported(int type, int rev) +{ + int cur_type = pch_silicon_type(); + int cur_rev = pch_silicon_revision(); + + switch (type) { + case PCH_TYPE_CPT: + /* CougarPoint minimum revision */ + if (cur_type == PCH_TYPE_CPT && cur_rev >= rev) + return 1; + /* PantherPoint any revision */ + if (cur_type == PCH_TYPE_PPT) + return 1; + break; + + case PCH_TYPE_PPT: + /* PantherPoint minimum revision */ + if (cur_type == PCH_TYPE_PPT && cur_rev >= rev) + return 1; + break; + } + + return 0; +} + +#define IOBP_RETRY 1000 +static inline int iobp_poll(void) +{ + unsigned try = IOBP_RETRY; + u32 data; + + while (try--) { + data = readl(RCB_REG(IOBPS)); + if ((data & 1) == 0) + return 1; + udelay(10); + } + + printf("IOBP timeout\n"); + return 0; +} + +void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue) +{ + u32 data; + + /* Set the address */ + writel(address, RCB_REG(IOBPIRI)); + + /* READ OPCODE */ + if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0)) + writel(IOBPS_RW_BX, RCB_REG(IOBPS)); + else + writel(IOBPS_READ_AX, RCB_REG(IOBPS)); + if (!iobp_poll()) + return; + + /* Read IOBP data */ + data = readl(RCB_REG(IOBPD)); + if (!iobp_poll()) + return; + + /* Check for successful transaction */ + if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) { + printf("IOBP read 0x%08x failed\n", address); + return; + } + + /* Update the data */ + data &= andvalue; + data |= orvalue; + + /* WRITE OPCODE */ + if (pch_silicon_supported(PCH_TYPE_CPT, PCH_STEP_B0)) + writel(IOBPS_RW_BX, RCB_REG(IOBPS)); + else + writel(IOBPS_WRITE_AX, RCB_REG(IOBPS)); + if (!iobp_poll()) + return; + + /* Write IOBP data */ + writel(data, RCB_REG(IOBPD)); + if (!iobp_poll()) + return; +} diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index aa626ad..b3ec7c5 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -14,11 +14,31 @@
#include <pci.h>
+/* PCH types */ +#define PCH_TYPE_CPT 0x1c /* CougarPoint */ +#define PCH_TYPE_PPT 0x1e /* IvyBridge */ + +/* PCH stepping values for LPC device */ +#define PCH_STEP_A0 0 +#define PCH_STEP_A1 1 +#define PCH_STEP_B0 2 +#define PCH_STEP_B1 3 +#define PCH_STEP_B2 4 +#define PCH_STEP_B3 5 #define DEFAULT_GPIOBASE 0x0480 #define DEFAULT_PMBASE 0x0500
#define SMBUS_IO_BASE 0x0400
+int pch_silicon_revision(void); +int pch_silicon_type(void); +int pch_silicon_supported(int type, int rev); +void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue); + +#define MAINBOARD_POWER_OFF 0 +#define MAINBOARD_POWER_ON 1 +#define MAINBOARD_POWER_KEEP 2 + /* PCI Configuration Space (D30:F0): PCI2PCI */ #define PSTS 0x06 #define SMLT 0x1b @@ -40,6 +60,35 @@
/* PCI Configuration Space (D31:F0): LPC */ #define PCH_LPC_DEV PCI_BDF(0, 0x1f, 0) +#define SERIRQ_CNTL 0x64 + +#define GEN_PMCON_1 0xa0 +#define GEN_PMCON_2 0xa2 +#define GEN_PMCON_3 0xa4 +#define ETR3 0xac +#define ETR3_CWORWRE (1 << 18) +#define ETR3_CF9GR (1 << 20) + +/* GEN_PMCON_3 bits */ +#define RTC_BATTERY_DEAD (1 << 2) +#define RTC_POWER_FAILED (1 << 1) +#define SLEEP_AFTER_POWER_FAIL (1 << 0) + +#define PMBASE 0x40 +#define ACPI_CNTL 0x44 +#define BIOS_CNTL 0xDC +#define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ +#define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ +#define GPIO_ROUT 0xb8 + +#define PIRQA_ROUT 0x60 +#define PIRQB_ROUT 0x61 +#define PIRQC_ROUT 0x62 +#define PIRQD_ROUT 0x63 +#define PIRQE_ROUT 0x68 +#define PIRQF_ROUT 0x69 +#define PIRQG_ROUT 0x6A +#define PIRQH_ROUT 0x6B
#define GEN_PMCON_1 0xa0 #define GEN_PMCON_2 0xa2

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add required init for the Intel Platform Controller Hub in ivybridge.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/pch.c | 123 ++++++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/pch.h | 49 ++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/pch.c
Applied to u-boot-x86.

Set up all the remaining pieces of the LPC (low-pin-count) peripheral in PCH (Peripheral Controller Hub).
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Adjust rtc_init() call to remove the parameter - Remove ISA DMA init which isn't needed in U-Boot - Use i8259 init in pcat_interrupts.c - Use interrupt.h header instead of i8259.h - Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/bd82x6x.c | 6 + arch/x86/cpu/ivybridge/lpc.c | 523 +++++++++++++++++++++++++++- doc/device-tree-bindings/misc/intel-lpc.txt | 47 ++- 3 files changed, 572 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index fab7c53..be4db74 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -88,6 +88,12 @@ void bd82x6x_pci_bus_enable_resources(pci_dev_t dev)
int bd82x6x_init_pci_devices(void) { + struct pci_controller *hose; + + hose = pci_bus_to_hose(0); + lpc_enable(PCH_LPC_DEV); + lpc_init(hose, PCH_LPC_DEV); + return 0; }
diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c index 621ef2c..43fdd31 100644 --- a/arch/x86/cpu/ivybridge/lpc.c +++ b/arch/x86/cpu/ivybridge/lpc.c @@ -9,10 +9,460 @@ #include <common.h> #include <errno.h> #include <fdtdec.h> +#include <rtc.h> #include <pci.h> +#include <asm/acpi.h> +#include <asm/interrupt.h> +#include <asm/io.h> +#include <asm/ioapic.h> #include <asm/pci.h> #include <asm/arch/pch.h>
+#define NMI_OFF 0 + +#define ENABLE_ACPI_MODE_IN_COREBOOT 0 +#define TEST_SMM_FLASH_LOCKDOWN 0 + +static int pch_enable_apic(pci_dev_t dev) +{ + u32 reg32; + int i; + + /* Enable ACPI I/O and power management. Set SCI IRQ to IRQ9 */ + pci_write_config8(dev, ACPI_CNTL, 0x80); + + writel(0, IO_APIC_INDEX); + writel(1 << 25, IO_APIC_DATA); + + /* affirm full set of redirection table entries ("write once") */ + writel(1, IO_APIC_INDEX); + reg32 = readl(IO_APIC_DATA); + writel(1, IO_APIC_INDEX); + writel(reg32, IO_APIC_DATA); + + writel(0, IO_APIC_INDEX); + reg32 = readl(IO_APIC_DATA); + debug("PCH APIC ID = %x\n", (reg32 >> 24) & 0x0f); + if (reg32 != (1 << 25)) { + printf("APIC Error - cannot write to registers\n"); + return -EPERM; + } + + debug("Dumping IOAPIC registers\n"); + for (i = 0; i < 3; i++) { + writel(i, IO_APIC_INDEX); + debug(" reg 0x%04x:", i); + reg32 = readl(IO_APIC_DATA); + debug(" 0x%08x\n", reg32); + } + + /* Select Boot Configuration register. */ + writel(3, IO_APIC_INDEX); + + /* Use Processor System Bus to deliver interrupts. */ + writel(1, IO_APIC_DATA); + + return 0; +} + +static void pch_enable_serial_irqs(pci_dev_t dev) +{ + u32 value; + + /* Set packet length and toggle silent mode bit for one frame. */ + value = (1 << 7) | (1 << 6) | ((21 - 17) << 2) | (0 << 0); +#ifdef CONFIG_SERIRQ_CONTINUOUS_MODE + pci_write_config8(dev, SERIRQ_CNTL, value); +#else + pci_write_config8(dev, SERIRQ_CNTL, value | (1 << 6)); +#endif +} + +static int pch_pirq_init(const void *blob, int node, pci_dev_t dev) +{ + uint8_t route[8], *ptr; + + if (fdtdec_get_byte_array(blob, node, "intel,pirq-routing", route, + sizeof(route))) + return -EINVAL; + ptr = route; + pci_write_config8(dev, PIRQA_ROUT, *ptr++); + pci_write_config8(dev, PIRQB_ROUT, *ptr++); + pci_write_config8(dev, PIRQC_ROUT, *ptr++); + pci_write_config8(dev, PIRQD_ROUT, *ptr++); + + pci_write_config8(dev, PIRQE_ROUT, *ptr++); + pci_write_config8(dev, PIRQF_ROUT, *ptr++); + pci_write_config8(dev, PIRQG_ROUT, *ptr++); + pci_write_config8(dev, PIRQH_ROUT, *ptr++); + + /* + * TODO(sjg@chromium.org): U-Boot does not set up the interrupts + * here. It's unclear if it is needed + */ + return 0; +} + +static int pch_gpi_routing(const void *blob, int node, pci_dev_t dev) +{ + u8 route[16]; + u32 reg; + int gpi; + + if (fdtdec_get_byte_array(blob, node, "intel,gpi-routing", route, + sizeof(route))) + return -EINVAL; + + for (reg = 0, gpi = 0; gpi < ARRAY_SIZE(route); gpi++) + reg |= route[gpi] << (gpi * 2); + + pci_write_config32(dev, 0xb8, reg); + + return 0; +} + +static int pch_power_options(const void *blob, int node, pci_dev_t dev) +{ + u8 reg8; + u16 reg16, pmbase; + u32 reg32; + const char *state; + int pwr_on; + int nmi_option; + int ret; + + /* + * Which state do we want to goto after g3 (power restored)? + * 0 == S0 Full On + * 1 == S5 Soft Off + * + * If the option is not existent (Laptops), use Kconfig setting. + * TODO(sjg@chromium.org): Make this configurable + */ + pwr_on = MAINBOARD_POWER_ON; + + reg16 = pci_read_config16(dev, GEN_PMCON_3); + reg16 &= 0xfffe; + switch (pwr_on) { + case MAINBOARD_POWER_OFF: + reg16 |= 1; + state = "off"; + break; + case MAINBOARD_POWER_ON: + reg16 &= ~1; + state = "on"; + break; + case MAINBOARD_POWER_KEEP: + reg16 &= ~1; + state = "state keep"; + break; + default: + state = "undefined"; + } + + reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */ + reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */ + + reg16 &= ~(1 << 10); + reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */ + + reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */ + + pci_write_config16(dev, GEN_PMCON_3, reg16); + debug("Set power %s after power failure.\n", state); + + /* Set up NMI on errors. */ + reg8 = inb(0x61); + reg8 &= 0x0f; /* Higher Nibble must be 0 */ + reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */ + reg8 |= (1 << 2); /* PCI SERR# Disable for now */ + outb(reg8, 0x61); + + reg8 = inb(0x70); + /* TODO(sjg@chromium.org): Make this configurable */ + nmi_option = NMI_OFF; + if (nmi_option) { + debug("NMI sources enabled.\n"); + reg8 &= ~(1 << 7); /* Set NMI. */ + } else { + debug("NMI sources disabled.\n"); + /* Can't mask NMI from PCI-E and NMI_NOW */ + reg8 |= (1 << 7); + } + outb(reg8, 0x70); + + /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */ + reg16 = pci_read_config16(dev, GEN_PMCON_1); + reg16 &= ~(3 << 0); /* SMI# rate 1 minute */ + reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */ +#if DEBUG_PERIODIC_SMIS + /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using periodic SMIs */ + reg16 |= (3 << 0); /* Periodic SMI every 8s */ +#endif + pci_write_config16(dev, GEN_PMCON_1, reg16); + + /* Set the board's GPI routing. */ + ret = pch_gpi_routing(blob, node, dev); + if (ret) + return ret; + + pmbase = pci_read_config16(dev, 0x40) & 0xfffe; + + writel(pmbase + GPE0_EN, fdtdec_get_int(blob, node, + "intel,gpe0-enable", 0)); + writew(pmbase + ALT_GP_SMI_EN, fdtdec_get_int(blob, node, + "intel,alt-gp-smi-enable", 0)); + + /* Set up power management block and determine sleep mode */ + reg32 = inl(pmbase + 0x04); /* PM1_CNT */ + reg32 &= ~(7 << 10); /* SLP_TYP */ + reg32 |= (1 << 0); /* SCI_EN */ + outl(reg32, pmbase + 0x04); + + /* Clear magic status bits to prevent unexpected wake */ + setbits_le32(RCB_REG(0x3310), (1 << 4) | (1 << 5) | (1 << 0)); + clrbits_le32(RCB_REG(0x3f02), 0xf); + + return 0; +} + +static void pch_rtc_init(pci_dev_t dev) +{ + int rtc_failed; + u8 reg8; + + reg8 = pci_read_config8(dev, GEN_PMCON_3); + rtc_failed = reg8 & RTC_BATTERY_DEAD; + if (rtc_failed) { + reg8 &= ~RTC_BATTERY_DEAD; + pci_write_config8(dev, GEN_PMCON_3, reg8); + } + debug("rtc_failed = 0x%x\n", rtc_failed); + +#if CONFIG_HAVE_ACPI_RESUME + /* Avoid clearing pending interrupts and resetting the RTC control + * register in the resume path because the Linux kernel relies on + * this to know if it should restart the RTC timerqueue if the wake + * was due to the RTC alarm. + */ + if (acpi_get_slp_type() == 3) + return; +#endif + /* TODO: Handle power failure */ + if (rtc_failed) + printf("RTC power failed\n"); + rtc_init(); +} + +/* CougarPoint PCH Power Management init */ +static void cpt_pm_init(pci_dev_t dev) +{ + debug("CougarPoint PM init\n"); + pci_write_config8(dev, 0xa9, 0x47); + setbits_le32(RCB_REG(0x2238), (1 << 6) | (1 << 0)); + + setbits_le32(RCB_REG(0x228c), 1 << 0); + setbits_le32(RCB_REG(0x1100), (1 << 13) | (1 << 14)); + setbits_le32(RCB_REG(0x0900), 1 << 14); + writel(0xc0388400, RCB_REG(0x2304)); + setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18)); + setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1)); + clrsetbits_le32(RCB_REG(0x3314), ~0x1f, 0xf); + writel(0x050f0000, RCB_REG(0x3318)); + writel(0x04000000, RCB_REG(0x3324)); + setbits_le32(RCB_REG(0x3340), 0xfffff); + setbits_le32(RCB_REG(0x3344), 1 << 1); + + writel(0x0001c000, RCB_REG(0x3360)); + writel(0x00061100, RCB_REG(0x3368)); + writel(0x7f8fdfff, RCB_REG(0x3378)); + writel(0x000003fc, RCB_REG(0x337c)); + writel(0x00001000, RCB_REG(0x3388)); + writel(0x0001c000, RCB_REG(0x3390)); + writel(0x00000800, RCB_REG(0x33a0)); + writel(0x00001000, RCB_REG(0x33b0)); + writel(0x00093900, RCB_REG(0x33c0)); + writel(0x24653002, RCB_REG(0x33cc)); + writel(0x062108fe, RCB_REG(0x33d0)); + clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060); + writel(0x01010000, RCB_REG(0x3a28)); + writel(0x01010404, RCB_REG(0x3a2c)); + writel(0x01041041, RCB_REG(0x3a80)); + clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001); + setbits_le32(RCB_REG(0x3a84), 1 << 24); /* SATA 2/3 disabled */ + setbits_le32(RCB_REG(0x3a88), 1 << 0); /* SATA 4/5 disabled */ + writel(0x00000001, RCB_REG(0x3a6c)); + clrsetbits_le32(RCB_REG(0x2344), ~0x00ffff00, 0xff00000c); + clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20); + writel(0, RCB_REG(0x33c8)); + setbits_le32(RCB_REG(0x21b0), 0xf); +} + +/* PantherPoint PCH Power Management init */ +static void ppt_pm_init(pci_dev_t dev) +{ + debug("PantherPoint PM init\n"); + pci_write_config8(dev, 0xa9, 0x47); + setbits_le32(RCB_REG(0x2238), 1 << 0); + setbits_le32(RCB_REG(0x228c), 1 << 0); + setbits_le16(RCB_REG(0x1100), (1 << 13) | (1 << 14)); + setbits_le16(RCB_REG(0x0900), 1 << 14); + writel(0xc03b8400, RCB_REG(0x2304)); + setbits_le32(RCB_REG(0x2314), (1 << 5) | (1 << 18)); + setbits_le32(RCB_REG(0x2320), (1 << 15) | (1 << 1)); + clrsetbits_le32(RCB_REG(0x3314), 0x1f, 0xf); + writel(0x054f0000, RCB_REG(0x3318)); + writel(0x04000000, RCB_REG(0x3324)); + setbits_le32(RCB_REG(0x3340), 0xfffff); + setbits_le32(RCB_REG(0x3344), (1 << 1) | (1 << 0)); + writel(0x0001c000, RCB_REG(0x3360)); + writel(0x00061100, RCB_REG(0x3368)); + writel(0x7f8fdfff, RCB_REG(0x3378)); + writel(0x000003fd, RCB_REG(0x337c)); + writel(0x00001000, RCB_REG(0x3388)); + writel(0x0001c000, RCB_REG(0x3390)); + writel(0x00000800, RCB_REG(0x33a0)); + writel(0x00001000, RCB_REG(0x33b0)); + writel(0x00093900, RCB_REG(0x33c0)); + writel(0x24653002, RCB_REG(0x33cc)); + writel(0x067388fe, RCB_REG(0x33d0)); + clrsetbits_le32(RCB_REG(0x33d4), 0x0fff0fff, 0x00670060); + writel(0x01010000, RCB_REG(0x3a28)); + writel(0x01010404, RCB_REG(0x3a2c)); + writel(0x01040000, RCB_REG(0x3a80)); + clrsetbits_le32(RCB_REG(0x3a84), 0x0000ffff, 0x00001001); + /* SATA 2/3 disabled */ + setbits_le32(RCB_REG(0x3a84), 1 << 24); + /* SATA 4/5 disabled */ + setbits_le32(RCB_REG(0x3a88), 1 << 0); + writel(0x00000001, RCB_REG(0x3a6c)); + clrsetbits_le32(RCB_REG(0x2344), 0xff0000ff, 0xff00000c); + clrsetbits_le32(RCB_REG(0x80c), 0xff << 20, 0x11 << 20); + setbits_le32(RCB_REG(0x33a4), (1 << 0)); + writel(0, RCB_REG(0x33c8)); + setbits_le32(RCB_REG(0x21b0), 0xf); +} + +static void enable_hpet(void) +{ + /* Move HPET to default address 0xfed00000 and enable it */ + clrsetbits_le32(RCB_REG(HPTC), 3 << 0, 1 << 7); +} + +static void enable_clock_gating(pci_dev_t dev) +{ + u32 reg32; + u16 reg16; + + setbits_le32(RCB_REG(0x2234), 0xf); + + reg16 = pci_read_config16(dev, GEN_PMCON_1); + reg16 |= (1 << 2) | (1 << 11); + pci_write_config16(dev, GEN_PMCON_1, reg16); + + pch_iobp_update(0xEB007F07, ~0UL, (1 << 31)); + pch_iobp_update(0xEB004000, ~0UL, (1 << 7)); + pch_iobp_update(0xEC007F07, ~0UL, (1 << 31)); + pch_iobp_update(0xEC004000, ~0UL, (1 << 7)); + + reg32 = readl(RCB_REG(CG)); + reg32 |= (1 << 31); + reg32 |= (1 << 29) | (1 << 28); + reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24); + reg32 |= (1 << 16); + reg32 |= (1 << 17); + reg32 |= (1 << 18); + reg32 |= (1 << 22); + reg32 |= (1 << 23); + reg32 &= ~(1 << 20); + reg32 |= (1 << 19); + reg32 |= (1 << 0); + reg32 |= (0xf << 1); + writel(reg32, RCB_REG(CG)); + + setbits_le32(RCB_REG(0x38c0), 0x7); + setbits_le32(RCB_REG(0x36d4), 0x6680c004); + setbits_le32(RCB_REG(0x3564), 0x3); +} + +#if CONFIG_HAVE_SMI_HANDLER +static void pch_lock_smm(pci_dev_t dev) +{ +#if TEST_SMM_FLASH_LOCKDOWN + u8 reg8; +#endif + + if (acpi_slp_type != 3) { +#if ENABLE_ACPI_MODE_IN_COREBOOT + debug("Enabling ACPI via APMC:\n"); + outb(0xe1, 0xb2); /* Enable ACPI mode */ + debug("done.\n"); +#else + debug("Disabling ACPI via APMC:\n"); + outb(0x1e, 0xb2); /* Disable ACPI mode */ + debug("done.\n"); +#endif + } + + /* Don't allow evil boot loaders, kernels, or + * userspace applications to deceive us: + */ + smm_lock(); + +#if TEST_SMM_FLASH_LOCKDOWN + /* Now try this: */ + debug("Locking BIOS to RO... "); + reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ + debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", + (reg8 & 1) ? "rw" : "ro"); + reg8 &= ~(1 << 0); /* clear BIOSWE */ + pci_write_config8(dev, 0xdc, reg8); + reg8 |= (1 << 1); /* set BLE */ + pci_write_config8(dev, 0xdc, reg8); + debug("ok.\n"); + reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ + debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", + (reg8 & 1) ? "rw" : "ro"); + + debug("Writing:\n"); + writeb(0, 0xfff00000); + debug("Testing:\n"); + reg8 |= (1 << 0); /* set BIOSWE */ + pci_write_config8(dev, 0xdc, reg8); + + reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ + debug(" BLE: %s; BWE: %s\n", (reg8 & 2) ? "on" : "off", + (reg8 & 1) ? "rw" : "ro"); + debug("Done.\n"); +#endif +} +#endif + +static void pch_disable_smm_only_flashing(pci_dev_t dev) +{ + u8 reg8; + + debug("Enabling BIOS updates outside of SMM... "); + reg8 = pci_read_config8(dev, 0xdc); /* BIOS_CNTL */ + reg8 &= ~(1 << 5); + pci_write_config8(dev, 0xdc, reg8); +} + +static void pch_fixups(pci_dev_t dev) +{ + u8 gen_pmcon_2; + + /* Indicate DRAM init done for MRC S3 to know it can resume */ + gen_pmcon_2 = pci_read_config8(dev, GEN_PMCON_2); + gen_pmcon_2 |= (1 << 7); + pci_write_config8(dev, GEN_PMCON_2, gen_pmcon_2); + + /* Enable DMI ASPM in the PCH */ + clrbits_le32(RCB_REG(0x2304), 1 << 10); + setbits_le32(RCB_REG(0x21a4), (1 << 11) | (1 << 10)); + setbits_le32(RCB_REG(0x21a8), 0x3); +} + int lpc_early_init(const void *blob, int node, pci_dev_t dev) { struct reg_info { @@ -22,7 +472,7 @@ int lpc_early_init(const void *blob, int node, pci_dev_t dev) int count; int i;
- count = fdtdec_get_int_array_count(blob, node, "gen-dec", + count = fdtdec_get_int_array_count(blob, node, "intel,gen-dec", (u32 *)values, sizeof(values) / sizeof(u32)); if (count < 0) return -EINVAL; @@ -46,3 +496,74 @@ int lpc_early_init(const void *blob, int node, pci_dev_t dev)
return 0; } + +int lpc_init(struct pci_controller *hose, pci_dev_t dev) +{ + const void *blob = gd->fdt_blob; + int node; + + debug("pch: lpc_init\n"); + pci_write_bar32(hose, dev, 0, 0); + pci_write_bar32(hose, dev, 1, 0xff800000); + pci_write_bar32(hose, dev, 2, 0xfec00000); + pci_write_bar32(hose, dev, 3, 0x800); + pci_write_bar32(hose, dev, 4, 0x900); + + node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC); + if (node < 0) + return -ENOENT; + + /* Set the value for PCI command register. */ + pci_write_config16(dev, PCI_COMMAND, 0x000f); + + /* IO APIC initialization. */ + pch_enable_apic(dev); + + pch_enable_serial_irqs(dev); + + /* Setup the PIRQ. */ + pch_pirq_init(blob, node, dev); + + /* Setup power options. */ + pch_power_options(blob, node, dev); + + /* Initialize power management */ + switch (pch_silicon_type()) { + case PCH_TYPE_CPT: /* CougarPoint */ + cpt_pm_init(dev); + break; + case PCH_TYPE_PPT: /* PantherPoint */ + ppt_pm_init(dev); + break; + default: + printf("Unknown Chipset: %#02x.%dx\n", PCI_DEV(dev), + PCI_FUNC(dev)); + return -ENOSYS; + } + + /* Initialize the real time clock. */ + pch_rtc_init(dev); + + /* Initialize the High Precision Event Timers, if present. */ + enable_hpet(); + + /* Initialize Clock Gating */ + enable_clock_gating(dev); + + pch_disable_smm_only_flashing(dev); + +#if CONFIG_HAVE_SMI_HANDLER + pch_lock_smm(dev); +#endif + + pch_fixups(dev); + + return 0; +} + +void lpc_enable(pci_dev_t dev) +{ + /* Enable PCH Display Port */ + writew(0x0010, RCB_REG(DISPBDF)); + setbits_le32(RCB_REG(FD2), PCH_ENABLE_DBDF); +} diff --git a/doc/device-tree-bindings/misc/intel-lpc.txt b/doc/device-tree-bindings/misc/intel-lpc.txt index 7e1b389..ba6ca9d 100644 --- a/doc/device-tree-bindings/misc/intel-lpc.txt +++ b/doc/device-tree-bindings/misc/intel-lpc.txt @@ -6,10 +6,37 @@ Count device is as follows:
Required properties : - compatible = "intel,lpc" -- gen-dec : Specifies the values for the gen-dec registers. Up to four cell - pairs can be provided - the first of each pair is the base address and +- intel,alt-gp-smi-enable : Enable SMI sources. This cell is written to the + ALT_GP_SMI_EN register +- intel,gen-dec : Specifies the values for the gen-dec registers. Up to four + cell pairs can be provided - the first of each pair is the base address and the second is the size. These are written into the GENx_DEC registers of the LPC device +- intel,gpi-routing : Specifies the GPI routing. There are 16 cells, valid + values are: + 0 No effect (default) + 1 SMI# (if corresponding ALT_GPI_SMI_EN bit is also set) + 2 SCI (if corresponding GPIO_EN bit is also set) +- intel,pirq-routing : Speciffies the routing IRQ number for each of PIRQA-H, + one cell for each. + 0x00 - 0000 = Reserved + 0x01 - 0001 = Reserved + 0x02 - 0010 = Reserved + 0x03 - 0011 = IRQ3 + 0x04 - 0100 = IRQ4 + 0x05 - 0101 = IRQ5 + 0x06 - 0110 = IRQ6 + 0x07 - 0111 = IRQ7 + 0x08 - 1000 = Reserved + 0x09 - 1001 = IRQ9 + 0x0A - 1010 = IRQ10 + 0x0B - 1011 = IRQ11 + 0x0C - 1100 = IRQ12 + 0x0D - 1101 = Reserved + 0x0E - 1110 = IRQ14 + 0x0F - 1111 = IRQ15 + PIRQ[n]_ROUT[7] - PIRQ Routing Control + 0x80 - The PIRQ is not routed.
Example @@ -19,5 +46,19 @@ lpc { compatible = "intel,lpc"; #address-cells = <1>; #size-cells = <1>; - gen-dec = <0x800 0xfc 0x900 0xfc>; + intel,gen-dec = <0x800 0xfc 0x900 0xfc>; + + intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b + 0x80 0x80 0x80 0x80>; + /* + * GPI routing + * 0 No effect (default) + * 1 SMI# (if corresponding ALT_GPI_SMI_EN bit is + * also set) + * 2 SCI (if corresponding GPIO_EN bit is also set) + */ + intel,gpi-routing = <0 0 0 0 0 0 0 2 + 1 0 0 0 0 0 0 0>; + /* Enable EC SMI source */ + intel,alt-gp-smi-enable = <0x0100>; };

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Set up all the remaining pieces of the LPC (low-pin-count) peripheral in PCH (Peripheral Controller Hub).
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Adjust rtc_init() call to remove the parameter
- Remove ISA DMA init which isn't needed in U-Boot
- Use i8259 init in pcat_interrupts.c
- Use interrupt.h header instead of i8259.h
- Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/bd82x6x.c | 6 + arch/x86/cpu/ivybridge/lpc.c | 523 +++++++++++++++++++++++++++- doc/device-tree-bindings/misc/intel-lpc.txt | 47 ++- 3 files changed, 572 insertions(+), 4 deletions(-)
Applied to u-boot-x86.

These peripherals should not be at the top level, since they exist inside the PCI bus. We don't have a full device tree node for pci yet, but we should at least put it at the right level.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/dts/link.dts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 9329916..4520db5 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -163,21 +163,23 @@ }; };
- lpc { - compatible = "intel,lpc"; - #address-cells = <1>; - #size-cells = <1>; - gen-dec = <0x800 0xfc 0x900 0xfc>; - cros-ec@200 { - compatible = "google,cros-ec"; - reg = <0x204 1 0x200 1 0x880 0x80>; - - /* This describes the flash memory within the EC */ + pci { + lpc { + compatible = "intel,lpc"; #address-cells = <1>; #size-cells = <1>; - flash@8000000 { - reg = <0x08000000 0x20000>; - erase-value = <0xff>; + gen-dec = <0x800 0xfc 0x900 0xfc>; + cros-ec@200 { + compatible = "google,cros-ec"; + reg = <0x204 1 0x200 1 0x880 0x80>; + + /* Describes the flash memory within the EC */ + #address-cells = <1>; + #size-cells = <1>; + flash@8000000 { + reg = <0x08000000 0x20000>; + erase-value = <0xff>; + }; }; }; };

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
These peripherals should not be at the top level, since they exist inside the PCI bus. We don't have a full device tree node for pci yet, but we should at least put it at the right level.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/dts/link.dts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
Applied to u-boot-x86.

Add some settings required to set up the LPC correctly.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/dts/link.dts | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 4520db5..28cef07 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -169,6 +169,14 @@ #address-cells = <1>; #size-cells = <1>; gen-dec = <0x800 0xfc 0x900 0xfc>; + intel,gen-dec = <0x800 0xfc 0x900 0xfc>; + intel,pirq-routing = <0x8b 0x8a 0x8b 0x8b + 0x80 0x80 0x80 0x80>; + intel,gpi-routing = <0 0 0 0 0 0 0 2 + 1 0 0 0 0 0 0 0>; + /* Enable EC SMI source */ + intel,alt-gp-smi-enable = <0x0100>; + cros-ec@200 { compatible = "google,cros-ec"; reg = <0x204 1 0x200 1 0x880 0x80>;

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add some settings required to set up the LPC correctly.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
Applied to u-boot-x86.

Add code to set up the SATA interfaces on boot.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Move common SATA init to a function to reduce duplication - Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 20 +++ arch/x86/cpu/ivybridge/sata.c | 225 ++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 2 + arch/x86/include/asm/arch-ivybridge/pch.h | 58 +++++++ doc/device-tree-bindings/ata/intel-sata.txt | 26 +++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 8 files changed, 334 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/sata.c create mode 100644 doc/device-tree-bindings/ata/intel-sata.txt
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 479e446..c6342cd 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -15,4 +15,5 @@ obj-y += microcode_intel.o obj-y += pch.o obj-y += pci.o obj-y += report_platform.o +obj-y += sata.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index be4db74..b54f5c7 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -88,18 +88,38 @@ void bd82x6x_pci_bus_enable_resources(pci_dev_t dev)
int bd82x6x_init_pci_devices(void) { + const void *blob = gd->fdt_blob; struct pci_controller *hose; + int sata_node;
hose = pci_bus_to_hose(0); lpc_enable(PCH_LPC_DEV); lpc_init(hose, PCH_LPC_DEV); + sata_node = fdtdec_next_compatible(blob, 0, + COMPAT_INTEL_PANTHERPOINT_AHCI); + if (sata_node < 0) { + debug("%s: Cannot find SATA node\n", __func__); + return -EINVAL; + } + bd82x6x_sata_init(PCH_SATA_DEV, blob, sata_node);
return 0; }
int bd82x6x_init(void) { + const void *blob = gd->fdt_blob; + int sata_node; + + sata_node = fdtdec_next_compatible(blob, 0, + COMPAT_INTEL_PANTHERPOINT_AHCI); + if (sata_node < 0) { + debug("%s: Cannot find SATA node\n", __func__); + return -EINVAL; + } + bd82x6x_pci_init(PCH_DEV); + bd82x6x_sata_enable(PCH_SATA_DEV, blob, sata_node);
return 0; } diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c new file mode 100644 index 0000000..bbcd47d --- /dev/null +++ b/arch/x86/cpu/ivybridge/sata.c @@ -0,0 +1,225 @@ +/* + * From Coreboot + * Copyright (C) 2008-2009 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> +#include <asm/arch/bd82x6x.h> + +static inline u32 sir_read(pci_dev_t dev, int idx) +{ + pci_write_config32(dev, SATA_SIRI, idx); + return pci_read_config32(dev, SATA_SIRD); +} + +static inline void sir_write(pci_dev_t dev, int idx, u32 value) +{ + pci_write_config32(dev, SATA_SIRI, idx); + pci_write_config32(dev, SATA_SIRD, value); +} + +static void common_sata_init(pci_dev_t dev, unsigned int port_map) +{ + u32 reg32; + u16 reg16; + + /* Set IDE I/O Configuration */ + reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; + pci_write_config32(dev, IDE_CONFIG, reg32); + + /* Port enable */ + reg16 = pci_read_config16(dev, 0x92); + reg16 &= ~0x3f; + reg16 |= port_map; + pci_write_config16(dev, 0x92, reg16); + + /* SATA Initialization register */ + port_map &= 0xff; + pci_write_config32(dev, 0x94, ((port_map ^ 0x3f) << 24) | 0x183); +} + +void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node) +{ + unsigned int port_map, speed_support, port_tx; + struct pci_controller *hose = pci_bus_to_hose(0); + const char *mode; + u32 reg32; + u16 reg16; + + debug("SATA: Initializing...\n"); + + /* SATA configuration */ + port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); + speed_support = fdtdec_get_int(blob, node, + "sata_interface_speed_support", 0); + + /* Enable BARs */ + pci_write_config16(dev, PCI_COMMAND, 0x0007); + + mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); + if (!mode || !strcmp(mode, "ahci")) { + u32 abar; + + debug("SATA: Controller in AHCI mode\n"); + + /* Set Interrupt Line, Interrupt Pin is set by D31IP.PIP */ + pci_write_config8(dev, INTR_LN, 0x0a); + + /* Set timings */ + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); + + /* Sync DMA */ + pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0001); + + common_sata_init(dev, 0x8000 | port_map); + + /* Initialize AHCI memory-mapped space */ + abar = pci_read_bar32(hose, dev, 5); + debug("ABAR: %08X\n", abar); + /* CAP (HBA Capabilities) : enable power management */ + reg32 = readl(abar + 0x00); + reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */ + reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */ + /* Set ISS, if available */ + if (speed_support) { + reg32 &= ~0x00f00000; + reg32 |= (speed_support & 0x03) << 20; + } + writel(reg32, abar + 0x00); + /* PI (Ports implemented) */ + writel(port_map, abar + 0x0c); + (void) readl(abar + 0x0c); /* Read back 1 */ + (void) readl(abar + 0x0c); /* Read back 2 */ + /* CAP2 (HBA Capabilities Extended)*/ + reg32 = readl(abar + 0x24); + reg32 &= ~0x00000002; + writel(reg32, abar + 0x24); + /* VSP (Vendor Specific Register */ + reg32 = readl(abar + 0xa0); + reg32 &= ~0x00000005; + writel(reg32, abar + 0xa0); + } else if (!strcmp(mode, "combined")) { + debug("SATA: Controller in combined mode\n"); + + /* No AHCI: clear AHCI base */ + pci_write_bar32(hose, dev, 5, 0x00000000); + /* And without AHCI BAR no memory decoding */ + reg16 = pci_read_config16(dev, PCI_COMMAND); + reg16 &= ~PCI_COMMAND_MEMORY; + pci_write_config16(dev, PCI_COMMAND, reg16); + + pci_write_config8(dev, 0x09, 0x80); + + /* Set timings */ + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); + + /* Sync DMA */ + pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0200); + + common_sata_init(dev, port_map); + } else { + debug("SATA: Controller in plain-ide mode\n"); + + /* No AHCI: clear AHCI base */ + pci_write_bar32(hose, dev, 5, 0x00000000); + + /* And without AHCI BAR no memory decoding */ + reg16 = pci_read_config16(dev, PCI_COMMAND); + reg16 &= ~PCI_COMMAND_MEMORY; + pci_write_config16(dev, PCI_COMMAND, reg16); + + /* + * Native mode capable on both primary and secondary (0xa) + * OR'ed with enabled (0x50) = 0xf + */ + pci_write_config8(dev, 0x09, 0x8f); + + /* Set Interrupt Line */ + /* Interrupt Pin is set by D31IP.PIP */ + pci_write_config8(dev, INTR_LN, 0xff); + + /* Set timings */ + pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | + IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | + IDE_PPE0 | IDE_IE0 | IDE_TIME0); + pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | + IDE_SITRE | IDE_ISP_3_CLOCKS | + IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0); + + /* Sync DMA */ + pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0); + pci_write_config16(dev, IDE_SDMA_TIM, 0x0201); + + common_sata_init(dev, port_map); + } + + /* Set Gen3 Transmitter settings if needed */ + port_tx = fdtdec_get_int(blob, node, "intel,sata-port0-gen3-tx", 0); + if (port_tx) + pch_iobp_update(SATA_IOBP_SP0G3IR, 0, port_tx); + + port_tx = fdtdec_get_int(blob, node, "intel,sata-port1-gen3-tx", 0); + if (port_tx) + pch_iobp_update(SATA_IOBP_SP1G3IR, 0, port_tx); + + /* Additional Programming Requirements */ + sir_write(dev, 0x04, 0x00001600); + sir_write(dev, 0x28, 0xa0000033); + reg32 = sir_read(dev, 0x54); + reg32 &= 0xff000000; + reg32 |= 0x5555aa; + sir_write(dev, 0x54, reg32); + sir_write(dev, 0x64, 0xcccc8484); + reg32 = sir_read(dev, 0x68); + reg32 &= 0xffff0000; + reg32 |= 0xcccc; + sir_write(dev, 0x68, reg32); + reg32 = sir_read(dev, 0x78); + reg32 &= 0x0000ffff; + reg32 |= 0x88880000; + sir_write(dev, 0x78, reg32); + sir_write(dev, 0x84, 0x001c7000); + sir_write(dev, 0x88, 0x88338822); + sir_write(dev, 0xa0, 0x001c7000); + sir_write(dev, 0xc4, 0x0c0c0c0c); + sir_write(dev, 0xc8, 0x0c0c0c0c); + sir_write(dev, 0xd4, 0x10000000); + + pch_iobp_update(0xea004001, 0x3fffffff, 0xc0000000); + pch_iobp_update(0xea00408a, 0xfffffcff, 0x00000100); +} + +void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node) +{ + unsigned port_map; + const char *mode; + u16 map = 0; + + /* + * Set SATA controller mode early so the resource allocator can + * properly assign IO/Memory resources for the controller. + */ + mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); + if (mode && !strcmp(mode, "ahci")) + map = 0x0060; + port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); + + map |= (port_map ^ 0x3f) << 8; + pci_write_config16(dev, 0x90, map); +} diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index e02520c..644755f 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -7,6 +7,8 @@ #ifndef _ASM_ARCH_BD82X6X_H #define _ASM_ARCH_BD82X6X_H
+void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node); +void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node); void bd82x6x_pci_init(pci_dev_t dev); int bd82x6x_init_pci_devices(void); int bd82x6x_init(void); diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index b3ec7c5..21df083 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -122,6 +122,64 @@ void pch_iobp_update(u32 address, u32 andvalue, u32 orvalue); #define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ #define LPC_GENX_DEC(x) (0x84 + 4 * (x))
+/* PCI Configuration Space (D31:F1): IDE */ +#define PCH_IDE_DEV PCI_BDF(0, 0x1f, 1) +#define PCH_SATA_DEV PCI_BDF(0, 0x1f, 2) +#define PCH_SATA2_DEV PCI_BDF(0, 0x1f, 5) + +#define INTR_LN 0x3c +#define IDE_TIM_PRI 0x40 /* IDE timings, primary */ +#define IDE_DECODE_ENABLE (1 << 15) +#define IDE_SITRE (1 << 14) +#define IDE_ISP_5_CLOCKS (0 << 12) +#define IDE_ISP_4_CLOCKS (1 << 12) +#define IDE_ISP_3_CLOCKS (2 << 12) +#define IDE_RCT_4_CLOCKS (0 << 8) +#define IDE_RCT_3_CLOCKS (1 << 8) +#define IDE_RCT_2_CLOCKS (2 << 8) +#define IDE_RCT_1_CLOCKS (3 << 8) +#define IDE_DTE1 (1 << 7) +#define IDE_PPE1 (1 << 6) +#define IDE_IE1 (1 << 5) +#define IDE_TIME1 (1 << 4) +#define IDE_DTE0 (1 << 3) +#define IDE_PPE0 (1 << 2) +#define IDE_IE0 (1 << 1) +#define IDE_TIME0 (1 << 0) +#define IDE_TIM_SEC 0x42 /* IDE timings, secondary */ + +#define IDE_SDMA_CNT 0x48 /* Synchronous DMA control */ +#define IDE_SSDE1 (1 << 3) +#define IDE_SSDE0 (1 << 2) +#define IDE_PSDE1 (1 << 1) +#define IDE_PSDE0 (1 << 0) + +#define IDE_SDMA_TIM 0x4a + +#define IDE_CONFIG 0x54 /* IDE I/O Configuration Register */ +#define SIG_MODE_SEC_NORMAL (0 << 18) +#define SIG_MODE_SEC_TRISTATE (1 << 18) +#define SIG_MODE_SEC_DRIVELOW (2 << 18) +#define SIG_MODE_PRI_NORMAL (0 << 16) +#define SIG_MODE_PRI_TRISTATE (1 << 16) +#define SIG_MODE_PRI_DRIVELOW (2 << 16) +#define FAST_SCB1 (1 << 15) +#define FAST_SCB0 (1 << 14) +#define FAST_PCB1 (1 << 13) +#define FAST_PCB0 (1 << 12) +#define SCB1 (1 << 3) +#define SCB0 (1 << 2) +#define PCB1 (1 << 1) +#define PCB0 (1 << 0) + +#define SATA_SIRI 0xa0 /* SATA Indexed Register Index */ +#define SATA_SIRD 0xa4 /* SATA Indexed Register Data */ +#define SATA_SP 0xd0 /* Scratchpad */ + +/* SATA IOBP Registers */ +#define SATA_IOBP_SP0G3IR 0xea000151 +#define SATA_IOBP_SP1G3IR 0xea000051 + /* PCI Configuration Space (D31:F3): SMBus */ #define PCH_SMBUS_DEV PCI_BDF(0, 0x1f, 3) #define SMB_BASE 0x20 diff --git a/doc/device-tree-bindings/ata/intel-sata.txt b/doc/device-tree-bindings/ata/intel-sata.txt new file mode 100644 index 0000000..5e4da83 --- /dev/null +++ b/doc/device-tree-bindings/ata/intel-sata.txt @@ -0,0 +1,26 @@ +Intel Pantherpoint SATA Device Binding +====================================== + +The device tree node which describes the operation of the Intel Pantherpoint +SATA device is as follows: + +Required properties : +- compatible = "intel,pantherpoint-ahci" +- intel,sata-mode : string, one of: + "ahci" : Use AHCI mode (default) + "combined" : Use combined IDE + legacy mode + "plain-ide" : Use plain IDE mode +- intel,sata-port-map : Which SATA ports are enabled, bit 0=enable first port, + bit 1=enable second port, etc. +- intel,sata-port0-gen3-tx : Value for the IOBP_SP0G3IR register +- intel,sata-port1-gen3-tx : Value for the IOBP_SP1G3IR register + +Example +------- + +sata { + compatible = "intel,pantherpoint-ahci"; + intel,sata-mode = "ahci"; + intel,sata-port-map = <1>; + intel,sata-port0-gen3-tx = <0x00880a7f>; +}; diff --git a/include/fdtdec.h b/include/fdtdec.h index abfd678..0a0afce 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -120,6 +120,7 @@ enum fdt_compat_id { COMPAT_INTEL_LPC, /* Intel Low Pin Count I/F */ COMPAT_INTEL_MICROCODE, /* Intel microcode update */ COMPAT_MEMORY_SPD, /* Memory SPD information */ + COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */
COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index aafc4f9..8865a26 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -75,6 +75,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), COMPAT(INTEL_MICROCODE, "intel,microcode"), COMPAT(MEMORY_SPD, "memory-spd"), + COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"), };
const char *fdtdec_get_compatible(enum fdt_compat_id id)

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add code to set up the SATA interfaces on boot.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Move common SATA init to a function to reduce duplication
- Use pci_write_bar32() to write to BARs
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 20 +++ arch/x86/cpu/ivybridge/sata.c | 225 ++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 2 + arch/x86/include/asm/arch-ivybridge/pch.h | 58 +++++++ doc/device-tree-bindings/ata/intel-sata.txt | 26 +++ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 8 files changed, 334 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/sata.c create mode 100644 doc/device-tree-bindings/ata/intel-sata.txt
Applied to u-boot-x86.

Add the requires settings to enable SATA on link.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/dts/link.dts | 7 +++++++ include/configs/chromebook_link.h | 1 - 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 28cef07..d3c94e0 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -164,6 +164,13 @@ };
pci { + sata { + compatible = "intel,pantherpoint-ahci"; + intel,sata-mode = "ahci"; + intel,sata-port-map = <1>; + intel,sata-port0-gen3-tx = <0x00880a7f>; + }; + lpc { compatible = "intel,lpc"; #address-cells = <1>; diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 055b3ac..e9efd7c 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -52,7 +52,6 @@ #undef CONFIG_CMD_SF #undef CONFIG_USB_EHCI #undef CONFIG_CMD_USB -#undef CONFIG_CMD_SCSI
#define CONFIG_PCI_MEM_BUS 0xe0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add the requires settings to enable SATA on link.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/dts/link.dts | 7 +++++++ include/configs/chromebook_link.h | 1 - 2 files changed, 7 insertions(+), 1 deletion(-)
Applied to u-boot-x86.

Add init for EHCI so that USB can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 2 ++ arch/x86/cpu/ivybridge/usb_ehci.c | 29 +++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 1 + 4 files changed, 33 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/usb_ehci.c
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index c6342cd..4a00757 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -17,3 +17,4 @@ obj-y += pci.o obj-y += report_platform.o obj-y += sata.o obj-y += sdram.o +obj-y += usb_ehci.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index b54f5c7..1fcbc28 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -102,6 +102,8 @@ int bd82x6x_init_pci_devices(void) return -EINVAL; } bd82x6x_sata_init(PCH_SATA_DEV, blob, sata_node); + bd82x6x_usb_ehci_init(PCH_EHCI1_DEV); + bd82x6x_usb_ehci_init(PCH_EHCI2_DEV);
return 0; } diff --git a/arch/x86/cpu/ivybridge/usb_ehci.c b/arch/x86/cpu/ivybridge/usb_ehci.c new file mode 100644 index 0000000..291c971 --- /dev/null +++ b/arch/x86/cpu/ivybridge/usb_ehci.c @@ -0,0 +1,29 @@ +/* + * From Coreboot + * Copyright (C) 2008-2009 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> + +void bd82x6x_usb_ehci_init(pci_dev_t dev) +{ + u32 reg32; + + /* Disable Wake on Disconnect in RMH */ + reg32 = readl(RCB_REG(0x35b0)); + reg32 |= 0x22; + writel(reg32, RCB_REG(0x35b0)); + + debug("EHCI: Setting up controller.. "); + reg32 = pci_read_config32(dev, PCI_COMMAND); + reg32 |= PCI_COMMAND_MASTER; + /* reg32 |= PCI_COMMAND_SERR; */ + pci_write_config32(dev, PCI_COMMAND, reg32); + + debug("done.\n"); +} diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index 644755f..2e6a079 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -10,6 +10,7 @@ void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node); void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node); void bd82x6x_pci_init(pci_dev_t dev); +void bd82x6x_usb_ehci_init(pci_dev_t dev); int bd82x6x_init_pci_devices(void); int bd82x6x_init(void);

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add init for EHCI so that USB can be used.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 2 ++ arch/x86/cpu/ivybridge/usb_ehci.c | 29 +++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 1 + 4 files changed, 33 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/usb_ehci.c
Applied to u-boot-x86.

Enable USB support on link - there are two EHCI ports available.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/chromebook_link.h | 2 -- 1 file changed, 2 deletions(-)
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index e9efd7c..86429cf 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -50,8 +50,6 @@ #undef CONFIG_SPI #undef CONFIG_CMD_SPI #undef CONFIG_CMD_SF -#undef CONFIG_USB_EHCI -#undef CONFIG_CMD_USB
#define CONFIG_PCI_MEM_BUS 0xe0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Enable USB support on link - there are two EHCI ports available.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/configs/chromebook_link.h | 2 -- 1 file changed, 2 deletions(-)
Applied to u-boot-x86.

Add init for XHCI so that high-speed USB can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/usb_xhci.c | 32 +++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 1 + 3 files changed, 34 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/usb_xhci.c
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 4a00757..aedc395 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -18,3 +18,4 @@ obj-y += report_platform.o obj-y += sata.o obj-y += sdram.o obj-y += usb_ehci.o +obj-y += usb_xhci.o diff --git a/arch/x86/cpu/ivybridge/usb_xhci.c b/arch/x86/cpu/ivybridge/usb_xhci.c new file mode 100644 index 0000000..4a32a7e --- /dev/null +++ b/arch/x86/cpu/ivybridge/usb_xhci.c @@ -0,0 +1,32 @@ +/* + * From Coreboot + * Copyright (C) 2008-2009 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> + +void bd82x6x_usb_xhci_init(pci_dev_t dev) +{ + u32 reg32; + + debug("XHCI: Setting up controller.. "); + + /* lock overcurrent map */ + reg32 = pci_read_config32(dev, 0x44); + reg32 |= 1; + pci_write_config32(dev, 0x44, reg32); + + /* Enable clock gating */ + reg32 = pci_read_config32(dev, 0x40); + reg32 &= ~((1 << 20) | (1 << 21)); + reg32 |= (1 << 19) | (1 << 18) | (1 << 17); + reg32 |= (1 << 10) | (1 << 9) | (1 << 8); + reg32 |= (1 << 31); /* lock */ + pci_write_config32(dev, 0x40, reg32); + + debug("done.\n"); +} diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index 2e6a079..6454dd9 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -11,6 +11,7 @@ void bd82x6x_sata_init(pci_dev_t dev, const void *blob, int node); void bd82x6x_sata_enable(pci_dev_t dev, const void *blob, int node); void bd82x6x_pci_init(pci_dev_t dev); void bd82x6x_usb_ehci_init(pci_dev_t dev); +void bd82x6x_usb_xhci_init(pci_dev_t dev); int bd82x6x_init_pci_devices(void); int bd82x6x_init(void);

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Add init for XHCI so that high-speed USB can be used.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/usb_xhci.c | 32 +++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 1 + 3 files changed, 34 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/usb_xhci.c
Applied to u-boot-x86.

Intel chips have a turbo mode where they can run faster for a short period until they reach thermal limits. Add code to adjust and query this feature.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/turbo.c | 98 ++++++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/speedstep.h | 89 ++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/turbo.h | 31 +++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 arch/x86/cpu/turbo.c create mode 100644 arch/x86/include/asm/speedstep.h create mode 100644 arch/x86/include/asm/turbo.h
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 97f36d5..1327f08 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -12,3 +12,4 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o obj-$(CONFIG_PCI) += pci.o +obj-y += turbo.o diff --git a/arch/x86/cpu/turbo.c b/arch/x86/cpu/turbo.c new file mode 100644 index 0000000..254d0de --- /dev/null +++ b/arch/x86/cpu/turbo.c @@ -0,0 +1,98 @@ +/* + * From Coreboot file of the same name + * + * Copyright (C) 2011 The Chromium Authors. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/cpu.h> +#include <asm/msr.h> +#include <asm/processor.h> +#include <asm/turbo.h> + +#if CONFIG_CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED +static inline int get_global_turbo_state(void) +{ + return TURBO_UNKNOWN; +} + +static inline void set_global_turbo_state(int state) +{ +} +#else +static int g_turbo_state = TURBO_UNKNOWN; + +static inline int get_global_turbo_state(void) +{ + return g_turbo_state; +} + +static inline void set_global_turbo_state(int state) +{ + g_turbo_state = state; +} +#endif + +static const char *const turbo_state_desc[] = { + [TURBO_UNKNOWN] = "unknown", + [TURBO_UNAVAILABLE] = "unavailable", + [TURBO_DISABLED] = "available but hidden", + [TURBO_ENABLED] = "available and visible" +}; + +/* + * Determine the current state of Turbo and cache it for later. + * Turbo is a package level config so it does not need to be + * enabled on every core. + */ +int turbo_get_state(void) +{ + struct cpuid_result cpuid_regs; + int turbo_en, turbo_cap; + msr_t msr; + int turbo_state = get_global_turbo_state(); + + /* Return cached state if available */ + if (turbo_state != TURBO_UNKNOWN) + return turbo_state; + + cpuid_regs = cpuid(CPUID_LEAF_PM); + turbo_cap = !!(cpuid_regs.eax & PM_CAP_TURBO_MODE); + + msr = msr_read(MSR_IA32_MISC_ENABLES); + turbo_en = !(msr.hi & H_MISC_DISABLE_TURBO); + + if (!turbo_cap && turbo_en) { + /* Unavailable */ + turbo_state = TURBO_UNAVAILABLE; + } else if (!turbo_cap && !turbo_en) { + /* Available but disabled */ + turbo_state = TURBO_DISABLED; + } else if (turbo_cap && turbo_en) { + /* Available */ + turbo_state = TURBO_ENABLED; + } + + set_global_turbo_state(turbo_state); + debug("Turbo is %s\n", turbo_state_desc[turbo_state]); + return turbo_state; +} + +void turbo_enable(void) +{ + msr_t msr; + + /* Only possible if turbo is available but hidden */ + if (turbo_get_state() == TURBO_DISABLED) { + /* Clear Turbo Disable bit in Misc Enables */ + msr = msr_read(MSR_IA32_MISC_ENABLES); + msr.hi &= ~H_MISC_DISABLE_TURBO; + msr_write(MSR_IA32_MISC_ENABLES, msr); + + /* Update cached turbo state */ + set_global_turbo_state(TURBO_ENABLED); + debug("Turbo has been enabled\n"); + } +} diff --git a/arch/x86/include/asm/speedstep.h b/arch/x86/include/asm/speedstep.h new file mode 100644 index 0000000..b938b86 --- /dev/null +++ b/arch/x86/include/asm/speedstep.h @@ -0,0 +1,89 @@ +/* + * From Coreboot file of same name + * + * Copyright (C) 2007-2009 coresystems GmbH + * 2012 secunet Security Networks AG + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_SPEEDSTEP_H +#define _ASM_SPEEDSTEP_H + +/* Magic value used to locate speedstep configuration in the device tree */ +#define SPEEDSTEP_APIC_MAGIC 0xACAC + +/* MWAIT coordination I/O base address. This must match + * the _PR_.CPU0 PM base address. + */ +#define PMB0_BASE 0x510 + +/* PMB1: I/O port that triggers SMI once cores are in the same state. + * See CSM Trigger, at PMG_CST_CONFIG_CONTROL[6:4] + */ +#define PMB1_BASE 0x800 + +struct sst_state { + uint8_t dynfsb:1; /* whether this is SLFM */ + uint8_t nonint:1; /* add .5 to ratio */ + uint8_t ratio:6; + uint8_t vid; + uint8_t is_turbo; + uint8_t is_slfm; + uint32_t power; +}; +#define SPEEDSTEP_RATIO_SHIFT 8 +#define SPEEDSTEP_RATIO_DYNFSB_SHIFT (7 + SPEEDSTEP_RATIO_SHIFT) +#define SPEEDSTEP_RATIO_DYNFSB (1 << SPEEDSTEP_RATIO_DYNFSB_SHIFT) +#define SPEEDSTEP_RATIO_NONINT_SHIFT (6 + SPEEDSTEP_RATIO_SHIFT) +#define SPEEDSTEP_RATIO_NONINT (1 << SPEEDSTEP_RATIO_NONINT_SHIFT) +#define SPEEDSTEP_RATIO_VALUE_MASK (0x1f << SPEEDSTEP_RATIO_SHIFT) +#define SPEEDSTEP_VID_MASK 0x3f +#define SPEEDSTEP_STATE_FROM_MSR(val, mask) ((struct sst_state){ \ + 0, /* dynfsb won't be read. */ \ + ((val & mask) & SPEEDSTEP_RATIO_NONINT) ? 1 : 0, \ + (((val & mask) & SPEEDSTEP_RATIO_VALUE_MASK) \ + >> SPEEDSTEP_RATIO_SHIFT), \ + (val & mask) & SPEEDSTEP_VID_MASK, \ + 0, /* not turbo by default */ \ + 0, /* not slfm by default */ \ + 0 /* power is hardcoded in software. */ \ + }) +#define SPEEDSTEP_ENCODE_STATE(state) ( \ + ((uint16_t)(state).dynfsb << SPEEDSTEP_RATIO_DYNFSB_SHIFT) | \ + ((uint16_t)(state).nonint << SPEEDSTEP_RATIO_NONINT_SHIFT) | \ + ((uint16_t)(state).ratio << SPEEDSTEP_RATIO_SHIFT) | \ + ((uint16_t)(state).vid & SPEEDSTEP_VID_MASK)) +#define SPEEDSTEP_DOUBLE_RATIO(state) ( \ + ((uint8_t)(state).ratio * 2) + (state).nonint) + +struct sst_params { + struct sst_state slfm; + struct sst_state min; + struct sst_state max; + struct sst_state turbo; +}; + +/* Looking at core2's spec, the highest normal bus ratio for an eist enabled + processor is 14, the lowest is always 6. This makes 5 states with the + minimal step width of 2. With turbo mode and super LFM we have at most 7. */ +#define SPEEDSTEP_MAX_NORMAL_STATES 5 +#define SPEEDSTEP_MAX_STATES (SPEEDSTEP_MAX_NORMAL_STATES + 2) +struct sst_table { + /* Table of p-states for EMTTM and ACPI by decreasing performance. */ + struct sst_state states[SPEEDSTEP_MAX_STATES]; + int num_states; +}; + +void speedstep_gen_pstates(struct sst_table *); + +#define SPEEDSTEP_MAX_POWER_YONAH 31000 +#define SPEEDSTEP_MIN_POWER_YONAH 13100 +#define SPEEDSTEP_MAX_POWER_MEROM 35000 +#define SPEEDSTEP_MIN_POWER_MEROM 25000 +#define SPEEDSTEP_SLFM_POWER_MEROM 12000 +#define SPEEDSTEP_MAX_POWER_PENRYN 35000 +#define SPEEDSTEP_MIN_POWER_PENRYN 15000 +#define SPEEDSTEP_SLFM_POWER_PENRYN 12000 + +#endif diff --git a/arch/x86/include/asm/turbo.h b/arch/x86/include/asm/turbo.h new file mode 100644 index 0000000..bb0d4b4 --- /dev/null +++ b/arch/x86/include/asm/turbo.h @@ -0,0 +1,31 @@ +/* + * From coreboot file of the same name + * + * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_TURBO_H +#define _ASM_TURBO_H + +#define CPUID_LEAF_PM 6 +#define PM_CAP_TURBO_MODE (1 << 1) + +#define MSR_IA32_MISC_ENABLES 0x1a0 +#define H_MISC_DISABLE_TURBO (1 << 6) + +enum { + TURBO_UNKNOWN, + TURBO_UNAVAILABLE, + TURBO_DISABLED, + TURBO_ENABLED, +}; + +/* Return current turbo state */ +int turbo_get_state(void); + +/* Enable turbo */ +void turbo_enable(void); + +#endif

On 14 November 2014 at 18:18, Simon Glass sjg@chromium.org wrote:
Intel chips have a turbo mode where they can run faster for a short period until they reach thermal limits. Add code to adjust and query this feature.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/turbo.c | 98 ++++++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/speedstep.h | 89 ++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/turbo.h | 31 +++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 arch/x86/cpu/turbo.c create mode 100644 arch/x86/include/asm/speedstep.h create mode 100644 arch/x86/include/asm/turbo.h
Applied to u-boot-x86.

Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Remove use of __PRE_RAM__ define - Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/* + * From coreboot file of same name + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h> + +void lapic_setup(void) +{ +#if NEED_LAPIC == 1 + /* Only Pentium Pro and later have those MSR stuff */ + debug("Setting up local apic: "); + + /* Enable the local apic */ + enable_lapic(); + + /* + * Set Task Priority to 'accept all'. + */ + lapic_write_around(LAPIC_TASKPRI, + lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK); + + /* Put the local apic in virtual wire mode */ + lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) & + ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); + lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) & + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_EXTINT)); + lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) & + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | + LAPIC_DELIVERY_MODE_MASK)) | + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | + LAPIC_DELIVERY_MODE_NMI)); + + debug("apic_id: 0x%02lx, ", lapicid()); +#else /* !NEED_LLAPIC */ + /* Only Pentium Pro and later have those MSR stuff */ + msr_t msr; + + debug("Disabling local apic:"); + + msr = msr_read(LAPIC_BASE_MSR); + msr.lo &= ~LAPIC_BASE_MSR_ENABLE; + msr_write(LAPIC_BASE_MSR, msr); +#endif /* !NEED_LAPIC */ + debug("done.\n"); + post_code(POST_LAPIC); +} diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h index 948e643..eaf2a98 100644 --- a/arch/x86/include/asm/lapic.h +++ b/arch/x86/include/asm/lapic.h @@ -14,6 +14,13 @@ #include <asm/msr.h> #include <asm/processor.h>
+/* See if I need to initialize the local apic */ +#if CONFIG_SMP || CONFIG_IOAPIC +# define NEED_LAPIC 1 +#else +# define NEED_LAPIC 0 +#endif + static inline __attribute__((always_inline)) unsigned long lapic_read(unsigned long reg) { @@ -36,9 +43,9 @@ static inline void enable_lapic(void) msr_t msr;
msr = msr_read(LAPIC_BASE_MSR); - msr.hi &= 0xffffff00; - msr.lo &= 0x000007ff; - msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11); + msr.lo |= LAPIC_BASE_MSR_ENABLE; + msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK; + msr.lo |= LAPIC_DEFAULT_BASE; msr_write(LAPIC_BASE_MSR, msr); }
@@ -56,4 +63,116 @@ static inline __attribute__((always_inline)) unsigned long lapicid(void) return lapic_read(LAPIC_ID) >> 24; }
+#if !CONFIG_AP_IN_SIPI_WAIT +/* If we need to go back to sipi wait, we use the long non-inlined version of + * this function in lapic_cpu_init.c + */ +static inline __attribute__((always_inline)) void stop_this_cpu(void) +{ + /* Called by an AP when it is ready to halt and wait for a new task */ + for (;;) + cpu_hlt(); +} +#else +void stop_this_cpu(void); +#endif + +#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ + sizeof(*(ptr)))) + +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((struct __xchg_dummy *)(x)) + +/* + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway + * Note 2: xchg has side effect, so that attribute volatile is necessary, + * but generally the primitive is invalid, *ptr is output argument. --ANK + */ +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, + int size) +{ + switch (size) { + case 1: + __asm__ __volatile__("xchgb %b0,%1" + : "=q" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + case 2: + __asm__ __volatile__("xchgw %w0,%1" + : "=r" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + case 4: + __asm__ __volatile__("xchgl %0,%1" + : "=r" (x) + : "m" (*__xg(ptr)), "0" (x) + : "memory"); + break; + } + + return x; +} + +static inline void lapic_write_atomic(unsigned long reg, unsigned long v) +{ + (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); +} + + +#ifdef X86_GOOD_APIC +# define FORCE_READ_AROUND_WRITE 0 +# define lapic_read_around(x) lapic_read(x) +# define lapic_write_around(x, y) lapic_write((x), (y)) +#else +# define FORCE_READ_AROUND_WRITE 1 +# define lapic_read_around(x) lapic_read(x) +# define lapic_write_around(x, y) lapic_write_atomic((x), (y)) +#endif + +static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) +{ + int timeout; + unsigned long status; + int result; + lapic_wait_icr_idle(); + lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid)); + lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4)); + timeout = 0; + do { + status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; + } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000); + + result = -1; + if (status == LAPIC_ICR_RR_VALID) { + *pvalue = lapic_read(LAPIC_RRR); + result = 0; + } + return result; +} + + +void lapic_setup(void); + +#if CONFIG_SMP +struct device; +int start_cpu(struct device *cpu); +#endif /* CONFIG_SMP */ + +int boot_cpu(void); + +/** + * struct x86_cpu_priv - Information about a single CPU + * + * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is + * just a number representing the CPU core + * + * TODO: Move this to driver model once lifecycle is understood + */ +struct x86_cpu_priv { + int apic_id; + int start_err; +}; + #endif diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h index ce68839..6d2ae5d 100644 --- a/arch/x86/include/asm/post.h +++ b/arch/x86/include/asm/post.h @@ -30,6 +30,7 @@ #define POST_PRE_MRC 0x2e #define POST_MRC 0x2f #define POST_DRAM 0x2f +#define POST_LAPIC 0x30
#define POST_RAM_FAILURE 0xea

Hi Simon,
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove use of __PRE_RAM__ define
- Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/*
- From coreboot file of same name
- Copyright (C) 2008-2009 coresystems GmbH
- Copyright (C) 2014 Google, Inc
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h>
+void lapic_setup(void) +{ +#if NEED_LAPIC == 1
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
/* Only Pentium Pro and later have those MSR stuff */
msr_t msr;
debug("Disabling local apic:");
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
msr_write(LAPIC_BASE_MSR, msr);
Seems you missed my previous comments about replacing above with disable_lapic() which is defined in lapic.h.
[snip]
Regards, Bin

Hi Bin,
On 14 November 2014 21:01, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove use of __PRE_RAM__ define
- Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/*
- From coreboot file of same name
- Copyright (C) 2008-2009 coresystems GmbH
- Copyright (C) 2014 Google, Inc
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h>
+void lapic_setup(void) +{ +#if NEED_LAPIC == 1
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
/* Only Pentium Pro and later have those MSR stuff */
msr_t msr;
debug("Disabling local apic:");
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
msr_write(LAPIC_BASE_MSR, msr);
Seems you missed my previous comments about replacing above with disable_lapic() which is defined in lapic.h.
No, it is there. This function calls enable_lapic() then does some other things too.
Regards, Simon

Hi Simon,
On Sat, Nov 15, 2014 at 12:30 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 14 November 2014 21:01, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove use of __PRE_RAM__ define
- Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/*
- From coreboot file of same name
- Copyright (C) 2008-2009 coresystems GmbH
- Copyright (C) 2014 Google, Inc
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h>
+void lapic_setup(void) +{ +#if NEED_LAPIC == 1
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
/* Only Pentium Pro and later have those MSR stuff */
msr_t msr;
debug("Disabling local apic:");
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
msr_write(LAPIC_BASE_MSR, msr);
Seems you missed my previous comments about replacing above with disable_lapic() which is defined in lapic.h.
No, it is there. This function calls enable_lapic() then does some other things too.
Where is it? You are saying enable_lapic()? But here is the disable_lapic().
Regards, Bin

Hi Bin,
On 14 November 2014 21:36, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Nov 15, 2014 at 12:30 PM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 14 November 2014 21:01, Bin Meng bmeng.cn@gmail.com wrote:
Hi Simon,
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove use of __PRE_RAM__ define
- Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/*
- From coreboot file of same name
- Copyright (C) 2008-2009 coresystems GmbH
- Copyright (C) 2014 Google, Inc
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h>
+void lapic_setup(void) +{ +#if NEED_LAPIC == 1
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
/* Only Pentium Pro and later have those MSR stuff */
msr_t msr;
debug("Disabling local apic:");
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
msr_write(LAPIC_BASE_MSR, msr);
Seems you missed my previous comments about replacing above with disable_lapic() which is defined in lapic.h.
No, it is there. This function calls enable_lapic() then does some other things too.
Where is it? You are saying enable_lapic()? But here is the disable_lapic().
Ah I think you wanted both enable and disabled replaced, and I only did enable. I'll take a look soon and resend this patch.
Regards, Simon

Hi Simon,
On Sat, Nov 15, 2014 at 9:18 AM, Simon Glass sjg@chromium.org wrote:
Add code to set up the Local Advanced Peripheral Interrupt Controller.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Remove use of __PRE_RAM__ define
- Use existing lapic_setup() code instead of duplicating it
arch/x86/cpu/Makefile | 1 + arch/x86/cpu/lapic.c | 62 +++++++++++++++++++++ arch/x86/include/asm/lapic.h | 125 +++++++++++++++++++++++++++++++++++++++++-- arch/x86/include/asm/post.h | 1 + 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 arch/x86/cpu/lapic.c
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 1327f08..adfd258 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,5 +11,6 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-y += lapic.o obj-$(CONFIG_PCI) += pci.o obj-y += turbo.o diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c new file mode 100644 index 0000000..4d14a8d --- /dev/null +++ b/arch/x86/cpu/lapic.c @@ -0,0 +1,62 @@ +/*
- From coreboot file of same name
- Copyright (C) 2008-2009 coresystems GmbH
- Copyright (C) 2014 Google, Inc
- SPDX-License-Identifier: GPL-2.0
- */
+#include <common.h> +#include <asm/msr.h> +#include <asm/io.h> +#include <asm/lapic.h> +#include <asm/post.h>
+void lapic_setup(void) +{ +#if NEED_LAPIC == 1
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
+#else /* !NEED_LLAPIC */
/* Only Pentium Pro and later have those MSR stuff */
msr_t msr;
debug("Disabling local apic:");
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~LAPIC_BASE_MSR_ENABLE;
msr_write(LAPIC_BASE_MSR, msr);
+#endif /* !NEED_LAPIC */
debug("done.\n");
post_code(POST_LAPIC);
+} diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h index 948e643..eaf2a98 100644 --- a/arch/x86/include/asm/lapic.h +++ b/arch/x86/include/asm/lapic.h @@ -14,6 +14,13 @@ #include <asm/msr.h> #include <asm/processor.h>
+/* See if I need to initialize the local apic */ +#if CONFIG_SMP || CONFIG_IOAPIC +# define NEED_LAPIC 1 +#else +# define NEED_LAPIC 0 +#endif
static inline __attribute__((always_inline)) unsigned long lapic_read(unsigned long reg) { @@ -36,9 +43,9 @@ static inline void enable_lapic(void) msr_t msr;
msr = msr_read(LAPIC_BASE_MSR);
msr.hi &= 0xffffff00;
msr.lo &= 0x000007ff;
msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11);
msr.lo |= LAPIC_BASE_MSR_ENABLE;
msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
msr.lo |= LAPIC_DEFAULT_BASE; msr_write(LAPIC_BASE_MSR, msr);
}
And here: msr.hi &= 0xffffff00 should not be removed.
[snip]
Regards, Bin

Add the setup code for the CPU so that it can be used at full speed.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 6 + arch/x86/cpu/ivybridge/model_206ax.c | 514 ++++++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/bd82x6x.h | 3 + arch/x86/include/asm/msr-index.h | 2 + include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 7 files changed, 528 insertions(+) create mode 100644 arch/x86/cpu/ivybridge/model_206ax.c
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index aedc395..95491b5 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -11,6 +11,7 @@ obj-y += early_init.o obj-y += early_me.o obj-y += lpc.o obj-y += me_status.o +obj-y += model_206ax.o obj-y += microcode_intel.o obj-y += pch.o obj-y += pci.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 1fcbc28..1a3c036 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -90,6 +90,7 @@ int bd82x6x_init_pci_devices(void) { const void *blob = gd->fdt_blob; struct pci_controller *hose; + struct x86_cpu_priv *cpu; int sata_node;
hose = pci_bus_to_hose(0); @@ -105,6 +106,11 @@ int bd82x6x_init_pci_devices(void) bd82x6x_usb_ehci_init(PCH_EHCI1_DEV); bd82x6x_usb_ehci_init(PCH_EHCI2_DEV);
+ cpu = calloc(1, sizeof(*cpu)); + if (!cpu) + return -ENOMEM; + model_206ax_init(cpu); + return 0; }
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c new file mode 100644 index 0000000..11dc625 --- /dev/null +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -0,0 +1,514 @@ +/* + * From Coreboot file of same name + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The Chromium Authors + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/acpi.h> +#include <asm/cpu.h> +#include <asm/lapic.h> +#include <asm/lapic_def.h> +#include <asm/msr.h> +#include <asm/mtrr.h> +#include <asm/processor.h> +#include <asm/speedstep.h> +#include <asm/turbo.h> +#include <asm/arch/model_206ax.h> + +static void enable_vmx(void) +{ + struct cpuid_result regs; +#ifdef CONFIG_ENABLE_VMX + int enable = true; +#else + int enable = false; +#endif + msr_t msr; + + regs = cpuid(1); + /* Check that the VMX is supported before reading or writing the MSR. */ + if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX))) + return; + + msr = msr_read(MSR_IA32_FEATURE_CONTROL); + + if (msr.lo & (1 << 0)) { + debug("VMX is locked, so %s will do nothing\n", __func__); + /* VMX locked. If we set it again we get an illegal + * instruction + */ + return; + } + + /* The IA32_FEATURE_CONTROL MSR may initialize with random values. + * It must be cleared regardless of VMX config setting. + */ + msr.hi = 0; + msr.lo = 0; + + debug("%s VMX\n", enable ? "Enabling" : "Disabling"); + + /* + * Even though the Intel manual says you must set the lock bit in + * addition to the VMX bit in order for VMX to work, it is incorrect. + * Thus we leave it unlocked for the OS to manage things itself. + * This is good for a few reasons: + * - No need to reflash the bios just to toggle the lock bit. + * - The VMX bits really really should match each other across cores, + * so hard locking it on one while another has the opposite setting + * can easily lead to crashes as code using VMX migrates between + * them. + * - Vendors that want to "upsell" from a bios that disables+locks to + * one that doesn't is sleazy. + * By leaving this to the OS (e.g. Linux), people can do exactly what + * they want on the fly, and do it correctly (e.g. across multiple + * cores). + */ + if (enable) { + msr.lo |= (1 << 2); + if (regs.ecx & CPUID_SMX) + msr.lo |= (1 << 1); + } + + msr_write(MSR_IA32_FEATURE_CONTROL, msr); +} + +/* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */ +static const u8 power_limit_time_sec_to_msr[] = { + [0] = 0x00, + [1] = 0x0a, + [2] = 0x0b, + [3] = 0x4b, + [4] = 0x0c, + [5] = 0x2c, + [6] = 0x4c, + [7] = 0x6c, + [8] = 0x0d, + [10] = 0x2d, + [12] = 0x4d, + [14] = 0x6d, + [16] = 0x0e, + [20] = 0x2e, + [24] = 0x4e, + [28] = 0x6e, + [32] = 0x0f, + [40] = 0x2f, + [48] = 0x4f, + [56] = 0x6f, + [64] = 0x10, + [80] = 0x30, + [96] = 0x50, + [112] = 0x70, + [128] = 0x11, +}; + +/* Convert POWER_LIMIT_1_TIME MSR value to seconds */ +static const u8 power_limit_time_msr_to_sec[] = { + [0x00] = 0, + [0x0a] = 1, + [0x0b] = 2, + [0x4b] = 3, + [0x0c] = 4, + [0x2c] = 5, + [0x4c] = 6, + [0x6c] = 7, + [0x0d] = 8, + [0x2d] = 10, + [0x4d] = 12, + [0x6d] = 14, + [0x0e] = 16, + [0x2e] = 20, + [0x4e] = 24, + [0x6e] = 28, + [0x0f] = 32, + [0x2f] = 40, + [0x4f] = 48, + [0x6f] = 56, + [0x10] = 64, + [0x30] = 80, + [0x50] = 96, + [0x70] = 112, + [0x11] = 128, +}; + +int cpu_config_tdp_levels(void) +{ + struct cpuid_result result; + msr_t platform_info; + + /* Minimum CPU revision */ + result = cpuid(1); + if (result.eax < IVB_CONFIG_TDP_MIN_CPUID) + return 0; + + /* Bits 34:33 indicate how many levels supported */ + platform_info = msr_read(MSR_PLATFORM_INFO); + return (platform_info.hi >> 1) & 3; +} + +/* + * Configure processor power limits if possible + * This must be done AFTER set of BIOS_RESET_CPL + */ +void set_power_limits(u8 power_limit_1_time) +{ + msr_t msr = msr_read(MSR_PLATFORM_INFO); + msr_t limit; + unsigned power_unit; + unsigned tdp, min_power, max_power, max_time; + u8 power_limit_1_val; + + if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr)) + return; + + if (!(msr.lo & PLATFORM_INFO_SET_TDP)) + return; + + /* Get units */ + msr = msr_read(MSR_PKG_POWER_SKU_UNIT); + power_unit = 2 << ((msr.lo & 0xf) - 1); + + /* Get power defaults for this SKU */ + msr = msr_read(MSR_PKG_POWER_SKU); + tdp = msr.lo & 0x7fff; + min_power = (msr.lo >> 16) & 0x7fff; + max_power = msr.hi & 0x7fff; + max_time = (msr.hi >> 16) & 0x7f; + + debug("CPU TDP: %u Watts\n", tdp / power_unit); + + if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time) + power_limit_1_time = power_limit_time_msr_to_sec[max_time]; + + if (min_power > 0 && tdp < min_power) + tdp = min_power; + + if (max_power > 0 && tdp > max_power) + tdp = max_power; + + power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time]; + + /* Set long term power limit to TDP */ + limit.lo = 0; + limit.lo |= tdp & PKG_POWER_LIMIT_MASK; + limit.lo |= PKG_POWER_LIMIT_EN; + limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) << + PKG_POWER_LIMIT_TIME_SHIFT; + + /* Set short term power limit to 1.25 * TDP */ + limit.hi = 0; + limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK; + limit.hi |= PKG_POWER_LIMIT_EN; + /* Power limit 2 time is only programmable on SNB EP/EX */ + + msr_write(MSR_PKG_POWER_LIMIT, limit); + + /* Use nominal TDP values for CPUs with configurable TDP */ + if (cpu_config_tdp_levels()) { + msr = msr_read(MSR_CONFIG_TDP_NOMINAL); + limit.hi = 0; + limit.lo = msr.lo & 0xff; + msr_write(MSR_TURBO_ACTIVATION_RATIO, limit); + } +} + +static void configure_c_states(void) +{ + struct cpuid_result result; + msr_t msr; + + msr = msr_read(MSR_PMG_CST_CONFIG_CTL); + msr.lo |= (1 << 28); /* C1 Auto Undemotion Enable */ + msr.lo |= (1 << 27); /* C3 Auto Undemotion Enable */ + msr.lo |= (1 << 26); /* C1 Auto Demotion Enable */ + msr.lo |= (1 << 25); /* C3 Auto Demotion Enable */ + msr.lo &= ~(1 << 10); /* Disable IO MWAIT redirection */ + msr.lo |= 7; /* No package C-state limit */ + msr_write(MSR_PMG_CST_CONFIG_CTL, msr); + + msr = msr_read(MSR_PMG_IO_CAPTURE_ADR); + msr.lo &= ~0x7ffff; + msr.lo |= (PMB0_BASE + 4); /* LVL_2 base address */ + msr.lo |= (2 << 16); /* CST Range: C7 is max C-state */ + msr_write(MSR_PMG_IO_CAPTURE_ADR, msr); + + msr = msr_read(MSR_MISC_PWR_MGMT); + msr.lo &= ~(1 << 0); /* Enable P-state HW_ALL coordination */ + msr_write(MSR_MISC_PWR_MGMT, msr); + + msr = msr_read(MSR_POWER_CTL); + msr.lo |= (1 << 18); /* Enable Energy Perf Bias MSR 0x1b0 */ + msr.lo |= (1 << 1); /* C1E Enable */ + msr.lo |= (1 << 0); /* Bi-directional PROCHOT# */ + msr_write(MSR_POWER_CTL, msr); + + /* C3 Interrupt Response Time Limit */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50; + msr_write(MSR_PKGC3_IRTL, msr); + + /* C6 Interrupt Response Time Limit */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68; + msr_write(MSR_PKGC6_IRTL, msr); + + /* C7 Interrupt Response Time Limit */ + msr.hi = 0; + msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D; + msr_write(MSR_PKGC7_IRTL, msr); + + /* Primary Plane Current Limit */ + msr = msr_read(MSR_PP0_CURRENT_CONFIG); + msr.lo &= ~0x1fff; + msr.lo |= PP0_CURRENT_LIMIT; + msr_write(MSR_PP0_CURRENT_CONFIG, msr); + + /* Secondary Plane Current Limit */ + msr = msr_read(MSR_PP1_CURRENT_CONFIG); + msr.lo &= ~0x1fff; + result = cpuid(1); + if (result.eax >= 0x30600) + msr.lo |= PP1_CURRENT_LIMIT_IVB; + else + msr.lo |= PP1_CURRENT_LIMIT_SNB; + msr_write(MSR_PP1_CURRENT_CONFIG, msr); +} + +static int configure_thermal_target(void) +{ + int tcc_offset; + msr_t msr; + int node; + + /* Find pointer to CPU configuration */ + node = fdtdec_next_compatible(gd->fdt_blob, 0, + COMPAT_INTEL_MODEL_206AX); + if (node < 0) + return -ENOENT; + tcc_offset = fdtdec_get_int(gd->fdt_blob, node, "tcc-offset", 0); + + /* Set TCC activaiton offset if supported */ + msr = msr_read(MSR_PLATFORM_INFO); + if ((msr.lo & (1 << 30)) && tcc_offset) { + msr = msr_read(MSR_TEMPERATURE_TARGET); + msr.lo &= ~(0xf << 24); /* Bits 27:24 */ + msr.lo |= (tcc_offset & 0xf) << 24; + msr_write(MSR_TEMPERATURE_TARGET, msr); + } + + return 0; +} + +static void configure_misc(void) +{ + msr_t msr; + + msr = msr_read(IA32_MISC_ENABLE); + msr.lo |= (1 << 0); /* Fast String enable */ + msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */ + msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */ + msr_write(IA32_MISC_ENABLE, msr); + + /* Disable Thermal interrupts */ + msr.lo = 0; + msr.hi = 0; + msr_write(IA32_THERM_INTERRUPT, msr); + + /* Enable package critical interrupt only */ + msr.lo = 1 << 4; + msr.hi = 0; + msr_write(IA32_PACKAGE_THERM_INTERRUPT, msr); +} + +static void enable_lapic_tpr(void) +{ + msr_t msr; + + msr = msr_read(MSR_PIC_MSG_CONTROL); + msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */ + msr_write(MSR_PIC_MSG_CONTROL, msr); +} + +static void configure_dca_cap(void) +{ + struct cpuid_result cpuid_regs; + msr_t msr; + + /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */ + cpuid_regs = cpuid(1); + if (cpuid_regs.ecx & (1 << 18)) { + msr = msr_read(IA32_PLATFORM_DCA_CAP); + msr.lo |= 1; + msr_write(IA32_PLATFORM_DCA_CAP, msr); + } +} + +static void set_max_ratio(void) +{ + msr_t msr, perf_ctl; + + perf_ctl.hi = 0; + + /* Check for configurable TDP option */ + if (cpu_config_tdp_levels()) { + /* Set to nominal TDP ratio */ + msr = msr_read(MSR_CONFIG_TDP_NOMINAL); + perf_ctl.lo = (msr.lo & 0xff) << 8; + } else { + /* Platform Info bits 15:8 give max ratio */ + msr = msr_read(MSR_PLATFORM_INFO); + perf_ctl.lo = msr.lo & 0xff00; + } + msr_write(IA32_PERF_CTL, perf_ctl); + + debug("model_x06ax: frequency set to %d\n", + ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK); +} + +static void set_energy_perf_bias(u8 policy) +{ + msr_t msr; + + /* Energy Policy is bits 3:0 */ + msr = msr_read(IA32_ENERGY_PERFORMANCE_BIAS); + msr.lo &= ~0xf; + msr.lo |= policy & 0xf; + msr_write(IA32_ENERGY_PERFORMANCE_BIAS, msr); + + debug("model_x06ax: energy policy set to %u\n", policy); +} + +static void configure_mca(void) +{ + msr_t msr; + int i; + + msr.lo = 0; + msr.hi = 0; + /* This should only be done on a cold boot */ + for (i = 0; i < 7; i++) + msr_write(IA32_MC0_STATUS + (i * 4), msr); +} + +#if CONFIG_USBDEBUG +static unsigned ehci_debug_addr; +#endif + +/* + * Initialize any extra cores/threads in this package. + */ +static int intel_cores_init(struct x86_cpu_priv *cpu) +{ + struct cpuid_result result; + unsigned threads_per_package, threads_per_core, i; + + /* Logical processors (threads) per core */ + result = cpuid_ext(0xb, 0); + threads_per_core = result.ebx & 0xffff; + + /* Logical processors (threads) per package */ + result = cpuid_ext(0xb, 1); + threads_per_package = result.ebx & 0xffff; + + debug("CPU: %u has %u cores, %u threads per core\n", + cpu->apic_id, threads_per_package / threads_per_core, + threads_per_core); + + for (i = 1; i < threads_per_package; ++i) { + struct x86_cpu_priv *new_cpu; + + new_cpu = calloc(1, sizeof(*new_cpu)); + if (!new_cpu) + return -ENOMEM; + + new_cpu->apic_id = cpu->apic_id + i; + + /* Update APIC ID if no hyperthreading */ + if (threads_per_core == 1) + new_cpu->apic_id <<= 1; + + debug("CPU: %u has core %u\n", cpu->apic_id, new_cpu->apic_id); + +#if CONFIG_SMP && CONFIG_MAX_CPUS > 1 + /* Start the new cpu */ + if (!start_cpu(new_cpu)) { + /* Record the error in cpu? */ + printk(BIOS_ERR, "CPU %u would not start!\n", + new_cpu->apic_id); + new_cpu->start_err = 1; + } +#endif + } + + return 0; +} + +int model_206ax_init(struct x86_cpu_priv *cpu) +{ + int ret; + + /* Clear out pending MCEs */ + configure_mca(); + +#if CONFIG_USBDEBUG + /* Is this caution really needed? */ + if (!ehci_debug_addr) + ehci_debug_addr = get_ehci_debug(); + set_ehci_debug(0); +#endif + + /* Setup MTRRs based on physical address size */ +#if 0 /* TODO: Implement this */ + struct cpuid_result cpuid_regs; + + cpuid_regs = cpuid(0x80000008); + x86_setup_fixed_mtrrs(); + x86_setup_var_mtrrs(cpuid_regs.eax & 0xff, 2); + x86_mtrr_check(); +#endif + +#if CONFIG_USBDEBUG + set_ehci_debug(ehci_debug_addr); +#endif + + /* Enable the local cpu apics */ + enable_lapic_tpr(); + lapic_setup(); + + /* Enable virtualization if enabled in CMOS */ + enable_vmx(); + + /* Configure C States */ + configure_c_states(); + + /* Configure Enhanced SpeedStep and Thermal Sensors */ + configure_misc(); + + /* Thermal throttle activation offset */ + ret = configure_thermal_target(); + if (ret) + return ret; + + /* Enable Direct Cache Access */ + configure_dca_cap(); + + /* Set energy policy */ + set_energy_perf_bias(ENERGY_POLICY_NORMAL); + + /* Set Max Ratio */ + set_max_ratio(); + + /* Enable Turbo */ + turbo_enable(); + + /* Start up extra cores */ + intel_cores_init(cpu); + + return 0; +} diff --git a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h index 6454dd9..96d51c2 100644 --- a/arch/x86/include/asm/arch-ivybridge/bd82x6x.h +++ b/arch/x86/include/asm/arch-ivybridge/bd82x6x.h @@ -15,4 +15,7 @@ void bd82x6x_usb_xhci_init(pci_dev_t dev); int bd82x6x_init_pci_devices(void); int bd82x6x_init(void);
+struct x86_cpu_priv; +int model_206ax_init(struct x86_cpu_priv *cpu); + #endif diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 6027d59..2cbb270 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -326,6 +326,8 @@ #define MSR_AMD_PERF_STATUS 0xc0010063 #define MSR_AMD_PERF_CTL 0xc0010062
+#define MSR_PMG_CST_CONFIG_CTL 0x000000e2 +#define MSR_PMG_IO_CAPTURE_ADR 0x000000e4 #define MSR_IA32_MPERF 0x000000e7 #define MSR_IA32_APERF 0x000000e8
diff --git a/include/fdtdec.h b/include/fdtdec.h index 0a0afce..b6e1d40 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -121,6 +121,7 @@ enum fdt_compat_id { COMPAT_INTEL_MICROCODE, /* Intel microcode update */ COMPAT_MEMORY_SPD, /* Memory SPD information */ COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */ + COMPAT_INTEL_MODEL_206AX, /* Intel Model 206AX CPU */
COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 8865a26..2f2b467 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -76,6 +76,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(INTEL_MICROCODE, "intel,microcode"), COMPAT(MEMORY_SPD, "memory-spd"), COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"), + COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"), };
const char *fdtdec_get_compatible(enum fdt_compat_id id)

These are not available in U-Boot as yet, so drop them.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/include/asm/msr.h | 11 ----------- 1 file changed, 11 deletions(-)
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index df43983..1955a75 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -229,17 +229,6 @@ do { \ struct msr *msrs_alloc(void); void msrs_free(struct msr *msrs);
-#ifdef CONFIG_SMP -int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); -int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); -void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); -void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs); -int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); -int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h); -int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); -int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]); - -#endif /* CONFIG_SMP */ #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_MSR_H */

Add init for the northbridge, another part of the platform controller hub.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/cpu/ivybridge/Makefile | 1 + arch/x86/cpu/ivybridge/bd82x6x.c | 2 + arch/x86/cpu/ivybridge/northbridge.c | 188 ++++++++++++++++++++++ arch/x86/include/asm/arch-ivybridge/model_206ax.h | 4 + arch/x86/include/asm/arch-ivybridge/sandybridge.h | 13 +- 5 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 arch/x86/cpu/ivybridge/northbridge.c
diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 95491b5..1296a78 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -13,6 +13,7 @@ obj-y += lpc.o obj-y += me_status.o obj-y += model_206ax.o obj-y += microcode_intel.o +obj-y += northbridge.o obj-y += pch.o obj-y += pci.o obj-y += report_platform.o diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 1a3c036..739f979 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -128,6 +128,8 @@ int bd82x6x_init(void)
bd82x6x_pci_init(PCH_DEV); bd82x6x_sata_enable(PCH_SATA_DEV, blob, sata_node); + northbridge_enable(PCH_DEV); + northbridge_init(PCH_DEV);
return 0; } diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c new file mode 100644 index 0000000..c50b5de --- /dev/null +++ b/arch/x86/cpu/ivybridge/northbridge.c @@ -0,0 +1,188 @@ +/* + * From Coreboot northbridge/intel/sandybridge/northbridge.c + * + * Copyright (C) 2007-2009 coresystems GmbH + * Copyright (C) 2011 The Chromium Authors + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <asm/msr.h> +#include <asm/acpi.h> +#include <asm/cpu.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/processor.h> +#include <asm/arch/pch.h> +#include <asm/arch/model_206ax.h> +#include <asm/arch/sandybridge.h> + +static int bridge_revision_id = -1; + +int bridge_silicon_revision(void) +{ + if (bridge_revision_id < 0) { + struct cpuid_result result; + uint8_t stepping, bridge_id; + pci_dev_t dev; + + result = cpuid(1); + stepping = result.eax & 0xf; + dev = PCI_BDF(0, 0, 0); + bridge_id = pci_read_config16(dev, PCI_DEVICE_ID) & 0xf0; + bridge_revision_id = bridge_id | stepping; + } + + return bridge_revision_id; +} + +/* + * Reserve everything between A segment and 1MB: + * + * 0xa0000 - 0xbffff: legacy VGA + * 0xc0000 - 0xcffff: VGA OPROM (needed by kernel) + * 0xe0000 - 0xfffff: SeaBIOS, if used, otherwise DMI + */ +static const int legacy_hole_base_k = 0xa0000 / 1024; +static const int legacy_hole_size_k = 384; + +static int get_pcie_bar(u32 *base, u32 *len) +{ + pci_dev_t dev = PCI_BDF(0, 0, 0); + u32 pciexbar_reg; + + *base = 0; + *len = 0; + + pciexbar_reg = pci_read_config32(dev, PCIEXBAR); + + if (!(pciexbar_reg & (1 << 0))) + return 0; + + switch ((pciexbar_reg >> 1) & 3) { + case 0: /* 256MB */ + *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | + (1 << 28)); + *len = 256 * 1024 * 1024; + return 1; + case 1: /* 128M */ + *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | + (1 << 28) | (1 << 27)); + *len = 128 * 1024 * 1024; + return 1; + case 2: /* 64M */ + *base = pciexbar_reg & ((1 << 31) | (1 << 30) | (1 << 29) | + (1 << 28) | (1 << 27) | (1 << 26)); + *len = 64 * 1024 * 1024; + return 1; + } + + return 0; +} + +static void add_fixed_resources(pci_dev_t dev, int index) +{ + u32 pcie_config_base, pcie_config_size; + + if (get_pcie_bar(&pcie_config_base, &pcie_config_size)) { + debug("Adding PCIe config bar base=0x%08x size=0x%x\n", + pcie_config_base, pcie_config_size); + } +} + +static void northbridge_dmi_init(pci_dev_t dev) +{ + /* Clear error status bits */ + writel(0xffffffff, DMIBAR_REG(0x1c4)); + writel(0xffffffff, DMIBAR_REG(0x1d0)); + + /* Steps prior to DMI ASPM */ + if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) { + clrsetbits_le32(DMIBAR_REG(0x250), (1 << 22) | (1 << 20), + 1 << 21); + } + + setbits_le32(DMIBAR_REG(0x238), 1 << 29); + + if (bridge_silicon_revision() >= SNB_STEP_D0) { + setbits_le32(DMIBAR_REG(0x1f8), 1 << 16); + } else if (bridge_silicon_revision() >= SNB_STEP_D1) { + clrsetbits_le32(DMIBAR_REG(0x1f8), 1 << 26, 1 << 16); + setbits_le32(DMIBAR_REG(0x1fc), (1 << 12) | (1 << 23)); + } + + /* Enable ASPM on SNB link, should happen before PCH link */ + if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) + setbits_le32(DMIBAR_REG(0xd04), 1 << 4); + + setbits_le32(DMIBAR_REG(0x88), (1 << 1) | (1 << 0)); +} + +void northbridge_init(pci_dev_t dev) +{ + u32 bridge_type; + + add_fixed_resources(dev, 6); + northbridge_dmi_init(dev); + + bridge_type = readl(MCHBAR_REG(0x5f10)); + bridge_type &= ~0xff; + + if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) { + /* Enable Power Aware Interrupt Routing - fixed priority */ + clrsetbits_8(MCHBAR_REG(0x5418), 0xf, 0x4); + + /* 30h for IvyBridge */ + bridge_type |= 0x30; + } else { + /* 20h for Sandybridge */ + bridge_type |= 0x20; + } + writel(bridge_type, MCHBAR_REG(0x5f10)); + + /* + * Set bit 0 of BIOS_RESET_CPL to indicate to the CPU + * that BIOS has initialized memory and power management + */ + setbits_8(MCHBAR_REG(BIOS_RESET_CPL), 1); + debug("Set BIOS_RESET_CPL\n"); + + /* Configure turbo power limits 1ms after reset complete bit */ + mdelay(1); + set_power_limits(28); + + /* + * CPUs with configurable TDP also need power limits set + * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT. + */ + if (cpu_config_tdp_levels()) { + msr_t msr = msr_read(MSR_PKG_POWER_LIMIT); + + writel(msr.lo, MCHBAR_REG(0x59A0)); + writel(msr.hi, MCHBAR_REG(0x59A4)); + } + + /* Set here before graphics PM init */ + writel(0x00100001, MCHBAR_REG(0x5500)); +} + +void northbridge_enable(pci_dev_t dev) +{ +#if CONFIG_HAVE_ACPI_RESUME + switch (pci_read_config32(dev, SKPAD)) { + case 0xcafebabe: + debug("Normal boot.\n"); + apci_set_slp_type(0); + break; + case 0xcafed00d: + debug("S3 Resume.\n"); + apci_set_slp_type(3); + break; + default: + debug("Unknown boot method, assuming normal.\n"); + apci_set_slp_type(0); + break; + } +#endif +} diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h index 8281d7a..7b4f2e7 100644 --- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h +++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h @@ -79,4 +79,8 @@ #define PSS_LATENCY_TRANSITION 10 #define PSS_LATENCY_BUSMASTER 10
+/* Configure power limits for turbo mode */ +void set_power_limits(u8 power_limit_1_time); +int cpu_config_tdp_levels(void); + #endif diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h index 114ee19..cf7457f 100644 --- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h +++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h @@ -97,11 +97,22 @@ /* * MCHBAR */ -#define MCHBAR_REG(reg) (DEFAULT_RCBA + (reg)) +#define MCHBAR_REG(reg) (DEFAULT_MCHBAR + (reg))
#define SSKPD 0x5d14 /* 16bit (scratchpad) */ #define BIOS_RESET_CPL 0x5da8 /* 8bit */
+/* + * DMIBAR + */ + +#define DMIBAR_REG(x) (DEFAULT_DMIBAR + x) + +int bridge_silicon_revision(void); + +void northbridge_enable(pci_dev_t dev); +void northbridge_init(pci_dev_t dev); + void report_platform_info(void);
void sandybridge_early_init(int chipset_type);

Enable SPI so that the SPI flash can be used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/chromebook_link.h | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 86429cf..6b57b28 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -46,10 +46,6 @@ */ #undef CONFIG_VIDEO #undef CONFIG_CFB_CONSOLE -#undef CONFIG_ICH_SPI -#undef CONFIG_SPI -#undef CONFIG_CMD_SPI -#undef CONFIG_CMD_SF
#define CONFIG_PCI_MEM_BUS 0xe0000000 #define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS
participants (2)
-
Bin Meng
-
Simon Glass