xref: /rk3399_rockchip-uboot/arch/arm/mach-aspeed/ast2500/sdram_ast2500.c (revision 4f66e09bb9fbc47b73f67c3cc08ee2663e8fcdb1)
114e4b149Smaxims@google.com /*
214e4b149Smaxims@google.com  * Copyright (C) 2012-2020  ASPEED Technology Inc.
314e4b149Smaxims@google.com  *
414e4b149Smaxims@google.com  * Copyright 2016 Google, Inc
514e4b149Smaxims@google.com  *
614e4b149Smaxims@google.com  * SPDX-License-Identifier:		GPL-2.0
714e4b149Smaxims@google.com  */
814e4b149Smaxims@google.com 
914e4b149Smaxims@google.com #include <common.h>
1014e4b149Smaxims@google.com #include <clk.h>
1114e4b149Smaxims@google.com #include <dm.h>
1214e4b149Smaxims@google.com #include <errno.h>
1314e4b149Smaxims@google.com #include <ram.h>
1414e4b149Smaxims@google.com #include <regmap.h>
1599f8ad73Smaxims@google.com #include <reset.h>
1614e4b149Smaxims@google.com #include <asm/io.h>
1714e4b149Smaxims@google.com #include <asm/arch/scu_ast2500.h>
1814e4b149Smaxims@google.com #include <asm/arch/sdram_ast2500.h>
1914e4b149Smaxims@google.com #include <asm/arch/wdt.h>
2014e4b149Smaxims@google.com #include <linux/err.h>
2114e4b149Smaxims@google.com #include <linux/kernel.h>
2214e4b149Smaxims@google.com #include <dt-bindings/clock/ast2500-scu.h>
2314e4b149Smaxims@google.com 
2414e4b149Smaxims@google.com /* These configuration parameters are taken from Aspeed SDK */
2514e4b149Smaxims@google.com #define DDR4_MR46_MODE		0x08000000
2614e4b149Smaxims@google.com #define DDR4_MR5_MODE		0x400
2714e4b149Smaxims@google.com #define DDR4_MR13_MODE		0x101
2814e4b149Smaxims@google.com #define DDR4_MR02_MODE		0x410
2914e4b149Smaxims@google.com #define DDR4_TRFC		0x45457188
3014e4b149Smaxims@google.com 
3114e4b149Smaxims@google.com #define PHY_CFG_SIZE		15
3214e4b149Smaxims@google.com 
3314e4b149Smaxims@google.com static const u32 ddr4_ac_timing[3] = {0x63604e37, 0xe97afa99, 0x00019000};
3414e4b149Smaxims@google.com static const struct {
3514e4b149Smaxims@google.com 	u32 index[PHY_CFG_SIZE];
3614e4b149Smaxims@google.com 	u32 value[PHY_CFG_SIZE];
3714e4b149Smaxims@google.com } ddr4_phy_config = {
3814e4b149Smaxims@google.com 	.index = {0, 1, 3, 4, 5, 56, 57, 58, 59, 60, 61, 62, 36, 49, 50},
3914e4b149Smaxims@google.com 	.value = {
4014e4b149Smaxims@google.com 		0x42492aae, 0x09002000, 0x55e00b0b, 0x20000000, 0x24,
4114e4b149Smaxims@google.com 		0x03002900, 0x0e0000a0, 0x000e001c, 0x35b8c106, 0x08080607,
4214e4b149Smaxims@google.com 		0x9b000900, 0x0e400a00, 0x00100008, 0x3c183c3c, 0x00631e0e,
4314e4b149Smaxims@google.com 	},
4414e4b149Smaxims@google.com };
4514e4b149Smaxims@google.com 
4614e4b149Smaxims@google.com #define SDRAM_MAX_SIZE		(1024 * 1024 * 1024)
4714e4b149Smaxims@google.com #define SDRAM_MIN_SIZE		(128 * 1024 * 1024)
4814e4b149Smaxims@google.com 
4914e4b149Smaxims@google.com DECLARE_GLOBAL_DATA_PTR;
5014e4b149Smaxims@google.com 
5114e4b149Smaxims@google.com /*
5214e4b149Smaxims@google.com  * Bandwidth configuration parameters for different SDRAM requests.
5314e4b149Smaxims@google.com  * These are hardcoded settings taken from Aspeed SDK.
5414e4b149Smaxims@google.com  */
5514e4b149Smaxims@google.com static const u32 ddr_max_grant_params[4] = {
5614e4b149Smaxims@google.com 	0x88448844, 0x24422288, 0x22222222, 0x22222222
5714e4b149Smaxims@google.com };
5814e4b149Smaxims@google.com 
5914e4b149Smaxims@google.com /*
6014e4b149Smaxims@google.com  * These registers are not documented by Aspeed at all.
6114e4b149Smaxims@google.com  * All writes and reads are taken pretty much as is from SDK.
6214e4b149Smaxims@google.com  */
6314e4b149Smaxims@google.com struct ast2500_ddr_phy {
6414e4b149Smaxims@google.com 	u32 phy[117];
6514e4b149Smaxims@google.com };
6614e4b149Smaxims@google.com 
6714e4b149Smaxims@google.com struct dram_info {
6814e4b149Smaxims@google.com 	struct ram_info info;
6914e4b149Smaxims@google.com 	struct clk ddr_clk;
7014e4b149Smaxims@google.com 	struct ast2500_sdrammc_regs *regs;
7114e4b149Smaxims@google.com 	struct ast2500_scu *scu;
7214e4b149Smaxims@google.com 	struct ast2500_ddr_phy *phy;
7314e4b149Smaxims@google.com 	ulong clock_rate;
7414e4b149Smaxims@google.com };
7514e4b149Smaxims@google.com 
ast2500_sdrammc_init_phy(struct ast2500_ddr_phy * phy)7614e4b149Smaxims@google.com static int ast2500_sdrammc_init_phy(struct ast2500_ddr_phy *phy)
7714e4b149Smaxims@google.com {
7814e4b149Smaxims@google.com 	writel(0, &phy->phy[2]);
7914e4b149Smaxims@google.com 	writel(0, &phy->phy[6]);
8014e4b149Smaxims@google.com 	writel(0, &phy->phy[8]);
8114e4b149Smaxims@google.com 	writel(0, &phy->phy[10]);
8214e4b149Smaxims@google.com 	writel(0, &phy->phy[12]);
8314e4b149Smaxims@google.com 	writel(0, &phy->phy[42]);
8414e4b149Smaxims@google.com 	writel(0, &phy->phy[44]);
8514e4b149Smaxims@google.com 
8614e4b149Smaxims@google.com 	writel(0x86000000, &phy->phy[16]);
8714e4b149Smaxims@google.com 	writel(0x00008600, &phy->phy[17]);
8814e4b149Smaxims@google.com 	writel(0x80000000, &phy->phy[18]);
8914e4b149Smaxims@google.com 	writel(0x80808080, &phy->phy[19]);
9014e4b149Smaxims@google.com 
9114e4b149Smaxims@google.com 	return 0;
9214e4b149Smaxims@google.com }
9314e4b149Smaxims@google.com 
ast2500_ddr_phy_init_process(struct dram_info * info)9414e4b149Smaxims@google.com static void ast2500_ddr_phy_init_process(struct dram_info *info)
9514e4b149Smaxims@google.com {
9614e4b149Smaxims@google.com 	struct ast2500_sdrammc_regs *regs = info->regs;
9714e4b149Smaxims@google.com 
9814e4b149Smaxims@google.com 	writel(0, &regs->phy_ctrl[0]);
9914e4b149Smaxims@google.com 	writel(0x4040, &info->phy->phy[51]);
10014e4b149Smaxims@google.com 
10114e4b149Smaxims@google.com 	writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_INIT, &regs->phy_ctrl[0]);
10214e4b149Smaxims@google.com 	while ((readl(&regs->phy_ctrl[0]) & SDRAM_PHYCTRL0_INIT))
10314e4b149Smaxims@google.com 		;
10414e4b149Smaxims@google.com 	writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_AUTO_UPDATE,
10514e4b149Smaxims@google.com 	       &regs->phy_ctrl[0]);
10614e4b149Smaxims@google.com }
10714e4b149Smaxims@google.com 
ast2500_sdrammc_set_vref(struct dram_info * info,u32 vref)10814e4b149Smaxims@google.com static void ast2500_sdrammc_set_vref(struct dram_info *info, u32 vref)
10914e4b149Smaxims@google.com {
11014e4b149Smaxims@google.com 	writel(0, &info->regs->phy_ctrl[0]);
11114e4b149Smaxims@google.com 	writel((vref << 8) | 0x6, &info->phy->phy[48]);
11214e4b149Smaxims@google.com 	ast2500_ddr_phy_init_process(info);
11314e4b149Smaxims@google.com }
11414e4b149Smaxims@google.com 
ast2500_ddr_cbr_test(struct dram_info * info)11514e4b149Smaxims@google.com static int ast2500_ddr_cbr_test(struct dram_info *info)
11614e4b149Smaxims@google.com {
11714e4b149Smaxims@google.com 	struct ast2500_sdrammc_regs *regs = info->regs;
11814e4b149Smaxims@google.com 	int i;
11914e4b149Smaxims@google.com 	const u32 test_params = SDRAM_TEST_EN
12014e4b149Smaxims@google.com 			| SDRAM_TEST_ERRSTOP
12114e4b149Smaxims@google.com 			| SDRAM_TEST_TWO_MODES;
12214e4b149Smaxims@google.com 	int ret = 0;
12314e4b149Smaxims@google.com 
12414e4b149Smaxims@google.com 	writel((1 << SDRAM_REFRESH_CYCLES_SHIFT) |
12514e4b149Smaxims@google.com 	       (0x5c << SDRAM_REFRESH_PERIOD_SHIFT), &regs->refresh_timing);
12614e4b149Smaxims@google.com 	writel((0xfff << SDRAM_TEST_LEN_SHIFT), &regs->test_addr);
12714e4b149Smaxims@google.com 	writel(0xff00ff00, &regs->test_init_val);
12814e4b149Smaxims@google.com 	writel(SDRAM_TEST_EN | (SDRAM_TEST_MODE_RW << SDRAM_TEST_MODE_SHIFT) |
12914e4b149Smaxims@google.com 	       SDRAM_TEST_ERRSTOP, &regs->ecc_test_ctrl);
13014e4b149Smaxims@google.com 
13114e4b149Smaxims@google.com 	while (!(readl(&regs->ecc_test_ctrl) & SDRAM_TEST_DONE))
13214e4b149Smaxims@google.com 		;
13314e4b149Smaxims@google.com 
13414e4b149Smaxims@google.com 	if (readl(&regs->ecc_test_ctrl) & SDRAM_TEST_FAIL) {
13514e4b149Smaxims@google.com 		ret = -EIO;
13614e4b149Smaxims@google.com 	} else {
13714e4b149Smaxims@google.com 		for (i = 0; i <= SDRAM_TEST_GEN_MODE_MASK; ++i) {
13814e4b149Smaxims@google.com 			writel((i << SDRAM_TEST_GEN_MODE_SHIFT) | test_params,
13914e4b149Smaxims@google.com 			       &regs->ecc_test_ctrl);
14014e4b149Smaxims@google.com 			while (!(readl(&regs->ecc_test_ctrl) & SDRAM_TEST_DONE))
14114e4b149Smaxims@google.com 				;
14214e4b149Smaxims@google.com 			if (readl(&regs->ecc_test_ctrl) & SDRAM_TEST_FAIL) {
14314e4b149Smaxims@google.com 				ret = -EIO;
14414e4b149Smaxims@google.com 				break;
14514e4b149Smaxims@google.com 			}
14614e4b149Smaxims@google.com 		}
14714e4b149Smaxims@google.com 	}
14814e4b149Smaxims@google.com 
14914e4b149Smaxims@google.com 	writel(0, &regs->refresh_timing);
15014e4b149Smaxims@google.com 	writel(0, &regs->ecc_test_ctrl);
15114e4b149Smaxims@google.com 
15214e4b149Smaxims@google.com 	return ret;
15314e4b149Smaxims@google.com }
15414e4b149Smaxims@google.com 
ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info * info)15514e4b149Smaxims@google.com static int ast2500_sdrammc_ddr4_calibrate_vref(struct dram_info *info)
15614e4b149Smaxims@google.com {
15714e4b149Smaxims@google.com 	int i;
15814e4b149Smaxims@google.com 	int vref_min = 0xff;
15914e4b149Smaxims@google.com 	int vref_max = 0;
16014e4b149Smaxims@google.com 	int range_size = 0;
16114e4b149Smaxims@google.com 
16214e4b149Smaxims@google.com 	for (i = 1; i < 0x40; ++i) {
16314e4b149Smaxims@google.com 		int res;
16414e4b149Smaxims@google.com 
16514e4b149Smaxims@google.com 		ast2500_sdrammc_set_vref(info, i);
16614e4b149Smaxims@google.com 		res = ast2500_ddr_cbr_test(info);
16714e4b149Smaxims@google.com 		if (res < 0) {
16814e4b149Smaxims@google.com 			if (range_size > 0)
16914e4b149Smaxims@google.com 				break;
17014e4b149Smaxims@google.com 		} else {
17114e4b149Smaxims@google.com 			++range_size;
17214e4b149Smaxims@google.com 			vref_min = min(vref_min, i);
17314e4b149Smaxims@google.com 			vref_max = max(vref_max, i);
17414e4b149Smaxims@google.com 		}
17514e4b149Smaxims@google.com 	}
17614e4b149Smaxims@google.com 
17714e4b149Smaxims@google.com 	/* Pick average setting */
17814e4b149Smaxims@google.com 	ast2500_sdrammc_set_vref(info, (vref_min + vref_max + 1) / 2);
17914e4b149Smaxims@google.com 
18014e4b149Smaxims@google.com 	return 0;
18114e4b149Smaxims@google.com }
18214e4b149Smaxims@google.com 
ast2500_sdrammc_get_vga_mem_size(struct dram_info * info)18314e4b149Smaxims@google.com static size_t ast2500_sdrammc_get_vga_mem_size(struct dram_info *info)
18414e4b149Smaxims@google.com {
18514e4b149Smaxims@google.com 	size_t vga_mem_size_base = 8 * 1024 * 1024;
186*defb1849Smaxims@google.com 	u32 vga_hwconf = (readl(&info->scu->hwstrap) & SCU_HWSTRAP_VGAMEM_MASK)
187*defb1849Smaxims@google.com 	    >> SCU_HWSTRAP_VGAMEM_SHIFT;
18814e4b149Smaxims@google.com 
18914e4b149Smaxims@google.com 	return vga_mem_size_base << vga_hwconf;
19014e4b149Smaxims@google.com }
19114e4b149Smaxims@google.com 
19214e4b149Smaxims@google.com /*
19314e4b149Smaxims@google.com  * Find out RAM size and save it in dram_info
19414e4b149Smaxims@google.com  *
19514e4b149Smaxims@google.com  * The procedure is taken from Aspeed SDK
19614e4b149Smaxims@google.com  */
ast2500_sdrammc_calc_size(struct dram_info * info)19714e4b149Smaxims@google.com static void ast2500_sdrammc_calc_size(struct dram_info *info)
19814e4b149Smaxims@google.com {
19914e4b149Smaxims@google.com 	/* The controller supports 128/256/512/1024 MB ram */
20014e4b149Smaxims@google.com 	size_t ram_size = SDRAM_MIN_SIZE;
20114e4b149Smaxims@google.com 	const int write_test_offset = 0x100000;
20214e4b149Smaxims@google.com 	u32 test_pattern = 0xdeadbeef;
20314e4b149Smaxims@google.com 	u32 cap_param = SDRAM_CONF_CAP_1024M;
20414e4b149Smaxims@google.com 	u32 refresh_timing_param = DDR4_TRFC;
20514e4b149Smaxims@google.com 	const u32 write_addr_base = CONFIG_SYS_SDRAM_BASE + write_test_offset;
20614e4b149Smaxims@google.com 
20714e4b149Smaxims@google.com 	for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
20814e4b149Smaxims@google.com 	     ram_size >>= 1) {
20914e4b149Smaxims@google.com 		writel(test_pattern, write_addr_base + (ram_size >> 1));
21014e4b149Smaxims@google.com 		test_pattern = (test_pattern >> 4) | (test_pattern << 28);
21114e4b149Smaxims@google.com 	}
21214e4b149Smaxims@google.com 
21314e4b149Smaxims@google.com 	/* One last write to overwrite all wrapped values */
21414e4b149Smaxims@google.com 	writel(test_pattern, write_addr_base);
21514e4b149Smaxims@google.com 
21614e4b149Smaxims@google.com 	/* Reset the pattern and see which value was really written */
21714e4b149Smaxims@google.com 	test_pattern = 0xdeadbeef;
21814e4b149Smaxims@google.com 	for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
21914e4b149Smaxims@google.com 	     ram_size >>= 1) {
22014e4b149Smaxims@google.com 		if (readl(write_addr_base + (ram_size >> 1)) == test_pattern)
22114e4b149Smaxims@google.com 			break;
22214e4b149Smaxims@google.com 
22314e4b149Smaxims@google.com 		--cap_param;
22414e4b149Smaxims@google.com 		refresh_timing_param >>= 8;
22514e4b149Smaxims@google.com 		test_pattern = (test_pattern >> 4) | (test_pattern << 28);
22614e4b149Smaxims@google.com 	}
22714e4b149Smaxims@google.com 
22814e4b149Smaxims@google.com 	clrsetbits_le32(&info->regs->ac_timing[1],
22914e4b149Smaxims@google.com 			(SDRAM_AC_TRFC_MASK << SDRAM_AC_TRFC_SHIFT),
23014e4b149Smaxims@google.com 			((refresh_timing_param & SDRAM_AC_TRFC_MASK)
23114e4b149Smaxims@google.com 			 << SDRAM_AC_TRFC_SHIFT));
23214e4b149Smaxims@google.com 
23314e4b149Smaxims@google.com 	info->info.base = CONFIG_SYS_SDRAM_BASE;
23414e4b149Smaxims@google.com 	info->info.size = ram_size - ast2500_sdrammc_get_vga_mem_size(info);
23514e4b149Smaxims@google.com 	clrsetbits_le32(&info->regs->config,
23614e4b149Smaxims@google.com 			(SDRAM_CONF_CAP_MASK << SDRAM_CONF_CAP_SHIFT),
23714e4b149Smaxims@google.com 			((cap_param & SDRAM_CONF_CAP_MASK)
23814e4b149Smaxims@google.com 			 << SDRAM_CONF_CAP_SHIFT));
23914e4b149Smaxims@google.com }
24014e4b149Smaxims@google.com 
ast2500_sdrammc_init_ddr4(struct dram_info * info)24114e4b149Smaxims@google.com static int ast2500_sdrammc_init_ddr4(struct dram_info *info)
24214e4b149Smaxims@google.com {
24314e4b149Smaxims@google.com 	int i;
24414e4b149Smaxims@google.com 	const u32 power_control = SDRAM_PCR_CKE_EN
24514e4b149Smaxims@google.com 	    | (1 << SDRAM_PCR_CKE_DELAY_SHIFT)
24614e4b149Smaxims@google.com 	    | (2 << SDRAM_PCR_TCKE_PW_SHIFT)
24714e4b149Smaxims@google.com 	    | SDRAM_PCR_RESETN_DIS
24814e4b149Smaxims@google.com 	    | SDRAM_PCR_RGAP_CTRL_EN | SDRAM_PCR_ODT_EN | SDRAM_PCR_ODT_EXT_EN;
24914e4b149Smaxims@google.com 	const u32 conf = (SDRAM_CONF_CAP_1024M << SDRAM_CONF_CAP_SHIFT)
25014e4b149Smaxims@google.com #ifdef CONFIG_DUALX8_RAM
25114e4b149Smaxims@google.com 	    | SDRAM_CONF_DUALX8
25214e4b149Smaxims@google.com #endif
25314e4b149Smaxims@google.com 	    | SDRAM_CONF_SCRAMBLE | SDRAM_CONF_SCRAMBLE_PAT2 | SDRAM_CONF_DDR4;
25414e4b149Smaxims@google.com 	int ret;
25514e4b149Smaxims@google.com 
25614e4b149Smaxims@google.com 	writel(conf, &info->regs->config);
25714e4b149Smaxims@google.com 	for (i = 0; i < ARRAY_SIZE(ddr4_ac_timing); ++i)
25814e4b149Smaxims@google.com 		writel(ddr4_ac_timing[i], &info->regs->ac_timing[i]);
25914e4b149Smaxims@google.com 
26014e4b149Smaxims@google.com 	writel(DDR4_MR46_MODE, &info->regs->mr46_mode_setting);
26114e4b149Smaxims@google.com 	writel(DDR4_MR5_MODE, &info->regs->mr5_mode_setting);
26214e4b149Smaxims@google.com 	writel(DDR4_MR02_MODE, &info->regs->mr02_mode_setting);
26314e4b149Smaxims@google.com 	writel(DDR4_MR13_MODE, &info->regs->mr13_mode_setting);
26414e4b149Smaxims@google.com 
26514e4b149Smaxims@google.com 	for (i = 0; i < PHY_CFG_SIZE; ++i) {
26614e4b149Smaxims@google.com 		writel(ddr4_phy_config.value[i],
26714e4b149Smaxims@google.com 		       &info->phy->phy[ddr4_phy_config.index[i]]);
26814e4b149Smaxims@google.com 	}
26914e4b149Smaxims@google.com 
27014e4b149Smaxims@google.com 	writel(power_control, &info->regs->power_control);
27114e4b149Smaxims@google.com 
27214e4b149Smaxims@google.com 	ast2500_ddr_phy_init_process(info);
27314e4b149Smaxims@google.com 
27414e4b149Smaxims@google.com 	ret = ast2500_sdrammc_ddr4_calibrate_vref(info);
27514e4b149Smaxims@google.com 	if (ret < 0) {
27614e4b149Smaxims@google.com 		debug("Vref calibration failed!\n");
27714e4b149Smaxims@google.com 		return ret;
27814e4b149Smaxims@google.com 	}
27914e4b149Smaxims@google.com 
28014e4b149Smaxims@google.com 	writel((1 << SDRAM_REFRESH_CYCLES_SHIFT)
28114e4b149Smaxims@google.com 	       | SDRAM_REFRESH_ZQCS_EN | (0x2f << SDRAM_REFRESH_PERIOD_SHIFT),
28214e4b149Smaxims@google.com 	       &info->regs->refresh_timing);
28314e4b149Smaxims@google.com 
28414e4b149Smaxims@google.com 	setbits_le32(&info->regs->power_control,
28514e4b149Smaxims@google.com 		     SDRAM_PCR_AUTOPWRDN_EN | SDRAM_PCR_ODT_AUTO_ON);
28614e4b149Smaxims@google.com 
28714e4b149Smaxims@google.com 	ast2500_sdrammc_calc_size(info);
28814e4b149Smaxims@google.com 
28914e4b149Smaxims@google.com 	setbits_le32(&info->regs->config, SDRAM_CONF_CACHE_INIT_EN);
29014e4b149Smaxims@google.com 	while (!(readl(&info->regs->config) & SDRAM_CONF_CACHE_INIT_DONE))
29114e4b149Smaxims@google.com 		;
29214e4b149Smaxims@google.com 	setbits_le32(&info->regs->config, SDRAM_CONF_CACHE_EN);
29314e4b149Smaxims@google.com 
29414e4b149Smaxims@google.com 	writel(SDRAM_MISC_DDR4_TREFRESH, &info->regs->misc_control);
29514e4b149Smaxims@google.com 
29614e4b149Smaxims@google.com 	/* Enable all requests except video & display */
29714e4b149Smaxims@google.com 	writel(SDRAM_REQ_USB20_EHCI1
29814e4b149Smaxims@google.com 	       | SDRAM_REQ_USB20_EHCI2
29914e4b149Smaxims@google.com 	       | SDRAM_REQ_CPU
30014e4b149Smaxims@google.com 	       | SDRAM_REQ_AHB2
30114e4b149Smaxims@google.com 	       | SDRAM_REQ_AHB
30214e4b149Smaxims@google.com 	       | SDRAM_REQ_MAC0
30314e4b149Smaxims@google.com 	       | SDRAM_REQ_MAC1
30414e4b149Smaxims@google.com 	       | SDRAM_REQ_PCIE
30514e4b149Smaxims@google.com 	       | SDRAM_REQ_XDMA
30614e4b149Smaxims@google.com 	       | SDRAM_REQ_ENCRYPTION
30714e4b149Smaxims@google.com 	       | SDRAM_REQ_VIDEO_FLAG
30814e4b149Smaxims@google.com 	       | SDRAM_REQ_VIDEO_LOW_PRI_WRITE
30914e4b149Smaxims@google.com 	       | SDRAM_REQ_2D_RW
31014e4b149Smaxims@google.com 	       | SDRAM_REQ_MEMCHECK, &info->regs->req_limit_mask);
31114e4b149Smaxims@google.com 
31214e4b149Smaxims@google.com 	return 0;
31314e4b149Smaxims@google.com }
31414e4b149Smaxims@google.com 
ast2500_sdrammc_unlock(struct dram_info * info)31514e4b149Smaxims@google.com static void ast2500_sdrammc_unlock(struct dram_info *info)
31614e4b149Smaxims@google.com {
31714e4b149Smaxims@google.com 	writel(SDRAM_UNLOCK_KEY, &info->regs->protection_key);
31814e4b149Smaxims@google.com 	while (!readl(&info->regs->protection_key))
31914e4b149Smaxims@google.com 		;
32014e4b149Smaxims@google.com }
32114e4b149Smaxims@google.com 
ast2500_sdrammc_lock(struct dram_info * info)32214e4b149Smaxims@google.com static void ast2500_sdrammc_lock(struct dram_info *info)
32314e4b149Smaxims@google.com {
32414e4b149Smaxims@google.com 	writel(~SDRAM_UNLOCK_KEY, &info->regs->protection_key);
32514e4b149Smaxims@google.com 	while (readl(&info->regs->protection_key))
32614e4b149Smaxims@google.com 		;
32714e4b149Smaxims@google.com }
32814e4b149Smaxims@google.com 
ast2500_sdrammc_probe(struct udevice * dev)32914e4b149Smaxims@google.com static int ast2500_sdrammc_probe(struct udevice *dev)
33014e4b149Smaxims@google.com {
33199f8ad73Smaxims@google.com 	struct reset_ctl reset_ctl;
33214e4b149Smaxims@google.com 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
33314e4b149Smaxims@google.com 	struct ast2500_sdrammc_regs *regs = priv->regs;
33414e4b149Smaxims@google.com 	int i;
33514e4b149Smaxims@google.com 	int ret = clk_get_by_index(dev, 0, &priv->ddr_clk);
33614e4b149Smaxims@google.com 
33714e4b149Smaxims@google.com 	if (ret) {
33814e4b149Smaxims@google.com 		debug("DDR:No CLK\n");
33914e4b149Smaxims@google.com 		return ret;
34014e4b149Smaxims@google.com 	}
34114e4b149Smaxims@google.com 
34214e4b149Smaxims@google.com 	priv->scu = ast_get_scu();
34314e4b149Smaxims@google.com 	if (IS_ERR(priv->scu)) {
34414e4b149Smaxims@google.com 		debug("%s(): can't get SCU\n", __func__);
34514e4b149Smaxims@google.com 		return PTR_ERR(priv->scu);
34614e4b149Smaxims@google.com 	}
34714e4b149Smaxims@google.com 
34814e4b149Smaxims@google.com 	clk_set_rate(&priv->ddr_clk, priv->clock_rate);
34999f8ad73Smaxims@google.com 	ret = reset_get_by_index(dev, 0, &reset_ctl);
35014e4b149Smaxims@google.com 	if (ret) {
35199f8ad73Smaxims@google.com 		debug("%s(): Failed to get reset signal\n", __func__);
35299f8ad73Smaxims@google.com 		return ret;
35399f8ad73Smaxims@google.com 	}
35499f8ad73Smaxims@google.com 
35599f8ad73Smaxims@google.com 	ret = reset_assert(&reset_ctl);
35699f8ad73Smaxims@google.com 	if (ret) {
35799f8ad73Smaxims@google.com 		debug("%s(): SDRAM reset failed: %u\n", __func__, ret);
35814e4b149Smaxims@google.com 		return ret;
35914e4b149Smaxims@google.com 	}
36014e4b149Smaxims@google.com 
36114e4b149Smaxims@google.com 	ast2500_sdrammc_unlock(priv);
36214e4b149Smaxims@google.com 
36314e4b149Smaxims@google.com 	writel(SDRAM_PCR_MREQI_DIS | SDRAM_PCR_RESETN_DIS,
36414e4b149Smaxims@google.com 	       &regs->power_control);
36514e4b149Smaxims@google.com 	writel(SDRAM_VIDEO_UNLOCK_KEY, &regs->gm_protection_key);
36614e4b149Smaxims@google.com 
36714e4b149Smaxims@google.com 	/* Mask all requests except CPU and AHB during PHY init */
36814e4b149Smaxims@google.com 	writel(~(SDRAM_REQ_CPU | SDRAM_REQ_AHB), &regs->req_limit_mask);
36914e4b149Smaxims@google.com 
37014e4b149Smaxims@google.com 	for (i = 0; i < ARRAY_SIZE(ddr_max_grant_params); ++i)
37114e4b149Smaxims@google.com 		writel(ddr_max_grant_params[i], &regs->max_grant_len[i]);
37214e4b149Smaxims@google.com 
37314e4b149Smaxims@google.com 	setbits_le32(&regs->intr_ctrl, SDRAM_ICR_RESET_ALL);
37414e4b149Smaxims@google.com 
37514e4b149Smaxims@google.com 	ast2500_sdrammc_init_phy(priv->phy);
37614e4b149Smaxims@google.com 	if (readl(&priv->scu->hwstrap) & SCU_HWSTRAP_DDR4) {
37714e4b149Smaxims@google.com 		ast2500_sdrammc_init_ddr4(priv);
37814e4b149Smaxims@google.com 	} else {
37914e4b149Smaxims@google.com 		debug("Unsupported DRAM3\n");
38014e4b149Smaxims@google.com 		return -EINVAL;
38114e4b149Smaxims@google.com 	}
38214e4b149Smaxims@google.com 
38314e4b149Smaxims@google.com 	clrbits_le32(&regs->intr_ctrl, SDRAM_ICR_RESET_ALL);
38414e4b149Smaxims@google.com 	ast2500_sdrammc_lock(priv);
38514e4b149Smaxims@google.com 
38614e4b149Smaxims@google.com 	return 0;
38714e4b149Smaxims@google.com }
38814e4b149Smaxims@google.com 
ast2500_sdrammc_ofdata_to_platdata(struct udevice * dev)38914e4b149Smaxims@google.com static int ast2500_sdrammc_ofdata_to_platdata(struct udevice *dev)
39014e4b149Smaxims@google.com {
39114e4b149Smaxims@google.com 	struct dram_info *priv = dev_get_priv(dev);
39214e4b149Smaxims@google.com 	struct regmap *map;
39314e4b149Smaxims@google.com 	int ret;
39414e4b149Smaxims@google.com 
39514e4b149Smaxims@google.com 	ret = regmap_init_mem(dev, &map);
39614e4b149Smaxims@google.com 	if (ret)
39714e4b149Smaxims@google.com 		return ret;
39814e4b149Smaxims@google.com 
39914e4b149Smaxims@google.com 	priv->regs = regmap_get_range(map, 0);
40014e4b149Smaxims@google.com 	priv->phy = regmap_get_range(map, 1);
40114e4b149Smaxims@google.com 
402e160f7d4SSimon Glass 	priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
40314e4b149Smaxims@google.com 					  "clock-frequency", 0);
40414e4b149Smaxims@google.com 
40514e4b149Smaxims@google.com 	if (!priv->clock_rate) {
40614e4b149Smaxims@google.com 		debug("DDR Clock Rate not defined\n");
40714e4b149Smaxims@google.com 		return -EINVAL;
40814e4b149Smaxims@google.com 	}
40914e4b149Smaxims@google.com 
41014e4b149Smaxims@google.com 	return 0;
41114e4b149Smaxims@google.com }
41214e4b149Smaxims@google.com 
ast2500_sdrammc_get_info(struct udevice * dev,struct ram_info * info)41314e4b149Smaxims@google.com static int ast2500_sdrammc_get_info(struct udevice *dev, struct ram_info *info)
41414e4b149Smaxims@google.com {
41514e4b149Smaxims@google.com 	struct dram_info *priv = dev_get_priv(dev);
41614e4b149Smaxims@google.com 
41714e4b149Smaxims@google.com 	*info = priv->info;
41814e4b149Smaxims@google.com 
41914e4b149Smaxims@google.com 	return 0;
42014e4b149Smaxims@google.com }
42114e4b149Smaxims@google.com 
42214e4b149Smaxims@google.com static struct ram_ops ast2500_sdrammc_ops = {
42314e4b149Smaxims@google.com 	.get_info = ast2500_sdrammc_get_info,
42414e4b149Smaxims@google.com };
42514e4b149Smaxims@google.com 
42614e4b149Smaxims@google.com static const struct udevice_id ast2500_sdrammc_ids[] = {
42714e4b149Smaxims@google.com 	{ .compatible = "aspeed,ast2500-sdrammc" },
42814e4b149Smaxims@google.com 	{ }
42914e4b149Smaxims@google.com };
43014e4b149Smaxims@google.com 
43114e4b149Smaxims@google.com U_BOOT_DRIVER(sdrammc_ast2500) = {
43214e4b149Smaxims@google.com 	.name = "aspeed_ast2500_sdrammc",
43314e4b149Smaxims@google.com 	.id = UCLASS_RAM,
43414e4b149Smaxims@google.com 	.of_match = ast2500_sdrammc_ids,
43514e4b149Smaxims@google.com 	.ops = &ast2500_sdrammc_ops,
43614e4b149Smaxims@google.com 	.ofdata_to_platdata = ast2500_sdrammc_ofdata_to_platdata,
43714e4b149Smaxims@google.com 	.probe = ast2500_sdrammc_probe,
43814e4b149Smaxims@google.com 	.priv_auto_alloc_size = sizeof(struct dram_info),
43914e4b149Smaxims@google.com };
440