diff mbox

[U-Boot,v2,15/23] sunxi: A64: use H3 DRAM initialization code for A64

Message ID 1480902750-839-16-git-send-email-andre.przywara@arm.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Andre Przywara Dec. 5, 2016, 1:52 a.m. UTC
From: Jens Kuske <jenskuske@gmail.com>

The A64 DRAM controller is very similar to the H3 one,
so the code can be reused with some small changes.
[Andre: fixed up typo, merged in fixes from Jens]

Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
 arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
 arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
 arch/arm/mach-sunxi/Makefile                    |   1 +
 arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
 arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
 6 files changed, 123 insertions(+), 32 deletions(-)

Comments

Simon Glass Dec. 5, 2016, 6:26 a.m. UTC | #1
Hi Andre,

On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
> From: Jens Kuske <jenskuske@gmail.com>
>
> The A64 DRAM controller is very similar to the H3 one,
> so the code can be reused with some small changes.

Yes but it makes the code a mess. Can you avoid putting #iifdefs everywhere?

Since it is a static function I wonder if you can instead use a
function parameter which defines the chip to support, and the compiler
will eliminate the unused code?

See below...

> [Andre: fixed up typo, merged in fixes from Jens]
>
> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
>  arch/arm/mach-sunxi/Makefile                    |   1 +
>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
>  6 files changed, 123 insertions(+), 32 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index be9fcfd..3f87672 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
>  #define CCM_DRAMCLK_CFG_DIV0_MASK      (0xf << 8)
>  #define CCM_DRAMCLK_CFG_SRC_PLL5       (0x0 << 20)
>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2     (0x1 << 20)
> +#define CCM_DRAMCLK_CFG_SRC_PLL11      (0x1 << 20) /* A64 only */
>  #define CCM_DRAMCLK_CFG_SRC_MASK       (0x3 << 20)
>  #define CCM_DRAMCLK_CFG_UPD            (0x1 << 16)
>  #define CCM_DRAMCLK_CFG_RST            (0x1 << 31)
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index e0be744..53e6d47 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -24,7 +24,7 @@
>  #include <asm/arch/dram_sun8i_a33.h>
>  #elif defined(CONFIG_MACH_SUN8I_A83T)
>  #include <asm/arch/dram_sun8i_a83t.h>
> -#elif defined(CONFIG_MACH_SUN8I_H3)
> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
>  #include <asm/arch/dram_sun8i_h3.h>
>  #elif defined(CONFIG_MACH_SUN9I)
>  #include <asm/arch/dram_sun9i.h>
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> index 867fd12..b0e5d93 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> @@ -15,7 +15,8 @@
>
>  struct sunxi_mctl_com_reg {
>         u32 cr;                 /* 0x00 control register */
> -       u8 res0[0xc];           /* 0x04 */
> +       u8 res0[0x8];           /* 0x04 */
> +       u32 tmr;                /* 0x0c (A64 only) */
>         u32 mcr[16][2];         /* 0x10 */
>         u32 bwcr;               /* 0x90 bandwidth control register */
>         u32 maer;               /* 0x94 master enable register */
> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
>         u32 swoffr;             /* 0xc4 */
>         u8 res2[0x8];           /* 0xc8 */
>         u32 cccr;               /* 0xd0 */
> -       u8 res3[0x72c];         /* 0xd4 */
> +       u8 res3[0x54];          /* 0xd4 */
> +       u32 mdfs_bwlr[3];       /* 0x128 (A64 only) */
> +       u8 res4[0x6cc];         /* 0x134 */
>         u32 protect;            /* 0x800 */
>  };
>
> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
>         u32 rfshtmg;            /* 0x90 refresh timing */
>         u32 rfshctl1;           /* 0x94 */
>         u32 pwrtmg;             /* 0x98 */
> -       u8 res3[0x20];          /* 0x9c */
> +       u8 res3[0x1c];          /* 0x9c */
> +       u32 vtfcr;              /* 0xb8 (A64 only) */
>         u32 dqsgmr;             /* 0xbc */
>         u32 dtcr;               /* 0xc0 */
>         u32 dtar[4];            /* 0xc4 */
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index e73114e..7daba11 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)  += dram_sun8i_a33.o
>  obj-$(CONFIG_MACH_SUN8I_A83T)  += dram_sun8i_a83t.o
>  obj-$(CONFIG_MACH_SUN8I_H3)    += dram_sun8i_h3.o
>  obj-$(CONFIG_MACH_SUN9I)       += dram_sun9i.o
> +obj-$(CONFIG_MACH_SUN50I)      += dram_sun8i_h3.o
>  endif
> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
> index 80cfc0b..99f515d 100644
> --- a/arch/arm/mach-sunxi/clock_sun6i.c
> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
> @@ -217,7 +217,7 @@ done:
>  }
>  #endif
>
> -#ifdef CONFIG_MACH_SUN8I_A33
> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
>  {
>         struct sunxi_ccm_reg * const ccm =
> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> index 1647d76..2dc2071 100644
> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
>         return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>  }
>
> -static u32 bin_to_mgray(int val)
> -{
> -       static const u8 lookup_table[32] = {
> -               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> -               0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
> -               0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
> -               0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
> -       };
> -
> -       return lookup_table[clamp(val, 0, 31)];
> -}
> -
> -static int mgray_to_bin(u32 val)
> -{
> -       static const u8 lookup_table[32] = {
> -               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> -               0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
> -               0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
> -               0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
> -       };
> -
> -       return lookup_table[val & 0x1f];
> -}
> -
>  static void mctl_phy_init(u32 val)
>  {
>         struct sunxi_mctl_ctl_reg * const mctl_ctl =
> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
>         struct sunxi_mctl_com_reg * const mctl_com =
>                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>
> +#if defined(CONFIG_MACH_SUN8I_H3)
>         /* enable bandwidth limit windows and set windows size 1us */
> -       writel(0x00010190, &mctl_com->bwcr);
> +       writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
>
>         /* set cpu high priority */
>         writel(0x00000001, &mctl_com->mapr);
> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
>         writel(0x04001800, &mctl_com->mcr[10][1]);
>         writel(0x04000009, &mctl_com->mcr[11][0]);
>         writel(0x00400120, &mctl_com->mcr[11][1]);
> +#elif defined(CONFIG_MACH_SUN50I)
> +       /* enable bandwidth limit windows and set windows size 1us */
> +       writel(399, &mctl_com->tmr);
> +       writel((1 << 16), &mctl_com->bwcr);
> +
> +       writel(0x00a0000d, &mctl_com->mcr[0][0]);
> +       writel(0x00500064, &mctl_com->mcr[0][1]);
> +       writel(0x06000009, &mctl_com->mcr[1][0]);
> +       writel(0x01000578, &mctl_com->mcr[1][1]);
> +       writel(0x0200000d, &mctl_com->mcr[2][0]);
> +       writel(0x00600100, &mctl_com->mcr[2][1]);
> +       writel(0x01000009, &mctl_com->mcr[3][0]);
> +       writel(0x00500064, &mctl_com->mcr[3][1]);
> +       writel(0x07000009, &mctl_com->mcr[4][0]);
> +       writel(0x01000640, &mctl_com->mcr[4][1]);
> +       writel(0x01000009, &mctl_com->mcr[5][0]);
> +       writel(0x00000080, &mctl_com->mcr[5][1]);
> +       writel(0x01000009, &mctl_com->mcr[6][0]);
> +       writel(0x00400080, &mctl_com->mcr[6][1]);
> +       writel(0x0100000d, &mctl_com->mcr[7][0]);
> +       writel(0x00400080, &mctl_com->mcr[7][1]);
> +       writel(0x0100000d, &mctl_com->mcr[8][0]);
> +       writel(0x00400080, &mctl_com->mcr[8][1]);
> +       writel(0x04000009, &mctl_com->mcr[9][0]);
> +       writel(0x00400100, &mctl_com->mcr[9][1]);
> +       writel(0x20000209, &mctl_com->mcr[10][0]);
> +       writel(0x08001800, &mctl_com->mcr[10][1]);
> +       writel(0x05000009, &mctl_com->mcr[11][0]);
> +       writel(0x00400090, &mctl_com->mcr[11][1]);
> +
> +       writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
> +#endif
>  }
>
>  static void mctl_set_timing_params(struct dram_para *para)
> @@ -204,7 +213,32 @@ static void mctl_set_timing_params(struct dram_para *para)
>         writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
>  }
>
> -static void mctl_zq_calibration(struct dram_para *para)
> +#ifdef CONFIG_MACH_SUN8I_H3
> +static u32 bin_to_mgray(int val)
> +{
> +       static const u8 lookup_table[32] = {
> +               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> +               0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
> +               0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
> +               0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
> +       };
> +
> +       return lookup_table[clamp(val, 0, 31)];
> +}
> +
> +static int mgray_to_bin(u32 val)
> +{
> +       static const u8 lookup_table[32] = {
> +               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> +               0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
> +               0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
> +               0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
> +       };
> +
> +       return lookup_table[val & 0x1f];
> +}
> +
> +static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
>  {
>         struct sunxi_mctl_ctl_reg * const mctl_ctl =
>                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
> @@ -261,6 +295,7 @@ static void mctl_zq_calibration(struct dram_para *para)
>                 writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
>         }
>  }
> +#endif
>
>  static void mctl_set_cr(struct dram_para *para)

Can this be:

static void mctl_set_cr(struct dram_para *para, enum chip_type type)

>  {
> @@ -286,16 +321,27 @@ static void mctl_sys_init(struct dram_para *para)
>         clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
>         clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
>         clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
> +#ifdef CONFIG_MACH_SUN50I
> +       clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
> +#endif
>         udelay(10);
>
>         clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
>         udelay(1000);
>
> +#ifdef CONFIG_MACH_SUN50I

if (type == SUN50I)

> +       clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
> +       clrsetbits_le32(&ccm->dram_clk_cfg,
> +                       CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
> +                       CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL11 |
> +                       CCM_DRAMCLK_CFG_UPD);
> +#else
>         clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
>         clrsetbits_le32(&ccm->dram_clk_cfg,
>                         CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
>                         CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL5 |
>                         CCM_DRAMCLK_CFG_UPD);
> +#endif
>         mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
>
>         setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
> @@ -347,12 +393,18 @@ static int mctl_channel_init(struct dram_para *para)
>         /* set DQS auto gating PD mode */
>         setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
>
> +#if defined(CONFIG_MACH_SUN8I_H3)
>         /* dx ddr_clk & hdr_clk dynamic mode */
>         clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
>
>         /* dphy & aphy phase select 270 degree */
>         clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
>                         (0x1 << 10) | (0x2 << 8));
> +#elif defined(CONFIG_MACH_SUN50I)
> +       /* dphy & aphy phase select ? */
> +       clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
> +                       (0x0 << 10) | (0x3 << 8));
> +#endif
>
>         /* set half DQ */
>         if (para->bus_width != 32) {
> @@ -367,10 +419,17 @@ static int mctl_channel_init(struct dram_para *para)
>         mctl_set_bit_delays(para);
>         udelay(50);
>
> -       mctl_zq_calibration(para);
> +#ifdef CONFIG_MACH_SUN8I_H3
> +       mctl_h3_zq_calibration_quirk(para);
>
>         mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST |
>                       PIR_DRAMINIT | PIR_QSGATE);
> +#else
> +       clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
> +
> +       mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
> +                     PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
> +#endif
>
>         /* detect ranks and bus width */
>         if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
> @@ -408,7 +467,11 @@ static int mctl_channel_init(struct dram_para *para)
>         udelay(10);
>
>         /* set PGCR3, CKE polarity */
> +#ifdef CONFIG_MACH_SUN50I
> +       writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
> +#else
>         writel(0x00aa0060, &mctl_ctl->pgcr[3]);
> +#endif
>
>         /* power down zq calibration module for power save */
>         setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
> @@ -452,6 +515,7 @@ unsigned long sunxi_dram_init(void)
>                 .row_bits = 15,
>                 .page_size = 4096,
>
> +#if defined(CONFIG_MACH_SUN8I_H3)
>                 .dx_read_delays =  {{ 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
>                                     { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },
>                                     { 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
> @@ -464,6 +528,20 @@ unsigned long sunxi_dram_init(void)
>                                 0,  0,  0,  0,  0,  0,  0,  0,
>                                 0,  0,  0,  0,  0,  0,  0,  0,
>                                 0,  0,  0,  0,  0,  0,  0      },
> +#elif defined(CONFIG_MACH_SUN50I)
> +               .dx_read_delays =  {{ 16, 16, 16, 16, 17, 16, 16, 17, 16,  1,  0 },
> +                                   { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 },
> +                                   { 16, 17, 17, 16, 16, 16, 16, 16, 16,  0,  0 },
> +                                   { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 }},
> +               .dx_write_delays = {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 15, 15 },
> +                                   {  0,  0,  0,  0,  1,  1,  1,  1,  0, 10, 10 },
> +                                   {  1,  0,  1,  1,  1,  1,  1,  1,  0, 11, 11 },
> +                                   {  1,  0,  0,  1,  1,  1,  1,  1,  0, 12, 12 }},
> +               .ac_delays = {  5,  5, 13, 10,  2,  5,  3,  3,
> +                               0,  3,  3,  3,  1,  0,  0,  0,
> +                               3,  4,  0,  3,  4,  1,  4,  0,
> +                               1,  1,  0,  1, 13,  5,  4      },
> +#endif
>         };
>
>         mctl_sys_init(&para);
> @@ -476,8 +554,15 @@ unsigned long sunxi_dram_init(void)
>                 writel(0x00000201, &mctl_ctl->odtmap);
>         udelay(1);
>
> +#ifdef CONFIG_MACH_SUN8I_H3
>         /* odt delay */
>         writel(0x0c000400, &mctl_ctl->odtcfg);
> +#endif
> +
> +#ifdef CONFIG_MACH_SUN50I
> +       setbits_le32(&mctl_ctl->vtfcr, (1 << 9));
> +       clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
> +#endif
>
>         /* clear credit value */
>         setbits_le32(&mctl_com->cccr, 1 << 31);
> --
> 2.8.2
>

Then:

+#ifdef CONFIG_MACH_SUN50I
mctl_set_cr(params, SUN50I)
#elif defined(CONFIG_MACH_SUN8I_H3)
mctl_set_cr(params, SUN8I_H3)
...

Regards,
Simon
Maxime Ripard Dec. 6, 2016, 11:20 a.m. UTC | #2
On Mon, Dec 05, 2016 at 01:52:22AM +0000, Andre Przywara wrote:
> From: Jens Kuske <jenskuske@gmail.com>
> 
> The A64 DRAM controller is very similar to the H3 one,
> so the code can be reused with some small changes.
> [Andre: fixed up typo, merged in fixes from Jens]
> 
> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
>  arch/arm/mach-sunxi/Makefile                    |   1 +
>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
>  6 files changed, 123 insertions(+), 32 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index be9fcfd..3f87672 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
>  #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
>  #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
> +#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
>  #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
>  #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
>  #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> index e0be744..53e6d47 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> @@ -24,7 +24,7 @@
>  #include <asm/arch/dram_sun8i_a33.h>
>  #elif defined(CONFIG_MACH_SUN8I_A83T)
>  #include <asm/arch/dram_sun8i_a83t.h>
> -#elif defined(CONFIG_MACH_SUN8I_H3)
> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
>  #include <asm/arch/dram_sun8i_h3.h>
>  #elif defined(CONFIG_MACH_SUN9I)
>  #include <asm/arch/dram_sun9i.h>
> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> index 867fd12..b0e5d93 100644
> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> @@ -15,7 +15,8 @@
>  
>  struct sunxi_mctl_com_reg {
>  	u32 cr;			/* 0x00 control register */
> -	u8 res0[0xc];		/* 0x04 */
> +	u8 res0[0x8];		/* 0x04 */
> +	u32 tmr;		/* 0x0c (A64 only) */

#ifdef?

>  	u32 mcr[16][2];		/* 0x10 */
>  	u32 bwcr;		/* 0x90 bandwidth control register */
>  	u32 maer;		/* 0x94 master enable register */
> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
>  	u32 swoffr;		/* 0xc4 */
>  	u8 res2[0x8];		/* 0xc8 */
>  	u32 cccr;		/* 0xd0 */
> -	u8 res3[0x72c];		/* 0xd4 */
> +	u8 res3[0x54];		/* 0xd4 */
> +	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
> +	u8 res4[0x6cc];		/* 0x134 */

Ditto.

>  	u32 protect;		/* 0x800 */
>  };
>  
> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
>  	u32 rfshtmg;		/* 0x90 refresh timing */
>  	u32 rfshctl1;		/* 0x94 */
>  	u32 pwrtmg;		/* 0x98 */
> -	u8 res3[0x20];		/* 0x9c */
> +	u8 res3[0x1c];		/* 0x9c */
> +	u32 vtfcr;		/* 0xb8 (A64 only) */

Ditto

>  	u32 dqsgmr;		/* 0xbc */
>  	u32 dtcr;		/* 0xc0 */
>  	u32 dtar[4];		/* 0xc4 */
> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> index e73114e..7daba11 100644
> --- a/arch/arm/mach-sunxi/Makefile
> +++ b/arch/arm/mach-sunxi/Makefile
> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
>  obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
>  obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
>  obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
> +obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
>  endif
> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
> index 80cfc0b..99f515d 100644
> --- a/arch/arm/mach-sunxi/clock_sun6i.c
> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
> @@ -217,7 +217,7 @@ done:
>  }
>  #endif
>  
> -#ifdef CONFIG_MACH_SUN8I_A33
> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
>  {
>  	struct sunxi_ccm_reg * const ccm =
> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> index 1647d76..2dc2071 100644
> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
>  	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>  }
>  
> -static u32 bin_to_mgray(int val)
> -{
> -	static const u8 lookup_table[32] = {
> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> -		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
> -		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
> -		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
> -	};
> -
> -	return lookup_table[clamp(val, 0, 31)];
> -}
> -
> -static int mgray_to_bin(u32 val)
> -{
> -	static const u8 lookup_table[32] = {
> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> -		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
> -		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
> -		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
> -	};
> -
> -	return lookup_table[val & 0x1f];
> -}
> -
>  static void mctl_phy_init(u32 val)
>  {
>  	struct sunxi_mctl_ctl_reg * const mctl_ctl =
> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
>  	struct sunxi_mctl_com_reg * const mctl_com =
>  			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>  
> +#if defined(CONFIG_MACH_SUN8I_H3)
>  	/* enable bandwidth limit windows and set windows size 1us */
> -	writel(0x00010190, &mctl_com->bwcr);
> +	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
>  
>  	/* set cpu high priority */
>  	writel(0x00000001, &mctl_com->mapr);
> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
>  	writel(0x04001800, &mctl_com->mcr[10][1]);
>  	writel(0x04000009, &mctl_com->mcr[11][0]);
>  	writel(0x00400120, &mctl_com->mcr[11][1]);
> +#elif defined(CONFIG_MACH_SUN50I)
> +	/* enable bandwidth limit windows and set windows size 1us */
> +	writel(399, &mctl_com->tmr);
> +	writel((1 << 16), &mctl_com->bwcr);
> +
> +	writel(0x00a0000d, &mctl_com->mcr[0][0]);
> +	writel(0x00500064, &mctl_com->mcr[0][1]);
> +	writel(0x06000009, &mctl_com->mcr[1][0]);
> +	writel(0x01000578, &mctl_com->mcr[1][1]);
> +	writel(0x0200000d, &mctl_com->mcr[2][0]);
> +	writel(0x00600100, &mctl_com->mcr[2][1]);
> +	writel(0x01000009, &mctl_com->mcr[3][0]);
> +	writel(0x00500064, &mctl_com->mcr[3][1]);
> +	writel(0x07000009, &mctl_com->mcr[4][0]);
> +	writel(0x01000640, &mctl_com->mcr[4][1]);
> +	writel(0x01000009, &mctl_com->mcr[5][0]);
> +	writel(0x00000080, &mctl_com->mcr[5][1]);
> +	writel(0x01000009, &mctl_com->mcr[6][0]);
> +	writel(0x00400080, &mctl_com->mcr[6][1]);
> +	writel(0x0100000d, &mctl_com->mcr[7][0]);
> +	writel(0x00400080, &mctl_com->mcr[7][1]);
> +	writel(0x0100000d, &mctl_com->mcr[8][0]);
> +	writel(0x00400080, &mctl_com->mcr[8][1]);
> +	writel(0x04000009, &mctl_com->mcr[9][0]);
> +	writel(0x00400100, &mctl_com->mcr[9][1]);
> +	writel(0x20000209, &mctl_com->mcr[10][0]);
> +	writel(0x08001800, &mctl_com->mcr[10][1]);
> +	writel(0x05000009, &mctl_com->mcr[11][0]);
> +	writel(0x00400090, &mctl_com->mcr[11][1]);
> +
> +	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);

Where is this pulled from? having some defines would be great..

Maxime
Andre Przywara Dec. 6, 2016, 2:15 p.m. UTC | #3
Hi,

On 06/12/16 11:20, Maxime Ripard wrote:
> On Mon, Dec 05, 2016 at 01:52:22AM +0000, Andre Przywara wrote:
>> From: Jens Kuske <jenskuske@gmail.com>
>>
>> The A64 DRAM controller is very similar to the H3 one,
>> so the code can be reused with some small changes.
>> [Andre: fixed up typo, merged in fixes from Jens]
>>
>> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
>>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
>>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
>>  arch/arm/mach-sunxi/Makefile                    |   1 +
>>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
>>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
>>  6 files changed, 123 insertions(+), 32 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> index be9fcfd..3f87672 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
>>  #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
>>  #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
>>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
>> +#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
>>  #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
>>  #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
>>  #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
>> index e0be744..53e6d47 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>> @@ -24,7 +24,7 @@
>>  #include <asm/arch/dram_sun8i_a33.h>
>>  #elif defined(CONFIG_MACH_SUN8I_A83T)
>>  #include <asm/arch/dram_sun8i_a83t.h>
>> -#elif defined(CONFIG_MACH_SUN8I_H3)
>> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
>>  #include <asm/arch/dram_sun8i_h3.h>
>>  #elif defined(CONFIG_MACH_SUN9I)
>>  #include <asm/arch/dram_sun9i.h>
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> index 867fd12..b0e5d93 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> @@ -15,7 +15,8 @@
>>  
>>  struct sunxi_mctl_com_reg {
>>  	u32 cr;			/* 0x00 control register */
>> -	u8 res0[0xc];		/* 0x04 */
>> +	u8 res0[0x8];		/* 0x04 */
>> +	u32 tmr;		/* 0x0c (A64 only) */
> 
> #ifdef?

What would that change aside from making it hard to read?
This is a structure definition, so it doesn't generate any code on its
own. And we only access that field from the A64, so it keeps its
reserved nature for the H3.

>>  	u32 mcr[16][2];		/* 0x10 */
>>  	u32 bwcr;		/* 0x90 bandwidth control register */
>>  	u32 maer;		/* 0x94 master enable register */
>> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
>>  	u32 swoffr;		/* 0xc4 */
>>  	u8 res2[0x8];		/* 0xc8 */
>>  	u32 cccr;		/* 0xd0 */
>> -	u8 res3[0x72c];		/* 0xd4 */
>> +	u8 res3[0x54];		/* 0xd4 */
>> +	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
>> +	u8 res4[0x6cc];		/* 0x134 */
> 
> Ditto.
> 
>>  	u32 protect;		/* 0x800 */
>>  };
>>  
>> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
>>  	u32 rfshtmg;		/* 0x90 refresh timing */
>>  	u32 rfshctl1;		/* 0x94 */
>>  	u32 pwrtmg;		/* 0x98 */
>> -	u8 res3[0x20];		/* 0x9c */
>> +	u8 res3[0x1c];		/* 0x9c */
>> +	u32 vtfcr;		/* 0xb8 (A64 only) */
> 
> Ditto
> 
>>  	u32 dqsgmr;		/* 0xbc */
>>  	u32 dtcr;		/* 0xc0 */
>>  	u32 dtar[4];		/* 0xc4 */
>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>> index e73114e..7daba11 100644
>> --- a/arch/arm/mach-sunxi/Makefile
>> +++ b/arch/arm/mach-sunxi/Makefile
>> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
>>  obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
>>  obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
>>  obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
>> +obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
>>  endif
>> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
>> index 80cfc0b..99f515d 100644
>> --- a/arch/arm/mach-sunxi/clock_sun6i.c
>> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
>> @@ -217,7 +217,7 @@ done:
>>  }
>>  #endif
>>  
>> -#ifdef CONFIG_MACH_SUN8I_A33
>> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
>>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
>>  {
>>  	struct sunxi_ccm_reg * const ccm =
>> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> index 1647d76..2dc2071 100644
>> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
>>  	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>>  }
>>  
>> -static u32 bin_to_mgray(int val)
>> -{
>> -	static const u8 lookup_table[32] = {
>> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> -		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
>> -		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
>> -		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
>> -	};
>> -
>> -	return lookup_table[clamp(val, 0, 31)];
>> -}
>> -
>> -static int mgray_to_bin(u32 val)
>> -{
>> -	static const u8 lookup_table[32] = {
>> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> -		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
>> -		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
>> -		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
>> -	};
>> -
>> -	return lookup_table[val & 0x1f];
>> -}
>> -
>>  static void mctl_phy_init(u32 val)
>>  {
>>  	struct sunxi_mctl_ctl_reg * const mctl_ctl =
>> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
>>  	struct sunxi_mctl_com_reg * const mctl_com =
>>  			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>>  
>> +#if defined(CONFIG_MACH_SUN8I_H3)
>>  	/* enable bandwidth limit windows and set windows size 1us */
>> -	writel(0x00010190, &mctl_com->bwcr);
>> +	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
>>  
>>  	/* set cpu high priority */
>>  	writel(0x00000001, &mctl_com->mapr);
>> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
>>  	writel(0x04001800, &mctl_com->mcr[10][1]);
>>  	writel(0x04000009, &mctl_com->mcr[11][0]);
>>  	writel(0x00400120, &mctl_com->mcr[11][1]);
>> +#elif defined(CONFIG_MACH_SUN50I)
>> +	/* enable bandwidth limit windows and set windows size 1us */
>> +	writel(399, &mctl_com->tmr);
>> +	writel((1 << 16), &mctl_com->bwcr);
>> +
>> +	writel(0x00a0000d, &mctl_com->mcr[0][0]);
>> +	writel(0x00500064, &mctl_com->mcr[0][1]);
>> +	writel(0x06000009, &mctl_com->mcr[1][0]);
>> +	writel(0x01000578, &mctl_com->mcr[1][1]);
>> +	writel(0x0200000d, &mctl_com->mcr[2][0]);
>> +	writel(0x00600100, &mctl_com->mcr[2][1]);
>> +	writel(0x01000009, &mctl_com->mcr[3][0]);
>> +	writel(0x00500064, &mctl_com->mcr[3][1]);
>> +	writel(0x07000009, &mctl_com->mcr[4][0]);
>> +	writel(0x01000640, &mctl_com->mcr[4][1]);
>> +	writel(0x01000009, &mctl_com->mcr[5][0]);
>> +	writel(0x00000080, &mctl_com->mcr[5][1]);
>> +	writel(0x01000009, &mctl_com->mcr[6][0]);
>> +	writel(0x00400080, &mctl_com->mcr[6][1]);
>> +	writel(0x0100000d, &mctl_com->mcr[7][0]);
>> +	writel(0x00400080, &mctl_com->mcr[7][1]);
>> +	writel(0x0100000d, &mctl_com->mcr[8][0]);
>> +	writel(0x00400080, &mctl_com->mcr[8][1]);
>> +	writel(0x04000009, &mctl_com->mcr[9][0]);
>> +	writel(0x00400100, &mctl_com->mcr[9][1]);
>> +	writel(0x20000209, &mctl_com->mcr[10][0]);
>> +	writel(0x08001800, &mctl_com->mcr[10][1]);
>> +	writel(0x05000009, &mctl_com->mcr[11][0]);
>> +	writel(0x00400090, &mctl_com->mcr[11][1]);
>> +
>> +	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
> 
> Where is this pulled from? having some defines would be great..

AFAIK this is from register dumps after boot0 has done its job. I am
afraid this is as far as we get in the moment. IIRC even the disassembly
of boot0 shows that these registers are just initialised with those
magic values and are not computed somehow.
So the original source code _might_ have names to it, but I guess we
will never know.

Cheers,
Andre.
Maxime Ripard Dec. 12, 2016, 12:29 p.m. UTC | #4
On Tue, Dec 06, 2016 at 02:15:17PM +0000, Andre Przywara wrote:
> Hi,
> 
> On 06/12/16 11:20, Maxime Ripard wrote:
> > On Mon, Dec 05, 2016 at 01:52:22AM +0000, Andre Przywara wrote:
> >> From: Jens Kuske <jenskuske@gmail.com>
> >>
> >> The A64 DRAM controller is very similar to the H3 one,
> >> so the code can be reused with some small changes.
> >> [Andre: fixed up typo, merged in fixes from Jens]
> >>
> >> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
> >> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> >> ---
> >>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
> >>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
> >>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
> >>  arch/arm/mach-sunxi/Makefile                    |   1 +
> >>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
> >>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
> >>  6 files changed, 123 insertions(+), 32 deletions(-)
> >>
> >> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> index be9fcfd..3f87672 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> >> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
> >>  #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
> >>  #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
> >>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
> >> +#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
> >>  #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
> >>  #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
> >>  #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
> >> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
> >> index e0be744..53e6d47 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/dram.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
> >> @@ -24,7 +24,7 @@
> >>  #include <asm/arch/dram_sun8i_a33.h>
> >>  #elif defined(CONFIG_MACH_SUN8I_A83T)
> >>  #include <asm/arch/dram_sun8i_a83t.h>
> >> -#elif defined(CONFIG_MACH_SUN8I_H3)
> >> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
> >>  #include <asm/arch/dram_sun8i_h3.h>
> >>  #elif defined(CONFIG_MACH_SUN9I)
> >>  #include <asm/arch/dram_sun9i.h>
> >> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> >> index 867fd12..b0e5d93 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
> >> @@ -15,7 +15,8 @@
> >>  
> >>  struct sunxi_mctl_com_reg {
> >>  	u32 cr;			/* 0x00 control register */
> >> -	u8 res0[0xc];		/* 0x04 */
> >> +	u8 res0[0x8];		/* 0x04 */
> >> +	u32 tmr;		/* 0x0c (A64 only) */
> > 
> > #ifdef?
> 
> What would that change aside from making it hard to read?
> This is a structure definition, so it doesn't generate any code on its
> own. And we only access that field from the A64, so it keeps its
> reserved nature for the H3.

Yes, but at least we can catch improper writes to the register on !A64
platforms at compile time. We already use that construct in the u-boot
code, and you're using it every where in the code already, so it
wouldn't really make it harder to read than it already is.

> 
> >>  	u32 mcr[16][2];		/* 0x10 */
> >>  	u32 bwcr;		/* 0x90 bandwidth control register */
> >>  	u32 maer;		/* 0x94 master enable register */
> >> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
> >>  	u32 swoffr;		/* 0xc4 */
> >>  	u8 res2[0x8];		/* 0xc8 */
> >>  	u32 cccr;		/* 0xd0 */
> >> -	u8 res3[0x72c];		/* 0xd4 */
> >> +	u8 res3[0x54];		/* 0xd4 */
> >> +	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
> >> +	u8 res4[0x6cc];		/* 0x134 */
> > 
> > Ditto.
> > 
> >>  	u32 protect;		/* 0x800 */
> >>  };
> >>  
> >> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
> >>  	u32 rfshtmg;		/* 0x90 refresh timing */
> >>  	u32 rfshctl1;		/* 0x94 */
> >>  	u32 pwrtmg;		/* 0x98 */
> >> -	u8 res3[0x20];		/* 0x9c */
> >> +	u8 res3[0x1c];		/* 0x9c */
> >> +	u32 vtfcr;		/* 0xb8 (A64 only) */
> > 
> > Ditto
> > 
> >>  	u32 dqsgmr;		/* 0xbc */
> >>  	u32 dtcr;		/* 0xc0 */
> >>  	u32 dtar[4];		/* 0xc4 */
> >> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
> >> index e73114e..7daba11 100644
> >> --- a/arch/arm/mach-sunxi/Makefile
> >> +++ b/arch/arm/mach-sunxi/Makefile
> >> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
> >>  obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
> >>  obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
> >>  obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
> >> +obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
> >>  endif
> >> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
> >> index 80cfc0b..99f515d 100644
> >> --- a/arch/arm/mach-sunxi/clock_sun6i.c
> >> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
> >> @@ -217,7 +217,7 @@ done:
> >>  }
> >>  #endif
> >>  
> >> -#ifdef CONFIG_MACH_SUN8I_A33
> >> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
> >>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
> >>  {
> >>  	struct sunxi_ccm_reg * const ccm =
> >> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> >> index 1647d76..2dc2071 100644
> >> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
> >> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
> >> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
> >>  	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
> >>  }
> >>  
> >> -static u32 bin_to_mgray(int val)
> >> -{
> >> -	static const u8 lookup_table[32] = {
> >> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> >> -		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
> >> -		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
> >> -		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
> >> -	};
> >> -
> >> -	return lookup_table[clamp(val, 0, 31)];
> >> -}
> >> -
> >> -static int mgray_to_bin(u32 val)
> >> -{
> >> -	static const u8 lookup_table[32] = {
> >> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
> >> -		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
> >> -		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
> >> -		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
> >> -	};
> >> -
> >> -	return lookup_table[val & 0x1f];
> >> -}
> >> -
> >>  static void mctl_phy_init(u32 val)
> >>  {
> >>  	struct sunxi_mctl_ctl_reg * const mctl_ctl =
> >> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
> >>  	struct sunxi_mctl_com_reg * const mctl_com =
> >>  			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> >>  
> >> +#if defined(CONFIG_MACH_SUN8I_H3)
> >>  	/* enable bandwidth limit windows and set windows size 1us */
> >> -	writel(0x00010190, &mctl_com->bwcr);
> >> +	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
> >>  
> >>  	/* set cpu high priority */
> >>  	writel(0x00000001, &mctl_com->mapr);
> >> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
> >>  	writel(0x04001800, &mctl_com->mcr[10][1]);
> >>  	writel(0x04000009, &mctl_com->mcr[11][0]);
> >>  	writel(0x00400120, &mctl_com->mcr[11][1]);
> >> +#elif defined(CONFIG_MACH_SUN50I)
> >> +	/* enable bandwidth limit windows and set windows size 1us */
> >> +	writel(399, &mctl_com->tmr);
> >> +	writel((1 << 16), &mctl_com->bwcr);
> >> +
> >> +	writel(0x00a0000d, &mctl_com->mcr[0][0]);
> >> +	writel(0x00500064, &mctl_com->mcr[0][1]);
> >> +	writel(0x06000009, &mctl_com->mcr[1][0]);
> >> +	writel(0x01000578, &mctl_com->mcr[1][1]);
> >> +	writel(0x0200000d, &mctl_com->mcr[2][0]);
> >> +	writel(0x00600100, &mctl_com->mcr[2][1]);
> >> +	writel(0x01000009, &mctl_com->mcr[3][0]);
> >> +	writel(0x00500064, &mctl_com->mcr[3][1]);
> >> +	writel(0x07000009, &mctl_com->mcr[4][0]);
> >> +	writel(0x01000640, &mctl_com->mcr[4][1]);
> >> +	writel(0x01000009, &mctl_com->mcr[5][0]);
> >> +	writel(0x00000080, &mctl_com->mcr[5][1]);
> >> +	writel(0x01000009, &mctl_com->mcr[6][0]);
> >> +	writel(0x00400080, &mctl_com->mcr[6][1]);
> >> +	writel(0x0100000d, &mctl_com->mcr[7][0]);
> >> +	writel(0x00400080, &mctl_com->mcr[7][1]);
> >> +	writel(0x0100000d, &mctl_com->mcr[8][0]);
> >> +	writel(0x00400080, &mctl_com->mcr[8][1]);
> >> +	writel(0x04000009, &mctl_com->mcr[9][0]);
> >> +	writel(0x00400100, &mctl_com->mcr[9][1]);
> >> +	writel(0x20000209, &mctl_com->mcr[10][0]);
> >> +	writel(0x08001800, &mctl_com->mcr[10][1]);
> >> +	writel(0x05000009, &mctl_com->mcr[11][0]);
> >> +	writel(0x00400090, &mctl_com->mcr[11][1]);
> >> +
> >> +	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
> > 
> > Where is this pulled from? having some defines would be great..
> 
> AFAIK this is from register dumps after boot0 has done its job. I am
> afraid this is as far as we get in the moment. IIRC even the disassembly
> of boot0 shows that these registers are just initialised with those
> magic values and are not computed somehow.
> So the original source code _might_ have names to it, but I guess we
> will never know.

Can you please make that a comment?

Thanks,
Maxime
Andre Przywara Dec. 12, 2016, 4:06 p.m. UTC | #5
Hi,

On 12/12/16 12:29, Maxime Ripard wrote:
> On Tue, Dec 06, 2016 at 02:15:17PM +0000, Andre Przywara wrote:
>> Hi,
>>
>> On 06/12/16 11:20, Maxime Ripard wrote:
>>> On Mon, Dec 05, 2016 at 01:52:22AM +0000, Andre Przywara wrote:
>>>> From: Jens Kuske <jenskuske@gmail.com>
>>>>
>>>> The A64 DRAM controller is very similar to the H3 one,
>>>> so the code can be reused with some small changes.
>>>> [Andre: fixed up typo, merged in fixes from Jens]
>>>>
>>>> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
>>>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>>>> ---
>>>>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
>>>>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
>>>>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
>>>>  arch/arm/mach-sunxi/Makefile                    |   1 +
>>>>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
>>>>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
>>>>  6 files changed, 123 insertions(+), 32 deletions(-)
>>>>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>>>> index be9fcfd..3f87672 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>>>> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
>>>>  #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
>>>>  #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
>>>>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
>>>> +#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
>>>>  #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
>>>>  #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
>>>>  #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
>>>> index e0be744..53e6d47 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>>>> @@ -24,7 +24,7 @@
>>>>  #include <asm/arch/dram_sun8i_a33.h>
>>>>  #elif defined(CONFIG_MACH_SUN8I_A83T)
>>>>  #include <asm/arch/dram_sun8i_a83t.h>
>>>> -#elif defined(CONFIG_MACH_SUN8I_H3)
>>>> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
>>>>  #include <asm/arch/dram_sun8i_h3.h>
>>>>  #elif defined(CONFIG_MACH_SUN9I)
>>>>  #include <asm/arch/dram_sun9i.h>
>>>> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>>>> index 867fd12..b0e5d93 100644
>>>> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>>>> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>>>> @@ -15,7 +15,8 @@
>>>>  
>>>>  struct sunxi_mctl_com_reg {
>>>>  	u32 cr;			/* 0x00 control register */
>>>> -	u8 res0[0xc];		/* 0x04 */
>>>> +	u8 res0[0x8];		/* 0x04 */
>>>> +	u32 tmr;		/* 0x0c (A64 only) */
>>>
>>> #ifdef?
>>
>> What would that change aside from making it hard to read?
>> This is a structure definition, so it doesn't generate any code on its
>> own. And we only access that field from the A64, so it keeps its
>> reserved nature for the H3.
> 
> Yes, but at least we can catch improper writes to the register on !A64
> platforms at compile time. We already use that construct in the u-boot
> code, and you're using it every where in the code already, so it
> wouldn't really make it harder to read than it already is.

Still not convinced, but I will give it a try.

>>
>>>>  	u32 mcr[16][2];		/* 0x10 */
>>>>  	u32 bwcr;		/* 0x90 bandwidth control register */
>>>>  	u32 maer;		/* 0x94 master enable register */
>>>> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
>>>>  	u32 swoffr;		/* 0xc4 */
>>>>  	u8 res2[0x8];		/* 0xc8 */
>>>>  	u32 cccr;		/* 0xd0 */
>>>> -	u8 res3[0x72c];		/* 0xd4 */
>>>> +	u8 res3[0x54];		/* 0xd4 */
>>>> +	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
>>>> +	u8 res4[0x6cc];		/* 0x134 */
>>>
>>> Ditto.
>>>
>>>>  	u32 protect;		/* 0x800 */
>>>>  };
>>>>  
>>>> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
>>>>  	u32 rfshtmg;		/* 0x90 refresh timing */
>>>>  	u32 rfshctl1;		/* 0x94 */
>>>>  	u32 pwrtmg;		/* 0x98 */
>>>> -	u8 res3[0x20];		/* 0x9c */
>>>> +	u8 res3[0x1c];		/* 0x9c */
>>>> +	u32 vtfcr;		/* 0xb8 (A64 only) */
>>>
>>> Ditto
>>>
>>>>  	u32 dqsgmr;		/* 0xbc */
>>>>  	u32 dtcr;		/* 0xc0 */
>>>>  	u32 dtar[4];		/* 0xc4 */
>>>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>>>> index e73114e..7daba11 100644
>>>> --- a/arch/arm/mach-sunxi/Makefile
>>>> +++ b/arch/arm/mach-sunxi/Makefile
>>>> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
>>>>  obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
>>>>  obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
>>>>  obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
>>>> +obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
>>>>  endif
>>>> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
>>>> index 80cfc0b..99f515d 100644
>>>> --- a/arch/arm/mach-sunxi/clock_sun6i.c
>>>> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
>>>> @@ -217,7 +217,7 @@ done:
>>>>  }
>>>>  #endif
>>>>  
>>>> -#ifdef CONFIG_MACH_SUN8I_A33
>>>> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
>>>>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
>>>>  {
>>>>  	struct sunxi_ccm_reg * const ccm =
>>>> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>>>> index 1647d76..2dc2071 100644
>>>> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
>>>> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>>>> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
>>>>  	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>>>>  }
>>>>  
>>>> -static u32 bin_to_mgray(int val)
>>>> -{
>>>> -	static const u8 lookup_table[32] = {
>>>> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>>>> -		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
>>>> -		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
>>>> -		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
>>>> -	};
>>>> -
>>>> -	return lookup_table[clamp(val, 0, 31)];
>>>> -}
>>>> -
>>>> -static int mgray_to_bin(u32 val)
>>>> -{
>>>> -	static const u8 lookup_table[32] = {
>>>> -		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>>>> -		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
>>>> -		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
>>>> -		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
>>>> -	};
>>>> -
>>>> -	return lookup_table[val & 0x1f];
>>>> -}
>>>> -
>>>>  static void mctl_phy_init(u32 val)
>>>>  {
>>>>  	struct sunxi_mctl_ctl_reg * const mctl_ctl =
>>>> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
>>>>  	struct sunxi_mctl_com_reg * const mctl_com =
>>>>  			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>>>>  
>>>> +#if defined(CONFIG_MACH_SUN8I_H3)
>>>>  	/* enable bandwidth limit windows and set windows size 1us */
>>>> -	writel(0x00010190, &mctl_com->bwcr);
>>>> +	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
>>>>  
>>>>  	/* set cpu high priority */
>>>>  	writel(0x00000001, &mctl_com->mapr);
>>>> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
>>>>  	writel(0x04001800, &mctl_com->mcr[10][1]);
>>>>  	writel(0x04000009, &mctl_com->mcr[11][0]);
>>>>  	writel(0x00400120, &mctl_com->mcr[11][1]);
>>>> +#elif defined(CONFIG_MACH_SUN50I)
>>>> +	/* enable bandwidth limit windows and set windows size 1us */
>>>> +	writel(399, &mctl_com->tmr);
>>>> +	writel((1 << 16), &mctl_com->bwcr);
>>>> +
>>>> +	writel(0x00a0000d, &mctl_com->mcr[0][0]);
>>>> +	writel(0x00500064, &mctl_com->mcr[0][1]);
>>>> +	writel(0x06000009, &mctl_com->mcr[1][0]);
>>>> +	writel(0x01000578, &mctl_com->mcr[1][1]);
>>>> +	writel(0x0200000d, &mctl_com->mcr[2][0]);
>>>> +	writel(0x00600100, &mctl_com->mcr[2][1]);
>>>> +	writel(0x01000009, &mctl_com->mcr[3][0]);
>>>> +	writel(0x00500064, &mctl_com->mcr[3][1]);
>>>> +	writel(0x07000009, &mctl_com->mcr[4][0]);
>>>> +	writel(0x01000640, &mctl_com->mcr[4][1]);
>>>> +	writel(0x01000009, &mctl_com->mcr[5][0]);
>>>> +	writel(0x00000080, &mctl_com->mcr[5][1]);
>>>> +	writel(0x01000009, &mctl_com->mcr[6][0]);
>>>> +	writel(0x00400080, &mctl_com->mcr[6][1]);
>>>> +	writel(0x0100000d, &mctl_com->mcr[7][0]);
>>>> +	writel(0x00400080, &mctl_com->mcr[7][1]);
>>>> +	writel(0x0100000d, &mctl_com->mcr[8][0]);
>>>> +	writel(0x00400080, &mctl_com->mcr[8][1]);
>>>> +	writel(0x04000009, &mctl_com->mcr[9][0]);
>>>> +	writel(0x00400100, &mctl_com->mcr[9][1]);
>>>> +	writel(0x20000209, &mctl_com->mcr[10][0]);
>>>> +	writel(0x08001800, &mctl_com->mcr[10][1]);
>>>> +	writel(0x05000009, &mctl_com->mcr[11][0]);
>>>> +	writel(0x00400090, &mctl_com->mcr[11][1]);
>>>> +
>>>> +	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
>>>
>>> Where is this pulled from? having some defines would be great..
>>
>> AFAIK this is from register dumps after boot0 has done its job. I am
>> afraid this is as far as we get in the moment. IIRC even the disassembly
>> of boot0 shows that these registers are just initialised with those
>> magic values and are not computed somehow.
>> So the original source code _might_ have names to it, but I guess we
>> will never know.
> 
> Can you please make that a comment?

Even better there is a patch from Philipp which actually dissects this
into meaningful fields.

So I looked into the H3 BSP and found the respective code there as well,
so I have now a patch which turns the existing H3 mctl_com->mcr setup
code into something like:
	MBUS_CONF(CPU, true, HIGHEST, 0, 160, 100, 80);
	....
(with explanations for the numerical parameters as well).

Then this A64 patch will just copy that scheme, and will hopefully make
everyone happy.

Cheers,
Andre.
Andre Przywara Dec. 16, 2016, 5:30 p.m. UTC | #6
Hi Simon,

On 05/12/16 06:26, Simon Glass wrote:
> Hi Andre,
> 
> On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
>> From: Jens Kuske <jenskuske@gmail.com>
>>
>> The A64 DRAM controller is very similar to the H3 one,
>> so the code can be reused with some small changes.
> 
> Yes but it makes the code a mess. Can you avoid putting #iifdefs everywhere?

Sure ...

> Since it is a static function I wonder if you can instead use a
> function parameter which defines the chip to support, and the compiler
> will eliminate the unused code?

I like that idea. Actually I went ahead and converted the file to this
approach and it looks much nicer, especially since I added support for a
third DRAM controller on top.
Also it opens the doors to potentially serve multiple variants in one
binary (one day ...)

I took the freedom to use the Allwinner SoCID (a 16-bit value (mostly)
unique to a certain SoC) as the variant identifier.
That doesn't make any difference for this passing-to-static-functions
case, but avoids inventing identifiers and can be easily reused with
auto-detection.

Cheers,
Andre.

> 
> See below...
> 
>> [Andre: fixed up typo, merged in fixes from Jens]
>>
>> Signed-off-by: Jens Kuske <jenskuske@gmail.com>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
>>  arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
>>  arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
>>  arch/arm/mach-sunxi/Makefile                    |   1 +
>>  arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
>>  arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
>>  6 files changed, 123 insertions(+), 32 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> index be9fcfd..3f87672 100644
>> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
>> @@ -322,6 +322,7 @@ struct sunxi_ccm_reg {
>>  #define CCM_DRAMCLK_CFG_DIV0_MASK      (0xf << 8)
>>  #define CCM_DRAMCLK_CFG_SRC_PLL5       (0x0 << 20)
>>  #define CCM_DRAMCLK_CFG_SRC_PLL6x2     (0x1 << 20)
>> +#define CCM_DRAMCLK_CFG_SRC_PLL11      (0x1 << 20) /* A64 only */
>>  #define CCM_DRAMCLK_CFG_SRC_MASK       (0x3 << 20)
>>  #define CCM_DRAMCLK_CFG_UPD            (0x1 << 16)
>>  #define CCM_DRAMCLK_CFG_RST            (0x1 << 31)
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
>> index e0be744..53e6d47 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram.h
>> @@ -24,7 +24,7 @@
>>  #include <asm/arch/dram_sun8i_a33.h>
>>  #elif defined(CONFIG_MACH_SUN8I_A83T)
>>  #include <asm/arch/dram_sun8i_a83t.h>
>> -#elif defined(CONFIG_MACH_SUN8I_H3)
>> +#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
>>  #include <asm/arch/dram_sun8i_h3.h>
>>  #elif defined(CONFIG_MACH_SUN9I)
>>  #include <asm/arch/dram_sun9i.h>
>> diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> index 867fd12..b0e5d93 100644
>> --- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> +++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
>> @@ -15,7 +15,8 @@
>>
>>  struct sunxi_mctl_com_reg {
>>         u32 cr;                 /* 0x00 control register */
>> -       u8 res0[0xc];           /* 0x04 */
>> +       u8 res0[0x8];           /* 0x04 */
>> +       u32 tmr;                /* 0x0c (A64 only) */
>>         u32 mcr[16][2];         /* 0x10 */
>>         u32 bwcr;               /* 0x90 bandwidth control register */
>>         u32 maer;               /* 0x94 master enable register */
>> @@ -32,7 +33,9 @@ struct sunxi_mctl_com_reg {
>>         u32 swoffr;             /* 0xc4 */
>>         u8 res2[0x8];           /* 0xc8 */
>>         u32 cccr;               /* 0xd0 */
>> -       u8 res3[0x72c];         /* 0xd4 */
>> +       u8 res3[0x54];          /* 0xd4 */
>> +       u32 mdfs_bwlr[3];       /* 0x128 (A64 only) */
>> +       u8 res4[0x6cc];         /* 0x134 */
>>         u32 protect;            /* 0x800 */
>>  };
>>
>> @@ -81,7 +84,8 @@ struct sunxi_mctl_ctl_reg {
>>         u32 rfshtmg;            /* 0x90 refresh timing */
>>         u32 rfshctl1;           /* 0x94 */
>>         u32 pwrtmg;             /* 0x98 */
>> -       u8 res3[0x20];          /* 0x9c */
>> +       u8 res3[0x1c];          /* 0x9c */
>> +       u32 vtfcr;              /* 0xb8 (A64 only) */
>>         u32 dqsgmr;             /* 0xbc */
>>         u32 dtcr;               /* 0xc0 */
>>         u32 dtar[4];            /* 0xc4 */
>> diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
>> index e73114e..7daba11 100644
>> --- a/arch/arm/mach-sunxi/Makefile
>> +++ b/arch/arm/mach-sunxi/Makefile
>> @@ -50,4 +50,5 @@ obj-$(CONFIG_MACH_SUN8I_A33)  += dram_sun8i_a33.o
>>  obj-$(CONFIG_MACH_SUN8I_A83T)  += dram_sun8i_a83t.o
>>  obj-$(CONFIG_MACH_SUN8I_H3)    += dram_sun8i_h3.o
>>  obj-$(CONFIG_MACH_SUN9I)       += dram_sun9i.o
>> +obj-$(CONFIG_MACH_SUN50I)      += dram_sun8i_h3.o
>>  endif
>> diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
>> index 80cfc0b..99f515d 100644
>> --- a/arch/arm/mach-sunxi/clock_sun6i.c
>> +++ b/arch/arm/mach-sunxi/clock_sun6i.c
>> @@ -217,7 +217,7 @@ done:
>>  }
>>  #endif
>>
>> -#ifdef CONFIG_MACH_SUN8I_A33
>> +#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
>>  void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
>>  {
>>         struct sunxi_ccm_reg * const ccm =
>> diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> index 1647d76..2dc2071 100644
>> --- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> +++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
>> @@ -32,30 +32,6 @@ static inline int ns_to_t(int nanoseconds)
>>         return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
>>  }
>>
>> -static u32 bin_to_mgray(int val)
>> -{
>> -       static const u8 lookup_table[32] = {
>> -               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> -               0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
>> -               0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
>> -               0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
>> -       };
>> -
>> -       return lookup_table[clamp(val, 0, 31)];
>> -}
>> -
>> -static int mgray_to_bin(u32 val)
>> -{
>> -       static const u8 lookup_table[32] = {
>> -               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> -               0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
>> -               0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
>> -               0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
>> -       };
>> -
>> -       return lookup_table[val & 0x1f];
>> -}
>> -
>>  static void mctl_phy_init(u32 val)
>>  {
>>         struct sunxi_mctl_ctl_reg * const mctl_ctl =
>> @@ -91,8 +67,9 @@ static void mctl_set_master_priority(void)
>>         struct sunxi_mctl_com_reg * const mctl_com =
>>                         (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
>>
>> +#if defined(CONFIG_MACH_SUN8I_H3)
>>         /* enable bandwidth limit windows and set windows size 1us */
>> -       writel(0x00010190, &mctl_com->bwcr);
>> +       writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
>>
>>         /* set cpu high priority */
>>         writel(0x00000001, &mctl_com->mapr);
>> @@ -121,6 +98,38 @@ static void mctl_set_master_priority(void)
>>         writel(0x04001800, &mctl_com->mcr[10][1]);
>>         writel(0x04000009, &mctl_com->mcr[11][0]);
>>         writel(0x00400120, &mctl_com->mcr[11][1]);
>> +#elif defined(CONFIG_MACH_SUN50I)
>> +       /* enable bandwidth limit windows and set windows size 1us */
>> +       writel(399, &mctl_com->tmr);
>> +       writel((1 << 16), &mctl_com->bwcr);
>> +
>> +       writel(0x00a0000d, &mctl_com->mcr[0][0]);
>> +       writel(0x00500064, &mctl_com->mcr[0][1]);
>> +       writel(0x06000009, &mctl_com->mcr[1][0]);
>> +       writel(0x01000578, &mctl_com->mcr[1][1]);
>> +       writel(0x0200000d, &mctl_com->mcr[2][0]);
>> +       writel(0x00600100, &mctl_com->mcr[2][1]);
>> +       writel(0x01000009, &mctl_com->mcr[3][0]);
>> +       writel(0x00500064, &mctl_com->mcr[3][1]);
>> +       writel(0x07000009, &mctl_com->mcr[4][0]);
>> +       writel(0x01000640, &mctl_com->mcr[4][1]);
>> +       writel(0x01000009, &mctl_com->mcr[5][0]);
>> +       writel(0x00000080, &mctl_com->mcr[5][1]);
>> +       writel(0x01000009, &mctl_com->mcr[6][0]);
>> +       writel(0x00400080, &mctl_com->mcr[6][1]);
>> +       writel(0x0100000d, &mctl_com->mcr[7][0]);
>> +       writel(0x00400080, &mctl_com->mcr[7][1]);
>> +       writel(0x0100000d, &mctl_com->mcr[8][0]);
>> +       writel(0x00400080, &mctl_com->mcr[8][1]);
>> +       writel(0x04000009, &mctl_com->mcr[9][0]);
>> +       writel(0x00400100, &mctl_com->mcr[9][1]);
>> +       writel(0x20000209, &mctl_com->mcr[10][0]);
>> +       writel(0x08001800, &mctl_com->mcr[10][1]);
>> +       writel(0x05000009, &mctl_com->mcr[11][0]);
>> +       writel(0x00400090, &mctl_com->mcr[11][1]);
>> +
>> +       writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
>> +#endif
>>  }
>>
>>  static void mctl_set_timing_params(struct dram_para *para)
>> @@ -204,7 +213,32 @@ static void mctl_set_timing_params(struct dram_para *para)
>>         writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
>>  }
>>
>> -static void mctl_zq_calibration(struct dram_para *para)
>> +#ifdef CONFIG_MACH_SUN8I_H3
>> +static u32 bin_to_mgray(int val)
>> +{
>> +       static const u8 lookup_table[32] = {
>> +               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> +               0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
>> +               0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
>> +               0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
>> +       };
>> +
>> +       return lookup_table[clamp(val, 0, 31)];
>> +}
>> +
>> +static int mgray_to_bin(u32 val)
>> +{
>> +       static const u8 lookup_table[32] = {
>> +               0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
>> +               0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
>> +               0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
>> +               0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
>> +       };
>> +
>> +       return lookup_table[val & 0x1f];
>> +}
>> +
>> +static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
>>  {
>>         struct sunxi_mctl_ctl_reg * const mctl_ctl =
>>                         (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
>> @@ -261,6 +295,7 @@ static void mctl_zq_calibration(struct dram_para *para)
>>                 writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
>>         }
>>  }
>> +#endif
>>
>>  static void mctl_set_cr(struct dram_para *para)
> 
> Can this be:
> 
> static void mctl_set_cr(struct dram_para *para, enum chip_type type)
> 
>>  {
>> @@ -286,16 +321,27 @@ static void mctl_sys_init(struct dram_para *para)
>>         clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
>>         clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
>>         clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
>> +#ifdef CONFIG_MACH_SUN50I
>> +       clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
>> +#endif
>>         udelay(10);
>>
>>         clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
>>         udelay(1000);
>>
>> +#ifdef CONFIG_MACH_SUN50I
> 
> if (type == SUN50I)
> 
>> +       clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
>> +       clrsetbits_le32(&ccm->dram_clk_cfg,
>> +                       CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
>> +                       CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL11 |
>> +                       CCM_DRAMCLK_CFG_UPD);
>> +#else
>>         clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
>>         clrsetbits_le32(&ccm->dram_clk_cfg,
>>                         CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
>>                         CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL5 |
>>                         CCM_DRAMCLK_CFG_UPD);
>> +#endif
>>         mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
>>
>>         setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
>> @@ -347,12 +393,18 @@ static int mctl_channel_init(struct dram_para *para)
>>         /* set DQS auto gating PD mode */
>>         setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
>>
>> +#if defined(CONFIG_MACH_SUN8I_H3)
>>         /* dx ddr_clk & hdr_clk dynamic mode */
>>         clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
>>
>>         /* dphy & aphy phase select 270 degree */
>>         clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
>>                         (0x1 << 10) | (0x2 << 8));
>> +#elif defined(CONFIG_MACH_SUN50I)
>> +       /* dphy & aphy phase select ? */
>> +       clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
>> +                       (0x0 << 10) | (0x3 << 8));
>> +#endif
>>
>>         /* set half DQ */
>>         if (para->bus_width != 32) {
>> @@ -367,10 +419,17 @@ static int mctl_channel_init(struct dram_para *para)
>>         mctl_set_bit_delays(para);
>>         udelay(50);
>>
>> -       mctl_zq_calibration(para);
>> +#ifdef CONFIG_MACH_SUN8I_H3
>> +       mctl_h3_zq_calibration_quirk(para);
>>
>>         mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST |
>>                       PIR_DRAMINIT | PIR_QSGATE);
>> +#else
>> +       clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
>> +
>> +       mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
>> +                     PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
>> +#endif
>>
>>         /* detect ranks and bus width */
>>         if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
>> @@ -408,7 +467,11 @@ static int mctl_channel_init(struct dram_para *para)
>>         udelay(10);
>>
>>         /* set PGCR3, CKE polarity */
>> +#ifdef CONFIG_MACH_SUN50I
>> +       writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
>> +#else
>>         writel(0x00aa0060, &mctl_ctl->pgcr[3]);
>> +#endif
>>
>>         /* power down zq calibration module for power save */
>>         setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
>> @@ -452,6 +515,7 @@ unsigned long sunxi_dram_init(void)
>>                 .row_bits = 15,
>>                 .page_size = 4096,
>>
>> +#if defined(CONFIG_MACH_SUN8I_H3)
>>                 .dx_read_delays =  {{ 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
>>                                     { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },
>>                                     { 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
>> @@ -464,6 +528,20 @@ unsigned long sunxi_dram_init(void)
>>                                 0,  0,  0,  0,  0,  0,  0,  0,
>>                                 0,  0,  0,  0,  0,  0,  0,  0,
>>                                 0,  0,  0,  0,  0,  0,  0      },
>> +#elif defined(CONFIG_MACH_SUN50I)
>> +               .dx_read_delays =  {{ 16, 16, 16, 16, 17, 16, 16, 17, 16,  1,  0 },
>> +                                   { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 },
>> +                                   { 16, 17, 17, 16, 16, 16, 16, 16, 16,  0,  0 },
>> +                                   { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 }},
>> +               .dx_write_delays = {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 15, 15 },
>> +                                   {  0,  0,  0,  0,  1,  1,  1,  1,  0, 10, 10 },
>> +                                   {  1,  0,  1,  1,  1,  1,  1,  1,  0, 11, 11 },
>> +                                   {  1,  0,  0,  1,  1,  1,  1,  1,  0, 12, 12 }},
>> +               .ac_delays = {  5,  5, 13, 10,  2,  5,  3,  3,
>> +                               0,  3,  3,  3,  1,  0,  0,  0,
>> +                               3,  4,  0,  3,  4,  1,  4,  0,
>> +                               1,  1,  0,  1, 13,  5,  4      },
>> +#endif
>>         };
>>
>>         mctl_sys_init(&para);
>> @@ -476,8 +554,15 @@ unsigned long sunxi_dram_init(void)
>>                 writel(0x00000201, &mctl_ctl->odtmap);
>>         udelay(1);
>>
>> +#ifdef CONFIG_MACH_SUN8I_H3
>>         /* odt delay */
>>         writel(0x0c000400, &mctl_ctl->odtcfg);
>> +#endif
>> +
>> +#ifdef CONFIG_MACH_SUN50I
>> +       setbits_le32(&mctl_ctl->vtfcr, (1 << 9));
>> +       clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
>> +#endif
>>
>>         /* clear credit value */
>>         setbits_le32(&mctl_com->cccr, 1 << 31);
>> --
>> 2.8.2
>>
> 
> Then:
> 
> +#ifdef CONFIG_MACH_SUN50I
> mctl_set_cr(params, SUN50I)
> #elif defined(CONFIG_MACH_SUN8I_H3)
> mctl_set_cr(params, SUN8I_H3)
> ...
> 
> Regards,
> Simon
>
Simon Glass Dec. 17, 2016, 10:48 p.m. UTC | #7
Hi Andre,

On 16 December 2016 at 10:30, Andre Przywara <andre.przywara@arm.com> wrote:
> Hi Simon,
>
> On 05/12/16 06:26, Simon Glass wrote:
>> Hi Andre,
>>
>> On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
>>> From: Jens Kuske <jenskuske@gmail.com>
>>>
>>> The A64 DRAM controller is very similar to the H3 one,
>>> so the code can be reused with some small changes.
>>
>> Yes but it makes the code a mess. Can you avoid putting #iifdefs everywhere?
>
> Sure ...
>
>> Since it is a static function I wonder if you can instead use a
>> function parameter which defines the chip to support, and the compiler
>> will eliminate the unused code?
>
> I like that idea. Actually I went ahead and converted the file to this
> approach and it looks much nicer, especially since I added support for a
> third DRAM controller on top.
> Also it opens the doors to potentially serve multiple variants in one
> binary (one day ...)
>
> I took the freedom to use the Allwinner SoCID (a 16-bit value (mostly)
> unique to a certain SoC) as the variant identifier.
> That doesn't make any difference for this passing-to-static-functions
> case, but avoids inventing identifiers and can be easily reused with
> auto-detection.
>

OK great I'm pleased it worked out.

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index be9fcfd..3f87672 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -322,6 +322,7 @@  struct sunxi_ccm_reg {
 #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
 #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
 #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
+#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
 #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
 #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
 #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index e0be744..53e6d47 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -24,7 +24,7 @@ 
 #include <asm/arch/dram_sun8i_a33.h>
 #elif defined(CONFIG_MACH_SUN8I_A83T)
 #include <asm/arch/dram_sun8i_a83t.h>
-#elif defined(CONFIG_MACH_SUN8I_H3)
+#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
 #include <asm/arch/dram_sun8i_h3.h>
 #elif defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/dram_sun9i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
index 867fd12..b0e5d93 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
@@ -15,7 +15,8 @@ 
 
 struct sunxi_mctl_com_reg {
 	u32 cr;			/* 0x00 control register */
-	u8 res0[0xc];		/* 0x04 */
+	u8 res0[0x8];		/* 0x04 */
+	u32 tmr;		/* 0x0c (A64 only) */
 	u32 mcr[16][2];		/* 0x10 */
 	u32 bwcr;		/* 0x90 bandwidth control register */
 	u32 maer;		/* 0x94 master enable register */
@@ -32,7 +33,9 @@  struct sunxi_mctl_com_reg {
 	u32 swoffr;		/* 0xc4 */
 	u8 res2[0x8];		/* 0xc8 */
 	u32 cccr;		/* 0xd0 */
-	u8 res3[0x72c];		/* 0xd4 */
+	u8 res3[0x54];		/* 0xd4 */
+	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
+	u8 res4[0x6cc];		/* 0x134 */
 	u32 protect;		/* 0x800 */
 };
 
@@ -81,7 +84,8 @@  struct sunxi_mctl_ctl_reg {
 	u32 rfshtmg;		/* 0x90 refresh timing */
 	u32 rfshctl1;		/* 0x94 */
 	u32 pwrtmg;		/* 0x98 */
-	u8 res3[0x20];		/* 0x9c */
+	u8 res3[0x1c];		/* 0x9c */
+	u32 vtfcr;		/* 0xb8 (A64 only) */
 	u32 dqsgmr;		/* 0xbc */
 	u32 dtcr;		/* 0xc0 */
 	u32 dtar[4];		/* 0xc4 */
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index e73114e..7daba11 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -50,4 +50,5 @@  obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
 obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
 obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
 obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
+obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
 endif
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
index 80cfc0b..99f515d 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -217,7 +217,7 @@  done:
 }
 #endif
 
-#ifdef CONFIG_MACH_SUN8I_A33
+#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
 void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
 {
 	struct sunxi_ccm_reg * const ccm =
diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
index 1647d76..2dc2071 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
@@ -32,30 +32,6 @@  static inline int ns_to_t(int nanoseconds)
 	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
 }
 
-static u32 bin_to_mgray(int val)
-{
-	static const u8 lookup_table[32] = {
-		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
-		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
-		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
-		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
-	};
-
-	return lookup_table[clamp(val, 0, 31)];
-}
-
-static int mgray_to_bin(u32 val)
-{
-	static const u8 lookup_table[32] = {
-		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
-		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
-		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
-		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
-	};
-
-	return lookup_table[val & 0x1f];
-}
-
 static void mctl_phy_init(u32 val)
 {
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
@@ -91,8 +67,9 @@  static void mctl_set_master_priority(void)
 	struct sunxi_mctl_com_reg * const mctl_com =
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 	/* enable bandwidth limit windows and set windows size 1us */
-	writel(0x00010190, &mctl_com->bwcr);
+	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
 
 	/* set cpu high priority */
 	writel(0x00000001, &mctl_com->mapr);
@@ -121,6 +98,38 @@  static void mctl_set_master_priority(void)
 	writel(0x04001800, &mctl_com->mcr[10][1]);
 	writel(0x04000009, &mctl_com->mcr[11][0]);
 	writel(0x00400120, &mctl_com->mcr[11][1]);
+#elif defined(CONFIG_MACH_SUN50I)
+	/* enable bandwidth limit windows and set windows size 1us */
+	writel(399, &mctl_com->tmr);
+	writel((1 << 16), &mctl_com->bwcr);
+
+	writel(0x00a0000d, &mctl_com->mcr[0][0]);
+	writel(0x00500064, &mctl_com->mcr[0][1]);
+	writel(0x06000009, &mctl_com->mcr[1][0]);
+	writel(0x01000578, &mctl_com->mcr[1][1]);
+	writel(0x0200000d, &mctl_com->mcr[2][0]);
+	writel(0x00600100, &mctl_com->mcr[2][1]);
+	writel(0x01000009, &mctl_com->mcr[3][0]);
+	writel(0x00500064, &mctl_com->mcr[3][1]);
+	writel(0x07000009, &mctl_com->mcr[4][0]);
+	writel(0x01000640, &mctl_com->mcr[4][1]);
+	writel(0x01000009, &mctl_com->mcr[5][0]);
+	writel(0x00000080, &mctl_com->mcr[5][1]);
+	writel(0x01000009, &mctl_com->mcr[6][0]);
+	writel(0x00400080, &mctl_com->mcr[6][1]);
+	writel(0x0100000d, &mctl_com->mcr[7][0]);
+	writel(0x00400080, &mctl_com->mcr[7][1]);
+	writel(0x0100000d, &mctl_com->mcr[8][0]);
+	writel(0x00400080, &mctl_com->mcr[8][1]);
+	writel(0x04000009, &mctl_com->mcr[9][0]);
+	writel(0x00400100, &mctl_com->mcr[9][1]);
+	writel(0x20000209, &mctl_com->mcr[10][0]);
+	writel(0x08001800, &mctl_com->mcr[10][1]);
+	writel(0x05000009, &mctl_com->mcr[11][0]);
+	writel(0x00400090, &mctl_com->mcr[11][1]);
+
+	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
+#endif
 }
 
 static void mctl_set_timing_params(struct dram_para *para)
@@ -204,7 +213,32 @@  static void mctl_set_timing_params(struct dram_para *para)
 	writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
 }
 
-static void mctl_zq_calibration(struct dram_para *para)
+#ifdef CONFIG_MACH_SUN8I_H3
+static u32 bin_to_mgray(int val)
+{
+	static const u8 lookup_table[32] = {
+		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
+		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
+		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
+		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
+	};
+
+	return lookup_table[clamp(val, 0, 31)];
+}
+
+static int mgray_to_bin(u32 val)
+{
+	static const u8 lookup_table[32] = {
+		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
+		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
+		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
+		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
+	};
+
+	return lookup_table[val & 0x1f];
+}
+
+static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
 {
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
 			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
@@ -261,6 +295,7 @@  static void mctl_zq_calibration(struct dram_para *para)
 		writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
 	}
 }
+#endif
 
 static void mctl_set_cr(struct dram_para *para)
 {
@@ -286,16 +321,27 @@  static void mctl_sys_init(struct dram_para *para)
 	clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
 	clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
 	clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
+#ifdef CONFIG_MACH_SUN50I
+	clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
+#endif
 	udelay(10);
 
 	clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
 	udelay(1000);
 
+#ifdef CONFIG_MACH_SUN50I
+	clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
+	clrsetbits_le32(&ccm->dram_clk_cfg,
+			CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
+			CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL11 |
+			CCM_DRAMCLK_CFG_UPD);
+#else
 	clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
 	clrsetbits_le32(&ccm->dram_clk_cfg,
 			CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
 			CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL5 |
 			CCM_DRAMCLK_CFG_UPD);
+#endif
 	mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
 
 	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
@@ -347,12 +393,18 @@  static int mctl_channel_init(struct dram_para *para)
 	/* set DQS auto gating PD mode */
 	setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 	/* dx ddr_clk & hdr_clk dynamic mode */
 	clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
 
 	/* dphy & aphy phase select 270 degree */
 	clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
 			(0x1 << 10) | (0x2 << 8));
+#elif defined(CONFIG_MACH_SUN50I)
+	/* dphy & aphy phase select ? */
+	clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
+			(0x0 << 10) | (0x3 << 8));
+#endif
 
 	/* set half DQ */
 	if (para->bus_width != 32) {
@@ -367,10 +419,17 @@  static int mctl_channel_init(struct dram_para *para)
 	mctl_set_bit_delays(para);
 	udelay(50);
 
-	mctl_zq_calibration(para);
+#ifdef CONFIG_MACH_SUN8I_H3
+	mctl_h3_zq_calibration_quirk(para);
 
 	mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST |
 		      PIR_DRAMINIT | PIR_QSGATE);
+#else
+	clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
+
+	mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
+		      PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
+#endif
 
 	/* detect ranks and bus width */
 	if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
@@ -408,7 +467,11 @@  static int mctl_channel_init(struct dram_para *para)
 	udelay(10);
 
 	/* set PGCR3, CKE polarity */
+#ifdef CONFIG_MACH_SUN50I
+	writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
+#else
 	writel(0x00aa0060, &mctl_ctl->pgcr[3]);
+#endif
 
 	/* power down zq calibration module for power save */
 	setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
@@ -452,6 +515,7 @@  unsigned long sunxi_dram_init(void)
 		.row_bits = 15,
 		.page_size = 4096,
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 		.dx_read_delays =  {{ 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
 		                    { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },
 		                    { 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
@@ -464,6 +528,20 @@  unsigned long sunxi_dram_init(void)
 		                0,  0,  0,  0,  0,  0,  0,  0,
 		                0,  0,  0,  0,  0,  0,  0,  0,
 		                0,  0,  0,  0,  0,  0,  0      },
+#elif defined(CONFIG_MACH_SUN50I)
+		.dx_read_delays =  {{ 16, 16, 16, 16, 17, 16, 16, 17, 16,  1,  0 },
+		                    { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 },
+		                    { 16, 17, 17, 16, 16, 16, 16, 16, 16,  0,  0 },
+		                    { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 }},
+		.dx_write_delays = {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 15, 15 },
+		                    {  0,  0,  0,  0,  1,  1,  1,  1,  0, 10, 10 },
+		                    {  1,  0,  1,  1,  1,  1,  1,  1,  0, 11, 11 },
+		                    {  1,  0,  0,  1,  1,  1,  1,  1,  0, 12, 12 }},
+		.ac_delays = {  5,  5, 13, 10,  2,  5,  3,  3,
+		                0,  3,  3,  3,  1,  0,  0,  0,
+		                3,  4,  0,  3,  4,  1,  4,  0,
+		                1,  1,  0,  1, 13,  5,  4      },
+#endif
 	};
 
 	mctl_sys_init(&para);
@@ -476,8 +554,15 @@  unsigned long sunxi_dram_init(void)
 		writel(0x00000201, &mctl_ctl->odtmap);
 	udelay(1);
 
+#ifdef CONFIG_MACH_SUN8I_H3
 	/* odt delay */
 	writel(0x0c000400, &mctl_ctl->odtcfg);
+#endif
+
+#ifdef CONFIG_MACH_SUN50I
+	setbits_le32(&mctl_ctl->vtfcr, (1 << 9));
+	clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
+#endif
 
 	/* clear credit value */
 	setbits_le32(&mctl_com->cccr, 1 << 31);