/*
 * Copyright 2017, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 */

#include "mmc.h"
#include "services.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>

#define DBG_INFO "info:"

//#define DEBUG
#undef DEBUG
#ifdef DEBUG
#define D(x, ...) printf(__VA_ARGS__)
#else
#define D(...) do{}while(0)
#endif

#define CSD_VERSION_1       0
#define CSD_VERSION_2_AND_3 1

struct mmc_completion_token {
    struct mmc_card *card;
    mmc_cb cb;
    void *token;
};


static uint32_t slice_bits(uint32_t *val, int start, int size)
{
    int idx;
    int high, low;
    uint32_t ret = 0;

    /* Can not return more than 32 bits. */
    assert(size <= 32);

    idx = start / 32;
    low = start % 32;
    high = (start + size) % 32;

    if (high == 0 && low == 0) {
        ret = val[idx];
    } else if (high == 0 && low != 0) {
        ret = val[idx] >> low;
    } else {
        if (high > low) {
            ret = val[idx] & ((1U << high) - 1);
            ret = ret >> low;
        } else {
            ret = val[idx] >> low;
            ret |= (val[idx + 1] & ((1U << high) - 1)) << (32 - low);
        }

    }

    return ret;
}

#if 0 /* Commenting this out as it appears unused. */
static int mmc_decode_cid(mmc_card_t mmc_card, struct cid *cid)
{
    if (mmc_card == NULL || cid == NULL) {
        return -1;
    }

    if (mmc_card->type == CARD_TYPE_SD) {
        cid->manfid         = slice_bits(mmc_card->raw_cid, 120,  8);
        cid->sd_cid.oemid   = slice_bits(mmc_card->raw_cid, 104, 16);
        cid->sd_cid.name[0] = slice_bits(mmc_card->raw_cid,  96,  8);
        cid->sd_cid.name[1] = slice_bits(mmc_card->raw_cid,  88,  8);
        cid->sd_cid.name[2] = slice_bits(mmc_card->raw_cid,  80,  8);
        cid->sd_cid.name[3] = slice_bits(mmc_card->raw_cid,  72,  8);
        cid->sd_cid.name[4] = slice_bits(mmc_card->raw_cid,  64,  8);
        cid->sd_cid.rev     = slice_bits(mmc_card->raw_cid,  56,  8);
        cid->sd_cid.serial  = slice_bits(mmc_card->raw_cid,  24, 32);
        cid->sd_cid.date    = slice_bits(mmc_card->raw_cid,   8, 12);

        printf("manfid(%x), oemid(%x), name(%c%c%c%c%c), rev(%x), serial(%x), date(%x)\n",
               cid->manfid, cid->sd_cid.oemid,
               cid->sd_cid.name[0], cid->sd_cid.name[1], cid->sd_cid.name[2],
               cid->sd_cid.name[3], cid->sd_cid.name[4],
               cid->sd_cid.rev, cid->sd_cid.serial, cid->sd_cid.date);
    } else {
        printf("Not Implemented!\n");
        return -1;
    }

    return 0;
}
#endif

static int mmc_decode_csd(mmc_card_t mmc_card, struct csd *csd)
{
    if (mmc_card == NULL || csd == NULL) {
        return -1;
    }

#define CSD_BITS(start, size) \
    slice_bits(mmc_card->raw_csd, start, size)

    csd->structure = CSD_BITS(126, 2);

    if (csd->structure == CSD_VERSION_1) {
        printf("CSD Version 1.0\n");
        csd->c_size      = CSD_BITS(62, 12);
        csd->c_size_mult = CSD_BITS(47,  3);
        csd->read_bl_len = CSD_BITS(80,  4);
        csd->tran_speed  = CSD_BITS(96,  8);
    } else if (csd->structure == CSD_VERSION_2_AND_3) {
        printf("CSD Version 2.0\n");
        csd->c_size      = CSD_BITS(48, 22);
        csd->c_size_mult = 0;
        csd->read_bl_len = CSD_BITS(80,  4);
        csd->tran_speed  = CSD_BITS(96,  8);
    } else {
        printf("Unknown CSD version!\n");
        return -1;
    }

    return 0;
}

static struct mmc_cmd *mmc_cmd_new(uint32_t index, uint32_t arg, int rsp_type)
{
    struct mmc_cmd *cmd;
    cmd = malloc(sizeof(*cmd));
    if (cmd) {
        /* Command */
        cmd->index = index;
        cmd->arg = arg;
        cmd->rsp_type = rsp_type;
        cmd->data = NULL;
        /* Transaction maintenance */
        cmd->cb = NULL;
        cmd->token = NULL;
        cmd->next = NULL;
        cmd->complete = 0;
    }
    return cmd;
}

static int mmc_cmd_add_data(struct mmc_cmd *cmd, void *vbuf, uintptr_t pbuf, uint32_t addr,
                            uint32_t block_size, uint32_t blocks)
{
    struct mmc_data *d;
    assert(cmd->data == NULL);
    d = (struct mmc_data *)malloc(sizeof(*d));
    if (d) {
        d->pbuf = pbuf;
        d->vbuf = vbuf;
        d->data_addr = addr;
        d->block_size = block_size;
        d->blocks = blocks;
        cmd->data = d;
        return 0;
    } else {
        return -1;
    }
}

static void mmc_cmd_destroy(struct mmc_cmd *cmd)
{
    if (cmd->data) {
        free(cmd->data);
    }
    free(cmd);
}

static struct mmc_completion_token *mmc_new_completion_token(mmc_card_t mmc_card, mmc_cb cb, void *token)
{
    struct mmc_completion_token *t;
    t = (struct mmc_completion_token *)malloc(sizeof(*t));
    if (t) {
        t->card = mmc_card;
        t->cb = cb;
        t->token = token;
    }
    return t;
}

static void mmc_completion_token_destroy(struct mmc_completion_token *t)
{
    free(t);
}

/**
 * MMC/SD/SDIO card registry.
 */
static int mmc_card_registry(mmc_card_t card)
{
    struct mmc_cmd cmd = {.data = NULL};
    int ret;

    D(DBG_INFO, "\n");

    /* Get card ID */
    cmd.index = MMC_ALL_SEND_CID;
    cmd.arg = 0;
    cmd.rsp_type = MMC_RSP_TYPE_R2;
    ret = host_send_command(card, &cmd, NULL, NULL);
    if (ret) {
        D(DBG_ERR, "No response!\n");
        card->status = CARD_STS_INACTIVE;
        return -1;
    } else {
        card->status = CARD_STS_ACTIVE;
    }

    /* Left shift the response by 8. Consult SDHC manual. */
    cmd.response[3] = ((cmd.response[3] << 8) | (cmd.response[2] >> 24));
    cmd.response[2] = ((cmd.response[2] << 8) | (cmd.response[1] >> 24));
    cmd.response[1] = ((cmd.response[1] << 8) | (cmd.response[0] >> 24));
    cmd.response[0] = (cmd.response[0] << 8);
    memcpy(card->raw_cid, cmd.response, sizeof(card->raw_cid));


    /* Retrieve RCA number. */
    cmd.index = MMC_SEND_RELATIVE_ADDR;
    cmd.arg = 0;
    cmd.rsp_type = MMC_RSP_TYPE_R6;
    host_send_command(card, &cmd, NULL, NULL);
    card->raw_rca = (cmd.response[0] >> 16);
    D(DBG_INFO, "New Card RCA: %x\n", card->raw_rca);

    /* Read CSD, Status */
    cmd.index = MMC_SEND_CSD;
    cmd.arg = card->raw_rca << 16;
    cmd.rsp_type = MMC_RSP_TYPE_R2;
    host_send_command(card, &cmd, NULL, NULL);

    /* Left shift the response by 8. Consult SDHC manual. */
    cmd.response[3] = ((cmd.response[3] << 8) | (cmd.response[2] >> 24));
    cmd.response[2] = ((cmd.response[2] << 8) | (cmd.response[1] >> 24));
    cmd.response[1] = ((cmd.response[1] << 8) | (cmd.response[0] >> 24));
    cmd.response[0] = (cmd.response[0] << 8);
    memcpy(card->raw_csd, cmd.response, sizeof(card->raw_csd));

    cmd.index = MMC_SEND_STATUS;
    cmd.rsp_type = MMC_RSP_TYPE_R1;
    host_send_command(card, &cmd, NULL, NULL);

    /* Select the card */
    cmd.index = MMC_SELECT_CARD;
    cmd.arg = card->raw_rca << 16;
    cmd.rsp_type = MMC_RSP_TYPE_R1b;
    host_send_command(card, &cmd, NULL, NULL);

    /* Set Bus width */
    cmd.index = MMC_APP_CMD;
    cmd.arg = card->raw_rca << 16;
    cmd.rsp_type = MMC_RSP_TYPE_R1;
    host_send_command(card, &cmd, NULL, NULL);
    cmd.index = SD_SET_BUS_WIDTH;
    host_send_command(card, &cmd, NULL, NULL);

    /* Set read/write block length for byte addressed standard capacity cards */
    if (!card->high_capacity) {
        cmd.index = MMC_SET_BLOCKLEN;
        cmd.arg = mmc_block_size(card);
        cmd.rsp_type = MMC_RSP_TYPE_R1;
        ret = host_send_command(card, &cmd, NULL, NULL);
    }

    return 0;
}


/**
 * Card voltage validation.
 */
static int mmc_voltage_validation(mmc_card_t card)
{
    struct mmc_cmd cmd = {.data = NULL};
    int voltage;
    int ret;

    /* Send CMD55 to issue an application specific command. */
    cmd.index = MMC_APP_CMD;
    cmd.arg = 0;
    cmd.rsp_type = MMC_RSP_TYPE_R1;
    ret = host_send_command(card, &cmd, NULL, NULL);
    if (!ret) {
        /* It is a SD card. */
        cmd.index = SD_SD_APP_OP_COND;
        cmd.arg = 0;
        cmd.rsp_type = MMC_RSP_TYPE_R3;
        card->type = CARD_TYPE_SD;
    } else {
        /* It is a MMC card. */
        cmd.index = MMC_SEND_OP_COND;
        cmd.arg = 0;
        cmd.rsp_type = MMC_RSP_TYPE_R3;
        card->type = CARD_TYPE_MMC;
    }
    ret = host_send_command(card, &cmd, NULL, NULL);
    if (ret) {
        card->type = CARD_TYPE_UNKNOWN;
        /* TODO: Be nicer */
        assert(0);
    }
    card->ocr = cmd.response[0];

    /* TODO: Check uSDHC compatibility */
    voltage = MMC_VDD_29_30 | MMC_VDD_30_31;
    if (host_is_voltage_compatible(card, 3300) && (card->ocr & voltage)) {
        /* Voltage compatible */
        voltage |= (1 << 30);
        voltage |= (1 << 25);
        voltage |= (1 << 24);
    }

    /* Wait until the voltage level is set. */
    do {
        if (card->type == CARD_TYPE_SD) {
            cmd.index = MMC_APP_CMD;
            cmd.arg = 0;
            cmd.rsp_type = MMC_RSP_TYPE_R1;
            host_send_command(card, &cmd, NULL, NULL);
        }

        cmd.index = SD_SD_APP_OP_COND;
        cmd.arg = voltage;
        cmd.rsp_type = MMC_RSP_TYPE_R3;
        host_send_command(card, &cmd, NULL, NULL);
        udelay(100000);
    } while (!(cmd.response[0] & (1U << 31)));
    card->ocr = cmd.response[0];

    /* Check CCS bit */
    if (card->ocr & (1 << 30)) {
        card->high_capacity = 1;
    } else {
        card->high_capacity = 0;
    }

    D(DBG_INFO, "Voltage set!\n");
    return 0;
}


static int mmc_reset(mmc_card_t card)
{
    /* Reset the card with CMD0 */
    struct mmc_cmd cmd = {.data = NULL};
    cmd.index = MMC_GO_IDLE_STATE;
    cmd.arg = 0;
    cmd.rsp_type = MMC_RSP_TYPE_NONE;
    host_send_command(card, &cmd, NULL, NULL);

    /* TODO: review this command. */
    cmd.index = MMC_SEND_EXT_CSD;
    cmd.arg = 0x1AA;
    cmd.rsp_type = MMC_RSP_TYPE_R1;
    host_send_command(card, &cmd, NULL, NULL);
    return 0;
}

static void mmc_blockop_completion_cb(struct sdio_host_dev *sdio, int stat, struct mmc_cmd *cmd,
                                      void *token)
{
    struct mmc_completion_token *t;
    size_t bytes;

    t = (struct mmc_completion_token *)token;
    if (stat == 0) {
        bytes = cmd->data->block_size * cmd->data->blocks;
    } else {
        bytes = 0;
    }
    /* Call the registered function */
    t->cb(t->card, stat, bytes, t->token);
    /* Free memory */
    mmc_cmd_destroy(cmd);
    mmc_completion_token_destroy(t);
}

int mmc_init(sdio_host_dev_t *sdio, ps_io_ops_t *io_ops, mmc_card_t *mmc_card)
{
    mmc_card_t mmc;

    /* Allocate the mmc card structure */
    mmc = (mmc_card_t)malloc(sizeof(*mmc));
    assert(mmc);
    if (!mmc) {
        return -1;
    }
    mmc->dalloc = &io_ops->dma_manager;
    mmc->sdio = sdio;
    /* Reset the host controller */
    if (host_reset(mmc)) {
        LOG_ERROR("Failed to reset host controller\n");
        free(mmc);
        return -1;
    }
    /* Initialise the card */
    if (mmc_reset(mmc)) {
        LOG_ERROR("Failed to reset SD/MMC card\n");
        free(mmc);
        return -1;
    }
    if (mmc_voltage_validation(mmc)) {
        LOG_ERROR("Failed to perform voltage validation\n");
        free(mmc);
        return -1;
    }
    /* Register the card */
    if (mmc_card_registry(mmc)) {
        LOG_ERROR("Failed to register card\n");
        free(mmc);
        return -1;
    }

    *mmc_card = mmc;
    assert(mmc);
    return 0;
}

static
long transfer_data(
    mmc_card_t mmc_card,
    unsigned long start,
    int nblocks,
    void *vbuf,
    uintptr_t pbuf,
    mmc_cb cb,
    void *token,
    uint32_t command)
{
    struct mmc_cmd *cmd;
    const int block_size = mmc_block_size(mmc_card);

    /* Determine command argument */
    const uint32_t arg = (mmc_card->high_capacity)
                         ? start
                         : (start * block_size);

    /* Allocate command structure
     *
     * Please note that `cmd` is dynamically allocated, so it must be destroyed.
     *
     * Clean up will be done prior to exiting this function OR in the
     * `mmc_blockop_completion_cb` if callback was given.
     *
     * In case of an unexpected error, there will be a jump to
     * `exit_transfer_data` label, so that memory leak can be avoided.
     */
    cmd = mmc_cmd_new(command, arg, MMC_RSP_TYPE_R1);
    if (cmd == NULL) {
        // `cmd` was NOT allocated, so we are exiting without destroying it.
        return -1;
    }

    long ret = -1;
    struct mmc_completion_token *mmc_token = NULL;

    /* Add a data segment */
    ret = mmc_cmd_add_data(cmd, vbuf, pbuf, start, block_size, nblocks);
    if (ret < 0) {
        goto exit_transfer_data;
    }

    if (cb) {
        mmc_token = mmc_new_completion_token(mmc_card, cb, token);

        if (NULL == mmc_token) {
            ret = -1;
            goto exit_transfer_data;
        }
    }

    ret = host_send_command(
              mmc_card,
              cmd,
              cb ? &mmc_blockop_completion_cb : NULL,
              cb ? mmc_token : NULL);

exit_transfer_data:
    ;
    const bool is_success = (0 == ret);

    // Clean up usually will happen during the callback, so we only clean up
    // here if no callback was given or failure has been encountered.
    if (!cb || !is_success) {
        if (mmc_token) {
            mmc_completion_token_destroy(mmc_token);
        }
        if (cmd)       {
            mmc_cmd_destroy(cmd);
        }
    }

    const size_t bytes_transferred = cb ? 0 : (block_size * nblocks);
    return is_success ? bytes_transferred : ret;
}

long mmc_block_read(mmc_card_t mmc_card, unsigned long start,
                    int nblocks, void *vbuf, uintptr_t pbuf, mmc_cb cb, void *token)
{
    return transfer_data(
               mmc_card,
               start,
               nblocks,
               vbuf,
               pbuf,
               cb,
               token,
               MMC_READ_SINGLE_BLOCK);
}

long mmc_block_write(mmc_card_t mmc_card, unsigned long start, int nblocks,
                     const void *vbuf, uintptr_t pbuf, mmc_cb cb, void *token)
{
    // vbuf's `const` gets dropped during the cast as the underlying layer
    // accepts only non-const buffer, however it is ok, as we are sending the
    // write command, what quarantees that the buffer won't be overwritten.
    return transfer_data(
               mmc_card,
               start,
               nblocks,
               (void *)vbuf,
               pbuf,
               cb,
               token,
               MMC_WRITE_BLOCK);
}

long long mmc_card_capacity(mmc_card_t mmc_card)
{
    int ret;
    struct csd csd;

    ret = mmc_decode_csd(mmc_card, &csd);
    if (ret) {
        return -1;
    }

    long long c_size = (long long)csd.c_size;
    switch (csd.structure) {
    case CSD_VERSION_1: {
        return (c_size + 1) * (1U << (csd.c_size_mult + 2))
               * (1U << csd.read_bl_len);
    }
    case CSD_VERSION_2_AND_3: {
        return (c_size + 1) * 512 * 1024;
    }
    default: {
        return -1;
    }
    }
}


int mmc_nth_irq(mmc_card_t mmc, int n)
{
    return host_nth_irq(mmc, n);
}

int mmc_handle_irq(mmc_card_t mmc, int irq)
{
    return host_handle_irq(mmc, irq);
}


