OperationRegion(ICM7, SystemMemory, 0xA112C000, 256)
Field(ICM7, DWordAcc, NoLock, Preserve) //Field
{
ICN7, 32, // R_IC_CON (I2C Control)
Offset(0x04),
TAR7, 32, // R_IC_TAR (I2C Target Address)
Offset(0x08),
SAR7, 32, // R_IC_SAR (I2C Slave Address) *
Offset(0x0C),
HMD7, 32, // R_IC_HS_MADDR (I2C HS MasterMode Code Address) *
Offset(0x10),
DCD7, 32, // R_IC_DATA_CMD (I2C Rx/Tx Data Buffer and Command)
Offset(0x14),
SSH7, 32, // R_IC_SS_SCL_HCNT (Standard Speed I2C Clock SCL High Count) *
Offset(0x18),
SSL7, 32, // R_IC_SS_SCL_LCNT (Standard Speed I2C Clock SCL Low Count) *
Offset(0x1C),
FSH7, 32, // R_IC_FS_SCL_HCNT (Full Speed I2C Clock SCL High Count) *
Offset(0x20),
FSL7, 32, // R_IC_FS_SCL_LCNT (Full Speed I2C Clock SCL Low Count) *
Offset(0x24),
HSH7, 32, // R_IC_HS_SCL_HCNT (High Speed I2C Clock SCL High Count) *
Offset(0x28),
HSL7, 32, // R_IC_HS_SCL_LCNT (High Speed I2C Clock SCL Low Count) *
Offset(0x2C),
ITS7, 32, // R_IC_INTR_STAT (I2C Inetrrupt Status) *
Offset(0x30),
ITM7, 32, // R_IC_INTR_MASK (I2C Interrupt Mask)
Offset(0x34),
RIS7, 32, // R_IC_RAW_INTR_STAT (I2C Raw Interrupt Status)
Offset(0x38),
IRT7, 32, // R_IC_RX_TL (I2C Receive FIFO Threshold)
Offset(0x3C),
ITT7, 32, // R_IC_TX_TL (I2C Transmit FIFO Threshold)
Offset(0x40),
CIT7, 32, // R_IC_CLR_INTR (Clear Combined and Individual Interrupts)
Offset(0x44),
CRU7, 32, // R_IC_CLR_RX_UNDER (Clear RX_UNDER Interrupt) *
Offset(0x48),
CRO7, 32, // R_IC_CLR_RX_OVER (Clear RX_OVERinterrupt) *
Offset(0x4C),
CTO7, 32, // R_IC_CLR_TX_OVER (Clear TX_OVER interrupt) *
Offset(0x50),
CRR7, 32, // R_IC_CLR_RD_REQ (Clear RD_REQ interrupt) *
Offset(0x54),
CTA7, 32, // R_IC_CLR_TX_ABRT (Clear TX_ABRT interrupt)
Offset(0x58),
CRD7, 32, // R_IC_CLR_RX_DONE (Clear RX_DONE interrupt) *
Offset(0x5C),
CAT7, 32, // R_IC_CLR_ACTIVITY (Clear ACTIVITY interrupt) *
Offset(0x60),
CSD7, 32, // R_IC_CLR_STOP_DET (Clear STOP_DET interrupt) *
Offset(0x64),
SAD7, 32, // R_IC_CLR_START_DET (Clear START_DET interrupt) *
Offset(0x68),
CGC7, 32, // R_IC_CLR_GEN_CALL (Clear GEN_CALL interrupt) *
Offset(0x6C),
IEN7, 32, // R_IC_ENABLE (I2C Enable)
Offset(0x70),
IST7, 32, // R_IC_STATUS (I2C Status)
Offset(0x74),
TFL7, 32, // R_IC_TXFLR (Transmit FIFO Level Register)
Offset(0x78),
RFL7, 32, // R_IC_RXFLR (Receive FIFO Level Register)
Offset(0x80),
TAS7, 32, // R_IC_TX_ABRT_SOURCE (I2C Transmit Abort Status Register)
Offset(0x84),
SDN7, 32, // R_IC_SLV_DATA_NACK_ONLY (Generate SLV_DATA_NACK Register) *
Offset(0x88),
DCR7, 32, // R_IC_DMA_CR (DMA Control Register) *
Offset(0x8C),
DTL7, 32, // R_IC_DMA_TDLR (DMA Transmit Data Level) *
Offset(0x90),
DRL7, 32, // R_IC_DMA_RDLR (DMA Receive Data Level) *
Offset(0x94),
SST7, 32, // R_IC_SDA_SETUP (I2C SDA Setup Register) *
Offset(0x98),
AGC7, 32, // R_IC_ACK_GENERAL_CALL (I2C ACK General Call Register) *
Offset(0x9C),
ETS7, 32, // R_IC_ENABLE_STATUS (I2C Enable Status Register) *
Offset(0xC0),
CGT7, 32, // R_IC_CLK_GATE (Clock Gate)
Offset(0xF4),
CPP7, 32, // R_IC_COMP_PARAM (Component Parameter Register) *
Offset(0xF8),
CPV7, 32, // R_IC_COMP_VERSION (Component Version ID) *
Offset(0xFC),
CPT7, 32, // R_IC_COMP_TYPE (Component Type) *
}
// ------------------------------------------------------------------------------------
// *********************I2C R/W Registers and Definition*******************************
// ------------------------------------------------------------------------------------
Name(RDST, 0) // RDST 是通用的 Read 回傳 Status
Name(RDDT, 0) // RDDT 是 I2C READ Data 暫存
Name(RRRS, 0) // ByteWrite_Basic 專用 POST Code
Name(RRRT, 0) // ByteRead_Basic 專用 POST Code
// ------------------------------------------------------------------------------------
// ******************Method (IWBB) Debug POST Code Example*****************************
// ------------------------------------------------------------------------------------
// *************************
// ShiftLeft (0x01, 0, Local7)
// Or (RRRS, Local7, RRRS)
// *************************
// ------------------------------------------------------------------------------------
// ******************Method (IRBB) Debug POST Code Example*****************************
// ------------------------------------------------------------------------------------
// *************************
// ShiftLeft (0x01, 1, Local7)
// Or (RRRT, Local7, RRRT)
// *************************
// ------------------------------------------------------------------------------------
// ***************************ByteReadI2C**********************************************
// ------------------------------------------------------------------------------------
Method (IRBC, 1)
{
// 1. 呼叫一次 IWBB, 主要功能為將 Offset 寫入 I2C Command
// arg0 = "Offset"
// START = It controls whether a RESTART is issued before the byte is sent or received
// END = It controls whether a STOP is issued after the byte is sent or received.
IWBB (arg0, TRUE, FALSE)
// 2. RDST 是 IWBB 的返回值
Store(RDST, Local0)
if(LNotEqual(Local0, 0x0))
{
Return(RDST)
}
// 3. 如果抵達此處, 則代表返回值為 0
IRBB(TRUE, TRUE)
// 以下是 I2C READ 的 Workaround-----------------------------
// 因為 Method (IRBB) 應該修好了, 所以不需要再用此 Workaround
// 但為了保險起見還是留著
//-----------------------------------------------------------
Return(RDST)
}
// ------------------------------------------------------------------------------------
// ***************************ByteReadI2C_Basic****************************************
// ------------------------------------------------------------------------------------
Method (IRBB, 2, NotSerialized)
{
// Return Status = SUCCESS
Store(0, RDST)
// 0. 因為 I2CBaseAddress 固定, 所以不需要維護
// 1. I2CInit 應該也不需要做事
// 2. arg0 = START (TRUE/FALSE), arg1 = END (TRUE/FALSE), RDDT 內含 Read Data
// ReceiveDataEnd = 1 (固定值)
// ReceiveRequest = Local0 = 初始值為 0, 區間應為 0~1
// ReadBuffer = Local1 = 初始值為 0, 區間應為 0~1
// Counter = Local2 = 初始值為 0, 區間應為 0~1024
// 檢查 Reg 專用 = Local3 = 初始值為 0
// 檢查 Reg 專用 = Local4 = 初始值為 0
// while ((ReceiveDataEnd > ReceiveRequest) || (ReceiveDataEnd > ReadBuffer))
Store (0x0, Local0)
Store (0x0, Local1)
Store (0x0, Local2)
Store (0x0, Local3)
Store (0x0, Local4)
While(LOr(LGreater(0x01, Local0), LGreater(0x01, Local1)))
{
// 1. 讀取 R_IC_RAW_INTR_STAT (Local3), RIS7 = R_IC_RAW_INTR_STAT (I2C Raw Interrupt Status)
// 如果 Local1 = R_IC_RAW_INTR_STAT == ERROR, Return with ERROR
// 0x40 = BIT06 = I2C_INTR_TX_ABRT = NACK Set
Store (RIS7, Local3)
If (LNotEqual(And(Local1, 0x40), 0))
{
// Before EXIT, READ R_IC_CLR_TX_ABRT
// CTA7 = R_IC_CLR_TX_ABRT (Clear TX_ABRT interrupt)
Store (CTA7, Local3)
Store(0xFE, RDST) // 0xFE = R_IC_RAW_INTR_STAT and I2C_INTR_TX_ABRT, ERROR
Return(RDST)
}
// 2. 讀取 R_IC_STATUS, IST7 = R_IC_STATUS (I2C Status) = Local3
// If R_IC_STATUS == Not Empty, we will READ DATA
// STAT_RFNE = BIT03 (0x08) = RX FIFO is not empty
// if FIFO is not empty, 代表可讀資料了
// DCD7 = R_IC_DATA_CMD (I2C Rx/Tx Data Buffer and Command)
Store (IST7, Local3)
If (LNotEqual(And(Local3, 0x08, Local3), 0))
{
// RDDT = READ DATA
Store (DCD7, Local3)
Store (Local3, RDDT)
// ReadBuffer = Local1, ReadBuffer ++
Increment(Local1)
}
// 3. ReceiveDataEnd = 1, ReceiveRequest = Local0
// 首次進入, 不會跑入此條件, 因為ReceiveRequest 此時指向 Data
// 第二次進入, 代表 ReceiveRequest 已經加過一次 1, 已經指向 EOF, 我們會到此的唯一可能就是首次進入時 FIFO is empty, 所以 ReadBuffer ++ 沒發生
// 此處之所以需要等待 2028 毫秒, 是因為 FIFO empty 的情況情實很少見
If (LEqual(0x01, Local0))
{
Stall (2)
Increment(Local2)
If (LLess(Local2, 1024))
{
Continue
}
else
{
Break
}
}
// 4. If FIFO is full, Wait until a read request will fit
// STAT_TFNF = BIT1 = TX FIFO = 0x02 is not full, 0 = FULL
Store (IST7, Local3)
If (LEqual(And(Local3, 0x02), 0))
{
Stall (10)
Continue
}
// 5. 這裡是重要的指令分歧點
// START = TRUE, END = TRUE, 第一個 if, 在 R_IC_DATA_CMD 直接寫入 READ + RESTART + STOP
// START = TRUE, END = FALSE, 第二個 if, 在 R_IC_DATA_CMD 直接寫入 READ + RESTART
// START = FALSE, END = TRUE, 第一個 if, 在 R_IC_DATA_CMD 直接寫入 READ + STOP
// START = FALSE, END = FALSE, 第一個 if, 在 R_IC_DATA_CMD 直接寫入 READ (通常沒人用這個)
// (Read Command = B_READ_CMD = BIT08 = 0x0100) 寫入 Local3
Store (0x0100, Local3)
// arg0 = START, arg1 = END
If (LEqual(arg0, TRUE))
{
If (LEqual(arg1, TRUE))
{
// Local0|B_CMD_RESTART|B_CMD_STOP, BIT09+BIT10
Or (Local3, 0x0600, Local3)
}
else
{
// Local0|B_CMD_RESTART, BIT10
Or (Local3, 0x0400, Local3)
}
}
else
{
If (LEqual(arg1, TRUE))
{
// Local0|B_CMD_STOP, BIT09
Or (Local3, 0x0200, Local3)
}
else
{
// Local3, Do nothing
}
}
// 將 (Read Command + 各種 MASK) 寫入 Command
Store(Local3 ,DCD7)
// 6. Wait after send cmd
Stall (2)
// 7. 累加 ReceiveRequest
Increment(Local0)
}
Return(RDST)
}
// ------------------------------------------------------------------------------------
// ***************************ByteWriteI2C*********************************************
// ------------------------------------------------------------------------------------
// AKA: ByteWriteI2C
Method (IWBC, 2, NotSerialized)
{
// 1. 呼叫一次 IWBB, 主要功能為將 Offset 寫入 I2C Command
// arg0 = "Offset to be Written"
// arg1 = "Data to be Written"
// START = It controls whether a RESTART is issued before the byte is sent or received
// END = It controls whether a STOP is issued after the byte is sent or received.
IWBB(arg0, TRUE, FALSE)
// 2. RDST 是 IWBB 的返回值
Store(RDST, Local0)
if(LNotEqual(Local0, 0x0))
{
Return(RDST)
}
// 3. 如果抵達此處, 則代表返回值為 0
IWBB(arg1, FALSE, TRUE)
Return(RDST)
}
// ------------------------------------------------------------------------------------
// ***************************ByteWriteI2C_Basic***************************************
// ------------------------------------------------------------------------------------
// arg0 = "Offset" or "Data to be Written"
// arg1 = It controls whether a RESTART is issued before the byte is sent or received
// arg2 = It controls whether a STOP is issued after the byte is sent or received.
// 0xFE = R_IC_RAW_INTR_STAT and I2C_INTR_TX_ABRT, ERROR
// 0xFD = R_IC_STATUS and STAT_TFNF, ERROR
// 0xFC = EFI_TIMEOUT
Method (IWBB, 3, NotSerialized)
{
// 0. 初始化 RDST, 做為回傳值-------------------------------------------------------------------------
Store(0xFF, RDST) // Set the status to FAIL
// 1. 這個是 (I2CInit) -------------------------------------------------------------------------------
// 將 SlaveAddress 寫到 IC_TAR
Store (0x46, TAR7)
// 2. 用 While 重覆跑前段的檢查 ----------------------------------------------------------------------
// Local5 = TransmitEnd
// Local6 = WriteBuffer
Store (1, Local5)
Store (0, Local6)
While(LGreater(Local5, Local6))
{
// 1. 讀取 R_IC_STATUS, IST7 = R_IC_STATUS (I2C Status)
Store (IST7, Local0)
// 2. 讀取 R_IC_RAW_INTR_STAT (Local1), RIS7 = R_IC_RAW_INTR_STAT (I2C Raw Interrupt Status)
Store (RIS7, Local1)
// 3. 如果 Local1 = R_IC_RAW_INTR_STAT == ERROR, Return with ERROR
// 0x40 = BIT06 = I2C_INTR_TX_ABRT = NACK Set
If (LNotEqual(And(Local1, 0x40), 0))
{
// Before EXIT, READ R_IC_CLR_TX_ABRT
// CTA7 = R_IC_CLR_TX_ABRT (Clear TX_ABRT interrupt)
Store (CTA7, Local1)
Store(0xFE, RDST) // 0xFE = R_IC_RAW_INTR_STAT and I2C_INTR_TX_ABRT, ERROR
Return(RDST)
}
// 4. If R_IC_STATUS == ERROR, Delay and Retry
// STAT_TFNF = BIT1 = 0x02
If (LEqual(And(Local0, 0x02), 0))
{
//FIFO_WRITE_DELAY = 0x02
Stall (0x02)
Store(0xFD, RDST) // 0xFD = R_IC_STATUS and STAT_TFNF, ERROR
Continue
}
// 這裡是重要的指令分歧點 -------------------------------------------
// 前導指令 (Read/Write) START = TRUE, END = FALSE, 第二個 if, 在 R_IC_DATA_CMD 直接寫入 RESTART
// 後續指令 (Read) START = TRUE, END = TRUE, 第一個 if, 在 R_IC_DATA_CMD 直接寫入 RESTART + STOP
// 後續指令 (Write) START = FALSE, END = TRUE, 第一個 if, 在 R_IC_DATA_CMD 直接寫入 STOP
// (Offset or Data) 寫入 Local0
Store (arg0, Local0)
// arg1 = START, arg2 = END
If (LEqual(arg1, TRUE))
{
If (LEqual(arg2, TRUE))
{
// Local0|B_CMD_RESTART|B_CMD_STOP, BIT09+BIT10
Or (Local0, 0x0600, Local0)
Increment (Local6)
}
else
{
// Local0|B_CMD_RESTART, BIT10
Or (Local0, 0x0400, Local0)
Increment (Local6)
}
}
else
{
If (LEqual(arg2, TRUE))
{
// Local0|B_CMD_STOP, BIT09
Or (Local0, 0x0200, Local0)
Increment (Local6)
}
else
{
// Local0, Do nothing
Increment (Local6)
}
}
// 將 (Offset or Data) 寫入 Command
Store(Local0 ,DCD7)
// Delay
Stall (2)
// ---------------------------------------------------------
// Local2 做為 Counter 初始化
Store(0,Local2)
While(TRUE)
{
// 1. 讀取 R_IC_RAW_INTR_STAT (Local1), RIS7 = R_IC_RAW_INTR_STAT (I2C Raw Interrupt Status)
Store (RIS7, Local1)
// 2. 如果 Local1 = R_IC_RAW_INTR_STAT == ERROR, Return with ERROR
// 0x40 = BIT06 = I2C_INTR_TX_ABRT = NACK Set
If (LNotEqual(And(Local1, 0x40), 0))
{
// Before EXIT, READ R_IC_CLR_TX_ABRT
// CTA7 = R_IC_CLR_TX_ABRT (Clear TX_ABRT interrupt)
Store (CTA7, Local1)
Store(0xFE, RDST) // 0xFE = R_IC_RAW_INTR_STAT and I2C_INTR_TX_ABRT, ERROR
}
// 3. 如果 Local1 = R_IC_TXFLR == 0, 則 Break
// TFL7 = R_IC_TXFLR (Transmit FIFO Level Register)
Store (TFL7, Local1)
If (LEqual(Local1, 0x0))
{
Store(0x00, RDST)
Break
}
// 4. Delay
Stall (2)
// 5. Timeout Test
Increment(Local2)
If(LLess(Local2, 1024))
{
Continue
}
else
{
Store(0xFC, RDST) // 0xFC = EFI_TIMEOUT
Break
}
}
}
// Return SUCCESS
Store(0x00, RDST)
Return(RDST)
}
讚
ReplyDelete