[U-Boot] [PATCH 13/13] rockchip: rk3066: add sdram init code for tpl

Simon Glass sjg at chromium.org
Tue Jun 6 21:10:31 UTC 2017


Hi Pawel,

On 6 June 2017 at 12:53, Paweł Jarosz <paweljarosz3691 at gmail.com> wrote:
> Add sdram initialisation code which will be ussed by tpl first boot stage.
> We need to implement sdram initialisation in tpl due to size issues on rk3066
> platform.
>
> Signed-off-by: Paweł Jarosz <paweljarosz3691 at gmail.com>
> ---
>  arch/arm/include/asm/arch-rockchip/ddr_rk3188.h |   5 +
>  arch/arm/mach-rockchip/rk3066/sdram_init.c      | 995 ++++++++++++++++++++++++
>  2 files changed, 1000 insertions(+)
>  create mode 100644 arch/arm/mach-rockchip/rk3066/sdram_init.c
>
> diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> index 3d7929f..74d11c6 100644
> --- a/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> +++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3188.h
> @@ -10,6 +10,11 @@
>  #include <asm/arch/ddr_rk3288.h>
>
>  /*
> + * RK3066 Tpl memory init.
> + */
> +void sdram_initialise(void);
> +
> +/*
>   * RK3188 Memory scheduler register map.
>   */
>  struct rk3188_msch {
> diff --git a/arch/arm/mach-rockchip/rk3066/sdram_init.c b/arch/arm/mach-rockchip/rk3066/sdram_init.c
> new file mode 100644
> index 0000000..e7e506a
> --- /dev/null
> +++ b/arch/arm/mach-rockchip/rk3066/sdram_init.c
> @@ -0,0 +1,995 @@
> +/*
> + * (C) Copyright 2015 Google, Inc
> + * Copyright 2014 Rockchip Inc.
> + *
> + * SPDX-License-Identifier:     GPL-2.0
> + *
> + * Adapted from the very similar rk3288 ddr init.
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <errno.h>
> +#include <ram.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/cru_rk3066.h>
> +#include <asm/arch/ddr_rk3188.h>
> +#include <asm/arch/grf_rk3066.h>
> +#include <asm/arch/pmu_rk3188.h>
> +#include <asm/arch/sdram.h>
> +#include <linux/err.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct pll_div {
> +       u32 nr;
> +       u32 nf;
> +       u32 no;
> +};
> +
> +enum {
> +       VCO_MAX_HZ      = 1416U * 1000000,
> +       VCO_MIN_HZ      = 300 * 1000000,
> +       OUTPUT_MAX_HZ   = 1416U * 1000000,
> +       OUTPUT_MIN_HZ   = 30 * 1000000,
> +       FREF_MAX_HZ     = 1416U * 1000000,
> +       FREF_MIN_HZ     = 30 * 1000,
> +};
> +
> +enum {
> +       /* PLL CON0 */
> +       PLL_OD_MASK             = 0x0f,
> +
> +       /* PLL CON1 */
> +       PLL_NF_MASK             = 0x1fff,
> +
> +       /* PLL CON2 */
> +       PLL_BWADJ_MASK          = 0x0fff,
> +
> +       /* PLL CON3 */
> +       PLL_RESET_SHIFT         = 5,
> +
> +       /* GRF_SOC_STATUS0 */
> +       SOCSTS_DPLL_LOCK        = 1 << 4,
> +       SOCSTS_APLL_LOCK        = 1 << 5,
> +       SOCSTS_CPLL_LOCK        = 1 << 6,
> +       SOCSTS_GPLL_LOCK        = 1 << 7,
> +};
> +
> +#define CRU_BASE       0x20000000
> +#define GRF_BASE       0x20008000
> +#define PMU_BASE       0x20004000
> +#define PCTL_BASE      0x20020000
> +#define PUBL_BASE      0x20040000
> +#define NOC_BASE       0x10128000

I'm assume we cannot use the DT / syscon because of space constraints?

> +
> +#define RK3066_PCTL_TIMING_DEFAULT { \

Do you need this? Why not just put these values below and avoid the indirection?

> +       .togcnt1u = 0x12c, \
> +       .tinit = 0xc8, \
> +       .trsth = 0x1f4, \
> +       .togcnt100n = 0x1e, \
> +       .trefi = 0x4e, \
> +       .tmrd = 0x4, \
> +       .trfc = 0x69, \
> +       .trp = 0x6, \
> +       .trtw = 0x3, \
> +       .tal = 0x0, \
> +       .tcl = 0x6, \
> +       .tcwl = 0x5, \
> +       .tras = 0xc, \
> +       .trc = 0x10, \
> +       .trcd = 0x6, \
> +       .trrd = 0x4, \
> +       .trtp = 0x4, \
> +       .twr = 0x5, \
> +       .twtr = 0x4, \
> +       .texsr = 0x200, \
> +       .txp = 0x3, \
> +       .txpdll = 0xa, \
> +       .tzqcs = 0x40, \
> +       .tzqcsi = 0x0, \
> +       .tdqs = 0x1, \
> +       .tcksre = 0x5, \
> +       .tcksrx = 0x5, \
> +       .tcke = 0x3, \
> +       .tmod = 0xc, \
> +       .trstl = 0x1e, \
> +       .tzqcl = 0x100, \
> +       .tmrr = 0x0, \
> +       .tckesr = 0x4, \
> +       .tdpd = 0x0 \
> +}
> +
> +#define RK3066_PHY_TIMING_DEFAULT { \
> +       .dtpr0 = 0x208c6690, \
> +       .dtpr1 = 0x690878, \
> +       .dtpr2 = 0x10022a00, \
> +       .mr = { 0x220, 0x40, 0x0,  0x0 } \
> +}
> +
> +#define RK3066_SDRAM_PARAMS_DEFAULT { \
> +       .noc_timing = 0x24716310, \
> +       .noc_activate = 0, \
> +       .ddrconfig = 2, \
> +       .ddr_freq = 300000000, \
> +       .dramtype = 3, \
> +       .stride = 9, \
> +       .odt = 0 \
> +}
> +
> +#ifndef RK3066_PCTL_TIMING
> +#define RK3066_PCTL_TIMING     RK3066_PCTL_TIMING_DEFAULT
> +#endif
> +
> +#ifndef RK3066_PHY_TIMING
> +#define RK3066_PHY_TIMING      RK3066_PHY_TIMING_DEFAULT
> +#endif
> +
> +#ifndef RK3066_SDRAM_PARAMS
> +#define RK3066_SDRAM_PARAMS    RK3066_SDRAM_PARAMS_DEFAULT
> +#endif
> +
> +struct chan_info {
> +       struct rk3288_ddr_pctl *pctl;
> +       struct rk3288_ddr_publ *publ;
> +       struct rk3188_msch *msch;
> +};
> +
> +struct dram_info {
> +       struct chan_info chan[1];
> +       struct ram_info info;
> +       struct rk3066_cru *cru;
> +       struct rk3066_grf *grf;
> +       struct rk3188_pmu *pmu;
> +};
> +
> +struct rk3066_sdram_params {
> +       struct rk3288_sdram_channel ch[2];
> +       struct rk3288_sdram_pctl_timing pctl_timing;
> +       struct rk3288_sdram_phy_timing phy_timing;
> +       struct rk3288_base_params base;
> +       int num_channels;
> +       struct regmap *map;
> +};
> +
> +const int ddrconf_table[] = {
> +       /*
> +        * [5:4] row(13+n)
> +        * [1:0] col(9+n), assume bw=2
> +        * row      col,bw
> +        */
> +       0,
> +       ((2 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT),

You can drop the ()

> +       ((1 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT),
> +       ((0 << DDRCONF_ROW_SHIFT) | 1 << DDRCONF_COL_SHIFT),
> +       ((2 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT),
> +       ((1 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT),
> +       ((0 << DDRCONF_ROW_SHIFT) | 2 << DDRCONF_COL_SHIFT),
> +       ((1 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT),
> +       ((0 << DDRCONF_ROW_SHIFT) | 0 << DDRCONF_COL_SHIFT),
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +       0,
> +};
> +
> +#define TEST_PATTEN    0x5aa5f00f
> +#define DQS_GATE_TRAINING_ERROR_RANK0  (1 << 4)
> +#define DQS_GATE_TRAINING_ERROR_RANK1  (2 << 4)
> +
> +
> +static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
> +{
> +       int i;
> +
> +       for (i = 0; i < n / sizeof(u32); i++) {
> +               writel(*src, dest);
> +               src++;
> +               dest++;
> +       }
> +}
> +
> +static void ddr_reset(struct rk3066_cru *cru, u32 ch, u32 ctl, u32 phy)
> +{
> +       u32 phy_ctl_srstn_shift = 13;
> +       u32 ctl_psrstn_shift = 11;
> +       u32 ctl_srstn_shift = 10;
> +       u32 phy_psrstn_shift = 9;
> +       u32 phy_srstn_shift = 8;
> +
> +       rk_clrsetreg(&cru->cru_softrst_con[5],
> +                    1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift |
> +                    1 << ctl_srstn_shift | 1 << phy_psrstn_shift |
> +                    1 << phy_srstn_shift,
> +                    phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift |
> +                    ctl << ctl_srstn_shift | phy << phy_psrstn_shift |
> +                    phy << phy_srstn_shift);
> +}
> +

How similar is this to rk3288? Could we put common code in a separate file?

Regards,
Simon


More information about the U-Boot mailing list