|Hi Kever, That's disappointing, but good to know. Can you please tell us where we can find the design guide? Thanks, Phillip | On 19/07/2019 07:52, Kever Yang wrote: > > Hi Philip and Jack, > > RK3288 does not support DDR3 write leveling. > > Rockchip have hardware design guide for RK3288 including DDR > layout requirement. > > > Thanks, > - Kever > On 2019/7/17 上午11:55, Phillip Karls wrote: >> Hi Kever, >> >> Thanks for getting back on this. Write leveling is a pretty important >> feature in DDR3. We were led to believe the RK3288 supported write >> leveling due to the following: >> Section 7.1 of version 1.0 of the RK3288 TRM states: >> /Complete, integrated, single-vendor DDR3, DDR3L, LPDDR2, LPDDR3 >> solution DFI 2.1 interface compatibility/ >> >> Section 3.6 of version 2.1 of the DFI Specification States: >> /The dfi_rdlvl_mode, dfi_wrlvl_mode and dfi_rdlvl_gate_mode signals >> are required for all DDR3 memory systems. These signals are used to >> indicate the type of data eye training, gate training and write >> leveling supported by the PHY: “No Support”, “MC Evaluation”, “PHY >> Evaluation” or “PHY Independent”. The MC must support all of the >> leveling modes to be fully DFI-compliant; however, the PHY is >> expected to support only a single mode per training operation. The >> signals required for data eye training, gate training and write >> leveling must be limited to the signals defined in this specification./ >> >> The register list in TRM also shows that the RK3288 contains the >> necessary DFI signals to implement write leveling. Does it state >> somewhere that write leveling is not supported? >> >> If it truly isn't supported, do you know what routing rules should be >> used to layout the DDR3? For example, what is the allowed skew >> between the byte lanes and the clock/address/command signals? >> >> Thanks, >> >> Phillip >> >> >> >> >> On Tue, Jul 16, 2019 at 6:53 PM Kever Yang <kever.yang@xxxxxxxxxxxxxx >> <mailto:kever.yang@xxxxxxxxxxxxxx>> wrote: >> >> Hi Jack, >> >> On 2019/7/17 上午2:02, Jack Mitchell wrote: >> > I've got an issue where I'm trying to implement write levelling >> for DDR3 >> > on an RK3288. From what I can tell by reading the TRM, DDR3 write >> > leveling is supported. >> >> >> Could you share which document do you find information that RK3288 >> support DDR3 write >> >> leveling? From what I know, RK3288 does not support this feature. >> >> >> Thanks, >> >> - Kever >> >> > >> > For some reason I can’t seem to get the write leveling routine >> to run >> > and compensate for the individual byte lane skews. According to the >> > DDR_PCTL_DFITRSTAT0 register, the PHY is configured for PHY >> Independent >> > mode (reading 0x30303). >> > >> > According to the DFI 2.1 spec: >> > >> > "In PHY Independent mode, the PHY is responsible for executing >> data eye >> > training, gate training or write leveling independent of the Memory >> > Controller. In this mode, the associated training interface is >> not used >> > other than the mode signal to the MC. >> > >> > The Memory Controller should be capable of generating the >> required MRS >> > commands to enter or exit the test modes of the memory devices. >> These >> > operations are not automatically generated. >> > >> > All training sequences, regardless of mode, are expected to be >> executed >> > after memory initialization. For PHY Independent mode, the update >> > interface may be used to suspend memory commands while the training >> > sequences are executed." >> > >> > The current driver (sdram_rk3288.c) makes no reference to DDR3 >> write >> > leveling. Here is what I’ve tried without luck: >> > >> > >> > >> > 1. Configure the DRAMs for write leveling using the appropriate MRS >> > commands. >> > >> > >> > // Issue a mode register set (MRS) command to MR1 to enable write >> > leveling (MR1[7] = '1') and disable the output of the SDRAM >> (MR1[12] = >> > '1'). This command is issued simultaneously to all ranks. >> > >> > send_command_op_corrected(pctl, 3, MRS_CMD, 1, >> > (sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7) | (1 << 12))); >> > >> > >> > >> > // Enable the output of the rank being write-leveled. This is >> done by >> > issuing a MRS command to the selected rank with bit MR1[12] set >> to '0'. >> > MR1[7] is kept set when issuing this command to make sure write >> leveling >> > remains enabled for the rank. Wait tMOD to satisfy SDRAM MRS to >> other >> > commands timing. >> > >> > >> > send_command_op_corrected(pctl, 1, MRS_CMD, 1, >> > ((sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7)) & 0x0fff)); >> > >> > >> > >> > 2. Configure the DRAMs for write leveling using the appropriate MRS >> > commands and set the dfi_wrlvl_en bit in register >> DDR_PCTL_DFITRWRLVLEN: >> > >> > >> > // Issue a mode register set (MRS) command to MR1 to enable write >> > leveling (MR1[7] = '1') and disable the output of the SDRAM >> (MR1[12] = >> > '1'). This command is issued simultaneously to all ranks. >> > >> > >> > send_command_op_corrected(pctl, 3, MRS_CMD, 1, >> > (sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7) | (1 << 12))); >> > >> > >> > >> > // Enable the output of the rank being write-leveled. This is >> done by >> > issuing a MRS command to the selected rank with bit MR1[12] set >> to '0'. >> > MR1[7] is kept set when issuing this command to make sure write >> leveling >> > remains enabled for the rank. Wait tMOD to satisfy SDRAM MRS to >> other >> > commands timing. >> > >> > >> > send_command_op_corrected(pctl, 1, MRS_CMD, 1, >> > ((sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7)) & 0x0fff)); >> > >> > >> > >> > // Set dfitrwrlvlen high >> > >> > writel(0x1ff, &pctl->dfitrwrlvlen); >> > >> > >> > >> > 3. Configure the DRAMs for write leveling using the appropriate MRS >> > commands, set the dfi_wrlvl_en bit in register >> DDR_PCTL_DFITRWRLVLEN, >> > and rerun memory_init(). >> > >> > >> > // Issue a mode register set (MRS) command to MR1 to enable write >> > leveling (MR1[7] = '1') and disable the output of the SDRAM >> (MR1[12] = >> > '1'). This command is issued simultaneously to all ranks. >> > >> > >> > send_command_op_corrected(pctl, 3, MRS_CMD, 1, >> > (sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7) | (1 << 12))); >> > >> > >> > >> > // Enable the output of the rank being write-leveled. This is >> done by >> > issuing a MRS command to the selected rank with bit MR1[12] set >> to '0'. >> > MR1[7] is kept set when issuing this command to make sure write >> leveling >> > remains enabled for the rank. Wait tMOD to satisfy SDRAM MRS to >> other >> > commands timing. >> > >> > >> > send_command_op_corrected(pctl, 1, MRS_CMD, 1, >> > ((sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7)) & 0x0fff)); >> > >> > >> > >> > // Set dfitrwrlvlen high >> > >> > writel(0x1ff, &pctl->dfitrwrlvlen); >> > >> > >> > >> > memory_init(publ, sdram_params->base.dramtype); >> > >> > >> > >> > 4. Manually control the dfi_wrlvl_en, dfi_wrlvl_strobe, >> dfi_wrlvl_load, >> > and dfi_wrlvl_delay bits while monitoring the dfi_wrlvl_resp >> bits as >> > described in Figure 50 of version 2.1 of the DDR PHY Interface >> (DFI) >> > Specification: >> > >> > >> > // Issue a mode register set (MRS) command to MR1 to enable write >> > leveling (MR1[7] = '1') and disable the output of the SDRAM >> (MR1[12] = >> > '1'). This command is issued simultaneously to all ranks. >> > >> > >> > send_command_op_corrected(pctl, 3, MRS_CMD, 1, >> > (sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7) | (1 << 12))); >> > >> > >> > >> > // Enable the output of the rank being write-leveled. This is >> done by >> > issuing a MRS command to the selected rank with bit MR1[12] set >> to '0'. >> > MR1[7] is kept set when issuing this command to make sure write >> leveling >> > remains enabled for the rank. Wait tMOD to satisfy SDRAM MRS to >> other >> > commands timing. >> > >> > >> > send_command_op_corrected(pctl, 1, MRS_CMD, 1, >> > ((sdram_params->phy_timing.mr <http://phy_timing.mr>[1] | (1 << >> 7)) & 0x0fff)); >> > >> > >> > >> > // Set dfitrwrlvlen high >> > >> > writel(0x1ff, &pctl->dfitrwrlvlen); >> > >> > >> > >> > int index0; >> > >> > >> > >> > for (index0 = 0; index0 < 10000; index0++) >> > >> > { >> > >> > // Set the delay >> > >> > writel(index0, &pctl->dfitrwrlvldelay0); >> > >> > udelay(1); >> > >> > >> > >> > // Set dfi_wrlvl_load >> > >> > writel(0x80001ff0, &pctl->dfitrcmd); >> > >> > udelay(1); >> > >> > >> > >> > // Set dfi_wrlvl_strobe >> > >> > writel(0x80001ff1, &pctl->dfitrcmd); >> > >> > udelay(1); >> > >> > >> > >> > // Read dfi_wrlvl_resp0 >> > >> > if (readl(&pctl->dfitrwrlvlresp0) & 0x1) >> > >> > { >> > >> > break; >> > >> > } >> > >> > } >> > >> > >> > >> > >> > >> > Here is the send_command_op_corrected function definition. >> > >> > >> > static inline void send_command_op_corrected(struct rk3288_ddr_pctl >> > *pctl, u32 rank, u32 cmd, u32 ma, u32 op) >> > >> > { >> > >> > send_command(pctl, rank, cmd, (ma & 0x3) << 17 | (op & >> 0x1fff) << 4); >> > >> > } >> > >> > >> > >> > None of these generate any activity on the DDR bus, besides the MRS >> > commands. >> > >> > Does anyone know what I need to do to trigger a write leveling >> routine? >> > It seems like after the DRAMs are configured, I would need to set >> > something on the RK3288 to trigger it. >> > >> > The TRM is pretty sparse when it comes to discussing write >> leveling, >> > does anyone know if the PHY actually supports this? >> > >> > Thanks! >> > >> > _______________________________________________ >> > Linux-rockchip mailing list >> > Linux-rockchip@xxxxxxxxxxxxxxxxxxx >> <mailto:Linux-rockchip@xxxxxxxxxxxxxxxxxxx> >> > http://lists.infradead.org/mailman/listinfo/linux-rockchip >> >> _______________________________________________ Linux-rockchip mailing list Linux-rockchip@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/linux-rockchip