xref: /rk3399_rockchip-uboot/arch/arm/mach-uniphier/dram_init.c (revision a9a4552a1c74e57a15d331bc9da00f046de9985f)
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>
10*1d21e1b9SMasahiro Yamada #include <fdt_support.h>
117b3a032dSMasahiro Yamada #include <fdtdec.h>
120f4ec05bSMasahiro Yamada #include <linux/errno.h>
133e9952beSMasahiro Yamada #include <linux/sizes.h>
14cf88affaSMasahiro Yamada 
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_LD4_ID,
293e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
303e9952beSMasahiro Yamada 	},
313e9952beSMasahiro Yamada 	{
323e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_PRO4_ID,
333e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xa0000000,
343e9952beSMasahiro Yamada 	},
353e9952beSMasahiro Yamada 	{
363e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_SLD8_ID,
373e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
383e9952beSMasahiro Yamada 	},
393e9952beSMasahiro Yamada 	{
403e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_PRO5_ID,
413e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
423e9952beSMasahiro Yamada 	},
433e9952beSMasahiro Yamada 	{
443e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_PXS2_ID,
453e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
463e9952beSMasahiro Yamada 		.have_ch2 = 1,
473e9952beSMasahiro Yamada 	},
483e9952beSMasahiro Yamada 	{
493e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_LD6B_ID,
503e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
513e9952beSMasahiro Yamada 		.have_ch2 = 1,
523e9952beSMasahiro Yamada 	},
533e9952beSMasahiro Yamada 	{
543e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_LD11_ID,
553e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
563e9952beSMasahiro Yamada 	},
573e9952beSMasahiro Yamada 	{
583e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_LD20_ID,
593e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
603e9952beSMasahiro Yamada 		.have_ch2 = 1,
613e9952beSMasahiro Yamada 	},
623e9952beSMasahiro Yamada 	{
633e9952beSMasahiro Yamada 		.soc_id = UNIPHIER_PXS3_ID,
643e9952beSMasahiro Yamada 		.sparse_ch1_base = 0xc0000000,
653e9952beSMasahiro Yamada 		.have_ch2 = 1,
663e9952beSMasahiro Yamada 	},
673e9952beSMasahiro Yamada };
683e9952beSMasahiro Yamada UNIPHIER_DEFINE_SOCDATA_FUNC(uniphier_get_memif_data, uniphier_memif_data)
69cf88affaSMasahiro Yamada 
7004cd4e72SMasahiro Yamada struct uniphier_dram_map {
7104cd4e72SMasahiro Yamada 	unsigned long base;
7204cd4e72SMasahiro Yamada 	unsigned long size;
7304cd4e72SMasahiro Yamada };
7404cd4e72SMasahiro Yamada 
uniphier_memconf_decode(struct uniphier_dram_map * dram_map)7504cd4e72SMasahiro Yamada static int uniphier_memconf_decode(struct uniphier_dram_map *dram_map)
763e9952beSMasahiro Yamada {
773e9952beSMasahiro Yamada 	const struct uniphier_memif_data *data;
783e9952beSMasahiro Yamada 	unsigned long size;
793e9952beSMasahiro Yamada 	u32 val;
80cf88affaSMasahiro Yamada 
813e9952beSMasahiro Yamada 	data = uniphier_get_memif_data();
823e9952beSMasahiro Yamada 	if (!data) {
833e9952beSMasahiro Yamada 		pr_err("unsupported SoC\n");
843e9952beSMasahiro Yamada 		return -EINVAL;
853e9952beSMasahiro Yamada 	}
863e9952beSMasahiro Yamada 
873e9952beSMasahiro Yamada 	val = readl(SG_MEMCONF);
883e9952beSMasahiro Yamada 
893e9952beSMasahiro Yamada 	/* set up ch0 */
9004cd4e72SMasahiro Yamada 	dram_map[0].base = CONFIG_SYS_SDRAM_BASE;
913e9952beSMasahiro Yamada 
923e9952beSMasahiro Yamada 	switch (val & SG_MEMCONF_CH0_SZ_MASK) {
933e9952beSMasahiro Yamada 	case SG_MEMCONF_CH0_SZ_64M:
943e9952beSMasahiro Yamada 		size = SZ_64M;
953e9952beSMasahiro Yamada 		break;
963e9952beSMasahiro Yamada 	case SG_MEMCONF_CH0_SZ_128M:
973e9952beSMasahiro Yamada 		size = SZ_128M;
983e9952beSMasahiro Yamada 		break;
993e9952beSMasahiro Yamada 	case SG_MEMCONF_CH0_SZ_256M:
1003e9952beSMasahiro Yamada 		size = SZ_256M;
1013e9952beSMasahiro Yamada 		break;
1023e9952beSMasahiro Yamada 	case SG_MEMCONF_CH0_SZ_512M:
1033e9952beSMasahiro Yamada 		size = SZ_512M;
1043e9952beSMasahiro Yamada 		break;
1053e9952beSMasahiro Yamada 	case SG_MEMCONF_CH0_SZ_1G:
1063e9952beSMasahiro Yamada 		size = SZ_1G;
1073e9952beSMasahiro Yamada 		break;
1083e9952beSMasahiro Yamada 	default:
1090f5bf09cSMasahiro Yamada 		pr_err("error: invalid value is set to MEMCONF ch0 size\n");
1103e9952beSMasahiro Yamada 		return -EINVAL;
1113e9952beSMasahiro Yamada 	}
1123e9952beSMasahiro Yamada 
1133e9952beSMasahiro Yamada 	if ((val & SG_MEMCONF_CH0_NUM_MASK) == SG_MEMCONF_CH0_NUM_2)
1143e9952beSMasahiro Yamada 		size *= 2;
1153e9952beSMasahiro Yamada 
11604cd4e72SMasahiro Yamada 	dram_map[0].size = size;
1173e9952beSMasahiro Yamada 
1183e9952beSMasahiro Yamada 	/* set up ch1 */
11904cd4e72SMasahiro Yamada 	dram_map[1].base = dram_map[0].base + size;
1203e9952beSMasahiro Yamada 
1213e9952beSMasahiro Yamada 	if (val & SG_MEMCONF_SPARSEMEM) {
12204cd4e72SMasahiro Yamada 		if (dram_map[1].base > data->sparse_ch1_base) {
1233e9952beSMasahiro Yamada 			pr_warn("Sparse mem is enabled, but ch0 and ch1 overlap\n");
1243e9952beSMasahiro Yamada 			pr_warn("Only ch0 is available\n");
12504cd4e72SMasahiro Yamada 			dram_map[1].base = 0;
1263e9952beSMasahiro Yamada 			return 0;
1273e9952beSMasahiro Yamada 		}
1283e9952beSMasahiro Yamada 
12904cd4e72SMasahiro Yamada 		dram_map[1].base = data->sparse_ch1_base;
1303e9952beSMasahiro Yamada 	}
1313e9952beSMasahiro Yamada 
1323e9952beSMasahiro Yamada 	switch (val & SG_MEMCONF_CH1_SZ_MASK) {
1333e9952beSMasahiro Yamada 	case SG_MEMCONF_CH1_SZ_64M:
1343e9952beSMasahiro Yamada 		size = SZ_64M;
1353e9952beSMasahiro Yamada 		break;
1363e9952beSMasahiro Yamada 	case SG_MEMCONF_CH1_SZ_128M:
1373e9952beSMasahiro Yamada 		size = SZ_128M;
1383e9952beSMasahiro Yamada 		break;
1393e9952beSMasahiro Yamada 	case SG_MEMCONF_CH1_SZ_256M:
1403e9952beSMasahiro Yamada 		size = SZ_256M;
1413e9952beSMasahiro Yamada 		break;
1423e9952beSMasahiro Yamada 	case SG_MEMCONF_CH1_SZ_512M:
1433e9952beSMasahiro Yamada 		size = SZ_512M;
1443e9952beSMasahiro Yamada 		break;
1453e9952beSMasahiro Yamada 	case SG_MEMCONF_CH1_SZ_1G:
1463e9952beSMasahiro Yamada 		size = SZ_1G;
1473e9952beSMasahiro Yamada 		break;
1483e9952beSMasahiro Yamada 	default:
1490f5bf09cSMasahiro Yamada 		pr_err("error: invalid value is set to MEMCONF ch1 size\n");
1503e9952beSMasahiro Yamada 		return -EINVAL;
1513e9952beSMasahiro Yamada 	}
1523e9952beSMasahiro Yamada 
1533e9952beSMasahiro Yamada 	if ((val & SG_MEMCONF_CH1_NUM_MASK) == SG_MEMCONF_CH1_NUM_2)
1543e9952beSMasahiro Yamada 		size *= 2;
1553e9952beSMasahiro Yamada 
15604cd4e72SMasahiro Yamada 	dram_map[1].size = size;
1573e9952beSMasahiro Yamada 
158bed1624dSMasahiro Yamada 	if (!data->have_ch2 || val & SG_MEMCONF_CH2_DISABLE)
1593e9952beSMasahiro Yamada 		return 0;
1603e9952beSMasahiro Yamada 
1613e9952beSMasahiro Yamada 	/* set up ch2 */
16204cd4e72SMasahiro Yamada 	dram_map[2].base = dram_map[1].base + size;
1633e9952beSMasahiro Yamada 
1643e9952beSMasahiro Yamada 	switch (val & SG_MEMCONF_CH2_SZ_MASK) {
1653e9952beSMasahiro Yamada 	case SG_MEMCONF_CH2_SZ_64M:
1663e9952beSMasahiro Yamada 		size = SZ_64M;
1673e9952beSMasahiro Yamada 		break;
1683e9952beSMasahiro Yamada 	case SG_MEMCONF_CH2_SZ_128M:
1693e9952beSMasahiro Yamada 		size = SZ_128M;
1703e9952beSMasahiro Yamada 		break;
1713e9952beSMasahiro Yamada 	case SG_MEMCONF_CH2_SZ_256M:
1723e9952beSMasahiro Yamada 		size = SZ_256M;
1733e9952beSMasahiro Yamada 		break;
1743e9952beSMasahiro Yamada 	case SG_MEMCONF_CH2_SZ_512M:
1753e9952beSMasahiro Yamada 		size = SZ_512M;
1763e9952beSMasahiro Yamada 		break;
1773e9952beSMasahiro Yamada 	case SG_MEMCONF_CH2_SZ_1G:
1783e9952beSMasahiro Yamada 		size = SZ_1G;
1793e9952beSMasahiro Yamada 		break;
1803e9952beSMasahiro Yamada 	default:
1810f5bf09cSMasahiro Yamada 		pr_err("error: invalid value is set to MEMCONF ch2 size\n");
1823e9952beSMasahiro Yamada 		return -EINVAL;
1833e9952beSMasahiro Yamada 	}
1843e9952beSMasahiro Yamada 
1853e9952beSMasahiro Yamada 	if ((val & SG_MEMCONF_CH2_NUM_MASK) == SG_MEMCONF_CH2_NUM_2)
1863e9952beSMasahiro Yamada 		size *= 2;
1873e9952beSMasahiro Yamada 
18804cd4e72SMasahiro Yamada 	dram_map[2].size = size;
1893e9952beSMasahiro Yamada 
1903e9952beSMasahiro Yamada 	return 0;
191cf88affaSMasahiro Yamada }
1924c425570SMasahiro Yamada 
dram_init(void)1934c425570SMasahiro Yamada int dram_init(void)
1944c425570SMasahiro Yamada {
19504cd4e72SMasahiro Yamada 	struct uniphier_dram_map dram_map[3] = {};
1963e9952beSMasahiro Yamada 	int ret, i;
197cf88affaSMasahiro Yamada 
1983e9952beSMasahiro Yamada 	gd->ram_size = 0;
1993e9952beSMasahiro Yamada 
20004cd4e72SMasahiro Yamada 	ret = uniphier_memconf_decode(dram_map);
2013e9952beSMasahiro Yamada 	if (ret)
2023e9952beSMasahiro Yamada 		return ret;
2033e9952beSMasahiro Yamada 
20404cd4e72SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
2053e9952beSMasahiro Yamada 
20604cd4e72SMasahiro Yamada 		if (!dram_map[i].size)
2073e9952beSMasahiro Yamada 			break;
2083e9952beSMasahiro Yamada 
2093e9952beSMasahiro Yamada 		/*
2103e9952beSMasahiro Yamada 		 * U-Boot relocates itself to the tail of the memory region,
2113e9952beSMasahiro Yamada 		 * but it does not expect sparse memory.  We use the first
2123e9952beSMasahiro Yamada 		 * contiguous chunk here.
2133e9952beSMasahiro Yamada 		 */
21404cd4e72SMasahiro Yamada 		if (i > 0 && dram_map[i - 1].base + dram_map[i - 1].size <
21504cd4e72SMasahiro Yamada 							dram_map[i].base)
2163e9952beSMasahiro Yamada 			break;
2173e9952beSMasahiro Yamada 
21804cd4e72SMasahiro Yamada 		gd->ram_size += dram_map[i].size;
219ac2a1030SMasahiro Yamada 	}
220ac2a1030SMasahiro Yamada 
2214c425570SMasahiro Yamada 	return 0;
2224c425570SMasahiro Yamada }
223cf88affaSMasahiro Yamada 
dram_init_banksize(void)22476b00acaSSimon Glass int dram_init_banksize(void)
225cf88affaSMasahiro Yamada {
22604cd4e72SMasahiro Yamada 	struct uniphier_dram_map dram_map[3] = {};
2273e9952beSMasahiro Yamada 	int i;
228cf88affaSMasahiro Yamada 
22904cd4e72SMasahiro Yamada 	uniphier_memconf_decode(dram_map);
230cf88affaSMasahiro Yamada 
23104cd4e72SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
2323e9952beSMasahiro Yamada 		if (i >= ARRAY_SIZE(gd->bd->bi_dram))
2333e9952beSMasahiro Yamada 			break;
234cf88affaSMasahiro Yamada 
23504cd4e72SMasahiro Yamada 		gd->bd->bi_dram[i].start = dram_map[i].base;
23604cd4e72SMasahiro Yamada 		gd->bd->bi_dram[i].size = dram_map[i].size;
237cf88affaSMasahiro Yamada 	}
23876b00acaSSimon Glass 
23976b00acaSSimon Glass 	return 0;
240cf88affaSMasahiro Yamada }
24151ea5a06SMasahiro Yamada 
24251ea5a06SMasahiro Yamada #ifdef CONFIG_OF_BOARD_SETUP
24351ea5a06SMasahiro Yamada /*
24451ea5a06SMasahiro Yamada  * The DRAM PHY requires 64 byte scratch area in each DRAM channel
24551ea5a06SMasahiro Yamada  * for its dynamic PHY training feature.
24651ea5a06SMasahiro Yamada  */
ft_board_setup(void * fdt,bd_t * bd)24751ea5a06SMasahiro Yamada int ft_board_setup(void *fdt, bd_t *bd)
24851ea5a06SMasahiro Yamada {
24951ea5a06SMasahiro Yamada 	unsigned long rsv_addr;
25051ea5a06SMasahiro Yamada 	const unsigned long rsv_size = 64;
251c995f3a3SMasahiro Yamada 	int i, ret;
25251ea5a06SMasahiro Yamada 
253e27d6c7dSMasahiro Yamada 	if (uniphier_get_soc_id() != UNIPHIER_LD20_ID)
25451ea5a06SMasahiro Yamada 		return 0;
25551ea5a06SMasahiro Yamada 
256c995f3a3SMasahiro Yamada 	for (i = 0; i < ARRAY_SIZE(gd->bd->bi_dram); i++) {
25787c3308cSMasahiro Yamada 		if (!gd->bd->bi_dram[i].size)
25887c3308cSMasahiro Yamada 			continue;
25987c3308cSMasahiro Yamada 
260c995f3a3SMasahiro Yamada 		rsv_addr = gd->bd->bi_dram[i].start + gd->bd->bi_dram[i].size;
26151ea5a06SMasahiro Yamada 		rsv_addr -= rsv_size;
26251ea5a06SMasahiro Yamada 
26351ea5a06SMasahiro Yamada 		ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size);
26451ea5a06SMasahiro Yamada 		if (ret)
26551ea5a06SMasahiro Yamada 			return -ENOSPC;
26651ea5a06SMasahiro Yamada 
26751ea5a06SMasahiro Yamada 		printf("   Reserved memory region for DRAM PHY training: addr=%lx size=%lx\n",
26851ea5a06SMasahiro Yamada 		       rsv_addr, rsv_size);
26951ea5a06SMasahiro Yamada 	}
27051ea5a06SMasahiro Yamada 
27151ea5a06SMasahiro Yamada 	return 0;
27251ea5a06SMasahiro Yamada }
27351ea5a06SMasahiro Yamada #endif
274