/*
 * This code was extracted from:
 * git://github.com/gonzoua/u-boot-pi.git master
 * and hence presumably (C) 2012 Oleksandr Tymoshenko
 *
 * Tweaks for U-Boot upstreaming
 * (C) 2012 Stephen Warren
 *
 * Portions (e.g. read/write macros, concepts for back-to-back register write
 * timing workarounds) obviously extracted from the Linux kernel at:
 * https://github.com/raspberrypi/linux.git rpi-3.6.y
 *
 * The Linux kernel code has the following (c) and license, which is hence
 * propagated to Oleksandr's tree and here:
 *
 * Support for SDHCI device on 2835
 * Based on sdhci-bcm2708.c (c) 2010 Broadcom
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* Supports:
 * SDHCI platform device - Arasan SD controller in BCM2708
 *
 * Inspired by sdhci-pci.c, by Pierre Ossman
 */

#include <dm.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
#include <sdhci.h>
#include <time.h>
#include <asm/arch/msg.h>
#include <asm/arch/mbox.h>
#include <mach/sdhci.h>
#include <mach/timer.h>

/* 400KHz is max freq for card ID etc. Use that as min */
#define MIN_FREQ 400000
#define SDHCI_BUFFER 0x20

struct bcm2835_sdhci_plat {
	struct mmc_config cfg;
	struct mmc mmc;
};

struct bcm2835_sdhci_host {
	struct sdhci_host host;
	uint twoticks_delay;
	ulong last_write;
};

static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host)
{
	return (struct bcm2835_sdhci_host *)host;
}

static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val,
					    int reg)
{
	struct bcm2835_sdhci_host *bcm_host = to_bcm(host);

	/*
	 * The Arasan has a bugette whereby it may lose the content of
	 * successive writes to registers that are within two SD-card clock
	 * cycles of each other (a clock domain crossing problem).
	 * It seems, however, that the data register does not have this problem.
	 * (Which is just as well - otherwise we'd have to nobble the DMA engine
	 * too)
	 */
	if (reg != SDHCI_BUFFER) {
		while (timer_get_us() - bcm_host->last_write <
		       bcm_host->twoticks_delay)
			;
	}

	writel(val, host->ioaddr + reg);
	bcm_host->last_write = timer_get_us();
}

static inline u32 bcm2835_sdhci_raw_readl(struct sdhci_host *host, int reg)
{
	return readl(host->ioaddr + reg);
}

static void bcm2835_sdhci_writel(struct sdhci_host *host, u32 val, int reg)
{
	bcm2835_sdhci_raw_writel(host, val, reg);
}

static void bcm2835_sdhci_writew(struct sdhci_host *host, u16 val, int reg)
{
	static u32 shadow;
	u32 oldval = (reg == SDHCI_COMMAND) ? shadow :
		bcm2835_sdhci_raw_readl(host, reg & ~3);
	u32 word_num = (reg >> 1) & 1;
	u32 word_shift = word_num * 16;
	u32 mask = 0xffff << word_shift;
	u32 newval = (oldval & ~mask) | (val << word_shift);

	if (reg == SDHCI_TRANSFER_MODE)
		shadow = newval;
	else
		bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
}

static void bcm2835_sdhci_writeb(struct sdhci_host *host, u8 val, int reg)
{
	u32 oldval = bcm2835_sdhci_raw_readl(host, reg & ~3);
	u32 byte_num = reg & 3;
	u32 byte_shift = byte_num * 8;
	u32 mask = 0xff << byte_shift;
	u32 newval = (oldval & ~mask) | (val << byte_shift);

	bcm2835_sdhci_raw_writel(host, newval, reg & ~3);
}

static u32 bcm2835_sdhci_readl(struct sdhci_host *host, int reg)
{
	u32 val = bcm2835_sdhci_raw_readl(host, reg);

	return val;
}

static u16 bcm2835_sdhci_readw(struct sdhci_host *host, int reg)
{
	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
	u32 word_num = (reg >> 1) & 1;
	u32 word_shift = word_num * 16;
	u32 word = (val >> word_shift) & 0xffff;

	return word;
}

static u8 bcm2835_sdhci_readb(struct sdhci_host *host, int reg)
{
	u32 val = bcm2835_sdhci_raw_readl(host, (reg & ~3));
	u32 byte_num = reg & 3;
	u32 byte_shift = byte_num * 8;
	u32 byte = (val >> byte_shift) & 0xff;

	return byte;
}

static const struct sdhci_ops bcm2835_ops = {
	.write_l = bcm2835_sdhci_writel,
	.write_w = bcm2835_sdhci_writew,
	.write_b = bcm2835_sdhci_writeb,
	.read_l = bcm2835_sdhci_readl,
	.read_w = bcm2835_sdhci_readw,
	.read_b = bcm2835_sdhci_readb,
};

static int bcm2835_sdhci_bind(struct udevice *dev)
{
	struct bcm2835_sdhci_plat *plat = dev_get_plat(dev);

	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
}

static int bcm2835_sdhci_probe(struct udevice *dev)
{
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	struct bcm2835_sdhci_plat *plat = dev_get_plat(dev);
	struct bcm2835_sdhci_host *priv = dev_get_priv(dev);
	struct sdhci_host *host = &priv->host;
	fdt_addr_t base;
	int emmc_freq;
	int ret;
	int clock_id = (int)dev_get_driver_data(dev);

	base = dev_read_addr(dev);
	if (base == FDT_ADDR_T_NONE)
		return -EINVAL;

	ret = bcm2835_get_mmc_clock(clock_id);
	if (ret < 0) {
		debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret);
		return ret;
	}
	emmc_freq = ret;

	/*
	 * See the comments in bcm2835_sdhci_raw_writel().
	 *
	 * This should probably be dynamically calculated based on the actual
	 * frequency. However, this is the longest we'll have to wait, and
	 * doesn't seem to slow access down too much, so the added complexity
	 * doesn't seem worth it for now.
	 *
	 * 1/MIN_FREQ is (max) time per tick of eMMC clock.
	 * 2/MIN_FREQ is time for two ticks.
	 * Multiply by 1000000 to get uS per two ticks.
	 * +1 for hack rounding.
	 */
	priv->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1;
	priv->last_write = 0;

	host->name = dev->name;
	host->ioaddr = (void *)(uintptr_t)base;
	host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B |
		SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT;
	host->max_clk = emmc_freq;
	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
	host->ops = &bcm2835_ops;

	host->mmc = &plat->mmc;
	host->mmc->dev = dev;

	ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ);
	if (ret) {
		debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret);
		return ret;
	}

	upriv->mmc = &plat->mmc;
	host->mmc->priv = host;

	return sdhci_probe(dev);
}

static const struct udevice_id bcm2835_sdhci_match[] = {
	{
		.compatible = "brcm,bcm2835-sdhci",
		.data = BCM2835_MBOX_CLOCK_ID_EMMC
	},
	{
		.compatible = "brcm,bcm2711-emmc2",
		.data = BCM2835_MBOX_CLOCK_ID_EMMC2
	},
	{ /* sentinel */ }
};

U_BOOT_DRIVER(sdhci_cdns) = {
	.name = "sdhci-bcm2835",
	.id = UCLASS_MMC,
	.of_match = bcm2835_sdhci_match,
	.bind = bcm2835_sdhci_bind,
	.probe = bcm2835_sdhci_probe,
	.priv_auto	= sizeof(struct bcm2835_sdhci_host),
	.plat_auto	= sizeof(struct bcm2835_sdhci_plat),
	.ops = &sdhci_ops,
};
