/*
 * Copyright (c) 2011 The Chromium OS Authors.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <fdtdec.h>
#include <asm/io.h>
#include <asm/arch-tegra/ap.h>
#include <asm/arch/apb_misc.h>
#include <asm/arch/clock.h>
#include <asm/arch/emc.h>
#include <asm/arch/tegra.h>

/*
 * The EMC registers have shadow registers.  When the EMC clock is updated
 * in the clock controller, the shadow registers are copied to the active
 * registers, allowing glitchless memory bus frequency changes.
 * This function updates the shadow registers for a new clock frequency,
 * and relies on the clock lock on the emc clock to avoid races between
 * multiple frequency changes
 */

/*
 * This table defines the ordering of the registers provided to
 * tegra_set_mmc()
 * TODO: Convert to fdt version once available
 */
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
	0x2c,	/* RC */
	0x30,	/* RFC */
	0x34,	/* RAS */
	0x38,	/* RP */
	0x3c,	/* R2W */
	0x40,	/* W2R */
	0x44,	/* R2P */
	0x48,	/* W2P */
	0x4c,	/* RD_RCD */
	0x50,	/* WR_RCD */
	0x54,	/* RRD */
	0x58,	/* REXT */
	0x5c,	/* WDV */
	0x60,	/* QUSE */
	0x64,	/* QRST */
	0x68,	/* QSAFE */
	0x6c,	/* RDV */
	0x70,	/* REFRESH */
	0x74,	/* BURST_REFRESH_NUM */
	0x78,	/* PDEX2WR */
	0x7c,	/* PDEX2RD */
	0x80,	/* PCHG2PDEN */
	0x84,	/* ACT2PDEN */
	0x88,	/* AR2PDEN */
	0x8c,	/* RW2PDEN */
	0x90,	/* TXSR */
	0x94,	/* TCKE */
	0x98,	/* TFAW */
	0x9c,	/* TRPAB */
	0xa0,	/* TCLKSTABLE */
	0xa4,	/* TCLKSTOP */
	0xa8,	/* TREFBW */
	0xac,	/* QUSE_EXTRA */
	0x114,	/* FBIO_CFG6 */
	0xb0,	/* ODT_WRITE */
	0xb4,	/* ODT_READ */
	0x104,	/* FBIO_CFG5 */
	0x2bc,	/* CFG_DIG_DLL */
	0x2c0,	/* DLL_XFORM_DQS */
	0x2c4,	/* DLL_XFORM_QUSE */
	0x2e0,	/* ZCAL_REF_CNT */
	0x2e4,	/* ZCAL_WAIT_CNT */
	0x2a8,	/* AUTO_CAL_INTERVAL */
	0x2d0,	/* CFG_CLKTRIM_0 */
	0x2d4,	/* CFG_CLKTRIM_1 */
	0x2d8,	/* CFG_CLKTRIM_2 */
};

struct emc_ctlr *emc_get_controller(const void *blob)
{
	fdt_addr_t addr;
	int node;

	node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
	if (node > 0) {
		addr = fdtdec_get_addr(blob, node, "reg");
		if (addr != FDT_ADDR_T_NONE)
			return (struct emc_ctlr *)addr;
	}
	return NULL;
}

/* Error codes we use */
enum {
	ERR_NO_EMC_NODE = -10,
	ERR_NO_EMC_REG,
	ERR_NO_FREQ,
	ERR_FREQ_NOT_FOUND,
	ERR_BAD_REGS,
	ERR_NO_RAM_CODE,
	ERR_RAM_CODE_NOT_FOUND,
};

/**
 * Find EMC tables for the given ram code.
 *
 * The tegra EMC binding has two options, one using the ram code and one not.
 * We detect which is in use by looking for the nvidia,use-ram-code property.
 * If this is not present, then the EMC tables are directly below 'node',
 * otherwise we select the correct emc-tables subnode based on the 'ram_code'
 * value.
 *
 * @param blob		Device tree blob
 * @param node		EMC node (nvidia,tegra20-emc compatible string)
 * @param ram_code	RAM code to select (0-3, or -1 if unknown)
 * @return 0 if ok, otherwise a -ve ERR_ code (see enum above)
 */
static int find_emc_tables(const void *blob, int node, int ram_code)
{
	int need_ram_code;
	int depth;
	int offset;

	/* If we are using RAM codes, scan through the tables for our code */
	need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code");
	if (!need_ram_code)
		return node;
	if (ram_code == -1) {
		debug("%s: RAM code required but not supplied\n", __func__);
		return ERR_NO_RAM_CODE;
	}

	offset = node;
	depth = 0;
	do {
		/*
		 * Sadly there is no compatible string so we cannot use
		 * fdtdec_next_compatible_subnode().
		 */
		offset = fdt_next_node(blob, offset, &depth);
		if (depth <= 0)
			break;

		/* Make sure this is a direct subnode */
		if (depth != 1)
			continue;
		if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL)))
			continue;

		if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1)
				== ram_code)
			return offset;
	} while (1);

	debug("%s: Could not find tables for RAM code %d\n", __func__,
	      ram_code);
	return ERR_RAM_CODE_NOT_FOUND;
}

/**
 * Decode the EMC node of the device tree, returning a pointer to the emc
 * controller and the table to be used for the given rate.
 *
 * @param blob	Device tree blob
 * @param rate	Clock speed of memory controller in Hz (=2x memory bus rate)
 * @param emcp	Returns address of EMC controller registers
 * @param tablep Returns pointer to table to program into EMC. There are
 *		TEGRA_EMC_NUM_REGS entries, destined for offsets as per the
 *		emc_reg_addr array.
 * @return 0 if ok, otherwise a -ve error code which will allow someone to
 * figure out roughly what went wrong by looking at this code.
 */
static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp,
		      const u32 **tablep)
{
	struct apb_misc_pp_ctlr *pp =
		(struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE;
	int ram_code;
	int depth;
	int node;

	ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK)
			>> RAM_CODE_SHIFT;
	/*
	 * The EMC clock rate is twice the bus rate, and the bus rate is
	 * measured in kHz
	 */
	rate = rate / 2 / 1000;

	node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC);
	if (node < 0) {
		debug("%s: No EMC node found in FDT\n", __func__);
		return ERR_NO_EMC_NODE;
	}
	*emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg");
	if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) {
		debug("%s: No EMC node reg property\n", __func__);
		return ERR_NO_EMC_REG;
	}

	/* Work out the parent node which contains our EMC tables */
	node = find_emc_tables(blob, node, ram_code & 3);
	if (node < 0)
		return node;

	depth = 0;
	for (;;) {
		int node_rate;

		node = fdtdec_next_compatible_subnode(blob, node,
				COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth);
		if (node < 0)
			break;
		node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1);
		if (node_rate == -1) {
			debug("%s: Missing clock-frequency\n", __func__);
			return ERR_NO_FREQ; /* we expect this property */
		}

		if (node_rate == rate)
			break;
	}
	if (node < 0) {
		debug("%s: No node found for clock frequency %d\n", __func__,
		      rate);
		return ERR_FREQ_NOT_FOUND;
	}

	*tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers",
				      TEGRA_EMC_NUM_REGS);
	if (!*tablep) {
		debug("%s: node '%s' array missing / wrong size\n", __func__,
		      fdt_get_name(blob, node, NULL));
		return ERR_BAD_REGS;
	}

	/* All seems well */
	return 0;
}

int tegra_set_emc(const void *blob, unsigned rate)
{
	struct emc_ctlr *emc;
	const u32 *table = NULL;
	int err, i;

	err = decode_emc(blob, rate, &emc, &table);
	if (err) {
		debug("Warning: no valid EMC (%d), memory timings unset\n",
		       err);
		return err;
	}

	debug("%s: Table found, setting EMC values as follows:\n", __func__);
	for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) {
		u32 value = fdt32_to_cpu(table[i]);
		u32 addr = (uintptr_t)emc + emc_reg_addr[i];

		debug("   %#x: %#x\n", addr, value);
		writel(value, addr);
	}

	/* trigger emc with new settings */
	clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY,
				clock_get_rate(CLOCK_ID_MEMORY), NULL);
	debug("EMC clock set to %lu\n",
	      clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY));

	return 0;
}
