#include "board.h" #include "../mcom_runtime/i2c.h" #include "regs.h" #include "ddr.h" #include "asm/types.h" #include "common.h" #include "../setup.h" #include "kernel.h" #ifdef CONFIG_TARGET_SALUTE_D /* Set parameters for Nanya NT5CB256M8FN-DI SDRAM */ int set_sdram_cfg(struct ddr_cfg *cfg, int tck) { if (!cfg) { while(1); } if (!tck) { while(1); } /* TODO: This function works only for exactly 1066 MHz, because memory * timings could be different for different frequency. */ cfg->type = MCOM_SDRAM_TYPE_DDR3; /* This is the best combination of ODS/ODT parameters. * It was found during DDR calibration for board types: * Salute-EL24D1 r1.4, * Salute-EL24D1 r1.5, * Salute-EL24D2 r1.1. */ cfg->impedance.ods_mc = 40; cfg->impedance.ods_dram = 40; cfg->impedance.odt_mc = 120; cfg->impedance.odt_dram = 120; cfg->ctl.dqs_gating_override = 0; cfg->common.ranks = MCOM_SDRAM_ONE_RANK; cfg->common.banks = 8; cfg->common.columns = 1024; cfg->common.rows = 32768; cfg->common.bl = 8; cfg->common.cl = 7; cfg->common.cwl = 6; cfg->common.twr = max(MCOM_DDR_MIN_TWR, to_clocks(15000, tck)); cfg->common.tfaw = to_clocks(37500, tck); cfg->common.tras = to_clocks(37500, tck); cfg->common.tras_max = to_clocks(9 * 7800000, tck); cfg->common.trc = to_clocks(50625, tck); cfg->common.txp = to_clocks(max(3 * tck, 7500), tck); cfg->common.trtp = to_clocks(max(4 * tck, 7500), tck); cfg->common.twtr = to_clocks(max(4 * tck, 7500), tck); cfg->common.trcd = to_clocks(13125, tck); cfg->common.trrd = to_clocks(max(4 * tck, 7500), tck); cfg->common.tccd = 4; cfg->common.tcke = to_clocks(max(3 * tck, 5000), tck); cfg->common.tckesr = cfg->common.tcke + 1; cfg->common.tzqcs = to_clocks(max(64 * tck, 80000), tck); cfg->common.trefi = to_clocks(7800000, tck); cfg->ddr3.trp = to_clocks(13125, tck); cfg->ddr3.txpdll = to_clocks(max(10 * tck, 24000), tck); cfg->ddr3.tmrd = 4; cfg->ddr3.tmod = to_clocks(max(12 * tck, 15000), tck); cfg->ddr3.tcksre = to_clocks(max(5 * tck, 10000), tck); cfg->ddr3.tcksrx = to_clocks(max(5 * tck, 10000), tck); cfg->ddr3.tzqoper = to_clocks(max(256 * tck, 320000), tck); cfg->ddr3.trfc = to_clocks(160000, tck); cfg->ddr3.tdllk = 512; cfg->ddr3.txsdll = cfg->ddr3.tdllk; cfg->ddr3.txs = max(5, to_clocks(10000, tck) + (int)cfg->ddr3.trfc); return 0; } #endif #ifdef CONFIG_TARGET_SALUTE_PM /* Set parameters for Micron MT41K256M16HA-125 SDRAM */ int set_sdram_cfg(struct ddr_cfg *cfg, int tck) { int i; if (!cfg) { while(1); } if (!tck) { while(1); } /* TODO: This function works only for exactly 1066 MHz, because memory * timings could be different for different frequency. */ cfg->type = MCOM_SDRAM_TYPE_DDR3; /* This is the best combination of ODS/ODT parameters. * It was found during DDR calibration for board types: * Salute-EL24PM1 r1.0. */ cfg->impedance.ods_mc = 40; cfg->impedance.ods_dram = 40; cfg->impedance.odt_mc = 0; cfg->impedance.odt_dram = 0; cfg->ctl.dqs_gating_override = 1; /* TODO: Replace this configuration by the optimal one. */ for (i = 0; i < 4; i++) cfg->ctl.dqs_gating[i] = 0xa001; cfg->common.ranks = MCOM_SDRAM_ONE_RANK; cfg->common.banks = 8; cfg->common.columns = 1024; cfg->common.rows = 32768; cfg->common.bl = 8; cfg->common.cl = 7; cfg->common.cwl = 6; cfg->common.twr = max(MCOM_DDR_MIN_TWR, to_clocks(15000, tck)); cfg->common.tfaw = to_clocks(50000, tck); cfg->common.tras = to_clocks(37500, tck); cfg->common.tras_max = to_clocks(9 * 7800000, tck); cfg->common.trc = to_clocks(50625, tck); cfg->common.txp = to_clocks(max(3 * tck, 7500), tck); cfg->common.trtp = to_clocks(max(4 * tck, 7500), tck); cfg->common.twtr = to_clocks(max(4 * tck, 7500), tck); cfg->common.trcd = to_clocks(13125, tck); cfg->common.trrd = to_clocks(max(4 * tck, 10000), tck); cfg->common.tccd = 4; cfg->common.tcke = to_clocks(max(3 * tck, 7500), tck); cfg->common.tckesr = cfg->common.tcke + 1; cfg->common.tzqcs = 64; cfg->common.trefi = to_clocks(7800000, tck); cfg->ddr3.trp = to_clocks(13125, tck); cfg->ddr3.txpdll = to_clocks(max(10 * tck, 24000), tck); cfg->ddr3.tmrd = 4; cfg->ddr3.tmod = to_clocks(max(12 * tck, 15000), tck); cfg->ddr3.tcksre = to_clocks(max(5 * tck, 10000), tck); cfg->ddr3.tcksrx = to_clocks(max(5 * tck, 10000), tck); cfg->ddr3.tzqoper = 256; cfg->ddr3.trfc = to_clocks(260000, tck); cfg->ddr3.tdllk = 512; cfg->ddr3.txsdll = cfg->ddr3.tdllk; cfg->ddr3.txs = max(5, to_clocks(10000, tck) + (int)cfg->ddr3.trfc); return 0; } #endif void board_init_start() { sys_t sys; INIT_SYS_REGS(sys); /* DDR retention mode should be disabled as soon as possible * to avoid large current on DDRx_VDDQ (see rf#1160). */ sys.PMCTR->DDR_PIN_RET = 0; /* Set ALWAYS_MISC0 to start address of bootrom _cold_reset * branch. The SoC can be rebooted correctly after this. */ sys.PMCTR->ALWAYS_MISC0 = BOOTROM_COLD_RESET_BRANCH; /* Disable boot memory remapping due to the ACP bug (see rf#971) */ sys.SMCTR->BOOT_REMAP = 0; /* Set default configuration for the ACP (see rf#972) */ sys.SMCTR->ACP_CTL = 0; /* After changing remap we need instruction barrier for use actual * bootrom API functions */ asm volatile ("isb" ::: "memory"); sys.CMCTR->DIV_MPU_CTR = 1; sys.CMCTR->DIV_ATB_CTR = 3; sys.CMCTR->DIV_APB_CTR = 1; sys.CMCTR->SEL_APLL = APLL_VALUE; if (APLL_VALUE != 0) { while ((sys.CMCTR->SEL_APLL & 0x80000000) == 0) { } } sys.CMCTR->DIV_SYS0_CTR = DIV_SYS0_CTR_VALUE; sys.CMCTR->DIV_SYS1_CTR = DIV_SYS1_CTR_VALUE; sys.CMCTR->SEL_SPLL = SPLL_VALUE; if (SPLL_VALUE != 0) { while ((sys.CMCTR->SEL_SPLL & 0x80000000) == 0) { } } } void ddr_power_on () { init_I2C(MMPF0100_SLAVE_ADDR); writeI2CRegByte(I2C_REG_8BIT_ADDRESS, MMPF0100_SW3AMODE_ADDR, MMPF0100_DDR_POWER_VAL); int i =0; for (i = 0; i < 10000; i++) { asm volatile("nop"); } writeI2CRegByte(I2C_REG_8BIT_ADDRESS, MMPF0100_SW3BMODE_ADDR, MMPF0100_DDR_POWER_VAL); } /* u32 ddr_get_clock_period(int ctl_id, struct ddr_freq *freq) { u32 frequency = freq->xti_freq * (freq->cpll_mult + 1); switch (ctl_id) { case 0: frequency = frequency >> freq->ddr0_div; break; case 1: frequency = frequency >> freq->ddr1_div; break; default: return 0; } return DIV_ROUND_UP(1000000000, frequency / 1000); } */ int dram_init(void) { gd->ram_size = PHYS_SDRAM_0_SIZE; struct ddr_cfg cfg[2]; struct ddr_freq freq; int i, ret; #ifdef CONFIG_TARGET_SALUTE_PM ddr_power_on(); #endif freq.xti_freq = XTI_FREQ; freq.cpll_mult = CPLL_VALUE; freq.ddr0_div = DIV_DDR0_CTR_VALUE; freq.ddr1_div = DIV_DDR1_CTR_VALUE; for (i = 0; i < 2; i++) { ret = set_sdram_cfg(&cfg[i], ddr_get_clock_period(i, &freq)); if (ret) return ret; cfg[i].ctl_id = i; } u32 status = mcom_ddr_init(&cfg[0], &cfg[1], &freq); return status; }