Patchwork [U-Boot,V3,25/32] imx-common: cpu: add imx_ddr_size

login
register
mail settings
Submitter Troy Kisky
Date Oct. 4, 2012, 1:47 a.m.
Message ID <1349315254-21151-26-git-send-email-troy.kisky@boundarydevices.com>
Download mbox | patch
Permalink /patch/188988/
State Changes Requested
Delegated to: Stefano Babic
Headers show

Comments

Troy Kisky - Oct. 4, 2012, 1:47 a.m.
Read memory setup registers to determine size
of available ram. This routine works for mx53/mx6x

I need this because when mx6solo called get_ram_size
with a too large maximum size, the system hanged.

Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>

---
New patch with V3. V2 had code in mx6qsabrelite.c
---
 arch/arm/imx-common/cpu.c                 |   50 +++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx5/sys_proto.h |    1 +
 arch/arm/include/asm/arch-mx6/sys_proto.h |    1 +
 3 files changed, 52 insertions(+)
Stefano Babic - Oct. 8, 2012, 1:06 p.m.
On 04/10/2012 03:47, Troy Kisky wrote:
> Read memory setup registers to determine size
> of available ram. This routine works for mx53/mx6x
> 
> I need this because when mx6solo called get_ram_size
> with a too large maximum size, the system hanged.
> 
> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
> 

Hi Troy,

I am interested to better understand why get_ram_size() does not work.
It seems to me you discovered a bug in this function, and you circumvent
it decoding the DRAM controller setup to get the RAM size.

Because the max size is added to the start address in get_ram_size(), I
have the feeling that this overwlow the long value, and maybe can be
fixed swithcing to a "long long". With which parameters to
get_ram_size() does your board hang ?

> ---
> New patch with V3. V2 had code in mx6qsabrelite.c
> ---
>  arch/arm/imx-common/cpu.c                 |   50 +++++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-mx5/sys_proto.h |    1 +
>  arch/arm/include/asm/arch-mx6/sys_proto.h |    1 +
>  3 files changed, 52 insertions(+)
> 
> diff --git a/arch/arm/imx-common/cpu.c b/arch/arm/imx-common/cpu.c
> index 102c254..5081908 100644
> --- a/arch/arm/imx-common/cpu.c
> +++ b/arch/arm/imx-common/cpu.c
> @@ -65,6 +65,56 @@ char *get_reset_cause(void)
>  	}
>  }
>  
> +#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
> +#if defined(CONFIG_MX53)
> +#define MEMCTL_BASE	ESDCTL_BASE_ADDR;
> +#else
> +#define MEMCTL_BASE	MMDC_P0_BASE_ADDR;
> +#endif
> +static const unsigned char col_lookup[] = {9, 10, 11, 8, 12, 9, 9, 9};
> +static const unsigned char bank_lookup[] = {3, 2};
> +
> +struct esd_mmdc_regs {
> +	uint32_t	ctl;
> +	uint32_t	pdc;
> +	uint32_t	otc;
> +	uint32_t	cfg0;
> +	uint32_t	cfg1;
> +	uint32_t	cfg2;
> +	uint32_t	misc;
> +	uint32_t	scr;
> +	uint32_t	ref;
> +	uint32_t	rsvd1;
> +	uint32_t	rsvd2;
> +	uint32_t	rwd;
> +	uint32_t	or;
> +	uint32_t	mrr;
> +	uint32_t	cfg3lp;
> +	uint32_t	mr4;
> +};
> +
> +#define ESD_MMDC_CTL_GET_ROW(mdctl)	((ctl >> 24) & 7)
> +#define ESD_MMDC_CTL_GET_COLUMN(mdctl)	((ctl >> 20) & 7)
> +#define ESD_MMDC_CTL_GET_WIDTH(mdctl)	((ctl >> 16) & 3)
> +#define ESD_MMDC_CTL_GET_CS1(mdctl)	((ctl >> 30) & 1)
> +#define ESD_MMDC_MISC_GET_BANK(mdmisc)	((misc >> 5) & 1)
> +
> +unsigned imx_ddr_size(void)
> +{
> +	struct esd_mmdc_regs *mem = (struct esd_mmdc_regs *)MEMCTL_BASE;
> +	unsigned ctl = readl(&mem->ctl);
> +	unsigned misc = readl(&mem->misc);
> +	int bits = 11 + 0 + 0 + 1;      /* row + col + bank + width */
> +
> +	bits += ESD_MMDC_CTL_GET_ROW(ctl);
> +	bits += col_lookup[ESD_MMDC_CTL_GET_COLUMN(ctl)];
> +	bits += bank_lookup[ESD_MMDC_MISC_GET_BANK(misc)];
> +	bits += ESD_MMDC_CTL_GET_WIDTH(ctl);
> +	bits += ESD_MMDC_CTL_GET_CS1(ctl);
> +	return 1 << bits;
> +}
> +#endif
> +
>  #if defined(CONFIG_DISPLAY_CPUINFO)
>  
>  const char *get_imx_type(u32 imxtype)
> diff --git a/arch/arm/include/asm/arch-mx5/sys_proto.h b/arch/arm/include/asm/arch-mx5/sys_proto.h
> index 4435be1..93ad1c6 100644
> --- a/arch/arm/include/asm/arch-mx5/sys_proto.h
> +++ b/arch/arm/include/asm/arch-mx5/sys_proto.h
> @@ -33,6 +33,7 @@
>  
>  #define is_soc_rev(rev)	((get_cpu_rev() & 0xFF) - rev)
>  u32 get_cpu_rev(void);
> +unsigned imx_ddr_size(void);
>  void sdelay(unsigned long);
>  void set_chipselect_size(int const);
>  
> diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h
> index 6627bbc..3193297 100644
> --- a/arch/arm/include/asm/arch-mx6/sys_proto.h
> +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h
> @@ -34,6 +34,7 @@
>  #define is_soc_rev(rev)	((get_cpu_rev() & 0xFF) - rev)
>  u32 get_cpu_rev(void);
>  const char *get_imx_type(u32 imxtype);
> +unsigned imx_ddr_size(void);
>  

Best regards,
Stefano Babic
Troy Kisky - Oct. 8, 2012, 9:35 p.m.
On 10/8/2012 6:06 AM, Stefano Babic wrote:
> On 04/10/2012 03:47, Troy Kisky wrote:
>> Read memory setup registers to determine size
>> of available ram. This routine works for mx53/mx6x
>>
>> I need this because when mx6solo called get_ram_size
>> with a too large maximum size, the system hanged.
>>
>> Signed-off-by: Troy Kisky <troy.kisky@boundarydevices.com>
>>
> Hi Troy,
>
> I am interested to better understand why get_ram_size() does not work.
> It seems to me you discovered a bug in this function, and you circumvent
> it decoding the DRAM controller setup to get the RAM size.
>
> Because the max size is added to the start address in get_ram_size(), I
> have the feeling that this overwlow the long value, and maybe can be
> fixed swithcing to a "long long". With which parameters to
> get_ram_size() does your board hang ?
>
>
#define MMDC0_ARB_BASE_ADDR             0x10000000
#define PHYS_SDRAM                     MMDC0_ARB_BASE_ADDR
#define PHYS_SDRAM_SIZE                        (1u * 1024 * 1024 * 1024)

get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);

So, base + size = 0x50000000

Patch

diff --git a/arch/arm/imx-common/cpu.c b/arch/arm/imx-common/cpu.c
index 102c254..5081908 100644
--- a/arch/arm/imx-common/cpu.c
+++ b/arch/arm/imx-common/cpu.c
@@ -65,6 +65,56 @@  char *get_reset_cause(void)
 	}
 }
 
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#if defined(CONFIG_MX53)
+#define MEMCTL_BASE	ESDCTL_BASE_ADDR;
+#else
+#define MEMCTL_BASE	MMDC_P0_BASE_ADDR;
+#endif
+static const unsigned char col_lookup[] = {9, 10, 11, 8, 12, 9, 9, 9};
+static const unsigned char bank_lookup[] = {3, 2};
+
+struct esd_mmdc_regs {
+	uint32_t	ctl;
+	uint32_t	pdc;
+	uint32_t	otc;
+	uint32_t	cfg0;
+	uint32_t	cfg1;
+	uint32_t	cfg2;
+	uint32_t	misc;
+	uint32_t	scr;
+	uint32_t	ref;
+	uint32_t	rsvd1;
+	uint32_t	rsvd2;
+	uint32_t	rwd;
+	uint32_t	or;
+	uint32_t	mrr;
+	uint32_t	cfg3lp;
+	uint32_t	mr4;
+};
+
+#define ESD_MMDC_CTL_GET_ROW(mdctl)	((ctl >> 24) & 7)
+#define ESD_MMDC_CTL_GET_COLUMN(mdctl)	((ctl >> 20) & 7)
+#define ESD_MMDC_CTL_GET_WIDTH(mdctl)	((ctl >> 16) & 3)
+#define ESD_MMDC_CTL_GET_CS1(mdctl)	((ctl >> 30) & 1)
+#define ESD_MMDC_MISC_GET_BANK(mdmisc)	((misc >> 5) & 1)
+
+unsigned imx_ddr_size(void)
+{
+	struct esd_mmdc_regs *mem = (struct esd_mmdc_regs *)MEMCTL_BASE;
+	unsigned ctl = readl(&mem->ctl);
+	unsigned misc = readl(&mem->misc);
+	int bits = 11 + 0 + 0 + 1;      /* row + col + bank + width */
+
+	bits += ESD_MMDC_CTL_GET_ROW(ctl);
+	bits += col_lookup[ESD_MMDC_CTL_GET_COLUMN(ctl)];
+	bits += bank_lookup[ESD_MMDC_MISC_GET_BANK(misc)];
+	bits += ESD_MMDC_CTL_GET_WIDTH(ctl);
+	bits += ESD_MMDC_CTL_GET_CS1(ctl);
+	return 1 << bits;
+}
+#endif
+
 #if defined(CONFIG_DISPLAY_CPUINFO)
 
 const char *get_imx_type(u32 imxtype)
diff --git a/arch/arm/include/asm/arch-mx5/sys_proto.h b/arch/arm/include/asm/arch-mx5/sys_proto.h
index 4435be1..93ad1c6 100644
--- a/arch/arm/include/asm/arch-mx5/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx5/sys_proto.h
@@ -33,6 +33,7 @@ 
 
 #define is_soc_rev(rev)	((get_cpu_rev() & 0xFF) - rev)
 u32 get_cpu_rev(void);
+unsigned imx_ddr_size(void);
 void sdelay(unsigned long);
 void set_chipselect_size(int const);
 
diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h
index 6627bbc..3193297 100644
--- a/arch/arm/include/asm/arch-mx6/sys_proto.h
+++ b/arch/arm/include/asm/arch-mx6/sys_proto.h
@@ -34,6 +34,7 @@ 
 #define is_soc_rev(rev)	((get_cpu_rev() & 0xFF) - rev)
 u32 get_cpu_rev(void);
 const char *get_imx_type(u32 imxtype);
+unsigned imx_ddr_size(void);
 
 void set_vddsoc(u32 mv);