• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /* Mem setup common file for different types of DDR present on SMDK5420 boards.
4  */
5 
6 #include <device/mmio.h>
7 #include <delay.h>
8 #include <soc/clk.h>
9 #include <soc/dmc.h>
10 #include <soc/setup.h>
11 
12 #define ZQ_INIT_TIMEOUT	10000
13 
dmc_config_zq(struct mem_timings * mem,struct exynos5_phy_control * phy0_ctrl,struct exynos5_phy_control * phy1_ctrl)14 int dmc_config_zq(struct mem_timings *mem,
15 		  struct exynos5_phy_control *phy0_ctrl,
16 		  struct exynos5_phy_control *phy1_ctrl)
17 {
18 	unsigned long val = 0;
19 	int i;
20 
21 	/*
22 	 * ZQ Calibration:
23 	 * Select Driver Strength,
24 	 * long calibration for manual calibration
25 	 */
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);
32 
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);
38 
39 	/* ZQ_MANUAL_START: Enable */
40 	val |= ZQ_MANUAL_STR;
41 	write32(&phy0_ctrl->phy_con16, val);
42 	write32(&phy1_ctrl->phy_con16, val);
43 
44 	/* ZQ_MANUAL_START: Disable */
45 	val &= ~ZQ_MANUAL_STR;
46 
47 	/*
48 	 * Since we are manually calibrating the ZQ values,
49 	 * we are looping for the ZQ_init to complete.
50 	 */
51 	i = ZQ_INIT_TIMEOUT;
52 	while ((read32(&phy0_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
53 		udelay(1);
54 		i--;
55 	}
56 	if (!i)
57 		return -1;
58 	write32(&phy0_ctrl->phy_con16, val);
59 
60 	i = ZQ_INIT_TIMEOUT;
61 	while ((read32(&phy1_ctrl->phy_con17) & ZQ_DONE) != ZQ_DONE && i > 0) {
62 		udelay(1);
63 		i--;
64 	}
65 	if (!i)
66 		return -1;
67 	write32(&phy1_ctrl->phy_con16, val);
68 
69 	return 0;
70 }
71 
update_reset_dll(struct exynos5_dmc * dmc,enum ddr_mode mode)72 void update_reset_dll(struct exynos5_dmc *dmc, enum ddr_mode mode)
73 {
74 	unsigned long val;
75 
76 	if (mode == DDR_MODE_DDR3) {
77 		val = MEM_TERM_EN | PHY_TERM_EN | DMC_CTRL_SHGATE;
78 		write32(&dmc->phycontrol0, val);
79 	}
80 
81 	/* Update DLL Information: Force DLL Resynchronization */
82 	val = read32(&dmc->phycontrol0);
83 	val |= FP_RSYNC;
84 	write32(&dmc->phycontrol0, val);
85 
86 	/* Reset Force DLL Resynchronization */
87 	val = read32(&dmc->phycontrol0);
88 	val &= ~FP_RSYNC;
89 	write32(&dmc->phycontrol0, val);
90 }
91 
dmc_config_mrs(struct mem_timings * mem,struct exynos5_dmc * dmc)92 void dmc_config_mrs(struct mem_timings *mem, struct exynos5_dmc *dmc)
93 {
94 	int channel, chip;
95 
96 	for (channel = 0; channel < mem->dmc_channels; channel++) {
97 		unsigned long mask;
98 
99 		mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
100 		for (chip = 0; chip < mem->chips_to_configure; chip++) {
101 			int i;
102 
103 			mask |= chip << DIRECT_CMD_CHIP_SHIFT;
104 
105 			/* Sending NOP command */
106 			write32(&dmc->directcmd, DIRECT_CMD_NOP | mask);
107 
108 			/*
109 			 * TODO(alim.akhtar@samsung.com): Do we need these
110 			 * delays? This one and the next were not there for
111 			 * DDR3.
112 			 */
113 			udelay(100);
114 
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);
120 			}
121 
122 			if (mem->send_zq_init) {
123 				/* Sending ZQINIT command */
124 				write32(&dmc->directcmd,
125 					DIRECT_CMD_ZQINIT | mask);
126 				/*
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.
132 				 */
133 				udelay(12);
134 			}
135 		}
136 	}
137 }
138 
dmc_config_prech(struct mem_timings * mem,struct exynos5_dmc * dmc)139 void dmc_config_prech(struct mem_timings *mem, struct exynos5_dmc *dmc)
140 {
141 	int channel, chip;
142 
143 	for (channel = 0; channel < mem->dmc_channels; channel++) {
144 		unsigned long mask;
145 
146 		mask = channel << DIRECT_CMD_CHANNEL_SHIFT;
147 		for (chip = 0; chip < mem->chips_per_channel; chip++) {
148 			mask |= chip << DIRECT_CMD_CHIP_SHIFT;
149 
150 			/* PALL (all banks precharge) CMD */
151 			write32(&dmc->directcmd, DIRECT_CMD_PALL | mask);
152 			udelay(100);
153 		}
154 	}
155 }
156