// Copyright 2018 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_NAND_DRIVERS_AML_RAWNAND_AML_RAWNAND_H_
#define SRC_DEVICES_NAND_DRIVERS_AML_RAWNAND_AML_RAWNAND_H_

#include <lib/device-protocol/pdev.h>
#include <lib/device-protocol/platform-device.h>
#include <lib/mmio/mmio.h>
#include <lib/zx/time.h>
#include <string.h>
#include <unistd.h>
#include <zircon/threads.h>
#include <zircon/types.h>

#include <memory>
#include <utility>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/io-buffer.h>
#include <ddk/mmio-buffer.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/device.h>
#include <ddktl/device.h>
#include <ddktl/protocol/rawnand.h>
#include <fbl/bits.h>
#include <fbl/mutex.h>
#include <hw/reg.h>
#include <soc/aml-common/aml-rawnand.h>

#include "src/devices/nand/drivers/aml-rawnand/onfi.h"

namespace amlrawnand {

struct AmlController {
  int ecc_strength;
  int user_mode;
  int rand_mode;
  int options;
  int bch_mode;
};

// In the case where user_mode == 2 (2 OOB bytes per ECC page),
// the controller adds one of these structs *per* ECC page in
// the info_buf.
struct AmlInfoFormat {
  uint16_t info_bytes;
  uint8_t zero_bits; /* bit0~5 is valid */
  union ecc_sta {
    uint8_t raw_value;
    fbl::BitFieldMember<uint8_t, 0, 6> eccerr_cnt;
    fbl::BitFieldMember<uint8_t, 7, 1> completed;
  } ecc;
  uint32_t reserved;

  // BitFieldMember is not trivially copyable so neither are we, have to copy
  // each member over manually (copy assignment is needed by tests).
  AmlInfoFormat& operator=(const AmlInfoFormat& other) {
    info_bytes = other.info_bytes;
    zero_bits = other.zero_bits;
    ecc.raw_value = other.ecc.raw_value;
    reserved = other.reserved;
    return *this;
  }
};

// gcc doesn't let us use __PACKED with fbl::BitFieldMember<>, but it shouldn't
// make a difference practically in how the AmlInfoFormat struct is laid out
// and this assertion will double-check that we don't need it.
static_assert(sizeof(AmlInfoFormat) == 8, "sizeof(AmlInfoFormat) must be exactly 8 bytes");

// This should always be the case, but we also need an array of AmlInfoFormats
// to have no padding between the items.
static_assert(sizeof(AmlInfoFormat[2]) == 16, "AmlInfoFormat has unexpected padding");

class AmlRawNand;
using DeviceType = ddk::Device<AmlRawNand, ddk::Unbindable, ddk::Suspendable>;

class AmlRawNand : public DeviceType, public ddk::RawNandProtocol<AmlRawNand, ddk::base_protocol> {
 public:
  explicit AmlRawNand(zx_device_t* parent, ddk::MmioBuffer mmio_nandreg,
                      ddk::MmioBuffer mmio_clockreg, zx::bti bti, zx::interrupt irq,
                      std::unique_ptr<Onfi> onfi)
      : DeviceType(parent),
        onfi_(std::move(onfi)),
        mmio_nandreg_(std::move(mmio_nandreg)),
        mmio_clockreg_(std::move(mmio_clockreg)),
        bti_(std::move(bti)),
        irq_(std::move(irq)) {}

  static zx_status_t Create(void* ctx, zx_device_t* parent);

  virtual ~AmlRawNand() = default;

  void DdkRelease();
  void DdkUnbind(ddk::UnbindTxn txn);
  void DdkSuspend(ddk::SuspendTxn txn);

  zx_status_t Bind();
  zx_status_t Init();
  zx_status_t RawNandReadPageHwecc(uint32_t nand_page, void* data, size_t data_size,
                                   size_t* data_actual, void* oob, size_t oob_size,
                                   size_t* oob_actual, uint32_t* ecc_correct);
  zx_status_t RawNandWritePageHwecc(const void* data, size_t data_size, const void* oob,
                                    size_t oob_size, uint32_t nand_page);
  zx_status_t RawNandEraseBlock(uint32_t nand_page);
  zx_status_t RawNandGetNandInfo(fuchsia_hardware_nand_Info* nand_info);

 protected:
  // These functions require complicated hardware interaction so need to be
  // overridden or called differently in tests.

  // Waits until a read completes.
  virtual zx_status_t AmlQueueRB();

  // Waits until DMA has transfered data into or out of the NAND buffers.
  virtual zx_status_t AmlWaitDmaFinish();

  // Reads a single status byte from a NAND register. Used during initialization
  // to query the chip information and settings.
  virtual uint8_t AmlReadByte();

  // Normally called when the driver is unregistered but is not automatically
  // called on destruction, so needs to be called manually by tests before
  // destroying this object.
  void CleanUpIrq();

  // Tests can fake page read/writes by copying bytes to/from these buffers.
  const ddk::IoBuffer& data_buffer() __TA_NO_THREAD_SAFETY_ANALYSIS {
    return buffers_->data_buffer;
  }
  const ddk::IoBuffer& info_buffer() __TA_NO_THREAD_SAFETY_ANALYSIS {
    return buffers_->info_buffer;
  }
  const zx::bti& bti() const { return bti_; }

 private:
  std::unique_ptr<Onfi> onfi_;

  struct Buffers {
    void *info_buf, *data_buf;
    zx_paddr_t info_buf_paddr, data_buf_paddr;
    ddk::IoBuffer data_buffer;
    ddk::IoBuffer info_buffer;
  };

  fbl::Mutex mutex_;
  std::optional<Buffers> buffers_ __TA_GUARDED(mutex_);
  ddk::MmioBuffer mmio_nandreg_;
  ddk::MmioBuffer mmio_clockreg_;

  zx::bti bti_;
  zx::interrupt irq_;

  AmlController controller_params_;
  uint32_t chip_select_ = 0;  // Default to 0.
  int chip_delay_ = 100;      // Conservative default before we query chip to find better value.
  uint32_t writesize_;        /* NAND pagesize - bytes */
  uint32_t erasesize_;        /* size of erase block - bytes */
  uint32_t erasesize_pages_;
  uint32_t oobsize_;    /* oob bytes per NAND page - bytes */
  uint32_t bus_width_;  /* 16bit or 8bit ? */
  uint64_t chipsize_;   /* MiB */
  uint32_t page_shift_; /* NAND page shift */
  struct {
    uint64_t ecc_corrected;
    uint64_t failed;
  } stats;

  polling_timings_t polling_timings_ = {};

  void AmlCmdCtrl(int32_t cmd, uint32_t ctrl);
  void NandctrlSetCfg(uint32_t val);
  void NandctrlSetTimingAsync(int bus_tim, int bus_cyc);
  void NandctrlSendCmd(uint32_t cmd);
  void AmlCmdIdle(uint32_t time);
  zx_status_t AmlWaitCmdFinish(zx::duration timeout, zx::duration first_interval,
                               zx::duration polling_interval);
  void AmlCmdSeed(uint32_t seed);
  void AmlCmdN2M(uint32_t ecc_pages, uint32_t ecc_pagesize);
  void AmlCmdM2N(uint32_t ecc_pages, uint32_t ecc_pagesize);
  void AmlCmdM2NPage0();
  void AmlCmdN2MPage0();
  // Returns the AmlInfoFormat struct corresponding to the i'th
  // ECC page. THIS ASSUMES user_mode == 2 (2 OOB bytes per ECC page).
  void* AmlInfoPtr(int i) __TA_REQUIRES(mutex_);
  zx_status_t AmlGetOOBByte(uint8_t* oob_buf, size_t* oob_actual) __TA_REQUIRES(mutex_);
  zx_status_t AmlSetOOBByte(const uint8_t* oob_buf, size_t oob_size, uint32_t ecc_pages)
      __TA_REQUIRES(mutex_);
  // Returns the maximum bitflips corrected on this NAND page
  // (the maximum bitflips across all of the ECC pages in this page).
  zx_status_t AmlGetECCCorrections(int ecc_pages, uint32_t nand_page, uint32_t* ecc_corrected)
      __TA_REQUIRES(mutex_);
  zx_status_t AmlCheckECCPages(int ecc_pages) __TA_REQUIRES(mutex_);
  void AmlSetClockRate(uint32_t clk_freq);
  void AmlClockInit();
  void AmlAdjustTimings(uint32_t tRC_min, uint32_t tREA_max, uint32_t RHOH_min);
  zx_status_t AmlGetFlashType();
  void AmlSetEncryption();
  zx_status_t AmlReadPage0(void* data, size_t data_size, void* oob, size_t oob_size,
                           uint32_t nand_page, uint32_t* ecc_correct, int retries);
  // Reads one of the page0 pages, and use the result to init
  // ECC algorithm and rand-mode.
  zx_status_t AmlNandInitFromPage0();
  zx_status_t AmlRawNandAllocBufs() __TA_REQUIRES(mutex_);
  zx_status_t AmlNandInit();
};

}  // namespace amlrawnand

#endif  // SRC_DEVICES_NAND_DRIVERS_AML_RAWNAND_AML_RAWNAND_H_
