[RFC PATCH 07/13] sunxi: add support for R329 DRAM controller

Samuel Holland samuel at sholland.org
Sat Nov 6 04:06:12 CET 2021


On 7/22/21 1:30 AM, Icenowy Zheng wrote:
> R329 has a new DRAM controller, which looks like a combination of the
> H6/H616 MCTL_COM part and the SUNXI_DW MCTL_CTL part. This design has
> already got reused by Allwinner, and V831/V833 SoCs have similar
> memory controller.
> 
> Add support for it. To prepare for further support of other SoCs,
> routines with socid parameter are added, although not checked now.
> 
> Signed-off-by: Icenowy Zheng <icenowy at sipeed.com>

I cannot really review the DRAM init part. But it works, so that's
probably good enough.

Tested-by: Samuel Holland <samuel at sholland.org>

There are a couple of magic values I happen to have an explanation for:

> diff --git a/arch/arm/mach-sunxi/dram_sun50i_r329.c b/arch/arm/mach-sunxi/dram_sun50i_r329.c
> new file mode 100644
> index 0000000000..730883999c
> --- /dev/null
> +++ b/arch/arm/mach-sunxi/dram_sun50i_r329.c
> ...> +unsigned long sunxi_dram_init(void)
> +{
> +	struct sunxi_mctl_com_reg * const mctl_com =
> +			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> +	struct sunxi_mctl_ctl_reg * const mctl_ctl =
> +			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
> +
> +	struct dram_para para = {
> +		.dual_rank = 0,
> +		.bus_full_width = 1,
> +		.row_bits = 16,
> +		.bank_bits = 3,
> +		.page_size = 8192,
> +
> +		.dx_read_delays  = SUN50I_R329_DX_READ_DELAYS,
> +		.dx_write_delays = SUN50I_R329_DX_WRITE_DELAYS,
> +		.ac_delays	 = SUN50I_R329_AC_DELAYS,
> +	};
> +
> +	/* Unknown magic */
> +	writel(0x10, 0x07010250);

This is VDD_SYS_POWEROFF_GATING_REG, presumably disabling pad hold.

> +	writel(0x330000, 0x07010310);
> +	writel(0x330003, 0x07010310);

This is a resistor calibration process. See here:

https://github.com/smaeul/sun20i_d1_spl/blob/342cb1d8/include/arch/cpu_ncat.h#L172
https://github.com/smaeul/sun20i_d1_spl/blob/342cb1d8/board/sun20iw1p1/clock.c#L186

Some other BSP code has:

#define REG_CALIB_CONTROL_REG           0x0310
#define OHMS200_REG                     0x0314
#define OHMS240_REG                     0x0318
#define REG_CALIB_STATUS_REG            0x031c

So this suggests we are calibrating the termination resistors.

Regards,
Samuel

> +
> +#if defined(CONFIG_MACH_SUN50I_R329)
> +	uint16_t socid = SOCID_R329;
> +#endif
> +
> +	mctl_sys_init(&para);
> +	if (mctl_channel_init(socid, &para))
> +		return 0;
> +
> +	udelay(1);
> +
> +	clrbits_le32(&mctl_ctl->unk_0x0a0, 0xffff);
> +	clrbits_le32(&mctl_ctl->pwrctl, 0x1);
> +
> +	/* HDR/DDR dynamic mode */
> +	clrbits_le32(&mctl_ctl->pgcr[0], 0xf000);
> +
> +	/* power down zq calibration module for power save */
> +	setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
> +
> +	/* DQ hold disable (tpr13[26] == 1) */
> +	clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
> +
> +	mctl_auto_detect_dram_size(&para);
> +	mctl_apply_para(&para);
> +
> +	/* enable master access */
> +	writel(0xffffffff, &mctl_com->maer0);
> +	writel(0x7f, &mctl_com->maer1);
> +	writel(0xffff, &mctl_com->maer2);
> +
> +	return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
> +	       (para.dual_rank ? 2 : 1);
> +}


More information about the U-Boot mailing list