#ifndef __MACH_SDRAM_CONFIG_H
#define __MACH_SDRAM_CONFIG_H

#include <mach/cyclone5-sdram.h>
#include <mach/cyclone5-regs.h>
#include <mach/cyclone5-system-manager.h>

static inline void sdram_write(unsigned register_offset, unsigned val)
{
	debug("0x%08x Data 0x%08x\n",
		(CYCLONE5_SDR_ADDRESS + register_offset), val);
	/* Write to register */
	writel(val, (CYCLONE5_SDR_ADDRESS + register_offset));
}

static inline void socfpga_sdram_mmr_init(void)
{
	uint32_t val;

	val = CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE << SDR_CTRLGRP_CTRLCFG_MEMTYPE_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMBL << SDR_CTRLGRP_CTRLCFG_MEMBL_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER << SDR_CTRLGRP_CTRLCFG_ADDRORDER_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN << SDR_CTRLGRP_CTRLCFG_ECCEN_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_ECCCORREN << SDR_CTRLGRP_CTRLCFG_ECCCORREN_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_REORDEREN << SDR_CTRLGRP_CTRLCFG_REORDEREN_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_STARVELIMIT << SDR_CTRLGRP_CTRLCFG_STARVELIMIT_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_DQSTRKEN << SDR_CTRLGRP_CTRLCFG_DQSTRKEN_LSB |
		CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_NODMPINS << SDR_CTRLGRP_CTRLCFG_NODMPINS_LSB;
	sdram_write(SDR_CTRLGRP_CTRLCFG_ADDRESS, val);

	val =  CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCWL << SDR_CTRLGRP_DRAMTIMING1_TCWL_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_AL << SDR_CTRLGRP_DRAMTIMING1_TAL_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCL <<  SDR_CTRLGRP_DRAMTIMING1_TCL_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRRD << SDR_CTRLGRP_DRAMTIMING1_TRRD_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TFAW << SDR_CTRLGRP_DRAMTIMING1_TFAW_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRFC << SDR_CTRLGRP_DRAMTIMING1_TRFC_LSB;
	sdram_write(SDR_CTRLGRP_DRAMTIMING1_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TREFI << SDR_CTRLGRP_DRAMTIMING2_TREFI_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRCD << SDR_CTRLGRP_DRAMTIMING2_TRCD_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRP << SDR_CTRLGRP_DRAMTIMING2_TRP_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWR << SDR_CTRLGRP_DRAMTIMING2_TWR_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWTR << SDR_CTRLGRP_DRAMTIMING2_TWTR_LSB;
	sdram_write(SDR_CTRLGRP_DRAMTIMING2_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRTP << SDR_CTRLGRP_DRAMTIMING3_TRTP_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRAS << SDR_CTRLGRP_DRAMTIMING3_TRAS_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRC << SDR_CTRLGRP_DRAMTIMING3_TRC_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TMRD << SDR_CTRLGRP_DRAMTIMING3_TMRD_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING3_TCCD << SDR_CTRLGRP_DRAMTIMING3_TCCD_LSB;
	sdram_write(SDR_CTRLGRP_DRAMTIMING3_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_SELFRFSHEXIT << SDR_CTRLGRP_DRAMTIMING4_SELFRFSHEXIT_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMTIMING4_PWRDOWNEXIT << SDR_CTRLGRP_DRAMTIMING4_PWRDOWNEXIT_LSB;
	sdram_write(SDR_CTRLGRP_DRAMTIMING4_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_LOWPWRTIMING_AUTOPDCYCLES << SDR_CTRLGRP_LOWPWRTIMING_AUTOPDCYCLES_LSB;
	sdram_write(SDR_CTRLGRP_LOWPWRTIMING_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS << SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS << SDR_CTRLGRP_DRAMADDRW_ROWBITS_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS << SDR_CTRLGRP_DRAMADDRW_BANKBITS_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS << SDR_CTRLGRP_DRAMADDRW_CSBITS_LSB;
	sdram_write(SDR_CTRLGRP_DRAMADDRW_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMIFWIDTH_IFWIDTH << SDR_CTRLGRP_DRAMIFWIDTH_IFWIDTH_LSB;
	sdram_write(SDR_CTRLGRP_DRAMIFWIDTH_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMDEVWIDTH_DEVWIDTH << SDR_CTRLGRP_DRAMDEVWIDTH_DEVWIDTH_LSB;
	sdram_write(SDR_CTRLGRP_DRAMDEVWIDTH_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMINTR_INTREN << SDR_CTRLGRP_DRAMINTR_INTREN_LSB;
	sdram_write(SDR_CTRLGRP_DRAMINTR_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_STATICCFG_MEMBL << SDR_CTRLGRP_STATICCFG_MEMBL_LSB |
		CONFIG_HPS_SDR_CTRLCFG_STATICCFG_USEECCASDATA << SDR_CTRLGRP_STATICCFG_USEECCASDATA_LSB;
	sdram_write(SDR_CTRLGRP_STATICCFG_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_CTRLWIDTH_CTRLWIDTH << SDR_CTRLGRP_CTRLWIDTH_CTRLWIDTH_LSB;
	sdram_write(SDR_CTRLGRP_CTRLWIDTH_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_PORTCFG_AUTOPCHEN << SDR_CTRLGRP_PORTCFG_AUTOPCHEN_LSB;
	sdram_write(SDR_CTRLGRP_PORTCFG_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_SYNCMODE << SDR_CTRLGRP_FIFOCFG_SYNCMODE_LSB |
		CONFIG_HPS_SDR_CTRLCFG_FIFOCFG_INCSYNC << SDR_CTRLGRP_FIFOCFG_INCSYNC_LSB;
	sdram_write(SDR_CTRLGRP_FIFOCFG_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPPRIORITY_USERPRIORITY << SDR_CTRLGRP_MPPRIORITY_USERPRIORITY_LSB;
	sdram_write(SDR_CTRLGRP_MPPRIORITY_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_0_STATICWEIGHT_31_0 << SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_STATICWEIGHT_31_0_LSB;
	sdram_write(SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_0_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_STATICWEIGHT_49_32 << SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_STATICWEIGHT_49_32_LSB |
		CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_SUMOFWEIGHT_13_0 << SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_SUMOFWEIGHTS_13_0_LSB;
	sdram_write(SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_1_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_2_SUMOFWEIGHT_45_14 << SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_SUMOFWEIGHTS_45_14_LSB;
	sdram_write(SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_2_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPWIEIGHT_3_SUMOFWEIGHT_63_46 << SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_SUMOFWEIGHTS_63_46_LSB;
	sdram_write(SDR_CTRLGRP_MPWEIGHT_MPWEIGHT_3_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPPACING_0_THRESHOLD1_31_0 << SDR_CTRLGRP_MPPACING_MPPACING_0_THRESHOLD1_31_0_LSB;
	sdram_write(SDR_CTRLGRP_MPPACING_MPPACING_0_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD1_59_32 << SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD1_59_32_LSB |
		CONFIG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD2_3_0 <<
			SDR_CTRLGRP_MPPACING_MPPACING_1_THRESHOLD2_3_0_LSB;
	sdram_write(SDR_CTRLGRP_MPPACING_MPPACING_1_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPPACING_2_THRESHOLD2_35_4 << SDR_CTRLGRP_MPPACING_MPPACING_2_THRESHOLD2_35_4_LSB;
	sdram_write(SDR_CTRLGRP_MPPACING_MPPACING_2_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPPACING_3_THRESHOLD2_59_36 << SDR_CTRLGRP_MPPACING_MPPACING_3_THRESHOLD2_59_36_LSB;
	sdram_write(SDR_CTRLGRP_MPPACING_MPPACING_3_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0 <<
		SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0_LSB;
	sdram_write(SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_0_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32 <<
		SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32_LSB;
	sdram_write(SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_1_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64 <<
		SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64_LSB;
	sdram_write(SDR_CTRLGRP_MPTHRESHOLDRST_MPTHRESHOLDRST_2_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_PHYCTRL_PHYCTRL_0;
	sdram_write(SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_CPORTWIDTH_CPORTWIDTH << SDR_CTRLGRP_CPORTWIDTH_CMDPORTWIDTH_LSB;
	sdram_write(SDR_CTRLGRP_CPORTWIDTH_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_CPORTWMAP_CPORTWMAP << SDR_CTRLGRP_CPORTWMAP_CPORTWFIFOMAP_LSB;
	sdram_write(SDR_CTRLGRP_CPORTWMAP_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_CPORTRMAP_CPORTRMAP << SDR_CTRLGRP_CPORTRMAP_CPORTRFIFOMAP_LSB;
	sdram_write(SDR_CTRLGRP_CPORTRMAP_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_RFIFOCMAP_RFIFOCMAP << SDR_CTRLGRP_RFIFOCMAP_RFIFOCPORTMAP_LSB;
	sdram_write(SDR_CTRLGRP_RFIFOCMAP_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_WFIFOCMAP_WFIFOCMAP << SDR_CTRLGRP_WFIFOCMAP_WFIFOCPORTMAP_LSB;
	sdram_write(SDR_CTRLGRP_WFIFOCMAP_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_CPORTRDWR_CPORTRDWR << SDR_CTRLGRP_CPORTRDWR_CPORTRDWR_LSB;
	sdram_write(SDR_CTRLGRP_CPORTRDWR_ADDRESS, val);

	val = CONFIG_HPS_SDR_CTRLCFG_DRAMODT_READ << SDR_CTRLGRP_DRAMODT_READ_LSB |
		CONFIG_HPS_SDR_CTRLCFG_DRAMODT_WRITE << SDR_CTRLGRP_DRAMODT_WRITE_LSB;
	sdram_write(SDR_CTRLGRP_DRAMODT_ADDRESS, val);

	val = readl(CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_STATICCFG_ADDRESS);
	val &= ~(SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK);
	val |= 1 << SDR_CTRLGRP_STATICCFG_APPLYCFG_LSB;
	writel(val, (CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_STATICCFG_ADDRESS));
}
#endif /* __MACH_SDRAM_CONFIG_H */
