]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
293eb33f | 2 | /* |
14ef4c7b ARS |
3 | * (C) Copyright 2013 - 2022, Xilinx, Inc. |
4 | * (C) Copyright 2022, Advanced Micro Devices, Inc. | |
293eb33f MS |
5 | * |
6 | * Xilinx Zynq SD Host Controller Interface | |
293eb33f MS |
7 | */ |
8 | ||
e0f4de1a | 9 | #include <clk.h> |
d9ae52c8 | 10 | #include <dm.h> |
345d3c0f | 11 | #include <fdtdec.h> |
c05ed00a | 12 | #include <linux/delay.h> |
d1f4e39d | 13 | #include "mmc_private.h" |
f7ae49fc | 14 | #include <log.h> |
90ab7faf | 15 | #include <reset.h> |
cc24fd78 | 16 | #include <asm/arch/sys_proto.h> |
336d4615 | 17 | #include <dm/device_compat.h> |
61b29b82 | 18 | #include <linux/err.h> |
b08c8c48 | 19 | #include <linux/libfdt.h> |
14ef4c7b | 20 | #include <linux/iopoll.h> |
90ab7faf ARS |
21 | #include <asm/types.h> |
22 | #include <linux/math64.h> | |
655d69fa | 23 | #include <asm/cache.h> |
293eb33f MS |
24 | #include <malloc.h> |
25 | #include <sdhci.h> | |
d0449825 | 26 | #include <zynqmp_firmware.h> |
293eb33f | 27 | |
ee9ae005 ARS |
28 | #define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 |
29 | #define SDHCI_ARASAN_ITAPDLY_SEL_MASK GENMASK(7, 0) | |
30 | #define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC | |
31 | #define SDHCI_ARASAN_OTAPDLY_SEL_MASK GENMASK(5, 0) | |
32 | #define SDHCI_ITAPDLY_CHGWIN BIT(9) | |
33 | #define SDHCI_ITAPDLY_ENABLE BIT(8) | |
34 | #define SDHCI_OTAPDLY_ENABLE BIT(6) | |
2e819a77 | 35 | |
9851f50d | 36 | #define SDHCI_TUNING_LOOP_COUNT 40 |
80355ae4 MS |
37 | #define MMC_BANK2 0x2 |
38 | ||
655d69fa ARS |
39 | #define SD_DLL_CTRL 0xFF180358 |
40 | #define SD_ITAP_DLY 0xFF180314 | |
41 | #define SD_OTAP_DLY 0xFF180318 | |
42 | #define SD0_DLL_RST BIT(2) | |
43 | #define SD1_DLL_RST BIT(18) | |
44 | #define SD0_ITAPCHGWIN BIT(9) | |
45 | #define SD1_ITAPCHGWIN BIT(25) | |
46 | #define SD0_ITAPDLYENA BIT(8) | |
47 | #define SD1_ITAPDLYENA BIT(24) | |
48 | #define SD0_ITAPDLYSEL_MASK GENMASK(7, 0) | |
49 | #define SD1_ITAPDLYSEL_MASK GENMASK(23, 16) | |
50 | #define SD0_OTAPDLYSEL_MASK GENMASK(5, 0) | |
51 | #define SD1_OTAPDLYSEL_MASK GENMASK(21, 16) | |
52 | ||
14ef4c7b ARS |
53 | #define MIN_PHY_CLK_HZ 50000000 |
54 | ||
55 | #define PHY_CTRL_REG1 0x270 | |
56 | #define PHY_CTRL_ITAPDLY_ENA_MASK BIT(0) | |
57 | #define PHY_CTRL_ITAPDLY_SEL_MASK GENMASK(5, 1) | |
58 | #define PHY_CTRL_ITAPDLY_SEL_SHIFT 1 | |
59 | #define PHY_CTRL_ITAP_CHG_WIN_MASK BIT(6) | |
60 | #define PHY_CTRL_OTAPDLY_ENA_MASK BIT(8) | |
61 | #define PHY_CTRL_OTAPDLY_SEL_MASK GENMASK(15, 12) | |
62 | #define PHY_CTRL_OTAPDLY_SEL_SHIFT 12 | |
63 | #define PHY_CTRL_STRB_SEL_MASK GENMASK(23, 16) | |
64 | #define PHY_CTRL_STRB_SEL_SHIFT 16 | |
65 | #define PHY_CTRL_TEST_CTRL_MASK GENMASK(31, 24) | |
66 | ||
67 | #define PHY_CTRL_REG2 0x274 | |
68 | #define PHY_CTRL_EN_DLL_MASK BIT(0) | |
69 | #define PHY_CTRL_DLL_RDY_MASK BIT(1) | |
70 | #define PHY_CTRL_FREQ_SEL_MASK GENMASK(6, 4) | |
71 | #define PHY_CTRL_FREQ_SEL_SHIFT 4 | |
72 | #define PHY_CTRL_SEL_DLY_TX_MASK BIT(16) | |
73 | #define PHY_CTRL_SEL_DLY_RX_MASK BIT(17) | |
74 | #define FREQSEL_200M_170M 0x0 | |
75 | #define FREQSEL_170M_140M 0x1 | |
76 | #define FREQSEL_140M_110M 0x2 | |
77 | #define FREQSEL_110M_80M 0x3 | |
78 | #define FREQSEL_80M_50M 0x4 | |
79 | #define FREQSEL_275M_250M 0x5 | |
80 | #define FREQSEL_250M_225M 0x6 | |
81 | #define FREQSEL_225M_200M 0x7 | |
82 | #define PHY_DLL_TIMEOUT_MS 100 | |
83 | ||
84 | #define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN 39 | |
85 | #define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL 146 | |
86 | #define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77 | |
87 | ||
80355ae4 MS |
88 | struct arasan_sdhci_clk_data { |
89 | int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; | |
90 | int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; | |
91 | }; | |
9851f50d | 92 | |
329a449f SG |
93 | struct arasan_sdhci_plat { |
94 | struct mmc_config cfg; | |
95 | struct mmc mmc; | |
96 | }; | |
97 | ||
d1f4e39d SDPP |
98 | struct arasan_sdhci_priv { |
99 | struct sdhci_host *host; | |
80355ae4 | 100 | struct arasan_sdhci_clk_data clk_data; |
aba0e651 | 101 | u32 node_id; |
d1f4e39d | 102 | u8 bank; |
7a49a16e | 103 | u8 no_1p8; |
14ef4c7b | 104 | bool internal_phy_reg; |
90ab7faf | 105 | struct reset_ctl_bulk resets; |
d1f4e39d SDPP |
106 | }; |
107 | ||
bde2e728 PB |
108 | enum arasan_sdhci_compatible { |
109 | SDHCI_COMPATIBLE_SDHCI_89A, | |
110 | SDHCI_COMPATIBLE_VERSAL_NET_EMMC, | |
111 | }; | |
112 | ||
113 | static bool arasan_sdhci_is_compatible(struct udevice *dev, | |
114 | enum arasan_sdhci_compatible family) | |
115 | { | |
116 | enum arasan_sdhci_compatible compat = dev_get_driver_data(dev); | |
117 | ||
118 | return compat == family; | |
119 | } | |
120 | ||
655d69fa ARS |
121 | /* For Versal platforms zynqmp_mmio_write() won't be available */ |
122 | __weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value) | |
123 | { | |
124 | return 0; | |
125 | } | |
126 | ||
a3e3d469 KR |
127 | __weak int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2, |
128 | u32 arg3, u32 *ret_payload) | |
129 | { | |
130 | return 0; | |
131 | } | |
132 | ||
15535323 KR |
133 | __weak int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) |
134 | { | |
135 | return 1; | |
136 | } | |
137 | ||
4950a98d MS |
138 | #if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || \ |
139 | defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2) | |
80355ae4 | 140 | /* Default settings for ZynqMP Clock Phases */ |
419b4a86 MS |
141 | static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, |
142 | 0, 183, 54, 0, 0}; | |
143 | static const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, | |
144 | 135, 48, 72, 135, 0}; | |
80355ae4 | 145 | |
2e819a77 | 146 | /* Default settings for Versal Clock Phases */ |
419b4a86 MS |
147 | static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, |
148 | 0, 0, 162, 90, 0, 0}; | |
149 | static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, | |
150 | 90, 36, 60, 90, 0}; | |
2e819a77 | 151 | |
14ef4c7b ARS |
152 | /* Default settings for versal-net eMMC Clock Phases */ |
153 | static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39, | |
154 | 0, 0}; | |
155 | static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0, | |
156 | 113, 79, 45}; | |
157 | ||
d1f4e39d | 158 | static const u8 mode2timing[] = { |
17a42abb ARS |
159 | [MMC_LEGACY] = MMC_TIMING_LEGACY, |
160 | [MMC_HS] = MMC_TIMING_MMC_HS, | |
161 | [SD_HS] = MMC_TIMING_SD_HS, | |
71f07731 ARS |
162 | [MMC_HS_52] = MMC_TIMING_MMC_HS, |
163 | [MMC_DDR_52] = MMC_TIMING_MMC_DDR52, | |
17a42abb ARS |
164 | [UHS_SDR12] = MMC_TIMING_UHS_SDR12, |
165 | [UHS_SDR25] = MMC_TIMING_UHS_SDR25, | |
166 | [UHS_SDR50] = MMC_TIMING_UHS_SDR50, | |
167 | [UHS_DDR50] = MMC_TIMING_UHS_DDR50, | |
168 | [UHS_SDR104] = MMC_TIMING_UHS_SDR104, | |
169 | [MMC_HS_200] = MMC_TIMING_MMC_HS200, | |
a1f8abf4 | 170 | [MMC_HS_400] = MMC_TIMING_MMC_HS400, |
d1f4e39d SDPP |
171 | }; |
172 | ||
4950a98d | 173 | #if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2) |
14ef4c7b ARS |
174 | /** |
175 | * arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock | |
176 | * | |
177 | * @host: Pointer to the sdhci_host structure | |
178 | * @enable: Enable or disable Delay chain based Tx and Rx clock | |
179 | * Return: None | |
180 | * | |
181 | * Enable or disable eMMC delay chain based Input and Output clock in | |
182 | * PHY_CTRL_REG2 | |
183 | */ | |
184 | static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable) | |
185 | { | |
186 | u32 reg; | |
187 | ||
188 | reg = sdhci_readw(host, PHY_CTRL_REG2); | |
189 | if (enable) | |
190 | reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK; | |
191 | else | |
192 | reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK); | |
193 | ||
194 | sdhci_writew(host, reg, PHY_CTRL_REG2); | |
195 | } | |
196 | ||
197 | /** | |
198 | * arasan_phy_set_dll - Set eMMC DLL clock | |
199 | * | |
200 | * @host: Pointer to the sdhci_host structure | |
201 | * @enable: Enable or disable DLL clock | |
202 | * Return: 0 if success or timeout error | |
203 | * | |
204 | * Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is | |
205 | * set, wait till DLL is locked | |
206 | */ | |
207 | static int arasan_phy_set_dll(struct sdhci_host *host, bool enable) | |
208 | { | |
209 | u32 reg; | |
210 | ||
211 | reg = sdhci_readw(host, PHY_CTRL_REG2); | |
212 | if (enable) | |
213 | reg |= PHY_CTRL_EN_DLL_MASK; | |
214 | else | |
215 | reg &= ~PHY_CTRL_EN_DLL_MASK; | |
216 | ||
217 | sdhci_writew(host, reg, PHY_CTRL_REG2); | |
218 | ||
219 | /* If DLL is disabled return success */ | |
220 | if (!enable) | |
221 | return 0; | |
222 | ||
223 | /* If DLL is enabled wait till DLL loop is locked, which is | |
224 | * indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2 | |
225 | */ | |
226 | return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg, | |
227 | (reg & PHY_CTRL_DLL_RDY_MASK), | |
228 | 1000 * PHY_DLL_TIMEOUT_MS); | |
229 | } | |
230 | ||
231 | /** | |
232 | * arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC | |
233 | * | |
234 | * @host: Pointer to the sdhci_host structure | |
235 | * @clock: clock value | |
236 | * Return: None | |
237 | * | |
238 | * Set frequency range bits based on the selected clock for eMMC | |
239 | */ | |
240 | static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock) | |
241 | { | |
242 | u32 reg, freq_sel, freq; | |
243 | ||
244 | freq = DIV_ROUND_CLOSEST(clock, 1000000); | |
245 | if (freq <= 200 && freq > 170) | |
246 | freq_sel = FREQSEL_200M_170M; | |
247 | else if (freq <= 170 && freq > 140) | |
248 | freq_sel = FREQSEL_170M_140M; | |
249 | else if (freq <= 140 && freq > 110) | |
250 | freq_sel = FREQSEL_140M_110M; | |
251 | else if (freq <= 110 && freq > 80) | |
252 | freq_sel = FREQSEL_110M_80M; | |
253 | else | |
254 | freq_sel = FREQSEL_80M_50M; | |
255 | ||
256 | reg = sdhci_readw(host, PHY_CTRL_REG2); | |
257 | reg &= ~PHY_CTRL_FREQ_SEL_MASK; | |
258 | reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT); | |
259 | sdhci_writew(host, reg, PHY_CTRL_REG2); | |
260 | } | |
261 | ||
262 | static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable) | |
263 | { | |
264 | struct mmc *mmc = (struct mmc *)host->mmc; | |
265 | struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); | |
266 | ||
267 | if (enable) { | |
268 | if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable) | |
269 | arasan_phy_set_dll(host, 1); | |
270 | return 0; | |
271 | } | |
272 | ||
273 | if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) { | |
274 | sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); | |
275 | arasan_phy_set_dll(host, 0); | |
276 | arasan_phy_set_delaychain(host, 0); | |
277 | arasan_phy_dll_set_freq(host, clock); | |
278 | return 0; | |
279 | } | |
280 | ||
281 | sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); | |
282 | arasan_phy_set_delaychain(host, 1); | |
283 | ||
284 | return 0; | |
285 | } | |
286 | #endif | |
287 | ||
cbdee4d5 | 288 | static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay) |
655d69fa ARS |
289 | { |
290 | int ret; | |
291 | ||
371dc068 | 292 | if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { |
655d69fa ARS |
293 | if (node_id == NODE_SD_0) { |
294 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, | |
295 | SD0_ITAPCHGWIN); | |
296 | if (ret) | |
297 | return ret; | |
298 | ||
299 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA, | |
300 | SD0_ITAPDLYENA); | |
301 | if (ret) | |
302 | return ret; | |
303 | ||
304 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK, | |
305 | itap_delay); | |
306 | if (ret) | |
307 | return ret; | |
308 | ||
309 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0); | |
310 | if (ret) | |
311 | return ret; | |
312 | } | |
313 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, | |
314 | SD1_ITAPCHGWIN); | |
315 | if (ret) | |
316 | return ret; | |
317 | ||
318 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA, | |
319 | SD1_ITAPDLYENA); | |
320 | if (ret) | |
321 | return ret; | |
322 | ||
323 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK, | |
324 | (itap_delay << 16)); | |
325 | if (ret) | |
326 | return ret; | |
327 | ||
328 | ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0); | |
329 | if (ret) | |
330 | return ret; | |
331 | } else { | |
cbdee4d5 | 332 | return xilinx_pm_request(PM_IOCTL, node_id, |
655d69fa ARS |
333 | IOCTL_SET_SD_TAPDELAY, |
334 | PM_TAPDELAY_INPUT, itap_delay, NULL); | |
335 | } | |
336 | ||
337 | return 0; | |
338 | } | |
339 | ||
cbdee4d5 | 340 | static inline int arasan_zynqmp_set_out_tapdelay(u32 node_id, u32 otap_delay) |
655d69fa | 341 | { |
371dc068 | 342 | if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { |
655d69fa ARS |
343 | if (node_id == NODE_SD_0) |
344 | return zynqmp_mmio_write(SD_OTAP_DLY, | |
345 | SD0_OTAPDLYSEL_MASK, | |
346 | otap_delay); | |
347 | ||
348 | return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK, | |
349 | (otap_delay << 16)); | |
350 | } else { | |
cbdee4d5 | 351 | return xilinx_pm_request(PM_IOCTL, node_id, |
655d69fa ARS |
352 | IOCTL_SET_SD_TAPDELAY, |
353 | PM_TAPDELAY_OUTPUT, otap_delay, NULL); | |
354 | } | |
355 | } | |
356 | ||
cbdee4d5 | 357 | static inline int zynqmp_dll_reset(u32 node_id, u32 type) |
655d69fa | 358 | { |
371dc068 | 359 | if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) { |
655d69fa ARS |
360 | if (node_id == NODE_SD_0) |
361 | return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST, | |
362 | type == PM_DLL_RESET_ASSERT ? | |
363 | SD0_DLL_RST : 0); | |
364 | ||
365 | return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST, | |
366 | type == PM_DLL_RESET_ASSERT ? | |
367 | SD1_DLL_RST : 0); | |
368 | } else { | |
cbdee4d5 | 369 | return xilinx_pm_request(PM_IOCTL, node_id, |
655d69fa ARS |
370 | IOCTL_SD_DLL_RESET, type, 0, NULL); |
371 | } | |
372 | } | |
373 | ||
cbdee4d5 | 374 | static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 node_id) |
d1f4e39d | 375 | { |
d0449825 ARS |
376 | struct mmc *mmc = (struct mmc *)host->mmc; |
377 | struct udevice *dev = mmc->dev; | |
d1f4e39d | 378 | unsigned long timeout; |
d0449825 ARS |
379 | int ret; |
380 | u16 clk; | |
d1f4e39d SDPP |
381 | |
382 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | |
383 | clk &= ~(SDHCI_CLOCK_CARD_EN); | |
384 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | |
385 | ||
386 | /* Issue DLL Reset */ | |
d0449825 ARS |
387 | ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT); |
388 | if (ret) { | |
389 | dev_err(dev, "dll_reset assert failed with err: %d\n", ret); | |
390 | return ret; | |
391 | } | |
392 | ||
393 | /* Allow atleast 1ms delay for proper DLL reset */ | |
394 | mdelay(1); | |
395 | ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE); | |
396 | if (ret) { | |
397 | dev_err(dev, "dll_reset release failed with err: %d\n", ret); | |
398 | return ret; | |
399 | } | |
d1f4e39d SDPP |
400 | |
401 | /* Wait max 20 ms */ | |
402 | timeout = 100; | |
403 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | |
404 | & SDHCI_CLOCK_INT_STABLE)) { | |
405 | if (timeout == 0) { | |
d0449825 ARS |
406 | dev_err(dev, ": Internal clock never stabilised.\n"); |
407 | return -EBUSY; | |
d1f4e39d SDPP |
408 | } |
409 | timeout--; | |
410 | udelay(1000); | |
411 | } | |
412 | ||
413 | clk |= SDHCI_CLOCK_CARD_EN; | |
414 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | |
d0449825 ARS |
415 | |
416 | return 0; | |
d1f4e39d SDPP |
417 | } |
418 | ||
419 | static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) | |
420 | { | |
421 | struct mmc_cmd cmd; | |
422 | struct mmc_data data; | |
423 | u32 ctrl; | |
424 | struct sdhci_host *host; | |
425 | struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); | |
b387c258 | 426 | int tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT; |
d1f4e39d | 427 | |
90ab7faf | 428 | dev_dbg(mmc->dev, "%s\n", __func__); |
d1f4e39d SDPP |
429 | |
430 | host = priv->host; | |
d1f4e39d | 431 | |
d1c0a220 | 432 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
d1f4e39d | 433 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
d1c0a220 | 434 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
d1f4e39d SDPP |
435 | |
436 | mdelay(1); | |
437 | ||
bde2e728 | 438 | if (arasan_sdhci_is_compatible(mmc->dev, SDHCI_COMPATIBLE_SDHCI_89A)) |
752e4b6c | 439 | arasan_zynqmp_dll_reset(host, priv->node_id); |
d1f4e39d SDPP |
440 | |
441 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); | |
442 | sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); | |
443 | ||
444 | do { | |
445 | cmd.cmdidx = opcode; | |
446 | cmd.resp_type = MMC_RSP_R1; | |
447 | cmd.cmdarg = 0; | |
448 | ||
449 | data.blocksize = 64; | |
450 | data.blocks = 1; | |
451 | data.flags = MMC_DATA_READ; | |
452 | ||
453 | if (tuning_loop_counter-- == 0) | |
454 | break; | |
455 | ||
456 | if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 && | |
457 | mmc->bus_width == 8) | |
458 | data.blocksize = 128; | |
459 | ||
460 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, | |
461 | data.blocksize), | |
462 | SDHCI_BLOCK_SIZE); | |
463 | sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT); | |
464 | sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); | |
465 | ||
466 | mmc_send_cmd(mmc, &cmd, NULL); | |
d1c0a220 | 467 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
d1f4e39d SDPP |
468 | |
469 | if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK) | |
470 | udelay(1); | |
471 | ||
472 | } while (ctrl & SDHCI_CTRL_EXEC_TUNING); | |
473 | ||
474 | if (tuning_loop_counter < 0) { | |
475 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | |
d1c0a220 | 476 | sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2); |
d1f4e39d SDPP |
477 | } |
478 | ||
479 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { | |
480 | printf("%s:Tuning failed\n", __func__); | |
481 | return -1; | |
482 | } | |
483 | ||
484 | udelay(1); | |
752e4b6c | 485 | |
bde2e728 | 486 | if (arasan_sdhci_is_compatible(mmc->dev, SDHCI_COMPATIBLE_SDHCI_89A)) |
752e4b6c | 487 | arasan_zynqmp_dll_reset(host, priv->node_id); |
d1f4e39d SDPP |
488 | |
489 | /* Enable only interrupts served by the SD controller */ | |
490 | sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, | |
491 | SDHCI_INT_ENABLE); | |
492 | /* Mask all sdhci interrupt sources */ | |
493 | sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE); | |
494 | ||
495 | return 0; | |
496 | } | |
497 | ||
f4b297bb ARS |
498 | /** |
499 | * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays | |
500 | * | |
f4b297bb ARS |
501 | * @host: Pointer to the sdhci_host structure. |
502 | * @degrees: The clock phase shift between 0 - 359. | |
8e34aa00 | 503 | * Return: 0 |
c0436fcf MS |
504 | * |
505 | * Set the SD Output Clock Tap Delays for Output path | |
f4b297bb ARS |
506 | */ |
507 | static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host, | |
508 | int degrees) | |
509 | { | |
f4b297bb | 510 | struct mmc *mmc = (struct mmc *)host->mmc; |
d0449825 ARS |
511 | struct udevice *dev = mmc->dev; |
512 | struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); | |
f4b297bb | 513 | u8 tap_delay, tap_max = 0; |
f4b297bb | 514 | int timing = mode2timing[mmc->selected_mode]; |
d0449825 | 515 | int ret; |
f4b297bb ARS |
516 | |
517 | /* | |
518 | * This is applicable for SDHCI_SPEC_300 and above | |
519 | * ZynqMP does not set phase for <=25MHz clock. | |
520 | * If degrees is zero, no need to do anything. | |
521 | */ | |
affcba72 | 522 | if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300) |
f4b297bb ARS |
523 | return 0; |
524 | ||
525 | switch (timing) { | |
526 | case MMC_TIMING_MMC_HS: | |
527 | case MMC_TIMING_SD_HS: | |
528 | case MMC_TIMING_UHS_SDR25: | |
529 | case MMC_TIMING_UHS_DDR50: | |
530 | case MMC_TIMING_MMC_DDR52: | |
531 | /* For 50MHz clock, 30 Taps are available */ | |
532 | tap_max = 30; | |
533 | break; | |
534 | case MMC_TIMING_UHS_SDR50: | |
535 | /* For 100MHz clock, 15 Taps are available */ | |
536 | tap_max = 15; | |
537 | break; | |
538 | case MMC_TIMING_UHS_SDR104: | |
539 | case MMC_TIMING_MMC_HS200: | |
540 | /* For 200MHz clock, 8 Taps are available */ | |
541 | tap_max = 8; | |
542 | default: | |
543 | break; | |
544 | } | |
545 | ||
546 | tap_delay = (degrees * tap_max) / 360; | |
547 | ||
a70bdafd ARS |
548 | /* Limit output tap_delay value to 6 bits */ |
549 | tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK; | |
550 | ||
d0449825 | 551 | /* Set the Clock Phase */ |
aba0e651 | 552 | ret = arasan_zynqmp_set_out_tapdelay(priv->node_id, tap_delay); |
d0449825 ARS |
553 | if (ret) { |
554 | dev_err(dev, "Error setting output Tap Delay\n"); | |
555 | return ret; | |
556 | } | |
557 | ||
558 | /* Release DLL Reset */ | |
aba0e651 | 559 | ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_RELEASE); |
d0449825 ARS |
560 | if (ret) { |
561 | dev_err(dev, "dll_reset release failed with err: %d\n", ret); | |
562 | return ret; | |
563 | } | |
f4b297bb | 564 | |
8e34aa00 | 565 | return 0; |
f4b297bb ARS |
566 | } |
567 | ||
568 | /** | |
569 | * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays | |
570 | * | |
f4b297bb ARS |
571 | * @host: Pointer to the sdhci_host structure. |
572 | * @degrees: The clock phase shift between 0 - 359. | |
8e34aa00 | 573 | * Return: 0 |
c0436fcf MS |
574 | * |
575 | * Set the SD Input Clock Tap Delays for Input path | |
f4b297bb ARS |
576 | */ |
577 | static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host, | |
578 | int degrees) | |
579 | { | |
f4b297bb | 580 | struct mmc *mmc = (struct mmc *)host->mmc; |
d0449825 ARS |
581 | struct udevice *dev = mmc->dev; |
582 | struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); | |
f4b297bb | 583 | u8 tap_delay, tap_max = 0; |
f4b297bb | 584 | int timing = mode2timing[mmc->selected_mode]; |
d0449825 | 585 | int ret; |
f4b297bb ARS |
586 | |
587 | /* | |
588 | * This is applicable for SDHCI_SPEC_300 and above | |
589 | * ZynqMP does not set phase for <=25MHz clock. | |
590 | * If degrees is zero, no need to do anything. | |
591 | */ | |
affcba72 | 592 | if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300) |
f4b297bb ARS |
593 | return 0; |
594 | ||
d0449825 | 595 | /* Assert DLL Reset */ |
aba0e651 | 596 | ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_ASSERT); |
d0449825 ARS |
597 | if (ret) { |
598 | dev_err(dev, "dll_reset assert failed with err: %d\n", ret); | |
599 | return ret; | |
600 | } | |
601 | ||
f4b297bb ARS |
602 | switch (timing) { |
603 | case MMC_TIMING_MMC_HS: | |
604 | case MMC_TIMING_SD_HS: | |
605 | case MMC_TIMING_UHS_SDR25: | |
606 | case MMC_TIMING_UHS_DDR50: | |
607 | case MMC_TIMING_MMC_DDR52: | |
608 | /* For 50MHz clock, 120 Taps are available */ | |
609 | tap_max = 120; | |
610 | break; | |
611 | case MMC_TIMING_UHS_SDR50: | |
612 | /* For 100MHz clock, 60 Taps are available */ | |
613 | tap_max = 60; | |
614 | break; | |
615 | case MMC_TIMING_UHS_SDR104: | |
616 | case MMC_TIMING_MMC_HS200: | |
617 | /* For 200MHz clock, 30 Taps are available */ | |
618 | tap_max = 30; | |
619 | default: | |
620 | break; | |
621 | } | |
622 | ||
623 | tap_delay = (degrees * tap_max) / 360; | |
624 | ||
a70bdafd ARS |
625 | /* Limit input tap_delay value to 8 bits */ |
626 | tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK; | |
627 | ||
aba0e651 | 628 | ret = arasan_zynqmp_set_in_tapdelay(priv->node_id, tap_delay); |
d0449825 ARS |
629 | if (ret) { |
630 | dev_err(dev, "Error setting Input Tap Delay\n"); | |
631 | return ret; | |
632 | } | |
f4b297bb | 633 | |
8e34aa00 | 634 | return 0; |
f4b297bb ARS |
635 | } |
636 | ||
2e819a77 ARS |
637 | /** |
638 | * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays | |
639 | * | |
2e819a77 | 640 | * @host: Pointer to the sdhci_host structure. |
c0436fcf | 641 | * @degrees: The clock phase shift between 0 - 359. |
8e34aa00 | 642 | * Return: 0 |
c0436fcf MS |
643 | * |
644 | * Set the SD Output Clock Tap Delays for Output path | |
2e819a77 ARS |
645 | */ |
646 | static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host, | |
647 | int degrees) | |
648 | { | |
649 | struct mmc *mmc = (struct mmc *)host->mmc; | |
650 | u8 tap_delay, tap_max = 0; | |
2e819a77 | 651 | int timing = mode2timing[mmc->selected_mode]; |
ee9ae005 | 652 | u32 regval; |
2e819a77 ARS |
653 | |
654 | /* | |
655 | * This is applicable for SDHCI_SPEC_300 and above | |
656 | * Versal does not set phase for <=25MHz clock. | |
657 | * If degrees is zero, no need to do anything. | |
658 | */ | |
affcba72 | 659 | if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300) |
2e819a77 ARS |
660 | return 0; |
661 | ||
662 | switch (timing) { | |
663 | case MMC_TIMING_MMC_HS: | |
664 | case MMC_TIMING_SD_HS: | |
665 | case MMC_TIMING_UHS_SDR25: | |
666 | case MMC_TIMING_UHS_DDR50: | |
667 | case MMC_TIMING_MMC_DDR52: | |
668 | /* For 50MHz clock, 30 Taps are available */ | |
669 | tap_max = 30; | |
670 | break; | |
671 | case MMC_TIMING_UHS_SDR50: | |
672 | /* For 100MHz clock, 15 Taps are available */ | |
673 | tap_max = 15; | |
674 | break; | |
675 | case MMC_TIMING_UHS_SDR104: | |
676 | case MMC_TIMING_MMC_HS200: | |
677 | /* For 200MHz clock, 8 Taps are available */ | |
678 | tap_max = 8; | |
679 | default: | |
680 | break; | |
681 | } | |
682 | ||
683 | tap_delay = (degrees * tap_max) / 360; | |
684 | ||
ee9ae005 ARS |
685 | /* Limit output tap_delay value to 6 bits */ |
686 | tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK; | |
687 | ||
2e819a77 | 688 | /* Set the Clock Phase */ |
ee9ae005 ARS |
689 | regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER); |
690 | regval |= SDHCI_OTAPDLY_ENABLE; | |
691 | sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); | |
692 | regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK; | |
693 | regval |= tap_delay; | |
694 | sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); | |
2e819a77 | 695 | |
8e34aa00 | 696 | return 0; |
2e819a77 ARS |
697 | } |
698 | ||
699 | /** | |
700 | * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays | |
701 | * | |
2e819a77 | 702 | * @host: Pointer to the sdhci_host structure. |
c0436fcf | 703 | * @degrees: The clock phase shift between 0 - 359. |
8e34aa00 | 704 | * Return: 0 |
c0436fcf MS |
705 | * |
706 | * Set the SD Input Clock Tap Delays for Input path | |
2e819a77 ARS |
707 | */ |
708 | static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host, | |
709 | int degrees) | |
710 | { | |
711 | struct mmc *mmc = (struct mmc *)host->mmc; | |
712 | u8 tap_delay, tap_max = 0; | |
2e819a77 | 713 | int timing = mode2timing[mmc->selected_mode]; |
ee9ae005 | 714 | u32 regval; |
2e819a77 ARS |
715 | |
716 | /* | |
717 | * This is applicable for SDHCI_SPEC_300 and above | |
718 | * Versal does not set phase for <=25MHz clock. | |
719 | * If degrees is zero, no need to do anything. | |
720 | */ | |
affcba72 | 721 | if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300) |
2e819a77 ARS |
722 | return 0; |
723 | ||
724 | switch (timing) { | |
725 | case MMC_TIMING_MMC_HS: | |
726 | case MMC_TIMING_SD_HS: | |
727 | case MMC_TIMING_UHS_SDR25: | |
728 | case MMC_TIMING_UHS_DDR50: | |
729 | case MMC_TIMING_MMC_DDR52: | |
730 | /* For 50MHz clock, 120 Taps are available */ | |
731 | tap_max = 120; | |
732 | break; | |
733 | case MMC_TIMING_UHS_SDR50: | |
734 | /* For 100MHz clock, 60 Taps are available */ | |
735 | tap_max = 60; | |
736 | break; | |
737 | case MMC_TIMING_UHS_SDR104: | |
738 | case MMC_TIMING_MMC_HS200: | |
739 | /* For 200MHz clock, 30 Taps are available */ | |
740 | tap_max = 30; | |
741 | default: | |
742 | break; | |
743 | } | |
744 | ||
745 | tap_delay = (degrees * tap_max) / 360; | |
746 | ||
ee9ae005 ARS |
747 | /* Limit input tap_delay value to 8 bits */ |
748 | tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK; | |
749 | ||
2e819a77 | 750 | /* Set the Clock Phase */ |
ee9ae005 ARS |
751 | regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER); |
752 | regval |= SDHCI_ITAPDLY_CHGWIN; | |
753 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); | |
754 | regval |= SDHCI_ITAPDLY_ENABLE; | |
755 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); | |
756 | regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK; | |
757 | regval |= tap_delay; | |
758 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); | |
759 | regval &= ~SDHCI_ITAPDLY_CHGWIN; | |
760 | sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); | |
2e819a77 | 761 | |
8e34aa00 | 762 | return 0; |
2e819a77 ARS |
763 | } |
764 | ||
14ef4c7b ARS |
765 | /** |
766 | * sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays | |
767 | * | |
768 | * @host: Pointer to the sdhci_host structure. | |
769 | * @degrees: The clock phase shift between 0 - 359. | |
770 | * Return: 0 | |
771 | * | |
772 | * Set eMMC Output Clock Tap Delays for Output path | |
773 | */ | |
774 | static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees) | |
775 | { | |
776 | struct mmc *mmc = (struct mmc *)host->mmc; | |
777 | int timing = mode2timing[mmc->selected_mode]; | |
778 | u8 tap_delay, tap_max = 0; | |
779 | u32 regval; | |
780 | ||
781 | switch (timing) { | |
782 | case MMC_TIMING_MMC_HS: | |
783 | case MMC_TIMING_MMC_DDR52: | |
784 | tap_max = 16; | |
785 | break; | |
786 | case MMC_TIMING_MMC_HS200: | |
787 | case MMC_TIMING_MMC_HS400: | |
788 | /* For 200MHz clock, 32 Taps are available */ | |
789 | tap_max = 32; | |
790 | break; | |
791 | default: | |
792 | break; | |
793 | } | |
794 | ||
795 | tap_delay = (degrees * tap_max) / 360; | |
796 | /* Set the Clock Phase */ | |
797 | if (tap_delay) { | |
798 | regval = sdhci_readl(host, PHY_CTRL_REG1); | |
799 | regval |= PHY_CTRL_OTAPDLY_ENA_MASK; | |
800 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
801 | regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK; | |
802 | regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT; | |
803 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
804 | } | |
805 | ||
806 | return 0; | |
807 | } | |
808 | ||
809 | /** | |
810 | * sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays | |
811 | * | |
812 | * @host: Pointer to the sdhci_host structure. | |
813 | * @degrees: The clock phase shift between 0 - 359. | |
814 | * Return: 0 | |
815 | * | |
816 | * Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected, | |
817 | * set strobe90 and strobe180 in PHY_CTRL_REG1. | |
818 | */ | |
819 | static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees) | |
820 | { | |
821 | struct mmc *mmc = (struct mmc *)host->mmc; | |
822 | int timing = mode2timing[mmc->selected_mode]; | |
823 | u8 tap_delay, tap_max = 0; | |
824 | u32 regval; | |
825 | ||
826 | switch (timing) { | |
827 | case MMC_TIMING_MMC_HS: | |
828 | case MMC_TIMING_MMC_DDR52: | |
829 | tap_max = 32; | |
830 | break; | |
831 | case MMC_TIMING_MMC_HS400: | |
832 | /* Strobe select tap point for strb90 and strb180 */ | |
833 | regval = sdhci_readl(host, PHY_CTRL_REG1); | |
834 | regval &= ~PHY_CTRL_STRB_SEL_MASK; | |
835 | regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT; | |
836 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
837 | break; | |
838 | default: | |
839 | break; | |
840 | } | |
841 | ||
842 | tap_delay = (degrees * tap_max) / 360; | |
843 | /* Set the Clock Phase */ | |
844 | if (tap_delay) { | |
845 | regval = sdhci_readl(host, PHY_CTRL_REG1); | |
846 | regval |= PHY_CTRL_ITAP_CHG_WIN_MASK; | |
847 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
848 | regval |= PHY_CTRL_ITAPDLY_ENA_MASK; | |
849 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
850 | regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK; | |
851 | regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT; | |
852 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
853 | regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK; | |
854 | sdhci_writel(host, regval, PHY_CTRL_REG1); | |
855 | } | |
856 | ||
857 | return 0; | |
858 | } | |
859 | ||
5ab5d9a4 | 860 | static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) |
d1f4e39d SDPP |
861 | { |
862 | struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); | |
f4b297bb | 863 | struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; |
d1f4e39d | 864 | struct mmc *mmc = (struct mmc *)host->mmc; |
f4b297bb ARS |
865 | struct udevice *dev = mmc->dev; |
866 | u8 timing = mode2timing[mmc->selected_mode]; | |
867 | u32 iclk_phase = clk_data->clk_phase_in[timing]; | |
868 | u32 oclk_phase = clk_data->clk_phase_out[timing]; | |
5ab5d9a4 | 869 | int ret; |
d1f4e39d | 870 | |
f4b297bb | 871 | dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing); |
d1f4e39d | 872 | |
f4b297bb | 873 | if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && |
bde2e728 | 874 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) { |
5ab5d9a4 ARS |
875 | ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase); |
876 | if (ret) | |
877 | return ret; | |
878 | ||
879 | ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase); | |
880 | if (ret) | |
881 | return ret; | |
11716acd | 882 | } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL) || |
4950a98d MS |
883 | IS_ENABLED(CONFIG_ARCH_VERSAL_NET) || |
884 | IS_ENABLED(CONFIG_ARCH_VERSAL2)) && | |
bde2e728 | 885 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) { |
5ab5d9a4 ARS |
886 | ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase); |
887 | if (ret) | |
888 | return ret; | |
889 | ||
890 | ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase); | |
891 | if (ret) | |
892 | return ret; | |
4950a98d MS |
893 | } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) || |
894 | IS_ENABLED(CONFIG_ARCH_VERSAL2)) && | |
bde2e728 | 895 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) { |
14ef4c7b ARS |
896 | if (mmc->clock >= MIN_PHY_CLK_HZ) |
897 | if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN) | |
898 | iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL; | |
899 | ||
900 | ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase); | |
901 | if (ret) | |
902 | return ret; | |
903 | ||
904 | ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase); | |
905 | if (ret) | |
906 | return ret; | |
f4b297bb | 907 | } |
5ab5d9a4 ARS |
908 | |
909 | return 0; | |
d1f4e39d SDPP |
910 | } |
911 | ||
80355ae4 MS |
912 | static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing, |
913 | const char *prop) | |
914 | { | |
915 | struct arasan_sdhci_priv *priv = dev_get_priv(dev); | |
916 | struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; | |
917 | u32 clk_phase[2] = {0}; | |
918 | ||
919 | /* | |
920 | * Read Tap Delay values from DT, if the DT does not contain the | |
921 | * Tap Values then use the pre-defined values | |
922 | */ | |
923 | if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) { | |
924 | dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n", | |
925 | prop, clk_data->clk_phase_in[timing], | |
926 | clk_data->clk_phase_out[timing]); | |
927 | return; | |
928 | } | |
929 | ||
930 | /* The values read are Input and Output Clock Delays in order */ | |
931 | clk_data->clk_phase_in[timing] = clk_phase[0]; | |
932 | clk_data->clk_phase_out[timing] = clk_phase[1]; | |
933 | } | |
934 | ||
935 | /** | |
936 | * arasan_dt_parse_clk_phases - Read Tap Delay values from DT | |
937 | * | |
80355ae4 | 938 | * @dev: Pointer to our struct udevice. |
c0436fcf MS |
939 | * |
940 | * Called at initialization to parse the values of Tap Delays. | |
80355ae4 MS |
941 | */ |
942 | static void arasan_dt_parse_clk_phases(struct udevice *dev) | |
943 | { | |
944 | struct arasan_sdhci_priv *priv = dev_get_priv(dev); | |
945 | struct arasan_sdhci_clk_data *clk_data = &priv->clk_data; | |
946 | int i; | |
947 | ||
948 | if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) && | |
bde2e728 | 949 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) { |
80355ae4 MS |
950 | for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { |
951 | clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i]; | |
952 | clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i]; | |
953 | } | |
954 | ||
955 | if (priv->bank == MMC_BANK2) { | |
956 | clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90; | |
957 | clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90; | |
958 | } | |
959 | } | |
960 | ||
11716acd | 961 | if ((IS_ENABLED(CONFIG_ARCH_VERSAL) || |
4950a98d MS |
962 | IS_ENABLED(CONFIG_ARCH_VERSAL_NET) || |
963 | IS_ENABLED(CONFIG_ARCH_VERSAL2)) && | |
bde2e728 | 964 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) { |
2e819a77 ARS |
965 | for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { |
966 | clk_data->clk_phase_in[i] = versal_iclk_phases[i]; | |
967 | clk_data->clk_phase_out[i] = versal_oclk_phases[i]; | |
968 | } | |
969 | } | |
970 | ||
4950a98d MS |
971 | if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) || |
972 | IS_ENABLED(CONFIG_ARCH_VERSAL2)) && | |
bde2e728 | 973 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) { |
14ef4c7b ARS |
974 | for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { |
975 | clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i]; | |
976 | clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i]; | |
977 | } | |
978 | } | |
979 | ||
80355ae4 MS |
980 | arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY, |
981 | "clk-phase-legacy"); | |
982 | arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS, | |
983 | "clk-phase-mmc-hs"); | |
984 | arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS, | |
985 | "clk-phase-sd-hs"); | |
986 | arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12, | |
987 | "clk-phase-uhs-sdr12"); | |
988 | arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25, | |
989 | "clk-phase-uhs-sdr25"); | |
990 | arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50, | |
991 | "clk-phase-uhs-sdr50"); | |
992 | arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104, | |
993 | "clk-phase-uhs-sdr104"); | |
994 | arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50, | |
995 | "clk-phase-uhs-ddr50"); | |
996 | arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52, | |
997 | "clk-phase-mmc-ddr52"); | |
998 | arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200, | |
999 | "clk-phase-mmc-hs200"); | |
1000 | arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400, | |
1001 | "clk-phase-mmc-hs400"); | |
1002 | } | |
1003 | ||
419b4a86 MS |
1004 | static const struct sdhci_ops arasan_ops = { |
1005 | .platform_execute_tuning = &arasan_sdhci_execute_tuning, | |
d1f4e39d | 1006 | .set_delay = &arasan_sdhci_set_tapdelay, |
3ae330c1 | 1007 | .set_control_reg = &sdhci_set_control_reg, |
4950a98d | 1008 | #if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2) |
14ef4c7b ARS |
1009 | .config_dll = &arasan_sdhci_config_dll, |
1010 | #endif | |
d1f4e39d SDPP |
1011 | }; |
1012 | #endif | |
1013 | ||
6d87b157 | 1014 | #if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE) |
90ab7faf ARS |
1015 | static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv, |
1016 | struct udevice *dev) | |
1017 | { | |
1018 | int ret; | |
90ab7faf ARS |
1019 | struct clk clk; |
1020 | unsigned long clock, mhz; | |
1021 | ||
aba0e651 ARS |
1022 | ret = xilinx_pm_request(PM_REQUEST_NODE, priv->node_id, |
1023 | ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS, | |
1024 | ZYNQMP_PM_REQUEST_ACK_NO, NULL); | |
90ab7faf | 1025 | if (ret) { |
aba0e651 | 1026 | dev_err(dev, "Request node failed for %d\n", priv->node_id); |
90ab7faf ARS |
1027 | return ret; |
1028 | } | |
1029 | ||
1030 | ret = reset_get_bulk(dev, &priv->resets); | |
1031 | if (ret == -ENOTSUPP || ret == -ENOENT) { | |
1032 | dev_err(dev, "Reset not found\n"); | |
1033 | return 0; | |
1034 | } else if (ret) { | |
1035 | dev_err(dev, "Reset failed\n"); | |
1036 | return ret; | |
1037 | } | |
1038 | ||
1039 | ret = reset_assert_bulk(&priv->resets); | |
1040 | if (ret) { | |
1041 | dev_err(dev, "Reset assert failed\n"); | |
1042 | return ret; | |
1043 | } | |
1044 | ||
aba0e651 | 1045 | ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_FIXED, 0); |
90ab7faf ARS |
1046 | if (ret) { |
1047 | dev_err(dev, "SD_CONFIG_FIXED failed\n"); | |
1048 | return ret; | |
1049 | } | |
1050 | ||
aba0e651 | 1051 | ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_EMMC_SEL, |
90ab7faf ARS |
1052 | dev_read_bool(dev, "non-removable")); |
1053 | if (ret) { | |
1054 | dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n"); | |
1055 | return ret; | |
1056 | } | |
1057 | ||
1058 | ret = clk_get_by_index(dev, 0, &clk); | |
1059 | if (ret < 0) { | |
1060 | dev_err(dev, "failed to get clock\n"); | |
1061 | return ret; | |
1062 | } | |
1063 | ||
1064 | clock = clk_get_rate(&clk); | |
1065 | if (IS_ERR_VALUE(clock)) { | |
1066 | dev_err(dev, "failed to get rate\n"); | |
1067 | return clock; | |
1068 | } | |
1069 | ||
1070 | mhz = DIV64_U64_ROUND_UP(clock, 1000000); | |
1071 | ||
035d56f2 ARS |
1072 | if (mhz > 100 && mhz <= 200) |
1073 | mhz = 200; | |
1074 | else if (mhz > 50 && mhz <= 100) | |
1075 | mhz = 100; | |
1076 | else if (mhz > 25 && mhz <= 50) | |
1077 | mhz = 50; | |
1078 | else | |
1079 | mhz = 25; | |
1080 | ||
aba0e651 | 1081 | ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_BASECLK, mhz); |
90ab7faf ARS |
1082 | if (ret) { |
1083 | dev_err(dev, "SD_CONFIG_BASECLK failed\n"); | |
1084 | return ret; | |
1085 | } | |
1086 | ||
aba0e651 | 1087 | ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_8BIT, |
90ab7faf ARS |
1088 | (dev_read_u32_default(dev, "bus-width", 1) == 8)); |
1089 | if (ret) { | |
1090 | dev_err(dev, "SD_CONFIG_8BIT failed\n"); | |
1091 | return ret; | |
1092 | } | |
1093 | ||
1094 | ret = reset_deassert_bulk(&priv->resets); | |
1095 | if (ret) { | |
1096 | dev_err(dev, "Reset release failed\n"); | |
1097 | return ret; | |
1098 | } | |
1099 | ||
1100 | return 0; | |
1101 | } | |
1102 | #endif | |
1103 | ||
d9ae52c8 | 1104 | static int arasan_sdhci_probe(struct udevice *dev) |
293eb33f | 1105 | { |
c69cda25 | 1106 | struct arasan_sdhci_plat *plat = dev_get_plat(dev); |
d9ae52c8 | 1107 | struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); |
d1f4e39d SDPP |
1108 | struct arasan_sdhci_priv *priv = dev_get_priv(dev); |
1109 | struct sdhci_host *host; | |
e0f4de1a SH |
1110 | struct clk clk; |
1111 | unsigned long clock; | |
329a449f | 1112 | int ret; |
293eb33f | 1113 | |
d1f4e39d SDPP |
1114 | host = priv->host; |
1115 | ||
6d87b157 | 1116 | #if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE) |
bde2e728 | 1117 | if (arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) { |
90ab7faf ARS |
1118 | ret = zynqmp_pm_is_function_supported(PM_IOCTL, |
1119 | IOCTL_SET_SD_CONFIG); | |
1120 | if (!ret) { | |
1121 | ret = sdhci_zynqmp_set_dynamic_config(priv, dev); | |
1122 | if (ret) | |
1123 | return ret; | |
1124 | } | |
1125 | } | |
1126 | #endif | |
bde2e728 | 1127 | if (arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) |
14ef4c7b | 1128 | priv->internal_phy_reg = true; |
90ab7faf | 1129 | |
e0f4de1a SH |
1130 | ret = clk_get_by_index(dev, 0, &clk); |
1131 | if (ret < 0) { | |
1132 | dev_err(dev, "failed to get clock\n"); | |
1133 | return ret; | |
1134 | } | |
1135 | ||
1136 | clock = clk_get_rate(&clk); | |
1137 | if (IS_ERR_VALUE(clock)) { | |
1138 | dev_err(dev, "failed to get rate\n"); | |
1139 | return clock; | |
1140 | } | |
d1f4e39d | 1141 | |
90ab7faf | 1142 | dev_dbg(dev, "%s: CLK %ld\n", __func__, clock); |
e0f4de1a SH |
1143 | |
1144 | ret = clk_enable(&clk); | |
9b7aac75 | 1145 | if (ret) { |
e0f4de1a SH |
1146 | dev_err(dev, "failed to enable clock\n"); |
1147 | return ret; | |
1148 | } | |
1149 | ||
eddabd16 | 1150 | host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | |
f9ec45d1 | 1151 | SDHCI_QUIRK_BROKEN_R1B; |
b2156146 SDPP |
1152 | |
1153 | #ifdef CONFIG_ZYNQ_HISPD_BROKEN | |
47819216 | 1154 | host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE; |
b2156146 SDPP |
1155 | #endif |
1156 | ||
7a49a16e ARS |
1157 | if (priv->no_1p8) |
1158 | host->quirks |= SDHCI_QUIRK_NO_1_8_V; | |
1159 | ||
a1f8abf4 | 1160 | if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) && |
bde2e728 | 1161 | arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) |
a1f8abf4 ARS |
1162 | host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400; |
1163 | ||
942b5fc0 BG |
1164 | plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ; |
1165 | ||
1166 | ret = mmc_of_parse(dev, &plat->cfg); | |
1167 | if (ret) | |
1168 | return ret; | |
d1f4e39d | 1169 | |
e0f4de1a | 1170 | host->max_clk = clock; |
6d0e34bf | 1171 | |
3148a3c2 MK |
1172 | host->mmc = &plat->mmc; |
1173 | host->mmc->dev = dev; | |
1174 | host->mmc->priv = host; | |
1175 | ||
942b5fc0 | 1176 | ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max, |
14bed52d | 1177 | CONFIG_ZYNQ_SDHCI_MIN_FREQ); |
329a449f SG |
1178 | if (ret) |
1179 | return ret; | |
329a449f | 1180 | upriv->mmc = host->mmc; |
d9ae52c8 | 1181 | |
b6f44082 KR |
1182 | /* |
1183 | * WORKAROUND: Versal platforms have an issue with card detect state. | |
1184 | * Due to this, host controller is switching off voltage to sd card | |
1185 | * causing sd card timeout error. Workaround this by adding a wait for | |
1186 | * 1000msec till the card detect state gets stable. | |
1187 | */ | |
980e5551 | 1188 | if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) { |
8d32bca2 | 1189 | u32 timeout = 1000000; |
b6f44082 KR |
1190 | |
1191 | while (((sdhci_readl(host, SDHCI_PRESENT_STATE) & | |
c252b277 | 1192 | SDHCI_CARD_STATE_STABLE) == 0) && timeout) { |
8d32bca2 | 1193 | udelay(1); |
c252b277 | 1194 | timeout--; |
b6f44082 KR |
1195 | } |
1196 | if (!timeout) { | |
1197 | dev_err(dev, "Sdhci card detect state not stable\n"); | |
1198 | return -ETIMEDOUT; | |
1199 | } | |
1200 | } | |
1201 | ||
329a449f | 1202 | return sdhci_probe(dev); |
293eb33f | 1203 | } |
d9ae52c8 | 1204 | |
d1998a9f | 1205 | static int arasan_sdhci_of_to_plat(struct udevice *dev) |
d9ae52c8 | 1206 | { |
d1f4e39d | 1207 | struct arasan_sdhci_priv *priv = dev_get_priv(dev); |
aba0e651 | 1208 | u32 pm_info[2]; |
d1f4e39d SDPP |
1209 | |
1210 | priv->host = calloc(1, sizeof(struct sdhci_host)); | |
1211 | if (!priv->host) | |
1212 | return -1; | |
d9ae52c8 | 1213 | |
d1f4e39d | 1214 | priv->host->name = dev->name; |
d1f4e39d | 1215 | |
4950a98d MS |
1216 | #if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) || \ |
1217 | defined(CONFIG_ARCH_VERSAL2) | |
d1f4e39d | 1218 | priv->host->ops = &arasan_ops; |
80355ae4 | 1219 | arasan_dt_parse_clk_phases(dev); |
d1f4e39d | 1220 | #endif |
d9ae52c8 | 1221 | |
a12a73b6 JJ |
1222 | priv->host->ioaddr = dev_read_addr_ptr(dev); |
1223 | if (!priv->host->ioaddr) | |
1224 | return -EINVAL; | |
61e745d1 | 1225 | |
e8deb221 | 1226 | priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0); |
7a49a16e | 1227 | priv->no_1p8 = dev_read_bool(dev, "no-1-8-v"); |
458e8d80 | 1228 | |
aba0e651 ARS |
1229 | priv->node_id = 0; |
1230 | if (!dev_read_u32_array(dev, "power-domains", pm_info, ARRAY_SIZE(pm_info))) | |
1231 | priv->node_id = pm_info[1]; | |
1232 | ||
d9ae52c8 MS |
1233 | return 0; |
1234 | } | |
1235 | ||
329a449f SG |
1236 | static int arasan_sdhci_bind(struct udevice *dev) |
1237 | { | |
c69cda25 | 1238 | struct arasan_sdhci_plat *plat = dev_get_plat(dev); |
329a449f | 1239 | |
24f5aec3 | 1240 | return sdhci_bind(dev, &plat->mmc, &plat->cfg); |
329a449f SG |
1241 | } |
1242 | ||
d9ae52c8 | 1243 | static const struct udevice_id arasan_sdhci_ids[] = { |
bde2e728 PB |
1244 | { .compatible = "arasan,sdhci-8.9a", .data = SDHCI_COMPATIBLE_SDHCI_89A }, |
1245 | { .compatible = "xlnx,versal-net-emmc", .data = SDHCI_COMPATIBLE_VERSAL_NET_EMMC }, | |
d9ae52c8 MS |
1246 | { } |
1247 | }; | |
1248 | ||
1249 | U_BOOT_DRIVER(arasan_sdhci_drv) = { | |
1250 | .name = "arasan_sdhci", | |
1251 | .id = UCLASS_MMC, | |
1252 | .of_match = arasan_sdhci_ids, | |
d1998a9f | 1253 | .of_to_plat = arasan_sdhci_of_to_plat, |
329a449f SG |
1254 | .ops = &sdhci_ops, |
1255 | .bind = arasan_sdhci_bind, | |
d9ae52c8 | 1256 | .probe = arasan_sdhci_probe, |
41575d8e | 1257 | .priv_auto = sizeof(struct arasan_sdhci_priv), |
caa4daa2 | 1258 | .plat_auto = sizeof(struct arasan_sdhci_plat), |
d9ae52c8 | 1259 | }; |