<p>Philipp Hug has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/28604">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">soc/sifive/fu540: Initialize SDRAM<br><br>Based on SiFive bootloader code<br><br>Change-Id: I71043ce9e458e25e64da28d53cd36b02d2e22acc<br>Signed-off-by: Philipp Hug <philipp@hug.cx><br>---<br>M src/mainboard/sifive/hifive-unleashed/romstage.c<br>M src/soc/sifive/fu540/include/soc/addressmap.h<br>M src/soc/sifive/fu540/sdram.c<br>A src/soc/sifive/fu540/ux00ddr.h<br>4 files changed, 242 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/04/28604/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/mainboard/sifive/hifive-unleashed/romstage.c b/src/mainboard/sifive/hifive-unleashed/romstage.c</span><br><span>index 9729f86..df4cf89 100644</span><br><span>--- a/src/mainboard/sifive/hifive-unleashed/romstage.c</span><br><span>+++ b/src/mainboard/sifive/hifive-unleashed/romstage.c</span><br><span>@@ -40,5 +40,7 @@</span><br><span>                 uart_init(CONFIG_UART_FOR_CONSOLE);</span><br><span>  #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    sdram_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      run_ramstage();</span><br><span> }</span><br><span>diff --git a/src/soc/sifive/fu540/include/soc/addressmap.h b/src/soc/sifive/fu540/include/soc/addressmap.h</span><br><span>index 0de1423..21709b5 100644</span><br><span>--- a/src/soc/sifive/fu540/include/soc/addressmap.h</span><br><span>+++ b/src/soc/sifive/fu540/include/soc/addressmap.h</span><br><span>@@ -29,6 +29,7 @@</span><br><span> #define FU540_ETHMAC               0x10090000</span><br><span> #define FU540_ETHMGMT             0x100a0000</span><br><span> #define FU540_DDRCTRL             0x100b0000</span><br><span style="color: hsl(120, 100%, 40%);">+#define FU540_DDRBUSBLOCKER 0x100b8000</span><br><span> #define FU540_DDRMGMT             0x100c0000</span><br><span> #define FU540_QSPI0FLASH  0x20000000</span><br><span> #define FU540_QSPI1FLASH  0x30000000</span><br><span>diff --git a/src/soc/sifive/fu540/sdram.c b/src/soc/sifive/fu540/sdram.c</span><br><span>index 1ad36da..6418b0d 100644</span><br><span>--- a/src/soc/sifive/fu540/sdram.c</span><br><span>+++ b/src/soc/sifive/fu540/sdram.c</span><br><span>@@ -14,10 +14,46 @@</span><br><span>  */</span><br><span> </span><br><span> #include <soc/sdram.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <soc/addressmap.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "regconfig-phy.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "regconfig-ctl.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ux00ddr.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DENALI_PHY_DATA ddr_phy_settings</span><br><span style="color: hsl(120, 100%, 40%);">+#define DENALI_CTL_DATA ddr_ctl_settings</span><br><span style="color: hsl(120, 100%, 40%);">+#include "ddrregs.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DDR_SIZE  (8UL * 1024UL * 1024UL * 1024UL)</span><br><span style="color: hsl(120, 100%, 40%);">+#define DDRCTLPLL_F 55</span><br><span style="color: hsl(120, 100%, 40%);">+#define DDRCTLPLL_Q 2</span><br><span> </span><br><span> void sdram_init(void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  // TODO: implement</span><br><span style="color: hsl(120, 100%, 40%);">+    ux00ddr_writeregmap(FU540_DDRCTRL, ddr_ctl_settings, ddr_phy_settings);</span><br><span style="color: hsl(120, 100%, 40%);">+       ux00ddr_disableaxireadinterleave(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ux00ddr_disableoptimalrmodw(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ux00ddr_enablewriteleveling(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+   ux00ddr_enablereadleveling(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+    ux00ddr_enablereadlevelinggate(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ux00ddr_getdramclass(FU540_DDRCTRL) == DRAM_CLASS_DDR4)</span><br><span style="color: hsl(120, 100%, 40%);">+           ux00ddr_enablevreftraining(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  //mask off interrupts for leveling completion</span><br><span style="color: hsl(120, 100%, 40%);">+ ux00ddr_mask_leveling_completed_interrupt(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ux00ddr_mask_mc_init_complete_interrupt(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+       ux00ddr_mask_outofrange_interrupts(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+    ux00ddr_setuprangeprotection(FU540_DDRCTRL, DDR_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+        ux00ddr_mask_port_command_error_interrupt(FU540_DDRCTRL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint64_t ddr_size = DDR_SIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+   const uint64_t ddr_end = FU540_DRAM + ddr_size;</span><br><span style="color: hsl(120, 100%, 40%);">+       ux00ddr_start(FU540_DDRCTRL, FU540_DDRBUSBLOCKER, ddr_end);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ux00ddr_phy_fixup(FU540_DDRCTRL);</span><br><span> }</span><br><span> </span><br><span> size_t sdram_size_mb(void)</span><br><span>diff --git a/src/soc/sifive/fu540/ux00ddr.h b/src/soc/sifive/fu540/ux00ddr.h</span><br><span>new file mode 100644</span><br><span>index 0000000..fc5e110</span><br><span>--- /dev/null</span><br><span>+++ b/src/soc/sifive/fu540/ux00ddr.h</span><br><span>@@ -0,0 +1,202 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Copyright (c) 2018 SiFive, Inc */</span><br><span style="color: hsl(120, 100%, 40%);">+/* SPDX-License-Identifier: Apache-2.0 */</span><br><span style="color: hsl(120, 100%, 40%);">+/* SPDX-License-Identifier: GPL-2.0-or-later */</span><br><span style="color: hsl(120, 100%, 40%);">+/* See the file LICENSE for further information */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef _SIFIVE_UX00DDR_H</span><br><span style="color: hsl(120, 100%, 40%);">+#define _SIFIVE_UX00DDR_H</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __ASSEMBLER__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stddef.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DRAM_CLASS_OFFSET                   8</span><br><span style="color: hsl(120, 100%, 40%);">+#define DRAM_CLASS_DDR4                     0xA</span><br><span style="color: hsl(120, 100%, 40%);">+#define OPTIMAL_RMODW_EN_OFFSET             0</span><br><span style="color: hsl(120, 100%, 40%);">+#define DISABLE_RD_INTERLEAVE_OFFSET        16</span><br><span style="color: hsl(120, 100%, 40%);">+#define OUT_OF_RANGE_OFFSET                 1</span><br><span style="color: hsl(120, 100%, 40%);">+#define MULTIPLE_OUT_OF_RANGE_OFFSET        2</span><br><span style="color: hsl(120, 100%, 40%);">+#define PORT_COMMAND_CHANNEL_ERROR_OFFSET   7</span><br><span style="color: hsl(120, 100%, 40%);">+#define MC_INIT_COMPLETE_OFFSET             8</span><br><span style="color: hsl(120, 100%, 40%);">+#define LEVELING_OPERATION_COMPLETED_OFFSET 22</span><br><span style="color: hsl(120, 100%, 40%);">+#define DFI_PHY_WRLELV_MODE_OFFSET          24</span><br><span style="color: hsl(120, 100%, 40%);">+#define DFI_PHY_RDLVL_MODE_OFFSET           24</span><br><span style="color: hsl(120, 100%, 40%);">+#define DFI_PHY_RDLVL_GATE_MODE_OFFSET      0</span><br><span style="color: hsl(120, 100%, 40%);">+#define VREF_EN_OFFSET                      24</span><br><span style="color: hsl(120, 100%, 40%);">+#define PORT_ADDR_PROTECTION_EN_OFFSET      0</span><br><span style="color: hsl(120, 100%, 40%);">+#define AXI0_ADDRESS_RANGE_ENABLE           8</span><br><span style="color: hsl(120, 100%, 40%);">+#define AXI0_RANGE_PROT_BITS_0_OFFSET       24</span><br><span style="color: hsl(120, 100%, 40%);">+#define RDLVL_EN_OFFSET                     16</span><br><span style="color: hsl(120, 100%, 40%);">+#define RDLVL_GATE_EN_OFFSET                24</span><br><span style="color: hsl(120, 100%, 40%);">+#define WRLVL_EN_OFFSET                     0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define PHY_RX_CAL_DQ0_0_OFFSET             0</span><br><span style="color: hsl(120, 100%, 40%);">+#define PHY_RX_CAL_DQ1_0_OFFSET             16</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void phy_reset(volatile uint32_t *ddrphyreg, const uint32_t *physettings) {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i=1152;i<=1214;i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t physet = physettings[i];</span><br><span style="color: hsl(120, 100%, 40%);">+    /*if (physet!=0)*/ ddrphyreg[i] = physet;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i=0;i<=1151;i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t physet = physettings[i];</span><br><span style="color: hsl(120, 100%, 40%);">+    /*if (physet!=0)*/ ddrphyreg[i] = physet;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_writeregmap(size_t ahbregaddr, const uint32_t *ctlsettings, const uint32_t *physettings) {</span><br><span style="color: hsl(120, 100%, 40%);">+  volatile uint32_t *ddrctlreg = (volatile uint32_t *) ahbregaddr;</span><br><span style="color: hsl(120, 100%, 40%);">+  volatile uint32_t *ddrphyreg = ((volatile uint32_t *) ahbregaddr) + (0x2000 / sizeof(uint32_t));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i=0;i<=264;i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t ctlset = ctlsettings[i];</span><br><span style="color: hsl(120, 100%, 40%);">+    /*if (ctlset!=0)*/ ddrctlreg[i] = ctlset;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  phy_reset(ddrphyreg, physettings);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_start(size_t ahbregaddr, size_t filteraddr, size_t ddrend) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // START register at ddrctl register base offset 0</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t regdata = _REG32(0<<2, ahbregaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+  regdata |= 0x1;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(0<<2, ahbregaddr) = regdata;</span><br><span style="color: hsl(120, 100%, 40%);">+  // WAIT for initialization complete : bit 8 of INT_STATUS (DENALI_CTL_132) 0x210</span><br><span style="color: hsl(120, 100%, 40%);">+  while ((_REG32(132<<2, ahbregaddr) & (1<<MC_INIT_COMPLETE_OFFSET)) == 0) {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  // Disable the BusBlocker in front of the controller AXI slave ports</span><br><span style="color: hsl(120, 100%, 40%);">+  volatile uint64_t *filterreg = (volatile uint64_t *)filteraddr;</span><br><span style="color: hsl(120, 100%, 40%);">+  filterreg[0] = 0x0f00000000000000UL | (ddrend >> 2);</span><br><span style="color: hsl(120, 100%, 40%);">+  //                ^^ RWX + TOR</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_mask_mc_init_complete_interrupt(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // Mask off Bit 8 of Interrupt Status</span><br><span style="color: hsl(120, 100%, 40%);">+  // Bit [8] The MC initialization has been completed</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(136<<2, ahbregaddr) |= (1<<MC_INIT_COMPLETE_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_mask_outofrange_interrupts(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // Mask off Bit 8, Bit 2 and Bit 1 of Interrupt Status</span><br><span style="color: hsl(120, 100%, 40%);">+  // Bit [2] Multiple accesses outside the defined PHYSICAL memory space have occured</span><br><span style="color: hsl(120, 100%, 40%);">+  // Bit [1] A memory access outside the defined PHYSICAL memory space has occured</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(136<<2, ahbregaddr) |= ((1<<OUT_OF_RANGE_OFFSET) | (1<<MULTIPLE_OUT_OF_RANGE_OFFSET));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_mask_port_command_error_interrupt(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // Mask off Bit 7 of Interrupt Status</span><br><span style="color: hsl(120, 100%, 40%);">+  // Bit [7] An error occured on the port command channel</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(136<<2, ahbregaddr) |= (1<<PORT_COMMAND_CHANNEL_ERROR_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_mask_leveling_completed_interrupt(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // Mask off Bit 22 of Interrupt Status</span><br><span style="color: hsl(120, 100%, 40%);">+  // Bit [22] The leveling operation has completed</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(136<<2, ahbregaddr) |= (1<<LEVELING_OPERATION_COMPLETED_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_setuprangeprotection(size_t ahbregaddr, size_t end_addr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(209<<2, ahbregaddr) = 0x0;</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t end_addr_16Kblocks = ((end_addr >> 14) & 0x7FFFFF)-1;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(210<<2, ahbregaddr) = ((uint32_t) end_addr_16Kblocks);</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(212<<2, ahbregaddr) = 0x0;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(214<<2, ahbregaddr) = 0x0;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(216<<2, ahbregaddr) = 0x0;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(224<<2, ahbregaddr) |= (0x3 << AXI0_RANGE_PROT_BITS_0_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(225<<2, ahbregaddr) = 0xFFFFFFFF;</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(208<<2, ahbregaddr) |= (1 << AXI0_ADDRESS_RANGE_ENABLE);</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(208<<2, ahbregaddr) |= (1 << PORT_ADDR_PROTECTION_EN_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_disableaxireadinterleave(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(120<<2, ahbregaddr) |= (1<<DISABLE_RD_INTERLEAVE_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_disableoptimalrmodw(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(21<<2, ahbregaddr) &= (~(1<<OPTIMAL_RMODW_EN_OFFSET));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_enablewriteleveling(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(170<<2, ahbregaddr) |= ((1<<WRLVL_EN_OFFSET) | (1<<DFI_PHY_WRLELV_MODE_OFFSET));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_enablereadleveling(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(181<<2, ahbregaddr) |= (1<<DFI_PHY_RDLVL_MODE_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(260<<2, ahbregaddr) |= (1<<RDLVL_EN_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_enablereadlevelinggate(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(260<<2, ahbregaddr) |= (1<<RDLVL_GATE_EN_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(182<<2, ahbregaddr) |= (1<<DFI_PHY_RDLVL_GATE_MODE_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void ux00ddr_enablevreftraining(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  _REG32(184<<2, ahbregaddr) |= (1<<VREF_EN_OFFSET);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint32_t ux00ddr_getdramclass(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  return ((_REG32(0, ahbregaddr) >> DRAM_CLASS_OFFSET) & 0xF);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline uint64_t ux00ddr_phy_fixup(size_t ahbregaddr) {</span><br><span style="color: hsl(120, 100%, 40%);">+  // return bitmask of failed lanes</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t ddrphyreg = ahbregaddr + 0x2000;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  uint64_t fails=0;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t slicebase = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t dq = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  // check errata condition</span><br><span style="color: hsl(120, 100%, 40%);">+  for (uint32_t slice = 0; slice < 8; slice++) {</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t regbase = slicebase + 34;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (uint32_t reg = 0 ; reg < 4; reg++) {</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t updownreg = _REG32((regbase+reg)<<2, ddrphyreg);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (uint32_t bit = 0; bit < 2; bit++) {</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t phy_rx_cal_dqn_0_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (bit==0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          phy_rx_cal_dqn_0_offset = PHY_RX_CAL_DQ0_0_OFFSET;</span><br><span style="color: hsl(120, 100%, 40%);">+        }else{</span><br><span style="color: hsl(120, 100%, 40%);">+          phy_rx_cal_dqn_0_offset = PHY_RX_CAL_DQ1_0_OFFSET;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t down = (updownreg >> phy_rx_cal_dqn_0_offset) & 0x3F;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t up = (updownreg >> (phy_rx_cal_dqn_0_offset+6)) & 0x3F;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t failc0 = ((down == 0) && (up == 0x3F));</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t failc1 = ((up == 0) && (down == 0x3F));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        // print error message on failure</span><br><span style="color: hsl(120, 100%, 40%);">+        if (failc0 || failc1) {</span><br><span style="color: hsl(120, 100%, 40%);">+          //if (fails==0) uart_puts((void*) UART0_CTRL_ADDR, "DDR error in fixing up \n");</span><br><span style="color: hsl(120, 100%, 40%);">+          fails |= (1<<dq);</span><br><span style="color: hsl(120, 100%, 40%);">+          char slicelsc = '0';</span><br><span style="color: hsl(120, 100%, 40%);">+          char slicemsc = '0';</span><br><span style="color: hsl(120, 100%, 40%);">+          slicelsc += (dq % 10);</span><br><span style="color: hsl(120, 100%, 40%);">+          slicemsc += (dq / 10);</span><br><span style="color: hsl(120, 100%, 40%);">+          //uart_puts((void*) UART0_CTRL_ADDR, "S ");</span><br><span style="color: hsl(120, 100%, 40%);">+          //uart_puts((void*) UART0_CTRL_ADDR, &slicemsc);</span><br><span style="color: hsl(120, 100%, 40%);">+          //uart_puts((void*) UART0_CTRL_ADDR, &slicelsc);</span><br><span style="color: hsl(120, 100%, 40%);">+          //if (failc0) uart_puts((void*) UART0_CTRL_ADDR, "U");</span><br><span style="color: hsl(120, 100%, 40%);">+          //else uart_puts((void*) UART0_CTRL_ADDR, "D");</span><br><span style="color: hsl(120, 100%, 40%);">+          //uart_puts((void*) UART0_CTRL_ADDR, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+        dq++;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+    slicebase+=128;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  return (0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/28604">change 28604</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/28604"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I71043ce9e458e25e64da28d53cd36b02d2e22acc </div>
<div style="display:none"> Gerrit-Change-Number: 28604 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Philipp Hug <philipp@hug.cx> </div>