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

#include <fuchsia/hardware/sdmmc/c/banjo.h>
#include <inttypes.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sdmmc-block-device.h"

namespace {

// If this bit is set in the Operating Conditions Register, then we know that
// the card is a SDHC (high capacity) card.
constexpr uint32_t kOcrSdhc = 0xc0000000;

constexpr uint32_t kAcmd41FlagSdhcSdxcSupport = 0x40000000;
constexpr uint32_t kAcmd41FlagVoltageWindowAll = 0x00ff8000;

// The "STRUCTURE" field of the "Card Specific Data" register defines the
// version of the structure and how to interpret the rest of the bits.
constexpr uint8_t kCsdStructV2 = 0x1;

}  // namespace

namespace sdmmc {

zx_status_t SdmmcBlockDevice::ProbeSd() {
  sdmmc_.SetRequestRetries(0);

  // Issue the SEND_IF_COND command, this will tell us that we can talk to
  // the card correctly and it will also tell us if the voltage range that we
  // have supplied has been accepted.
  zx_status_t st = sdmmc_.SdSendIfCond();
  if (st != ZX_OK) {
    return st;
  }

  // Get the operating conditions from the card.
  uint32_t ocr;
  if ((st = sdmmc_.SdSendOpCond(0, &ocr)) != ZX_OK) {
    zxlogf(ERROR, "SDMMC_SD_SEND_OP_COND failed, retcode = %d", st);
    return st;
  }

  int attempt = 0;
  const int max_attempts = 200;
  bool card_supports_18v_signalling = false;
  while (true) {
    const uint32_t flags = kAcmd41FlagSdhcSdxcSupport | kAcmd41FlagVoltageWindowAll;
    uint32_t ocr;
    if ((st = sdmmc_.SdSendOpCond(flags, &ocr)) != ZX_OK) {
      zxlogf(ERROR, "SD_SEND_OP_COND failed with retcode = %d", st);
      return st;
    }

    if (ocr & (1 << 31)) {
      if (!(ocr & kOcrSdhc)) {
        // Card is not an SDHC card. We currently don't support this.
        zxlogf(ERROR, "unsupported card type, must use sdhc card");
        return ZX_ERR_NOT_SUPPORTED;
      }
      card_supports_18v_signalling = !!((ocr >> 24) & 0x1);
      break;
    }

    if (++attempt == max_attempts) {
      zxlogf(ERROR, "too many attempt trying to negotiate card OCR");
      return ZX_ERR_TIMED_OUT;
    }

    zx::nanosleep(zx::deadline_after(zx::msec(5)));
  }

  st = sdmmc_.host().SetBusFreq(25000000);
  if (st != ZX_OK) {
    // This is non-fatal but the card will run slowly.
    zxlogf(ERROR, "failed to increase bus frequency.");
  }

  // TODO(bradenkell): Re-enable support for UHS-I mode once the Mediatek driver supports
  //                   switching to 1.8V.

  (void)card_supports_18v_signalling;
  // Try to switch the bus voltage to 1.8v
  // if (card_supports_18v_signalling) {
  //     st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_VOLTAGE_SWITCH, 0, setup_txn);
  //     if (st != ZX_OK) {
  //         zxlogf(ERROR, "failed to send switch voltage command to card, "
  //                 "retcode = %d\n", st);
  //         goto err;
  //     }
  //
  //     st = sdmmc_set_signal_voltage(&sdmmc->host, SDMMC_VOLTAGE_180);
  //     if (st != ZX_OK) {
  //         zxlogf(ERROR, "Card supports 1.8v signalling but was unable to "
  //                 "switch to 1.8v mode, retcode = %d\n", st);
  //         goto err;
  //     }
  // }

  if ((st = sdmmc_.MmcAllSendCid(raw_cid_)) != ZX_OK) {
    zxlogf(ERROR, "ALL_SEND_CID failed with retcode = %d", st);
    return st;
  }

  uint16_t card_status;
  if ((st = sdmmc_.SdSendRelativeAddr(&card_status)) != ZX_OK) {
    zxlogf(ERROR, "SEND_RELATIVE_ADDR failed with retcode = %d", st);
    return st;
  }

  if (card_status & 0xe000) {
    zxlogf(ERROR, "SEND_RELATIVE_ADDR failed with resp = %d", (card_status & 0xe000));
    return ZX_ERR_INTERNAL;
  }
  if ((card_status & (1u << 8)) == 0) {
    zxlogf(ERROR, "SEND_RELATIVE_ADDR failed. Card not ready.");
    return ZX_ERR_INTERNAL;
  }

  // Determine the size of the card.
  if ((st = sdmmc_.MmcSendCsd(raw_csd_)) != ZX_OK) {
    zxlogf(ERROR, "failed to send app cmd, retcode = %d", st);
    return st;
  }

  // For now we only support SDHC cards. These cards must have a CSD type = 1,
  // since CSD type 0 is unable to support SDHC sized cards.
  const auto csd_structure = static_cast<uint8_t>((raw_csd_[15] >> 6) & 0x3);
  if (csd_structure != kCsdStructV2) {
    zxlogf(ERROR,
           "sd: unsupported card type, expected CSD version = %d, "
           "got version %d\n",
           kCsdStructV2, csd_structure);
    return ZX_ERR_INTERNAL;
  }

  const uint32_t c_size = (raw_csd_[6] | (raw_csd_[7] << 8) | (raw_csd_[8] << 16)) & 0x3f'ffff;
  block_info_.block_count = (c_size + 1ul) * 1024ul;
  block_info_.block_size = 512ul;
  zxlogf(INFO, "found card with capacity = %" PRIu64 "B",
         block_info_.block_count * block_info_.block_size);

  if ((st = sdmmc_.SdSelectCard()) != ZX_OK) {
    zxlogf(ERROR, "SELECT_CARD failed with retcode = %d", st);
    return st;
  }

  std::array<uint8_t, 8> scr;
  if ((st = sdmmc_.SdSendScr(scr)) != ZX_OK) {
    zxlogf(ERROR, "SEND_SCR failed with retcode = %d", st);
    return st;
  }

  // TODO(bradenkell): Read SD_STATUS to see if the card supports discard (trim).

  // If this card supports 4 bit mode, then put it into 4 bit mode.
  const uint32_t supported_bus_widths = scr[1] & 0xf;
  if (supported_bus_widths & 0x4) {
    do {
      // First tell the card to go into four bit mode:
      if ((st = sdmmc_.SdSetBusWidth(SDMMC_BUS_WIDTH_FOUR)) != ZX_OK) {
        zxlogf(ERROR, "failed to set card bus width, retcode = %d", st);
        break;
      }
      st = sdmmc_.host().SetBusWidth(SDMMC_BUS_WIDTH_FOUR);
      if (st != ZX_OK) {
        zxlogf(ERROR, "failed to set host bus width, retcode = %d", st);
      }
    } while (false);
  }

  is_sd_ = true;
  return ZX_OK;
}

}  // namespace sdmmc
