blob: ccc10df1845282e5b1e1ac25eaa106dd09f7bbc2 [file] [log] [blame]
Peng Fane3963c02018-11-20 10:19:57 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 */
5
Simon Glassf7ae49f2020-05-10 11:40:05 -06006#include <log.h>
Peng Fane3963c02018-11-20 10:19:57 +00007#include <linux/kernel.h>
8#include <asm/arch/ddr.h>
Oliver Chenb3359662020-04-21 14:48:09 +08009#include <asm/arch/sys_proto.h>
Peng Fane3963c02018-11-20 10:19:57 +000010
Frieder Schrempf83083fe2019-12-11 10:01:19 +000011int ddr_cfg_phy(struct dram_timing_info *dram_timing)
Peng Fane3963c02018-11-20 10:19:57 +000012{
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;
Frieder Schrempf83083fe2019-12-11 10:01:19 +000018 int ret;
Peng Fane3963c02018-11-20 10:19:57 +000019
20 /* initialize PHY configuration */
21 dram_cfg = dram_timing->ddrphy_cfg;
22 num = dram_timing->ddrphy_cfg_num;
23 for (i = 0; i < num; i++) {
24 /* config phy reg */
25 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
26 dram_cfg++;
27 }
28
29 /* load the frequency setpoint message block config */
30 fsp_msg = dram_timing->fsp_msg;
31 for (i = 0; i < dram_timing->fsp_msg_num; i++) {
32 debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
33 /* set dram PHY input clocks to desired frequency */
34 ddrphy_init_set_dfi_clk(fsp_msg->drate);
35
36 /* load the dram training firmware image */
37 dwc_ddrphy_apb_wr(0xd0000, 0x0);
38 ddr_load_train_firmware(fsp_msg->fw_type);
39
40 /* load the frequency set point message block parameter */
41 dram_cfg = fsp_msg->fsp_cfg;
42 num = fsp_msg->fsp_cfg_num;
43 for (j = 0; j < num; j++) {
44 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
45 dram_cfg++;
46 }
47
48 /*
49 * -------------------- excute the firmware --------------------
50 * Running the firmware is a simply process to taking the
51 * PMU out of reset and stall, then the firwmare will be run
52 * 1. reset the PMU;
53 * 2. begin the excution;
54 * 3. wait for the training done;
55 * 4. read the message block result.
56 * -------------------------------------------------------------
57 */
58 dwc_ddrphy_apb_wr(0xd0000, 0x1);
59 dwc_ddrphy_apb_wr(0xd0099, 0x9);
60 dwc_ddrphy_apb_wr(0xd0099, 0x1);
61 dwc_ddrphy_apb_wr(0xd0099, 0x0);
62
63 /* Wait for the training firmware to complete */
Frieder Schrempf83083fe2019-12-11 10:01:19 +000064 ret = wait_ddrphy_training_complete();
65 if (ret)
66 return ret;
Peng Fane3963c02018-11-20 10:19:57 +000067
68 /* Halt the microcontroller. */
69 dwc_ddrphy_apb_wr(0xd0099, 0x1);
70
71 /* Read the Message Block results */
72 dwc_ddrphy_apb_wr(0xd0000, 0x0);
Oliver Chenb3359662020-04-21 14:48:09 +080073
Peng Fane3963c02018-11-20 10:19:57 +000074 ddrphy_init_read_msg_block(fsp_msg->fw_type);
Oliver Chenb3359662020-04-21 14:48:09 +080075
76 if(fsp_msg->fw_type != FW_2D_IMAGE)
77 get_trained_CDD(i);
78
Peng Fane3963c02018-11-20 10:19:57 +000079 dwc_ddrphy_apb_wr(0xd0000, 0x1);
80
Oliver Chenb3359662020-04-21 14:48:09 +080081
Peng Fane3963c02018-11-20 10:19:57 +000082 fsp_msg++;
83 }
84
85 /* Load PHY Init Engine Image */
86 dram_cfg = dram_timing->ddrphy_pie;
87 num = dram_timing->ddrphy_pie_num;
88 for (i = 0; i < num; i++) {
89 dwc_ddrphy_apb_wr(dram_cfg->reg, dram_cfg->val);
90 dram_cfg++;
91 }
92
93 /* save the ddr PHY trained CSR in memory for low power use */
94 ddrphy_trained_csr_save(ddrphy_trained_csr, ddrphy_trained_csr_num);
Frieder Schrempf83083fe2019-12-11 10:01:19 +000095
96 return 0;
Peng Fane3963c02018-11-20 10:19:57 +000097}