// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_DEVICES_MISC_DRIVERS_TPM_I2C_CR50_H_
#define SRC_DEVICES_MISC_DRIVERS_TPM_I2C_CR50_H_

#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/handle.h>
#include <stdint.h>
#include <zircon/assert.h>
#include <zircon/types.h>

#include <memory>

#include <ddk/device.h>
#include <ddktl/protocol/i2c.h>
#include <fbl/mutex.h>

#include "tpm.h"

namespace tpm {

class I2cCr50Interface : public HardwareInterface {
 public:
  // Creates a new I2cCr50Interface from the given |i2c_dev|.  This will issue an
  // I2C transaction to determine support.
  static zx_status_t Create(zx_device_t* i2c_dev, zx::handle irq,
                            std::unique_ptr<I2cCr50Interface>* out);
  virtual ~I2cCr50Interface();

  zx_status_t Validate() override;

  zx_status_t ReadAccess(Locality loc, uint8_t* access) override;
  zx_status_t WriteAccess(Locality loc, uint8_t access) override;

  zx_status_t ReadStatus(Locality loc, uint32_t* sts) override;
  zx_status_t WriteStatus(Locality loc, uint32_t sts) override;

  zx_status_t ReadDidVid(uint16_t* vid, uint16_t* did) override;

  zx_status_t ReadDataFifo(Locality loc, uint8_t* buf, size_t len) override;
  zx_status_t WriteDataFifo(Locality loc, const uint8_t* buf, size_t len) override;

 private:
  template <typename T>
  struct I2cRegister {
    explicit constexpr I2cRegister(uint8_t addr) : addr(addr) {}
    const uint8_t addr;
  };

  // Timeout to use if this device does not have an IRQ wired up.
  static constexpr zx::duration kNoIrqTimeout = zx::msec(20);
  // Delay to use between retries if an I2C operation errors.
  static constexpr zx::duration kI2cRetryDelay = zx::usec(50);

  I2cCr50Interface(zx_device_t* i2c_dev, zx::handle irq);

  // Block until the controller signals it is ready.  May return spuriously,
  // so the condition being waited on should be checked after return.
  zx_status_t WaitForIrqLocked() TA_REQ(lock_);

  // Template for enforcing correct access size for each register read
  template <typename T>
  zx_status_t RegisterRead(const I2cRegister<T>& reg, T* out) {
    // TODO(teisenbe): If we ever support a big-endian host, we need to do
    // endianness swapping here.
    static_assert(std::is_integral<T>::value, "T must be integral");
    return RegisterRead(I2cRegister<uint8_t[]>(reg.addr), reinterpret_cast<uint8_t*>(out),
                        sizeof(T));
  }

  // Template for enforcing correct access size for each register write
  template <typename T>
  zx_status_t RegisterWrite(const I2cRegister<T>& reg, const T& val) {
    static_assert(std::is_integral<T>::value, "T must be integral");
    return RegisterWrite(I2cRegister<uint8_t[]>(reg.addr), reinterpret_cast<const uint8_t*>(&val),
                         sizeof(T));
  }

  // Perform an I2C read cycle
  zx_status_t I2cReadLocked(uint8_t* val, size_t len) TA_REQ(lock_);
  // Perform an I2C write cycle
  zx_status_t I2cWriteLocked(const uint8_t* val, size_t len) TA_REQ(lock_);

  // Perform a register read/write for an unsized register (indicated
  // by T=uint8_t[]).
  zx_status_t RegisterWrite(const I2cRegister<uint8_t[]>& reg, const uint8_t* val, size_t len)
      TA_EXCL(lock_);
  zx_status_t RegisterRead(const I2cRegister<uint8_t[]>& reg, uint8_t* out, size_t len)
      TA_EXCL(lock_);

  // Compute the register address prefix for the given locality
  static constexpr uint8_t LocToPrefix(Locality loc) {
    ZX_DEBUG_ASSERT(loc <= 4);
    return static_cast<uint8_t>(loc << 4);
  }

  // These methods return an object usable with RegisterRead/RegisterWrite representing
  // the specified register and locality.
  static constexpr I2cRegister<uint8_t> RegisterAccess(Locality loc) {
    return I2cRegister<uint8_t>(static_cast<uint8_t>(LocToPrefix(loc) | 0x0u));
  }
  static constexpr I2cRegister<uint32_t> RegisterStatus(Locality loc) {
    ZX_DEBUG_ASSERT(loc <= 4);
    return I2cRegister<uint32_t>(static_cast<uint8_t>(LocToPrefix(loc) | 0x1u));
  }
  static constexpr I2cRegister<uint8_t[]> RegisterDataFifo(Locality loc) {
    ZX_DEBUG_ASSERT(loc <= 4);
    return I2cRegister<uint8_t[]>(static_cast<uint8_t>(LocToPrefix(loc) | 0x5u));
  }
  static constexpr I2cRegister<uint32_t> RegisterDidVid(Locality loc) {
    ZX_DEBUG_ASSERT(loc <= 4);
    return I2cRegister<uint32_t>(static_cast<uint8_t>(LocToPrefix(loc) | 0x6u));
  }

  fbl::Mutex lock_;

  // The upstream i2c device
  ddk::I2cProtocolClient i2c_ TA_GUARDED(lock_);
  zx::handle irq_ TA_GUARDED(lock_);
};

}  // namespace tpm

#endif  // SRC_DEVICES_MISC_DRIVERS_TPM_I2C_CR50_H_
