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

Andre Przywara andre.przywara at arm.com
Fri Dec 16 18:30:23 CET 2016


Hi Simon,

On 05/12/16 06:26, Simon Glass wrote:
> Hi Andre,
> 
> On 4 December 2016 at 18:52, Andre Przywara <andre.przywara at arm.com> wrote:
>> From: Jens Kuske <jenskuske at 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 at gmail.com>
>> Signed-off-by: Andre Przywara <andre.przywara at 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
> 


More information about the U-Boot mailing list