X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fddr%2Ffsl%2Futil.c;h=e49cf6e8e3dbfd35a487ef0cc2ebe0160442bba9;hb=6cc04547cb3bbd3a3d78947f200acbae19e3c67f;hp=ad53658fc92927a525bd2c2f27cbc9ed90fdaf5b;hpb=a7e8c15f71456d55ccb27f843862af03a00e0957;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c index ad53658..e49cf6e 100644 --- a/drivers/ddr/fsl/util.c +++ b/drivers/ddr/fsl/util.c @@ -1,9 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2008-2012 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * Version 2 as published by the Free Software Foundation. + * Copyright 2008-2014 Freescale Semiconductor, Inc. + * Copyright 2021 NXP */ #include @@ -11,10 +9,16 @@ #include #endif #include +#include #include #include +#include #include +#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ + defined(CONFIG_ARM) +#include +#endif /* To avoid 64-bit full-divides, we factor this here */ #define ULL_2E12 2000000000000ULL @@ -23,6 +27,40 @@ #define ULL_8FS 0xFFFFFFFFULL +u32 fsl_ddr_get_version(unsigned int ctrl_num) +{ + struct ccsr_ddr __iomem *ddr; + u32 ver_major_minor_errata; + + switch (ctrl_num) { + case 0: + ddr = (void *)CFG_SYS_FSL_DDR_ADDR; + break; +#if defined(CFG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1) + case 1: + ddr = (void *)CFG_SYS_FSL_DDR2_ADDR; + break; +#endif +#if defined(CFG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2) + case 2: + ddr = (void *)CFG_SYS_FSL_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3) + case 3: + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; + break; +#endif + default: + printf("%s unexpected ctrl_num = %u\n", __func__, ctrl_num); + return 0; + } + ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8; + ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8; + + return ver_major_minor_errata; +} + /* * Round up mclk_ps to nearest 1 ps in memory controller code * if the error is 0.5ps or more. @@ -31,26 +69,29 @@ * propagation, compute a suitably rounded mclk_ps to compute * a working memory controller configuration. */ -unsigned int get_memory_clk_period_ps(void) +unsigned int get_memory_clk_period_ps(const unsigned int ctrl_num) { - unsigned int data_rate = get_ddr_freq(0); + unsigned int data_rate = get_ddr_freq(ctrl_num); unsigned int result; /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ unsigned long long rem, mclk_ps = ULL_2E12; - - /* Now perform the big divide, the result fits in 32-bits */ - rem = do_div(mclk_ps, data_rate); - result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; + if (data_rate) { + /* Now perform the big divide, the result fits in 32-bits */ + rem = do_div(mclk_ps, data_rate); + result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; + } else { + result = 0; + } return result; } /* Convert picoseconds into DRAM clock cycles (rounding up if needed). */ -unsigned int picos_to_mclk(unsigned int picos) +unsigned int picos_to_mclk(const unsigned int ctrl_num, unsigned int picos) { unsigned long long clks, clks_rem; - unsigned long data_rate = get_ddr_freq(0); + unsigned long data_rate = get_ddr_freq(ctrl_num); /* Short circuit for zero picos */ if (!picos) @@ -76,9 +117,9 @@ unsigned int picos_to_mclk(unsigned int picos) return (unsigned int) clks; } -unsigned int mclk_to_picos(unsigned int mclk) +unsigned int mclk_to_picos(const unsigned int ctrl_num, unsigned int mclk) { - return get_memory_clk_period_ps() * mclk; + return get_memory_clk_period_ps(ctrl_num) * mclk; } #ifdef CONFIG_PPC @@ -106,7 +147,7 @@ __fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params, if (set_ddr_laws(base, size, law_memctl) < 0) { printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num, law_memctl); - return ; + return; } debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n", base, size, law_memctl); @@ -137,32 +178,40 @@ u32 fsl_ddr_get_intl3r(void) return val; } -void board_add_ram_info(int use_default) +void print_ddr_info(unsigned int start_ctrl) { struct ccsr_ddr __iomem *ddr = - (struct ccsr_ddr __iomem *)(CONFIG_SYS_FSL_DDR_ADDR); + (struct ccsr_ddr __iomem *)(CFG_SYS_FSL_DDR_ADDR); -#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3) +#if defined(CONFIG_E6500) && (CONFIG_SYS_NUM_DDR_CTLRS == 3) u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004); #endif -#if (CONFIG_NUM_DDR_CONTROLLERS > 1) +#if (CONFIG_SYS_NUM_DDR_CTLRS > 1) uint32_t cs0_config = ddr_in32(&ddr->cs0_config); #endif uint32_t sdram_cfg = ddr_in32(&ddr->sdram_cfg); int cas_lat; -#if CONFIG_NUM_DDR_CONTROLLERS >= 2 - if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { - ddr = (void __iomem *)CONFIG_SYS_FSL_DDR2_ADDR; +#if CONFIG_SYS_NUM_DDR_CTLRS >= 2 + if ((!(sdram_cfg & SDRAM_CFG_MEM_EN)) || + (start_ctrl == 1)) { + ddr = (void __iomem *)CFG_SYS_FSL_DDR2_ADDR; sdram_cfg = ddr_in32(&ddr->sdram_cfg); } #endif -#if CONFIG_NUM_DDR_CONTROLLERS >= 3 - if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { - ddr = (void __iomem *)CONFIG_SYS_FSL_DDR3_ADDR; +#if CONFIG_SYS_NUM_DDR_CTLRS >= 3 + if ((!(sdram_cfg & SDRAM_CFG_MEM_EN)) || + (start_ctrl == 2)) { + ddr = (void __iomem *)CFG_SYS_FSL_DDR3_ADDR; sdram_cfg = ddr_in32(&ddr->sdram_cfg); } #endif + + if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) { + puts(" (DDR not enabled)\n"); + return; + } + puts(" (DDR"); switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> SDRAM_CFG_SDRAM_TYPE_SHIFT) { @@ -175,6 +224,9 @@ void board_add_ram_info(int use_default) case SDRAM_TYPE_DDR3: puts("3"); break; + case SDRAM_TYPE_DDR4: + puts("4"); + break; default: puts("?"); break; @@ -188,9 +240,12 @@ void board_add_ram_info(int use_default) puts(", 64-bit"); /* Calculate CAS latency based on timing cfg values */ - cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1; - if ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 1) - cas_lat += (8 << 1); + cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf); + if (fsl_ddr_get_version(0) <= 0x40400) + cas_lat += 1; + else + cas_lat += 2; + cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4; printf(", CL=%d", cas_lat >> 1); if (cas_lat & 0x1) puts(".5"); @@ -200,7 +255,7 @@ void board_add_ram_info(int use_default) else puts(", ECC off)"); -#if (CONFIG_NUM_DDR_CONTROLLERS == 3) +#if (CONFIG_SYS_NUM_DDR_CTLRS == 3) #ifdef CONFIG_E6500 if (*mcintl3r & 0x80000000) { puts("\n"); @@ -222,8 +277,8 @@ void board_add_ram_info(int use_default) } #endif #endif -#if (CONFIG_NUM_DDR_CONTROLLERS >= 2) - if (cs0_config & 0x20000000) { +#if (CONFIG_SYS_NUM_DDR_CTLRS >= 2) + if ((cs0_config & 0x20000000) && (start_ctrl == 0)) { puts("\n"); puts(" DDR Controller Interleaving Mode: "); @@ -272,3 +327,108 @@ void board_add_ram_info(int use_default) } } } + +void __weak detail_board_ddr_info(void) +{ + print_ddr_info(0); +} + +void board_add_ram_info(int use_default) +{ + detail_board_ddr_info(); +} + +#ifdef CONFIG_FSL_DDR_SYNC_REFRESH +#define DDRC_DEBUG20_INIT_DONE 0x80000000 +#define DDRC_DEBUG2_RF 0x00000040 +void fsl_ddr_sync_memctl_refresh(unsigned int first_ctrl, + unsigned int last_ctrl) +{ + unsigned int i; + u32 ddrc_debug20; + u32 ddrc_debug2[CONFIG_SYS_NUM_DDR_CTLRS] = {}; + u32 *ddrc_debug2_p[CONFIG_SYS_NUM_DDR_CTLRS] = {}; + struct ccsr_ddr __iomem *ddr; + + for (i = first_ctrl; i <= last_ctrl; i++) { + switch (i) { + case 0: + ddr = (void *)CFG_SYS_FSL_DDR_ADDR; + break; +#if defined(CFG_SYS_FSL_DDR2_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 1) + case 1: + ddr = (void *)CFG_SYS_FSL_DDR2_ADDR; + break; +#endif +#if defined(CFG_SYS_FSL_DDR3_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 2) + case 2: + ddr = (void *)CFG_SYS_FSL_DDR3_ADDR; + break; +#endif +#if defined(CONFIG_SYS_FSL_DDR4_ADDR) && (CONFIG_SYS_NUM_DDR_CTLRS > 3) + case 3: + ddr = (void *)CONFIG_SYS_FSL_DDR4_ADDR; + break; +#endif + default: + printf("%s unexpected ctrl = %u\n", __func__, i); + return; + } + ddrc_debug20 = ddr_in32(&ddr->debug[19]); + ddrc_debug2_p[i] = &ddr->debug[1]; + while (!(ddrc_debug20 & DDRC_DEBUG20_INIT_DONE)) { + /* keep polling until DDRC init is done */ + udelay(100); + ddrc_debug20 = ddr_in32(&ddr->debug[19]); + } + ddrc_debug2[i] = ddr_in32(&ddr->debug[1]) | DDRC_DEBUG2_RF; + } + /* + * Sync refresh + * This is put together to make sure the refresh reqeusts are sent + * closely to each other. + */ + for (i = first_ctrl; i <= last_ctrl; i++) + ddr_out32(ddrc_debug2_p[i], ddrc_debug2[i]); +} +#endif /* CONFIG_FSL_DDR_SYNC_REFRESH */ + +void remove_unused_controllers(fsl_ddr_info_t *info) +{ +#ifdef CONFIG_SYS_FSL_HAS_CCN504 + int i; + u64 nodeid; + void *hnf_sam_ctrl = (void *)(CCI_HN_F_0_BASE + CCN_HN_F_SAM_CTL); + bool ddr0_used = false; + bool ddr1_used = false; + + for (i = 0; i < 8; i++) { + nodeid = in_le64(hnf_sam_ctrl) & CCN_HN_F_SAM_NODEID_MASK; + if (nodeid == CCN_HN_F_SAM_NODEID_DDR0) { + ddr0_used = true; + } else if (nodeid == CCN_HN_F_SAM_NODEID_DDR1) { + ddr1_used = true; + } else { + printf("Unknown nodeid in HN-F SAM control: 0x%llx\n", + nodeid); + } + hnf_sam_ctrl += (CCI_HN_F_1_BASE - CCI_HN_F_0_BASE); + } + if (!ddr0_used && !ddr1_used) { + printf("Invalid configuration in HN-F SAM control\n"); + return; + } + + if (!ddr0_used && info->first_ctrl == 0) { + info->first_ctrl = 1; + info->num_ctrls = 1; + debug("First DDR controller disabled\n"); + return; + } + + if (!ddr1_used && info->first_ctrl + info->num_ctrls > 1) { + info->num_ctrls = 1; + debug("Second DDR controller disabled\n"); + } +#endif +}