/**************************************************************************; ;* *; ;* Intel Confidential *; ;* *; ;* Intel Corporation - ACPI Reference Code for the Haswell *; ;* Family of Customer Reference Boards. *; ;* *; ;* *; ;* Copyright (c) 1999 - 2011 Intel Corporation. All rights reserved *; ;* This software and associated documentation (if any) is furnished *; ;* under a license and may only be used or copied in accordance *; ;* with the terms of the license. Except as permitted by such *; ;* license, no part of this software or documentation may be *; ;* reproduced, stored in a retrieval system, or transmitted in any *; ;* form or by any means without the express written consent of *; ;* Intel Corporation. *; ;* *; ;* *; ;**************************************************************************/ /*++ This file contains an 'Intel Peripheral Driver' and is licensed for Intel CPUs and chipsets under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to additional terms of the license agreement --*/ // Define various SMBus PCI Configuration Space Registers. OperationRegion(SMBP,PCI_Config,0x40,0xC0) Field(SMBP,DWordAcc,NoLock,Preserve) { , 2, I2CE, 1 } OperationRegion(SMPB,PCI_Config,0x20,4) Field(SMPB,DWordAcc,NoLock,Preserve) { , 5, SBAR, 11 } // Define various SMBus IO Mapped Registers. OperationRegion(SMBI,SystemIO,ShiftLeft(SBAR,5),0x10) Field(SMBI,ByteAcc,NoLock,Preserve) { HSTS, 8, // 0 - Host Status Register Offset(0x02), HCON, 8, // 2 - Host Control HCOM, 8, // 3 - Host Command TXSA, 8, // 4 - Transmit Slave Address DAT0, 8, // 5 - Host Data 0 DAT1, 8, // 6 - Host Data 1 HBDR, 8, // 7 - Host Block Data PECR, 8, // 8 - Packer Error Check RXSA, 8, // 9 - Receive Slave Address SDAT, 16, // A - Slave Data } // SMBus Send Byte - This function will write a single byte of // data to a specific Slave Device per SMBus Send Byte Protocol. // Arg0 = Address // Arg1 = Data // Return: Success = 1 // Failure = 0 Method(SSXB,2,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform // communication. If(STRT()) { Return(0) } // Step 2: Initiate a Send Byte. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Arg0,TXSA) // Write Address in TXSA. Store(Arg1,HCOM) // Data in HCOM. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 001 = Byte Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x48,HCON) // Step 3: Exit the Method correctly. If(COMP) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. Return(1) // Return Success. } Return(0) } // SMBus Receive Byte - This function will write a single byte // of data to a specific Slave Device per SMBus Receive Byte // Protocol. // Arg0 = Address // Return: Success = Byte-Size Value // Failure = Word-Size Value = FFFFh. Method(SRXB,1,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform // communication. If(STRT()) { Return(0xFFFF) } // Step 2: Initiate a Receive Byte. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Or(Arg0,1),TXSA) // Read Address in TXSA. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 001 = Byte Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x44,HCON) // Step 3: Exit the Method correctly. If(COMP) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. Return(DAT0) // Return Success. } Return(0xFFFF) // Return Failure. } // SMBus Write Byte - This function will write a single byte // of data to a specific Slave Device per SMBus Write Byte // Protocol. // Arg0 = Address // Arg1 = Command // Arg2 = Data // Return: Success = 1 // Failure = 0 Method(SWRB,3,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0) } // Step 2: Initiate a Write Byte. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Arg0,TXSA) // Write Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. Store(Arg2,DAT0) // Data in DAT0. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 010 = Byte Data Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x48,HCON) // Step 3: Exit the Method correctly. If(COMP) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. Return(1) // Return Success. } Return(0) // Return Failure. } // SMBus Read Byte - This function will read a single byte of data // from a specific slave device per SMBus Read Byte Protocol. // Arg0 = Address // Arg1 = Command // Return: Success = Byte-Size Value // Failure = Word-Size Value Method(SRDB,2,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0xFFFF) } // Step 2: Initiate a Read Byte. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Or(Arg0,1),TXSA) // Read Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 010 = Byte Data Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x48,HCON) // Step 3: Exit the Method correctly. If(COMP) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others.. Return(DAT0) // Return Success. } Return(0xFFFF) // Return Failure. } // SMBus Write Word - This function will write a single word // of data to a specific Slave Device per SMBus Write Word // Protocol. // Arg0 = Address // Arg1 = Command // Arg2 = Data (16 bits in size) // Return: Success = 1 // Failure = 0 Method(SWRW,3,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0) } // Step 2: Initiate a Write Word. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Arg0,TXSA) // Write Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. And(Arg2,0xFF,DAT1) // Low byte Data in DAT1. And(ShiftRight(Arg2,8),0xFF,DAT0) // High byte Data in DAT0. // Set the SMBus Host control register to 0x4C. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 011 = Word Data Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x4C,HCON) // Step 3: Exit the Method correctly. If(COMP()) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. Return(1) // Return Success. } Return(0) // Return Failure. } // SMBus Read Word - This function will read a single byte of data // from a specific slave device per SMBus Read Word Protocol. // Arg0 = Address // Arg1 = Command // Return: Success = Word-Size Value // Failure = Dword-Size Value Method(SRDW,2,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0xFFFF) } // Step 2: Initiate a Read Word. Store(0,I2CE) // Ensure SMbus Mode. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Or(Arg0,1),TXSA) // Read Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. // Set the SMBus Host control register to 0x4C. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 011 = Word Data Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x4C,HCON) // Step 3: Exit the Method correctly. If(COMP()) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. Return(Or(ShiftLeft(DAT0,8),DAT1)) // Return Success. } Return(0xFFFFFFFF) // Return Failure. } // SMBus Block Write - This function will write an entire block of data // to a specific slave device per SMBus Block Write Protocol. // Arg0 = Address // Arg1 = Command // Arg2 = Buffer of Data to Write // Arg3 = 1 = I2C Block Write, 0 = SMBus Block Write // Return: Success = 1 // Failure = 0 Method(SBLW,4,Serialized) { // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0) } // Step 2: Initiate a Block Write. Store(Arg3,I2CE) // Select the proper protocol. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Arg0,TXSA) // Write Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. Store(Sizeof(Arg2),DAT0) // Count in DAT0. Store(0,Local1) // Init Pointer to Buffer. Store(DerefOf(Index(Arg2,0)),HBDR) // First Byte in HBD Register. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 101 = Block Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x54,HCON) // Step 3: Send the entire Block of Data. While(LGreater(Sizeof(Arg2),Local1)) { // Wait up to 200ms for Host Status to get set. Store(4000,Local0) // 4000 * 50us = 200ms. While(LAnd(LNot(And(HSTS,0x80)),Local0)) { Decrement(Local0) // Decrement Count. Stall(50) // Delay = 50us. } If(LNot(Local0)) // Timeout? { KILL() // Yes. Kill Communication. Return(0) // Return failure. } Store(0x80,HSTS) // Clear Host Status. Increment(Local1) // Point to Next Byte. // Place next byte in HBDR if last byte has not been sent. If(LGreater(Sizeof(Arg2),Local1)) { Store(DerefOf(Index(Arg2,Local1)),HBDR) } } // Step 4: Exit the Method correctly. If(COMP()) { Or(HSTS,0xFF,HSTS) // Clear all status bits. Return(1) // Return Success. } Return(0) // Return Failure. } // SMBus Block Read - This function will read a block of data from // a specific slave device per SMBus Block Read Protocol. // Arg0 = Address // Arg1 = Command // Arg2 = 1 = I2C Block Write, 0 = SMBus Block Write // Return: Success = Data Buffer (First Byte = length) // Failure = 0 Method(SBLR,3,Serialized) { Name(TBUF, Buffer(256) {}) // Step 1: Confirm the ICHx SMBus is ready to perform communication. If(STRT()) { Return(0) } // Step 2: Initiate a Block Read. Store(Arg2,I2CE) // Select the proper protocol. Store(0xBF,HSTS) // Clear all but INUSE_STS. Store(Or(Arg0,1),TXSA) // Read Address in TXSA. Store(Arg1,HCOM) // Command in HCOM. // Set the SMBus Host control register to 0x48. // Bit 7: = 0 = reserved // Bit 6: = 1 = start // Bit 5: = 0 = disregard, I2C related bit // Bits 4:2: = 101 = Block Protocol // Bit 1: = 0 = Normal Function // Bit 0: = 0 = Disable interrupt generation Store(0x54,HCON) // Step 3: Wait up to 200ms to get the Data Count. Store(4000,Local0) // 4000 * 50us = 200ms. While(LAnd(LNot(And(HSTS,0x80)),Local0)) { Decrement(Local0) // Decrement Count. Stall(50) // Delay = 50us. } If(LNot(Local0)) // Timeout? { KILL() // Yes. Kill Communication. Return(0) // Return failure. } Store(DAT0,Index(TBUF,0)) // Get the Data Count. Store(0x80,HSTS) // Clear Host Status. Store(1,Local1) // Local1 = Buffer Pointer. // Step 4: Get the Block Data and store it. While(LLess(Local1,DerefOf(Index(TBUF,0)))) { // Wait up to 200ms for Host Status to get set. Store(4000,Local0) // 4000 * 50us = 200ms. While(LAnd(LNot(And(HSTS,0x80)),Local0)) { Decrement(Local0) // Decrement Count. Stall(50) // Delay = 50us. } If(LNot(Local0)) // Timeout? { KILL() // Yes. Kill Communication. Return(0) // Return failure. } Store(HBDR,Index(TBUF,Local1)) // Place into Buffer. Store(0x80,HSTS) // Clear Host Status. Increment(Local1) } // Step 5: Exit the Method correctly. If(COMP()) { Or(HSTS,0xFF,HSTS) // Clear INUSE_STS and others. Return(TBUF) // Return Success. } Return(0) // Return Failure. } // SMBus Start Check // Return: Success = 0 // Failure = 1 Method(STRT,0,Serialized) { // Wait up to 200ms to confirm the SMBus Semaphore has been // released (In Use Status = 0). Note that the Sleep time may take // longer as the This function will yield the Processor such that it // may perform different tasks during the delay. Store(200,Local0) // 200 * 1ms = 200ms. While(Local0) { If(And(HSTS,0x40)) // In Use Set? { Decrement(Local0) // Yes. Decrement Count. Sleep(1) // Delay = 1ms. If(LEqual(Local0,0)) // Count = 0? { Return(1) // Return failure. } } Else { Store(0,Local0) // In Use Clear. Continue. } } // In Use Status = 0 during last read, which will make subsequent // reads return In Use Status = 1 until software clears it. All // software using ICHx SMBus should check this bit before initiating // any SMBus communication. // Wait up to 200ms to confirm the Host Interface is // not processing a command. Store(4000,Local0) // 4000 * 50us = 200ms. While(Local0) { If(And(HSTS,0x01)) // Host Busy Set? { Decrement(Local0) // Decrement Count. Stall(50) // Delay = 50us. If(LEqual(Local0,0)) // Count = 0? { KILL() // Yes. Kill Communication. } } Else { Return(0) } } Return(1) // Timeout. Return failure. } // SMBus Completion Check // Return: Success = 1 // Failure = 0 Method(COMP,0,Serialized) { // Wait for up to 200ms for the Completion Command // Status to get set. Store(4000,Local0) // 4000 * 50us = 200ms. While(Local0) { If(And(HSTS,0x02)) // Completion Status Set? { Return(1) // Yes. We are done. } Else { Decrement(Local0) // Decrement Count. Stall(50) // Delay 50us. If(LEqual(Local0,0)) // Count = 0? { KILL() // Yes. Kill Communication. } } } Return(0) // Timeout. Return Failure. } // SMBus Kill Command Method(KILL,0,Serialized) { Or(HCON,0x02,HCON) // Yes. Send Kill command. Or(HSTS,0xFF,HSTS) // Clear all status. }