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, ®s->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, ®s->phy_ctrl[0]);
10214e4b149Smaxims@google.com while ((readl(®s->phy_ctrl[0]) & SDRAM_PHYCTRL0_INIT))
10314e4b149Smaxims@google.com ;
10414e4b149Smaxims@google.com writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_AUTO_UPDATE,
10514e4b149Smaxims@google.com ®s->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), ®s->refresh_timing);
12614e4b149Smaxims@google.com writel((0xfff << SDRAM_TEST_LEN_SHIFT), ®s->test_addr);
12714e4b149Smaxims@google.com writel(0xff00ff00, ®s->test_init_val);
12814e4b149Smaxims@google.com writel(SDRAM_TEST_EN | (SDRAM_TEST_MODE_RW << SDRAM_TEST_MODE_SHIFT) |
12914e4b149Smaxims@google.com SDRAM_TEST_ERRSTOP, ®s->ecc_test_ctrl);
13014e4b149Smaxims@google.com
13114e4b149Smaxims@google.com while (!(readl(®s->ecc_test_ctrl) & SDRAM_TEST_DONE))
13214e4b149Smaxims@google.com ;
13314e4b149Smaxims@google.com
13414e4b149Smaxims@google.com if (readl(®s->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 ®s->ecc_test_ctrl);
14014e4b149Smaxims@google.com while (!(readl(®s->ecc_test_ctrl) & SDRAM_TEST_DONE))
14114e4b149Smaxims@google.com ;
14214e4b149Smaxims@google.com if (readl(®s->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, ®s->refresh_timing);
15014e4b149Smaxims@google.com writel(0, ®s->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 ®s->power_control);
36514e4b149Smaxims@google.com writel(SDRAM_VIDEO_UNLOCK_KEY, ®s->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), ®s->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], ®s->max_grant_len[i]);
37214e4b149Smaxims@google.com
37314e4b149Smaxims@google.com setbits_le32(®s->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(®s->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