Moving OMAP 3530 code out of BeagleBoard package into its own package
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9854 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
325
Omap35xxPkg/SmbusDxe/Smbus.c
Normal file
325
Omap35xxPkg/SmbusDxe/Smbus.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
||||
|
||||
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 <Uefi.h>
|
||||
#include <Omap3530/Omap3530.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include <Protocol/SmbusHc.h>
|
||||
|
||||
#define MAX_RETRY 1000
|
||||
|
||||
//
|
||||
// Internal Functions
|
||||
//
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
WaitForBusBusy (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Retry = 0;
|
||||
|
||||
while (++Retry < MAX_RETRY && (MmioRead16(I2C_STAT) & BB) == 0x1);
|
||||
|
||||
if (Retry == MAX_RETRY) {
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
PollForStatus(
|
||||
UINT16 StatusBit
|
||||
)
|
||||
{
|
||||
UINTN Retry = 0;
|
||||
|
||||
while(Retry < MAX_RETRY) {
|
||||
if (MmioRead16(I2C_STAT) & StatusBit) {
|
||||
//Clear particular status bit from Status register.
|
||||
MmioOr16(I2C_STAT, StatusBit);
|
||||
break;
|
||||
}
|
||||
Retry++;
|
||||
}
|
||||
|
||||
if (Retry == MAX_RETRY) {
|
||||
return EFI_TIMEOUT;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ConfigureI2c (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//Program prescaler to obtain 12-MHz clock
|
||||
MmioWrite16(I2C_PSC, 0x0000);
|
||||
|
||||
//Program SCLL and SCLH
|
||||
//NOTE: Following values are the register dump after U-Boot code executed.
|
||||
//We need to figure out how its calculated based on the I2C functional clock and I2C_PSC.
|
||||
MmioWrite16(I2C_SCLL, 0x0035);
|
||||
MmioWrite16(I2C_SCLH, 0x0035);
|
||||
|
||||
//Take the I2C controller out of reset.
|
||||
MmioOr16(I2C_CON, I2C_EN);
|
||||
|
||||
//Initialize the I2C controller.
|
||||
|
||||
//Set I2C controller in Master mode.
|
||||
MmioOr16(I2C_CON, MST);
|
||||
|
||||
//Enable interrupts for receive/transmit mode.
|
||||
MmioOr16(I2C_IE, (XRDY_IE | RRDY_IE | ARDY_IE | NACK_IE));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
I2CReadOneByte (
|
||||
UINT8 *Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//I2C bus status checking
|
||||
Status = WaitForBusBusy();
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//Poll till Receive ready bit is set.
|
||||
Status = PollForStatus(RRDY);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Data = MmioRead8(I2C_DATA);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
I2CWriteOneByte (
|
||||
UINT8 Data
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//I2C bus status checking
|
||||
Status = WaitForBusBusy();
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//Data transfer
|
||||
//Poll till Transmit ready bit is set
|
||||
Status = PollForStatus(XRDY);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
MmioWrite8(I2C_DATA, Data);
|
||||
|
||||
//Wait and check if the NACK is not set.
|
||||
gBS->Stall(1000);
|
||||
if (MmioRead16(I2C_STAT) & NACK) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SmbusBlockRead (
|
||||
OUT UINT8 *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
UINTN Index = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
//Transfer configuration for receiving data.
|
||||
MmioWrite16(I2C_CNT, Length);
|
||||
//Need stop bit before sending data.
|
||||
MmioWrite16(I2C_CON, (I2C_EN | MST | STP | STT));
|
||||
|
||||
while (Index < Length) {
|
||||
//Read a byte
|
||||
Status = I2CReadOneByte(&Buffer[Index++]);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//Transfer completion
|
||||
Status = PollForStatus(ARDY);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SmbusBlockWrite (
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
UINTN Index = 0;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
|
||||
//Transfer configuration for transmitting data
|
||||
MmioWrite16(I2C_CNT, Length);
|
||||
MmioWrite16(I2C_CON, (I2C_EN | TRX | MST | STT | STP));
|
||||
|
||||
while (Index < Length) {
|
||||
//Send a byte
|
||||
Status = I2CWriteOneByte(Buffer[Index++]);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//Transfer completion
|
||||
Status = PollForStatus(ARDY);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Public Functions.
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmbusExecute (
|
||||
IN CONST EFI_SMBUS_HC_PROTOCOL *This,
|
||||
IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
|
||||
IN CONST EFI_SMBUS_DEVICE_COMMAND Command,
|
||||
IN CONST EFI_SMBUS_OPERATION Operation,
|
||||
IN CONST BOOLEAN PecCheck,
|
||||
IN OUT UINTN *Length,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT8 *ByteBuffer = Buffer;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINT8 SlaveAddr = (UINT8)(SlaveAddress.SmbusDeviceAddress);
|
||||
|
||||
if (PecCheck) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((Operation != EfiSmbusWriteBlock) && (Operation != EfiSmbusReadBlock)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//Set the Slave address.
|
||||
MmioWrite16(I2C_SA, SlaveAddr);
|
||||
|
||||
if (Operation == EfiSmbusReadBlock) {
|
||||
Status = SmbusBlockRead(ByteBuffer, *Length);
|
||||
} else if (Operation == EfiSmbusWriteBlock) {
|
||||
Status = SmbusBlockWrite(ByteBuffer, *Length);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmbusArpDevice (
|
||||
IN CONST EFI_SMBUS_HC_PROTOCOL *This,
|
||||
IN CONST BOOLEAN ArpAll,
|
||||
IN CONST EFI_SMBUS_UDID *SmbusUdid OPTIONAL,
|
||||
IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmbusGetArpMap (
|
||||
IN CONST EFI_SMBUS_HC_PROTOCOL *This,
|
||||
IN OUT UINTN *Length,
|
||||
IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmbusNotify (
|
||||
IN CONST EFI_SMBUS_HC_PROTOCOL *This,
|
||||
IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress,
|
||||
IN CONST UINTN Data,
|
||||
IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EFI_SMBUS_HC_PROTOCOL SmbusProtocol =
|
||||
{
|
||||
SmbusExecute,
|
||||
SmbusArpDevice,
|
||||
SmbusGetArpMap,
|
||||
SmbusNotify
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
InitializeSmbus (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_HANDLE Handle = NULL;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//Configure I2C controller.
|
||||
Status = ConfigureI2c();
|
||||
if (EFI_ERROR(Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "InitializeI2c fails.\n"));
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Install the SMBUS interface
|
||||
Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiSmbusHcProtocolGuid, &SmbusProtocol, NULL);
|
||||
ASSERT_EFI_ERROR(Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
Reference in New Issue
Block a user