123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*
- * Copyright 2021-2022 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
- #include <errno.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <common/debug.h>
- #include <ddr.h>
- #include <immap.h>
- #include <lib/mmio.h>
- #define UL_5POW12 244140625UL
- #define ULL_2E12 2000000000000ULL
- #define UL_2POW13 (1UL << 13)
- #define ULL_8FS 0xFFFFFFFFULL
- #define do_div(n, base) ({ \
- unsigned int __base = (base); \
- unsigned int __rem; \
- __rem = ((unsigned long long)(n)) % __base; \
- (n) = ((unsigned long long)(n)) / __base; \
- __rem; \
- })
- #define CCN_HN_F_SAM_NODEID_MASK 0x7f
- #ifdef NXP_HAS_CCN504
- #define CCN_HN_F_SAM_NODEID_DDR0 0x4
- #define CCN_HN_F_SAM_NODEID_DDR1 0xe
- #elif defined(NXP_HAS_CCN508)
- #define CCN_HN_F_SAM_NODEID_DDR0_0 0x3
- #define CCN_HN_F_SAM_NODEID_DDR0_1 0x8
- #define CCN_HN_F_SAM_NODEID_DDR1_0 0x13
- #define CCN_HN_F_SAM_NODEID_DDR1_1 0x18
- #endif
- unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num)
- {
- if (sys->freq_ddr_pll0 == 0) {
- get_clocks(sys);
- }
- switch (ctrl_num) {
- case 0:
- return sys->freq_ddr_pll0;
- case 1:
- return sys->freq_ddr_pll0;
- case 2:
- return sys->freq_ddr_pll1;
- }
- return 0;
- }
- unsigned int get_memory_clk_ps(const unsigned long data_rate)
- {
- 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;
- return result;
- }
- unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos)
- {
- unsigned long long clks, clks_rem;
- /* Short circuit for zero picos */
- if ((picos == 0U) || (data_rate == 0UL)) {
- return 0U;
- }
- /* First multiply the time by the data rate (32x32 => 64) */
- clks = picos * (unsigned long long)data_rate;
- /*
- * Now divide by 5^12 and track the 32-bit remainder, then divide
- * by 2*(2^12) using shifts (and updating the remainder).
- */
- clks_rem = do_div(clks, UL_5POW12);
- clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12;
- clks >>= 13U;
- /* If we had a remainder greater than the 1ps error, then round up */
- if (clks_rem > data_rate) {
- clks++;
- }
- /* Clamp to the maximum representable value */
- if (clks > ULL_8FS) {
- clks = ULL_8FS;
- }
- return (unsigned int) clks;
- }
- /* valid_spd_mask has been checked by parse_spd */
- int disable_unused_ddrc(struct ddr_info *priv,
- int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr)
- {
- #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
- void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL);
- uint32_t val, nodeid;
- #ifdef NXP_HAS_CCN504
- uint32_t num_hnf_nodes = 4U;
- #else
- uint32_t num_hnf_nodes = 8U;
- #endif
- int disable_ddrc = 0;
- int i;
- if (priv->num_ctlrs < 2) {
- debug("%s: nothing to do.\n", __func__);
- }
- switch (priv->dimm_on_ctlr) {
- case 1:
- disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0;
- disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
- break;
- case 2:
- disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0;
- disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
- break;
- default:
- ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr);
- return -EINVAL;
- }
- if (disable_ddrc != 0) {
- debug("valid_spd_mask = 0x%x\n", valid_spd_mask);
- }
- switch (disable_ddrc) {
- case 1:
- priv->num_ctlrs = 1;
- priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr];
- priv->ddr[0] = priv->ddr[1];
- priv->ddr[1] = NULL;
- priv->phy[0] = priv->phy[0];
- priv->phy[1] = NULL;
- debug("Disable first DDR controller\n");
- break;
- case 2:
- priv->num_ctlrs = 1;
- priv->ddr[1] = NULL;
- priv->phy[1] = NULL;
- debug("Disable second DDR controller\n");
- /* fallthrough */
- case 0:
- break;
- default:
- ERROR("Program error.\n");
- return -EINVAL;
- }
- if (disable_ddrc == 0) {
- debug("Both controllers in use.\n");
- return 0;
- }
- for (i = 0; i < num_hnf_nodes; i++) {
- val = mmio_read_64((uintptr_t)hnf_sam_ctrl);
- #ifdef NXP_HAS_CCN504
- nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 :
- (disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 :
- 0x0); /*Failure condition. never hit */
- #elif defined(NXP_HAS_CCN508)
- if (disable_ddrc == 1) {
- nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR1_1 :
- CCN_HN_F_SAM_NODEID_DDR1_0;
- } else if (disable_ddrc == 2) {
- nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR0_0 :
- CCN_HN_F_SAM_NODEID_DDR0_1;
- } else {
- nodeid = 0; /* Failure condition. never hit */
- }
- #endif
- if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) {
- debug("Setting HN-F node %d\n", i);
- debug("nodeid = 0x%x\n", nodeid);
- val &= ~CCN_HN_F_SAM_NODEID_MASK;
- val |= nodeid;
- mmio_write_64((uintptr_t)hnf_sam_ctrl, val);
- }
- hnf_sam_ctrl += CCN_HN_F_REGION_SIZE;
- }
- #endif
- return 0;
- }
- unsigned int get_ddrc_version(const struct ccsr_ddr *ddr)
- {
- unsigned int ver;
- ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U;
- ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U;
- return ver;
- }
- void print_ddr_info(struct ccsr_ddr *ddr)
- {
- unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]);
- unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg);
- int cas_lat;
- if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) {
- printf(" (DDR not enabled)\n");
- return;
- }
- printf("DDR");
- switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
- SDRAM_CFG_SDRAM_TYPE_SHIFT) {
- case SDRAM_TYPE_DDR4:
- printf("4");
- break;
- default:
- printf("?");
- break;
- }
- switch (sdram_cfg & SDRAM_CFG_DBW_MASK) {
- case SDRAM_CFG_32_BW:
- printf(", 32-bit");
- break;
- case SDRAM_CFG_16_BW:
- printf(", 16-bit");
- break;
- case SDRAM_CFG_8_BW:
- printf(", 8-bit");
- break;
- default:
- printf(", 64-bit");
- break;
- }
- /* Calculate CAS latency based on timing cfg values */
- cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
- cas_lat += 2; /* for DDRC newer than 4.4 */
- cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
- printf(", CL=%d", cas_lat >> 1);
- if ((cas_lat & 0x1) != 0) {
- printf(".5");
- }
- if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) {
- printf(", ECC on");
- } else {
- printf(", ECC off");
- }
- if ((cs0_config & 0x20000000) != 0) {
- printf(", ");
- switch ((cs0_config >> 24) & 0xf) {
- case DDR_256B_INTLV:
- printf("256B");
- break;
- default:
- printf("invalid");
- break;
- }
- }
- if (((sdram_cfg >> 8) & 0x7f) != 0) {
- printf(", ");
- switch (sdram_cfg >> 8 & 0x7f) {
- case DDR_BA_INTLV_CS0123:
- printf("CS0+CS1+CS2+CS3");
- break;
- case DDR_BA_INTLV_CS01:
- printf("CS0+CS1");
- break;
- default:
- printf("invalid");
- break;
- }
- }
- printf("\n");
- }
|