14c425570SMasahiro Yamada /* 23e9952beSMasahiro Yamada * Copyright (C) 2012-2015 Panasonic Corporation 33e9952beSMasahiro Yamada * Copyright (C) 2015-2017 Socionext Inc. 43e9952beSMasahiro Yamada * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 54c425570SMasahiro Yamada * 64c425570SMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 74c425570SMasahiro Yamada */ 84c425570SMasahiro Yamada 94c425570SMasahiro Yamada #include <common.h> 107b3a032dSMasahiro Yamada #include <fdtdec.h> 110f4ec05bSMasahiro Yamada #include <linux/errno.h> 123e9952beSMasahiro Yamada #include <linux/sizes.h> 13cf88affaSMasahiro Yamada 1451ea5a06SMasahiro Yamada #include "init.h" 153e9952beSMasahiro Yamada #include "sg-regs.h" 1651ea5a06SMasahiro Yamada #include "soc-info.h" 1751ea5a06SMasahiro Yamada 18cf88affaSMasahiro Yamada DECLARE_GLOBAL_DATA_PTR; 19cf88affaSMasahiro Yamada 203e9952beSMasahiro Yamada struct uniphier_memif_data { 213e9952beSMasahiro Yamada unsigned int soc_id; 223e9952beSMasahiro Yamada unsigned long sparse_ch1_base; 233e9952beSMasahiro Yamada int have_ch2; 243e9952beSMasahiro Yamada }; 253e9952beSMasahiro Yamada 263e9952beSMasahiro Yamada static const struct uniphier_memif_data uniphier_memif_data[] = { 27cf88affaSMasahiro Yamada { 283e9952beSMasahiro Yamada .soc_id = UNIPHIER_SLD3_ID, 293e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 303e9952beSMasahiro Yamada /* 313e9952beSMasahiro Yamada * In fact, SLD3 has DRAM ch2, but the memory regions for ch1 323e9952beSMasahiro Yamada * and ch2 overlap, and host cannot get access to them at the 333e9952beSMasahiro Yamada * same time. Hide the ch2 from U-Boot. 343e9952beSMasahiro Yamada */ 353e9952beSMasahiro Yamada }, 363e9952beSMasahiro Yamada { 373e9952beSMasahiro Yamada .soc_id = UNIPHIER_LD4_ID, 383e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 393e9952beSMasahiro Yamada }, 403e9952beSMasahiro Yamada { 413e9952beSMasahiro Yamada .soc_id = UNIPHIER_PRO4_ID, 423e9952beSMasahiro Yamada .sparse_ch1_base = 0xa0000000, 433e9952beSMasahiro Yamada }, 443e9952beSMasahiro Yamada { 453e9952beSMasahiro Yamada .soc_id = UNIPHIER_SLD8_ID, 463e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 473e9952beSMasahiro Yamada }, 483e9952beSMasahiro Yamada { 493e9952beSMasahiro Yamada .soc_id = UNIPHIER_PRO5_ID, 503e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 513e9952beSMasahiro Yamada }, 523e9952beSMasahiro Yamada { 533e9952beSMasahiro Yamada .soc_id = UNIPHIER_PXS2_ID, 543e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 553e9952beSMasahiro Yamada .have_ch2 = 1, 563e9952beSMasahiro Yamada }, 573e9952beSMasahiro Yamada { 583e9952beSMasahiro Yamada .soc_id = UNIPHIER_LD6B_ID, 593e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 603e9952beSMasahiro Yamada .have_ch2 = 1, 613e9952beSMasahiro Yamada }, 623e9952beSMasahiro Yamada { 633e9952beSMasahiro Yamada .soc_id = UNIPHIER_LD11_ID, 643e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 653e9952beSMasahiro Yamada }, 663e9952beSMasahiro Yamada { 673e9952beSMasahiro Yamada .soc_id = UNIPHIER_LD20_ID, 683e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 693e9952beSMasahiro Yamada .have_ch2 = 1, 703e9952beSMasahiro Yamada }, 713e9952beSMasahiro Yamada { 723e9952beSMasahiro Yamada .soc_id = UNIPHIER_PXS3_ID, 733e9952beSMasahiro Yamada .sparse_ch1_base = 0xc0000000, 743e9952beSMasahiro Yamada .have_ch2 = 1, 753e9952beSMasahiro Yamada }, 763e9952beSMasahiro Yamada }; 773e9952beSMasahiro Yamada UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_memif_data, uniphier_memif_data) 78cf88affaSMasahiro Yamada 793e9952beSMasahiro Yamada static int uniphier_memconf_decode(struct uniphier_dram_ch *dram_ch) 803e9952beSMasahiro Yamada { 813e9952beSMasahiro Yamada const struct uniphier_memif_data *data; 823e9952beSMasahiro Yamada unsigned long size; 833e9952beSMasahiro Yamada u32 val; 84cf88affaSMasahiro Yamada 853e9952beSMasahiro Yamada data = uniphier_get_memif_data(); 863e9952beSMasahiro Yamada if (!data) { 873e9952beSMasahiro Yamada pr_err("unsupported SoC\n"); 883e9952beSMasahiro Yamada return -EINVAL; 893e9952beSMasahiro Yamada } 903e9952beSMasahiro Yamada 913e9952beSMasahiro Yamada val = readl(SG_MEMCONF); 923e9952beSMasahiro Yamada 933e9952beSMasahiro Yamada /* set up ch0 */ 943e9952beSMasahiro Yamada dram_ch[0].base = CONFIG_SYS_SDRAM_BASE; 953e9952beSMasahiro Yamada 963e9952beSMasahiro Yamada switch (val & SG_MEMCONF_CH0_SZ_MASK) { 973e9952beSMasahiro Yamada case SG_MEMCONF_CH0_SZ_64M: 983e9952beSMasahiro Yamada size = SZ_64M; 993e9952beSMasahiro Yamada break; 1003e9952beSMasahiro Yamada case SG_MEMCONF_CH0_SZ_128M: 1013e9952beSMasahiro Yamada size = SZ_128M; 1023e9952beSMasahiro Yamada break; 1033e9952beSMasahiro Yamada case SG_MEMCONF_CH0_SZ_256M: 1043e9952beSMasahiro Yamada size = SZ_256M; 1053e9952beSMasahiro Yamada break; 1063e9952beSMasahiro Yamada case SG_MEMCONF_CH0_SZ_512M: 1073e9952beSMasahiro Yamada size = SZ_512M; 1083e9952beSMasahiro Yamada break; 1093e9952beSMasahiro Yamada case SG_MEMCONF_CH0_SZ_1G: 1103e9952beSMasahiro Yamada size = SZ_1G; 1113e9952beSMasahiro Yamada break; 1123e9952beSMasahiro Yamada default: 113*0f5bf09cSMasahiro Yamada pr_err("error: invalid value is set to MEMCONF ch0 size\n"); 1143e9952beSMasahiro Yamada return -EINVAL; 1153e9952beSMasahiro Yamada } 1163e9952beSMasahiro Yamada 1173e9952beSMasahiro Yamada if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2) 1183e9952beSMasahiro Yamada size *= 2; 1193e9952beSMasahiro Yamada 1203e9952beSMasahiro Yamada dram_ch[0].size = size; 1213e9952beSMasahiro Yamada 1223e9952beSMasahiro Yamada /* set up ch1 */ 1233e9952beSMasahiro Yamada dram_ch[1].base = dram_ch[0].base + size; 1243e9952beSMasahiro Yamada 1253e9952beSMasahiro Yamada if (val & SG_MEMCONF_SPARSEMEM) { 1263e9952beSMasahiro Yamada if (dram_ch[1].base > data->sparse_ch1_base) { 1273e9952beSMasahiro Yamada pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n"); 1283e9952beSMasahiro Yamada pr_warn("Only ch0 is available\n"); 1293e9952beSMasahiro Yamada dram_ch[1].base = 0; 1303e9952beSMasahiro Yamada return 0; 1313e9952beSMasahiro Yamada } 1323e9952beSMasahiro Yamada 1333e9952beSMasahiro Yamada dram_ch[1].base = data->sparse_ch1_base; 1343e9952beSMasahiro Yamada } 1353e9952beSMasahiro Yamada 1363e9952beSMasahiro Yamada switch (val & SG_MEMCONF_CH1_SZ_MASK) { 1373e9952beSMasahiro Yamada case SG_MEMCONF_CH1_SZ_64M: 1383e9952beSMasahiro Yamada size = SZ_64M; 1393e9952beSMasahiro Yamada break; 1403e9952beSMasahiro Yamada case SG_MEMCONF_CH1_SZ_128M: 1413e9952beSMasahiro Yamada size = SZ_128M; 1423e9952beSMasahiro Yamada break; 1433e9952beSMasahiro Yamada case SG_MEMCONF_CH1_SZ_256M: 1443e9952beSMasahiro Yamada size = SZ_256M; 1453e9952beSMasahiro Yamada break; 1463e9952beSMasahiro Yamada case SG_MEMCONF_CH1_SZ_512M: 1473e9952beSMasahiro Yamada size = SZ_512M; 1483e9952beSMasahiro Yamada break; 1493e9952beSMasahiro Yamada case SG_MEMCONF_CH1_SZ_1G: 1503e9952beSMasahiro Yamada size = SZ_1G; 1513e9952beSMasahiro Yamada break; 1523e9952beSMasahiro Yamada default: 153*0f5bf09cSMasahiro Yamada pr_err("error: invalid value is set to MEMCONF ch1 size\n"); 1543e9952beSMasahiro Yamada return -EINVAL; 1553e9952beSMasahiro Yamada } 1563e9952beSMasahiro Yamada 1573e9952beSMasahiro Yamada if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2) 1583e9952beSMasahiro Yamada size *= 2; 1593e9952beSMasahiro Yamada 1603e9952beSMasahiro Yamada dram_ch[1].size = size; 1613e9952beSMasahiro Yamada 162bed1624dSMasahiro Yamada if (!data->have_ch2 || val & SG_MEMCONF_CH2_DISABLE) 1633e9952beSMasahiro Yamada return 0; 1643e9952beSMasahiro Yamada 1653e9952beSMasahiro Yamada /* set up ch2 */ 1663e9952beSMasahiro Yamada dram_ch[2].base = dram_ch[1].base + size; 1673e9952beSMasahiro Yamada 1683e9952beSMasahiro Yamada switch (val & SG_MEMCONF_CH2_SZ_MASK) { 1693e9952beSMasahiro Yamada case SG_MEMCONF_CH2_SZ_64M: 1703e9952beSMasahiro Yamada size = SZ_64M; 1713e9952beSMasahiro Yamada break; 1723e9952beSMasahiro Yamada case SG_MEMCONF_CH2_SZ_128M: 1733e9952beSMasahiro Yamada size = SZ_128M; 1743e9952beSMasahiro Yamada break; 1753e9952beSMasahiro Yamada case SG_MEMCONF_CH2_SZ_256M: 1763e9952beSMasahiro Yamada size = SZ_256M; 1773e9952beSMasahiro Yamada break; 1783e9952beSMasahiro Yamada case SG_MEMCONF_CH2_SZ_512M: 1793e9952beSMasahiro Yamada size = SZ_512M; 1803e9952beSMasahiro Yamada break; 1813e9952beSMasahiro Yamada case SG_MEMCONF_CH2_SZ_1G: 1823e9952beSMasahiro Yamada size = SZ_1G; 1833e9952beSMasahiro Yamada break; 1843e9952beSMasahiro Yamada default: 185*0f5bf09cSMasahiro Yamada pr_err("error: invalid value is set to MEMCONF ch2 size\n"); 1863e9952beSMasahiro Yamada return -EINVAL; 1873e9952beSMasahiro Yamada } 1883e9952beSMasahiro Yamada 1893e9952beSMasahiro Yamada if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2) 1903e9952beSMasahiro Yamada size *= 2; 1913e9952beSMasahiro Yamada 1923e9952beSMasahiro Yamada dram_ch[2].size = size; 1933e9952beSMasahiro Yamada 1943e9952beSMasahiro Yamada return 0; 195cf88affaSMasahiro Yamada } 1964c425570SMasahiro Yamada 1974c425570SMasahiro Yamada int dram_init(void) 1984c425570SMasahiro Yamada { 1993e9952beSMasahiro Yamada struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; 2003e9952beSMasahiro Yamada int ret, i; 201cf88affaSMasahiro Yamada 2023e9952beSMasahiro Yamada gd->ram_size = 0; 2033e9952beSMasahiro Yamada 2043e9952beSMasahiro Yamada ret = uniphier_memconf_decode(dram_ch); 2053e9952beSMasahiro Yamada if (ret) 2063e9952beSMasahiro Yamada return ret; 2073e9952beSMasahiro Yamada 2083e9952beSMasahiro Yamada for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { 2093e9952beSMasahiro Yamada 2103e9952beSMasahiro Yamada if (!dram_ch[i].size) 2113e9952beSMasahiro Yamada break; 2123e9952beSMasahiro Yamada 2133e9952beSMasahiro Yamada /* 2143e9952beSMasahiro Yamada * U-Boot relocates itself to the tail of the memory region, 2153e9952beSMasahiro Yamada * but it does not expect sparse memory. We use the first 2163e9952beSMasahiro Yamada * contiguous chunk here. 2173e9952beSMasahiro Yamada */ 2183e9952beSMasahiro Yamada if (i > 0 && 2193e9952beSMasahiro Yamada dram_ch[i - 1].base + dram_ch[i - 1].size < dram_ch[i].base) 2203e9952beSMasahiro Yamada break; 2213e9952beSMasahiro Yamada 2223e9952beSMasahiro Yamada gd->ram_size += dram_ch[i].size; 223ac2a1030SMasahiro Yamada } 224ac2a1030SMasahiro Yamada 2254c425570SMasahiro Yamada return 0; 2264c425570SMasahiro Yamada } 227cf88affaSMasahiro Yamada 228cf88affaSMasahiro Yamada void dram_init_banksize(void) 229cf88affaSMasahiro Yamada { 2303e9952beSMasahiro Yamada struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH] = {}; 2313e9952beSMasahiro Yamada int i; 232cf88affaSMasahiro Yamada 2333e9952beSMasahiro Yamada uniphier_memconf_decode(dram_ch); 234cf88affaSMasahiro Yamada 2353e9952beSMasahiro Yamada for (i = 0; i < ARRAY_SIZE(dram_ch); i++) { 2363e9952beSMasahiro Yamada if (i >= ARRAY_SIZE(gd->bd->bi_dram)) 2373e9952beSMasahiro Yamada break; 238cf88affaSMasahiro Yamada 2393e9952beSMasahiro Yamada gd->bd->bi_dram[i].start = dram_ch[i].base; 2403e9952beSMasahiro Yamada gd->bd->bi_dram[i].size = dram_ch[i].size; 241cf88affaSMasahiro Yamada } 242cf88affaSMasahiro Yamada } 24351ea5a06SMasahiro Yamada 24451ea5a06SMasahiro Yamada #ifdef CONFIG_OF_BOARD_SETUP 24551ea5a06SMasahiro Yamada /* 24651ea5a06SMasahiro Yamada * The DRAM PHY requires 64 byte scratch area in each DRAM channel 24751ea5a06SMasahiro Yamada * for its dynamic PHY training feature. 24851ea5a06SMasahiro Yamada */ 24951ea5a06SMasahiro Yamada int ft_board_setup(void *fdt, bd_t *bd) 25051ea5a06SMasahiro Yamada { 25151ea5a06SMasahiro Yamada unsigned long rsv_addr; 25251ea5a06SMasahiro Yamada const unsigned long rsv_size = 64; 253c995f3a3SMasahiro Yamada int i, ret; 25451ea5a06SMasahiro Yamada 255e27d6c7dSMasahiro Yamada if (uniphier_get_soc_id() != UNIPHIER_LD20_ID) 25651ea5a06SMasahiro Yamada return 0; 25751ea5a06SMasahiro Yamada 258c995f3a3SMasahiro Yamada for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) { 259c995f3a3SMasahiro Yamada rsv_addr = gd->bd->bi_dram[i].start + gd->bd->bi_dram[i].size; 26051ea5a06SMasahiro Yamada rsv_addr -= rsv_size; 26151ea5a06SMasahiro Yamada 26251ea5a06SMasahiro Yamada ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); 26351ea5a06SMasahiro Yamada if (ret) 26451ea5a06SMasahiro Yamada return -ENOSPC; 26551ea5a06SMasahiro Yamada 26651ea5a06SMasahiro Yamada printf(" Reserved memory region for DRAM PHY training: addr=%lx size=%lx\n", 26751ea5a06SMasahiro Yamada rsv_addr, rsv_size); 26851ea5a06SMasahiro Yamada } 26951ea5a06SMasahiro Yamada 27051ea5a06SMasahiro Yamada return 0; 27151ea5a06SMasahiro Yamada } 27251ea5a06SMasahiro Yamada #endif 273