diff --git a/src/northbridge/intel/sandybridge/pei_data.h b/src/northbridge/intel/sandybridge/pei_data.h index 8c907c1db8..fb56873d2b 100644 --- a/src/northbridge/intel/sandybridge/pei_data.h +++ b/src/northbridge/intel/sandybridge/pei_data.h @@ -30,8 +30,16 @@ #ifndef PEI_DATA_H #define PEI_DATA_H +typedef struct { + uint16_t mode; // 0: Disable, 1: Enable, 2: Auto, 3: Smart Auto + uint16_t hs_port_switch_mask; // 4 bit mask, 1: switchable, 0: not switchable + uint16_t preboot_support; // 0: No xHCI preOS driver, 1: xHCI preOS driver + uint16_t xhci_streams; // 0: Disable, 1: Enable +} pch_usb3_controller_settings; + typedef void (*tx_byte_func)(unsigned char byte); -#define PEI_VERSION 4 +#define PEI_VERSION 5 + struct pei_data { uint32_t pei_version; @@ -92,6 +100,8 @@ struct pei_data * < 0x150 = Setting 3 (back panel, 13-15in, higest tx amplitude) */ uint16_t usb_port_config[16][3]; + /* See the usb3 struct above for details */ + pch_usb3_controller_settings usb3; /* SPD data array for onboard RAM. Specify address 0xf0, * 0xf1, 0xf2, 0xf3 to index one of the 4 slots in * spd_address for a given "DIMM". diff --git a/src/southbridge/intel/bd82x6x/acpi/globalnvs.asl b/src/southbridge/intel/bd82x6x/acpi/globalnvs.asl index 2fe092d952..99edc317cf 100644 --- a/src/southbridge/intel/bd82x6x/acpi/globalnvs.asl +++ b/src/southbridge/intel/bd82x6x/acpi/globalnvs.asl @@ -136,6 +136,9 @@ Field (GNVS, ByteAcc, NoLock, Preserve) GTF2, 56, // 0xa4 - GTF task file buffer for port 2 IDEM, 8, // 0xab - IDE mode (compatible / enhanced) IDET, 8, // 0xac - IDE + /* XHCI */ + Offset (0xb2), + XHCI, 8, /* IGD OpRegion */ Offset (0xb4), ASLB, 32, // 0xb4 - IGD OpRegion Base Address @@ -223,6 +226,17 @@ Method (S3GD) Store (Zero, \S33G) } +/* Set XHCI Mode enable */ +Method (XHCE) +{ + Store (One, \XHCI) +} + +/* Set XHCI Mode disable */ +Method (XHCD) +{ + Store (Zero, \XHCI) +} External (\_TZ.THRM) External (\_TZ.SKIN) diff --git a/src/southbridge/intel/bd82x6x/acpi/pch.asl b/src/southbridge/intel/bd82x6x/acpi/pch.asl index 8632ad849e..2f75fdc3f7 100644 --- a/src/southbridge/intel/bd82x6x/acpi/pch.asl +++ b/src/southbridge/intel/bd82x6x/acpi/pch.asl @@ -245,7 +245,7 @@ Scope(\) // PCI Express Ports 0:1c.x #include "pcie.asl" -// USB 0:1d.0 and 0:1a.0 +// USB EHCI 0:1d.0 and 0:1a.0, XHCI 0:14.0 #include "usb.asl" // LPC Bridge 0:1f.0 @@ -259,17 +259,22 @@ Scope(\) Method (_OSC, 4) { - /* Check for proper GUID */ + /* Check for XHCI */ + If (LEqual (Arg0, ToUUID("7c9512a9-1705-4cb4-af7d-506a2423ab71"))) + { + Return (^XHC.POSC(Arg1, Arg2, Arg3)) + } + + /* Check for PCIe */ If (LEqual (Arg0, ToUUID("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) { /* Let OS control everything */ Return (Arg3) } - Else - { - /* Unrecognized UUID */ - CreateDWordField (Arg3, 0, CDW1) - Or (CDW1, 4, CDW1) - Return (Arg3) - } + + /* Else Return Unrecognized UUID */ + CreateDWordField (Arg3, 0, CDW1) + Or (CDW1, 4, CDW1) + Return (Arg3) + } diff --git a/src/southbridge/intel/bd82x6x/acpi/usb.asl b/src/southbridge/intel/bd82x6x/acpi/usb.asl index cf3e6a049f..f19d3685ae 100644 --- a/src/southbridge/intel/bd82x6x/acpi/usb.asl +++ b/src/southbridge/intel/bd82x6x/acpi/usb.asl @@ -89,3 +89,72 @@ Device (EHC2) } } +Device (XHC) +{ + Name(_ADR, 0x00140000) + OperationRegion(XDEV, PCI_Config, 0, 256) + Field(XDEV, DWordAcc, NoLock, Preserve) + { + Offset(0xD0), + X2PR, 32, // XUSB2PR + PRM2, 32, // XUSB2PRM + SSEN, 32, // USB3_PSSEN + RPM3, 32, // USB3PRM + XPRT, 32, // XHCI Ports + } + + Name (_PRW, Package(){ 13, 4 }) // Power Resources for Wake + + Method(POSC,3,Serialized) + { + // Create DWord field from the Capabilities Buffer + CreateDWordField(Arg2,0,CDW1) + + // Check revision + If(LNotEqual(Arg1,One)) { + // Set unknown revision bit + Or(CDW1,0x8,CDW1) + } + + // Set failure if xHCI is disabled by coreboot + If(LEqual(XHCI, 0)) { + Or(CDW1,0x2,CDW1) + } + + // Query flag clear and xHCI in auto mode + If(LAnd(LNot(And(CDW1,0x1)),LOr(LEqual(XHCI ,2), LEqual(XHCI ,3)))) { + Store ("XHCI Switch", Debug) + Store(Zero, Local0) + And(XPRT, 0x3, Local0) + If(LOr(LEqual(Local0, 0), LEqual(Local0, 1))) { + Store(0xF, Local1) + } + ElseIf(LEqual(Local0, 2)) { + Store(0x3, Local1) + } + ElseIf(LEqual(Local0, 3)) { + Store(Zero, Local1) + } + And(RPM3, 0xFFFFFFF0, Local0) + Or(Local0, Local1, RPM3) + And(PRM2, 0xFFFFFFF0, Local0) + Or(Local0, Local1, PRM2) + And(SSEN, 0xFFFFFFF0, Local0) + Or(Local0, Local1, SSEN) + And(X2PR, 0xFFFFFFF0, Local0) + Or(Local0, Local1, X2PR) + } + Return(Arg2) + } + + // Leave USB ports on for to allow Wake from USB + Method(_S3D,0) // Highest D State in S3 State + { + Return (2) + } + + Method(_S4D,0) // Highest D State in S4 State + { + Return (2) + } +} diff --git a/src/southbridge/intel/bd82x6x/early_usb.c b/src/southbridge/intel/bd82x6x/early_usb.c index b2e009123e..bbe792f908 100644 --- a/src/southbridge/intel/bd82x6x/early_usb.c +++ b/src/southbridge/intel/bd82x6x/early_usb.c @@ -27,6 +27,7 @@ #define PCH_EHCI1_TEMP_BAR0 0xe8000000 #define PCH_EHCI2_TEMP_BAR0 0xe8000400 +#define PCH_XHCI_TEMP_BAR0 0xe8001000 /* * Setup USB controller MMIO BAR to prevent the @@ -39,6 +40,7 @@ void enable_usb_bar(void) { device_t usb0 = PCH_EHCI1_DEV; device_t usb1 = PCH_EHCI2_DEV; + device_t usb3 = PCH_XHCI_DEV; u32 cmd; /* USB Controller 1 */ @@ -54,4 +56,11 @@ void enable_usb_bar(void) cmd = pci_read_config32(usb1, PCI_COMMAND); cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; pci_write_config32(usb1, PCI_COMMAND, cmd); + + /* USB3 Controller */ + pci_write_config32(usb3, PCI_BASE_ADDRESS_0, + PCH_XHCI_TEMP_BAR0); + cmd = pci_read_config32(usb3, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb3, PCI_COMMAND, cmd); } diff --git a/src/southbridge/intel/bd82x6x/nvs.h b/src/southbridge/intel/bd82x6x/nvs.h index b8506d4db4..7b8b6c9e9c 100644 --- a/src/southbridge/intel/bd82x6x/nvs.h +++ b/src/southbridge/intel/bd82x6x/nvs.h @@ -113,7 +113,9 @@ typedef struct { u8 gtf2[7]; u8 idem; u8 idet; - u8 rsvd11[7]; + u8 rsvd11[6]; + /* XHCI */ + u8 xhci; /* IGD OpRegion (not implemented yet) */ u32 aslb; /* 0xb4 - IGD OpRegion Base Address */ u8 ibtt; /* 0xb8 - IGD boot type */ diff --git a/src/southbridge/intel/bd82x6x/pch.h b/src/southbridge/intel/bd82x6x/pch.h index 13ffe3a2a6..ca54418914 100644 --- a/src/southbridge/intel/bd82x6x/pch.h +++ b/src/southbridge/intel/bd82x6x/pch.h @@ -95,6 +95,7 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define PCH_EHCI1_DEV PCI_DEV(0, 0x1d, 0) #define PCH_EHCI2_DEV PCI_DEV(0, 0x1a, 0) +#define PCH_XHCI_DEV PCI_DEV(0, 0x14, 0) #define PCH_ME_DEV PCI_DEV(0, 0x16, 0) #define PCH_PCIE_DEV_SLOT 28 @@ -365,6 +366,8 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define D22IP_IDERIP 8 /* IDE-R Pin */ #define D22IP_MEI2IP 4 /* MEI #2 Pin */ #define D22IP_MEI1IP 0 /* MEI #1 Pin */ +#define D20IP 0x3128 /* 32bit */ +#define D20IP_XHCIIP 0 #define D31IR 0x3140 /* 16bit */ #define D30IR 0x3142 /* 16bit */ #define D29IR 0x3144 /* 16bit */ @@ -373,6 +376,7 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define D26IR 0x314c /* 16bit */ #define D25IR 0x3150 /* 16bit */ #define D22IR 0x315c /* 16bit */ +#define D20IR 0x3160 /* 16bit */ #define OIC 0x31fe /* 16bit */ #define SOFT_RESET_CTRL 0x38f4 #define SOFT_RESET_DATA 0x38f8 @@ -392,7 +396,7 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define CG 0x341c /* 32bit */ /* Function Disable 1 RCBA 0x3418 */ -#define PCH_DISABLE_ALWAYS ((1 << 0)|(1 << 26)|(1 << 27)) +#define PCH_DISABLE_ALWAYS ((1 << 0)|(1 << 26)) #define PCH_DISABLE_P2P (1 << 1) #define PCH_DISABLE_SATA1 (1 << 2) #define PCH_DISABLE_SMBUS (1 << 3) @@ -403,6 +407,7 @@ int early_spi_read(u32 offset, u32 size, u8 *buffer); #define PCH_DISABLE_PCIE(x) (1 << (16 + x)) #define PCH_DISABLE_THERMAL (1 << 24) #define PCH_DISABLE_SATA2 (1 << 25) +#define PCH_DISABLE_XHCI (1 << 27) /* Function Disable 2 RCBA 0x3428 */ #define PCH_DISABLE_KT (1 << 4) diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c index 420c5db211..093da5c60a 100644 --- a/src/southbridge/intel/bd82x6x/smihandler.c +++ b/src/southbridge/intel/bd82x6x/smihandler.c @@ -326,6 +326,17 @@ static void southbridge_gate_memory_reset(void) outl(reg32, gpiobase + GP_LVL2); } +static void xhci_sleep(u8 slp_typ) +{ + u32 reg32; + + if (slp_typ == SLP_TYP_S5) { + reg32 = pcie_read_config32(PCH_XHCI_DEV, 0x74); + reg32 |= (1 << 8 | 0x03 ); + pcie_write_config32(PCH_XHCI_DEV, 0x74, reg32); + } +} + static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *state_save) { u8 reg8; @@ -353,6 +364,9 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32); slp_typ = (reg32 >> 10) & 7; + if (smm_get_gnvs()->xhci) + xhci_sleep(slp_typ); + /* Do any mainboard sleep handling */ tseg_relocate((void **)&mainboard_sleep); if (mainboard_sleep)