| 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. |