[v3,14/18] ram: rk3399: Compute stride for 2 channels

Message ID 20190715182856.21688-15-jagan@amarulasolutions.com
State New
Headers show
Series
  • ram: rk3399: Add rank detection
Related show

Commit Message

Jagan Teki July 15, 2019, 6:28 p.m. UTC
stride value from sdram timings can be computed dynamically
based on the determined capacity for the given channel.

Right now these stride values are taken as part of sdram timings
via dtsi, but it possible to use same timings dtsi for given
frequency even though the configured board sdram do support
single channel with different size by dynamically detect the
stride value.

Example, NanoPi NEO4 do have DDR3-1866, but with single channel
and 1GB size with dynamic stride detection it is possible to
use existing rk3399-sdram-ddr3-1866.dtsi whose stride,
number of channels and capacity it support is d efferent.

So, add initial support to calculate the stride value for
2 channels sdram, which is available by default on existing
boards.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Signed-off-by: YouMin Chen <cym@rock-chips.com>
---
 drivers/ram/rockchip/sdram_rk3399.c | 71 ++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 1 deletion(-)

Comments

Kever Yang July 16, 2019, 7:44 a.m. UTC | #1
On 2019/7/16 上午2:28, Jagan Teki wrote:
> stride value from sdram timings can be computed dynamically
> based on the determined capacity for the given channel.
>
> Right now these stride values are taken as part of sdram timings
> via dtsi, but it possible to use same timings dtsi for given
> frequency even though the configured board sdram do support
> single channel with different size by dynamically detect the
> stride value.
>
> Example, NanoPi NEO4 do have DDR3-1866, but with single channel
> and 1GB size with dynamic stride detection it is possible to
> use existing rk3399-sdram-ddr3-1866.dtsi whose stride,
> number of channels and capacity it support is d efferent.
>
> So, add initial support to calculate the stride value for
> 2 channels sdram, which is available by default on existing
> boards.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Signed-off-by: YouMin Chen <cym@rock-chips.com>

Reviewed-by: Kever Yang <Kever.yang@rock-chips.com>

Thanks,
  - Kever
> ---
>   drivers/ram/rockchip/sdram_rk3399.c | 71 ++++++++++++++++++++++++++++-
>   1 file changed, 70 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
> index 084c949728..c626ef602c 100644
> --- a/drivers/ram/rockchip/sdram_rk3399.c
> +++ b/drivers/ram/rockchip/sdram_rk3399.c
> @@ -1183,8 +1183,75 @@ static int switch_to_phy_index1(struct dram_info *dram,
>   	return 0;
>   }
>   
> +static unsigned char calculate_stride(struct rk3399_sdram_params *params)
> +{
> +	unsigned int stride = params->base.stride;
> +	unsigned int channel, chinfo = 0;
> +	unsigned int ch_cap[2] = {0, 0};
> +	u64 cap;
> +
> +	for (channel = 0; channel < 2; channel++) {
> +		unsigned int cs0_cap = 0;
> +		unsigned int cs1_cap = 0;
> +		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
> +
> +		if (cap_info->col == 0)
> +			continue;
> +
> +		cs0_cap = (1 << (cap_info->cs0_row + cap_info->col +
> +				 cap_info->bk + cap_info->bw - 20));
> +		if (cap_info->rank > 1)
> +			cs1_cap = cs0_cap >> (cap_info->cs0_row
> +					      - cap_info->cs1_row);
> +		if (cap_info->row_3_4) {
> +			cs0_cap = cs0_cap * 3 / 4;
> +			cs1_cap = cs1_cap * 3 / 4;
> +		}
> +		ch_cap[channel] = cs0_cap + cs1_cap;
> +		chinfo |= 1 << channel;
> +	}
> +
> +	/* stride calculation for 2 channels, default gstride type is 256B */
> +	if (ch_cap[0] == ch_cap[1]) {
> +		cap = ch_cap[0] + ch_cap[1];
> +		switch (cap) {
> +		/* 512MB */
> +		case 512:
> +			stride = 0;
> +			break;
> +		/* 1GB */
> +		case 1024:
> +			stride = 0x5;
> +			break;
> +		/*
> +		 * 768MB + 768MB same as total 2GB memory
> +		 * useful space: 0-768MB 1GB-1792MB
> +		 */
> +		case 1536:
> +		/* 2GB */
> +		case 2048:
> +			stride = 0x9;
> +			break;
> +		/* 1536MB + 1536MB */
> +		case 3072:
> +			stride = 0x11;
> +			break;
> +		/* 4GB */
> +		case 4096:
> +			stride = 0xD;
> +			break;
> +		default:
> +			printf("%s: Unable to calculate stride for ", __func__);
> +			print_size((cap * (1 << 20)), " capacity\n");
> +			break;
> +		}
> +	}
> +
> +	return stride;
> +}
> +
>   static int sdram_init(struct dram_info *dram,
> -		      const struct rk3399_sdram_params *params)
> +		      struct rk3399_sdram_params *params)
>   {
>   	unsigned char dramtype = params->base.dramtype;
>   	unsigned int ddr_freq = params->base.ddr_freq;
> @@ -1232,6 +1299,8 @@ static int sdram_init(struct dram_info *dram,
>   		set_ddrconfig(chan, params, channel,
>   			      params->ch[channel].cap_info.ddrconfig);
>   	}
> +
> +	params->base.stride = calculate_stride(params);
>   	dram_all_config(dram, params);
>   	switch_to_phy_index1(dram, params);
>

Patch

diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 084c949728..c626ef602c 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -1183,8 +1183,75 @@  static int switch_to_phy_index1(struct dram_info *dram,
 	return 0;
 }
 
+static unsigned char calculate_stride(struct rk3399_sdram_params *params)
+{
+	unsigned int stride = params->base.stride;
+	unsigned int channel, chinfo = 0;
+	unsigned int ch_cap[2] = {0, 0};
+	u64 cap;
+
+	for (channel = 0; channel < 2; channel++) {
+		unsigned int cs0_cap = 0;
+		unsigned int cs1_cap = 0;
+		struct sdram_cap_info *cap_info = &params->ch[channel].cap_info;
+
+		if (cap_info->col == 0)
+			continue;
+
+		cs0_cap = (1 << (cap_info->cs0_row + cap_info->col +
+				 cap_info->bk + cap_info->bw - 20));
+		if (cap_info->rank > 1)
+			cs1_cap = cs0_cap >> (cap_info->cs0_row
+					      - cap_info->cs1_row);
+		if (cap_info->row_3_4) {
+			cs0_cap = cs0_cap * 3 / 4;
+			cs1_cap = cs1_cap * 3 / 4;
+		}
+		ch_cap[channel] = cs0_cap + cs1_cap;
+		chinfo |= 1 << channel;
+	}
+
+	/* stride calculation for 2 channels, default gstride type is 256B */
+	if (ch_cap[0] == ch_cap[1]) {
+		cap = ch_cap[0] + ch_cap[1];
+		switch (cap) {
+		/* 512MB */
+		case 512:
+			stride = 0;
+			break;
+		/* 1GB */
+		case 1024:
+			stride = 0x5;
+			break;
+		/*
+		 * 768MB + 768MB same as total 2GB memory
+		 * useful space: 0-768MB 1GB-1792MB
+		 */
+		case 1536:
+		/* 2GB */
+		case 2048:
+			stride = 0x9;
+			break;
+		/* 1536MB + 1536MB */
+		case 3072:
+			stride = 0x11;
+			break;
+		/* 4GB */
+		case 4096:
+			stride = 0xD;
+			break;
+		default:
+			printf("%s: Unable to calculate stride for ", __func__);
+			print_size((cap * (1 << 20)), " capacity\n");
+			break;
+		}
+	}
+
+	return stride;
+}
+
 static int sdram_init(struct dram_info *dram,
-		      const struct rk3399_sdram_params *params)
+		      struct rk3399_sdram_params *params)
 {
 	unsigned char dramtype = params->base.dramtype;
 	unsigned int ddr_freq = params->base.ddr_freq;
@@ -1232,6 +1299,8 @@  static int sdram_init(struct dram_info *dram,
 		set_ddrconfig(chan, params, channel,
 			      params->ch[channel].cap_info.ddrconfig);
 	}
+
+	params->base.stride = calculate_stride(params);
 	dram_all_config(dram, params);
 	switch_to_phy_index1(dram, params);