/*
 * Copyright (c) 2016, NVIDIA CORPORATION.
 * Copright 2019, 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 GNU General Public License version 2. Note that NO WARRANTY is provided.
 * See "LICENSE_GPLv2.txt" for details.
 *
 * @TAG(DATA61_GPL)
 */

/*
 * This is a port of the Tegra186 BPMP sources from U-boot with some additional
 * modifications. Similar to the Tegra IVC protocol, there's no documentation
 * on the BPMP module ABI.
 */

#include <string.h>

#include <platsupport/pmem.h>
#include <tx2bpmp/bpmp.h>
#include <tx2bpmp/hsp.h>
#include <tx2bpmp/ivc.h>
#include <utils/util.h>

#define BPMP_IVC_FRAME_COUNT 1
#define BPMP_IVC_FRAME_SIZE 128

#define BPMP_FLAG_DO_ACK	BIT(0)
#define BPMP_FLAG_RING_DOORBELL	BIT(1)

#define TX_SHMEM 0
#define RX_SHMEM 1
#define NUM_SHMEM 2

#define TIMEOUT_THRESHOLD 2000000ul

struct tx2_bpmp_priv {
    ps_io_ops_t *io_ops;
    tx2_hsp_t hsp;
    bool hsp_initialised;
    struct tegra_ivc ivc;
    void *tx_base; // Virtual address base of the TX shared memory channel
    void *rx_base; // Virtual address base of the RX shared memory channel
};

pmem_region_t bpmp_shmems[NUM_SHMEM] = {
    {
        .type = PMEM_TYPE_DEVICE,
        .base_addr = TX2_BPMP_TX_SHMEM_PADDR,
        .length = TX2_BPMP_TX_SHMEM_SIZE
    },
    {
        .type = PMEM_TYPE_DEVICE,
        .base_addr = TX2_BPMP_RX_SHMEM_PADDR,
        .length = TX2_BPMP_RX_SHMEM_SIZE
    }
};

static bool bpmp_initialised = false;
static unsigned int bpmp_refcount = 0;
static struct tx2_bpmp_priv bpmp_data = {0};

static int bpmp_call(void *data, int mrq, void *tx_msg, size_t tx_size, void *rx_msg, size_t rx_size)
{
	int ret, err;
	void *ivc_frame;
	struct mrq_request *req;
	struct mrq_response *resp;
	unsigned long timeout = TIMEOUT_THRESHOLD;

    struct tx2_bpmp_priv *bpmp_priv = data;

	if ((tx_size > BPMP_IVC_FRAME_SIZE) || (rx_size > BPMP_IVC_FRAME_SIZE))
		return -EINVAL;

	ret = tegra_ivc_write_get_next_frame(&bpmp_priv->ivc, &ivc_frame);
	if (ret) {
		ZF_LOGE("tegra_ivc_write_get_next_frame() failed: %d\n", ret);
		return ret;
	}

	req = ivc_frame;
	req->mrq = mrq;
	req->flags = BPMP_FLAG_DO_ACK | BPMP_FLAG_RING_DOORBELL;
	memcpy(req + 1, tx_msg, tx_size);

	ret = tegra_ivc_write_advance(&bpmp_priv->ivc);
	if (ret) {
		ZF_LOGE("tegra_ivc_write_advance() failed: %d\n", ret);
		return ret;
	}

	for (; timeout > 0; timeout--) {
		ret = tegra_ivc_channel_notified(&bpmp_priv->ivc);
		if (ret) {
			ZF_LOGE("tegra_ivc_channel_notified() failed: %d\n", ret);
			return ret;
		}

		ret = tegra_ivc_read_get_next_frame(&bpmp_priv->ivc, &ivc_frame);
		if (!ret)
			break;
	}

    if (!timeout) {
        ZF_LOGE("tegra_ivc_read_get_next_frame() timed out (%d)\n", ret);
        return -ETIMEDOUT;
    }

	resp = ivc_frame;
	err = resp->err;
	if (!err && rx_msg && rx_size)
		memcpy(rx_msg, resp + 1, rx_size);

	ret = tegra_ivc_read_advance(&bpmp_priv->ivc);
	if (ret) {
		ZF_LOGE("tegra_ivc_write_advance() failed: %d\n", ret);
		return ret;
	}

	if (err) {
		ZF_LOGE("BPMP responded with error %d\n", err);
		/* err isn't a U-Boot error code, so don't that */
		return -EIO;
	}

	return rx_size;
}

static void bpmp_ivc_notify(struct tegra_ivc *ivc, void *token)
{
	struct tx2_bpmp_priv *bpmp_priv = token;
	int ret;

	ret = tx2_hsp_doorbell_ring(&bpmp_priv->hsp, BPMP_DBELL);
	if (ret)
		ZF_LOGF("Failed to ring BPMP's doorbell in the HSP: %d\n", ret);
}

static int bpmp_destroy(void *data)
{
    struct tx2_bpmp_priv *bpmp_priv = data;

    bpmp_refcount--;

    if (bpmp_refcount != 0) {
        /* Only cleanup the BPMP structure if there are no more references that are valid. */
        return 0;
    }

    if (bpmp_priv->hsp_initialised) {
        ZF_LOGF_IF(tx2_hsp_destroy(&bpmp_priv->hsp),
                   "Failed to clean up after a failed BPMP initialisation process!");
    }

    /* Unmapping the shared memory also destroys the IVC */
    if (bpmp_priv->tx_base) {
        ps_io_unmap(&bpmp_priv->io_ops->io_mapper, bpmp_priv->tx_base, bpmp_shmems[TX_SHMEM].length);
    }

    if (bpmp_priv->rx_base) {
        ps_io_unmap(&bpmp_priv->io_ops->io_mapper, bpmp_priv->rx_base, bpmp_shmems[RX_SHMEM].length);
    }

    return 0;
}

int tx2_bpmp_init(ps_io_ops_t *io_ops, struct tx2_bpmp *bpmp)
{
    if (!io_ops || !bpmp) {
        ZF_LOGE("Arguments are NULL!");
        return -EINVAL;
    }

    if (bpmp_initialised) {
        /* If we've initialised the BPMP once, just fill the private data with
         * what we've initialised */
        goto success;
    }

    int ret = 0;
    /* Not sure if this is too long or too short. */
    unsigned long timeout = TIMEOUT_THRESHOLD;

    ret = tx2_hsp_init(io_ops, &bpmp_data.hsp);
    if (ret) {
        ZF_LOGE("Failed to initialise the HSP device for BPMP");
        return ret;
    }

    bpmp_data.io_ops = io_ops;

    bpmp_data.hsp_initialised = true;

    bpmp_data.tx_base = ps_pmem_map(io_ops, bpmp_shmems[TX_SHMEM], false, PS_MEM_NORMAL);
    if (!bpmp_data.tx_base) {
        ZF_LOGE("Failed to map the TX BPMP channel");
        ret = -ENOMEM;
        goto fail;
    }

    bpmp_data.rx_base = ps_pmem_map(io_ops, bpmp_shmems[RX_SHMEM], false, PS_MEM_NORMAL);
    if (!bpmp_data.rx_base) {
        ZF_LOGE("Failed to map the RX BPMP channel");
        ret = -ENOMEM;
        goto fail;
    }

    ret = tegra_ivc_init(&bpmp_data.ivc, (unsigned long) bpmp_data.rx_base, (unsigned long) bpmp_data.tx_base,
                         BPMP_IVC_FRAME_COUNT, BPMP_IVC_FRAME_SIZE, bpmp_ivc_notify, (void *) &bpmp_data);
    if (ret) {
        ZF_LOGE("tegra_ivc_init() failed: %d", ret);
        goto fail;
    }

    tegra_ivc_channel_reset(&bpmp_data.ivc);
    for (; timeout > 0; timeout--) {
        ret = tegra_ivc_channel_notified(&bpmp_data.ivc);
        if (!ret) {
            break;
        }
    }

    if (!timeout) {
        ZF_LOGE("Initial IVC reset timed out (%d)", ret);
        ret = -ETIMEDOUT;
        goto fail;
    }

success:
    bpmp_refcount++;

    bpmp->data = &bpmp_data;
    bpmp->call = bpmp_call;
    bpmp->destroy = bpmp_destroy;
    bpmp_initialised = true;

    return 0;

fail:
    ZF_LOGF_IF(bpmp_destroy(&bpmp_data), "Failed to cleanup the BPMP after a failed initialisation");
    return ret;
}


