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