/* * Copyright (C) Marvell International Ltd. and its affiliates * * SPDX-License-Identifier: GPL-2.0 */ #include #include #include #include #include #include #include "ddr3_init.h" #if defined(MV88F78X60) #include "ddr3_axp_config.h" #elif defined(MV88F67XX) #include "ddr3_a370_config.h" #endif #if defined(MV88F672X) #include "ddr3_a375_config.h" #endif #ifdef DUNIT_SPD /* DIMM SPD offsets */ #define SPD_DEV_TYPE_BYTE 2 #define SPD_MODULE_TYPE_BYTE 3 #define SPD_MODULE_MASK 0xf #define SPD_MODULE_TYPE_RDIMM 1 #define SPD_MODULE_TYPE_UDIMM 2 #define SPD_DEV_DENSITY_BYTE 4 #define SPD_DEV_DENSITY_MASK 0xf #define SPD_ROW_NUM_BYTE 5 #define SPD_ROW_NUM_MIN 12 #define SPD_ROW_NUM_OFF 3 #define SPD_ROW_NUM_MASK (7 << SPD_ROW_NUM_OFF) #define SPD_COL_NUM_BYTE 5 #define SPD_COL_NUM_MIN 9 #define SPD_COL_NUM_OFF 0 #define SPD_COL_NUM_MASK (7 << SPD_COL_NUM_OFF) #define SPD_MODULE_ORG_BYTE 7 #define SPD_MODULE_SDRAM_DEV_WIDTH_OFF 0 #define SPD_MODULE_SDRAM_DEV_WIDTH_MASK (7 << SPD_MODULE_SDRAM_DEV_WIDTH_OFF) #define SPD_MODULE_BANK_NUM_MIN 1 #define SPD_MODULE_BANK_NUM_OFF 3 #define SPD_MODULE_BANK_NUM_MASK (7 << SPD_MODULE_BANK_NUM_OFF) #define SPD_BUS_WIDTH_BYTE 8 #define SPD_BUS_WIDTH_OFF 0 #define SPD_BUS_WIDTH_MASK (7 << SPD_BUS_WIDTH_OFF) #define SPD_BUS_ECC_OFF 3 #define SPD_BUS_ECC_MASK (3 << SPD_BUS_ECC_OFF) #define SPD_MTB_DIVIDEND_BYTE 10 #define SPD_MTB_DIVISOR_BYTE 11 #define SPD_TCK_BYTE 12 #define SPD_SUP_CAS_LAT_LSB_BYTE 14 #define SPD_SUP_CAS_LAT_MSB_BYTE 15 #define SPD_TAA_BYTE 16 #define SPD_TWR_BYTE 17 #define SPD_TRCD_BYTE 18 #define SPD_TRRD_BYTE 19 #define SPD_TRP_BYTE 20 #define SPD_TRAS_MSB_BYTE 21 #define SPD_TRAS_MSB_MASK 0xf #define SPD_TRC_MSB_BYTE 21 #define SPD_TRC_MSB_MASK 0xf0 #define SPD_TRAS_LSB_BYTE 22 #define SPD_TRC_LSB_BYTE 23 #define SPD_TRFC_LSB_BYTE 24 #define SPD_TRFC_MSB_BYTE 25 #define SPD_TWTR_BYTE 26 #define SPD_TRTP_BYTE 27 #define SPD_TFAW_MSB_BYTE 28 #define SPD_TFAW_MSB_MASK 0xf #define SPD_TFAW_LSB_BYTE 29 #define SPD_OPT_FEATURES_BYTE 30 #define SPD_THERMAL_REFRESH_OPT_BYTE 31 #define SPD_ADDR_MAP_BYTE 63 #define SPD_ADDR_MAP_MIRROR_OFFS 0 #define SPD_RDIMM_RC_BYTE 69 #define SPD_RDIMM_RC_NIBBLE_MASK 0xF #define SPD_RDIMM_RC_NUM 16 /* Dimm Memory Type values */ #define SPD_MEM_TYPE_SDRAM 0x4 #define SPD_MEM_TYPE_DDR1 0x7 #define SPD_MEM_TYPE_DDR2 0x8 #define SPD_MEM_TYPE_DDR3 0xB #define DIMM_MODULE_MANU_OFFS 64 #define DIMM_MODULE_MANU_SIZE 8 #define DIMM_MODULE_VEN_OFFS 73 #define DIMM_MODULE_VEN_SIZE 25 #define DIMM_MODULE_ID_OFFS 99 #define DIMM_MODULE_ID_SIZE 18 /* enumeration for voltage levels. */ enum dimm_volt_if { TTL_5V_TOLERANT, LVTTL, HSTL_1_5V, SSTL_3_3V, SSTL_2_5V, VOLTAGE_UNKNOWN, }; /* enumaration for SDRAM CAS Latencies. */ enum dimm_sdram_cas { SD_CL_1 = 1, SD_CL_2, SD_CL_3, SD_CL_4, SD_CL_5, SD_CL_6, SD_CL_7, SD_FAULT }; /* enumeration for memory types */ enum memory_type { MEM_TYPE_SDRAM, MEM_TYPE_DDR1, MEM_TYPE_DDR2, MEM_TYPE_DDR3 }; /* DIMM information structure */ typedef struct dimm_info { /* DIMM dimensions */ u32 num_of_module_ranks; u32 data_width; u32 rank_capacity; u32 num_of_devices; u32 sdram_width; u32 num_of_banks_on_each_device; u32 sdram_capacity; u32 num_of_row_addr; u32 num_of_col_addr; u32 addr_mirroring; u32 err_check_type; /* ECC , PARITY.. */ u32 type_info; /* DDR2 only */ /* DIMM timing parameters */ u32 supported_cas_latencies; u32 refresh_interval; u32 min_cycle_time; u32 min_row_precharge_time; u32 min_row_active_to_row_active; u32 min_ras_to_cas_delay; u32 min_write_recovery_time; /* DDR3/2 only */ u32 min_write_to_read_cmd_delay; /* DDR3/2 only */ u32 min_read_to_prech_cmd_delay; /* DDR3/2 only */ u32 min_active_to_precharge; u32 min_refresh_recovery; /* DDR3/2 only */ u32 min_cas_lat_time; u32 min_four_active_win_delay; u8 dimm_rc[SPD_RDIMM_RC_NUM]; /* DIMM vendor ID */ u32 vendor; } MV_DIMM_INFO; static int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info, u32 dimm); static u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val); static u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val); static int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width); static u32 ddr3_div(u32 val, u32 divider, u32 sub); extern u8 spd_data[SPD_SIZE]; extern u32 odt_config[ODT_OPT]; extern u16 odt_static[ODT_OPT][MAX_CS]; extern u16 odt_dynamic[ODT_OPT][MAX_CS]; #if !(defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710)) /* * Name: ddr3_get_dimm_num - Find number of dimms and their addresses * Desc: * Args: dimm_addr - array of dimm addresses * Notes: * Returns: None. */ static u32 ddr3_get_dimm_num(u32 *dimm_addr) { u32 dimm_cur_addr; u8 data[3]; u32 dimm_num = 0; int ret; /* Read the dimm eeprom */ for (dimm_cur_addr = MAX_DIMM_ADDR; dimm_cur_addr > MIN_DIMM_ADDR; dimm_cur_addr--) { data[SPD_DEV_TYPE_BYTE] = 0; /* Far-End DIMM must be connected */ if ((dimm_num == 0) && (dimm_cur_addr < FAR_END_DIMM_ADDR)) return 0; ret = i2c_read(dimm_cur_addr, 0, 1, (uchar *)data, 3); if (!ret) { if (data[SPD_DEV_TYPE_BYTE] == SPD_MEM_TYPE_DDR3) { dimm_addr[dimm_num] = dimm_cur_addr; dimm_num++; } } } return dimm_num; } #endif /* * Name: dimmSpdInit - Get the SPD parameters. * Desc: Read the DIMM SPD parameters into given struct parameter. * Args: dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator. * info - DIMM information structure. * Notes: * Returns: MV_OK if function could read DIMM parameters, 0 otherwise. */ int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width) { u32 tmp; u32 time_base; int ret; __maybe_unused u32 rc; __maybe_unused u8 vendor_high, vendor_low; if (dimm_addr != 0) { memset(spd_data, 0, SPD_SIZE * sizeof(u8)); ret = i2c_read(dimm_addr, 0, 1, (uchar *)spd_data, SPD_SIZE); if (ret) return MV_DDR3_TRAINING_ERR_TWSI_FAIL; } /* Check if DDR3 */ if (spd_data[SPD_DEV_TYPE_BYTE] != SPD_MEM_TYPE_DDR3) return MV_DDR3_TRAINING_ERR_TWSI_BAD_TYPE; /* Error Check Type */ /* No byte for error check in DDR3 SPD, use DDR2 convention */ info->err_check_type = 0; /* Check if ECC */ if ((spd_data[SPD_BUS_WIDTH_BYTE] & 0x18) >> 3) info->err_check_type = 1; DEBUG_INIT_FULL_C("DRAM err_check_type ", info->err_check_type, 1); switch (spd_data[SPD_MODULE_TYPE_BYTE]) { case 1: /* support RDIMM */ info->type_info = SPD_MODULE_TYPE_RDIMM; break; case 2: /* support UDIMM */ info->type_info = SPD_MODULE_TYPE_UDIMM; break; case 11: /* LRDIMM current not supported */ default: info->type_info = (spd_data[SPD_MODULE_TYPE_BYTE]); break; } /* Size Calculations: */ /* Number Of Row Addresses - 12/13/14/15/16 */ info->num_of_row_addr = (spd_data[SPD_ROW_NUM_BYTE] & SPD_ROW_NUM_MASK) >> SPD_ROW_NUM_OFF; info->num_of_row_addr += SPD_ROW_NUM_MIN; DEBUG_INIT_FULL_C("DRAM num_of_row_addr ", info->num_of_row_addr, 2); /* Number Of Column Addresses - 9/10/11/12 */ info->num_of_col_addr = (spd_data[SPD_COL_NUM_BYTE] & SPD_COL_NUM_MASK) >> SPD_COL_NUM_OFF; info->num_of_col_addr += SPD_COL_NUM_MIN; DEBUG_INIT_FULL_C("DRAM num_of_col_addr ", info->num_of_col_addr, 1); /* Number Of Ranks = number of CS on Dimm - 1/2/3/4 Ranks */ info->num_of_module_ranks = (spd_data[SPD_MODULE_ORG_BYTE] & SPD_MODULE_BANK_NUM_MASK) >> SPD_MODULE_BANK_NUM_OFF; info->num_of_module_ranks += SPD_MODULE_BANK_NUM_MIN; DEBUG_INIT_FULL_C("DRAM numOfModuleBanks ", info->num_of_module_ranks, 1); /* Data Width - 8/16/32/64 bits */ info->data_width = 1 << (3 + (spd_data[SPD_BUS_WIDTH_BYTE] & SPD_BUS_WIDTH_MASK)); DEBUG_INIT_FULL_C("DRAM data_width ", info->data_width, 1); /* Number Of Banks On Each Device - 8/16/32/64 banks */ info->num_of_banks_on_each_device = 1 << (3 + ((spd_data[SPD_DEV_DENSITY_BYTE] >> 4) & 0x7)); DEBUG_INIT_FULL_C("DRAM num_of_banks_on_each_device ", info->num_of_banks_on_each_device, 1); /* Total SDRAM capacity - 256Mb/512Mb/1Gb/2Gb/4Gb/8Gb/16Gb - MegaBits */ info->sdram_capacity = spd_data[SPD_DEV_DENSITY_BYTE] & SPD_DEV_DENSITY_MASK; /* Sdram Width - 4/8/16/32 bits */ info->sdram_width = 1 << (2 + (spd_data[SPD_MODULE_ORG_BYTE] & SPD_MODULE_SDRAM_DEV_WIDTH_MASK)); DEBUG_INIT_FULL_C("DRAM sdram_width ", info->sdram_width, 1); /* CS (Rank) Capacity - MB */ /* * DDR3 device uiDensity val are: (device capacity/8) * * (Module_width/Device_width) */ /* Jedec SPD DDR3 - page 7, Save spd_data in Mb - 2048=2GB */ if (dimm_width == 32) { info->rank_capacity = ((1 << info->sdram_capacity) * 256 * (info->data_width / info->sdram_width)) << 16; /* CS size = CS size / 2 */ } else { info->rank_capacity = ((1 << info->sdram_capacity) * 256 * (info->data_width / info->sdram_width) * 0x2) << 16; /* 0x2 => 0x100000-1Mbit / 8-bit->byte / 0x10000 */ } DEBUG_INIT_FULL_C("DRAM rank_capacity[31] ", info->rank_capacity, 1); /* Number of devices includeing Error correction */ info->num_of_devices = ((info->data_width / info->sdram_width) * info->num_of_module_ranks) + info->err_check_type; DEBUG_INIT_FULL_C("DRAM num_of_devices ", info->num_of_devices, 1); /* Address Mapping from Edge connector to DRAM - mirroring option */ info->addr_mirroring = spd_data[SPD_ADDR_MAP_BYTE] & (1 << SPD_ADDR_MAP_MIRROR_OFFS); /* Timings - All in ps */ time_base = (1000 * spd_data[SPD_MTB_DIVIDEND_BYTE]) / spd_data[SPD_MTB_DIVISOR_BYTE]; /* Minimum Cycle Time At Max CasLatancy */ info->min_cycle_time = spd_data[SPD_TCK_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM tCKmin ", info->min_cycle_time, 1); /* Refresh Interval */ /* No byte for refresh interval in DDR3 SPD, use DDR2 convention */ /* * JEDEC param are 0 <= Tcase <= 85: 7.8uSec, 85 <= Tcase * <= 95: 3.9uSec */ info->refresh_interval = 7800000; /* Set to 7.8uSec */ DEBUG_INIT_FULL_C("DRAM refresh_interval ", info->refresh_interval, 1); /* Suported Cas Latencies - DDR 3: */ /* * bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 * *******-******-******-******-******-******-******-*******-******* CAS = 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 * *********************************************************-******* *******-******-******-******-******-******-******-*******-******* * bit15 |bit14 |bit13 |bit12 |bit11 |bit10 | bit9 | bit8 * *******-******-******-******-******-******-******-*******-******* CAS = TBD | 18 | 17 | 16 | 15 | 14 | 13 | 12 * */ /* DDR3 include 2 byte of CAS support */ info->supported_cas_latencies = (spd_data[SPD_SUP_CAS_LAT_MSB_BYTE] << 8) | spd_data[SPD_SUP_CAS_LAT_LSB_BYTE]; DEBUG_INIT_FULL_C("DRAM supported_cas_latencies ", info->supported_cas_latencies, 1); /* Minimum Cycle Time At Max CasLatancy */ info->min_cas_lat_time = (spd_data[SPD_TAA_BYTE] * time_base); /* * This field divided by the cycleTime will give us the CAS latency * to config */ /* * For DDR3 and DDR2 includes Write Recovery Time field. * Other SDRAM ignore */ info->min_write_recovery_time = spd_data[SPD_TWR_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_write_recovery_time ", info->min_write_recovery_time, 1); /* Mininmum Ras to Cas Delay */ info->min_ras_to_cas_delay = spd_data[SPD_TRCD_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_ras_to_cas_delay ", info->min_ras_to_cas_delay, 1); /* Minimum Row Active to Row Active Time */ info->min_row_active_to_row_active = spd_data[SPD_TRRD_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_row_active_to_row_active ", info->min_row_active_to_row_active, 1); /* Minimum Row Precharge Delay Time */ info->min_row_precharge_time = spd_data[SPD_TRP_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_row_precharge_time ", info->min_row_precharge_time, 1); /* Minimum Active to Precharge Delay Time - tRAS ps */ info->min_active_to_precharge = (spd_data[SPD_TRAS_MSB_BYTE] & SPD_TRAS_MSB_MASK) << 8; info->min_active_to_precharge |= spd_data[SPD_TRAS_LSB_BYTE]; info->min_active_to_precharge *= time_base; DEBUG_INIT_FULL_C("DRAM min_active_to_precharge ", info->min_active_to_precharge, 1); /* Minimum Refresh Recovery Delay Time - tRFC ps */ info->min_refresh_recovery = spd_data[SPD_TRFC_MSB_BYTE] << 8; info->min_refresh_recovery |= spd_data[SPD_TRFC_LSB_BYTE]; info->min_refresh_recovery *= time_base; DEBUG_INIT_FULL_C("DRAM min_refresh_recovery ", info->min_refresh_recovery, 1); /* * For DDR3 and DDR2 includes Internal Write To Read Command Delay * field. */ info->min_write_to_read_cmd_delay = spd_data[SPD_TWTR_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_write_to_read_cmd_delay ", info->min_write_to_read_cmd_delay, 1); /* * For DDR3 and DDR2 includes Internal Read To Precharge Command Delay * field. */ info->min_read_to_prech_cmd_delay = spd_data[SPD_TRTP_BYTE] * time_base; DEBUG_INIT_FULL_C("DRAM min_read_to_prech_cmd_delay ", info->min_read_to_prech_cmd_delay, 1); /* * For DDR3 includes Minimum Activate to Activate/Refresh Command * field */ tmp = ((spd_data[SPD_TFAW_MSB_BYTE] & SPD_TFAW_MSB_MASK) << 8) | spd_data[SPD_TFAW_LSB_BYTE]; info->min_four_active_win_delay = tmp * time_base; DEBUG_INIT_FULL_C("DRAM min_four_active_win_delay ", info->min_four_active_win_delay, 1); #if defined(MV88F78X60) || defined(MV88F672X) /* Registered DIMM support */ if (info->type_info == SPD_MODULE_TYPE_RDIMM) { for (rc = 2; rc < 6; rc += 2) { tmp = spd_data[SPD_RDIMM_RC_BYTE + rc / 2]; info->dimm_rc[rc] = spd_data[SPD_RDIMM_RC_BYTE + rc / 2] & SPD_RDIMM_RC_NIBBLE_MASK; info->dimm_rc[rc + 1] = (spd_data[SPD_RDIMM_RC_BYTE + rc / 2] >> 4) & SPD_RDIMM_RC_NIBBLE_MASK; } vendor_low = spd_data[66]; vendor_high = spd_data[65]; info->vendor = (vendor_high << 8) + vendor_low; DEBUG_INIT_C("DDR3 Training Sequence - Registered DIMM vendor ID 0x", info->vendor, 4); info->dimm_rc[0] = RDIMM_RC0; info->dimm_rc[1] = RDIMM_RC1; info->dimm_rc[2] = RDIMM_RC2; info->dimm_rc[8] = RDIMM_RC8; info->dimm_rc[9] = RDIMM_RC9; info->dimm_rc[10] = RDIMM_RC10; info->dimm_rc[11] = RDIMM_RC11; } #endif return MV_OK; } /* * Name: ddr3_spd_sum_init - Get the SPD parameters. * Desc: Read the DIMM SPD parameters into given struct parameter. * Args: dimmNum - DIMM number. See MV_BOARD_DIMM_NUM enumerator. * info - DIMM information structure. * Notes: * Returns: MV_OK if function could read DIMM parameters, 0 otherwise. */ int ddr3_spd_sum_init(MV_DIMM_INFO *info, MV_DIMM_INFO *sum_info, u32 dimm) { if (dimm == 0) { memcpy(sum_info, info, sizeof(MV_DIMM_INFO)); return MV_OK; } if (sum_info->type_info != info->type_info) { DEBUG_INIT_S("DDR3 Dimm Compare - DIMM type does not match - FAIL\n"); return MV_DDR3_TRAINING_ERR_DIMM_TYPE_NO_MATCH; } if (sum_info->err_check_type > info->err_check_type) { sum_info->err_check_type = info->err_check_type; DEBUG_INIT_S("DDR3 Dimm Compare - ECC does not match. ECC is disabled\n"); } if (sum_info->data_width != info->data_width) { DEBUG_INIT_S("DDR3 Dimm Compare - DRAM bus width does not match - FAIL\n"); return MV_DDR3_TRAINING_ERR_BUS_WIDTH_NOT_MATCH; } if (sum_info->min_cycle_time < info->min_cycle_time) sum_info->min_cycle_time = info->min_cycle_time; if (sum_info->refresh_interval < info->refresh_interval) sum_info->refresh_interval = info->refresh_interval; sum_info->supported_cas_latencies &= info->supported_cas_latencies; if (sum_info->min_cas_lat_time < info->min_cas_lat_time) sum_info->min_cas_lat_time = info->min_cas_lat_time; if (sum_info->min_write_recovery_time < info->min_write_recovery_time) sum_info->min_write_recovery_time = info->min_write_recovery_time; if (sum_info->min_ras_to_cas_delay < info->min_ras_to_cas_delay) sum_info->min_ras_to_cas_delay = info->min_ras_to_cas_delay; if (sum_info->min_row_active_to_row_active < info->min_row_active_to_row_active) sum_info->min_row_active_to_row_active = info->min_row_active_to_row_active; if (sum_info->min_row_precharge_time < info->min_row_precharge_time) sum_info->min_row_precharge_time = info->min_row_precharge_time; if (sum_info->min_active_to_precharge < info->min_active_to_precharge) sum_info->min_active_to_precharge = info->min_active_to_precharge; if (sum_info->min_refresh_recovery < info->min_refresh_recovery) sum_info->min_refresh_recovery = info->min_refresh_recovery; if (sum_info->min_write_to_read_cmd_delay < info->min_write_to_read_cmd_delay) sum_info->min_write_to_read_cmd_delay = info->min_write_to_read_cmd_delay; if (sum_info->min_read_to_prech_cmd_delay < info->min_read_to_prech_cmd_delay) sum_info->min_read_to_prech_cmd_delay = info->min_read_to_prech_cmd_delay; if (sum_info->min_four_active_win_delay < info->min_four_active_win_delay) sum_info->min_four_active_win_delay = info->min_four_active_win_delay; if (sum_info->min_write_to_read_cmd_delay < info->min_write_to_read_cmd_delay) sum_info->min_write_to_read_cmd_delay = info->min_write_to_read_cmd_delay; return MV_OK; } /* * Name: ddr3_dunit_setup * Desc: Set the controller with the timing values. * Args: ecc_ena - User ECC setup * Notes: * Returns: */ int ddr3_dunit_setup(u32 ecc_ena, u32 hclk_time, u32 *ddr_width) { u32 reg, tmp, cwl; u32 ddr_clk_time; MV_DIMM_INFO dimm_info[2]; MV_DIMM_INFO sum_info; u32 stat_val, spd_val; u32 cs, cl, cs_num, cs_ena; u32 dimm_num = 0; int status; u32 rc; __maybe_unused u32 dimm_cnt, cs_count, dimm; __maybe_unused u32 dimm_addr[2] = { 0, 0 }; #if defined(DB_88F6710) || defined(DB_88F6710_PCAC) || defined(RD_88F6710) /* Armada 370 - SPD is not available on DIMM */ /* * Set MC registers according to Static SPD values Values - * must be set manually */ /* * We only have one optional DIMM for the DB and we already got the * SPD matching values */ status = ddr3_spd_init(&dimm_info[0], 0, *ddr_width); if (MV_OK != status) return status; dimm_num = 1; /* Use JP8 to enable multiCS support for Armada 370 DB */ if (!ddr3_check_config(EEPROM_MODULE_ADDR, CONFIG_MULTI_CS)) dimm_info[0].num_of_module_ranks = 1; status = ddr3_spd_sum_init(&dimm_info[0], &sum_info, 0); if (MV_OK != status) return status; #else /* Dynamic D-Unit Setup - Read SPD values */ #ifdef DUNIT_SPD dimm_num = ddr3_get_dimm_num(dimm_addr); if (dimm_num == 0) { #ifdef MIXED_DIMM_STATIC DEBUG_INIT_S("DDR3 Training Sequence - No DIMMs detected\n"); #else DEBUG_INIT_S("DDR3 Training Sequence - FAILED (Wrong DIMMs Setup)\n"); return MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP; #endif } else { DEBUG_INIT_C("DDR3 Training Sequence - Number of DIMMs detected: ", dimm_num, 1); } for (dimm = 0; dimm < dimm_num; dimm++) { status = ddr3_spd_init(&dimm_info[dimm], dimm_addr[dimm], *ddr_width); if (MV_OK != status) return status; status = ddr3_spd_sum_init(&dimm_info[dimm], &sum_info, dimm); if (MV_OK != status) return status; } #endif #endif /* Set number of enabled CS */ cs_num = 0; #ifdef DUNIT_STATIC cs_num = ddr3_get_cs_num_from_reg(); #endif #ifdef DUNIT_SPD for (dimm = 0; dimm < dimm_num; dimm++) cs_num += dimm_info[dimm].num_of_module_ranks; #endif if (cs_num > MAX_CS) { DEBUG_INIT_C("DDR3 Training Sequence - Number of CS exceed limit - ", MAX_CS, 1); return MV_DDR3_TRAINING_ERR_MAX_CS_LIMIT; } /* Set bitmap of enabled CS */ cs_ena = 0; #ifdef DUNIT_STATIC cs_ena = ddr3_get_cs_ena_from_reg(); #endif #ifdef DUNIT_SPD dimm = 0; if (dimm_num) { for (cs = 0; cs < MAX_CS; cs += 2) { if (((1 << cs) & DIMM_CS_BITMAP) && !(cs_ena & (1 << cs))) { if (dimm_info[dimm].num_of_module_ranks == 1) cs_ena |= (0x1 << cs); else if (dimm_info[dimm].num_of_module_ranks == 2) cs_ena |= (0x3 << cs); else if (dimm_info[dimm].num_of_module_ranks == 3) cs_ena |= (0x7 << cs); else if (dimm_info[dimm].num_of_module_ranks == 4) cs_ena |= (0xF << cs); dimm++; if (dimm == dimm_num) break; } } } #endif if (cs_ena > 0xF) { DEBUG_INIT_C("DDR3 Training Sequence - Number of enabled CS exceed limit - ", MAX_CS, 1); return MV_DDR3_TRAINING_ERR_MAX_ENA_CS_LIMIT; } DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Number of CS = ", cs_num, 1); /* Check Ratio - '1' - 2:1, '0' - 1:1 */ if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS)) ddr_clk_time = hclk_time / 2; else ddr_clk_time = hclk_time; #ifdef DUNIT_STATIC /* Get target CL value from set register */ reg = (reg_read(REG_DDR3_MR0_ADDR) >> 2); reg = ((((reg >> 1) & 0xE)) | (reg & 0x1)) & 0xF; cl = ddr3_get_max_val(ddr3_div(sum_info.min_cas_lat_time, ddr_clk_time, 0), dimm_num, ddr3_valid_cl_to_cl(reg)); #else cl = ddr3_div(sum_info.min_cas_lat_time, ddr_clk_time, 0); #endif if (cl < 5) cl = 5; DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - Cas Latency = ", cl, 1); /* {0x00001400} - DDR SDRAM Configuration Register */ reg = 0x73004000; stat_val = ddr3_get_static_mc_value( REG_SDRAM_CONFIG_ADDR, REG_SDRAM_CONFIG_ECC_OFFS, 0x1, 0, 0); if (ecc_ena && ddr3_get_min_val(sum_info.err_check_type, dimm_num, stat_val)) { reg |= (1 << REG_SDRAM_CONFIG_ECC_OFFS); reg |= (1 << REG_SDRAM_CONFIG_IERR_OFFS); DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Enabled\n"); } else { DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - ECC Disabled\n"); } if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) { #ifdef DUNIT_STATIC DEBUG_INIT_S("DDR3 Training Sequence - FAIL - Illegal R-DIMM setup\n"); return MV_DDR3_TRAINING_ERR_BAD_R_DIMM_SETUP; #endif reg |= (1 << REG_SDRAM_CONFIG_REGDIMM_OFFS); DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - R-DIMM\n"); } else { DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - U-DIMM\n"); } #ifndef MV88F67XX #ifdef DUNIT_STATIC if (ddr3_get_min_val(sum_info.data_width, dimm_num, BUS_WIDTH) == 64) { #else if (*ddr_width == 64) { #endif reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS); DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 64Bits\n"); } else { DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n"); } #else DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n"); #endif #if defined(MV88F672X) if (*ddr_width == 32) { reg |= (1 << REG_SDRAM_CONFIG_WIDTH_OFFS); DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 32Bits\n"); } else { DEBUG_INIT_FULL_S("DDR3 - DUNIT-SET - Datawidth - 16Bits\n"); } #endif stat_val = ddr3_get_static_mc_value(REG_SDRAM_CONFIG_ADDR, 0, REG_SDRAM_CONFIG_RFRS_MASK, 0, 0); tmp = ddr3_get_min_val(sum_info.refresh_interval / hclk_time, dimm_num, stat_val); #ifdef TREFI_USER_EN tmp = min(TREFI_USER / hclk_time, tmp); #endif DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - RefreshInterval/Hclk = ", tmp, 4); reg |= tmp; if (cl != 3) reg |= (1 << 16); /* If 2:1 need to set P2DWr */ #if defined(MV88F672X) reg |= (1 << 27); /* PhyRfRST = Disable */ #endif reg_write(REG_SDRAM_CONFIG_ADDR, reg); /*{0x00001404} - DDR SDRAM Configuration Register */ reg = 0x3630B800; #ifdef DUNIT_SPD reg |= (DRAM_2T << REG_DUNIT_CTRL_LOW_2T_OFFS); #endif reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg); /* {0x00001408} - DDR SDRAM Timing (Low) Register */ reg = 0x0; /* tRAS - (0:3,20) */ spd_val = ddr3_div(sum_info.min_active_to_precharge, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 0, 0xF, 16, 0x10); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRAS-1 = ", tmp, 1); reg |= (tmp & 0xF); reg |= ((tmp & 0x10) << 16); /* to bit 20 */ /* tRCD - (4:7) */ spd_val = ddr3_div(sum_info.min_ras_to_cas_delay, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 4, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRCD-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 4); /* tRP - (8:11) */ spd_val = ddr3_div(sum_info.min_row_precharge_time, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 8, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRP-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 8); /* tWR - (12:15) */ spd_val = ddr3_div(sum_info.min_write_recovery_time, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 12, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWR-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 12); /* tWTR - (16:19) */ spd_val = ddr3_div(sum_info.min_write_to_read_cmd_delay, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 16, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tWTR-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 16); /* tRRD - (24:27) */ spd_val = ddr3_div(sum_info.min_row_active_to_row_active, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 24, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRRD-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 24); /* tRTP - (28:31) */ spd_val = ddr3_div(sum_info.min_read_to_prech_cmd_delay, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_LOW_ADDR, 28, 0xF, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRTP-1 = ", tmp, 1); reg |= ((tmp & 0xF) << 28); if (cl < 7) reg = 0x33137663; reg_write(REG_SDRAM_TIMING_LOW_ADDR, reg); /*{0x0000140C} - DDR SDRAM Timing (High) Register */ /* Add cycles to R2R W2W */ reg = 0x39F8FF80; /* tRFC - (0:6,16:18) */ spd_val = ddr3_div(sum_info.min_refresh_recovery, ddr_clk_time, 1); stat_val = ddr3_get_static_mc_value(REG_SDRAM_TIMING_HIGH_ADDR, 0, 0x7F, 9, 0x380); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tRFC-1 = ", tmp, 1); reg |= (tmp & 0x7F); reg |= ((tmp & 0x380) << 9); /* to bit 16 */ reg_write(REG_SDRAM_TIMING_HIGH_ADDR, reg); /*{0x00001410} - DDR SDRAM Address Control Register */ reg = 0x000F0000; /* tFAW - (24:28) */ #if (defined(MV88F78X60) || defined(MV88F672X)) tmp = sum_info.min_four_active_win_delay; spd_val = ddr3_div(tmp, ddr_clk_time, 0); stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR, 24, 0x3F, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW = ", tmp, 1); reg |= ((tmp & 0x3F) << 24); #else tmp = sum_info.min_four_active_win_delay - 4 * (sum_info.min_row_active_to_row_active); spd_val = ddr3_div(tmp, ddr_clk_time, 0); stat_val = ddr3_get_static_mc_value(REG_SDRAM_ADDRESS_CTRL_ADDR, 24, 0x1F, 0, 0); tmp = ddr3_get_max_val(spd_val, dimm_num, stat_val); DEBUG_INIT_FULL_C("DDR3 - DUNIT-SET - tFAW-4*tRRD = ", tmp, 1); reg |= ((tmp & 0x1F) << 24); #endif /* SDRAM device capacity */ #ifdef DUNIT_STATIC reg |= (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & 0xF0FFFF); #endif #ifdef DUNIT_SPD cs_count = 0; dimm_cnt = 0; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) { if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) { dimm_cnt++; cs_count = 0; } cs_count++; if (dimm_info[dimm_cnt].sdram_capacity < 0x3) { reg |= ((dimm_info[dimm_cnt].sdram_capacity + 1) << (REG_SDRAM_ADDRESS_SIZE_OFFS + (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs))); } else if (dimm_info[dimm_cnt].sdram_capacity > 0x3) { reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x3) << (REG_SDRAM_ADDRESS_SIZE_OFFS + (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs))); reg |= ((dimm_info[dimm_cnt].sdram_capacity & 0x4) << (REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs)); } } } /* SDRAM device structure */ cs_count = 0; dimm_cnt = 0; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) { if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) { dimm_cnt++; cs_count = 0; } cs_count++; if (dimm_info[dimm_cnt].sdram_width == 16) reg |= (1 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs)); } } #endif reg_write(REG_SDRAM_ADDRESS_CTRL_ADDR, reg); /*{0x00001418} - DDR SDRAM Operation Register */ reg = 0xF00; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) reg &= ~(1 << (cs + REG_SDRAM_OPERATION_CS_OFFS)); } reg_write(REG_SDRAM_OPERATION_ADDR, reg); /*{0x00001420} - DDR SDRAM Extended Mode Register */ reg = 0x00000004; reg_write(REG_SDRAM_EXT_MODE_ADDR, reg); /*{0x00001424} - DDR Controller Control (High) Register */ #if (defined(MV88F78X60) || defined(MV88F672X)) reg = 0x0000D3FF; #else reg = 0x0100D1FF; #endif reg_write(REG_DDR_CONT_HIGH_ADDR, reg); /*{0x0000142C} - DDR3 Timing Register */ reg = 0x014C2F38; #if defined(MV88F78X60) || defined(MV88F672X) reg = 0x1FEC2F38; #endif reg_write(0x142C, reg); /*{0x00001484} - MBus CPU Block Register */ #ifdef MV88F67XX if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS)) reg_write(REG_MBUS_CPU_BLOCK_ADDR, 0x0000E907); #endif /* * In case of mixed dimm and on-board devices setup paramters will * be taken statically */ /*{0x00001494} - DDR SDRAM ODT Control (Low) Register */ reg = odt_config[cs_ena]; reg_write(REG_SDRAM_ODT_CTRL_LOW_ADDR, reg); /*{0x00001498} - DDR SDRAM ODT Control (High) Register */ reg = 0x00000000; reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg); /*{0x0000149C} - DDR Dunit ODT Control Register */ reg = cs_ena; reg_write(REG_DUNIT_ODT_CTRL_ADDR, reg); /*{0x000014A0} - DDR Dunit ODT Control Register */ #if defined(MV88F672X) reg = 0x000006A9; reg_write(REG_DRAM_FIFO_CTRL_ADDR, reg); #endif /*{0x000014C0} - DRAM address and Control Driving Strenght */ reg_write(REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR, 0x192435e9); /*{0x000014C4} - DRAM Data and DQS Driving Strenght */ reg_write(REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR, 0xB2C35E9); #if (defined(MV88F78X60) || defined(MV88F672X)) /*{0x000014CC} - DRAM Main Pads Calibration Machine Control Register */ reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR); reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg | (1 << 0)); #endif #if defined(MV88F672X) /* DRAM Main Pads Calibration Machine Control Register */ /* 0x14CC[4:3] - CalUpdateControl = IntOnly */ reg = reg_read(REG_DRAM_MAIN_PADS_CAL_ADDR); reg &= 0xFFFFFFE7; reg |= (1 << 3); reg_write(REG_DRAM_MAIN_PADS_CAL_ADDR, reg); #endif #ifdef DUNIT_SPD cs_count = 0; dimm_cnt = 0; for (cs = 0; cs < MAX_CS; cs++) { if ((1 << cs) & DIMM_CS_BITMAP) { if ((1 << cs) & cs_ena) { if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) { dimm_cnt++; cs_count = 0; } cs_count++; reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8), dimm_info[dimm_cnt].rank_capacity - 1); } else { reg_write(REG_CS_SIZE_SCRATCH_ADDR + (cs * 0x8), 0); } } } #endif /*{0x00020184} - Close FastPath - 2G */ reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, 0); /*{0x00001538} - Read Data Sample Delays Register */ reg = 0; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) reg |= (cl << (REG_READ_DATA_SAMPLE_DELAYS_OFFS * cs)); } reg_write(REG_READ_DATA_SAMPLE_DELAYS_ADDR, reg); DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Sample Delays = ", reg, 1); /*{0x0000153C} - Read Data Ready Delay Register */ reg = 0; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) { reg |= ((cl + 2) << (REG_READ_DATA_READY_DELAYS_OFFS * cs)); } } reg_write(REG_READ_DATA_READY_DELAYS_ADDR, reg); DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Read Data Ready Delays = ", reg, 1); /* Set MR registers */ /* MR0 */ reg = 0x00000600; tmp = ddr3_cl_to_valid_cl(cl); reg |= ((tmp & 0x1) << 2); reg |= ((tmp & 0xE) << 3); /* to bit 4 */ for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) { reg_write(REG_DDR3_MR0_CS_ADDR + (cs << MR_CS_ADDR_OFFS), reg); } } /* MR1 */ reg = 0x00000044 & REG_DDR3_MR1_ODT_MASK; if (cs_num > 1) reg = 0x00000046 & REG_DDR3_MR1_ODT_MASK; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) { reg |= odt_static[cs_ena][cs]; reg_write(REG_DDR3_MR1_CS_ADDR + (cs << MR_CS_ADDR_OFFS), reg); } } /* MR2 */ if (reg_read(REG_DDR_IO_ADDR) & (1 << REG_DDR_IO_CLK_RATIO_OFFS)) tmp = hclk_time / 2; else tmp = hclk_time; if (tmp >= 2500) cwl = 5; /* CWL = 5 */ else if (tmp >= 1875 && tmp < 2500) cwl = 6; /* CWL = 6 */ else if (tmp >= 1500 && tmp < 1875) cwl = 7; /* CWL = 7 */ else if (tmp >= 1250 && tmp < 1500) cwl = 8; /* CWL = 8 */ else if (tmp >= 1070 && tmp < 1250) cwl = 9; /* CWL = 9 */ else if (tmp >= 935 && tmp < 1070) cwl = 10; /* CWL = 10 */ else if (tmp >= 833 && tmp < 935) cwl = 11; /* CWL = 11 */ else if (tmp >= 750 && tmp < 833) cwl = 12; /* CWL = 12 */ else { cwl = 12; /* CWL = 12 */ printf("Unsupported hclk %d MHz\n", tmp); } reg = ((cwl - 5) << REG_DDR3_MR2_CWL_OFFS); for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) { reg &= REG_DDR3_MR2_ODT_MASK; reg |= odt_dynamic[cs_ena][cs]; reg_write(REG_DDR3_MR2_CS_ADDR + (cs << MR_CS_ADDR_OFFS), reg); } } /* MR3 */ reg = 0x00000000; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs)) { reg_write(REG_DDR3_MR3_CS_ADDR + (cs << MR_CS_ADDR_OFFS), reg); } } /* {0x00001428} - DDR ODT Timing (Low) Register */ reg = 0; reg |= (((cl - cwl + 1) & 0xF) << 4); reg |= (((cl - cwl + 6) & 0xF) << 8); reg |= ((((cl - cwl + 6) >> 4) & 0x1) << 21); reg |= (((cl - 1) & 0xF) << 12); reg |= (((cl + 6) & 0x1F) << 16); reg_write(REG_ODT_TIME_LOW_ADDR, reg); /* {0x0000147C} - DDR ODT Timing (High) Register */ reg = 0x00000071; reg |= ((cwl - 1) << 8); reg |= ((cwl + 5) << 12); reg_write(REG_ODT_TIME_HIGH_ADDR, reg); #ifdef DUNIT_SPD /*{0x000015E0} - DDR3 Rank Control Register */ reg = cs_ena; cs_count = 0; dimm_cnt = 0; for (cs = 0; cs < MAX_CS; cs++) { if (cs_ena & (1 << cs) & DIMM_CS_BITMAP) { if (dimm_info[dimm_cnt].num_of_module_ranks == cs_count) { dimm_cnt++; cs_count = 0; } cs_count++; if (dimm_info[dimm_cnt].addr_mirroring && (cs == 1 || cs == 3) && (sum_info.type_info != SPD_MODULE_TYPE_RDIMM)) { reg |= (1 << (REG_DDR3_RANK_CTRL_MIRROR_OFFS + cs)); DEBUG_INIT_FULL_C("DDR3 - SPD-SET - Setting Address Mirroring for CS = ", cs, 1); } } } reg_write(REG_DDR3_RANK_CTRL_ADDR, reg); #endif /*{0xD00015E4} - ZQDS Configuration Register */ reg = 0x00203c18; reg_write(REG_ZQC_CONF_ADDR, reg); /* {0x00015EC} - DDR PHY */ #if defined(MV88F78X60) reg = 0xF800AAA5; if (mv_ctrl_rev_get() == MV_78XX0_B0_REV) reg = 0xF800A225; #else reg = 0xDE000025; #if defined(MV88F672X) reg = 0xF800A225; #endif #endif reg_write(REG_DRAM_PHY_CONFIG_ADDR, reg); #if (defined(MV88F78X60) || defined(MV88F672X)) /* Registered DIMM support - supported only in AXP A0 devices */ /* Currently supported for SPD detection only */ /* * Flow is according to the Registered DIMM chapter in the * Functional Spec */ if (sum_info.type_info == SPD_MODULE_TYPE_RDIMM) { DEBUG_INIT_S("DDR3 Training Sequence - Registered DIMM detected\n"); /* Set commands parity completion */ reg = reg_read(REG_REGISTERED_DRAM_CTRL_ADDR); reg &= ~REG_REGISTERED_DRAM_CTRL_PARITY_MASK; reg |= 0x8; reg_write(REG_REGISTERED_DRAM_CTRL_ADDR, reg); /* De-assert M_RESETn and assert M_CKE */ reg_write(REG_SDRAM_INIT_CTRL_ADDR, 1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS); do { reg = (reg_read(REG_SDRAM_INIT_CTRL_ADDR)) & (1 << REG_SDRAM_INIT_CKE_ASSERT_OFFS); } while (reg); for (rc = 0; rc < SPD_RDIMM_RC_NUM; rc++) { if (rc != 6 && rc != 7) { /* Set CWA Command */ reg = (REG_SDRAM_OPERATION_CMD_CWA & ~(0xF << REG_SDRAM_OPERATION_CS_OFFS)); reg |= ((dimm_info[0].dimm_rc[rc] & REG_SDRAM_OPERATION_CWA_DATA_MASK) << REG_SDRAM_OPERATION_CWA_DATA_OFFS); reg |= rc << REG_SDRAM_OPERATION_CWA_RC_OFFS; /* Configure - Set Delay - tSTAB/tMRD */ if (rc == 2 || rc == 10) reg |= (0x1 << REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS); /* 0x1418 - SDRAM Operation Register */ reg_write(REG_SDRAM_OPERATION_ADDR, reg); /* * Poll the "cmd" field in the SDRAM OP * register for 0x0 */ do { reg = reg_read(REG_SDRAM_OPERATION_ADDR) & (REG_SDRAM_OPERATION_CMD_MASK); } while (reg); } } } #endif return MV_OK; } /* * Name: ddr3_div - this function divides integers * Desc: * Args: val - the value * divider - the divider * sub - substruction value * Notes: * Returns: required value */ u32 ddr3_div(u32 val, u32 divider, u32 sub) { return val / divider + (val % divider > 0 ? 1 : 0) - sub; } /* * Name: ddr3_get_max_val * Desc: * Args: * Notes: * Returns: */ u32 ddr3_get_max_val(u32 spd_val, u32 dimm_num, u32 static_val) { #ifdef DUNIT_STATIC if (dimm_num > 0) { if (spd_val >= static_val) return spd_val; else return static_val; } else { return static_val; } #else return spd_val; #endif } /* * Name: ddr3_get_min_val * Desc: * Args: * Notes: * Returns: */ u32 ddr3_get_min_val(u32 spd_val, u32 dimm_num, u32 static_val) { #ifdef DUNIT_STATIC if (dimm_num > 0) { if (spd_val <= static_val) return spd_val; else return static_val; } else return static_val; #else return spd_val; #endif } #endif