123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /** @file
- I2C Bus implementation upon CirrusLogic.
- Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #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;
- }
|