sunxi: Add F1C100s DRAM initial support
Add support for F1C100s internal dram controller. Signed-off-by: Icenowy Zheng <icenowy@aosc.io> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
		
							parent
							
								
									5d35f0f254
								
							
						
					
					
						commit
						645ee3c25d
					
				| 
						 | 
					@ -31,6 +31,8 @@
 | 
				
			||||||
#include <asm/arch/dram_sun50i_h6.h>
 | 
					#include <asm/arch/dram_sun50i_h6.h>
 | 
				
			||||||
#elif defined(CONFIG_MACH_SUN50I_H616)
 | 
					#elif defined(CONFIG_MACH_SUN50I_H616)
 | 
				
			||||||
#include <asm/arch/dram_sun50i_h616.h>
 | 
					#include <asm/arch/dram_sun50i_h616.h>
 | 
				
			||||||
 | 
					#elif defined(CONFIG_MACH_SUNIV)
 | 
				
			||||||
 | 
					#include <asm/arch/dram_suniv.h>
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#include <asm/arch/dram_sun4i.h>
 | 
					#include <asm/arch/dram_sun4i.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0+ */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * suniv DRAM controller register definition
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Based on xboot's arch/arm32/mach-f1c100s/sys-dram.c, which is:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PIO_SDRAM_DRV			(0x2c0)
 | 
				
			||||||
 | 
					#define PIO_SDRAM_PULL			(0x2c4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DRAM_SCONR			(0x00)
 | 
				
			||||||
 | 
					#define DRAM_STMG0R			(0x04)
 | 
				
			||||||
 | 
					#define DRAM_STMG1R			(0x08)
 | 
				
			||||||
 | 
					#define DRAM_SCTLR			(0x0c)
 | 
				
			||||||
 | 
					#define DRAM_SREFR			(0x10)
 | 
				
			||||||
 | 
					#define DRAM_SEXTMR			(0x14)
 | 
				
			||||||
 | 
					#define DRAM_DDLYR			(0x24)
 | 
				
			||||||
 | 
					#define DRAM_DADRR			(0x28)
 | 
				
			||||||
 | 
					#define DRAM_DVALR			(0x2c)
 | 
				
			||||||
 | 
					#define DRAM_DRPTR0			(0x30)
 | 
				
			||||||
 | 
					#define DRAM_DRPTR1			(0x34)
 | 
				
			||||||
 | 
					#define DRAM_DRPTR2			(0x38)
 | 
				
			||||||
 | 
					#define DRAM_DRPTR3			(0x3c)
 | 
				
			||||||
 | 
					#define DRAM_SEFR			(0x40)
 | 
				
			||||||
 | 
					#define DRAM_MAE			(0x44)
 | 
				
			||||||
 | 
					#define DRAM_ASPR			(0x48)
 | 
				
			||||||
 | 
					#define DRAM_SDLY0			(0x4C)
 | 
				
			||||||
 | 
					#define DRAM_SDLY1			(0x50)
 | 
				
			||||||
 | 
					#define DRAM_SDLY2			(0x54)
 | 
				
			||||||
 | 
					#define DRAM_MCR0			(0x100)
 | 
				
			||||||
 | 
					#define DRAM_MCR1			(0x104)
 | 
				
			||||||
 | 
					#define DRAM_MCR2			(0x108)
 | 
				
			||||||
 | 
					#define DRAM_MCR3			(0x10c)
 | 
				
			||||||
 | 
					#define DRAM_MCR4			(0x110)
 | 
				
			||||||
 | 
					#define DRAM_MCR5			(0x114)
 | 
				
			||||||
 | 
					#define DRAM_MCR6			(0x118)
 | 
				
			||||||
 | 
					#define DRAM_MCR7			(0x11c)
 | 
				
			||||||
 | 
					#define DRAM_MCR8			(0x120)
 | 
				
			||||||
 | 
					#define DRAM_MCR9			(0x124)
 | 
				
			||||||
 | 
					#define DRAM_MCR10			(0x128)
 | 
				
			||||||
 | 
					#define DRAM_MCR11			(0x12c)
 | 
				
			||||||
 | 
					#define DRAM_BWCR			(0x140)
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ obj-y	+= dram_helpers.o
 | 
				
			||||||
obj-y	+= pinmux.o
 | 
					obj-y	+= pinmux.o
 | 
				
			||||||
obj-$(CONFIG_SUN6I_PRCM)	+= prcm.o
 | 
					obj-$(CONFIG_SUN6I_PRCM)	+= prcm.o
 | 
				
			||||||
obj-$(CONFIG_AXP_PMIC_BUS)	+= pmic_bus.o
 | 
					obj-$(CONFIG_AXP_PMIC_BUS)	+= pmic_bus.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_MACH_SUNIV)	+= clock_sun6i.o
 | 
				
			||||||
obj-$(CONFIG_MACH_SUN4I)	+= clock_sun4i.o
 | 
					obj-$(CONFIG_MACH_SUN4I)	+= clock_sun4i.o
 | 
				
			||||||
obj-$(CONFIG_MACH_SUN5I)	+= clock_sun4i.o
 | 
					obj-$(CONFIG_MACH_SUN5I)	+= clock_sun4i.o
 | 
				
			||||||
obj-$(CONFIG_MACH_SUN6I)	+= clock_sun6i.o
 | 
					obj-$(CONFIG_MACH_SUN6I)	+= clock_sun6i.o
 | 
				
			||||||
| 
						 | 
					@ -30,6 +31,7 @@ obj-y	+= timer.o
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef CONFIG_SPL_BUILD
 | 
					ifdef CONFIG_SPL_BUILD
 | 
				
			||||||
 | 
					obj-$(CONFIG_MACH_SUNIV)	+= dram_suniv.o
 | 
				
			||||||
obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
 | 
					obj-$(CONFIG_DRAM_SUN4I)	+= dram_sun4i.o
 | 
				
			||||||
obj-$(CONFIG_DRAM_SUN6I)	+= dram_sun6i.o
 | 
					obj-$(CONFIG_DRAM_SUN6I)	+= dram_sun6i.o
 | 
				
			||||||
obj-$(CONFIG_DRAM_SUN8I_A23)	+= dram_sun8i_a23.o
 | 
					obj-$(CONFIG_DRAM_SUN8I_A23)	+= dram_sun8i_a23.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,10 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Test if memory at offset offset matches memory at begin of DRAM
 | 
					 * Test if memory at offset offset matches memory at begin of DRAM
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Note: dsb() is not available on ARMv5 in Thumb mode
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef CONFIG_MACH_SUNIV
 | 
				
			||||||
bool mctl_mem_matches(u32 offset)
 | 
					bool mctl_mem_matches(u32 offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Try to write different values to RAM at two addresses */
 | 
						/* Try to write different values to RAM at two addresses */
 | 
				
			||||||
| 
						 | 
					@ -37,3 +40,4 @@ bool mctl_mem_matches(u32 offset)
 | 
				
			||||||
	return readl(CONFIG_SYS_SDRAM_BASE) ==
 | 
						return readl(CONFIG_SYS_SDRAM_BASE) ==
 | 
				
			||||||
	       readl((ulong)CONFIG_SYS_SDRAM_BASE + offset);
 | 
						       readl((ulong)CONFIG_SYS_SDRAM_BASE + offset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,420 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: (GPL-2.0+)
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * suniv DRAM initialization
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Based on xboot's arch/arm32/mach-f1c100s/sys-dram.c, which is:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <asm/io.h>
 | 
				
			||||||
 | 
					#include <asm/arch/clock.h>
 | 
				
			||||||
 | 
					#include <asm/arch/dram.h>
 | 
				
			||||||
 | 
					#include <asm/arch/gpio.h>
 | 
				
			||||||
 | 
					#include <linux/bitops.h>
 | 
				
			||||||
 | 
					#include <linux/delay.h>
 | 
				
			||||||
 | 
					#include <hang.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SDR_T_CAS			(0x2)
 | 
				
			||||||
 | 
					#define SDR_T_RAS			(0x8)
 | 
				
			||||||
 | 
					#define SDR_T_RCD			(0x3)
 | 
				
			||||||
 | 
					#define SDR_T_RP			(0x3)
 | 
				
			||||||
 | 
					#define SDR_T_WR			(0x3)
 | 
				
			||||||
 | 
					#define SDR_T_RFC			(0xd)
 | 
				
			||||||
 | 
					#define SDR_T_XSR			(0xf9)
 | 
				
			||||||
 | 
					#define SDR_T_RC			(0xb)
 | 
				
			||||||
 | 
					#define SDR_T_INIT			(0x8)
 | 
				
			||||||
 | 
					#define SDR_T_INIT_REF			(0x7)
 | 
				
			||||||
 | 
					#define SDR_T_WTR			(0x2)
 | 
				
			||||||
 | 
					#define SDR_T_RRD			(0x2)
 | 
				
			||||||
 | 
					#define SDR_T_XP			(0x0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum dram_type {
 | 
				
			||||||
 | 
						DRAM_TYPE_SDR	= 0,
 | 
				
			||||||
 | 
						DRAM_TYPE_DDR	= 1,
 | 
				
			||||||
 | 
						/* Not supported yet. */
 | 
				
			||||||
 | 
						DRAM_TYPE_MDDR	= 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dram_para {
 | 
				
			||||||
 | 
						u32 size;		/* dram size (unit: MByte) */
 | 
				
			||||||
 | 
						u32 clk;		/* dram work clock (unit: MHz) */
 | 
				
			||||||
 | 
						u32 access_mode;	/* 0: interleave mode 1: sequence mode */
 | 
				
			||||||
 | 
						u32 cs_num;		/* dram chip count  1: one chip  2: two chip */
 | 
				
			||||||
 | 
						u32 ddr8_remap;		/* for 8bits data width DDR 0: normal  1: 8bits */
 | 
				
			||||||
 | 
						enum dram_type sdr_ddr;
 | 
				
			||||||
 | 
						u32 bwidth;		/* dram bus width */
 | 
				
			||||||
 | 
						u32 col_width;		/* column address width */
 | 
				
			||||||
 | 
						u32 row_width;		/* row address width */
 | 
				
			||||||
 | 
						u32 bank_size;		/* dram bank count */
 | 
				
			||||||
 | 
						u32 cas;		/* dram cas */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dram_para suniv_dram_para = {
 | 
				
			||||||
 | 
						.size = 32,
 | 
				
			||||||
 | 
						.clk = 156,
 | 
				
			||||||
 | 
						.access_mode = 1,
 | 
				
			||||||
 | 
						.cs_num = 1,
 | 
				
			||||||
 | 
						.ddr8_remap = 0,
 | 
				
			||||||
 | 
						.sdr_ddr = DRAM_TYPE_DDR,
 | 
				
			||||||
 | 
						.bwidth = 16,
 | 
				
			||||||
 | 
						.col_width = 10,
 | 
				
			||||||
 | 
						.row_width = 13,
 | 
				
			||||||
 | 
						.bank_size = 4,
 | 
				
			||||||
 | 
						.cas = 0x3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dram_initial(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int time = 0xffffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR, 0x1);
 | 
				
			||||||
 | 
						while ((readl(SUNXI_DRAMC_BASE + DRAM_SCTLR) & 0x1) && time--) {
 | 
				
			||||||
 | 
							if (time == 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dram_delay_scan(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int time = 0xffffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setbits_le32(SUNXI_DRAMC_BASE + DRAM_DDLYR, 0x1);
 | 
				
			||||||
 | 
						while ((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) & 0x1) && time--) {
 | 
				
			||||||
 | 
							if (time == 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void dram_set_autofresh_cycle(u32 clk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 val = 0;
 | 
				
			||||||
 | 
						u32 row = 0;
 | 
				
			||||||
 | 
						u32 temp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						row = readl(SUNXI_DRAMC_BASE + DRAM_SCONR);
 | 
				
			||||||
 | 
						row &= 0x1e0;
 | 
				
			||||||
 | 
						row >>= 0x5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (row == 0xc) {
 | 
				
			||||||
 | 
							if (clk >= 1000000) {
 | 
				
			||||||
 | 
								temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
 | 
				
			||||||
 | 
								while (temp >= (10000000 >> 6)) {
 | 
				
			||||||
 | 
									temp -= (10000000 >> 6);
 | 
				
			||||||
 | 
									val++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								val = (clk * 499) >> 6;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if (row == 0xb) {
 | 
				
			||||||
 | 
							if (clk >= 1000000) {
 | 
				
			||||||
 | 
								temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
 | 
				
			||||||
 | 
								while (temp >= (10000000 >> 7)) {
 | 
				
			||||||
 | 
									temp -= (10000000 >> 7);
 | 
				
			||||||
 | 
									val++;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								val = (clk * 499) >> 5;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						writel(val, SUNXI_DRAMC_BASE + DRAM_SREFR);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dram_para_setup(struct dram_para *para)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 val = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = (para->ddr8_remap) | (0x1 << 1) |
 | 
				
			||||||
 | 
						      ((para->bank_size >> 2) << 3) |
 | 
				
			||||||
 | 
						      ((para->cs_num >> 1) << 4) |
 | 
				
			||||||
 | 
						      ((para->row_width - 1) << 5) |
 | 
				
			||||||
 | 
						      ((para->col_width - 1) << 9) |
 | 
				
			||||||
 | 
						      ((para->sdr_ddr ? (para->bwidth >> 4) : (para->bwidth >> 5)) << 13) |
 | 
				
			||||||
 | 
						      (para->access_mode << 15) |
 | 
				
			||||||
 | 
						      (para->sdr_ddr << 16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writel(val, SUNXI_DRAMC_BASE + DRAM_SCONR);
 | 
				
			||||||
 | 
						setbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR, 0x1 << 19);
 | 
				
			||||||
 | 
						return dram_initial();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 dram_check_delay(u32 bwidth)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 dsize;
 | 
				
			||||||
 | 
						int i, j;
 | 
				
			||||||
 | 
						u32 num = 0;
 | 
				
			||||||
 | 
						u32 dflag = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dsize = ((bwidth == 16) ? 4 : 2);
 | 
				
			||||||
 | 
						for (i = 0; i < dsize; i++) {
 | 
				
			||||||
 | 
							if (i == 0)
 | 
				
			||||||
 | 
								dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR0);
 | 
				
			||||||
 | 
							else if (i == 1)
 | 
				
			||||||
 | 
								dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR1);
 | 
				
			||||||
 | 
							else if (i == 2)
 | 
				
			||||||
 | 
								dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR2);
 | 
				
			||||||
 | 
							else if (i == 3)
 | 
				
			||||||
 | 
								dflag = readl(SUNXI_DRAMC_BASE + DRAM_DRPTR3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (j = 0; j < 32; j++) {
 | 
				
			||||||
 | 
								if (dflag & 0x1)
 | 
				
			||||||
 | 
									num++;
 | 
				
			||||||
 | 
								dflag >>= 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return num;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int sdr_readpipe_scan(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 k = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (k = 0; k < 32; k++)
 | 
				
			||||||
 | 
							writel(k, CONFIG_SYS_SDRAM_BASE + 4 * k);
 | 
				
			||||||
 | 
						for (k = 0; k < 32; k++) {
 | 
				
			||||||
 | 
							if (readl(CONFIG_SYS_SDRAM_BASE + 4 * k) != k)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 sdr_readpipe_select(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 value = 0;
 | 
				
			||||||
 | 
						u32 i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
							clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
 | 
				
			||||||
 | 
									0x7 << 6, i << 6);
 | 
				
			||||||
 | 
							if (sdr_readpipe_scan()) {
 | 
				
			||||||
 | 
								value = i;
 | 
				
			||||||
 | 
								return value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 dram_check_type(struct dram_para *para)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 times = 0;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
							clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
 | 
				
			||||||
 | 
									0x7 << 6, i << 6);
 | 
				
			||||||
 | 
							dram_delay_scan();
 | 
				
			||||||
 | 
							if (readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) & 0x30)
 | 
				
			||||||
 | 
								times++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (times == 8) {
 | 
				
			||||||
 | 
							para->sdr_ddr = DRAM_TYPE_SDR;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						para->sdr_ddr = DRAM_TYPE_DDR;
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 dram_scan_readpipe(struct dram_para *para)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 rp_best = 0, rp_val = 0;
 | 
				
			||||||
 | 
						u32 readpipe[8];
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (para->sdr_ddr == DRAM_TYPE_DDR) {
 | 
				
			||||||
 | 
							for (i = 0; i < 8; i++) {
 | 
				
			||||||
 | 
								clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
 | 
				
			||||||
 | 
										0x7 << 6, i << 6);
 | 
				
			||||||
 | 
								dram_delay_scan();
 | 
				
			||||||
 | 
								readpipe[i] = 0;
 | 
				
			||||||
 | 
								if ((((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) >> 4) & 0x3) == 0x0) &&
 | 
				
			||||||
 | 
								    (((readl(SUNXI_DRAMC_BASE + DRAM_DDLYR) >> 4) & 0x1) == 0x0))
 | 
				
			||||||
 | 
									readpipe[i] = dram_check_delay(para->bwidth);
 | 
				
			||||||
 | 
								if (rp_val < readpipe[i]) {
 | 
				
			||||||
 | 
									rp_val = readpipe[i];
 | 
				
			||||||
 | 
									rp_best = i;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
 | 
				
			||||||
 | 
									0x7 << 6, rp_best << 6);
 | 
				
			||||||
 | 
							dram_delay_scan();
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							clrbits_le32(SUNXI_DRAMC_BASE + DRAM_SCONR,
 | 
				
			||||||
 | 
								     (0x1 << 16) | (0x3 << 13));
 | 
				
			||||||
 | 
							rp_best = sdr_readpipe_select();
 | 
				
			||||||
 | 
							clrsetbits_le32(SUNXI_DRAMC_BASE + DRAM_SCTLR,
 | 
				
			||||||
 | 
									0x7 << 6, rp_best << 6);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u32 dram_get_dram_size(struct dram_para *para)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 colflag = 10, rowflag = 13;
 | 
				
			||||||
 | 
						u32 val1 = 0;
 | 
				
			||||||
 | 
						u32 count = 0;
 | 
				
			||||||
 | 
						u32 addr1, addr2;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						para->col_width = colflag;
 | 
				
			||||||
 | 
						para->row_width = rowflag;
 | 
				
			||||||
 | 
						dram_para_setup(para);
 | 
				
			||||||
 | 
						dram_scan_readpipe(para);
 | 
				
			||||||
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
 | 
							*((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x200 + i)) = 0x11;
 | 
				
			||||||
 | 
							*((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x600 + i)) = 0x22;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
 | 
							val1 = *((u8 *)(CONFIG_SYS_SDRAM_BASE + 0x200 + i));
 | 
				
			||||||
 | 
							if (val1 == 0x22)
 | 
				
			||||||
 | 
								count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (count == 32)
 | 
				
			||||||
 | 
							colflag = 9;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							colflag = 10;
 | 
				
			||||||
 | 
						count = 0;
 | 
				
			||||||
 | 
						para->col_width = colflag;
 | 
				
			||||||
 | 
						para->row_width = rowflag;
 | 
				
			||||||
 | 
						dram_para_setup(para);
 | 
				
			||||||
 | 
						if (colflag == 10) {
 | 
				
			||||||
 | 
							addr1 = CONFIG_SYS_SDRAM_BASE + 0x400000;
 | 
				
			||||||
 | 
							addr2 = CONFIG_SYS_SDRAM_BASE + 0xc00000;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							addr1 = CONFIG_SYS_SDRAM_BASE + 0x200000;
 | 
				
			||||||
 | 
							addr2 = CONFIG_SYS_SDRAM_BASE + 0x600000;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
 | 
							*((u8 *)(addr1 + i)) = 0x33;
 | 
				
			||||||
 | 
							*((u8 *)(addr2 + i)) = 0x44;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < 32; i++) {
 | 
				
			||||||
 | 
							val1 = *((u8 *)(addr1 + i));
 | 
				
			||||||
 | 
							if (val1 == 0x44)
 | 
				
			||||||
 | 
								count++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (count == 32)
 | 
				
			||||||
 | 
							rowflag = 12;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							rowflag = 13;
 | 
				
			||||||
 | 
						para->col_width = colflag;
 | 
				
			||||||
 | 
						para->row_width = rowflag;
 | 
				
			||||||
 | 
						if (para->row_width != 13)
 | 
				
			||||||
 | 
							para->size = 16;
 | 
				
			||||||
 | 
						else if (para->col_width == 10)
 | 
				
			||||||
 | 
							para->size = 64;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							para->size = 32;
 | 
				
			||||||
 | 
						dram_set_autofresh_cycle(para->clk);
 | 
				
			||||||
 | 
						para->access_mode = 0;
 | 
				
			||||||
 | 
						dram_para_setup(para);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void simple_dram_check(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						volatile u32 *dram = (u32 *)CONFIG_SYS_SDRAM_BASE;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 0x40; i++)
 | 
				
			||||||
 | 
							dram[i] = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 0x40; i++) {
 | 
				
			||||||
 | 
							if (dram[i] != i) {
 | 
				
			||||||
 | 
								printf("DRAM initialization failed: dram[0x%x] != 0x%x.", i, dram[i]);
 | 
				
			||||||
 | 
								hang();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 0x10000; i += 0x40)
 | 
				
			||||||
 | 
							dram[i] = i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 0x10000; i += 0x40) {
 | 
				
			||||||
 | 
							if (dram[i] != i) {
 | 
				
			||||||
 | 
								printf("DRAM initialization failed: dram[0x%x] != 0x%x.", i, dram[i]);
 | 
				
			||||||
 | 
								hang();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void do_dram_init(struct dram_para *para)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sunxi_ccm_reg * const ccm =
 | 
				
			||||||
 | 
							(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 | 
				
			||||||
 | 
						u32 val;
 | 
				
			||||||
 | 
						u8 m; /* PLL_DDR clock factor */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sunxi_gpio_set_cfgpin(SUNXI_GPB(3), 0x7);
 | 
				
			||||||
 | 
						mdelay(5);
 | 
				
			||||||
 | 
						/* TODO: dig out what's them... some analog register? */
 | 
				
			||||||
 | 
						if ((para->cas >> 3) & 0x1)
 | 
				
			||||||
 | 
							setbits_le32(SUNXI_PIO_BASE + 0x2c4, (0x1 << 23) | (0x20 << 17));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (para->clk >= 144 && para->clk <= 180)
 | 
				
			||||||
 | 
							writel(0xaaa, SUNXI_PIO_BASE + 0x2c0);
 | 
				
			||||||
 | 
						if (para->clk >= 180)
 | 
				
			||||||
 | 
							writel(0xfff, SUNXI_PIO_BASE + 0x2c0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (para->cas & BIT(4))
 | 
				
			||||||
 | 
							writel(0xd1303333, &ccm->pll5_pattern_cfg);
 | 
				
			||||||
 | 
						else if (para->cas & BIT(5))
 | 
				
			||||||
 | 
							writel(0xcce06666, &ccm->pll5_pattern_cfg);
 | 
				
			||||||
 | 
						else if (para->cas & BIT(6))
 | 
				
			||||||
 | 
							writel(0xc8909999, &ccm->pll5_pattern_cfg);
 | 
				
			||||||
 | 
						else if (para->cas & BIT(7))
 | 
				
			||||||
 | 
							writel(0xc440cccc, &ccm->pll5_pattern_cfg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (para->clk <= 96)
 | 
				
			||||||
 | 
							m = 2;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							m = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = CCM_PLL5_CTRL_EN | CCM_PLL5_CTRL_UPD |
 | 
				
			||||||
 | 
						      CCM_PLL5_CTRL_N((para->clk * 2) / (24 / m)) |
 | 
				
			||||||
 | 
						      CCM_PLL5_CTRL_K(1) | CCM_PLL5_CTRL_M(m);
 | 
				
			||||||
 | 
						if (para->cas & GENMASK(7, 4))
 | 
				
			||||||
 | 
							val |= CCM_PLL5_CTRL_SIGMA_DELTA_EN;
 | 
				
			||||||
 | 
						writel(val, &ccm->pll5_cfg);
 | 
				
			||||||
 | 
						setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_UPD);
 | 
				
			||||||
 | 
						mctl_await_completion(&ccm->pll5_cfg, BIT(28), BIT(28));
 | 
				
			||||||
 | 
						mdelay(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_MCTL));
 | 
				
			||||||
 | 
						clrbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_RESET_OFFSET_MCTL));
 | 
				
			||||||
 | 
						udelay(50);
 | 
				
			||||||
 | 
						setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_RESET_OFFSET_MCTL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clrsetbits_le32(SUNXI_PIO_BASE + 0x2c4, (1 << 16),
 | 
				
			||||||
 | 
								((para->sdr_ddr == DRAM_TYPE_DDR) << 16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						val = (SDR_T_CAS << 0) | (SDR_T_RAS << 3) | (SDR_T_RCD << 7) |
 | 
				
			||||||
 | 
						      (SDR_T_RP << 10) | (SDR_T_WR << 13) | (SDR_T_RFC << 15) |
 | 
				
			||||||
 | 
						      (SDR_T_XSR << 19) | (SDR_T_RC << 28);
 | 
				
			||||||
 | 
						writel(val, SUNXI_DRAMC_BASE + DRAM_STMG0R);
 | 
				
			||||||
 | 
						val = (SDR_T_INIT << 0) | (SDR_T_INIT_REF << 16) | (SDR_T_WTR << 20) |
 | 
				
			||||||
 | 
						      (SDR_T_RRD << 22) | (SDR_T_XP << 25);
 | 
				
			||||||
 | 
						writel(val, SUNXI_DRAMC_BASE + DRAM_STMG1R);
 | 
				
			||||||
 | 
						dram_para_setup(para);
 | 
				
			||||||
 | 
						dram_check_type(para);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clrsetbits_le32(SUNXI_PIO_BASE + 0x2c4, (1 << 16),
 | 
				
			||||||
 | 
								((para->sdr_ddr == DRAM_TYPE_DDR) << 16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dram_set_autofresh_cycle(para->clk);
 | 
				
			||||||
 | 
						dram_scan_readpipe(para);
 | 
				
			||||||
 | 
						dram_get_dram_size(para);
 | 
				
			||||||
 | 
						simple_dram_check();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned long sunxi_dram_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						do_dram_init(&suniv_dram_para);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return suniv_dram_para.size * 1024 * 1024;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue