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.