[v3,34/57] ram: sdram: Configure lpddr4 tsel rd, wr based on IO settings
Commit Message
Now we have IO settings available for all supported sdram
frequencies, so retrieve these IO settings and make used
for LPDDR4 ds odt configuration.
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Signed-off-by: YouMin Chen <cym@rock-chips.com>
---
drivers/ram/rockchip/sdram_rk3399.c | 42 ++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 6 deletions(-)
Comments
On 2019/7/16 下午7:57, Jagan Teki wrote:
> Now we have IO settings available for all supported sdram
> frequencies, so retrieve these IO settings and make used
> for LPDDR4 ds odt configuration.
>
> 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 | 42 ++++++++++++++++++++++++-----
> 1 file changed, 36 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
> index 95d9f3a88b..1b8ce5160f 100644
> --- a/drivers/ram/rockchip/sdram_rk3399.c
> +++ b/drivers/ram/rockchip/sdram_rk3399.c
> @@ -184,6 +184,33 @@ struct io_setting {
> },
> };
>
> +/**
> + * phy = 0, PHY boot freq
> + * phy = 1, PHY index 0
> + * phy = 2, PHY index 1
> + */
> +static struct io_setting *
> +lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
> +{
> + struct io_setting *io = NULL;
> + u32 n;
> +
> + for (n = 0; n < ARRAY_SIZE(lpddr4_io_setting); n++) {
> + io = &lpddr4_io_setting[n];
> +
> + if (io->mr5 != 0) {
> + if (io->mhz >= params->base.ddr_freq &&
> + io->mr5 == mr5)
> + break;
> + } else {
> + if (io->mhz >= params->base.ddr_freq)
> + break;
> + }
> + }
> +
> + return io;
> +}
> +
> static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
> {
> return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;
> @@ -524,7 +551,7 @@ static int phy_io_config(const struct chan_info *chan,
> }
>
> static void set_ds_odt(const struct chan_info *chan,
> - const struct rk3399_sdram_params *params)
> + const struct rk3399_sdram_params *params, u32 mr5)
> {
> u32 *denali_phy = chan->publ->denali_phy;
>
> @@ -533,19 +560,22 @@ static void set_ds_odt(const struct chan_info *chan,
> u32 tsel_idle_select_n, tsel_rd_select_n;
> u32 tsel_wr_select_dq_p, tsel_wr_select_ca_p;
> u32 tsel_wr_select_dq_n, tsel_wr_select_ca_n;
> + struct io_setting *io = NULL;
> u32 reg_value;
>
> if (params->base.dramtype == LPDDR4) {
> + io = lpddr4_get_io_settings(params, mr5);
> +
> tsel_rd_select_p = PHY_DRV_ODT_HI_Z;
> - tsel_rd_select_n = PHY_DRV_ODT_240;
> + tsel_rd_select_n = io->rd_odt;
>
> tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
> tsel_idle_select_n = PHY_DRV_ODT_240;
>
> - tsel_wr_select_dq_p = PHY_DRV_ODT_40;
> + tsel_wr_select_dq_p = io->wr_dq_drv;
> tsel_wr_select_dq_n = PHY_DRV_ODT_40;
>
> - tsel_wr_select_ca_p = PHY_DRV_ODT_40;
> + tsel_wr_select_ca_p = io->wr_ca_drv;
> tsel_wr_select_ca_n = PHY_DRV_ODT_40;
> } else if (params->base.dramtype == LPDDR3) {
> tsel_rd_select_p = PHY_DRV_ODT_240;
> @@ -723,7 +753,7 @@ static void pctl_start(struct dram_info *dram, u8 channel)
> }
>
> static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
> - u32 channel, const struct rk3399_sdram_params *params)
> + u32 channel, struct rk3399_sdram_params *params)
> {
> u32 *denali_ctl = chan->pctl->denali_ctl;
> u32 *denali_pi = chan->pi->denali_pi;
> @@ -805,7 +835,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
> copy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4);
> copy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4);
> copy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4);
> - set_ds_odt(chan, params);
> + set_ds_odt(chan, params, 0);
>
> /*
> * phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8
@@ -184,6 +184,33 @@ struct io_setting {
},
};
+/**
+ * phy = 0, PHY boot freq
+ * phy = 1, PHY index 0
+ * phy = 2, PHY index 1
+ */
+static struct io_setting *
+lpddr4_get_io_settings(const struct rk3399_sdram_params *params, u32 mr5)
+{
+ struct io_setting *io = NULL;
+ u32 n;
+
+ for (n = 0; n < ARRAY_SIZE(lpddr4_io_setting); n++) {
+ io = &lpddr4_io_setting[n];
+
+ if (io->mr5 != 0) {
+ if (io->mhz >= params->base.ddr_freq &&
+ io->mr5 == mr5)
+ break;
+ } else {
+ if (io->mhz >= params->base.ddr_freq)
+ break;
+ }
+ }
+
+ return io;
+}
+
static void *get_ddrc0_con(struct dram_info *dram, u8 channel)
{
return (channel == 0) ? &dram->grf->ddrc0_con0 : &dram->grf->ddrc0_con1;
@@ -524,7 +551,7 @@ static int phy_io_config(const struct chan_info *chan,
}
static void set_ds_odt(const struct chan_info *chan,
- const struct rk3399_sdram_params *params)
+ const struct rk3399_sdram_params *params, u32 mr5)
{
u32 *denali_phy = chan->publ->denali_phy;
@@ -533,19 +560,22 @@ static void set_ds_odt(const struct chan_info *chan,
u32 tsel_idle_select_n, tsel_rd_select_n;
u32 tsel_wr_select_dq_p, tsel_wr_select_ca_p;
u32 tsel_wr_select_dq_n, tsel_wr_select_ca_n;
+ struct io_setting *io = NULL;
u32 reg_value;
if (params->base.dramtype == LPDDR4) {
+ io = lpddr4_get_io_settings(params, mr5);
+
tsel_rd_select_p = PHY_DRV_ODT_HI_Z;
- tsel_rd_select_n = PHY_DRV_ODT_240;
+ tsel_rd_select_n = io->rd_odt;
tsel_idle_select_p = PHY_DRV_ODT_HI_Z;
tsel_idle_select_n = PHY_DRV_ODT_240;
- tsel_wr_select_dq_p = PHY_DRV_ODT_40;
+ tsel_wr_select_dq_p = io->wr_dq_drv;
tsel_wr_select_dq_n = PHY_DRV_ODT_40;
- tsel_wr_select_ca_p = PHY_DRV_ODT_40;
+ tsel_wr_select_ca_p = io->wr_ca_drv;
tsel_wr_select_ca_n = PHY_DRV_ODT_40;
} else if (params->base.dramtype == LPDDR3) {
tsel_rd_select_p = PHY_DRV_ODT_240;
@@ -723,7 +753,7 @@ static void pctl_start(struct dram_info *dram, u8 channel)
}
static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
- u32 channel, const struct rk3399_sdram_params *params)
+ u32 channel, struct rk3399_sdram_params *params)
{
u32 *denali_ctl = chan->pctl->denali_ctl;
u32 *denali_pi = chan->pi->denali_pi;
@@ -805,7 +835,7 @@ static int pctl_cfg(struct dram_info *dram, const struct chan_info *chan,
copy_to_reg(&denali_phy[512], ¶ms_phy[512], (549 - 512 + 1) * 4);
copy_to_reg(&denali_phy[640], ¶ms_phy[640], (677 - 640 + 1) * 4);
copy_to_reg(&denali_phy[768], ¶ms_phy[768], (805 - 768 + 1) * 4);
- set_ds_odt(chan, params);
+ set_ds_odt(chan, params, 0);
/*
* phy_dqs_tsel_wr_timing_X 8bits DENALI_PHY_84/212/340/468 offset_8