We assumed that a DDR4 always has 16 banks. This is true for x4 and x8 devices, but not for x16 devices which only have 8 banks.
It seems we can read the number of banks from the BANK_DIFF_x register fields, but the exact encoding of these fields is unknown. The reference manual only describes them as: "Encoded number of banks on the DRAM[s]" >From looking at the output of the TI AM62x DDR configuration tool it seems that it sets the fields to 0 for x8 devices and to 1 for x16 devices. LPDDR4 devices always have 8 banks. In the AM625SIP board which has LPDDR4 the BANK_DIFF_x fields are also set to 1 meaning 8 banks, so we can drop the LPDDR4/DDR4 detection and just rely on the BANK_DIFF_x fields to determine the number of banks. This has been tested on the BeaglePlay board (2GB x16 DDR4) and verified on the AM62-SK board (also 2GiB x16 DDR4) and on the AM625SIP-SK board (512MiB x16 LPDDR4) Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de> --- arch/arm/mach-k3/ddrss.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-k3/ddrss.c b/arch/arm/mach-k3/ddrss.c index b51371d661..a4becfbad0 100644 --- a/arch/arm/mach-k3/ddrss.c +++ b/arch/arm/mach-k3/ddrss.c @@ -13,6 +13,10 @@ #define CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_327 0x51c +#define CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_316 0x4f0 +#define BANK_DIFF_1 GENMASK(25, 24) +#define BANK_DIFF_0 GENMASK(17, 16) + #define CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_317 0x4f4 #define ROW_DIFF_0 GENMASK(2, 0) @@ -30,32 +34,51 @@ #define DENALI_CTL_0_DRAM_CLASS_DDR4 0xa #define DENALI_CTL_0_DRAM_CLASS_LPDDR4 0xb +static unsigned int am625_get_banks_count(unsigned int regval) +{ + /* + * The BANK_DIFF_x are only described in the Reference Manual as: + * + * "Encoded number of banks on the DRAM[s]" + * + * From putting different configurations into the TI DDR configuration + * tool it seems that a register value of 0 means 16 banks and 1 means + * 8 banks. + */ + switch (regval) { + case 0: + return 16; + case 1: + return 8; + default: + return 0; + } +} + u64 am625_sdram_size(void) { void __iomem *base = IOMEM(AM625_DDRSS_BASE); u32 ctl0 = readl(base + CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_0); u32 ctl3 = readl(base + CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_3); + u32 ctl316 = readl(base + CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_316); u32 ctl317 = readl(base + CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_317); u32 ctl327 = readl(base + CTLPHY_CTL_CFG_CTLCFG_DENALI_CTL_327); unsigned int cols, rows, banks; u64 size = 0; - if (FIELD_GET(DRAM_CLASS, ctl0) == DENALI_CTL_0_DRAM_CLASS_LPDDR4) - banks = 8; - else if (FIELD_GET(DRAM_CLASS, ctl0) == DENALI_CTL_0_DRAM_CLASS_DDR4) - banks = 16; - else - return 0; - if (ctl327 & BIT(0)) { cols = FIELD_GET(MAX_COL, ctl3) - FIELD_GET(COL_DIFF_0, ctl317); rows = FIELD_GET(MAX_ROW, ctl3) - FIELD_GET(ROW_DIFF_0, ctl317); + banks = am625_get_banks_count(FIELD_GET(BANK_DIFF_0, ctl316)); + size += memory_sdram_size(cols, rows, banks, 2); } if (ctl327 & BIT(1)) { cols = FIELD_GET(MAX_COL, ctl3) - FIELD_GET(COL_DIFF_1, ctl317); rows = FIELD_GET(MAX_ROW, ctl3) - FIELD_GET(ROW_DIFF_1, ctl317); + banks = am625_get_banks_count(FIELD_GET(BANK_DIFF_1, ctl316)); + size += memory_sdram_size(cols, rows, banks, 2); } -- 2.39.5