diff --git a/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.c b/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.c new file mode 100644 index 0000000000..377a597646 --- /dev/null +++ b/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.c @@ -0,0 +1,433 @@ +/** @file + I2C Bus implementation upon CirrusLogic. + + Copyright (c) 2008 - 2009, 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 + which 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. + +**/ + +#include "CirrusLogic5430.h" +#include "CirrusLogic5430I2c.h" + +#define SEQ_ADDRESS_REGISTER 0x3c4 +#define SEQ_DATA_REGISTER 0x3c5 + +#define I2C_CONTROL 0x08 +#define I2CDAT_IN 7 +#define I2CCLK_IN 2 +#define I2CDAT_OUT 1 +#define I2CCLK_OUT 0 + +#define I2C_BUS_SPEED 100 //100kbps + +/** + PCI I/O byte write function. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param Address The bit map of I2C Data or I2C Clock pins. + @param Data The date to write. + +**/ +VOID +I2cOutb ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINTN Address, + UINT8 Data + ) +{ + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); +} +/** + PCI I/O byte read function. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param Address The bit map of I2C Data or I2C Clock pins. + + return byte value read from PCI I/O space. + +**/ +UINT8 +I2cInb ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINTN Address + ) +{ + UINT8 Data; + + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); + return Data; +} + +/** + Read status of I2C Data and I2C Clock Pins. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param Blt The bit map of I2C Data or I2C Clock pins. + + @retval 0 Low on I2C Data or I2C Clock Pin. + @retval 1 High on I2C Data or I2C Clock Pin. + +**/ +UINT8 +I2cPinRead ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 Bit + ) +{ + I2cOutb (PciIo, SEQ_ADDRESS_REGISTER, I2C_CONTROL); + return (UINT8) ((I2cInb (PciIo, SEQ_DATA_REGISTER) >> Bit ) & 0xfe); +} + + +/** + Set/Clear I2C Data and I2C Clock Pins. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param Blt The bit map to controller I2C Data or I2C Clock pins. + @param Value 1 or 0 stands for Set or Clear I2C Data and I2C Clock Pins. + +**/ +VOID +I2cPinWrite ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 Bit, + UINT8 Value + ) +{ + UINT8 Byte; + I2cOutb (PciIo, SEQ_ADDRESS_REGISTER, I2C_CONTROL); + Byte = (UINT8) (I2cInb (PciIo, SEQ_DATA_REGISTER) & (UINT8) ~(1 << Bit)) ; + Byte = (UINT8) (Byte | ((Value & 0x01) << Bit)); + I2cOutb (PciIo, SEQ_DATA_REGISTER, (UINT8) (Byte | 0x40)); + return; +} + +/** + Read/write delay acoording to I2C Bus Speed. + +**/ +VOID +I2cDelay ( + VOID + ) +{ + MicroSecondDelay (1000 / I2C_BUS_SPEED); +} + +/** + Write a 8-bit data onto I2C Data Pin. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param Data The byte data to write. + +**/ +VOID +I2cSendByte ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 Data + ) +{ + UINTN Index; + // + // Send byte data onto I2C Bus + // + for (Index = 0; Index < 8; Index --) { + I2cPinWrite (PciIo, I2CDAT_OUT, (UINT8) (Data >> (7 - Index))); + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cDelay (); + I2cPinWrite (PciIo, I2CCLK_OUT, 0); + } +} + +/** + Read a 8-bit data from I2C Data Pin. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + + Return the byte data read from I2C Data Pin. +**/ +UINT8 +I2cReceiveByte ( + EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + UINT8 Data; + UINTN Index; + + Data = 0; + // + // Read byte data from I2C Bus + // + for (Index = 0; Index < 8; Index --) { + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cDelay (); + Data = (UINT8) (Data << 1); + Data = (UINT8) (Data | I2cPinRead (PciIo, I2CDAT_IN)); + I2cPinWrite (PciIo, I2CCLK_OUT, 0); + } + + return Data; +} + +/** + Receive an ACK signal from I2C Bus. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + +**/ +BOOLEAN +I2cWaitAck ( + EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + // + // Wait for ACK signal + // + I2cPinWrite (PciIo, I2CDAT_OUT, 1); + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cDelay (); + if (I2cPinRead (PciIo, I2CDAT_IN) == 0) { + I2cPinWrite (PciIo, I2CDAT_OUT, 1); + return TRUE; + } else { + return FALSE; + } +} + +/** + Send an ACK signal onto I2C Bus. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + +**/ +VOID +I2cSendAck ( + EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cPinWrite (PciIo, I2CDAT_OUT, 1); + I2cPinWrite (PciIo, I2CDAT_OUT, 0); + I2cPinWrite (PciIo, I2CCLK_OUT, 0); +} + +/** + Start a I2C transfer on I2C Bus. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + +**/ +VOID +I2cStart ( + EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + // + // Init CLK and DAT pins + // + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cPinWrite (PciIo, I2CDAT_OUT, 1); + // + // Start a I2C transfer, set SDA low from high, when SCL is high + // + I2cPinWrite (PciIo, I2CDAT_OUT, 0); + I2cPinWrite (PciIo, I2CCLK_OUT, 0); +} + +/** + Stop a I2C transfer on I2C Bus. + + @param PciIo The pointer to PCI_IO_PROTOCOL. + +**/ +VOID +I2cStop ( + EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + // + // Stop a I2C transfer, set SDA high from low, when SCL is high + // + I2cPinWrite (PciIo, I2CDAT_OUT, 0); + I2cPinWrite (PciIo, I2CCLK_OUT, 1); + I2cPinWrite (PciIo, I2CDAT_OUT, 1); +} + +/** + Read one byte data on I2C Bus. + + Read one byte data from the slave device connectet to I2C Bus. + If Data is NULL, then ASSERT(). + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param DeviceAddress Slave device's address. + @param RegisterAddress The register address on slave device. + @param Data The pointer to returned data if EFI_SUCCESS returned. + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +I2cReadByte ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 DeviceAddress, + UINT8 RegisterAddress, + UINT8 *Data + ) +{ + ASSERT (Data != NULL); + + // + // Start I2C transfer + // + I2cStart (PciIo); + + // + // Send slave address with enabling write flag + // + I2cSendByte (PciIo, (UINT8) (DeviceAddress & 0xfe)); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Send register address + // + I2cSendByte (PciIo, RegisterAddress); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Send slave address with enabling read flag + // + I2cSendByte (PciIo, (UINT8) (DeviceAddress | 0x01)); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Read byte data from I2C Bus + // + *Data = I2cReceiveByte (PciIo); + + // + // Send ACK signal onto I2C Bus + // + I2cSendAck (PciIo); + + // + // Stop a I2C transfer + // + I2cStop (PciIo); + + return EFI_SUCCESS; +} + +/** + Write one byte data onto I2C Bus. + + Write one byte data to the slave device connectet to I2C Bus. + If Data is NULL, then ASSERT(). + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param DeviceAddress Slave device's address. + @param RegisterAddress The register address on slave device. + @param Data The pointer to write data. + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +I2cWriteByte ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 DeviceAddress, + UINT8 RegisterAddress, + UINT8 *Data + ) +{ + ASSERT (Data != NULL); + + I2cStart (PciIo); + // + // Send slave address with enabling write flag + // + I2cSendByte (PciIo, (UINT8) (DeviceAddress & 0xfe)); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Send register address + // + I2cSendByte (PciIo, RegisterAddress); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Send byte data onto I2C Bus + // + I2cSendByte (PciIo, *Data); + + // + // Wait for ACK signal + // + if (I2cWaitAck (PciIo) == FALSE) { + return EFI_DEVICE_ERROR; + } + + // + // Stop a I2C transfer + // + I2cStop (PciIo); + + return EFI_SUCCESS; +} + + + diff --git a/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.h b/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.h new file mode 100644 index 0000000000..b39f47f719 --- /dev/null +++ b/OptionRomPkg/CirrusLogic5430Dxe/CirrusLogic5430I2c.h @@ -0,0 +1,68 @@ +/** @file + I2c Bus byte read/write functions. + + Copyright (c) 2008 - 2009, 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 + which 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. + +**/ + +#ifndef _CIRRUS_LOGIC_I2C_H_ +#define _CIRRUS_LOGIC_I2C_H_ + +#include + +/** + Read one byte data on I2C Bus. + + Read one byte data from the slave device connectet to I2C Bus. + If Data is NULL, then ASSERT(). + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param DeviceAddress Slave device's address. + @param RegisterAddress The register address on slave device. + @param Data The pointer to returned data if EFI_SUCCESS returned. + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +I2cReadByte ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 DeviceAddress, + UINT8 RegisterAddress, + UINT8 *Data + ); + +/** + Write one byte data onto I2C Bus. + + Write one byte data to the slave device connectet to I2C Bus. + If Data is NULL, then ASSERT(). + + @param PciIo The pointer to PCI_IO_PROTOCOL. + @param DeviceAddress Slave device's address. + @param RegisterAddress The register address on slave device. + @param Data The pointer to write data. + + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +I2cWriteByte ( + EFI_PCI_IO_PROTOCOL *PciIo, + UINT8 DeviceAddress, + UINT8 RegisterAddress, + UINT8 *Data + ); + +#endif