1. Introduction | |
--------------- | |
**MvEeprom** driver creates MARVELL_EEPROM_PROTOCOL, which | |
+is used for managing eeprom. | |
2. MvEeprom driver design | |
------------------------- | |
Every I2C device driver should implement EFI_DRIVER_BINDING_PROTOCOL and | |
consume EFI_I2C_IO_PROTOCOL for transactions on I2C bus. MvEeprom driver | |
additionally implements MARVELL_EEPROM_PROTOCOL. | |
2.1 EFI_DRIVER_BINDING_PROTOCOL | |
------------------------------- | |
Driver Binding protocol is extensively covered in UEFI documentation, as | |
it is not specific to I2C stack. The only difference is that Supported() | |
function should check if EFI_I2C_IO_PROTOCOL provides valid EFI_GUID and | |
DeviceIndex values. | |
Excerpt from MvEepromSupported(): | |
Status = gBS->OpenProtocol ( | |
ControllerHandle, | |
&gEfiI2cIoProtocolGuid, | |
(VOID **) &TmpI2cIo, | |
gImageHandle, | |
ControllerHandle, | |
EFI_OPEN_PROTOCOL_BY_DRIVER | |
); | |
if (EFI_ERROR(Status)) { | |
return EFI_UNSUPPORTED; | |
} | |
/* get EEPROM devices' addresses from PCD */ | |
EepromAddresses = PcdGetPtr (PcdEepromI2cAddresses); | |
if (EepromAddresses == 0) { | |
Status = EFI_UNSUPPORTED; | |
goto out; | |
} | |
Status = EFI_UNSUPPORTED; | |
for (i = 0; EepromAddresses[i] != '\0'; i++) { | |
/* I2C guid must fit and valid DeviceIndex must be provided */ | |
if (CompareGuid(TmpI2cIo->DeviceGuid, &I2cGuid) && | |
TmpI2cIo->DeviceIndex == EepromAddresses[i]) { | |
DEBUG((DEBUG_INFO, "A8kEepromSupported: attached to EEPROM device\n")); | |
Status = EFI_SUCCESS; | |
break; | |
} | |
} | |
2.2 EFI_I2C_IO_PROTOCOL | |
----------------------- | |
This protocol is provided by generic I2C stack. Multiple drivers can use IO | |
protocol at once, as queueing is implemented. | |
QueueRequest is a routine that queues an I2C transaction to the I2C | |
controller for execution on the I2C bus. | |
2.3 MARVELL_EEPROM_PROTOCOL | |
----------------------- | |
typedef struct _MARVELL_EEPROM_PROTOCOL MARVELL_EEPROM_PROTOCOL; | |
#define EEPROM_READ 0x1 | |
#define EEPROM_WRITE 0x0 | |
typedef | |
EFI_STATUS | |
(EFIAPI *EFI_EEPROM_TRANSFER) ( | |
IN CONST MARVELL_EEPROM_PROTOCOL *This, | |
IN UINT16 Address, | |
IN UINT32 Length, | |
IN UINT8 *Buffer, | |
IN UINT8 Operation | |
); | |
struct _MARVELL_EEPROM_PROTOCOL { | |
EFI_EEPROM_TRANSFER Transfer; | |
UINT8 Identifier; | |
}; | |
3. Adding new I2C slave device drivers | |
-------------------------------------- | |
In order to support I2C slave device other than EEPROM, new driver should | |
be created. Required steps follow. | |
1. Create driver directory (OpenPlatformPkg/Drivers/I2c/Devices/...). | |
2. Create stubs of .inf and .c files (MvEeprom files are a reference), | |
include .inf file in platform .dsc and .fdf files. | |
3. Implement EFI_DRIVER_BINDING_PROTOCOL - Start(), Stop(), Supported() | |
functions' implementation is a must. EFI_DRIVER_BINDING_PROTOCOL | |
should be installed at driver's entry point. | |
4. Add I2C address of device to PcdI2cSlaveAddresses in .dsc file. | |
5. Test available EFI_I2C_IO_PROTOCOLs in Supported() - find instance | |
with valid GUID and DeviceIndex (I2C slave address). | |
6. Open EFI_I2C_IO_PROTOCOL for usage in Start(). After that, QueueRequest | |
function should be available. | |
7. Implement core functionality of driver (using QueueRequest to access I2C). | |
8. (not mandatory) Produce/consume additional protocols. |