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 (Platform/Marvell/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.
