Maxim Polyakov has uploaded this change for review.

View Change

soc/intel/apl: Add ACPI for SBMBUS control

Based on acpidump from AMI firmware on the Kontron mAL10 COMe module
and SMBus Control Methods Interface Specification, Ver 1.0, 1999.

Signed-off-by: Maxim Polyakov <max.senia.poliak@gmail.com>
Change-Id: I3846266d3155bbe831123fef4751748ff0e00511
---
A src/soc/intel/apollolake/acpi/smbus.asl
M src/soc/intel/apollolake/acpi/southbridge.asl
2 files changed, 795 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/07/44507/1
diff --git a/src/soc/intel/apollolake/acpi/smbus.asl b/src/soc/intel/apollolake/acpi/smbus.asl
new file mode 100644
index 0000000..b41c0f2
--- /dev/null
+++ b/src/soc/intel/apollolake/acpi/smbus.asl
@@ -0,0 +1,792 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Device (SBUS)
+{
+ /* Intel SMBus Controller 0:1f.1 */
+ Name (_ADR, 0x001F0001)
+
+ OperationRegion (SMBP, PCI_Config, 0x40, 0xC0)
+ Field (SMBP, DWordAcc, NoLock, Preserve)
+ {
+ , 2,
+ I2CE, 1
+ }
+
+ OperationRegion (SMPB, PCI_Config, 0x20, 0x04)
+ Field (SMPB, DWordAcc, NoLock, Preserve)
+ {
+ , 5,
+ SBAR, 11
+ }
+
+ OperationRegion (SMBI, SystemIO, (SBAR << 0x05), 0x10)
+ Field (SMBI, ByteAcc, NoLock, Preserve)
+ {
+ HSTS, 8, // Host Status
+ Offset (0x02),
+ HCON, 8, // Host Control
+ HCOM, 8, // Host Command
+ TXSA, 8, // Transmit Slave Address
+ DAT0, 8, // Host Data 0
+ DAT1, 8, // Host Data 1
+ HBDR, 8, // Host Block Data Byte
+ PECR, 8, // Packet Error Check
+ RXSA, 8, // Receive Slave Data
+ SDAT, 16
+ }
+
+ // SMBus Send Byte
+ // Arg0: Address
+ // Arg1: Data
+ // Return: 1 = Success, 0=Failure
+ Method (SSXB, 2, Serialized)
+ {
+ If (STRT ())
+ { // Is the SMBus Controller Ready?
+ Return (Zero)
+ }
+
+ // Send Byte
+ // SMBus Enable
+ I2CE = Zero
+ HSTS = 0xBF
+ TXSA = Arg0 // Write Address
+ HCOM = Arg1 // Write Data
+ HCON = 0x48 // Start + Byte Data Protocol
+ If (COMP ())
+ {
+ HSTS |= 0xFF // Clean up
+ Return (One) // Success
+ }
+
+ Return (Zero)
+ }
+
+ // SMBus Receive Byte
+ // Arg0: Address
+ // Return: 0xffff = Failure, Data (8bit) = Success
+ Method (SRXB, 1, Serialized)
+ {
+ // Is the SMBus Controller Ready?
+ If (STRT ())
+ {
+ Return (0xFFFF)
+ }
+
+ // Receive Byte
+ I2CE = Zero // SMBus Enable
+ HSTS = 0xBF
+ TXSA = (Arg0 | One) // Write Address
+ HCON = 0x44
+ If (COMP ())
+ {
+ HSTS |= 0xFF // Clean up
+ Return (DAT0) // Success
+ }
+
+ Return (0xFFFF)
+ }
+
+ // SMBus Write Byte
+ // Arg0: Address
+ // Arg1: Command
+ // Arg2: Data
+ // Return: 1 = Success, 0=Failure
+ Method (SWRB, 3, Serialized)
+ {
+ If (STRT ())
+ { // Is the SMBus Controller Ready?
+ Return (Zero)
+ }
+
+ I2CE = Zero // SMBus Enable
+ HSTS = 0xBF
+ TXSA = Arg0 // Write Address
+ HCOM = Arg1 // Write Command
+ DAT0 = Arg2 // Write Data
+ HCON = 0x48 // Start + Byte Protocol
+ If (COMP ())
+ {
+ HSTS |= 0xFF // Clean up
+ Return (One) // Success
+ }
+
+ Return (Zero)
+ }
+
+ // SMBus Read Byte
+ // Arg0: Address
+ // Arg1: Command
+ // Return: 0xffff = Failure, Data (8bit) = Success
+ Method (SRDB, 2, Serialized)
+ {
+ If (STRT ())
+ { // Is the SMBus Controller Ready?
+ Return (0xFFFF)
+ }
+
+ I2CE = Zero // SMBus Enable
+ HSTS = 0xBF
+ // Write Address
+ TXSA = (Arg0 | One)
+ HCOM = Arg1 // Command
+ HCON = 0x48 // Start
+ If (COMP ())
+ {
+ HSTS |= 0xFF // Clean up
+ Return (DAT0) // Success
+ }
+
+ Return (0xFFFF)
+ }
+
+ // SWRW - write word
+ // Arg0: Address
+ // Arg1: Command
+ // Arg2: Data
+ // Return: 0 on failure, 1, on success
+ Method (SWRW, 3, Serialized)
+ {
+ If (STRT ())
+ {
+ Return (Zero)
+ }
+
+ I2CE = Zero
+ HSTS = 0xBF
+ TXSA = Arg0
+ HCOM = Arg1
+ DAT1 = (Arg2 & 0xFF)
+ DAT0 = ((Arg2 >> 0x08) & 0xFF)
+ HCON = 0x4C
+ If (COMP ())
+ {
+ HSTS |= 0xFF
+ Return (One)
+ }
+
+ Return (Zero)
+ }
+
+ // SRDW - read word
+ // Arg0: Address
+ // Arg1: Command
+ // Return: 0xffffffff on failure, the read word otherwise
+ Method (SRDW, 2, Serialized)
+ {
+ If (STRT ())
+ {
+ Return (0xFFFF)
+ }
+
+ I2CE = Zero
+ HSTS = 0xBF
+ TXSA = (Arg0 | One)
+ HCOM = Arg1
+ HCON = 0x4C
+ If (COMP ())
+ {
+ HSTS |= 0xFF
+ Return (((DAT0 << 0x08) | DAT1))
+ }
+
+ Return (0xFFFFFFFF)
+ }
+
+ // SBLW - write block data
+ // Arg0: Address
+ // Arg1: Command
+ // Arg2: Data - data[0] is the number of bytes that follow
+ // Return: 0 on failure, 1, on success
+ Method (SBLW, 4, Serialized)
+ {
+ If (STRT ())
+ {
+ Return (Zero)
+ }
+
+ I2CE = Arg3
+ HSTS = 0xBF
+ TXSA = Arg0
+ HCOM = Arg1
+ DAT0 = SizeOf (Arg2)
+ Local1 = Zero
+ HBDR = DerefOf (Arg2 [Zero])
+ HCON = 0x54
+ While ((SizeOf (Arg2) > Local1))
+ {
+ Local0 = 0x0FA0
+ While ((!(HSTS & 0x80) && Local0))
+ {
+ Local0--
+ Stall (0x32)
+ }
+
+ If (!Local0)
+ {
+ KILL ()
+ Return (Zero)
+ }
+
+ HSTS = 0x80
+ Local1++
+ If ((SizeOf (Arg2) > Local1))
+ {
+ HBDR = DerefOf (Arg2 [Local1])
+ }
+ }
+
+ If (COMP ())
+ {
+ HSTS |= 0xFF
+ Return (One)
+ }
+
+ Return (Zero)
+ }
+
+ // SBLR - read block data
+ // Arg0: Address
+ // Arg1: Command
+ // Return: 0 on failure, the read data otherwise
+ Method (SBLR, 3, Serialized)
+ {
+ Name (TBUF, Buffer (0x0100){})
+ If (STRT ())
+ {
+ Return (Zero)
+ }
+
+ I2CE = Arg2
+ HSTS = 0xBF
+ TXSA = (Arg0 | One)
+ HCOM = Arg1
+ HCON = 0x54
+ Local0 = 0x0FA0
+ While ((!(HSTS & 0x80) && Local0))
+ {
+ Local0--
+ Stall (0x32)
+ }
+
+ If (!Local0)
+ {
+ KILL ()
+ Return (Zero)
+ }
+
+ TBUF [Zero] = DAT0 /* \_SB_.PCI0.SBUS.DAT0 */
+ HSTS = 0x80
+ Local1 = One
+ While ((Local1 < DerefOf (TBUF [Zero])))
+ {
+ Local0 = 0x0FA0
+ While ((!(HSTS & 0x80) && Local0))
+ {
+ Local0--
+ Stall (0x32)
+ }
+
+ If (!Local0)
+ {
+ KILL ()
+ Return (Zero)
+ }
+
+ TBUF [Local1] = HBDR /* \_SB_.PCI0.SBUS.HBDR */
+ HSTS = 0x80
+ Local1++
+ }
+
+ If (COMP ())
+ {
+ HSTS |= 0xFF
+ Return (TBUF) /* \_SB_.PCI0.SBUS.SBLR.TBUF */
+ }
+
+ Return (Zero)
+ }
+
+ // Wait for SMBus to become ready
+ Method (STRT, 0, Serialized)
+ {
+ // Timeout 200ms
+ Local0 = 0xC8
+
+ While (Local0)
+ {
+ If ((HSTS & 0x40))
+ { // Is used?
+ // timeout--
+ Local0--
+
+ // Wait 1ms
+ Sleep (One)
+ If ((Local0 == Zero))
+ {
+ Return (One)
+ }
+ }
+ Else
+ {
+ // We're ready
+ Local0 = Zero
+ }
+ }
+
+ // Timeout 200ms (50us * 4000)
+ Local0 = 0x0FA0
+ While (Local0)
+ {
+ If ((HSTS & One))
+ { // Is the host busy?
+ // timeout--
+ Local0--
+
+ // Wait 50us
+ Stall (0x32)
+
+ If ((Local0 == Zero))
+ {
+ KILL ()
+ }
+ }
+ Else
+ { // Success
+ Return (Zero)
+ }
+ }
+ // Failure
+ Return (One)
+ }
+
+ // Check if last operation completed
+ // return Failure = 0, Success = 1
+ Method (COMP, 0, Serialized)
+ {
+ Local0 = 0x0FA0 // Timeout 200ms in 50us steps
+ While (Local0)
+ {
+ If ((HSTS & 0x02))
+ { // Completion Status?
+ // Operation Completed
+ Return (One)
+ }
+ Else
+ {
+ Local0--
+ Stall (0x32)
+ If ((Local0 == Zero))
+ {
+ KILL ()
+ }
+ }
+ }
+ Return (Zero) // Failure
+ }
+
+ // Kill all SMBus communication
+ Method (KILL, 0, Serialized)
+ {
+ HCON |= 0x02 // Send Kill
+ HSTS |= 0xFF // Clean Status
+ }
+
+ // SMBus transactional synchronization
+ Mutex (SBX0, 0x00)
+
+ OperationRegion (SBU0, SystemIO, (SBAR << 0x05), 0x10)
+ Field (SBU0, ByteAcc, NoLock, Preserve)
+ {
+ HSTA, 8,
+ Offset (0x02),
+ HCNT, 8,
+ HCMD, 8,
+ HADD, 8,
+ HDT0, 8,
+ HDT1, 8,
+ BLKD, 8,
+ Offset (0x0D),
+ AUCT, 8
+ }
+
+ // SWTC - Wait for Transaction Complete
+ // Wait until the previous SMBus transaction has completed
+ // Arg0 : Timeout Value
+ // return
+ // 0x00 : OK
+ // 0x07 : Unknown Failure
+ // 0x10 : Address Not Acknowledged
+ // 0x11 : Device Error
+ // 0x12 : Command Access Denied
+ // 0x13 : Unknown Error
+ // 0x17 : Device Access Denied
+ // 0x18 : Timeout
+ // 0x19 : Unsupported Protocol
+ // 0x1A : Bus Busy
+ // 0x1F : PEC (CRC-8) Error
+ Method (SWTC, 1, NotSerialized)
+ {
+ Local0 = Arg0
+ Local2 = 0x07
+ // The previous command has completed when the protocol
+ // register is equal to 0 (zero). Wait <timeout> ms
+ // for this to occur.
+ Local1 = One
+ While ((Local1 == One))
+ {
+ Local3 = (HSTA & 0x1E)
+ If ((Local3 != Zero))
+ {
+ If ((Local3 == 0x02))
+ {
+ Local2 = Zero
+ }
+ Else
+ {
+ Local2 = 0x07
+ }
+
+ Local1 = Zero
+ }
+ // Transaction isn't complete. Check for timeout, and if not,
+ // sleep 10ms and loop again.
+ ElseIf ((Local0 < 0x0A))
+ {
+ Local2 = 0x18 // ERROR: Timeout occurred.
+ Local1 = Zero // Terminate loop.
+ }
+ Else
+ {
+ Sleep (0x0A)
+ Local0 -= 0x0A
+ }
+ }
+ Return (Local2)
+ }
+
+ // SBR - SMBus Read
+ // Arg0 : Protocol (Integer)
+ // Arg1 : Slave Address (Integer)
+ // Arg2 : Command (Integer)
+ // return
+ // (0) : Status (Integer)
+ // (1) : Data Length (Integer)
+ // (2) : Data (Integer | Buffer)
+ Method (SBR, 3, Serialized)
+ {
+ I2CE = Zero
+ Local0 = Package (0x12)
+ {
+ 0x07,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero,
+ Zero
+ }
+
+ // Make sure the protocol is valid, if not return the
+ // 'invalid protocol' status code. Note that this segment
+ // does not support packet error checking.
+ If ((Arg0 != 0x03))
+ { // Read Quick
+ If ((Arg0 != 0x05))
+ { // Receive Byte
+ If ((Arg0 != 0x07))
+ { // Read Byte
+ If ((Arg0 != 0x09))
+ { // Read Word
+ If ((Arg0 != 0x0B))
+ { // Read Block
+ Local0 [Zero] = 0x19
+ Return (Local0)
+ }
+ }
+ }
+ }
+ }
+
+ // Acquire the SMBus mutex to ensure transactional synchronization.
+ If ((Acquire (SBX0, 0xFFFF) == Zero))
+ {
+ // Initiate the transaction by writing the slave address,
+ // command, and protocol registers. Note that the command
+ // code and data length are always written, even if the
+ // protocol doesn't require it (it
+ // will be ignored).
+ HSTA = (HSTA | 0xFF)
+ HADD = (Arg1 | One)
+ HCMD = Arg2
+ If ((Arg0 == 0x03))
+ { // Read Quick
+ HCNT = ((HCNT & 0xA0) | 0x40)
+ }
+
+ If ((Arg0 == 0x05))
+ { // Receive Byte
+ HCNT = ((HCNT & 0xA0) | 0x44)
+ }
+
+ If ((Arg0 == 0x07))
+ { // Read Byte
+ HCNT = ((HCNT & 0xA0) | 0x48)
+ }
+
+ If ((Arg0 == 0x09))
+ { // Read Word
+ HCNT = ((HCNT & 0xA0) | 0x4C)
+ }
+
+ If ((Arg0 == 0x0B))
+ { // Read Block
+ AUCT &= 0xFD
+ HCNT = ((HCNT & 0xA0) | 0x54)
+ Local1 = Zero
+ }
+ Else
+ {
+ // Wait for completion
+ Local1 = SWTC (0x03E8)
+ }
+
+ // Save the status code, data size, and data into the return
+ // package (if required by the protocol).
+ Local0 [Zero] = Local1
+ If ((Local1 == Zero))
+ {
+ If ((Arg0 == 0x05))
+ { // Receive Byte
+ Local0 [One] = One
+ Local0 [0x02] = HDT0
+ }
+
+ If ((Arg0 == 0x07))
+ { // Read Byte
+ Local0 [One] = One
+ Local0 [0x02] = HDT0
+ }
+
+ If ((Arg0 == 0x09))
+ { // Read Word
+ Local0 [One] = 0x02
+ Local2 = HDT1
+ Local2 <<= 0x08
+ Local2 += HDT0
+ Local0 [0x02] = Local2
+ }
+
+ If ((Arg0 == 0x0B))
+ { // Read Block
+ Local0 [Zero] = 0x07
+ Local4 = 0x9C40
+ While ((!(HSTA & 0x80) && Local4))
+ {
+ Local4--
+ Stall (0x32)
+ }
+
+ If (!Local4)
+ {
+ HCNT |= 0x02
+ HSTA |= 0xFF
+ Local0 [Zero] = 0x17
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ Local0 [Zero] = Zero
+ Local2 = HDT0
+ If ((Local2 > 0x10))
+ {
+ Local2 = 0x10
+ }
+
+ Local0 [One] = Local2
+ Local0 [0x02] = BLKD
+ Local3 = 0x03
+ HSTA = 0x80
+ While ((Local3 < (Local2 + 0x02)))
+ {
+ Local4 = 0x9C40
+ While ((!(HSTA & 0x80) && Local4))
+ {
+ Local4--
+ Stall (0x32)
+ }
+
+ If (!Local4)
+ {
+ HCNT |= 0x02
+ HSTA |= 0xFF
+ Local0 [Zero] = 0x18
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ Local0 [Local3] = BLKD
+ HSTA = 0x80
+ Local3++
+ }
+ }
+ }
+
+ Release (SBX0)
+ }
+
+ Return (Local0)
+ }
+
+ // _SBW - SMBus Write
+ //
+ // Arg0 : Protocol Value (Integer)
+ // Arg1 : Slave Address (Integer)
+ // Arg2 : Command Code (Integer)
+ // Arg3 : Data Length (Integer)
+ // Arg4 : Data (Integer | Buffer)
+ //
+ // return Value (Package):
+ // (0) : Status (Integer)
+ Method (SBW, 5, Serialized)
+ {
+ I2CE = Zero
+ // Local0 is the return package. The status code is defaulted
+ // to 'unknown failure' (0x07).
+ Local0 = Package (0x01)
+ {
+ 0x07
+ }
+
+ // Make sure the protocol is valid, if not return the
+ // 'invalid protocol' status code. Note that this segment
+ // does not support packet error checking or the 'process call'
+ // protocol.
+ If ((Arg0 != 0x02))
+ { // Write Quick
+ If ((Arg0 != 0x04))
+ { // Send Byte
+ If ((Arg0 != 0x06))
+ { // Write Byte
+ If ((Arg0 != 0x08))
+ { // Write Word
+ If ((Arg0 != 0x0A))
+ { // Write Block
+ Local0 [Zero] = 0x19
+ Return (Local0)
+ }
+ }
+ }
+ }
+ }
+
+ // Acquire the SMBus mutex to ensure transactional synchronization.
+ If ((Acquire (SBX0, 0xFFFF) == Zero))
+ {
+ HSTA = (HSTA | 0xFF)
+ HADD = (Arg1 & 0xFE)
+ HCMD = Arg2
+ If ((Arg0 == 0x02))
+ { // Write Quick
+ HCNT = ((HCNT & 0xA0) | 0x40)
+ }
+
+ If ((Arg0 == 0x04))
+ { // Send Byte
+ HCNT = ((HCNT & 0xA0) | 0x44)
+ }
+
+ If ((Arg0 == 0x06))
+ { // Write Byte
+ HDT0 = Arg4
+ HCNT = ((HCNT & 0xA0) | 0x48)
+ }
+
+ If ((Arg0 == 0x08))
+ { // Write Word
+ HDT0 = (Arg4 & 0xFF)
+ HDT1 = (Arg4 >> 0x08)
+ HCNT = ((HCNT & 0xA0) | 0x4C)
+ }
+
+ If ((Arg0 == 0x0A))
+ { // Write Block
+ If ((Arg3 > 0x10))
+ {
+ Local0 [Zero] = 0x12
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ If ((Arg3 == Zero))
+ {
+ Local0 [Zero] = 0x12
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ AUCT &= 0xFD
+ HDT0 = Arg3
+ Local3 = One
+ BLKD = DerefOf (Arg4 [Zero])
+ HCNT = ((HCNT & 0x80) | 0x54)
+ While ((Arg3 > Local3))
+ {
+ Local4 = 0x9C40
+ While ((!(HSTA & 0x80) && Local4))
+ {
+ Local4--
+ Stall (0x32)
+ }
+
+ If (!Local4)
+ {
+ HCNT |= 0x02
+ HSTA |= 0xFF
+ Local0 [Zero] = 0x18
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ BLKD = DerefOf (Arg4 [Local3])
+ Local3++
+ HSTA = 0x80
+ }
+
+ Local4 = 0x9C40
+ While ((!(HSTA & 0x80) && Local4))
+ {
+ Local4--
+ Stall (0x32)
+ }
+
+ If (!Local4)
+ {
+ HCNT |= 0x02
+ HSTA |= 0xFF
+ Local0 [Zero] = 0x18
+ Release (SBX0)
+ Return (Local0)
+ }
+
+ HSTA = 0x80
+ }
+
+ Local0 [Zero] = SWTC (0x03E8)
+ Release (SBX0)
+ }
+
+ Return (Local0)
+ }
+}
diff --git a/src/soc/intel/apollolake/acpi/southbridge.asl b/src/soc/intel/apollolake/acpi/southbridge.asl
index f4d1497..9a5a5ec 100644
--- a/src/soc/intel/apollolake/acpi/southbridge.asl
+++ b/src/soc/intel/apollolake/acpi/southbridge.asl
@@ -20,6 +20,9 @@
/* LPC */
#include <soc/intel/common/block/acpi/acpi/lpc.asl>

+/* SMBus 0:1f.1 */
+#include "smbus.asl"
+
/* eMMC */
#include "scs.asl"


To view, visit change 44507. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I3846266d3155bbe831123fef4751748ff0e00511
Gerrit-Change-Number: 44507
Gerrit-PatchSet: 1
Gerrit-Owner: Maxim Polyakov <max.senia.poliak@gmail.com>
Gerrit-Reviewer: Andrey Petrov <andrey.petrov@gmail.com>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-MessageType: newchange