[U-Boot] [PATCH v2 15/23] sunxi: A64: use H3 DRAM initialization code for A64
Andre Przywara
andre.przywara at arm.com
Mon Dec 12 17:06:39 CET 2016
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 at 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 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) */
>>>
>>> #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.
More information about the U-Boot
mailing list