blob: 28d2b456fbf6e8001d121970d6613175843f4aff [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek0dd222b2013-04-22 14:56:49 +02002/*
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07003 * (C) Copyright 2013 - 2022, Xilinx, Inc.
4 * (C) Copyright 2022, Advanced Micro Devices, Inc.
Michal Simek0dd222b2013-04-22 14:56:49 +02005 *
6 * Xilinx Zynq SD Host Controller Interface
Michal Simek0dd222b2013-04-22 14:56:49 +02007 */
8
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01009#include <clk.h>
Michal Simek9ecd2682015-11-30 16:13:03 +010010#include <dm.h>
Michal Simekc57ba042014-02-24 11:16:31 +010011#include <fdtdec.h>
Simon Glassdbd79542020-05-10 11:40:11 -060012#include <linux/delay.h>
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +053013#include "mmc_private.h"
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +010015#include <reset.h>
Algapally Santosh Sagar58f731a2023-03-01 03:33:33 -070016#include <asm/arch/sys_proto.h>
Simon Glass9bc15642020-02-03 07:36:16 -070017#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070018#include <linux/err.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090019#include <linux/libfdt.h>
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -070020#include <linux/iopoll.h>
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +010021#include <asm/types.h>
22#include <linux/math64.h>
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -060023#include <asm/cache.h>
Michal Simek0dd222b2013-04-22 14:56:49 +020024#include <malloc.h>
25#include <sdhci.h>
Ashok Reddy Soma467d0782021-08-02 23:20:43 -060026#include <zynqmp_firmware.h>
Michal Simek0dd222b2013-04-22 14:56:49 +020027
Ashok Reddy Soma24a51072021-07-09 05:53:41 -060028#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)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -060035
Michal Simek5b5101e2020-10-23 04:58:59 -060036#define SDHCI_TUNING_LOOP_COUNT 40
Michal Simek33a6b772020-10-23 04:59:00 -060037#define MMC_BANK2 0x2
38
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -060039#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
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -070053#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
Michal Simek33a6b772020-10-23 04:59:00 -060088struct 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};
Michal Simek5b5101e2020-10-23 04:58:59 -060092
Simon Glass4cc87fb2016-07-05 17:10:15 -060093struct arasan_sdhci_plat {
94 struct mmc_config cfg;
95 struct mmc mmc;
96};
97
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +053098struct arasan_sdhci_priv {
99 struct sdhci_host *host;
Michal Simek33a6b772020-10-23 04:59:00 -0600100 struct arasan_sdhci_clk_data clk_data;
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600101 u32 node_id;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530102 u8 bank;
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -0600103 u8 no_1p8;
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700104 bool internal_phy_reg;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +0100105 struct reset_ctl_bulk resets;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530106};
107
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600108/* For Versal platforms zynqmp_mmio_write() won't be available */
109__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
110{
111 return 0;
112}
113
T Karthik Reddyd0618272021-10-01 16:38:38 +0530114__weak int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
115 u32 arg3, u32 *ret_payload)
116{
117 return 0;
118}
119
T Karthik Reddy0b35fa22022-04-27 10:27:12 +0200120__weak int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
121{
122 return 1;
123}
124
Michal Simek534a9342024-05-29 16:48:00 +0200125#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || \
126 defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Michal Simek33a6b772020-10-23 04:59:00 -0600127/* Default settings for ZynqMP Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600128static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0,
129 0, 183, 54, 0, 0};
130static const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72,
131 135, 48, 72, 135, 0};
Michal Simek33a6b772020-10-23 04:59:00 -0600132
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600133/* Default settings for Versal Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600134static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132,
135 0, 0, 162, 90, 0, 0};
136static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72,
137 90, 36, 60, 90, 0};
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600138
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700139/* Default settings for versal-net eMMC Clock Phases */
140static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39,
141 0, 0};
142static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0,
143 113, 79, 45};
144
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530145static const u8 mode2timing[] = {
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600146 [MMC_LEGACY] = MMC_TIMING_LEGACY,
147 [MMC_HS] = MMC_TIMING_MMC_HS,
148 [SD_HS] = MMC_TIMING_SD_HS,
Ashok Reddy Soma5ff7acf2022-06-27 14:22:45 +0530149 [MMC_HS_52] = MMC_TIMING_MMC_HS,
150 [MMC_DDR_52] = MMC_TIMING_MMC_DDR52,
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600151 [UHS_SDR12] = MMC_TIMING_UHS_SDR12,
152 [UHS_SDR25] = MMC_TIMING_UHS_SDR25,
153 [UHS_SDR50] = MMC_TIMING_UHS_SDR50,
154 [UHS_DDR50] = MMC_TIMING_UHS_DDR50,
155 [UHS_SDR104] = MMC_TIMING_UHS_SDR104,
156 [MMC_HS_200] = MMC_TIMING_MMC_HS200,
Ashok Reddy Soma407a5612023-01-10 04:31:24 -0700157 [MMC_HS_400] = MMC_TIMING_MMC_HS400,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530158};
159
Michal Simek534a9342024-05-29 16:48:00 +0200160#if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700161/**
162 * arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock
163 *
164 * @host: Pointer to the sdhci_host structure
165 * @enable: Enable or disable Delay chain based Tx and Rx clock
166 * Return: None
167 *
168 * Enable or disable eMMC delay chain based Input and Output clock in
169 * PHY_CTRL_REG2
170 */
171static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable)
172{
173 u32 reg;
174
175 reg = sdhci_readw(host, PHY_CTRL_REG2);
176 if (enable)
177 reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK;
178 else
179 reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK);
180
181 sdhci_writew(host, reg, PHY_CTRL_REG2);
182}
183
184/**
185 * arasan_phy_set_dll - Set eMMC DLL clock
186 *
187 * @host: Pointer to the sdhci_host structure
188 * @enable: Enable or disable DLL clock
189 * Return: 0 if success or timeout error
190 *
191 * Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is
192 * set, wait till DLL is locked
193 */
194static int arasan_phy_set_dll(struct sdhci_host *host, bool enable)
195{
196 u32 reg;
197
198 reg = sdhci_readw(host, PHY_CTRL_REG2);
199 if (enable)
200 reg |= PHY_CTRL_EN_DLL_MASK;
201 else
202 reg &= ~PHY_CTRL_EN_DLL_MASK;
203
204 sdhci_writew(host, reg, PHY_CTRL_REG2);
205
206 /* If DLL is disabled return success */
207 if (!enable)
208 return 0;
209
210 /* If DLL is enabled wait till DLL loop is locked, which is
211 * indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2
212 */
213 return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg,
214 (reg & PHY_CTRL_DLL_RDY_MASK),
215 1000 * PHY_DLL_TIMEOUT_MS);
216}
217
218/**
219 * arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC
220 *
221 * @host: Pointer to the sdhci_host structure
222 * @clock: clock value
223 * Return: None
224 *
225 * Set frequency range bits based on the selected clock for eMMC
226 */
227static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock)
228{
229 u32 reg, freq_sel, freq;
230
231 freq = DIV_ROUND_CLOSEST(clock, 1000000);
232 if (freq <= 200 && freq > 170)
233 freq_sel = FREQSEL_200M_170M;
234 else if (freq <= 170 && freq > 140)
235 freq_sel = FREQSEL_170M_140M;
236 else if (freq <= 140 && freq > 110)
237 freq_sel = FREQSEL_140M_110M;
238 else if (freq <= 110 && freq > 80)
239 freq_sel = FREQSEL_110M_80M;
240 else
241 freq_sel = FREQSEL_80M_50M;
242
243 reg = sdhci_readw(host, PHY_CTRL_REG2);
244 reg &= ~PHY_CTRL_FREQ_SEL_MASK;
245 reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT);
246 sdhci_writew(host, reg, PHY_CTRL_REG2);
247}
248
249static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable)
250{
251 struct mmc *mmc = (struct mmc *)host->mmc;
252 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
253
254 if (enable) {
255 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable)
256 arasan_phy_set_dll(host, 1);
257 return 0;
258 }
259
260 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) {
261 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
262 arasan_phy_set_dll(host, 0);
263 arasan_phy_set_delaychain(host, 0);
264 arasan_phy_dll_set_freq(host, clock);
265 return 0;
266 }
267
268 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
269 arasan_phy_set_delaychain(host, 1);
270
271 return 0;
272}
273#endif
274
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600275static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600276{
277 int ret;
278
279 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
280 if (node_id == NODE_SD_0) {
281 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
282 SD0_ITAPCHGWIN);
283 if (ret)
284 return ret;
285
286 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
287 SD0_ITAPDLYENA);
288 if (ret)
289 return ret;
290
291 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
292 itap_delay);
293 if (ret)
294 return ret;
295
296 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
297 if (ret)
298 return ret;
299 }
300 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
301 SD1_ITAPCHGWIN);
302 if (ret)
303 return ret;
304
305 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
306 SD1_ITAPDLYENA);
307 if (ret)
308 return ret;
309
310 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
311 (itap_delay << 16));
312 if (ret)
313 return ret;
314
315 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
316 if (ret)
317 return ret;
318 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600319 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600320 IOCTL_SET_SD_TAPDELAY,
321 PM_TAPDELAY_INPUT, itap_delay, NULL);
322 }
323
324 return 0;
325}
326
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600327static inline int arasan_zynqmp_set_out_tapdelay(u32 node_id, u32 otap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600328{
329 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
330 if (node_id == NODE_SD_0)
331 return zynqmp_mmio_write(SD_OTAP_DLY,
332 SD0_OTAPDLYSEL_MASK,
333 otap_delay);
334
335 return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
336 (otap_delay << 16));
337 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600338 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600339 IOCTL_SET_SD_TAPDELAY,
340 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
341 }
342}
343
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600344static inline int zynqmp_dll_reset(u32 node_id, u32 type)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600345{
346 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
347 if (node_id == NODE_SD_0)
348 return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
349 type == PM_DLL_RESET_ASSERT ?
350 SD0_DLL_RST : 0);
351
352 return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
353 type == PM_DLL_RESET_ASSERT ?
354 SD1_DLL_RST : 0);
355 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600356 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600357 IOCTL_SD_DLL_RESET, type, 0, NULL);
358 }
359}
360
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600361static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 node_id)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530362{
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600363 struct mmc *mmc = (struct mmc *)host->mmc;
364 struct udevice *dev = mmc->dev;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530365 unsigned long timeout;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600366 int ret;
367 u16 clk;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530368
369 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
370 clk &= ~(SDHCI_CLOCK_CARD_EN);
371 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
372
373 /* Issue DLL Reset */
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600374 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
375 if (ret) {
376 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
377 return ret;
378 }
379
380 /* Allow atleast 1ms delay for proper DLL reset */
381 mdelay(1);
382 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
383 if (ret) {
384 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
385 return ret;
386 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530387
388 /* Wait max 20 ms */
389 timeout = 100;
390 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
391 & SDHCI_CLOCK_INT_STABLE)) {
392 if (timeout == 0) {
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600393 dev_err(dev, ": Internal clock never stabilised.\n");
394 return -EBUSY;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530395 }
396 timeout--;
397 udelay(1000);
398 }
399
400 clk |= SDHCI_CLOCK_CARD_EN;
401 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600402
403 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530404}
405
406static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
407{
408 struct mmc_cmd cmd;
409 struct mmc_data data;
410 u32 ctrl;
411 struct sdhci_host *host;
412 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Algapally Santosh Sagar99a98ca2023-01-19 22:36:17 -0700413 int tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530414
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +0100415 dev_dbg(mmc->dev, "%s\n", __func__);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530416
417 host = priv->host;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530418
Faiz Abbas2eddc002019-06-11 00:43:40 +0530419 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530420 ctrl |= SDHCI_CTRL_EXEC_TUNING;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530421 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530422
423 mdelay(1);
424
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200425 if (device_is_compatible(mmc->dev, "xlnx,zynqmp-8.9a"))
426 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530427
428 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
429 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
430
431 do {
432 cmd.cmdidx = opcode;
433 cmd.resp_type = MMC_RSP_R1;
434 cmd.cmdarg = 0;
435
436 data.blocksize = 64;
437 data.blocks = 1;
438 data.flags = MMC_DATA_READ;
439
440 if (tuning_loop_counter-- == 0)
441 break;
442
443 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
444 mmc->bus_width == 8)
445 data.blocksize = 128;
446
447 sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
448 data.blocksize),
449 SDHCI_BLOCK_SIZE);
450 sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
451 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
452
453 mmc_send_cmd(mmc, &cmd, NULL);
Faiz Abbas2eddc002019-06-11 00:43:40 +0530454 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530455
456 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
457 udelay(1);
458
459 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
460
461 if (tuning_loop_counter < 0) {
462 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530463 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530464 }
465
466 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
467 printf("%s:Tuning failed\n", __func__);
468 return -1;
469 }
470
471 udelay(1);
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200472
473 if (device_is_compatible(mmc->dev, "xlnx,zynqmp-8.9a"))
474 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530475
476 /* Enable only interrupts served by the SD controller */
477 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
478 SDHCI_INT_ENABLE);
479 /* Mask all sdhci interrupt sources */
480 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
481
482 return 0;
483}
484
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600485/**
486 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
487 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600488 * @host: Pointer to the sdhci_host structure.
489 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600490 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600491 *
492 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600493 */
494static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
495 int degrees)
496{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600497 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600498 struct udevice *dev = mmc->dev;
499 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600500 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600501 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600502 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600503
504 /*
505 * This is applicable for SDHCI_SPEC_300 and above
506 * ZynqMP does not set phase for <=25MHz clock.
507 * If degrees is zero, no need to do anything.
508 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600509 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600510 return 0;
511
512 switch (timing) {
513 case MMC_TIMING_MMC_HS:
514 case MMC_TIMING_SD_HS:
515 case MMC_TIMING_UHS_SDR25:
516 case MMC_TIMING_UHS_DDR50:
517 case MMC_TIMING_MMC_DDR52:
518 /* For 50MHz clock, 30 Taps are available */
519 tap_max = 30;
520 break;
521 case MMC_TIMING_UHS_SDR50:
522 /* For 100MHz clock, 15 Taps are available */
523 tap_max = 15;
524 break;
525 case MMC_TIMING_UHS_SDR104:
526 case MMC_TIMING_MMC_HS200:
527 /* For 200MHz clock, 8 Taps are available */
528 tap_max = 8;
529 default:
530 break;
531 }
532
533 tap_delay = (degrees * tap_max) / 360;
534
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600535 /* Limit output tap_delay value to 6 bits */
536 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
537
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600538 /* Set the Clock Phase */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600539 ret = arasan_zynqmp_set_out_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600540 if (ret) {
541 dev_err(dev, "Error setting output Tap Delay\n");
542 return ret;
543 }
544
545 /* Release DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600546 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_RELEASE);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600547 if (ret) {
548 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
549 return ret;
550 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600551
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600552 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600553}
554
555/**
556 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
557 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600558 * @host: Pointer to the sdhci_host structure.
559 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600560 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600561 *
562 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600563 */
564static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
565 int degrees)
566{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600567 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600568 struct udevice *dev = mmc->dev;
569 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600570 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600571 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600572 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600573
574 /*
575 * This is applicable for SDHCI_SPEC_300 and above
576 * ZynqMP does not set phase for <=25MHz clock.
577 * If degrees is zero, no need to do anything.
578 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600579 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600580 return 0;
581
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600582 /* Assert DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600583 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_ASSERT);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600584 if (ret) {
585 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
586 return ret;
587 }
588
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600589 switch (timing) {
590 case MMC_TIMING_MMC_HS:
591 case MMC_TIMING_SD_HS:
592 case MMC_TIMING_UHS_SDR25:
593 case MMC_TIMING_UHS_DDR50:
594 case MMC_TIMING_MMC_DDR52:
595 /* For 50MHz clock, 120 Taps are available */
596 tap_max = 120;
597 break;
598 case MMC_TIMING_UHS_SDR50:
599 /* For 100MHz clock, 60 Taps are available */
600 tap_max = 60;
601 break;
602 case MMC_TIMING_UHS_SDR104:
603 case MMC_TIMING_MMC_HS200:
604 /* For 200MHz clock, 30 Taps are available */
605 tap_max = 30;
606 default:
607 break;
608 }
609
610 tap_delay = (degrees * tap_max) / 360;
611
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600612 /* Limit input tap_delay value to 8 bits */
613 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
614
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600615 ret = arasan_zynqmp_set_in_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600616 if (ret) {
617 dev_err(dev, "Error setting Input Tap Delay\n");
618 return ret;
619 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600620
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600621 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600622}
623
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600624/**
625 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
626 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600627 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600628 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600629 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600630 *
631 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600632 */
633static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
634 int degrees)
635{
636 struct mmc *mmc = (struct mmc *)host->mmc;
637 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600638 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600639 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600640
641 /*
642 * This is applicable for SDHCI_SPEC_300 and above
643 * Versal does not set phase for <=25MHz clock.
644 * If degrees is zero, no need to do anything.
645 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600646 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600647 return 0;
648
649 switch (timing) {
650 case MMC_TIMING_MMC_HS:
651 case MMC_TIMING_SD_HS:
652 case MMC_TIMING_UHS_SDR25:
653 case MMC_TIMING_UHS_DDR50:
654 case MMC_TIMING_MMC_DDR52:
655 /* For 50MHz clock, 30 Taps are available */
656 tap_max = 30;
657 break;
658 case MMC_TIMING_UHS_SDR50:
659 /* For 100MHz clock, 15 Taps are available */
660 tap_max = 15;
661 break;
662 case MMC_TIMING_UHS_SDR104:
663 case MMC_TIMING_MMC_HS200:
664 /* For 200MHz clock, 8 Taps are available */
665 tap_max = 8;
666 default:
667 break;
668 }
669
670 tap_delay = (degrees * tap_max) / 360;
671
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600672 /* Limit output tap_delay value to 6 bits */
673 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600674
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600675 /* Set the Clock Phase */
676 regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
677 regval |= SDHCI_OTAPDLY_ENABLE;
678 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
679 regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
680 regval |= tap_delay;
681 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600682
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600683 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600684}
685
686/**
687 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
688 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600689 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600690 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600691 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600692 *
693 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600694 */
695static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
696 int degrees)
697{
698 struct mmc *mmc = (struct mmc *)host->mmc;
699 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600700 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600701 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600702
703 /*
704 * This is applicable for SDHCI_SPEC_300 and above
705 * Versal does not set phase for <=25MHz clock.
706 * If degrees is zero, no need to do anything.
707 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600708 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600709 return 0;
710
711 switch (timing) {
712 case MMC_TIMING_MMC_HS:
713 case MMC_TIMING_SD_HS:
714 case MMC_TIMING_UHS_SDR25:
715 case MMC_TIMING_UHS_DDR50:
716 case MMC_TIMING_MMC_DDR52:
717 /* For 50MHz clock, 120 Taps are available */
718 tap_max = 120;
719 break;
720 case MMC_TIMING_UHS_SDR50:
721 /* For 100MHz clock, 60 Taps are available */
722 tap_max = 60;
723 break;
724 case MMC_TIMING_UHS_SDR104:
725 case MMC_TIMING_MMC_HS200:
726 /* For 200MHz clock, 30 Taps are available */
727 tap_max = 30;
728 default:
729 break;
730 }
731
732 tap_delay = (degrees * tap_max) / 360;
733
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600734 /* Limit input tap_delay value to 8 bits */
735 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600736
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600737 /* Set the Clock Phase */
738 regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
739 regval |= SDHCI_ITAPDLY_CHGWIN;
740 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
741 regval |= SDHCI_ITAPDLY_ENABLE;
742 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
743 regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
744 regval |= tap_delay;
745 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
746 regval &= ~SDHCI_ITAPDLY_CHGWIN;
747 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600748
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600749 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600750}
751
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700752/**
753 * sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays
754 *
755 * @host: Pointer to the sdhci_host structure.
756 * @degrees: The clock phase shift between 0 - 359.
757 * Return: 0
758 *
759 * Set eMMC Output Clock Tap Delays for Output path
760 */
761static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees)
762{
763 struct mmc *mmc = (struct mmc *)host->mmc;
764 int timing = mode2timing[mmc->selected_mode];
765 u8 tap_delay, tap_max = 0;
766 u32 regval;
767
768 switch (timing) {
769 case MMC_TIMING_MMC_HS:
770 case MMC_TIMING_MMC_DDR52:
771 tap_max = 16;
772 break;
773 case MMC_TIMING_MMC_HS200:
774 case MMC_TIMING_MMC_HS400:
775 /* For 200MHz clock, 32 Taps are available */
776 tap_max = 32;
777 break;
778 default:
779 break;
780 }
781
782 tap_delay = (degrees * tap_max) / 360;
783 /* Set the Clock Phase */
784 if (tap_delay) {
785 regval = sdhci_readl(host, PHY_CTRL_REG1);
786 regval |= PHY_CTRL_OTAPDLY_ENA_MASK;
787 sdhci_writel(host, regval, PHY_CTRL_REG1);
788 regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK;
789 regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT;
790 sdhci_writel(host, regval, PHY_CTRL_REG1);
791 }
792
793 return 0;
794}
795
796/**
797 * sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays
798 *
799 * @host: Pointer to the sdhci_host structure.
800 * @degrees: The clock phase shift between 0 - 359.
801 * Return: 0
802 *
803 * Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected,
804 * set strobe90 and strobe180 in PHY_CTRL_REG1.
805 */
806static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees)
807{
808 struct mmc *mmc = (struct mmc *)host->mmc;
809 int timing = mode2timing[mmc->selected_mode];
810 u8 tap_delay, tap_max = 0;
811 u32 regval;
812
813 switch (timing) {
814 case MMC_TIMING_MMC_HS:
815 case MMC_TIMING_MMC_DDR52:
816 tap_max = 32;
817 break;
818 case MMC_TIMING_MMC_HS400:
819 /* Strobe select tap point for strb90 and strb180 */
820 regval = sdhci_readl(host, PHY_CTRL_REG1);
821 regval &= ~PHY_CTRL_STRB_SEL_MASK;
822 regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT;
823 sdhci_writel(host, regval, PHY_CTRL_REG1);
824 break;
825 default:
826 break;
827 }
828
829 tap_delay = (degrees * tap_max) / 360;
830 /* Set the Clock Phase */
831 if (tap_delay) {
832 regval = sdhci_readl(host, PHY_CTRL_REG1);
833 regval |= PHY_CTRL_ITAP_CHG_WIN_MASK;
834 sdhci_writel(host, regval, PHY_CTRL_REG1);
835 regval |= PHY_CTRL_ITAPDLY_ENA_MASK;
836 sdhci_writel(host, regval, PHY_CTRL_REG1);
837 regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK;
838 regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT;
839 sdhci_writel(host, regval, PHY_CTRL_REG1);
840 regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK;
841 sdhci_writel(host, regval, PHY_CTRL_REG1);
842 }
843
844 return 0;
845}
846
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600847static int arasan_sdhci_set_tapdelay(struct sdhci_host *host)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530848{
849 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600850 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530851 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600852 struct udevice *dev = mmc->dev;
853 u8 timing = mode2timing[mmc->selected_mode];
854 u32 iclk_phase = clk_data->clk_phase_in[timing];
855 u32 oclk_phase = clk_data->clk_phase_out[timing];
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600856 int ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530857
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600858 dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530859
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600860 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
861 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600862 ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
863 if (ret)
864 return ret;
865
866 ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
867 if (ret)
868 return ret;
Simek, Michald78ea252024-04-17 20:06:13 -1200869 } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
Michal Simek534a9342024-05-29 16:48:00 +0200870 IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
871 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600872 device_is_compatible(dev, "xlnx,versal-8.9a")) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600873 ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
874 if (ret)
875 return ret;
876
877 ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
878 if (ret)
879 return ret;
Michal Simek534a9342024-05-29 16:48:00 +0200880 } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
881 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +0200882 device_is_compatible(dev, "xlnx,versal-net-emmc")) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700883 if (mmc->clock >= MIN_PHY_CLK_HZ)
884 if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN)
885 iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL;
886
887 ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase);
888 if (ret)
889 return ret;
890
891 ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase);
892 if (ret)
893 return ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600894 }
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600895
896 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530897}
898
Michal Simek33a6b772020-10-23 04:59:00 -0600899static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
900 const char *prop)
901{
902 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
903 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
904 u32 clk_phase[2] = {0};
905
906 /*
907 * Read Tap Delay values from DT, if the DT does not contain the
908 * Tap Values then use the pre-defined values
909 */
910 if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
911 dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
912 prop, clk_data->clk_phase_in[timing],
913 clk_data->clk_phase_out[timing]);
914 return;
915 }
916
917 /* The values read are Input and Output Clock Delays in order */
918 clk_data->clk_phase_in[timing] = clk_phase[0];
919 clk_data->clk_phase_out[timing] = clk_phase[1];
920}
921
922/**
923 * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
924 *
Michal Simek33a6b772020-10-23 04:59:00 -0600925 * @dev: Pointer to our struct udevice.
Michal Simek2a43ab82021-07-09 05:53:43 -0600926 *
927 * Called at initialization to parse the values of Tap Delays.
Michal Simek33a6b772020-10-23 04:59:00 -0600928 */
929static void arasan_dt_parse_clk_phases(struct udevice *dev)
930{
931 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
932 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
933 int i;
934
935 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
936 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
937 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
938 clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
939 clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
940 }
941
942 if (priv->bank == MMC_BANK2) {
943 clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
944 clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
945 }
946 }
947
Simek, Michald78ea252024-04-17 20:06:13 -1200948 if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
Michal Simek534a9342024-05-29 16:48:00 +0200949 IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
950 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600951 device_is_compatible(dev, "xlnx,versal-8.9a")) {
952 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
953 clk_data->clk_phase_in[i] = versal_iclk_phases[i];
954 clk_data->clk_phase_out[i] = versal_oclk_phases[i];
955 }
956 }
957
Michal Simek534a9342024-05-29 16:48:00 +0200958 if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
959 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +0200960 device_is_compatible(dev, "xlnx,versal-net-emmc")) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700961 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
962 clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i];
963 clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i];
964 }
965 }
966
Michal Simek33a6b772020-10-23 04:59:00 -0600967 arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
968 "clk-phase-legacy");
969 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
970 "clk-phase-mmc-hs");
971 arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
972 "clk-phase-sd-hs");
973 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
974 "clk-phase-uhs-sdr12");
975 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
976 "clk-phase-uhs-sdr25");
977 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
978 "clk-phase-uhs-sdr50");
979 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
980 "clk-phase-uhs-sdr104");
981 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
982 "clk-phase-uhs-ddr50");
983 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
984 "clk-phase-mmc-ddr52");
985 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
986 "clk-phase-mmc-hs200");
987 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
988 "clk-phase-mmc-hs400");
989}
990
Michal Simek635cf4a2021-07-09 05:53:44 -0600991static const struct sdhci_ops arasan_ops = {
992 .platform_execute_tuning = &arasan_sdhci_execute_tuning,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530993 .set_delay = &arasan_sdhci_set_tapdelay,
Ashok Reddy Soma8ee49f02021-08-02 23:20:46 -0600994 .set_control_reg = &sdhci_set_control_reg,
Michal Simek534a9342024-05-29 16:48:00 +0200995#if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700996 .config_dll = &arasan_sdhci_config_dll,
997#endif
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530998};
999#endif
1000
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -07001001#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001002static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
1003 struct udevice *dev)
1004{
1005 int ret;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001006 struct clk clk;
1007 unsigned long clock, mhz;
1008
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001009 ret = xilinx_pm_request(PM_REQUEST_NODE, priv->node_id,
1010 ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS,
1011 ZYNQMP_PM_REQUEST_ACK_NO, NULL);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001012 if (ret) {
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001013 dev_err(dev, "Request node failed for %d\n", priv->node_id);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001014 return ret;
1015 }
1016
1017 ret = reset_get_bulk(dev, &priv->resets);
1018 if (ret == -ENOTSUPP || ret == -ENOENT) {
1019 dev_err(dev, "Reset not found\n");
1020 return 0;
1021 } else if (ret) {
1022 dev_err(dev, "Reset failed\n");
1023 return ret;
1024 }
1025
1026 ret = reset_assert_bulk(&priv->resets);
1027 if (ret) {
1028 dev_err(dev, "Reset assert failed\n");
1029 return ret;
1030 }
1031
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001032 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_FIXED, 0);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001033 if (ret) {
1034 dev_err(dev, "SD_CONFIG_FIXED failed\n");
1035 return ret;
1036 }
1037
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001038 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_EMMC_SEL,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001039 dev_read_bool(dev, "non-removable"));
1040 if (ret) {
1041 dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
1042 return ret;
1043 }
1044
1045 ret = clk_get_by_index(dev, 0, &clk);
1046 if (ret < 0) {
1047 dev_err(dev, "failed to get clock\n");
1048 return ret;
1049 }
1050
1051 clock = clk_get_rate(&clk);
1052 if (IS_ERR_VALUE(clock)) {
1053 dev_err(dev, "failed to get rate\n");
1054 return clock;
1055 }
1056
1057 mhz = DIV64_U64_ROUND_UP(clock, 1000000);
1058
Ashok Reddy Soma088febe2022-03-25 13:11:10 +01001059 if (mhz > 100 && mhz <= 200)
1060 mhz = 200;
1061 else if (mhz > 50 && mhz <= 100)
1062 mhz = 100;
1063 else if (mhz > 25 && mhz <= 50)
1064 mhz = 50;
1065 else
1066 mhz = 25;
1067
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001068 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_BASECLK, mhz);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001069 if (ret) {
1070 dev_err(dev, "SD_CONFIG_BASECLK failed\n");
1071 return ret;
1072 }
1073
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001074 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_8BIT,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001075 (dev_read_u32_default(dev, "bus-width", 1) == 8));
1076 if (ret) {
1077 dev_err(dev, "SD_CONFIG_8BIT failed\n");
1078 return ret;
1079 }
1080
1081 ret = reset_deassert_bulk(&priv->resets);
1082 if (ret) {
1083 dev_err(dev, "Reset release failed\n");
1084 return ret;
1085 }
1086
1087 return 0;
1088}
1089#endif
1090
Michal Simek9ecd2682015-11-30 16:13:03 +01001091static int arasan_sdhci_probe(struct udevice *dev)
Michal Simek0dd222b2013-04-22 14:56:49 +02001092{
Simon Glassfa20e932020-12-03 16:55:20 -07001093 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Michal Simek9ecd2682015-11-30 16:13:03 +01001094 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301095 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
1096 struct sdhci_host *host;
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001097 struct clk clk;
1098 unsigned long clock;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001099 int ret;
Michal Simek0dd222b2013-04-22 14:56:49 +02001100
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301101 host = priv->host;
1102
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -07001103#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001104 if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
1105 ret = zynqmp_pm_is_function_supported(PM_IOCTL,
1106 IOCTL_SET_SD_CONFIG);
1107 if (!ret) {
1108 ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
1109 if (ret)
1110 return ret;
1111 }
1112 }
1113#endif
Michal Simekb1fa0d02023-05-17 10:22:48 +02001114 if (device_is_compatible(dev, "xlnx,versal-net-emmc"))
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07001115 priv->internal_phy_reg = true;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001116
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001117 ret = clk_get_by_index(dev, 0, &clk);
1118 if (ret < 0) {
1119 dev_err(dev, "failed to get clock\n");
1120 return ret;
1121 }
1122
1123 clock = clk_get_rate(&clk);
1124 if (IS_ERR_VALUE(clock)) {
1125 dev_err(dev, "failed to get rate\n");
1126 return clock;
1127 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301128
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001129 dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001130
1131 ret = clk_enable(&clk);
Michal Simek41710952021-02-09 15:28:15 +01001132 if (ret) {
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001133 dev_err(dev, "failed to enable clock\n");
1134 return ret;
1135 }
1136
Siva Durga Prasad Paladugu049e0032014-07-08 15:31:04 +05301137 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
Siva Durga Prasad Paladugu0d6891b2014-01-22 09:17:09 +01001138 SDHCI_QUIRK_BROKEN_R1B;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301139
1140#ifdef CONFIG_ZYNQ_HISPD_BROKEN
Hannes Schmelzer94a5bbc2018-03-07 08:00:57 +01001141 host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301142#endif
1143
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001144 if (priv->no_1p8)
1145 host->quirks |= SDHCI_QUIRK_NO_1_8_V;
1146
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001147 if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +02001148 device_is_compatible(dev, "xlnx,versal-net-emmc"))
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001149 host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400;
1150
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001151 plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
1152
1153 ret = mmc_of_parse(dev, &plat->cfg);
1154 if (ret)
1155 return ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301156
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001157 host->max_clk = clock;
Stefan Herbrechtsmeierbc47e0e2017-01-17 15:58:48 +01001158
Matwey V. Kornilov194b8602019-08-01 18:00:05 +03001159 host->mmc = &plat->mmc;
1160 host->mmc->dev = dev;
1161 host->mmc->priv = host;
1162
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001163 ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
Jaehoon Chung8a5ffbb2016-07-26 19:06:24 +09001164 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001165 if (ret)
1166 return ret;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001167 upriv->mmc = host->mmc;
Michal Simek9ecd2682015-11-30 16:13:03 +01001168
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001169 /*
1170 * WORKAROUND: Versal platforms have an issue with card detect state.
1171 * Due to this, host controller is switching off voltage to sd card
1172 * causing sd card timeout error. Workaround this by adding a wait for
1173 * 1000msec till the card detect state gets stable.
1174 */
Ashok Reddy Soma6556bff2022-02-23 15:13:32 +01001175 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001176 u32 timeout = 1000000;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001177
1178 while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001179 SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001180 udelay(1);
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001181 timeout--;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001182 }
1183 if (!timeout) {
1184 dev_err(dev, "Sdhci card detect state not stable\n");
1185 return -ETIMEDOUT;
1186 }
1187 }
1188
Simon Glass4cc87fb2016-07-05 17:10:15 -06001189 return sdhci_probe(dev);
Michal Simek0dd222b2013-04-22 14:56:49 +02001190}
Michal Simek9ecd2682015-11-30 16:13:03 +01001191
Simon Glassaad29ae2020-12-03 16:55:21 -07001192static int arasan_sdhci_of_to_plat(struct udevice *dev)
Michal Simek9ecd2682015-11-30 16:13:03 +01001193{
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301194 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001195 u32 pm_info[2];
Michal Simek9ecd2682015-11-30 16:13:03 +01001196
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301197 priv->host = calloc(1, sizeof(struct sdhci_host));
1198 if (!priv->host)
1199 return -1;
1200
1201 priv->host->name = dev->name;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301202
Michal Simek534a9342024-05-29 16:48:00 +02001203#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) || \
1204 defined(CONFIG_ARCH_VERSAL2)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301205 priv->host->ops = &arasan_ops;
Michal Simek33a6b772020-10-23 04:59:00 -06001206 arasan_dt_parse_clk_phases(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301207#endif
Michal Simek9ecd2682015-11-30 16:13:03 +01001208
Johan Jonker8d5d8e02023-03-13 01:32:04 +01001209 priv->host->ioaddr = dev_read_addr_ptr(dev);
1210 if (!priv->host->ioaddr)
1211 return -EINVAL;
Michal Simek921a8de2018-05-16 10:57:07 +02001212
Michal Simeke40ae572020-07-22 17:46:31 +02001213 priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001214 priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
Stefan Herbrechtsmeier5567b422017-01-17 16:27:33 +01001215
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001216 priv->node_id = 0;
1217 if (!dev_read_u32_array(dev, "power-domains", pm_info, ARRAY_SIZE(pm_info)))
1218 priv->node_id = pm_info[1];
1219
Michal Simek9ecd2682015-11-30 16:13:03 +01001220 return 0;
1221}
1222
Simon Glass4cc87fb2016-07-05 17:10:15 -06001223static int arasan_sdhci_bind(struct udevice *dev)
1224{
Simon Glassfa20e932020-12-03 16:55:20 -07001225 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001226
Masahiro Yamadacdb67f32016-09-06 22:17:32 +09001227 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001228}
1229
Michal Simek9ecd2682015-11-30 16:13:03 +01001230static const struct udevice_id arasan_sdhci_ids[] = {
1231 { .compatible = "arasan,sdhci-8.9a" },
Michal Simekb1fa0d02023-05-17 10:22:48 +02001232 { .compatible = "xlnx,versal-net-emmc" },
Michal Simek9ecd2682015-11-30 16:13:03 +01001233 { }
1234};
1235
1236U_BOOT_DRIVER(arasan_sdhci_drv) = {
1237 .name = "arasan_sdhci",
1238 .id = UCLASS_MMC,
1239 .of_match = arasan_sdhci_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001240 .of_to_plat = arasan_sdhci_of_to_plat,
Simon Glass4cc87fb2016-07-05 17:10:15 -06001241 .ops = &sdhci_ops,
1242 .bind = arasan_sdhci_bind,
Michal Simek9ecd2682015-11-30 16:13:03 +01001243 .probe = arasan_sdhci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001244 .priv_auto = sizeof(struct arasan_sdhci_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001245 .plat_auto = sizeof(struct arasan_sdhci_plat),
Michal Simek9ecd2682015-11-30 16:13:03 +01001246};