1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2018 NXP 4 */ 5 6#include <common.h> 7#include <log.h> 8#include <linux/kernel.h> 9#include <asm/arch/ddr.h> 10#include <asm/arch/sys_proto.h> 11 12int ddr_cfg_phy(struct dram_timing_info *dram_timing) 13{ 14 struct dram_cfg_param *dram_cfg; 15 struct dram_fsp_msg *fsp_msg; 16 unsigned int num; 17 int i = 0; 18 int j = 0; 19 int ret; 20 21 /* initialize PHY configuration */ 22 dram_cfg = dram_timing->ddrphy_cfg; 23 num = dram_timing->ddrphy_cfg_num; 24 for (i = 0; i < num; i++) { 25 /* config phy reg */ 26 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); 27 dram_cfg++; 28 } 29 30 /* load the frequency setpoint message block config */ 31 fsp_msg = dram_timing->fsp_msg; 32 for (i = 0; i < dram_timing->fsp_msg_num; i++) { 33 debug("DRAM PHY training for %dMTS\n", fsp_msg->drate); 34 /* set dram PHY input clocks to desired frequency */ 35 ddrphy_init_set_dfi_clk(fsp_msg->drate); 36 37 /* load the dram training firmware image */ 38 dwc_ddrphy_apb_wr(0xd0000, 0x0); 39 ddr_load_train_firmware(fsp_msg->fw_type); 40 41 /* load the frequency set point message block parameter */ 42 dram_cfg = fsp_msg->fsp_cfg; 43 num = fsp_msg->fsp_cfg_num; 44 for (j = 0; j < num; j++) { 45 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); 46 dram_cfg++; 47 } 48 49 /* 50 * -------------------- excute the firmware -------------------- 51 * Running the firmware is a simply process to taking the 52 * PMU out of reset and stall, then the firwmare will be run 53 * 1. reset the PMU; 54 * 2. begin the excution; 55 * 3. wait for the training done; 56 * 4. read the message block result. 57 * ------------------------------------------------------------- 58 */ 59 dwc_ddrphy_apb_wr(0xd0000, 0x1); 60 dwc_ddrphy_apb_wr(0xd0099, 0x9); 61 dwc_ddrphy_apb_wr(0xd0099, 0x1); 62 dwc_ddrphy_apb_wr(0xd0099, 0x0); 63 64 /* Wait for the training firmware to complete */ 65 ret = wait_ddrphy_training_complete(); 66 if (ret) 67 return ret; 68 69 /* Halt the microcontroller. */ 70 dwc_ddrphy_apb_wr(0xd0099, 0x1); 71 72 /* Read the Message Block results */ 73 dwc_ddrphy_apb_wr(0xd0000, 0x0); 74 75 ddrphy_init_read_msg_block(fsp_msg->fw_type); 76 77 if(fsp_msg->fw_type != FW_2D_IMAGE) 78 get_trained_CDD(i); 79 80 dwc_ddrphy_apb_wr(0xd0000, 0x1); 81 82 83 fsp_msg++; 84 } 85 86 /* Load PHY Init Engine Image */ 87 dram_cfg = dram_timing->ddrphy_pie; 88 num = dram_timing->ddrphy_pie_num; 89 for (i = 0; i < num; i++) { 90 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val); 91 dram_cfg++; 92 } 93 94 /* save the ddr PHY trained CSR in memory for low power use */ 95 ddrphy_trained_csr_save(ddrphy_trained_csr, ddrphy_trained_csr_num); 96 97 return 0; 98} 99