uboot/arch/arm/mach-sunxi/dram_timings/h6_lpddr3.c
<<
>>
Prefs
   1/*
   2 * sun50i H6 LPDDR3 timings
   3 *
   4 * (C) Copyright 2017      Icenowy Zheng <icenowy@aosc.io>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <asm/arch/dram.h>
  11#include <asm/arch/cpu.h>
  12
  13static u32 mr_lpddr3[12] = {
  14        0x00000000, 0x00000043, 0x0000001a, 0x00000001,
  15        0x00000000, 0x00000000, 0x00000048, 0x00000000,
  16        0x00000000, 0x00000000, 0x00000000, 0x00000003,
  17};
  18
  19/* TODO: flexible timing */
  20void mctl_set_timing_params(struct dram_para *para)
  21{
  22        struct sunxi_mctl_ctl_reg * const mctl_ctl =
  23                        (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
  24        struct sunxi_mctl_phy_reg * const mctl_phy =
  25                        (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
  26        int i;
  27
  28        u8 tccd         = 2;
  29        u8 tfaw         = max(ns_to_t(50), 4);
  30        u8 trrd         = max(ns_to_t(10), 2);
  31        u8 trcd         = max(ns_to_t(24), 2);
  32        u8 trc          = ns_to_t(70);
  33        u8 txp          = max(ns_to_t(8), 2);
  34        u8 twtr         = max(ns_to_t(8), 2);
  35        u8 trtp         = max(ns_to_t(8), 2);
  36        u8 twr          = max(ns_to_t(15), 2);
  37        u8 trp          = ns_to_t(18);
  38        u8 tras         = ns_to_t(42);
  39        u8 twtr_sa      = ns_to_t(5);
  40        u8 tcksrea      = ns_to_t(11);
  41        u16 trefi       = ns_to_t(3900) / 32;
  42        u16 trfc        = ns_to_t(210);
  43        u16 txsr        = ns_to_t(220);
  44
  45        if (CONFIG_DRAM_CLK % 400 == 0) {
  46                /* Round up these parameters */
  47                twtr_sa++;
  48                tcksrea++;
  49        }
  50
  51        u8 tmrw         = 5;
  52        u8 tmrd         = 5;
  53        u8 tmod         = 12;
  54        u8 tcke         = 3;
  55        u8 tcksrx       = 5;
  56        u8 tcksre       = 5;
  57        u8 tckesr       = 5;
  58        u8 trasmax      = CONFIG_DRAM_CLK / 60;
  59        u8 txs          = 4;
  60        u8 txsdll       = 4;
  61        u8 txsabort     = 4;
  62        u8 txsfast      = 4;
  63
  64        u8 tcl          = 5; /* CL 10 */
  65        u8 tcwl         = 3; /* CWL 6 */
  66        u8 t_rdata_en   = twtr_sa + 8;
  67
  68        u32 tdinit0     = (200 * CONFIG_DRAM_CLK) + 1;          /* 200us */
  69        u32 tdinit1     = (100 * CONFIG_DRAM_CLK) / 1000 + 1;   /* 100ns */
  70        u32 tdinit2     = (11 * CONFIG_DRAM_CLK) + 1;           /* 11us */
  71        u32 tdinit3     = (1 * CONFIG_DRAM_CLK) + 1;            /* 1us */
  72
  73        u8 twtp         = tcwl + 4 + twr + 1;
  74        /*
  75         * The code below for twr2rd and trd2wr follows the IP core's
  76         * document from ZynqMP and i.MX7. The BSP has both number
  77         * substracted by 2.
  78         */
  79        u8 twr2rd       = tcwl + 4 + 1 + twtr;
  80        u8 trd2wr       = tcl + 4 + (tcksrea >> 1) - tcwl + 1;
  81
  82        /* set mode registers */
  83        for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
  84                writel(mr_lpddr3[i], &mctl_phy->mr[i]);
  85
  86        /* set DRAM timing */
  87        writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
  88               &mctl_ctl->dramtmg[0]);
  89        writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
  90        writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
  91               &mctl_ctl->dramtmg[2]);
  92        writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
  93        writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
  94               &mctl_ctl->dramtmg[4]);
  95        writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
  96               &mctl_ctl->dramtmg[5]);
  97        /* Value suggested by ZynqMP manual and used by libdram */
  98        writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
  99        writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
 100               &mctl_ctl->dramtmg[8]);
 101        writel(txsr, &mctl_ctl->dramtmg[14]);
 102
 103        clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
 104        writel(0, &mctl_ctl->dfimisc);
 105        clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
 106
 107        /*
 108         * Set timing registers of the PHY.
 109         * Note: the PHY is clocked 2x from the DRAM frequency.
 110         */
 111        writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
 112               &mctl_phy->dtpr[0]);
 113        writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
 114        writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
 115        writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
 116               &mctl_phy->dtpr[3]);
 117        writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
 118        writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
 119        writel(0x0505, &mctl_phy->dtpr[6]);
 120
 121        /* Configure DFI timing */
 122        writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
 123               &mctl_ctl->dfitmg0);
 124        writel(0x040201, &mctl_ctl->dfitmg1);
 125
 126        /* Configure PHY timing */
 127        writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
 128        writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
 129
 130        /* set refresh timing */
 131        writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
 132}
 133