19b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney/************************************************************************
29b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney *
39b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney * Copyright (c) 2013-2015 Intel Corporation.
49b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney *
59b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* This program and the accompanying materials
69b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* are licensed and made available under the terms and conditions of the BSD License
79b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* which accompanies this distribution.  The full text of the license may be found at
89b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* http://opensource.org/licenses/bsd-license.php
99b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney*
109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney *
139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney ***************************************************************************/
149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "mrc.h"
169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "memory_options.h"
179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "meminit_utils.h"
199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "hte.h"
209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#include "io.h"
219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid select_hte(
239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params);
249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneystatic uint8_t first_run = 0;
269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyconst uint8_t vref_codes[64] =
289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{ // lowest to highest
299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, // 00 - 15
309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, // 16 - 31
319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 32 - 47
329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F  // 48 - 63
339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney};
349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#ifdef EMU
369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// Track current post code for debugging purpose
379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t PostCode;
389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_rcvn:
419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the RCVEN delays.
439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_rcvn(
459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane,
489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (byte_lane & BIT0) ? (BIT23 | BIT22 | BIT21 | BIT20) : (BIT11 | BIT10 | BIT9 | BIT8);
629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = (byte_lane & BIT0) ? ((pi_count / HALF_CLK) << 20) : ((pi_count / HALF_CLK) << 8);
639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count << 24;
759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[08/11] (+1 select)
799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[02/05] (enable)
809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT5) : (BIT2);
859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT11) : (BIT8);
919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
1009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    training_message(channel, rank, byte_lane);
1019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE0);
1029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
1039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
1059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
1069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
1079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_rcvn:
1099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
1109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the current RCVEN delay on the given channel, rank, byte_lane as an absolute PI count.
1119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
1129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_rcvn(
1139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
1149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
1159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
1169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
1189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
1199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
1209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
1229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
1249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
1259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
1269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
1279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
1289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= (byte_lane & BIT0) ? (20) : (8);
1299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
1309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
1329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = tempD * HALF_CLK;
1339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
1359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
1369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
1379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
1389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
1399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
1409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 24;
1419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
1429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
1449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
1459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
1479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
1489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
1499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_rdqs:
1519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
1529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the RDQS delays based on an absolute amount of PIs.
1539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
1549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_rdqs(
1559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
1569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
1579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane,
1589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
1599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
1619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
1629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
1639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
1659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
1669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/128 MCLK)
1689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
1699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
1709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);
1719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
1729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
1739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count << 0;
1749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
1759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check (shouldn't go above 0x3F)
1779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x47)
1789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
1799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    training_message(channel, rank, byte_lane);
1809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE1);
1819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
1829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
1849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
1859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
1869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_rdqs:
1889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
1899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the current RDQS delay on the given channel, rank, byte_lane as an absolute PI count.
1909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
1919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_rdqs(
1929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
1939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
1949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
1959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
1969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
1979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
1989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
1999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
2019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/128 MCLK)
2039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
2049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
2059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1RXDQSPICODE) : (B0RXDQSPICODE);
2069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
2079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
2089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
2109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = tempD & 0x7F;
2119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
2139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
2149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
2159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_wdqs:
2179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
2189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the WDQS delays based on an absolute amount of PIs.
2199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
2209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_wdqs(
2219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
2229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
2239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane,
2249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
2259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
2269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
2279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
2289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
2299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
2319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
2329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
2349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
2359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
2369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
2379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (byte_lane & BIT0) ? (BIT19 | BIT18 | BIT17 | BIT16) : (BIT7 | BIT6 | BIT5 | BIT4);
2389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count / HALF_CLK;
2399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD <<= (byte_lane & BIT0) ? (16) : (4);
2409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
2419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
2439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
2449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
2469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
2479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
2489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
2499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
2509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16);
2519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count << 16;
2529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
2539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
2559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[07/10] (+1 select)
2569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[01/04] (enable)
2579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
2589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
2599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
2609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
2619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT4) : (BIT1);
2629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
2639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
2649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
2659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
2669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
2679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT10) : (BIT7);
2689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
2699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
2709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
2719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
2729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
2739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
2759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
2769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
2779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    training_message(channel, rank, byte_lane);
2789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE2);
2799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
2809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
2829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
2839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
2849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_wdqs:
2869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
2879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the amount of WDQS delay on the given channel, rank, byte_lane as an absolute PI count.
2889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
2899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_wdqs(
2909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
2919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
2929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
2939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
2949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
2959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
2969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
2979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
2989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
2999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
3019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
3029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
3039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
3049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
3059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= (byte_lane & BIT0) ? (16) : (4);
3069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
3079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
3099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = (tempD * HALF_CLK);
3109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
3129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
3139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
3149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
3159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
3169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
3179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 16;
3189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
3199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
3219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
3229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
3249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
3259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
3269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_wdq:
3289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
3299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the WDQ delays based on an absolute number of PIs.
3309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
3319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_wdq(
3329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
3339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
3349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane,
3359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
3369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
3379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
3389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
3399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
3409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
3429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n", channel, rank, byte_lane, pi_count);
3439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
3459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
3469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
3479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
3489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (byte_lane & BIT0) ? (BIT15 | BIT14 | BIT13 | BIT12) : (BIT3 | BIT2 | BIT1 | BIT0);
3499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count / HALF_CLK;
3509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD <<= (byte_lane & BIT0) ? (12) : (0);
3519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
3529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
3549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
3559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
3579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
3589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
3599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
3609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
3619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
3629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count << 8;
3639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
3649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
3669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[06/09] (+1 select)
3679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0/1 -> B01DBCTL1[00/03] (enable)
3689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01DBCTL1 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
3699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
3709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
3719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
3729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT3) : (BIT0);
3739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
3749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
3759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
3769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
3779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
3789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (byte_lane & BIT0) ? (BIT9) : (BIT6);
3799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
3809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
3819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
3829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
3839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
3849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
3869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
3879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
3889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    training_message(channel, rank, byte_lane);
3899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE3);
3909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
3919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
3939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
3949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
3959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
3969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_wdq:
3979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
3989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the amount of WDQ delay on the given channel, rank, byte_lane as an absolute PI count.
3999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
4009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_wdq(
4019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
4029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
4039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
4049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
4059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
4069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
4079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
4089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
4109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
4129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
4139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
4149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = B01PTRCTL0 + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET);
4159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
4169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= (byte_lane & BIT0) ? (12) : (0);
4179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
4189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
4209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = (tempD * HALF_CLK);
4219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
4239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
4249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
4259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (byte_lane & BIT0) ? (B1DLLPICODER0) : (B0DLLPICODER0);
4269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (((byte_lane >> 1) * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET));
4279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
4289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 8;
4299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
4309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
4329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
4339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
4359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
4369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
4379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_wcmd:
4399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
4409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the WCMD delays based on an absolute number of PIs.
4419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_wcmd(
4429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
4439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
4449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
4459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
4469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
4479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
4489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
4509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
4519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDPTRREG[11:08] (0x0-0xF)
4529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
4539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT11 | BIT10 | BIT9 | BIT8);
4549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = pi_count / HALF_CLK;
4559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD <<= 8;
4569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
4579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
4599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
4609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
4629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
4639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
4649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
4659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
4669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
4679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
4689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
4699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
4709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
4719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24) | (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
4739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8) | (BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);
4749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = (pi_count << 24) | (pi_count << 16) | (pi_count << 8) | (pi_count << 0);
4769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
4789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDDLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET); // PO
4799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
4809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
4819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
4829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDCFGREG0[17] (+1 select)
4839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDCFGREG0[16] (enable)
4849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDCFGREG0 + (channel * DDRIOCCC_CH_OFFSET);
4859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
4869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
4879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
4889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= BIT16;
4899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
4909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
4919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
4929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
4939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
4949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= BIT17;
4959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
4969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
4979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
4989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
4999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
5029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
5039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
5049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE4);
5059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
5069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
5089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
5099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
5109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_wcmd:
5129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
5139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the amount of WCMD delay on the given channel as an absolute PI count.
5149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_wcmd(
5159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel)
5169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
5179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
5189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
5199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
5209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
5229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
5239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDPTRREG[11:08] (0x0-0xF)
5249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDPTRREG + (channel * DDRIOCCC_CH_OFFSET);
5259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
5269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 8;
5279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
5289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
5309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = tempD * HALF_CLK;
5319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
5339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
5349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
5359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
5369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
5379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
5389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
5399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
5409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
5419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CMDDLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
5429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
5439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 16;
5449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
5459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
5479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
5489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
5509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
5519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
5529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_wclk:
5549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
5559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the WCLK delays based on an absolute number of PIs.
5569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_wclk(
5579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
5589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
5599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
5609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
5619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
5629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
5639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
5649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
5669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
5679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[15:12] -> CLK1 (0x0-0xF)
5689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[11:08] -> CLK0 (0x0-0xF)
5699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
5709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT15 | BIT14 | BIT13 | BIT12) | (BIT11 | BIT10 | BIT9 | BIT8);
5719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);
5729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
5759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
5769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
5789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
5799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
5809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);
5819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (channel * DDRIOCCC_CH_OFFSET);
5829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16) | (BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8);
5839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = (pi_count << 16) | (pi_count << 8);
5849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (rank) ? (ECCB1DLLPICODER1) : (ECCB1DLLPICODER1);
5869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (channel * DDRIOCCC_CH_OFFSET);
5879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (rank) ? (ECCB1DLLPICODER2) : (ECCB1DLLPICODER2);
5899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (channel * DDRIOCCC_CH_OFFSET);
5909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (rank) ? (ECCB1DLLPICODER3) : (ECCB1DLLPICODER3);
5929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (channel * DDRIOCCC_CH_OFFSET);
5939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
5949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
5959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
5969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCCFGREG1[11:08] (+1 select)
5979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCCFGREG1[03:00] (enable)
5989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
5999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
6009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
6019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
6029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (BIT3 | BIT2 | BIT1 | BIT0); // only ??? matters
6039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
6049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
6059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
6069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
6089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (BIT11 | BIT10 | BIT9 | BIT8); // only ??? matters
6099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
6109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
6119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
6129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
6149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
6169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
6179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
6189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE5);
6199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
6209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
6229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
6239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
6249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_wclk:
6269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
6279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the amout of WCLK delay on the given channel, rank as an absolute PI count.
6289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_wclk(
6299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
6309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank)
6319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
6329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
6339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
6349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
6359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
6379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
6389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[15:12] -> CLK1 (0x0-0xF)
6399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[11:08] -> CLK0 (0x0-0xF)
6409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
6419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
6429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= (rank) ? (12) : (8);
6439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
6449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
6469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = tempD * HALF_CLK;
6479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
6499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
6509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
6519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = (rank) ? (ECCB1DLLPICODER0) : (ECCB1DLLPICODER0);
6529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg += (channel * DDRIOCCC_CH_OFFSET);
6539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
6549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= (rank) ? (16) : (8);
6559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
6569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
6589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
6609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
6619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
6629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_wctl:
6649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
6659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the WCTL delays based on an absolute number of PIs.
6669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
6679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_wctl(
6689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
6699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
6709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t pi_count)
6719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
6729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
6739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk;
6749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
6759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
6779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
6799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[31:28] (0x0-0xF)
6809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[27:24] (0x0-0xF)
6819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
6829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT31 | BIT30 | BIT29 | BIT28) | (BIT27 | BIT26 | BIT25 | BIT24);
6839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);
6849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
6859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
6879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count -= ((pi_count / HALF_CLK) & 0xF) * HALF_CLK;
6889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
6899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
6909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
6919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
6929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
6939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = (BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24);
6949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = (pi_count << 24);
6959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
6969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = ECCB1DLLPICODER1 + (channel * DDRIOCCC_CH_OFFSET);
6979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
6989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = ECCB1DLLPICODER2 + (channel * DDRIOCCC_CH_OFFSET);
6999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
7009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = ECCB1DLLPICODER3 + (channel * DDRIOCCC_CH_OFFSET);
7019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
7029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // DEADBAND
7049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCCFGREG1[13:12] (+1 select)
7059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCCFGREG1[05:04] (enable)
7069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCCFGREG1 + (channel * DDRIOCCC_CH_OFFSET);
7079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk = 0x00;
7089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = 0x00;
7099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // enable
7109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (BIT5 | BIT4); // only ??? matters
7119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
7129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
7139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
7149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
7159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select
7169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk |= (BIT13 | BIT12); // only ??? matters
7179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count < EARLY_DB)
7189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
7199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD |= msk;
7209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
7219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, reg, tempD, msk);
7229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check
7249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (pi_count > 0x3F)
7259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
7269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    post_code(0xEE, 0xE6);
7279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
7289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
7309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
7319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
7329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_wctl:
7349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
7359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the amount of WCTL delay on the given channel, rank as an absolute PI count.
7369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// (currently doesn't comprehend rank)
7379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_wctl(
7389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
7399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank)
7409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
7419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg;
7429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
7439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t pi_count;
7449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
7469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // RDPTR (1/2 MCLK, 64 PIs)
7489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[31:28] (0x0-0xF)
7499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // CCPTRREG[27:24] (0x0-0xF)
7509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = CCPTRREG + (channel * DDRIOCCC_CH_OFFSET);
7519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
7529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 24;
7539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0xF;
7549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
7569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count = tempD * HALF_CLK;
7579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // PI (1/64 MCLK, 1 PIs)
7599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
7609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ECCB1DLLPICODER?[29:24] (0x00-0x3F)
7619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  reg = ECCB1DLLPICODER0 + (channel * DDRIOCCC_CH_OFFSET);
7629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, reg);
7639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 24;
7649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
7659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Adjust PI_COUNT
7679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  pi_count += tempD;
7689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
7709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return pi_count;
7719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
7729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// set_vref:
7749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
7759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will program the internal Vref setting in a given byte lane in a given channel.
7769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid set_vref(
7779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
7789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane,
7799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t setting)
7809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
7819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
7829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
7849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n", channel, byte_lane, setting);
7859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)),
7879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      (vref_codes[setting] << 2), (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2));
7889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  //isbM32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)), (setting<<2), (BIT7|BIT6|BIT5|BIT4|BIT3|BIT2));
7899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // need to wait ~300ns for Vref to settle (check that this is necessary)
7909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  delay_n(300);
7919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // ??? may need to clear pointers ???
7929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
7939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
7949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
7959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
7969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_vref:
7979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
7989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return the internal Vref setting for the given channel, byte_lane;
7999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_vref(
8009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
8019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
8029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t j;
8049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t ret_val = sizeof(vref_codes) / 2;
8059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t reg = (byte_lane & 0x1) ? (B1VREFCTL) : (B0VREFCTL);
8069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD;
8089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
8109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD = isbR32m(DDRPHY, (reg + (channel * DDRIODQ_CH_OFFSET) + ((byte_lane >> 1) * DDRIODQ_BL_OFFSET)));
8119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD >>= 2;
8129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tempD &= 0x3F;
8139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (j = 0; j < sizeof(vref_codes); j++)
8149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
8159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (vref_codes[j] == tempD)
8169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
8179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      ret_val = j;
8189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
8199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
8209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
8229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return ret_val;
8239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// clear_pointers:
8269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
8279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will be used to clear the pointers in a given byte lane in a given channel.
8289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid clear_pointers(
8299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    void)
8309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t channel_i;
8329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_i;
8339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
8359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
8369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
8379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (bl_i = 0; bl_i < NUM_BYTE_LANES; bl_i++)
8389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
8399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), ~(BIT8),
8409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          (BIT8));
8419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      //delay_m(1); // DEBUG
8429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      isbM32m(DDRPHY, (B01PTRCTL1 + (channel_i * DDRIODQ_CH_OFFSET) + ((bl_i >> 1) * DDRIODQ_BL_OFFSET)), (BIT8),
8439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          (BIT8));
8449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
8459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
8469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
8479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
8489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// void enable_cache:
8519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid enable_cache(
8529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    void)
8539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Cache control not used in Quark MRC
8559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
8569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// void disable_cache:
8599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid disable_cache(
8609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    void)
8619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Cache control not used in Quark MRC
8639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
8649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// Send DRAM command, data should be formated
8679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// using DCMD_Xxxx macro or emrsXCommand structure.
8689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneystatic void dram_init_command(
8699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t data)
8709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  Wr32(DCMD, 0, data);
8729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
8739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// find_rising_edge:
8759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
8769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will find the rising edge transition on RCVN or WDQS.
8779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid find_rising_edge(
8789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params,
8799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t delay[],
8809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
8819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
8829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bool rcvn)
8839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
8849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#define SAMPLE_CNT 3   // number of sample points
8869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#define SAMPLE_DLY 26  // number of PIs to increment per sample
8879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#define FORWARD true   // indicates to increase delays when looking for edge
8889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#define BACKWARD false // indicates to decrease delays when looking for edge
8899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  bool all_edges_found; // determines stop condition
8919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  bool direction[NUM_BYTE_LANES]; // direction indicator
8929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t sample_i; // sample counter
8939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_i; // byte lane counter
8949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
8959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t sample_result[SAMPLE_CNT]; // results of "sample_dqs()"
8969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t tempD; // temporary DWORD
8979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t transition_pattern;
8989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
8999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
9009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // select hte and request initial configuration
9029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  select_hte(mrc_params);
9039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  first_run = 1;
9049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Take 3 sample points (T1,T2,T3) to obtain a transition pattern.
9069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)
9079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
9089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // program the desired delays for sample
9099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
9109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
9119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // increase sample delay by 26 PI (0.2 CLK)
9129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      if (rcvn)
9139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
9149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_rcvn(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));
9159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
9169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      else
9179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
9189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_wdqs(channel, rank, bl_i, delay[bl_i] + (sample_i * SAMPLE_DLY));
9199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
9209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } // bl_i loop
9219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // take samples (Tsample_i)
9229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    sample_result[sample_i] = sample_dqs(mrc_params, channel, rank, rcvn);
9239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DPF(D_TRN, "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",
9259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        (rcvn ? "RCVN" : "WDQS"), channel, rank,
9269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        sample_i, sample_i * SAMPLE_DLY, sample_result[sample_i]);
9279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } // sample_i loop
9299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // This pattern will help determine where we landed and ultimately how to place RCVEN/WDQS.
9319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
9329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
9339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // build "transition_pattern" (MSB is 1st sample)
9349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    transition_pattern = 0x00;
9359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (sample_i = 0; sample_i < SAMPLE_CNT; sample_i++)
9369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
9379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      transition_pattern |= ((sample_result[sample_i] & (1 << bl_i)) >> bl_i) << (SAMPLE_CNT - 1 - sample_i);
9389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } // sample_i loop
9399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);
9419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // set up to look for rising edge based on "transition_pattern"
9439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    switch (transition_pattern)
9449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
9459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x00: // sampled 0->0->0
9469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // move forward from T3 looking for 0->1
9479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[bl_i] += 2 * SAMPLE_DLY;
9489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      direction[bl_i] = FORWARD;
9499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x01: // sampled 0->0->1
9519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x05: // sampled 1->0->1 (bad duty cycle) *HSD#237503*
9529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // move forward from T2 looking for 0->1
9539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[bl_i] += 1 * SAMPLE_DLY;
9549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      direction[bl_i] = FORWARD;
9559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// HSD#237503
9579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//      case 0x02: // sampled 0->1->0 (bad duty cycle)
9589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        training_message(channel, rank, bl_i);
9599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        post_code(0xEE, 0xE8);
9609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        break;
9619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x02: // sampled 0->1->0 (bad duty cycle) *HSD#237503*
9629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x03: // sampled 0->1->1
9639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // move forward from T1 looking for 0->1
9649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[bl_i] += 0 * SAMPLE_DLY;
9659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      direction[bl_i] = FORWARD;
9669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x04: // sampled 1->0->0 (assumes BL8, HSD#234975)
9689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // move forward from T3 looking for 0->1
9699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[bl_i] += 2 * SAMPLE_DLY;
9709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      direction[bl_i] = FORWARD;
9719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// HSD#237503
9739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//      case 0x05: // sampled 1->0->1 (bad duty cycle)
9749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        training_message(channel, rank, bl_i);
9759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        post_code(0xEE, 0xE9);
9769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//        break;
9779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x06: // sampled 1->1->0
9789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    case 0x07: // sampled 1->1->1
9799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // move backward from T1 looking for 1->0
9809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[bl_i] += 0 * SAMPLE_DLY;
9819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      direction[bl_i] = BACKWARD;
9829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    default:
9849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      post_code(0xEE, 0xEE);
9859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      break;
9869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } // transition_pattern switch
9879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // program delays
9889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (rcvn)
9899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
9909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      set_rcvn(channel, rank, bl_i, delay[bl_i]);
9919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
9929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    else
9939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
9949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      set_wdqs(channel, rank, bl_i, delay[bl_i]);
9959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
9969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } // bl_i loop
9979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
9989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Based on the observed transition pattern on the byte lane,
9999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // begin looking for a rising edge with single PI granularity.
10009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  do
10019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
10029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    all_edges_found = true; // assume all byte lanes passed
10039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    tempD = sample_dqs(mrc_params, channel, rank, rcvn); // take a sample
10049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // check all each byte lane for proper edge
10059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
10069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
10079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      if (tempD & (1 << bl_i))
10089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
10099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        // sampled "1"
10109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (direction[bl_i] == BACKWARD)
10119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
10129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          // keep looking for edge on this byte lane
10139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          all_edges_found = false;
10149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          delay[bl_i] -= 1;
10159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          if (rcvn)
10169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          {
10179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            set_rcvn(channel, rank, bl_i, delay[bl_i]);
10189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          }
10199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          else
10209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          {
10219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            set_wdqs(channel, rank, bl_i, delay[bl_i]);
10229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          }
10239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
10249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
10259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      else
10269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
10279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        // sampled "0"
10289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (direction[bl_i] == FORWARD)
10299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
10309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          // keep looking for edge on this byte lane
10319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          all_edges_found = false;
10329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          delay[bl_i] += 1;
10339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          if (rcvn)
10349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          {
10359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            set_rcvn(channel, rank, bl_i, delay[bl_i]);
10369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          }
10379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          else
10389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          {
10399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            set_wdqs(channel, rank, bl_i, delay[bl_i]);
10409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          }
10419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
10429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
10439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } // bl_i loop
10449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } while (!all_edges_found);
10459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // restore DDR idle state
10479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  dram_init_command(DCMD_PREA(rank));
10489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_TRN, "Delay %03X %03X %03X %03X\n",
10509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      delay[0], delay[1], delay[2], delay[3]);
10519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
10539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
10549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
10559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// sample_dqs:
10579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
10589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will sample the DQTRAINSTS registers in the given channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.
10599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// It will return an encoded DWORD in which each bit corresponds to the sampled value on the byte lane.
10609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t sample_dqs(
10619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params,
10629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
10639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
10649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bool rcvn)
10659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
10669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t j; // just a counter
10679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_i; // which BL in the module (always 2 per module)
10689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_grp; // which BL module
10699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1; // byte lane divisor
10709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t msk[2]; // BLx in module
10719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t sampled_val[SAMPLE_SIZE]; // DQTRAINSTS register contents for each sample
10729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t num_0s; // tracks the number of '0' samples
10739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t num_1s; // tracks the number of '1' samples
10749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t ret_val = 0x00; // assume all '0' samples
10759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t address = get_addr(mrc_params, channel, rank);
10769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // initialise "msk[]"
10789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk[0] = (rcvn) ? (BIT1) : (BIT9); // BL0
10799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  msk[1] = (rcvn) ? (BIT0) : (BIT8); // BL1
10809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // cycle through each byte lane group
10839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++)
10849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
10859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // take SAMPLE_SIZE samples
10869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (j = 0; j < SAMPLE_SIZE; j++)
10879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
10889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      HteMemOp(address, first_run, rcvn?0:1);
10899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      first_run = 0;
10909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
10919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      // record the contents of the proper DQTRAINSTS register
10929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      sampled_val[j] = isbR32m(DDRPHY, (DQTRAINSTS + (bl_grp * DDRIODQ_BL_OFFSET) + (channel * DDRIODQ_CH_OFFSET)));
10939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
10949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // look for a majority value ( (SAMPLE_SIZE/2)+1 ) on the byte lane
10959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // and set that value in the corresponding "ret_val" bit
10969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (bl_i = 0; bl_i < 2; bl_i++)
10979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
10989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      num_0s = 0x00; // reset '0' tracker for byte lane
10999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      num_1s = 0x00; // reset '1' tracker for byte lane
11009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (j = 0; j < SAMPLE_SIZE; j++)
11019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
11029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (sampled_val[j] & msk[bl_i])
11039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
11049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          num_1s++;
11059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
11069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        else
11079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
11089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          num_0s++;
11099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
11109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
11119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      if (num_1s > num_0s)
11129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
11139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        ret_val |= (1 << (bl_i + (bl_grp * 2)));
11149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
11159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
11169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
11179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // "ret_val.0" contains the status of BL0
11199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // "ret_val.1" contains the status of BL1
11209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // "ret_val.2" contains the status of BL2
11219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // etc.
11229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return ret_val;
11239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
11249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_addr:
11269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
11279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return a 32 bit address in the desired channel and rank.
11289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_addr(
11299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params,
11309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
11319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank)
11329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
11339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t offset = 0x02000000; // 32MB
11349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Begin product specific code
11369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (channel > 0)
11379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
11389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DPF(D_ERROR, "ILLEGAL CHANNEL\n");
11399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DEAD_LOOP();
11409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
11419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (rank > 1)
11439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
11449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DPF(D_ERROR, "ILLEGAL RANK\n");
11459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DEAD_LOOP();
11469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
11479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // use 256MB lowest density as per DRP == 0x0003
11499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  offset += rank * (256 * 1024 * 1024);
11509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return offset;
11529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
11539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// byte_lane_mask:
11559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
11569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will return a 32 bit mask that will be used to check for byte lane failures.
11579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t byte_lane_mask(
11589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
11599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
11609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t j;
11619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t ret_val = 0x00;
11629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // set "ret_val" based on NUM_BYTE_LANES such that you will check only BL0 in "result"
11649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // (each bit in "result" represents a byte lane)
11659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)
11669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
11679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));
11689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
11699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // HSD#235037
11719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // need to adjust the mask for 16-bit mode
11729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (mrc_params->channel_width == x16)
11739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
11749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    ret_val |= (ret_val << 2);
11759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
11769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return ret_val;
11789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
11799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// read_tsc:
11829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
11839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will do some assembly to return TSC register contents as a uint64_t.
11849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint64_t read_tsc(
11859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    void)
11869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
11879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  volatile uint64_t tsc;  // EDX:EAX
11889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#if defined (SIM) || defined (GCC)
11909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  volatile uint32_t tscH; // EDX
11919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  volatile uint32_t tscL;// EAX
11929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
11939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  asm("rdtsc":"=a"(tscL),"=d"(tscH));
11949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tsc = tscH;
11959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tsc = (tsc<<32)|tscL;
11969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#else
11979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  tsc = __rdtsc();
11989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
11999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return tsc;
12019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// get_tsc_freq:
12049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function returns the TSC frequency in MHz
12069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyuint32_t get_tsc_freq(
12079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    void)
12089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  static uint32_t freq[] =
12109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  { 533, 400, 200, 100 };
12119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t fuse;
12129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#if 0
12139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  fuse = (isbR32m(FUSE, 0) >> 12) & (BIT1|BIT0);
12149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#else
12159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // todo!!! Fixed 533MHz for emulation or debugging
12169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  fuse = 0;
12179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
12189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return freq[fuse];
12199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#ifndef SIM
12229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// delay_n:
12239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This is a simple delay function.
12259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// It takes "nanoseconds" as a parameter.
12269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid delay_n(
12279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t nanoseconds)
12289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // 1000 MHz clock has 1ns period --> no conversion required
12309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint64_t final_tsc = read_tsc();
12319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  final_tsc += ((get_tsc_freq() * (nanoseconds)) / 1000);
12329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  while (read_tsc() < final_tsc)
12349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    ;
12359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
12369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
12389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// delay_u:
12409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This is a simple delay function.
12429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// It takes "microseconds as a parameter.
12439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid delay_u(
12449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t microseconds)
12459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // 64 bit math is not an option, just use loops
12479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  while (microseconds--)
12489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
12499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    delay_n(1000);
12509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
12519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
12529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// delay_m:
12559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This is a simple delay function.
12579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// It takes "milliseconds" as a parameter.
12589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid delay_m(
12599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t milliseconds)
12609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // 64 bit math is not an option, just use loops
12629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  while (milliseconds--)
12639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
12649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    delay_u(1000);
12659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
12669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
12679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// delay_s:
12709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This is a simple delay function.
12729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// It takes "seconds" as a parameter.
12739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid delay_s(
12749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t seconds)
12759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // 64 bit math is not an option, just use loops
12779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  while (seconds--)
12789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
12799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    delay_m(1000);
12809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
12819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
12829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
12839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// post_code:
12859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney//
12869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will output the POST CODE to the four 7-Segment LED displays.
12879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid post_code(
12889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t major,
12899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t minor)
12909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
12919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#ifdef EMU
12929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // Update global variable for execution tracking in debug env
12939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  PostCode = ((major << 8) | minor);
12949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
12959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // send message to UART
12979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "POST: 0x%01X%02X\n", major, minor);
12989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
12999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // error check:
13009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (major == 0xEE)
13019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
13029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // todo!!! Consider updating error status and exit MRC
13039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#ifdef SIM
13049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // enable Ctrl-C handling
13059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for(;;) delay_n(100);
13069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#else
13079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    DEAD_LOOP();
13089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney#endif
13099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
13109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
13119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
13129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid training_message(
13139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t channel,
13149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t rank,
13159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint8_t byte_lane)
13169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
13179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // send message to UART
13189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);
13199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
13209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
13219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
13229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid print_timings(
13239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
13249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
13259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t algo_i;
13269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t channel_i;
13279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t rank_i;
13289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_i;
13299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t bl_divisor = (mrc_params->channel_width == x16) ? 2 : 1;
13309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
13319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "\n---------------------------");
13329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");
13339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "\n===========================");
13349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (algo_i = 0; algo_i < eMAX_ALGOS; algo_i++)
13359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
13369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (channel_i = 0; channel_i < NUM_CHANNELS; channel_i++)
13379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
13389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      if (mrc_params->channel_enables & (1 << channel_i))
13399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
13409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        for (rank_i = 0; rank_i < NUM_RANKS; rank_i++)
13419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
13429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          if (mrc_params->rank_enables & (1 << rank_i))
13439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          {
13449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            switch (algo_i)
13459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            {
13469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eRCVN:
13479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nRCVN[%02d:%02d]", channel_i, rank_i);
13489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eWDQS:
13509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nWDQS[%02d:%02d]", channel_i, rank_i);
13519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eWDQx:
13539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nWDQx[%02d:%02d]", channel_i, rank_i);
13549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eRDQS:
13569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nRDQS[%02d:%02d]", channel_i, rank_i);
13579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eVREF:
13599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nVREF[%02d:%02d]", channel_i, rank_i);
13609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eWCMD:
13629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nWCMD[%02d:%02d]", channel_i, rank_i);
13639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eWCTL:
13659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nWCTL[%02d:%02d]", channel_i, rank_i);
13669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            case eWCLK:
13689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              DPF(D_INFO, "\nWCLK[%02d:%02d]", channel_i, rank_i);
13699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            default:
13719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              break;
13729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            } // algo_i switch
13739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            for (bl_i = 0; bl_i < (NUM_BYTE_LANES / bl_divisor); bl_i++)
13749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            {
13759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              switch (algo_i)
13769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              {
13779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eRCVN:
13789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_rcvn(channel_i, rank_i, bl_i));
13799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eWDQS:
13819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_wdqs(channel_i, rank_i, bl_i));
13829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eWDQx:
13849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_wdq(channel_i, rank_i, bl_i));
13859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eRDQS:
13879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_rdqs(channel_i, rank_i, bl_i));
13889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eVREF:
13909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_vref(channel_i, bl_i));
13919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eWCMD:
13939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_wcmd(channel_i));
13949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eWCTL:
13969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_wctl(channel_i, rank_i));
13979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
13989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              case eWCLK:
13999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                DPF(D_INFO, " %03d", get_wclk(channel_i, rank_i));
14009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
14019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              default:
14029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney                break;
14039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney              } // algo_i switch
14049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney            } // bl_i loop
14059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          } // if rank_i enabled
14069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        } // rank_i loop
14079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      } // if channel_i enabled
14089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    } // channel_i loop
14099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } // algo_i loop
14109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "\n---------------------------");
14119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  DPF(D_INFO, "\n");
14129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
14139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
14149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// 32 bit LFSR with characteristic polynomial:  X^32 + X^22 +X^2 + X^1
14169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// The function takes pointer to previous 32 bit value and modifies it to next value.
14179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid lfsr32(
14189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    uint32_t *lfsr_ptr)
14199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
14209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t bit;
14219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t lfsr;
14229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t i;
14239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  lfsr = *lfsr_ptr;
14259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (i = 0; i < 32; i++)
14279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
14289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bit = 1 ^ (lfsr & BIT0);
14299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bit = bit ^ ((lfsr & BIT1) >> 1);
14309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bit = bit ^ ((lfsr & BIT2) >> 2);
14319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    bit = bit ^ ((lfsr & BIT22) >> 22);
14329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    lfsr = ((lfsr >> 1) | (bit << 31));
14349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
14359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  *lfsr_ptr = lfsr;
14379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
14389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
14399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// The purpose of this function is to ensure the SEC comes out of reset
14419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// and IA initiates the SEC enabling Memory Scrambling.
14429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid enable_scrambling(
14439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
14449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
14459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint32_t lfsr = 0;
14469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t i;
14479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (mrc_params->scrambling_enables == 0)
14499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    return;
14509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  ENTERFN();
14529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // 32 bit seed is always stored in BIOS NVM.
14549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  lfsr = mrc_params->timings.scrambler_seed;
14559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  if (mrc_params->boot_mode == bmCold)
14579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
14589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // factory value is 0 and in first boot, a clock based seed is loaded.
14599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    if (lfsr == 0)
14609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
14619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      lfsr = read_tsc() & 0x0FFFFFFF; // get seed from system clock and make sure it is not all 1's
14629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
14639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // need to replace scrambler
14649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    // get next 32bit LFSR 16 times which is the last part of the previous scrambler vector.
14659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    else
14669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
14679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (i = 0; i < 16; i++)
14689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
14699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        lfsr32(&lfsr);
14709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
14719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
14729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    mrc_params->timings.scrambler_seed = lfsr;  // save new seed.
14739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  } // if (cold_boot)
14749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // In warm boot or S3 exit, we have the previous seed.
14769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // In cold boot, we have the last 32bit LFSR which is the new seed.
14779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  lfsr32(&lfsr); // shift to next value
14789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  isbW32m(MCU, SCRMSEED, (lfsr & 0x0003FFFF));
14799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (i = 0; i < 2; i++)
14809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
14819b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    isbW32m(MCU, SCRMLO + i, (lfsr & 0xAAAAAAAA));
14829b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
14839b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14849b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  LEAVEFN();
14859b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
14869b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
14879b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14889b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will store relevant timing data
14899b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This data will be used on subsequent boots to speed up boot times
14909b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// and is required for Suspend To RAM capabilities.
14919b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid store_timings(
14929b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
14939b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
14949b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t ch, rk, bl;
14959b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  MrcTimings_t *mt = &mrc_params->timings;
14969b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
14979b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (ch = 0; ch < NUM_CHANNELS; ch++)
14989b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
14999b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (rk = 0; rk < NUM_RANKS; rk++)
15009b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
15019b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (bl = 0; bl < NUM_BYTE_LANES; bl++)
15029b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
15039b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl); // RCVN
15049b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl); // RDQS
15059b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl); // WDQS
15069b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);  // WDQ
15079b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (rk == 0)
15089b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
15099b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          mt->vref[ch][bl] = get_vref(ch, bl);  // VREF (RANK0 only)
15109b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
15119b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
15129b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      mt->wctl[ch][rk] = get_wctl(ch, rk); // WCTL
15139b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
15149b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    mt->wcmd[ch] = get_wcmd(ch); // WCMD
15159b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
15169b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15179b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  // need to save for a case of changing frequency after warm reset
15189b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  mt->ddr_speed = mrc_params->ddr_speed;
15199b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15209b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
15219b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
15229b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15239b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This function will retrieve relevant timing data
15249b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// This data will be used on subsequent boots to speed up boot times
15259b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// and is required for Suspend To RAM capabilities.
15269b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid restore_timings(
15279b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
15289b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
15299b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t ch, rk, bl;
15309b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  const MrcTimings_t *mt = &mrc_params->timings;
15319b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15329b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (ch = 0; ch < NUM_CHANNELS; ch++)
15339b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
15349b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (rk = 0; rk < NUM_RANKS; rk++)
15359b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
15369b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (bl = 0; bl < NUM_BYTE_LANES; bl++)
15379b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
15389b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]); // RCVN
15399b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]); // RDQS
15409b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]); // WDQS
15419b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);  // WDQ
15429b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (rk == 0)
15439b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
15449b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          set_vref(ch, bl, mt->vref[ch][bl]); // VREF (RANK0 only)
15459b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
15469b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
15479b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      set_wctl(ch, rk, mt->wctl[ch][rk]); // WCTL
15489b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
15499b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    set_wcmd(ch, mt->wcmd[ch]); // WCMD
15509b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
15519b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15529b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
15539b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
15549b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15559b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// Configure default settings normally set as part of read training
15569b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// Some defaults have to be set earlier as they may affect earlier
15579b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney// training steps.
15589b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinneyvoid default_timings(
15599b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    MRCParams_t *mrc_params)
15609b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney{
15619b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  uint8_t ch, rk, bl;
15629b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15639b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  for (ch = 0; ch < NUM_CHANNELS; ch++)
15649b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  {
15659b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    for (rk = 0; rk < NUM_RANKS; rk++)
15669b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    {
15679b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      for (bl = 0; bl < NUM_BYTE_LANES; bl++)
15689b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      {
15699b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        set_rdqs(ch, rk, bl, 24); // RDQS
15709b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        if (rk == 0)
15719b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        {
15729b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney          set_vref(ch, bl, 32); // VREF (RANK0 only)
15739b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney        }
15749b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney      }
15759b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney    }
15769b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  }
15779b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
15789b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney  return;
15799b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney}
15809b6bbcdbfdf5e54c6d1ed538ea8076d0858fb164Michael Kinney
1581