/*
 * Copyright (c) 2014 The Linux Foundation. All rights reserved.

 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
*/

#include <config.h>
#include <common.h>
#include <command.h>
#include <mmc.h>
#include <part.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm-generic/errno.h>
#include <asm/arch-qca-common/qca_common.h>
#include "qca_mmc.h"

static inline void qca_reg_wr_delay(qca_mmc  *host)
{
	while (readl(host->base + MCI_STATUS2) & MCI_MCLK_REG_WR_ACTIVE);
}

static inline void
qca_start_command_exec(qca_mmc  *host, struct mmc_cmd *cmd)
{
	unsigned int c = 0;
	unsigned int arg = cmd->cmdarg;

	writel(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);

	qca_reg_wr_delay(host);

	c |= (cmd->cmdidx | MCI_CPSM_ENABLE);

	if (cmd->resp_type & MMC_RSP_PRESENT) {
		if (cmd->resp_type & MMC_RSP_136)
			c |= MCI_CPSM_LONGRSP;
		c |= MCI_CPSM_RESPONSE;
	}

	if ((cmd->resp_type & MMC_RSP_R1b) == MMC_RSP_R1b) {
		c |= MCI_CPSM_PROGENA;
	}

	writel(arg, host->base + MMCIARGUMENT);
	writel(c, host->base + MMCICOMMAND);
	qca_reg_wr_delay(host);
}

static int
qca_start_command(qca_mmc *host, struct mmc_cmd *cmd)
{
	unsigned int status = 0;
	int rc = 0;

	qca_start_command_exec(host, cmd);

	while (readl(host->base + MMCISTATUS) & MCI_CMDACTIVE);

	status = readl(host->base + MMCISTATUS);

	if ((cmd->resp_type != MMC_RSP_NONE)) {

		if (status & MCI_CMDTIMEOUT) {
			rc = TIMEOUT;
		}
		/*  MMC_CMD_SEND_OP_COND response doesn't have CRC. */
		if ((status & MCI_CMDCRCFAIL) && (cmd->cmdidx != MMC_CMD_SEND_OP_COND)) {
			rc = UNUSABLE_ERR;
		}
		cmd->response[0] = readl(host->base + MMCIRESPONSE0);
		/*
		 * Read rest of the response registers only if
		 * long response is expected for this command
		 */
		if (cmd->resp_type & MMC_RSP_136) {
			cmd->response[1] = readl(host->base + MMCIRESPONSE1);
			cmd->response[2] = readl(host->base + MMCIRESPONSE2);
			cmd->response[3] = readl(host->base + MMCIRESPONSE3);
		}
	}

	writel(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
	qca_reg_wr_delay(host);

	return rc;
}


static int
qca_pio_read(qca_mmc *host, char *buffer, unsigned int remain)
{
	unsigned int *ptr = (unsigned int *) buffer;
	unsigned int status = 0;
	unsigned int count = 0;
	unsigned int error = MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_RXOVERRUN;
	unsigned int i;


	do {
		status = readl(host->base + MMCISTATUS);
		udelay(1);

		if (status & error) {
			break;
		}

		if (status & MCI_RXDATAAVLBL ) {
			unsigned rd_cnt = 1;

			if (status & MCI_RXFIFOHALFFULL) {
				rd_cnt = MCI_HFIFO_COUNT;
			}

			for (i = 0; i < rd_cnt; i++) {
				*ptr = readl(host->base + MMCIFIFO +
					(count % MCI_FIFOSIZE));
				ptr++;
				count += sizeof(unsigned int);
			}

			if (count == remain)
				break;

		} else if (status & MCI_DATAEND) {
			break;
		}
	} while (1);

	return count;
}

static int
qca_pio_write(qca_mmc *host, const char *buffer,
		  unsigned int remain)
{
	unsigned int *ptr = (unsigned int *) buffer;
	unsigned int status = 0;
	unsigned int count = 0;
	unsigned int error = MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_TXUNDERRUN;
	unsigned int bcnt = 0;
	unsigned int sz = 0;
	int i;

	do {
		status = readl(host->base + MMCISTATUS);

		if (status & error)
			break;

		bcnt = remain - count;

		if (!bcnt)
			break;

		if ((status & MCI_TXFIFOEMPTY) ||
			(status & MCI_TXFIFOHALFEMPTY)) {

			sz = ((bcnt >> 2) >  MCI_HFIFO_COUNT) \
					? MCI_HFIFO_COUNT : (bcnt >> 2);

			for (i = 0; i < sz; i++) {
				writel(*ptr, host->base + MMCIFIFO);
				ptr++;
				count += sizeof(unsigned int);
			}
		}
	} while (1);

	do {
		status = readl(host->base + MMCISTATUS);

		if (status & error) {
			printf("Error: %s, status=0x%x\n", __func__, status);
			count = status;
			break;
		}
	} while (!(status & MCI_DATAEND));

	return count;
}

static int
qca_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
	unsigned int datactrl = 0;
	qca_mmc *host = mmc->priv;
	unsigned int xfer_size ;
	int status = 0;

	if (data) {
		writel((readl(host->base + MMCICLOCK) | MCI_CLK_FLOWENA),
						host->base + MMCICLOCK);
		xfer_size = data->blocksize * data->blocks;
		datactrl = MCI_DPSM_ENABLE | (data->blocksize << 4);
		writel(0xffffffff, host->base + MMCIDATATIMER);

		if (data->flags & MMC_DATA_READ)
			datactrl |= (MCI_DPSM_DIRECTION | MCI_RX_DATA_PEND);

		writel(xfer_size, host->base + MMCIDATALENGTH);
		writel(datactrl, host->base + MMCIDATACTRL);
		qca_reg_wr_delay(host);

		status = qca_start_command(host, cmd);

		if (data->flags & MMC_DATA_READ) {
			qca_pio_read(host, data->dest, xfer_size);
		} else {
			if (qca_pio_write(host, data->src, xfer_size) != xfer_size)
				status = -1;
		}
		writel(0, host->base + MMCIDATACTRL);
		qca_reg_wr_delay(host);
	} else if (cmd) {
		status = qca_start_command(host, cmd);
	}

	return status;
}


void qca_set_ios(struct mmc *mmc)
{
	qca_mmc *host = mmc->priv;
	u32 clk = 0, pwr = 0;
	int mode;

	if (mmc->clock <= mmc->cfg->f_min) {
		mode = MMC_IDENTIFY_MODE;
	} else {
		mode = MMC_DATA_TRANSFER_MODE;
	}

	if (mode != host->clk_mode) {
		host->clk_mode = mode;
		emmc_clock_config(host->clk_mode);
	}

	pwr = MCI_PWR_UP | MCI_PWR_ON;

	writel(pwr, host->base + MMCIPOWER);
	qca_reg_wr_delay(host);
	clk = readl(host->base + MMCICLOCK);

	clk |= MCI_CLK_ENABLE;
	clk |= MCI_CLK_SELECTIN;
	clk |= MCI_CLK_FLOWENA;
	/* feedback clock */
	clk |= (2 << 14);

	if (mmc->bus_width == 1) {
		 clk |= MCI_CLK_WIDEBUS_1;
	} else if (mmc->bus_width == 4) {
		clk |= MCI_CLK_WIDEBUS_4;
	} else if (mmc->bus_width == 8) {
		 clk |= MCI_CLK_WIDEBUS_8;
	}

	/* Select free running MCLK as input clock of cm_dll_sdc4 */
	clk |= (2 << 23);

	/* Don't write into registers if clocks are disabled */
	writel(clk, host->base + MMCICLOCK);
	qca_reg_wr_delay(host);

	writel((readl(host->base + MMCICLOCK) | MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
	qca_reg_wr_delay(host);
}

int qca_mmc_start (struct mmc *mmc)
{
	qca_mmc *host = mmc->priv;

	writel(readl(host->base + MMCIPOWER) | MCI_SW_RST,
			host->base + MMCIPOWER);
	qca_reg_wr_delay(host);

	while (readl(host->base + MMCIPOWER) & MCI_SW_RST) {
		udelay(10);
	}

	return 0;
}
static struct mmc_ops qca_mmc_ops = {
	.send_cmd = qca_mmc_send_cmd,
	.set_ios = qca_set_ios,
	.init = qca_mmc_start
};

int qca_mmc_init(bd_t *bis, qca_mmc *host)
{
	struct mmc_config *cfg;
	struct mmc *mmc;
	int ret = 0;

	cfg = malloc(sizeof(struct mmc_config));
	if (!cfg) {
	    return -ENOMEM;
	}

	memset(cfg, 0, sizeof(struct mmc_config));

	cfg->ops = &qca_mmc_ops;
	cfg->f_min = 400000;
	cfg->f_max = 52000000;
	cfg->b_max = 512;

	/* voltage either 2.7-3.6V or 1.70 -1.95V  */
	cfg->voltages = 0x40FF8080;
	cfg->host_caps = MMC_MODE_8BIT;
	cfg->host_caps |= MMC_MODE_HC;
	cfg->part_type = PART_TYPE_EFI;

	mmc = mmc_create(cfg, host);
	if (!mmc) {
		puts("mmc_create failed\n");
		free(cfg);
		ret = -ENODEV;
	} else {

		host->mmc = mmc;
		host->dev_num = mmc->block_dev.dev;
		mmc->has_init = 0;
		mmc->init_in_progress = 0;
	}

	return ret;
}
