mb/google/nissa/var/pujjo: Add new supported memory part
[coreboot2.git] / src / soc / samsung / exynos5420 / dmc_common.c
blob1b830e3de628903424a64b08b074e8d4b8e6bfdb
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /* Mem setup common file for different types of DDR present on SMDK5420 boards.
4 */
6 #include <device/mmio.h>
7 #include <delay.h>
8 #include <soc/clk.h>
9 #include <soc/dmc.h>
10 #include <soc/setup.h>
12 #define ZQ_INIT_TIMEOUT 10000
14 int dmc_config_zq(struct mem_timings *mem,
15 struct exynos5_phy_control *phy0_ctrl,
16 struct exynos5_phy_control *phy1_ctrl)
18 unsigned long val = 0;
19 int i;
22 * ZQ Calibration:
23 * Select Driver Strength,
24 * long calibration for manual calibration
26 val = PHY_CON16_RESET_VAL;
27 val |= mem->zq_mode_dds << PHY_CON16_ZQ_MODE_DDS_SHIFT;
28 val |= mem->zq_mode_term << PHY_CON16_ZQ_MODE_TERM_SHIFT;
29 val |= ZQ_CLK_DIV_EN;
30 write32(&phy0_ctrl->phy_con16, val);
31 write32(&phy1_ctrl->phy_con16, val);
33 /* Disable termination */
34 if (mem->zq_mode_noterm)
35 val |= PHY_CON16_ZQ_MODE_NOTERM_MASK;
36 write32(&phy0_ctrl->phy_con16, val);
37 write32(&phy1_ctrl->phy_con16, val);
39 /* ZQ_MANUAL_START: Enable */
40 val |= ZQ_MANUAL_STR;
41 write32(&phy0_ctrl->phy_con16, val);
42 write32(&phy1_ctrl->phy_con16, val);
44 /* ZQ_MANUAL_START: Disable */
45 val &= ~ZQ_MANUAL_STR;
48 * Since we are manually calibrating the ZQ values,
49 * we are looping for the ZQ_init to complete.
51 i = ZQ_INIT_TIMEOUT;
52 while ((read32(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
53 udelay(1);
54 i--;
56 if (!i)
57 return -1;
58 write32(&phy0_ctrl->phy_con16, val);
60 i = ZQ_INIT_TIMEOUT;
61 while ((read32(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
62 udelay(1);
63 i--;
65 if (!i)
66 return -1;
67 write32(&phy1_ctrl->phy_con16, val);
69 return 0;
72 void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
74 unsigned long val;
76 if (mode == DDR_MODE_DDR3) {
77 val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
78 write32(&dmc->phycontrol0, val);
81 /* Update DLL Information: Force DLL Resynchronization */
82 val = read32(&dmc->phycontrol0);
83 val |= FP_RSYNC;
84 write32(&dmc->phycontrol0, val);
86 /* Reset Force DLL Resynchronization */
87 val = read32(&dmc->phycontrol0);
88 val &= ~FP_RSYNC;
89 write32(&dmc->phycontrol0, val);
92 void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
94 int channel, chip;
96 for (channel = 0; channel < mem->dmc_channels; channel++) {
97 unsigned long mask;
99 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
100 for (chip = 0; chip < mem->chips_to_configure; chip++) {
101 int i;
103 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
105 /* Sending NOP command */
106 write32(&dmc->directcmd, DIRECT_CMD_NOP | mask);
109 * TODO(alim.akhtar@samsung.com): Do we need these
110 * delays? This one and the next were not there for
111 * DDR3.
113 udelay(100);
115 /* Sending EMRS/MRS commands */
116 for (i = 0; i < MEM_TIMINGS_MSR_COUNT; i++) {
117 write32(&dmc->directcmd,
118 mem->direct_cmd_msr[i] | mask);
119 udelay(100);
122 if (mem->send_zq_init) {
123 /* Sending ZQINIT command */
124 write32(&dmc->directcmd,
125 DIRECT_CMD_ZQINIT | mask);
127 * FIXME: This was originally sdelay(10000)
128 * in the imported u-boot code. That may have
129 * been meant to be sdelay(0x10000) since that
130 * was used elsewhere in this function. Either
131 * way seems to work, though.
133 udelay(12);
139 void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
141 int channel, chip;
143 for (channel = 0; channel < mem->dmc_channels; channel++) {
144 unsigned long mask;
146 mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
147 for (chip = 0; chip < mem->chips_per_channel; chip++) {
148 mask |= chip << DIRECT_CMD_CHIP_SHIFT;
150 /* PALL (all banks precharge) CMD */
151 write32(&dmc->directcmd, DIRECT_CMD_PALL | mask);
152 udelay(100);