blob: cd905f952c64b5a9147234c69c4eb655b524df58 [file] [log] [blame]
Peng Fan692f9432018-11-20 10:19:57 +00001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 */
5
Tom Riniabb9a042024-05-18 20:20:43 -06006#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Peng Fan692f9432018-11-20 10:19:57 +00008#include <linux/kernel.h>
9#include <asm/arch/ddr.h>
Oliver Chen42eda3a2020-04-21 14:48:09 +080010#include <asm/arch/sys_proto.h>
Peng Fan692f9432018-11-20 10:19:57 +000011
Frieder Schrempf2a9b1f52019-12-11 10:01:19 +000012int ddr_cfg_phy(struct dram_timing_info *dram_timing)
Peng Fan692f9432018-11-20 10:19:57 +000013{
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;
Frieder Schrempf2a9b1f52019-12-11 10:01:19 +000019 int ret;
Peng Fan692f9432018-11-20 10:19:57 +000020
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 */
Frieder Schrempf2a9b1f52019-12-11 10:01:19 +000065 ret = wait_ddrphy_training_complete();
66 if (ret)
67 return ret;
Peng Fan692f9432018-11-20 10:19:57 +000068
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);
Oliver Chen42eda3a2020-04-21 14:48:09 +080074
Peng Fan692f9432018-11-20 10:19:57 +000075 ddrphy_init_read_msg_block(fsp_msg->fw_type);
Oliver Chen42eda3a2020-04-21 14:48:09 +080076
77 if(fsp_msg->fw_type != FW_2D_IMAGE)
78 get_trained_CDD(i);
79
Peng Fan692f9432018-11-20 10:19:57 +000080 dwc_ddrphy_apb_wr(0xd0000, 0x1);
81
Oliver Chen42eda3a2020-04-21 14:48:09 +080082
Peng Fan692f9432018-11-20 10:19:57 +000083 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);
Frieder Schrempf2a9b1f52019-12-11 10:01:19 +000096
97 return 0;
Peng Fan692f9432018-11-20 10:19:57 +000098}