/**************************************************************************; ;* *; ;* *; ;* Intel Corporation - ACPI Reference Code for the Baytrail *; ;* Family of Customer Reference Boards. *; ;* *; ;* *; ;* Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved *; ; ; This program and the accompanying materials are licensed and made available under ; the terms and conditions of the BSD License that accompanies this distribution. ; The full text of the license may be found at ; http://opensource.org/licenses/bsd-license.php. ; ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; ;* *; ;* *; ;**************************************************************************/ // Define various SMBus PCI Configuration Space Registers. OperationRegion(SMBP,PCI_Config,0x40,0xC0) Field(SMBP,DWordAcc,NoLock,Preserve) { , 2, I2CE, 1 } // 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) { 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 } // 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) { 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 } // 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) { 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 } // 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) { 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 } // 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) { 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 } // 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) { 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 } // 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) { 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 } // 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) { 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 } 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) { 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 } // 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) { 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 } // 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) { 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 } Or(HCON,0x02,HCON) // Yes. Send Kill command. Or(HSTS,0xFF,HSTS) // Clear all status. }