mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-12 14:23:00 +00:00
258bad41ac
The configuration files imximage.cfg are used for the DDR controller configuration. Add DDR configuration function to replace the DDR controller configuration in the imximage.cfg file. The function can be used for DDR size detection. Signed-off-by: Uri Mashiach <uri.mashiach@compulab.co.il>
201 lines
7.3 KiB
C
201 lines
7.3 KiB
C
/*
|
|
* DDR controller configuration for the i.MX7 architecture
|
|
*
|
|
* (C) Copyright 2017 CompuLab, Ltd. http://www.compulab.com
|
|
*
|
|
* Author: Uri Mashiach <uri.mashiach@compulab.co.il>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch/imx-regs.h>
|
|
#include <asm/arch/crm_regs.h>
|
|
#include <asm/arch/mx7-ddr.h>
|
|
#include <common.h>
|
|
|
|
/*
|
|
* Routine: mx7_dram_cfg
|
|
* Description: DDR controller configuration
|
|
*
|
|
* @ddrc_regs_val: DDRC registers value
|
|
* @ddrc_mp_val: DDRC_MP registers value
|
|
* @ddr_phy_regs_val: DDR_PHY registers value
|
|
* @calib_param: calibration parameters
|
|
*
|
|
*/
|
|
void mx7_dram_cfg(struct ddrc *ddrc_regs_val, struct ddrc_mp *ddrc_mp_val,
|
|
struct ddr_phy *ddr_phy_regs_val,
|
|
struct mx7_calibration *calib_param)
|
|
{
|
|
struct src *const src_regs = (struct src *)SRC_BASE_ADDR;
|
|
struct ddrc *const ddrc_regs = (struct ddrc *)DDRC_IPS_BASE_ADDR;
|
|
struct ddrc_mp *const ddrc_mp_reg = (struct ddrc_mp *)DDRC_MP_BASE_ADDR;
|
|
struct ddr_phy *const ddr_phy_regs =
|
|
(struct ddr_phy *)DDRPHY_IPS_BASE_ADDR;
|
|
struct iomuxc_gpr_base_regs *const iomuxc_gpr_regs =
|
|
(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
|
|
int i;
|
|
|
|
/* Assert DDR Controller preset and DDR PHY reset */
|
|
writel(SRC_DDRC_RCR_DDRC_CORE_RST_MASK, &src_regs->ddrc_rcr);
|
|
|
|
/* DDR controller configuration */
|
|
writel(ddrc_regs_val->mstr, &ddrc_regs->mstr);
|
|
writel(ddrc_regs_val->rfshtmg, &ddrc_regs->rfshtmg);
|
|
writel(ddrc_mp_val->pctrl_0, &ddrc_mp_reg->pctrl_0);
|
|
writel(ddrc_regs_val->init1, &ddrc_regs->init1);
|
|
writel(ddrc_regs_val->init0, &ddrc_regs->init0);
|
|
writel(ddrc_regs_val->init3, &ddrc_regs->init3);
|
|
writel(ddrc_regs_val->init4, &ddrc_regs->init4);
|
|
writel(ddrc_regs_val->init5, &ddrc_regs->init5);
|
|
writel(ddrc_regs_val->rankctl, &ddrc_regs->rankctl);
|
|
writel(ddrc_regs_val->dramtmg0, &ddrc_regs->dramtmg0);
|
|
writel(ddrc_regs_val->dramtmg1, &ddrc_regs->dramtmg1);
|
|
writel(ddrc_regs_val->dramtmg2, &ddrc_regs->dramtmg2);
|
|
writel(ddrc_regs_val->dramtmg3, &ddrc_regs->dramtmg3);
|
|
writel(ddrc_regs_val->dramtmg4, &ddrc_regs->dramtmg4);
|
|
writel(ddrc_regs_val->dramtmg5, &ddrc_regs->dramtmg5);
|
|
writel(ddrc_regs_val->dramtmg8, &ddrc_regs->dramtmg8);
|
|
writel(ddrc_regs_val->zqctl0, &ddrc_regs->zqctl0);
|
|
writel(ddrc_regs_val->dfitmg0, &ddrc_regs->dfitmg0);
|
|
writel(ddrc_regs_val->dfitmg1, &ddrc_regs->dfitmg1);
|
|
writel(ddrc_regs_val->dfiupd0, &ddrc_regs->dfiupd0);
|
|
writel(ddrc_regs_val->dfiupd1, &ddrc_regs->dfiupd1);
|
|
writel(ddrc_regs_val->dfiupd2, &ddrc_regs->dfiupd2);
|
|
writel(ddrc_regs_val->addrmap0, &ddrc_regs->addrmap0);
|
|
writel(ddrc_regs_val->addrmap1, &ddrc_regs->addrmap1);
|
|
writel(ddrc_regs_val->addrmap4, &ddrc_regs->addrmap4);
|
|
writel(ddrc_regs_val->addrmap5, &ddrc_regs->addrmap5);
|
|
writel(ddrc_regs_val->addrmap6, &ddrc_regs->addrmap6);
|
|
writel(ddrc_regs_val->odtcfg, &ddrc_regs->odtcfg);
|
|
writel(ddrc_regs_val->odtmap, &ddrc_regs->odtmap);
|
|
|
|
/* De-assert DDR Controller preset and DDR PHY reset */
|
|
clrbits_le32(&src_regs->ddrc_rcr, SRC_DDRC_RCR_DDRC_CORE_RST_MASK);
|
|
|
|
/* PHY configuration */
|
|
writel(ddr_phy_regs_val->phy_con0, &ddr_phy_regs->phy_con0);
|
|
writel(ddr_phy_regs_val->phy_con1, &ddr_phy_regs->phy_con1);
|
|
writel(ddr_phy_regs_val->phy_con4, &ddr_phy_regs->phy_con4);
|
|
writel(ddr_phy_regs_val->mdll_con0, &ddr_phy_regs->mdll_con0);
|
|
writel(ddr_phy_regs_val->drvds_con0, &ddr_phy_regs->drvds_con0);
|
|
writel(ddr_phy_regs_val->offset_wr_con0, &ddr_phy_regs->offset_wr_con0);
|
|
writel(ddr_phy_regs_val->offset_rd_con0, &ddr_phy_regs->offset_rd_con0);
|
|
writel(ddr_phy_regs_val->cmd_sdll_con0 |
|
|
DDR_PHY_CMD_SDLL_CON0_CTRL_RESYNC_MASK,
|
|
&ddr_phy_regs->cmd_sdll_con0);
|
|
writel(ddr_phy_regs_val->cmd_sdll_con0 &
|
|
~DDR_PHY_CMD_SDLL_CON0_CTRL_RESYNC_MASK,
|
|
&ddr_phy_regs->cmd_sdll_con0);
|
|
writel(ddr_phy_regs_val->offset_lp_con0, &ddr_phy_regs->offset_lp_con0);
|
|
|
|
/* calibration */
|
|
for (i = 0; i < calib_param->num_val; i++)
|
|
writel(calib_param->values[i], &ddr_phy_regs->zq_con0);
|
|
|
|
/* Wake_up DDR PHY */
|
|
HW_CCM_CCGR_WR(CCGR_IDX_DDR, CCM_CLK_ON_N_N);
|
|
writel(IOMUXC_GPR_GPR8_ddr_phy_ctrl_wake_up(0xf) |
|
|
IOMUXC_GPR_GPR8_ddr_phy_dfi_init_start_MASK,
|
|
&iomuxc_gpr_regs->gpr[8]);
|
|
HW_CCM_CCGR_WR(CCGR_IDX_DDR, CCM_CLK_ON_R_W);
|
|
}
|
|
|
|
/*
|
|
* Routine: imx_ddr_size
|
|
* Description: extract the current DRAM size from the DDRC registers
|
|
*
|
|
* @return: DRAM size
|
|
*/
|
|
unsigned int imx_ddr_size(void)
|
|
{
|
|
struct ddrc *const ddrc_regs = (struct ddrc *)DDRC_IPS_BASE_ADDR;
|
|
u32 reg_val, field_val;
|
|
int bits = 0;/* Number of address bits */
|
|
|
|
/* Count data bus width bits */
|
|
reg_val = readl(&ddrc_regs->mstr);
|
|
field_val = (reg_val & MSTR_DATA_BUS_WIDTH_MASK) >> MSTR_DATA_BUS_WIDTH_SHIFT;
|
|
bits += 2 - field_val;
|
|
/* Count rank address bits */
|
|
field_val = (reg_val & MSTR_DATA_ACTIVE_RANKS_MASK) >> MSTR_DATA_ACTIVE_RANKS_SHIFT;
|
|
if (field_val > 1)
|
|
bits += field_val - 1;
|
|
/* Count column address bits */
|
|
bits += 2;/* Column address 0 and 1 are fixed mapped */
|
|
reg_val = readl(&ddrc_regs->addrmap2);
|
|
field_val = (reg_val & ADDRMAP2_COL_B2_MASK) >> ADDRMAP2_COL_B2_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP2_COL_B3_MASK) >> ADDRMAP2_COL_B3_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP2_COL_B4_MASK) >> ADDRMAP2_COL_B4_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP2_COL_B5_MASK) >> ADDRMAP2_COL_B5_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
reg_val = readl(&ddrc_regs->addrmap3);
|
|
field_val = (reg_val & ADDRMAP3_COL_B6_MASK) >> ADDRMAP3_COL_B6_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP3_COL_B7_MASK) >> ADDRMAP3_COL_B7_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP3_COL_B8_MASK) >> ADDRMAP3_COL_B8_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP3_COL_B9_MASK) >> ADDRMAP3_COL_B9_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
reg_val = readl(&ddrc_regs->addrmap4);
|
|
field_val = (reg_val & ADDRMAP4_COL_B10_MASK) >> ADDRMAP4_COL_B10_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP4_COL_B11_MASK) >> ADDRMAP4_COL_B11_SHIFT;
|
|
if (field_val <= 7)
|
|
bits++;
|
|
/* Count row address bits */
|
|
reg_val = readl(&ddrc_regs->addrmap5);
|
|
field_val = (reg_val & ADDRMAP5_ROW_B0_MASK) >> ADDRMAP5_ROW_B0_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP5_ROW_B1_MASK) >> ADDRMAP5_ROW_B1_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP5_ROW_B2_10_MASK) >> ADDRMAP5_ROW_B2_10_SHIFT;
|
|
if (field_val <= 11)
|
|
bits += 9;
|
|
field_val = (reg_val & ADDRMAP5_ROW_B11_MASK) >> ADDRMAP5_ROW_B11_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
reg_val = readl(&ddrc_regs->addrmap6);
|
|
field_val = (reg_val & ADDRMAP6_ROW_B12_MASK) >> ADDRMAP6_ROW_B12_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP6_ROW_B13_MASK) >> ADDRMAP6_ROW_B13_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP6_ROW_B14_MASK) >> ADDRMAP6_ROW_B14_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP6_ROW_B15_MASK) >> ADDRMAP6_ROW_B15_SHIFT;
|
|
if (field_val <= 11)
|
|
bits++;
|
|
/* Count bank bits */
|
|
reg_val = readl(&ddrc_regs->addrmap1);
|
|
field_val = (reg_val & ADDRMAP1_BANK_B0_MASK) >> ADDRMAP1_BANK_B0_SHIFT;
|
|
if (field_val <= 30)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP1_BANK_B1_MASK) >> ADDRMAP1_BANK_B1_SHIFT;
|
|
if (field_val <= 30)
|
|
bits++;
|
|
field_val = (reg_val & ADDRMAP1_BANK_B2_MASK) >> ADDRMAP1_BANK_B2_SHIFT;
|
|
if (field_val <= 29)
|
|
bits++;
|
|
|
|
return 1 << bits;
|
|
}
|