12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) Marvell International Ltd. and its affiliates
- */
- #include <common.h>
- #include <i2c.h>
- #include <spl.h>
- #include <asm/io.h>
- #include <asm/arch/cpu.h>
- #include <asm/arch/soc.h>
- #include "ddr3_hw_training.h"
- /*
- * Debug
- */
- #define DEBUG_DQS_C(s, d, l) \
- DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
- #define DEBUG_DQS_FULL_C(s, d, l) \
- DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
- #define DEBUG_DQS_RESULTS_C(s, d, l) \
- DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
- #define DEBUG_PER_DQ_C(s, d, l) \
- puts(s); printf("%x", d); puts("\n")
- #define DEBUG_DQS_RESULTS_S(s) \
- debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
- #define DEBUG_DQS_RESULTS_D(d, l) \
- debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
- #define DEBUG_PER_DQ_S(s) \
- debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
- #define DEBUG_PER_DQ_D(d, l) \
- debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
- #define DEBUG_PER_DQ_DD(d, l) \
- debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
- #ifdef MV_DEBUG_DQS
- #define DEBUG_DQS_S(s) puts(s)
- #define DEBUG_DQS_D(d, l) printf("%x", d)
- #else
- #define DEBUG_DQS_S(s)
- #define DEBUG_DQS_D(d, l)
- #endif
- #ifdef MV_DEBUG_DQS_FULL
- #define DEBUG_DQS_FULL_S(s) puts(s)
- #define DEBUG_DQS_FULL_D(d, l) printf("%x", d)
- #else
- #define DEBUG_DQS_FULL_S(s)
- #define DEBUG_DQS_FULL_D(d, l)
- #endif
- /* State machine for centralization - find low & high limit */
- enum {
- PUP_ADLL_LIMITS_STATE_FAIL,
- PUP_ADLL_LIMITS_STATE_PASS,
- PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
- };
- /* Hold centralization low results */
- static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
- /* Hold centralization high results */
- static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
- int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
- int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
- int *size_valid);
- static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx);
- int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx, u32 special_pattern_pup);
- int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx, u32 special_pattern_pup);
- int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx);
- #ifdef MV88F78X60
- extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
- extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
- extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
- #else
- extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
- extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
- #if defined(MV88F672X)
- extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
- #endif
- #endif
- extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
- static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
- {
- u32 *pattern_ptr;
- /* Choose pattern */
- switch (dram_info->ddr_width) {
- #if defined(MV88F672X)
- case 16:
- pattern_ptr = (u32 *)&killer_pattern[victim_dq];
- break;
- #endif
- case 32:
- pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
- break;
- #if defined(MV88F78X60)
- case 64:
- pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
- break;
- #endif
- default:
- #if defined(MV88F78X60)
- pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
- #else
- pattern_ptr = (u32 *)&killer_pattern[victim_dq];
- #endif
- break;
- }
- return pattern_ptr;
- }
- /*
- * Name: ddr3_dqs_centralization_rx
- * Desc: Execute the DQS centralization RX phase.
- * Args: dram_info
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
- {
- u32 cs, ecc, reg;
- int status;
- DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
- /* Enable SW override */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
- (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
- /* [0] = 1 - Enable SW override */
- /* 0x15B8 - Training SW 2 Register */
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
- reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
- reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
- /* Loop for each CS */
- for (cs = 0; cs < MAX_CS; cs++) {
- if (dram_info->cs_ena & (1 << cs)) {
- DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
- (u32) cs, 1);
- for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
- /* ECC Support - Switch ECC Mux on ecc=1 */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
- ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg |= (dram_info->ecc_ena *
- ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- if (ecc)
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
- else
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
- status = ddr3_find_adll_limits(dram_info, cs,
- ecc, 0);
- if (MV_OK != status)
- return status;
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
- status = ddr3_center_calc(dram_info, cs, ecc,
- 0);
- if (MV_OK != status)
- return status;
- }
- }
- }
- /* ECC Support - Disable ECC MUX */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
- ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- /* Disable SW override - Must be in a different stage */
- /* [0]=0 - Enable SW override */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
- reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
- /* 0x15B8 - Training SW 2 Register */
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
- (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
- reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
- return MV_OK;
- }
- /*
- * Name: ddr3_dqs_centralization_tx
- * Desc: Execute the DQS centralization TX phase.
- * Args: dram_info
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
- {
- u32 cs, ecc, reg;
- int status;
- DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
- /* Enable SW override */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
- (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
- /* [0] = 1 - Enable SW override */
- /* 0x15B8 - Training SW 2 Register */
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
- reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
- reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
- /* Loop for each CS */
- for (cs = 0; cs < MAX_CS; cs++) {
- if (dram_info->cs_ena & (1 << cs)) {
- DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
- (u32) cs, 1);
- for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
- /* ECC Support - Switch ECC Mux on ecc=1 */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
- ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg |= (dram_info->ecc_ena *
- ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- if (ecc)
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
- else
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
- status = ddr3_find_adll_limits(dram_info, cs,
- ecc, 1);
- if (MV_OK != status)
- return status;
- DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
- status = ddr3_center_calc(dram_info, cs, ecc,
- 1);
- if (MV_OK != status)
- return status;
- }
- }
- }
- /* ECC Support - Disable ECC MUX */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
- ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- /* Disable SW override - Must be in a different stage */
- /* [0]=0 - Enable SW override */
- reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
- reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
- /* 0x15B8 - Training SW 2 Register */
- reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
- reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
- (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
- reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
- return MV_OK;
- }
- /*
- * Name: ddr3_find_adll_limits
- * Desc: Execute the Find ADLL limits phase.
- * Args: dram_info
- * cs
- * ecc_ena
- * is_tx Indicate whether Rx or Tx
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
- {
- u32 victim_dq, pup, tmp;
- u32 adll_addr;
- u32 max_pup; /* maximal pup index */
- u32 pup_mask = 0;
- u32 unlock_pup; /* bit array of un locked pups */
- u32 new_unlock_pup; /* bit array of compare failed pups */
- u32 curr_adll;
- u32 adll_start_val; /* adll start loop value - for rx or tx limit */
- u32 high_limit; /* holds found High Limit */
- u32 low_limit; /* holds found Low Limit */
- int win_valid;
- int update_win;
- u32 sdram_offset;
- u32 uj, cs_count, cs_tmp, ii;
- u32 *pattern_ptr;
- u32 dq;
- u32 adll_end_val; /* adll end of loop val - for rx or tx limit */
- u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
- u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
- int pup_adll_limit_state[MAX_PUP_NUM]; /* hold state of each pup */
- adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
- adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
- adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
- max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
- DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
- /* init the array */
- for (pup = 0; pup < max_pup; pup++) {
- centralization_low_limit[pup] = ADLL_MIN;
- centralization_high_limit[pup] = ADLL_MAX;
- }
- /* Killer Pattern */
- cs_count = 0;
- for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
- if (dram_info->cs_ena & (1 << cs_tmp))
- cs_count++;
- }
- sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
- sdram_offset += ((is_tx == 1) ?
- SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
- /* Prepare pup masks */
- for (pup = 0; pup < max_pup; pup++)
- pup_mask |= (1 << pup);
- for (pup = 0; pup < max_pup; pup++) {
- for (dq = 0; dq < DQ_NUM; dq++) {
- analog_pbs_sum[pup][dq][0] = adll_start_val;
- analog_pbs_sum[pup][dq][1] = adll_end_val;
- }
- }
- /* Loop - use different pattern for each victim_dq */
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
- (u32)victim_dq, 1);
- /*
- * The pups 3 bit arrays represent state machine. with
- * 3 stages for each pup.
- * 1. fail and didn't get pass in earlier compares.
- * 2. pass compare
- * 3. fail after pass - end state.
- * The window limits are the adll values where the adll
- * was in the pass stage.
- */
- /* Set all states to Fail (1st state) */
- for (pup = 0; pup < max_pup; pup++)
- pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
- /* Set current valid pups */
- unlock_pup = pup_mask;
- /* Set ADLL to start value */
- curr_adll = adll_start_val;
- #if defined(MV88F78X60)
- for (pup = 0; pup < max_pup; pup++) {
- for (dq = 0; dq < DQ_NUM; dq++) {
- analog_pbs[victim_dq][pup][dq][0] =
- adll_start_val;
- analog_pbs[victim_dq][pup][dq][1] =
- adll_end_val;
- per_bit_data[pup][dq] = 0;
- }
- }
- #endif
- for (uj = 0; uj < ADLL_MAX; uj++) {
- DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
- curr_adll, 2);
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
- tmp = ((is_tx == 1) ? curr_adll +
- dram_info->wl_val[cs]
- [pup * (1 - ecc) + ecc * ECC_PUP]
- [D] : curr_adll);
- ddr3_write_pup_reg(adll_addr, cs, pup +
- (ecc * ECC_PUP), 0, tmp);
- }
- }
- /* Choose pattern */
- pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
- victim_dq);
- /* '1' - means pup failed, '0' - means pup pass */
- new_unlock_pup = 0;
- /* Read and compare results for Victim_DQ# */
- for (ii = 0; ii < 3; ii++) {
- u32 tmp = 0;
- if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
- unlock_pup, &tmp,
- pattern_ptr,
- LEN_KILLER_PATTERN,
- sdram_offset +
- LEN_KILLER_PATTERN *
- 4 * victim_dq,
- is_tx, 0, NULL,
- 0))
- return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
- new_unlock_pup |= tmp;
- }
- pup = 0;
- DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
- unlock_pup, 2);
- DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
- new_unlock_pup, 2);
- /* Update pup state */
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
- DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
- pup, 1);
- continue;
- }
- /*
- * Still didn't find the window limit of the pup
- */
- if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
- /* Current compare result == fail */
- if (pup_adll_limit_state[pup] ==
- PUP_ADLL_LIMITS_STATE_PASS) {
- /*
- * If now it failed but passed
- * earlier
- */
- DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
- DEBUG_DQS_D(cs, 1);
- DEBUG_DQS_S(", DQ - ");
- DEBUG_DQS_D(victim_dq, 1);
- DEBUG_DQS_S(", Pup - ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_S(", ADLL - ");
- DEBUG_DQS_D(curr_adll, 2);
- DEBUG_DQS_S("\n");
- #if defined(MV88F78X60)
- for (dq = 0; dq < DQ_NUM; dq++) {
- if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
- && (analog_pbs[victim_dq][pup]
- [dq][1] == adll_end_val))
- analog_pbs
- [victim_dq]
- [pup][dq]
- [1] =
- curr_adll;
- }
- #endif
- win_valid = 1;
- update_win = 0;
- /* Keep min / max limit value */
- if (is_tx == 0) {
- /* RX - found upper limit */
- if (centralization_high_limit[pup] >
- (curr_adll - 1)) {
- high_limit =
- curr_adll - 1;
- low_limit =
- centralization_low_limit[pup];
- update_win = 1;
- }
- } else {
- /* TX - found lower limit */
- if (centralization_low_limit[pup] < (curr_adll + 1)) {
- high_limit =
- centralization_high_limit
- [pup];
- low_limit =
- curr_adll + 1;
- update_win =
- 1;
- }
- }
- if (update_win == 1) {
- /*
- * Before updating
- * window limits we need
- * to check that the
- * limits are valid
- */
- if (MV_OK !=
- ddr3_check_window_limits
- (pup, high_limit,
- low_limit, is_tx,
- &win_valid))
- return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
- if (win_valid == 1) {
- /*
- * Window limits
- * should be
- * updated
- */
- centralization_low_limit
- [pup] =
- low_limit;
- centralization_high_limit
- [pup] =
- high_limit;
- }
- }
- if (win_valid == 1) {
- /* Found end of window - lock the pup */
- pup_adll_limit_state[pup] =
- PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
- unlock_pup &= ~(1 << pup);
- } else {
- /* Probably false pass - reset status */
- pup_adll_limit_state[pup] =
- PUP_ADLL_LIMITS_STATE_FAIL;
- #if defined(MV88F78X60)
- /* Clear logging array of win size (per Dq) */
- for (dq = 0;
- dq < DQ_NUM;
- dq++) {
- analog_pbs
- [victim_dq]
- [pup][dq]
- [0] =
- adll_start_val;
- analog_pbs
- [victim_dq]
- [pup][dq]
- [1] =
- adll_end_val;
- per_bit_data
- [pup][dq]
- = 0;
- }
- #endif
- }
- }
- } else {
- /* Current compare result == pass */
- if (pup_adll_limit_state[pup] ==
- PUP_ADLL_LIMITS_STATE_FAIL) {
- /* If now it passed but failed earlier */
- DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
- DEBUG_DQS_D(cs, 1);
- DEBUG_DQS_S(", DQ - ");
- DEBUG_DQS_D(victim_dq, 1);
- DEBUG_DQS_S(", Pup - ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_S(", ADLL - ");
- DEBUG_DQS_D(curr_adll, 2);
- DEBUG_DQS_S("\n");
- #if defined(MV88F78X60)
- for (dq = 0; dq < DQ_NUM;
- dq++) {
- if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
- analog_pbs
- [victim_dq]
- [pup][dq]
- [0] =
- curr_adll;
- }
- #endif
- /* Found start of window */
- pup_adll_limit_state[pup] =
- PUP_ADLL_LIMITS_STATE_PASS;
- /* Keep min / max limit value */
- if (is_tx == 0) {
- /* RX - found low limit */
- if (centralization_low_limit[pup] <= curr_adll)
- centralization_low_limit
- [pup] =
- curr_adll;
- } else {
- /* TX - found high limit */
- if (centralization_high_limit[pup] >= curr_adll)
- centralization_high_limit
- [pup] =
- curr_adll;
- }
- }
- }
- }
- if (unlock_pup == 0) {
- /* Found limit to all pups */
- DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
- break;
- }
- /*
- * Increment / decrement (Move to right / left
- * one phase - ADLL) dqs RX / TX delay (for all un
- * lock pups
- */
- if (is_tx == 0)
- curr_adll++;
- else
- curr_adll--;
- }
- if (unlock_pup != 0) {
- /*
- * Found pups that didn't reach to the end of the
- * state machine
- */
- DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
- unlock_pup, 1);
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
- if (pup_adll_limit_state[pup] ==
- PUP_ADLL_LIMITS_STATE_FAIL) {
- /* ERROR - found fail for all window size */
- DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_C(" victim DQ ",
- victim_dq, 1);
- /* For debug - set min limit to illegal limit */
- centralization_low_limit[pup]
- = ADLL_ERROR;
- /*
- * In case the pup is in mode
- * PASS - the limit is the min
- * / max adll, no need to
- * update because of the results
- * array default value
- */
- return MV_DDR3_TRAINING_ERR_PUP_RANGE;
- }
- }
- }
- }
- }
- DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- for (pup = 0; pup < max_pup; pup++) {
- DEBUG_DQS_S("Victim DQ-");
- DEBUG_DQS_D(victim_dq, 1);
- DEBUG_DQS_S(", PUP-");
- DEBUG_DQS_D(pup, 1);
- for (dq = 0; dq < DQ_NUM; dq++) {
- DEBUG_DQS_S(", DQ-");
- DEBUG_DQS_D(dq, 1);
- DEBUG_DQS_S(",S-");
- DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
- [0], 2);
- DEBUG_DQS_S(",E-");
- DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
- [1], 2);
- if (is_tx == 0) {
- if (analog_pbs[victim_dq][pup][dq][0]
- > analog_pbs_sum[pup][dq][0])
- analog_pbs_sum[pup][dq][0] =
- analog_pbs[victim_dq][pup]
- [dq][0];
- if (analog_pbs[victim_dq][pup][dq][1]
- < analog_pbs_sum[pup][dq][1])
- analog_pbs_sum[pup][dq][1] =
- analog_pbs[victim_dq][pup]
- [dq][1];
- } else {
- if (analog_pbs[victim_dq][pup][dq][0]
- < analog_pbs_sum[pup][dq][0])
- analog_pbs_sum[pup][dq][0] =
- analog_pbs[victim_dq][pup]
- [dq][0];
- if (analog_pbs[victim_dq][pup][dq][1]
- > analog_pbs_sum[pup][dq][1])
- analog_pbs_sum[pup][dq][1] =
- analog_pbs[victim_dq][pup]
- [dq][1];
- }
- }
- DEBUG_DQS_S("\n");
- }
- }
- if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
- u32 dq;
- DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
- if (is_tx) {
- DEBUG_PER_DQ_C("DDR3 - TX CS: ", cs, 1);
- } else {
- DEBUG_PER_DQ_C("DDR3 - RX CS: ", cs, 1);
- }
- if (ecc == 0) {
- DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
- } else {
- DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
- }
- /* Since all dq has the same value we take 0 as representive */
- dq = 0;
- for (pup = 0; pup < max_pup; pup++) {
- if (ecc == 0) {
- DEBUG_PER_DQ_S("\nBYTE:");
- DEBUG_PER_DQ_D(pup, 1);
- DEBUG_PER_DQ_S("\n");
- } else {
- DEBUG_PER_DQ_S("\nECC BYTE:\n");
- }
- DEBUG_PER_DQ_S(" DQ's LOW HIGH WIN-SIZE\n");
- DEBUG_PER_DQ_S("============================================\n");
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- if (ecc == 0) {
- DEBUG_PER_DQ_S("DQ[");
- DEBUG_PER_DQ_DD((victim_dq +
- DQ_NUM * pup), 2);
- DEBUG_PER_DQ_S("]");
- } else {
- DEBUG_PER_DQ_S("CB[");
- DEBUG_PER_DQ_DD(victim_dq, 2);
- DEBUG_PER_DQ_S("]");
- }
- if (is_tx) {
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2); /* low value */
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* high value */
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2); /* win-size */
- } else {
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* low value */
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2); /* high value */
- DEBUG_PER_DQ_S(" 0x");
- DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2); /* win-size */
- }
- DEBUG_PER_DQ_S("\n");
- }
- }
- DEBUG_PER_DQ_S("\n");
- }
- if (is_tx) {
- DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
- } else {
- DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
- }
- for (pup = 0; pup < max_pup; pup++) {
- DEBUG_DQS_S("PUP-");
- DEBUG_DQS_D(pup, 1);
- for (dq = 0; dq < DQ_NUM; dq++) {
- DEBUG_DQS_S(", DQ-");
- DEBUG_DQS_D(dq, 1);
- DEBUG_DQS_S(",S-");
- DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
- DEBUG_DQS_S(",E-");
- DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
- }
- DEBUG_DQS_S("\n");
- }
- if (is_tx) {
- DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
- } else {
- DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
- }
- for (pup = 0; pup < max_pup; pup++) {
- if (max_pup == 1) {
- /* For ECC PUP */
- DEBUG_DQS_S("DDR3 - DQS8");
- } else {
- DEBUG_DQS_S("DDR3 - DQS");
- DEBUG_DQS_D(pup, 1);
- }
- for (dq = 0; dq < DQ_NUM; dq++) {
- DEBUG_DQS_S(", DQ-");
- DEBUG_DQS_D(dq, 1);
- DEBUG_DQS_S("::S-");
- DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
- DEBUG_DQS_S(",E-");
- DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
- }
- DEBUG_DQS_S("\n");
- }
- DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
- return MV_OK;
- }
- /*
- * Name: ddr3_check_window_limits
- * Desc: Check window High & Low limits.
- * Args: pup pup index
- * high_limit window high limit
- * low_limit window low limit
- * is_tx Indicate whether Rx or Tx
- * size_valid Indicate whether window size is valid
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
- int *size_valid)
- {
- DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
- if (low_limit > high_limit) {
- DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_S(" Low Limit grater than High Limit\n");
- *size_valid = 0;
- return MV_OK;
- }
- /*
- * Check that window size is valid, if not it was probably false pass
- * before
- */
- if ((high_limit - low_limit) < MIN_WIN_SIZE) {
- /*
- * Since window size is too small probably there was false
- * pass
- */
- *size_valid = 0;
- DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
- } else if ((high_limit - low_limit) > ADLL_MAX) {
- *size_valid = 0;
- DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
- DEBUG_DQS_D(pup, 1);
- DEBUG_DQS_S
- (" Window size is bigger than max ADLL taps (31) Exiting.\n");
- return MV_FAIL;
- } else {
- *size_valid = 1;
- DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
- DEBUG_DQS_FULL_D(pup, 1);
- DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
- 2);
- }
- return MV_OK;
- }
- /*
- * Name: ddr3_center_calc
- * Desc: Execute the calculate the center of windows phase.
- * Args: pDram Info
- * is_tx Indicate whether Rx or Tx
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx)
- {
- /* bit array of pups that need specail search */
- u32 special_pattern_i_pup = 0;
- u32 special_pattern_ii_pup = 0;
- u32 pup;
- u32 max_pup;
- max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
- for (pup = 0; pup < max_pup; pup++) {
- if (is_tx == 0) {
- /* Check special pattern I */
- /*
- * Special pattern Low limit search - relevant only
- * for Rx, win size < threshold and low limit = 0
- */
- if (((centralization_high_limit[pup] -
- centralization_low_limit[pup]) < VALID_WIN_THRS)
- && (centralization_low_limit[pup] == MIN_DELAY))
- special_pattern_i_pup |= (1 << pup);
- /* Check special pattern II */
- /*
- * Special pattern High limit search - relevant only
- * for Rx, win size < threshold and high limit = 31
- */
- if (((centralization_high_limit[pup] -
- centralization_low_limit[pup]) < VALID_WIN_THRS)
- && (centralization_high_limit[pup] == MAX_DELAY))
- special_pattern_ii_pup |= (1 << pup);
- }
- }
- /* Run special pattern Low limit search - for relevant pup */
- if (special_pattern_i_pup != 0) {
- DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
- if (MV_OK !=
- ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
- special_pattern_i_pup))
- return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
- }
- /* Run special pattern High limit search - for relevant pup */
- if (special_pattern_ii_pup != 0) {
- DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
- if (MV_OK !=
- ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
- special_pattern_ii_pup))
- return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
- }
- /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
- return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
- }
- /*
- * Name: ddr3_special_pattern_i_search
- * Desc: Execute special pattern low limit search.
- * Args:
- * special_pattern_pup The pups that need the special search
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx, u32 special_pattern_pup)
- {
- u32 victim_dq; /* loop index - victim DQ */
- u32 adll_idx;
- u32 pup;
- u32 unlock_pup; /* bit array of the unlock pups */
- u32 first_fail; /* bit array - of pups that get first fail */
- u32 new_lockup_pup; /* bit array of compare failed pups */
- u32 pass_pup; /* bit array of compare pass pup */
- u32 sdram_offset;
- u32 max_pup;
- u32 comp_val;
- u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
- DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
- max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
- /* Init the temporary results to max ADLL value */
- for (pup = 0; pup < max_pup; pup++)
- special_res[pup] = ADLL_MAX;
- /* Run special pattern for all DQ - use the same pattern */
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- unlock_pup = special_pattern_pup;
- first_fail = 0;
- sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
- LEN_KILLER_PATTERN * 4 * victim_dq;
- for (pup = 0; pup < max_pup; pup++) {
- /* Set adll value per PUP. adll = high limit per pup */
- if (IS_PUP_ACTIVE(unlock_pup, pup)) {
- /* only for pups that need special search */
- ddr3_write_pup_reg(PUP_DQS_RD, cs,
- pup + (ecc * ECC_PUP), 0,
- centralization_high_limit
- [pup]);
- }
- }
- adll_idx = 0;
- do {
- /*
- * Perform read and compare simultaneously for all
- * un-locked MC use the special pattern mask
- */
- new_lockup_pup = 0;
- if (MV_OK !=
- ddr3_sdram_dqs_compare(dram_info, unlock_pup,
- &new_lockup_pup,
- special_pattern
- [victim_dq],
- LEN_SPECIAL_PATTERN,
- sdram_offset, 0,
- 0, NULL, 1))
- return MV_FAIL;
- DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
- DEBUG_DQS_D(adll_idx, 2);
- DEBUG_DQS_S(", UnlockPup: ");
- DEBUG_DQS_D(unlock_pup, 2);
- DEBUG_DQS_S(", NewLockPup: ");
- DEBUG_DQS_D(new_lockup_pup, 2);
- DEBUG_DQS_S("\n");
- if (unlock_pup != new_lockup_pup)
- DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
- /* Search for pups with passed compare & already fail */
- pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
- first_fail |= new_lockup_pup;
- unlock_pup &= ~pass_pup;
- /* Get pass pups */
- if (pass_pup != 0) {
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(pass_pup, pup) ==
- 1) {
- /* If pup passed and has first fail = 1 */
- /* keep min value of ADLL max value - current adll */
- /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
- comp_val =
- (ADLL_MAX -
- (centralization_high_limit
- [pup] + adll_idx));
- DEBUG_DQS_C
- ("DDR3 - DQS - Special I - Pup - ",
- pup, 1);
- DEBUG_DQS_C
- (" comp_val = ",
- comp_val, 2);
- if (comp_val <
- special_res[pup]) {
- special_res[pup] =
- comp_val;
- centralization_low_limit
- [pup] =
- (-1) *
- comp_val;
- DEBUG_DQS_C
- ("DDR3 - DQS - Special I - Pup - ",
- pup, 1);
- DEBUG_DQS_C
- (" Changed Low limit to ",
- centralization_low_limit
- [pup], 2);
- }
- }
- }
- }
- /*
- * Did all PUP found missing window?
- * Check for each pup if adll (different for each pup)
- * reach maximum if reach max value - lock the pup
- * if not - increment (Move to right one phase - ADLL)
- * dqs RX delay
- */
- adll_idx++;
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
- /* Check only unlocked pups */
- if ((centralization_high_limit[pup] +
- adll_idx) >= ADLL_MAX) {
- /* reach maximum - lock the pup */
- DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
- pup, 1);
- unlock_pup &= ~(1 << pup);
- } else {
- /* Didn't reach maximum - increment ADLL */
- ddr3_write_pup_reg(PUP_DQS_RD,
- cs,
- pup +
- (ecc *
- ECC_PUP), 0,
- (centralization_high_limit
- [pup] +
- adll_idx));
- }
- }
- }
- } while (unlock_pup != 0);
- }
- return MV_OK;
- }
- /*
- * Name: ddr3_special_pattern_ii_search
- * Desc: Execute special pattern high limit search.
- * Args:
- * special_pattern_pup The pups that need the special search
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
- int is_tx, u32 special_pattern_pup)
- {
- u32 victim_dq; /* loop index - victim DQ */
- u32 adll_idx;
- u32 pup;
- u32 unlock_pup; /* bit array of the unlock pups */
- u32 first_fail; /* bit array - of pups that get first fail */
- u32 new_lockup_pup; /* bit array of compare failed pups */
- u32 pass_pup; /* bit array of compare pass pup */
- u32 sdram_offset;
- u32 max_pup;
- u32 comp_val;
- u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
- DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
- max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
- /* init the tmporary results to max ADLL value */
- for (pup = 0; pup < max_pup; pup++)
- special_res[pup] = ADLL_MAX;
- sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
- /* run special pattern for all DQ - use the same pattern */
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- unlock_pup = special_pattern_pup;
- first_fail = 0;
- for (pup = 0; pup < max_pup; pup++) {
- /* Set adll value per PUP. adll = 0 */
- if (IS_PUP_ACTIVE(unlock_pup, pup)) {
- /* Only for pups that need special search */
- ddr3_write_pup_reg(PUP_DQS_RD, cs,
- pup + (ecc * ECC_PUP), 0,
- ADLL_MIN);
- }
- }
- adll_idx = 0;
- do {
- /*
- * Perform read and compare simultaneously for all
- * un-locked MC use the special pattern mask
- */
- new_lockup_pup = 0;
- if (MV_OK != ddr3_sdram_dqs_compare(
- dram_info, unlock_pup, &new_lockup_pup,
- special_pattern[victim_dq],
- LEN_SPECIAL_PATTERN,
- sdram_offset, 0, 0, NULL, 0))
- return MV_FAIL;
- DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
- DEBUG_DQS_D(adll_idx, 2);
- DEBUG_DQS_S("unlock_pup ");
- DEBUG_DQS_D(unlock_pup, 1);
- DEBUG_DQS_S("new_lockup_pup ");
- DEBUG_DQS_D(new_lockup_pup, 1);
- DEBUG_DQS_S("\n");
- if (unlock_pup != new_lockup_pup) {
- DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
- }
- /* Search for pups with passed compare & already fail */
- pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
- first_fail |= new_lockup_pup;
- unlock_pup &= ~pass_pup;
- /* Get pass pups */
- if (pass_pup != 0) {
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(pass_pup, pup) ==
- 1) {
- /* If pup passed and has first fail = 1 */
- /* keep min value of ADLL max value - current adll */
- /* (adll_idx) = current adll !!! */
- comp_val = adll_idx;
- DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
- pup, 1);
- DEBUG_DQS_C(" comp_val = ",
- comp_val, 1);
- if (comp_val <
- special_res[pup]) {
- special_res[pup] =
- comp_val;
- centralization_high_limit
- [pup] =
- ADLL_MAX +
- comp_val;
- DEBUG_DQS_C
- ("DDR3 - DQS - Special II - Pup - ",
- pup, 1);
- DEBUG_DQS_C
- (" Changed High limit to ",
- centralization_high_limit
- [pup], 2);
- }
- }
- }
- }
- /*
- * Did all PUP found missing window?
- * Check for each pup if adll (different for each pup)
- * reach maximum if reach max value - lock the pup
- * if not - increment (Move to right one phase - ADLL)
- * dqs RX delay
- */
- adll_idx++;
- for (pup = 0; pup < max_pup; pup++) {
- if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
- /* Check only unlocked pups */
- if ((adll_idx) >= ADLL_MAX) {
- /* Reach maximum - lock the pup */
- DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
- pup, 1);
- unlock_pup &= ~(1 << pup);
- } else {
- /* Didn't reach maximum - increment ADLL */
- ddr3_write_pup_reg(PUP_DQS_RD,
- cs,
- pup +
- (ecc *
- ECC_PUP), 0,
- (adll_idx));
- }
- }
- }
- } while (unlock_pup != 0);
- }
- return MV_OK;
- }
- /*
- * Name: ddr3_set_dqs_centralization_results
- * Desc: Set to HW the DQS centralization phase results.
- * Args:
- * is_tx Indicates whether to set Tx or RX results
- * Notes:
- * Returns: MV_OK if success, other error code if fail.
- */
- int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
- u32 ecc, int is_tx)
- {
- u32 pup, pup_num;
- int addl_val;
- u32 max_pup;
- max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
- DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
- if (is_tx) {
- DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
- cs, 1);
- } else {
- DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
- cs, 1);
- }
- /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
- DEBUG_DQS_RESULTS_S("\nDQS LOW HIGH WIN-SIZE Set\n");
- DEBUG_DQS_RESULTS_S("==============================================\n");
- for (pup = 0; pup < max_pup; pup++) {
- addl_val = (centralization_high_limit[pup] +
- centralization_low_limit[pup]) / 2;
- pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
- DEBUG_DQS_RESULTS_D(pup_num, 1);
- DEBUG_DQS_RESULTS_S(" 0x");
- DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
- DEBUG_DQS_RESULTS_S(" 0x");
- DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
- DEBUG_DQS_RESULTS_S(" 0x");
- DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
- centralization_low_limit[pup], 2);
- DEBUG_DQS_RESULTS_S(" 0x");
- DEBUG_DQS_RESULTS_D(addl_val, 2);
- DEBUG_DQS_RESULTS_S("\n");
- if (addl_val < ADLL_MIN) {
- addl_val = ADLL_MIN;
- DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
- }
- if (addl_val > ADLL_MAX) {
- addl_val = ADLL_MAX;
- DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
- }
- if (is_tx) {
- ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
- addl_val +
- dram_info->wl_val[cs][pup_num][D]);
- } else {
- ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
- addl_val);
- }
- }
- return MV_OK;
- }
- /*
- * Set training patterns
- */
- int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
- {
- u32 cs, cs_count, cs_tmp, victim_dq;
- u32 sdram_addr;
- u32 *pattern_ptr;
- /* Loop for each CS */
- for (cs = 0; cs < MAX_CS; cs++) {
- if (dram_info->cs_ena & (1 << cs)) {
- cs_count = 0;
- for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
- if (dram_info->cs_ena & (1 << cs_tmp))
- cs_count++;
- }
- /* Init killer pattern */
- sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
- SDRAM_DQS_RX_OFFS);
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
- victim_dq);
- if (MV_OK != ddr3_sdram_dqs_compare(
- dram_info, (u32)NULL, NULL,
- pattern_ptr, LEN_KILLER_PATTERN,
- sdram_addr + LEN_KILLER_PATTERN *
- 4 * victim_dq, 1, 0, NULL,
- 0))
- return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
- }
- /* Init special-killer pattern */
- sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
- SDRAM_DQS_RX_SPECIAL_OFFS);
- for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
- if (MV_OK != ddr3_sdram_dqs_compare(
- dram_info, (u32)NULL, NULL,
- special_pattern[victim_dq],
- LEN_KILLER_PATTERN, sdram_addr +
- LEN_KILLER_PATTERN * 4 * victim_dq,
- 1, 0, NULL, 0))
- return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
- }
- }
- }
- return MV_OK;
- }
|