1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2021 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu /* 9*91f16700Schasinglulu * Generic driver for Freescale MMDC(Multi Mode DDR Controller). 10*91f16700Schasinglulu */ 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <errno.h> 13*91f16700Schasinglulu #include <stdint.h> 14*91f16700Schasinglulu #include <stdio.h> 15*91f16700Schasinglulu #include <stdlib.h> 16*91f16700Schasinglulu #include <string.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <common/debug.h> 19*91f16700Schasinglulu #include "ddr_io.h" 20*91f16700Schasinglulu #include <drivers/delay_timer.h> 21*91f16700Schasinglulu #include <fsl_mmdc.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu static void set_wait_for_bits_clear(void *ptr, unsigned int value, 24*91f16700Schasinglulu unsigned int bits) 25*91f16700Schasinglulu { 26*91f16700Schasinglulu int timeout = 1000; 27*91f16700Schasinglulu 28*91f16700Schasinglulu ddr_out32(ptr, value); 29*91f16700Schasinglulu 30*91f16700Schasinglulu while ((ddr_in32(ptr) & bits) != 0) { 31*91f16700Schasinglulu udelay(100); 32*91f16700Schasinglulu timeout--; 33*91f16700Schasinglulu } 34*91f16700Schasinglulu if (timeout <= 0) { 35*91f16700Schasinglulu INFO("Error: %llx", (unsigned long long)ptr); 36*91f16700Schasinglulu INFO(" wait for clear timeout.\n"); 37*91f16700Schasinglulu } 38*91f16700Schasinglulu } 39*91f16700Schasinglulu 40*91f16700Schasinglulu void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr) 41*91f16700Schasinglulu { 42*91f16700Schasinglulu struct mmdc_regs *mmdc = (struct mmdc_regs *)nxp_ddr_addr; 43*91f16700Schasinglulu unsigned int tmp; 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* 1. set configuration request */ 46*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); 47*91f16700Schasinglulu 48*91f16700Schasinglulu /* 2. configure the desired timing parameters */ 49*91f16700Schasinglulu ddr_out32(&mmdc->mdotc, priv->mdotc); 50*91f16700Schasinglulu ddr_out32(&mmdc->mdcfg0, priv->mdcfg0); 51*91f16700Schasinglulu ddr_out32(&mmdc->mdcfg1, priv->mdcfg1); 52*91f16700Schasinglulu ddr_out32(&mmdc->mdcfg2, priv->mdcfg2); 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* 3. configure DDR type and other miscellaneous parameters */ 55*91f16700Schasinglulu ddr_out32(&mmdc->mdmisc, priv->mdmisc); 56*91f16700Schasinglulu ddr_out32(&mmdc->mpmur0, MMDC_MPMUR0_FRC_MSR); 57*91f16700Schasinglulu ddr_out32(&mmdc->mdrwd, priv->mdrwd); 58*91f16700Schasinglulu ddr_out32(&mmdc->mpodtctrl, priv->mpodtctrl); 59*91f16700Schasinglulu 60*91f16700Schasinglulu /* 4. configure the required delay while leaving reset */ 61*91f16700Schasinglulu ddr_out32(&mmdc->mdor, priv->mdor); 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* 5. configure DDR physical parameters */ 64*91f16700Schasinglulu /* set row/column address width, burst length, data bus width */ 65*91f16700Schasinglulu tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1); 66*91f16700Schasinglulu ddr_out32(&mmdc->mdctl, tmp); 67*91f16700Schasinglulu /* configure address space partition */ 68*91f16700Schasinglulu ddr_out32(&mmdc->mdasp, priv->mdasp); 69*91f16700Schasinglulu 70*91f16700Schasinglulu /* 6. perform a ZQ calibration - not needed here, doing in #8b */ 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* 7. enable MMDC with the desired chip select */ 73*91f16700Schasinglulu #if (DDRC_NUM_CS == 1) 74*91f16700Schasinglulu ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0); 75*91f16700Schasinglulu #elif (DDRC_NUM_CS == 2) 76*91f16700Schasinglulu ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1); 77*91f16700Schasinglulu #else 78*91f16700Schasinglulu #error "Unsupported DDRC_NUM_CS" 79*91f16700Schasinglulu #endif 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */ 82*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(8) | 83*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 84*91f16700Schasinglulu CMD_LOAD_MODE_REG | 85*91f16700Schasinglulu CMD_BANK_ADDR_2); 86*91f16700Schasinglulu 87*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0) | 88*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 89*91f16700Schasinglulu CMD_LOAD_MODE_REG | 90*91f16700Schasinglulu CMD_BANK_ADDR_3); 91*91f16700Schasinglulu 92*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | 93*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 94*91f16700Schasinglulu CMD_LOAD_MODE_REG | 95*91f16700Schasinglulu CMD_BANK_ADDR_1); 96*91f16700Schasinglulu 97*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x19) | 98*91f16700Schasinglulu CMD_ADDR_LSB_MR_ADDR(0x30) | 99*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 100*91f16700Schasinglulu CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0); 101*91f16700Schasinglulu 102*91f16700Schasinglulu /* 8b. ZQ calibration */ 103*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x4) | 104*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 105*91f16700Schasinglulu CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0); 106*91f16700Schasinglulu 107*91f16700Schasinglulu set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl, 108*91f16700Schasinglulu MPZQHWCTRL_ZQ_HW_FORCE); 109*91f16700Schasinglulu 110*91f16700Schasinglulu /* 9a. calibrations now, wr lvl */ 111*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0x84) | MDSCR_WL_EN | 112*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 113*91f16700Schasinglulu CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); 114*91f16700Schasinglulu 115*91f16700Schasinglulu set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN, 116*91f16700Schasinglulu MPWLGCR_HW_WL_EN); 117*91f16700Schasinglulu 118*91f16700Schasinglulu mdelay(1); 119*91f16700Schasinglulu 120*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | 121*91f16700Schasinglulu MDSCR_ENABLE_CON_REQ | 122*91f16700Schasinglulu CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); 123*91f16700Schasinglulu 124*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); 125*91f16700Schasinglulu 126*91f16700Schasinglulu mdelay(1); 127*91f16700Schasinglulu 128*91f16700Schasinglulu /* 9b. read DQS gating calibration */ 129*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | 130*91f16700Schasinglulu CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); 131*91f16700Schasinglulu 132*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | 133*91f16700Schasinglulu CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); 134*91f16700Schasinglulu 135*91f16700Schasinglulu ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* set absolute read delay offset */ 138*91f16700Schasinglulu if (priv->mprddlctl != 0) { 139*91f16700Schasinglulu ddr_out32(&mmdc->mprddlctl, priv->mprddlctl); 140*91f16700Schasinglulu } else { 141*91f16700Schasinglulu ddr_out32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY); 142*91f16700Schasinglulu } 143*91f16700Schasinglulu 144*91f16700Schasinglulu set_wait_for_bits_clear(&mmdc->mpdgctrl0, 145*91f16700Schasinglulu AUTO_RD_DQS_GATING_CALIBRATION_EN, 146*91f16700Schasinglulu AUTO_RD_DQS_GATING_CALIBRATION_EN); 147*91f16700Schasinglulu 148*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | 149*91f16700Schasinglulu CMD_BANK_ADDR_3); 150*91f16700Schasinglulu 151*91f16700Schasinglulu /* 9c. read calibration */ 152*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | 153*91f16700Schasinglulu CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); 154*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | 155*91f16700Schasinglulu CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); 156*91f16700Schasinglulu ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); 157*91f16700Schasinglulu set_wait_for_bits_clear(&mmdc->mprddlhwctl, 158*91f16700Schasinglulu MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN, 159*91f16700Schasinglulu MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN); 160*91f16700Schasinglulu 161*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | 162*91f16700Schasinglulu CMD_BANK_ADDR_3); 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* 10. configure power-down, self-refresh entry, exit parameters */ 165*91f16700Schasinglulu ddr_out32(&mmdc->mdpdc, priv->mdpdc); 166*91f16700Schasinglulu ddr_out32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT); 167*91f16700Schasinglulu 168*91f16700Schasinglulu /* 11. ZQ config again? do nothing here */ 169*91f16700Schasinglulu 170*91f16700Schasinglulu /* 12. refresh scheme */ 171*91f16700Schasinglulu set_wait_for_bits_clear(&mmdc->mdref, priv->mdref, 172*91f16700Schasinglulu MDREF_START_REFRESH); 173*91f16700Schasinglulu 174*91f16700Schasinglulu /* 13. disable CON_REQ */ 175*91f16700Schasinglulu ddr_out32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ); 176*91f16700Schasinglulu } 177