/*
 * Copyright 2011, Marvell Semiconductor Inc.
 * Lei Wen <leiwen@marvell.com>
 *
 * Copyright 2017 Intel Corporation
 *
 * Secure Digital (SD) Host Controller interface specific code
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * 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 "bouncebuf.h"
#include <commonlib/sd_mmc_ctrlr.h>
#include <commonlib/sdhci.h>
#include <commonlib/storage.h>
#include <delay.h>
#include <endian.h>
#include "sdhci.h"
#include "sd_mmc.h"
#include "storage.h"
#include <timer.h>
#include <commonlib/stdlib.h>

#define DMA_AVAILABLE	((CONFIG(SDHCI_ADMA_IN_BOOTBLOCK) && ENV_BOOTBLOCK) \
			|| (CONFIG(SDHCI_ADMA_IN_VERSTAGE) && ENV_VERSTAGE) \
			|| (CONFIG(SDHCI_ADMA_IN_ROMSTAGE) && ENV_ROMSTAGE) \
			|| ENV_POSTCAR || ENV_RAMSTAGE)

__weak void *dma_malloc(size_t length_in_bytes)
{
	return malloc(length_in_bytes);
}

void sdhci_reset(struct sdhci_ctrlr *sdhci_ctrlr, u8 mask)
{
	struct stopwatch sw;

	/* Wait max 100 ms */
	stopwatch_init_msecs_expire(&sw, 100);

	sdhci_writeb(sdhci_ctrlr, mask, SDHCI_SOFTWARE_RESET);
	while (sdhci_readb(sdhci_ctrlr, SDHCI_SOFTWARE_RESET) & mask) {
		if (stopwatch_expired(&sw)) {
			sdhc_error("Reset 0x%x never completed.\n", (int)mask);
			return;
		}
		udelay(1000);
	}
}

void sdhci_cmd_done(struct sdhci_ctrlr *sdhci_ctrlr, struct mmc_command *cmd)
{
	int i;
	if (cmd->resp_type & CARD_RSP_136) {
		/* CRC is stripped so we need to do some shifting. */
		for (i = 0; i < 4; i++) {
			cmd->response[i] = sdhci_readl(sdhci_ctrlr,
					SDHCI_RESPONSE + (3-i)*4) << 8;
			if (i != 3)
				cmd->response[i] |= sdhci_readb(sdhci_ctrlr,
						SDHCI_RESPONSE + (3-i)*4-1);
		}
		sdhc_log_response(4, &cmd->response[0]);
		sdhc_trace("Response: 0x%08x.%08x.%08x.%08x\n",
			cmd->response[3], cmd->response[2], cmd->response[1],
			cmd->response[0]);
	} else {
		cmd->response[0] = sdhci_readl(sdhci_ctrlr, SDHCI_RESPONSE);
		sdhc_log_response(1, &cmd->response[0]);
		sdhc_trace("Response: 0x%08x\n", cmd->response[0]);
	}
}

static int sdhci_transfer_data(struct sdhci_ctrlr *sdhci_ctrlr,
	struct mmc_data *data, unsigned int start_addr)
{
	uint32_t block_count;
	uint32_t *buffer;
	uint32_t *buffer_end;
	uint32_t ps;
	uint32_t ps_mask;
	uint32_t stat;
	struct stopwatch sw;

	block_count = 0;
	buffer = (uint32_t *)data->dest;
	ps_mask = (data->flags & DATA_FLAG_READ)
		? SDHCI_DATA_AVAILABLE : SDHCI_SPACE_AVAILABLE;
	stopwatch_init_msecs_expire(&sw, 100);
	do {
		/* Stop transfers if there is an error */
		stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
		sdhci_writel(sdhci_ctrlr, stat, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			sdhc_error("Error detected in status(0x%X)!\n", stat);
			return -1;
		}

		/* Determine if the buffer is ready to move data */
		ps = sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE);
		if (!(ps & ps_mask)) {
			if (stopwatch_expired(&sw)) {
				sdhc_error("Transfer data timeout\n");
				return -1;
			}
			udelay(1);
			continue;
		}

		/* Transfer a block of data */
		buffer_end = &buffer[data->blocksize >> 2];
		if (data->flags == DATA_FLAG_READ)
			while (buffer_end > buffer)
				*buffer++ = sdhci_readl(sdhci_ctrlr,
					SDHCI_BUFFER);
		else
			while (buffer_end > buffer)
				sdhci_writel(sdhci_ctrlr, *buffer++,
					SDHCI_BUFFER);
		if (++block_count >= data->blocks)
			break;
	} while (!(stat & SDHCI_INT_DATA_END));
	return 0;
}

static int sdhci_send_command_bounced(struct sd_mmc_ctrlr *ctrlr,
	struct mmc_command *cmd, struct mmc_data *data,
	struct bounce_buffer *bbstate)
{
	struct sdhci_ctrlr *sdhci_ctrlr = (struct sdhci_ctrlr *)ctrlr;
	u16 mode = 0;
	unsigned int stat = 0;
	int ret = 0;
	u32 mask, flags;
	unsigned int timeout, start_addr = 0;
	struct stopwatch sw;

	/* Wait max 1 s */
	timeout = 1000;

	sdhci_writel(sdhci_ctrlr, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
	mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;

	/* We shouldn't wait for data inihibit for stop commands, even
	   though they might use busy signaling */
	if (cmd->flags & CMD_FLAG_IGNORE_INHIBIT)
		mask &= ~SDHCI_DATA_INHIBIT;

	while (sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE) & mask) {
		if (timeout == 0) {
			sdhc_trace("Cmd: %2d, Arg: 0x%08x, not sent\n",
					cmd->cmdidx, cmd->cmdarg);
			sdhc_error("Controller never released inhibit bit(s), "
			       "present state %#8.8x.\n",
			       sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE));
			return CARD_COMM_ERR;
		}
		timeout--;
		udelay(1000);
	}

	mask = SDHCI_INT_RESPONSE;
	if (!(cmd->resp_type & CARD_RSP_PRESENT))
		flags = SDHCI_CMD_RESP_NONE;
	else if (cmd->resp_type & CARD_RSP_136)
		flags = SDHCI_CMD_RESP_LONG;
	else if (cmd->resp_type & CARD_RSP_BUSY) {
		flags = SDHCI_CMD_RESP_SHORT_BUSY;
		mask |= SDHCI_INT_DATA_END;
	} else
		flags = SDHCI_CMD_RESP_SHORT;

	if (cmd->resp_type & CARD_RSP_CRC)
		flags |= SDHCI_CMD_CRC;
	if (cmd->resp_type & CARD_RSP_OPCODE)
		flags |= SDHCI_CMD_INDEX;
	if (data)
		flags |= SDHCI_CMD_DATA;

	/* Set Transfer mode regarding to data flag */
	if (data) {
		sdhci_writew(sdhci_ctrlr,
			SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
			data->blocksize), SDHCI_BLOCK_SIZE);

		if (data->flags == DATA_FLAG_READ)
			mode |= SDHCI_TRNS_READ;

		if (data->blocks > 1)
			mode |= SDHCI_TRNS_BLK_CNT_EN |
				SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12;

		sdhci_writew(sdhci_ctrlr, data->blocks, SDHCI_BLOCK_COUNT);

		if (DMA_AVAILABLE && (ctrlr->caps & DRVR_CAP_AUTO_CMD12)
			&& (cmd->cmdidx != MMC_CMD_AUTO_TUNING_SEQUENCE)) {
			if (sdhci_setup_adma(sdhci_ctrlr, data))
				return -1;
			mode |= SDHCI_TRNS_DMA;
		}
		sdhci_writew(sdhci_ctrlr, mode, SDHCI_TRANSFER_MODE);
	}

	sdhc_trace("Cmd: %2d, Arg: 0x%08x\n", cmd->cmdidx, cmd->cmdarg);
	sdhci_writel(sdhci_ctrlr, cmd->cmdarg, SDHCI_ARGUMENT);
	sdhci_writew(sdhci_ctrlr, SDHCI_MAKE_CMD(cmd->cmdidx, flags),
		SDHCI_COMMAND);
	sdhc_log_command_issued();

	if (DMA_AVAILABLE && (mode & SDHCI_TRNS_DMA))
		return sdhci_complete_adma(sdhci_ctrlr, cmd);

	stopwatch_init_msecs_expire(&sw, 2550);
	do {
		stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
		if (stat & SDHCI_INT_ERROR) {
			sdhc_trace("Error - IntStatus: 0x%08x\n", stat);
			break;
		}

		if (stat & SDHCI_INT_DATA_AVAIL) {
			sdhci_writel(sdhci_ctrlr, stat, SDHCI_INT_STATUS);
			return 0;
		}

		/* Apply max timeout for R1b-type CMD defined in eMMC ext_csd
		   except for erase ones */
		if (stopwatch_expired(&sw)) {
			if (ctrlr->caps & DRVR_CAP_BROKEN_R1B)
				return 0;
			sdhc_error(
				"Timeout for status update!  IntStatus: 0x%08x\n",
				stat);
			return CARD_TIMEOUT;
		}
	} while ((stat & mask) != mask);

	if ((stat & (SDHCI_INT_ERROR | mask)) == mask) {
		if (cmd->cmdidx)
			sdhci_cmd_done(sdhci_ctrlr, cmd);
		sdhci_writel(sdhci_ctrlr, mask, SDHCI_INT_STATUS);
	} else
		ret = -1;

	if (!ret && data)
		ret = sdhci_transfer_data(sdhci_ctrlr, data, start_addr);

	if (ctrlr->udelay_wait_after_cmd)
		udelay(ctrlr->udelay_wait_after_cmd);

	stat = sdhci_readl(sdhci_ctrlr, SDHCI_INT_STATUS);
	sdhci_writel(sdhci_ctrlr, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);

	if (!ret)
		return 0;

	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_CMD);
	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_DATA);
	if (stat & SDHCI_INT_TIMEOUT) {
		sdhc_error("CMD%d timeout, IntStatus: 0x%08x\n", cmd->cmdidx,
			stat);
		return CARD_TIMEOUT;
	}

	sdhc_error("CMD%d failed, IntStatus: 0x%08x\n", cmd->cmdidx, stat);
	return CARD_COMM_ERR;
}

__weak void sdhc_log_command(struct mmc_command *cmd)
{
}

__weak void sdhc_log_command_issued(void)
{
}

__weak void sdhc_log_response(uint32_t entries,
	uint32_t *response)
{
}

__weak void sdhc_log_ret(int ret)
{
}

static void sdhci_led_control(struct sd_mmc_ctrlr *ctrlr, int on)
{
	uint8_t host_ctrl;
	struct sdhci_ctrlr *sdhci_ctrlr = (struct sdhci_ctrlr *)ctrlr;

	host_ctrl = sdhci_readb(sdhci_ctrlr, SDHCI_HOST_CONTROL);
	host_ctrl &= ~SDHCI_CTRL_LED;
	if (on)
		host_ctrl |= SDHCI_CTRL_LED;
	sdhci_writeb(sdhci_ctrlr, host_ctrl, SDHCI_HOST_CONTROL);
}

static int sdhci_send_command(struct sd_mmc_ctrlr *ctrlr,
	struct mmc_command *cmd, struct mmc_data *data)
{
	void *buf;
	unsigned int bbflags;
	size_t len;
	struct bounce_buffer *bbstate = NULL;
	struct bounce_buffer bbstate_val;
	int ret;

	sdhc_log_command(cmd);

	if (CONFIG(SDHCI_BOUNCE_BUFFER) && data) {
		if (data->flags & DATA_FLAG_READ) {
			buf = data->dest;
			bbflags = GEN_BB_WRITE;
		} else {
			buf = (void *)data->src;
			bbflags = GEN_BB_READ;
		}
		len = data->blocks * data->blocksize;

		/*
		 * on some platform(like rk3399 etc) need to worry about
		 * cache coherency, so check the buffer, if not dma
		 * coherent, use bounce_buffer to do DMA management.
		 */
		if (!dma_coherent(buf)) {
			bbstate = &bbstate_val;
			if (bounce_buffer_start(bbstate, buf, len, bbflags)) {
				sdhc_error(
					"ERROR: Failed to get bounce buffer.\n");
				return -1;
			}
		}
	}

	sdhci_led_control(ctrlr, 1);
	ret = sdhci_send_command_bounced(ctrlr, cmd, data, bbstate);
	sdhci_led_control(ctrlr, 0);
	sdhc_log_ret(ret);

	if (CONFIG(SDHCI_BOUNCE_BUFFER) && bbstate)
		bounce_buffer_stop(bbstate);

	return ret;
}

static int sdhci_set_clock(struct sdhci_ctrlr *sdhci_ctrlr, unsigned int clock)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
	unsigned int actual, div, clk, timeout;

	/* Turn off the clock if requested */
	actual = clock;
	if (actual == 0) {
		sdhci_writew(sdhci_ctrlr, 0, SDHCI_CLOCK_CONTROL);
		sdhc_debug("SDHCI bus clock: Off\n");
		return 0;
	}

	/* Compute the divisor for the new clock frequency */
	actual = MIN(actual, ctrlr->f_max);
	actual = MAX(actual, ctrlr->f_min);
	if (ctrlr->clock_base <= actual)
		div = 0;
	else {
		/* Version 3.00 divisors must be a multiple of 2. */
		if ((ctrlr->version & SDHCI_SPEC_VER_MASK)
			>= SDHCI_SPEC_300) {
			div = MIN(((ctrlr->clock_base + actual - 1)
				/ actual), SDHCI_MAX_DIV_SPEC_300);
			actual = ctrlr->clock_base / div;
			div += 1;
		} else {
			/* Version 2.00 divisors must be a power of 2. */
			for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) {
				if ((ctrlr->clock_base / div) <= actual)
					break;
			}
			actual = ctrlr->clock_base / div;
		}
		div >>= 1;
	}

	/* Set the new clock frequency */
	if (actual != ctrlr->bus_hz) {
		/* Turn off the clock */
		sdhci_writew(sdhci_ctrlr, 0, SDHCI_CLOCK_CONTROL);

		/* Set the new clock frequency */
		clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
		clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
			<< SDHCI_DIVIDER_HI_SHIFT;
		clk |= SDHCI_CLOCK_INT_EN;
		sdhci_writew(sdhci_ctrlr, clk, SDHCI_CLOCK_CONTROL);

		/* Display the requested clock frequency */
		sdhc_debug("SDHCI bus clock: %d.%03d MHz\n",
				actual / 1000000,
				(actual / 1000) % 1000);

		/* Wait max 20 ms */
		timeout = 20;
		while (!((clk = sdhci_readw(sdhci_ctrlr, SDHCI_CLOCK_CONTROL))
			& SDHCI_CLOCK_INT_STABLE)) {
			if (timeout == 0) {
				sdhc_error(
					"Internal clock never stabilised.\n");
				return -1;
			}
			timeout--;
			udelay(1000);
		}

		clk |= SDHCI_CLOCK_CARD_EN;
		sdhci_writew(sdhci_ctrlr, clk, SDHCI_CLOCK_CONTROL);
		ctrlr->bus_hz = actual;
	}
	return 0;
}

/* Find leftmost set bit in a 32 bit integer */
static int fls(u32 x)
{
	int r = 32;

	if (!x)
		return 0;
	if (!(x & 0xffff0000u)) {
		x <<= 16;
		r -= 16;
	}
	if (!(x & 0xff000000u)) {
		x <<= 8;
		r -= 8;
	}
	if (!(x & 0xf0000000u)) {
		x <<= 4;
		r -= 4;
	}
	if (!(x & 0xc0000000u)) {
		x <<= 2;
		r -= 2;
	}
	if (!(x & 0x80000000u)) {
		x <<= 1;
		r -= 1;
	}
	return r;
}

static void sdhci_set_power(struct sdhci_ctrlr *sdhci_ctrlr,
	unsigned short power)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
	u8 pwr = 0;
	u8 pwr_ctrl;
	const char *voltage;

	if (power != (unsigned short)-1) {
		switch (1 << power) {
		case MMC_VDD_165_195:
			voltage = "1.8";
			pwr = SDHCI_POWER_180;
			break;
		case MMC_VDD_29_30:
		case MMC_VDD_30_31:
			voltage = "3.0";
			pwr = SDHCI_POWER_300;
			break;
		case MMC_VDD_32_33:
		case MMC_VDD_33_34:
			voltage = "3.3";
			pwr = SDHCI_POWER_330;
			break;
		}
	}

	/* Determine the power state */
	pwr_ctrl = sdhci_readb(sdhci_ctrlr, SDHCI_POWER_CONTROL);
	if (pwr == 0) {
		if (pwr_ctrl & SDHCI_POWER_ON)
			sdhc_debug("SDHCI voltage: Off\n");
		sdhci_writeb(sdhci_ctrlr, 0, SDHCI_POWER_CONTROL);
		return;
	}

	/* Determine if the power has changed */
	if (pwr_ctrl != (pwr | SDHCI_POWER_ON)) {
		sdhc_debug("SDHCI voltage: %s Volts\n", voltage);

		/* Select the voltage */
		if (ctrlr->caps & DRVR_CAP_NO_SIMULT_VDD_AND_POWER)
			sdhci_writeb(sdhci_ctrlr, pwr, SDHCI_POWER_CONTROL);

		/* Apply power to the SD/MMC device */
		pwr |= SDHCI_POWER_ON;
		sdhci_writeb(sdhci_ctrlr, pwr, SDHCI_POWER_CONTROL);
	}
}

const u16 speed_driver_voltage[] = {
	0, /*  0: BUS_TIMING_LEGACY */
	0, /*  1: BUS_TIMING_MMC_HS */
	0, /*  2: BUS_TIMING_SD_HS */
	SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180, /* 3: BUS_TIMING_UHS_SDR12 */
	SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180, /* 4: BUS_TIMING_UHS_SDR25 */
	SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180, /* 5: BUS_TIMING_UHS_SDR50 */
	/*  6: BUS_TIMING_UHS_SDR104 */
	SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A | SDHCI_CTRL_VDD_180,
	SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180, /* 7: BUS_TIMING_UHS_DDR50 */
	SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180, /* 8: BUS_TIMING_MMC_DDR52 */
	/*  9: BUS_TIMING_MMC_HS200 */
	SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A | SDHCI_CTRL_VDD_180,
	/* 10: BUS_TIMING_MMC_HS400 */
	SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A | SDHCI_CTRL_VDD_180,
	/* 11: BUS_TIMING_MMC_HS400ES */
	SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A | SDHCI_CTRL_VDD_180
};

static void sdhci_set_uhs_signaling(struct sdhci_ctrlr *sdhci_ctrlr,
	uint32_t timing)
{
	u16 ctrl_2;

	/* Select bus speed mode, driver and VDD 1.8 volt support */
	ctrl_2 = sdhci_readw(sdhci_ctrlr, SDHCI_HOST_CONTROL2);
	ctrl_2 &= ~(SDHCI_CTRL_UHS_MASK | SDHCI_CTRL_DRV_TYPE_MASK
		| SDHCI_CTRL_VDD_180);
	if (timing < ARRAY_SIZE(speed_driver_voltage))
		ctrl_2 |= speed_driver_voltage[timing];
	sdhci_writew(sdhci_ctrlr, ctrl_2, SDHCI_HOST_CONTROL2);
}

static void sdhci_set_ios(struct sd_mmc_ctrlr *ctrlr)
{
	struct sdhci_ctrlr *sdhci_ctrlr = (struct sdhci_ctrlr *)ctrlr;
	u32 ctrl;
	u32 previous_ctrl;
	u32 bus_width;
	int version;

	/* Set the clock frequency */
	if (ctrlr->bus_hz != ctrlr->request_hz)
		sdhci_set_clock(sdhci_ctrlr, ctrlr->request_hz);

	/* Switch to 1.8 volt for HS200 */
	if (ctrlr->caps & DRVR_CAP_1V8_VDD)
		if (ctrlr->bus_hz == CLOCK_200MHZ)
			sdhci_set_power(sdhci_ctrlr, MMC_VDD_165_195_SHIFT);

	/* Determine the new bus width */
	bus_width = 1;
	ctrl = sdhci_readb(sdhci_ctrlr, SDHCI_HOST_CONTROL);
	previous_ctrl = ctrl;
	ctrl &= ~SDHCI_CTRL_4BITBUS;
	version = ctrlr->version & SDHCI_SPEC_VER_MASK;
	if (version >= SDHCI_SPEC_300)
		ctrl &= ~SDHCI_CTRL_8BITBUS;

	if ((ctrlr->bus_width == 8) && (version >= SDHCI_SPEC_300)) {
		ctrl |= SDHCI_CTRL_8BITBUS;
		bus_width = 8;
	} else if (ctrlr->bus_width == 4) {
		ctrl |= SDHCI_CTRL_4BITBUS;
		bus_width = 4;
	}

	if (!(ctrlr->timing == BUS_TIMING_LEGACY) &&
	    !(ctrlr->caps & DRVR_CAP_NO_HISPD_BIT))
		ctrl |= SDHCI_CTRL_HISPD;
	else
		ctrl &= ~SDHCI_CTRL_HISPD;

	sdhci_set_uhs_signaling(sdhci_ctrlr, ctrlr->timing);

	if (DMA_AVAILABLE) {
		if (ctrlr->caps & DRVR_CAP_AUTO_CMD12) {
			ctrl &= ~SDHCI_CTRL_DMA_MASK;
			if (ctrlr->caps & DRVR_CAP_DMA_64BIT)
				ctrl |= SDHCI_CTRL_ADMA64;
			else
				ctrl |= SDHCI_CTRL_ADMA32;
		}
	}

	/* Set the new bus width */
	if (CONFIG(SDHC_DEBUG)
		&& ((ctrl ^ previous_ctrl) & (SDHCI_CTRL_4BITBUS
		| ((version >= SDHCI_SPEC_300) ? SDHCI_CTRL_8BITBUS : 0))))
		sdhc_debug("SDHCI bus width: %d bit%s\n", bus_width,
			(bus_width != 1) ? "s" : "");
	sdhci_writeb(sdhci_ctrlr, ctrl, SDHCI_HOST_CONTROL);
}

static void sdhci_tuning_start(struct sd_mmc_ctrlr *ctrlr, int retune)
{
	uint16_t host_ctrl2;
	struct sdhci_ctrlr *sdhci_ctrlr = (struct sdhci_ctrlr *)ctrlr;

	/* Start the bus tuning */
	host_ctrl2 = sdhci_readw(sdhci_ctrlr, SDHCI_HOST_CONTROL2);
	host_ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
	host_ctrl2 |= (retune ? SDHCI_CTRL_TUNED_CLK : 0)
		| SDHCI_CTRL_EXEC_TUNING;
	sdhci_writew(sdhci_ctrlr, host_ctrl2, SDHCI_HOST_CONTROL2);
}

static int sdhci_is_tuning_complete(struct sd_mmc_ctrlr *ctrlr, int *successful)
{
	uint16_t host_ctrl2;
	struct sdhci_ctrlr *sdhci_ctrlr = (struct sdhci_ctrlr *)ctrlr;

	/* Determine if the bus tuning has completed */
	host_ctrl2 = sdhci_readw(sdhci_ctrlr, SDHCI_HOST_CONTROL2);
	*successful = ((host_ctrl2 & SDHCI_CTRL_TUNED_CLK) != 0);
	return ((host_ctrl2 & SDHCI_CTRL_EXEC_TUNING) == 0);
}

/* Prepare SDHCI controller to be initialized */
static int sdhci_pre_init(struct sdhci_ctrlr *sdhci_ctrlr)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
	unsigned int caps, caps_1;

	/* Get controller version and capabilities */
	ctrlr->version = sdhci_readw(sdhci_ctrlr, SDHCI_HOST_VERSION) & 0xff;
	caps = sdhci_readl(sdhci_ctrlr, SDHCI_CAPABILITIES);
	caps_1 = sdhci_readl(sdhci_ctrlr, SDHCI_CAPABILITIES_1);

	/* Determine the supported voltages */
	if (caps & SDHCI_CAN_VDD_330)
		ctrlr->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
	if (caps & SDHCI_CAN_VDD_300)
		ctrlr->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
	if (caps & SDHCI_CAN_VDD_180)
		ctrlr->voltages |= MMC_VDD_165_195;

	/* Get the controller's base clock frequency */
	if ((ctrlr->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
		ctrlr->clock_base = (caps & SDHCI_CLOCK_V3_BASE_MASK)
			>> SDHCI_CLOCK_BASE_SHIFT;
	else
		ctrlr->clock_base = (caps & SDHCI_CLOCK_BASE_MASK)
			>> SDHCI_CLOCK_BASE_SHIFT;
	ctrlr->clock_base *= 1000000;
	ctrlr->f_max = ctrlr->clock_base;

	/* Determine the controller's clock frequency range */
	ctrlr->f_min = 0;
	if ((ctrlr->version & SDHCI_SPEC_VER_MASK) >= SDHCI_SPEC_300)
		ctrlr->f_min =
			ctrlr->clock_base / SDHCI_MAX_DIV_SPEC_300;
	else
		ctrlr->f_min =
			ctrlr->clock_base / SDHCI_MAX_DIV_SPEC_200;

	/* Determine the controller's modes of operation */
	ctrlr->caps |= DRVR_CAP_HS52 | DRVR_CAP_HS;
	if (ctrlr->clock_base >= CLOCK_200MHZ) {
		ctrlr->caps |= DRVR_CAP_HS200 | DRVR_CAP_HS200_TUNING;
		if (caps_1 & SDHCI_SUPPORT_HS400)
			ctrlr->caps |= DRVR_CAP_HS400
				| DRVR_CAP_ENHANCED_STROBE;
	}

	/* Determine the bus widths the controller supports */
	ctrlr->caps |= DRVR_CAP_4BIT;
	if (caps & SDHCI_CAN_DO_8BIT)
		ctrlr->caps |= DRVR_CAP_8BIT;

	/* Determine the controller's DMA support */
	if (caps & SDHCI_CAN_DO_ADMA2)
		ctrlr->caps |= DRVR_CAP_AUTO_CMD12;
	if (DMA_AVAILABLE && (caps & SDHCI_CAN_64BIT))
		ctrlr->caps |= DRVR_CAP_DMA_64BIT;

	/* Specify the modes that the driver stack supports */
	ctrlr->caps |= DRVR_CAP_HC;

	/* Let the SOC adjust the configuration to handle controller quirks */
	soc_sd_mmc_controller_quirks(&sdhci_ctrlr->sd_mmc_ctrlr);
	if (ctrlr->clock_base == 0) {
		sdhc_error("Hardware doesn't specify base clock frequency\n");
		return -1;
	}
	if (!ctrlr->f_max)
		ctrlr->f_max = ctrlr->clock_base;

	/* Display the results */
	sdhc_trace("0x%08x: ctrlr->caps\n", ctrlr->caps);
	sdhc_trace("%d.%03d MHz: ctrlr->clock_base\n",
		ctrlr->clock_base / 1000000,
		(ctrlr->clock_base / 1000) % 1000);
	sdhc_trace("%d.%03d MHz: ctrlr->f_max\n",
		ctrlr->f_max / 1000000,
		(ctrlr->f_max / 1000) % 1000);
	sdhc_trace("%d.%03d MHz: ctrlr->f_min\n",
		ctrlr->f_min / 1000000,
		(ctrlr->f_min / 1000) % 1000);
	sdhc_trace("0x%08x: ctrlr->voltages\n", ctrlr->voltages);

	sdhci_reset(sdhci_ctrlr, SDHCI_RESET_ALL);

	return 0;
}

__weak void soc_sd_mmc_controller_quirks(struct sd_mmc_ctrlr
	*ctrlr)
{
}

static int sdhci_init(struct sdhci_ctrlr *sdhci_ctrlr)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;
	int rv;

	/* Only initialize the controller upon reset or card insertion */
	if (ctrlr->initialized)
		return 0;

	sdhc_debug("SDHCI Controller Base Address: 0x%p\n",
			sdhci_ctrlr->ioaddr);

	rv = sdhci_pre_init(sdhci_ctrlr);
	if (rv)
		return rv; /* The error has been already reported */

	sdhci_set_power(sdhci_ctrlr, fls(ctrlr->voltages) - 1);

	if (ctrlr->caps & DRVR_CAP_NO_CD) {
		unsigned int status;

		sdhci_writel(sdhci_ctrlr, SDHCI_CTRL_CD_TEST_INS
			| SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL);

		status = sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE);
		while ((!(status & SDHCI_CARD_PRESENT)) ||
		    (!(status & SDHCI_CARD_STATE_STABLE)) ||
		    (!(status & SDHCI_CARD_DETECT_PIN_LEVEL)))
			status = sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE);
	}

	/* Enable only interrupts served by the SD controller */
	sdhci_writel(sdhci_ctrlr, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
		     SDHCI_INT_ENABLE);
	/* Mask all sdhci interrupt sources */
	sdhci_writel(sdhci_ctrlr, 0x0, SDHCI_SIGNAL_ENABLE);

	/* Set timeout to maximum, shouldn't happen if everything's right. */
	sdhci_writeb(sdhci_ctrlr, 0xe, SDHCI_TIMEOUT_CONTROL);

	mdelay(10);
	ctrlr->initialized = 1;
	return 0;
}

static int sdhci_update(struct sdhci_ctrlr *sdhci_ctrlr)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;

	if (ctrlr->caps & DRVR_CAP_REMOVABLE) {
		int present = (sdhci_readl(sdhci_ctrlr, SDHCI_PRESENT_STATE) &
			       SDHCI_CARD_PRESENT) != 0;

		if (!present) {
			/* A card was present indicate the controller needs
			 * initialization on the next call.
			 */
			ctrlr->initialized = 0;
			return 0;
		}
	}

	/* A card is present, get it ready. */
	if (sdhci_init(sdhci_ctrlr))
		return -1;
	return 0;
}

void sdhci_update_pointers(struct sdhci_ctrlr *sdhci_ctrlr)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;

	/* Update the routine pointers */
	ctrlr->send_cmd = &sdhci_send_command;
	ctrlr->set_ios = &sdhci_set_ios;
	ctrlr->tuning_start = &sdhci_tuning_start;
	ctrlr->is_tuning_complete = &sdhci_is_tuning_complete;
}

int add_sdhci(struct sdhci_ctrlr *sdhci_ctrlr)
{
	struct sd_mmc_ctrlr *ctrlr = &sdhci_ctrlr->sd_mmc_ctrlr;

	sdhci_update_pointers(sdhci_ctrlr);

	/* TODO(vbendeb): check if SDHCI spec allows to retrieve this value. */
	ctrlr->b_max = 65535;

	/* Initialize the SDHC controller */
	return sdhci_update(sdhci_ctrlr);
}
