blob: 8a83adef43429ae6a91cd0c5bb0a3a7934a6b191 [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
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700125#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET)
Michal Simek33a6b772020-10-23 04:59:00 -0600126/* Default settings for ZynqMP Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600127static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0,
128 0, 183, 54, 0, 0};
129static const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72,
130 135, 48, 72, 135, 0};
Michal Simek33a6b772020-10-23 04:59:00 -0600131
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600132/* Default settings for Versal Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600133static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132,
134 0, 0, 162, 90, 0, 0};
135static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72,
136 90, 36, 60, 90, 0};
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600137
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700138/* Default settings for versal-net eMMC Clock Phases */
139static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39,
140 0, 0};
141static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0,
142 113, 79, 45};
143
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530144static const u8 mode2timing[] = {
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600145 [MMC_LEGACY] = MMC_TIMING_LEGACY,
146 [MMC_HS] = MMC_TIMING_MMC_HS,
147 [SD_HS] = MMC_TIMING_SD_HS,
Ashok Reddy Soma5ff7acf2022-06-27 14:22:45 +0530148 [MMC_HS_52] = MMC_TIMING_MMC_HS,
149 [MMC_DDR_52] = MMC_TIMING_MMC_DDR52,
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600150 [UHS_SDR12] = MMC_TIMING_UHS_SDR12,
151 [UHS_SDR25] = MMC_TIMING_UHS_SDR25,
152 [UHS_SDR50] = MMC_TIMING_UHS_SDR50,
153 [UHS_DDR50] = MMC_TIMING_UHS_DDR50,
154 [UHS_SDR104] = MMC_TIMING_UHS_SDR104,
155 [MMC_HS_200] = MMC_TIMING_MMC_HS200,
Ashok Reddy Soma407a5612023-01-10 04:31:24 -0700156 [MMC_HS_400] = MMC_TIMING_MMC_HS400,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530157};
158
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700159#if defined(CONFIG_ARCH_VERSAL_NET)
160/**
161 * arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock
162 *
163 * @host: Pointer to the sdhci_host structure
164 * @enable: Enable or disable Delay chain based Tx and Rx clock
165 * Return: None
166 *
167 * Enable or disable eMMC delay chain based Input and Output clock in
168 * PHY_CTRL_REG2
169 */
170static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable)
171{
172 u32 reg;
173
174 reg = sdhci_readw(host, PHY_CTRL_REG2);
175 if (enable)
176 reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK;
177 else
178 reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK);
179
180 sdhci_writew(host, reg, PHY_CTRL_REG2);
181}
182
183/**
184 * arasan_phy_set_dll - Set eMMC DLL clock
185 *
186 * @host: Pointer to the sdhci_host structure
187 * @enable: Enable or disable DLL clock
188 * Return: 0 if success or timeout error
189 *
190 * Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is
191 * set, wait till DLL is locked
192 */
193static int arasan_phy_set_dll(struct sdhci_host *host, bool enable)
194{
195 u32 reg;
196
197 reg = sdhci_readw(host, PHY_CTRL_REG2);
198 if (enable)
199 reg |= PHY_CTRL_EN_DLL_MASK;
200 else
201 reg &= ~PHY_CTRL_EN_DLL_MASK;
202
203 sdhci_writew(host, reg, PHY_CTRL_REG2);
204
205 /* If DLL is disabled return success */
206 if (!enable)
207 return 0;
208
209 /* If DLL is enabled wait till DLL loop is locked, which is
210 * indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2
211 */
212 return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg,
213 (reg & PHY_CTRL_DLL_RDY_MASK),
214 1000 * PHY_DLL_TIMEOUT_MS);
215}
216
217/**
218 * arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC
219 *
220 * @host: Pointer to the sdhci_host structure
221 * @clock: clock value
222 * Return: None
223 *
224 * Set frequency range bits based on the selected clock for eMMC
225 */
226static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock)
227{
228 u32 reg, freq_sel, freq;
229
230 freq = DIV_ROUND_CLOSEST(clock, 1000000);
231 if (freq <= 200 && freq > 170)
232 freq_sel = FREQSEL_200M_170M;
233 else if (freq <= 170 && freq > 140)
234 freq_sel = FREQSEL_170M_140M;
235 else if (freq <= 140 && freq > 110)
236 freq_sel = FREQSEL_140M_110M;
237 else if (freq <= 110 && freq > 80)
238 freq_sel = FREQSEL_110M_80M;
239 else
240 freq_sel = FREQSEL_80M_50M;
241
242 reg = sdhci_readw(host, PHY_CTRL_REG2);
243 reg &= ~PHY_CTRL_FREQ_SEL_MASK;
244 reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT);
245 sdhci_writew(host, reg, PHY_CTRL_REG2);
246}
247
248static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable)
249{
250 struct mmc *mmc = (struct mmc *)host->mmc;
251 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
252
253 if (enable) {
254 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable)
255 arasan_phy_set_dll(host, 1);
256 return 0;
257 }
258
259 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) {
260 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
261 arasan_phy_set_dll(host, 0);
262 arasan_phy_set_delaychain(host, 0);
263 arasan_phy_dll_set_freq(host, clock);
264 return 0;
265 }
266
267 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
268 arasan_phy_set_delaychain(host, 1);
269
270 return 0;
271}
272#endif
273
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600274static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600275{
276 int ret;
277
278 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
279 if (node_id == NODE_SD_0) {
280 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
281 SD0_ITAPCHGWIN);
282 if (ret)
283 return ret;
284
285 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
286 SD0_ITAPDLYENA);
287 if (ret)
288 return ret;
289
290 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
291 itap_delay);
292 if (ret)
293 return ret;
294
295 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
296 if (ret)
297 return ret;
298 }
299 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
300 SD1_ITAPCHGWIN);
301 if (ret)
302 return ret;
303
304 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
305 SD1_ITAPDLYENA);
306 if (ret)
307 return ret;
308
309 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
310 (itap_delay << 16));
311 if (ret)
312 return ret;
313
314 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
315 if (ret)
316 return ret;
317 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600318 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600319 IOCTL_SET_SD_TAPDELAY,
320 PM_TAPDELAY_INPUT, itap_delay, NULL);
321 }
322
323 return 0;
324}
325
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600326static inline int arasan_zynqmp_set_out_tapdelay(u32 node_id, u32 otap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600327{
328 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
329 if (node_id == NODE_SD_0)
330 return zynqmp_mmio_write(SD_OTAP_DLY,
331 SD0_OTAPDLYSEL_MASK,
332 otap_delay);
333
334 return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
335 (otap_delay << 16));
336 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600337 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600338 IOCTL_SET_SD_TAPDELAY,
339 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
340 }
341}
342
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600343static inline int zynqmp_dll_reset(u32 node_id, u32 type)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600344{
345 if (IS_ENABLED(CONFIG_SPL_BUILD) || current_el() == 3) {
346 if (node_id == NODE_SD_0)
347 return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
348 type == PM_DLL_RESET_ASSERT ?
349 SD0_DLL_RST : 0);
350
351 return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
352 type == PM_DLL_RESET_ASSERT ?
353 SD1_DLL_RST : 0);
354 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600355 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600356 IOCTL_SD_DLL_RESET, type, 0, NULL);
357 }
358}
359
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600360static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 node_id)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530361{
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600362 struct mmc *mmc = (struct mmc *)host->mmc;
363 struct udevice *dev = mmc->dev;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530364 unsigned long timeout;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600365 int ret;
366 u16 clk;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530367
368 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
369 clk &= ~(SDHCI_CLOCK_CARD_EN);
370 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
371
372 /* Issue DLL Reset */
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600373 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
374 if (ret) {
375 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
376 return ret;
377 }
378
379 /* Allow atleast 1ms delay for proper DLL reset */
380 mdelay(1);
381 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
382 if (ret) {
383 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
384 return ret;
385 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530386
387 /* Wait max 20 ms */
388 timeout = 100;
389 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
390 & SDHCI_CLOCK_INT_STABLE)) {
391 if (timeout == 0) {
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600392 dev_err(dev, ": Internal clock never stabilised.\n");
393 return -EBUSY;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530394 }
395 timeout--;
396 udelay(1000);
397 }
398
399 clk |= SDHCI_CLOCK_CARD_EN;
400 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600401
402 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530403}
404
405static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
406{
407 struct mmc_cmd cmd;
408 struct mmc_data data;
409 u32 ctrl;
410 struct sdhci_host *host;
411 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Algapally Santosh Sagar99a98ca2023-01-19 22:36:17 -0700412 int tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530413
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +0100414 dev_dbg(mmc->dev, "%s\n", __func__);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530415
416 host = priv->host;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530417
Faiz Abbas2eddc002019-06-11 00:43:40 +0530418 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530419 ctrl |= SDHCI_CTRL_EXEC_TUNING;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530420 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530421
422 mdelay(1);
423
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200424 if (device_is_compatible(mmc->dev, "xlnx,zynqmp-8.9a"))
425 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530426
427 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
428 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
429
430 do {
431 cmd.cmdidx = opcode;
432 cmd.resp_type = MMC_RSP_R1;
433 cmd.cmdarg = 0;
434
435 data.blocksize = 64;
436 data.blocks = 1;
437 data.flags = MMC_DATA_READ;
438
439 if (tuning_loop_counter-- == 0)
440 break;
441
442 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
443 mmc->bus_width == 8)
444 data.blocksize = 128;
445
446 sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
447 data.blocksize),
448 SDHCI_BLOCK_SIZE);
449 sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
450 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
451
452 mmc_send_cmd(mmc, &cmd, NULL);
Faiz Abbas2eddc002019-06-11 00:43:40 +0530453 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530454
455 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
456 udelay(1);
457
458 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
459
460 if (tuning_loop_counter < 0) {
461 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530462 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530463 }
464
465 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
466 printf("%s:Tuning failed\n", __func__);
467 return -1;
468 }
469
470 udelay(1);
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200471
472 if (device_is_compatible(mmc->dev, "xlnx,zynqmp-8.9a"))
473 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530474
475 /* Enable only interrupts served by the SD controller */
476 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
477 SDHCI_INT_ENABLE);
478 /* Mask all sdhci interrupt sources */
479 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
480
481 return 0;
482}
483
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600484/**
485 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
486 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600487 * @host: Pointer to the sdhci_host structure.
488 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600489 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600490 *
491 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600492 */
493static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
494 int degrees)
495{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600496 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600497 struct udevice *dev = mmc->dev;
498 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600499 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600500 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600501 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600502
503 /*
504 * This is applicable for SDHCI_SPEC_300 and above
505 * ZynqMP does not set phase for <=25MHz clock.
506 * If degrees is zero, no need to do anything.
507 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600508 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600509 return 0;
510
511 switch (timing) {
512 case MMC_TIMING_MMC_HS:
513 case MMC_TIMING_SD_HS:
514 case MMC_TIMING_UHS_SDR25:
515 case MMC_TIMING_UHS_DDR50:
516 case MMC_TIMING_MMC_DDR52:
517 /* For 50MHz clock, 30 Taps are available */
518 tap_max = 30;
519 break;
520 case MMC_TIMING_UHS_SDR50:
521 /* For 100MHz clock, 15 Taps are available */
522 tap_max = 15;
523 break;
524 case MMC_TIMING_UHS_SDR104:
525 case MMC_TIMING_MMC_HS200:
526 /* For 200MHz clock, 8 Taps are available */
527 tap_max = 8;
528 default:
529 break;
530 }
531
532 tap_delay = (degrees * tap_max) / 360;
533
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600534 /* Limit output tap_delay value to 6 bits */
535 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
536
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600537 /* Set the Clock Phase */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600538 ret = arasan_zynqmp_set_out_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600539 if (ret) {
540 dev_err(dev, "Error setting output Tap Delay\n");
541 return ret;
542 }
543
544 /* Release DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600545 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_RELEASE);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600546 if (ret) {
547 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
548 return ret;
549 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600550
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600551 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600552}
553
554/**
555 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
556 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600557 * @host: Pointer to the sdhci_host structure.
558 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600559 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600560 *
561 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600562 */
563static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
564 int degrees)
565{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600566 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600567 struct udevice *dev = mmc->dev;
568 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600569 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600570 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600571 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600572
573 /*
574 * This is applicable for SDHCI_SPEC_300 and above
575 * ZynqMP does not set phase for <=25MHz clock.
576 * If degrees is zero, no need to do anything.
577 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600578 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600579 return 0;
580
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600581 /* Assert DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600582 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_ASSERT);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600583 if (ret) {
584 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
585 return ret;
586 }
587
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600588 switch (timing) {
589 case MMC_TIMING_MMC_HS:
590 case MMC_TIMING_SD_HS:
591 case MMC_TIMING_UHS_SDR25:
592 case MMC_TIMING_UHS_DDR50:
593 case MMC_TIMING_MMC_DDR52:
594 /* For 50MHz clock, 120 Taps are available */
595 tap_max = 120;
596 break;
597 case MMC_TIMING_UHS_SDR50:
598 /* For 100MHz clock, 60 Taps are available */
599 tap_max = 60;
600 break;
601 case MMC_TIMING_UHS_SDR104:
602 case MMC_TIMING_MMC_HS200:
603 /* For 200MHz clock, 30 Taps are available */
604 tap_max = 30;
605 default:
606 break;
607 }
608
609 tap_delay = (degrees * tap_max) / 360;
610
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600611 /* Limit input tap_delay value to 8 bits */
612 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
613
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600614 ret = arasan_zynqmp_set_in_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600615 if (ret) {
616 dev_err(dev, "Error setting Input Tap Delay\n");
617 return ret;
618 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600619
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600620 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600621}
622
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600623/**
624 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
625 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600626 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600627 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600628 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600629 *
630 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600631 */
632static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
633 int degrees)
634{
635 struct mmc *mmc = (struct mmc *)host->mmc;
636 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600637 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600638 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600639
640 /*
641 * This is applicable for SDHCI_SPEC_300 and above
642 * Versal does not set phase for <=25MHz clock.
643 * If degrees is zero, no need to do anything.
644 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600645 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600646 return 0;
647
648 switch (timing) {
649 case MMC_TIMING_MMC_HS:
650 case MMC_TIMING_SD_HS:
651 case MMC_TIMING_UHS_SDR25:
652 case MMC_TIMING_UHS_DDR50:
653 case MMC_TIMING_MMC_DDR52:
654 /* For 50MHz clock, 30 Taps are available */
655 tap_max = 30;
656 break;
657 case MMC_TIMING_UHS_SDR50:
658 /* For 100MHz clock, 15 Taps are available */
659 tap_max = 15;
660 break;
661 case MMC_TIMING_UHS_SDR104:
662 case MMC_TIMING_MMC_HS200:
663 /* For 200MHz clock, 8 Taps are available */
664 tap_max = 8;
665 default:
666 break;
667 }
668
669 tap_delay = (degrees * tap_max) / 360;
670
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600671 /* Limit output tap_delay value to 6 bits */
672 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600673
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600674 /* Set the Clock Phase */
675 regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
676 regval |= SDHCI_OTAPDLY_ENABLE;
677 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
678 regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
679 regval |= tap_delay;
680 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600681
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600682 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600683}
684
685/**
686 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
687 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600688 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600689 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600690 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600691 *
692 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600693 */
694static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
695 int degrees)
696{
697 struct mmc *mmc = (struct mmc *)host->mmc;
698 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600699 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600700 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600701
702 /*
703 * This is applicable for SDHCI_SPEC_300 and above
704 * Versal does not set phase for <=25MHz clock.
705 * If degrees is zero, no need to do anything.
706 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600707 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600708 return 0;
709
710 switch (timing) {
711 case MMC_TIMING_MMC_HS:
712 case MMC_TIMING_SD_HS:
713 case MMC_TIMING_UHS_SDR25:
714 case MMC_TIMING_UHS_DDR50:
715 case MMC_TIMING_MMC_DDR52:
716 /* For 50MHz clock, 120 Taps are available */
717 tap_max = 120;
718 break;
719 case MMC_TIMING_UHS_SDR50:
720 /* For 100MHz clock, 60 Taps are available */
721 tap_max = 60;
722 break;
723 case MMC_TIMING_UHS_SDR104:
724 case MMC_TIMING_MMC_HS200:
725 /* For 200MHz clock, 30 Taps are available */
726 tap_max = 30;
727 default:
728 break;
729 }
730
731 tap_delay = (degrees * tap_max) / 360;
732
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600733 /* Limit input tap_delay value to 8 bits */
734 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600735
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600736 /* Set the Clock Phase */
737 regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
738 regval |= SDHCI_ITAPDLY_CHGWIN;
739 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
740 regval |= SDHCI_ITAPDLY_ENABLE;
741 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
742 regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
743 regval |= tap_delay;
744 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
745 regval &= ~SDHCI_ITAPDLY_CHGWIN;
746 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600747
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600748 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600749}
750
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700751/**
752 * sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays
753 *
754 * @host: Pointer to the sdhci_host structure.
755 * @degrees: The clock phase shift between 0 - 359.
756 * Return: 0
757 *
758 * Set eMMC Output Clock Tap Delays for Output path
759 */
760static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees)
761{
762 struct mmc *mmc = (struct mmc *)host->mmc;
763 int timing = mode2timing[mmc->selected_mode];
764 u8 tap_delay, tap_max = 0;
765 u32 regval;
766
767 switch (timing) {
768 case MMC_TIMING_MMC_HS:
769 case MMC_TIMING_MMC_DDR52:
770 tap_max = 16;
771 break;
772 case MMC_TIMING_MMC_HS200:
773 case MMC_TIMING_MMC_HS400:
774 /* For 200MHz clock, 32 Taps are available */
775 tap_max = 32;
776 break;
777 default:
778 break;
779 }
780
781 tap_delay = (degrees * tap_max) / 360;
782 /* Set the Clock Phase */
783 if (tap_delay) {
784 regval = sdhci_readl(host, PHY_CTRL_REG1);
785 regval |= PHY_CTRL_OTAPDLY_ENA_MASK;
786 sdhci_writel(host, regval, PHY_CTRL_REG1);
787 regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK;
788 regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT;
789 sdhci_writel(host, regval, PHY_CTRL_REG1);
790 }
791
792 return 0;
793}
794
795/**
796 * sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays
797 *
798 * @host: Pointer to the sdhci_host structure.
799 * @degrees: The clock phase shift between 0 - 359.
800 * Return: 0
801 *
802 * Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected,
803 * set strobe90 and strobe180 in PHY_CTRL_REG1.
804 */
805static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees)
806{
807 struct mmc *mmc = (struct mmc *)host->mmc;
808 int timing = mode2timing[mmc->selected_mode];
809 u8 tap_delay, tap_max = 0;
810 u32 regval;
811
812 switch (timing) {
813 case MMC_TIMING_MMC_HS:
814 case MMC_TIMING_MMC_DDR52:
815 tap_max = 32;
816 break;
817 case MMC_TIMING_MMC_HS400:
818 /* Strobe select tap point for strb90 and strb180 */
819 regval = sdhci_readl(host, PHY_CTRL_REG1);
820 regval &= ~PHY_CTRL_STRB_SEL_MASK;
821 regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT;
822 sdhci_writel(host, regval, PHY_CTRL_REG1);
823 break;
824 default:
825 break;
826 }
827
828 tap_delay = (degrees * tap_max) / 360;
829 /* Set the Clock Phase */
830 if (tap_delay) {
831 regval = sdhci_readl(host, PHY_CTRL_REG1);
832 regval |= PHY_CTRL_ITAP_CHG_WIN_MASK;
833 sdhci_writel(host, regval, PHY_CTRL_REG1);
834 regval |= PHY_CTRL_ITAPDLY_ENA_MASK;
835 sdhci_writel(host, regval, PHY_CTRL_REG1);
836 regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK;
837 regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT;
838 sdhci_writel(host, regval, PHY_CTRL_REG1);
839 regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK;
840 sdhci_writel(host, regval, PHY_CTRL_REG1);
841 }
842
843 return 0;
844}
845
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600846static int arasan_sdhci_set_tapdelay(struct sdhci_host *host)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530847{
848 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600849 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530850 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600851 struct udevice *dev = mmc->dev;
852 u8 timing = mode2timing[mmc->selected_mode];
853 u32 iclk_phase = clk_data->clk_phase_in[timing];
854 u32 oclk_phase = clk_data->clk_phase_out[timing];
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600855 int ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530856
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600857 dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530858
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600859 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
860 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600861 ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
862 if (ret)
863 return ret;
864
865 ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
866 if (ret)
867 return ret;
Simek, Michald78ea252024-04-17 20:06:13 -1200868 } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
869 IS_ENABLED(CONFIG_ARCH_VERSAL_NET)) &&
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600870 device_is_compatible(dev, "xlnx,versal-8.9a")) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600871 ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
872 if (ret)
873 return ret;
874
875 ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
876 if (ret)
877 return ret;
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700878 } else if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +0200879 device_is_compatible(dev, "xlnx,versal-net-emmc")) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700880 if (mmc->clock >= MIN_PHY_CLK_HZ)
881 if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN)
882 iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL;
883
884 ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase);
885 if (ret)
886 return ret;
887
888 ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase);
889 if (ret)
890 return ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600891 }
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600892
893 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530894}
895
Michal Simek33a6b772020-10-23 04:59:00 -0600896static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
897 const char *prop)
898{
899 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
900 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
901 u32 clk_phase[2] = {0};
902
903 /*
904 * Read Tap Delay values from DT, if the DT does not contain the
905 * Tap Values then use the pre-defined values
906 */
907 if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
908 dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
909 prop, clk_data->clk_phase_in[timing],
910 clk_data->clk_phase_out[timing]);
911 return;
912 }
913
914 /* The values read are Input and Output Clock Delays in order */
915 clk_data->clk_phase_in[timing] = clk_phase[0];
916 clk_data->clk_phase_out[timing] = clk_phase[1];
917}
918
919/**
920 * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
921 *
Michal Simek33a6b772020-10-23 04:59:00 -0600922 * @dev: Pointer to our struct udevice.
Michal Simek2a43ab82021-07-09 05:53:43 -0600923 *
924 * Called at initialization to parse the values of Tap Delays.
Michal Simek33a6b772020-10-23 04:59:00 -0600925 */
926static void arasan_dt_parse_clk_phases(struct udevice *dev)
927{
928 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
929 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
930 int i;
931
932 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
933 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
934 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
935 clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
936 clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
937 }
938
939 if (priv->bank == MMC_BANK2) {
940 clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
941 clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
942 }
943 }
944
Simek, Michald78ea252024-04-17 20:06:13 -1200945 if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
946 IS_ENABLED(CONFIG_ARCH_VERSAL_NET)) &&
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600947 device_is_compatible(dev, "xlnx,versal-8.9a")) {
948 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
949 clk_data->clk_phase_in[i] = versal_iclk_phases[i];
950 clk_data->clk_phase_out[i] = versal_oclk_phases[i];
951 }
952 }
953
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700954 if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +0200955 device_is_compatible(dev, "xlnx,versal-net-emmc")) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700956 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
957 clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i];
958 clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i];
959 }
960 }
961
Michal Simek33a6b772020-10-23 04:59:00 -0600962 arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
963 "clk-phase-legacy");
964 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
965 "clk-phase-mmc-hs");
966 arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
967 "clk-phase-sd-hs");
968 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
969 "clk-phase-uhs-sdr12");
970 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
971 "clk-phase-uhs-sdr25");
972 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
973 "clk-phase-uhs-sdr50");
974 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
975 "clk-phase-uhs-sdr104");
976 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
977 "clk-phase-uhs-ddr50");
978 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
979 "clk-phase-mmc-ddr52");
980 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
981 "clk-phase-mmc-hs200");
982 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
983 "clk-phase-mmc-hs400");
984}
985
Michal Simek635cf4a2021-07-09 05:53:44 -0600986static const struct sdhci_ops arasan_ops = {
987 .platform_execute_tuning = &arasan_sdhci_execute_tuning,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530988 .set_delay = &arasan_sdhci_set_tapdelay,
Ashok Reddy Soma8ee49f02021-08-02 23:20:46 -0600989 .set_control_reg = &sdhci_set_control_reg,
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700990#if defined(CONFIG_ARCH_VERSAL_NET)
991 .config_dll = &arasan_sdhci_config_dll,
992#endif
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530993};
994#endif
995
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -0700996#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +0100997static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
998 struct udevice *dev)
999{
1000 int ret;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001001 struct clk clk;
1002 unsigned long clock, mhz;
1003
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001004 ret = xilinx_pm_request(PM_REQUEST_NODE, priv->node_id,
1005 ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS,
1006 ZYNQMP_PM_REQUEST_ACK_NO, NULL);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001007 if (ret) {
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001008 dev_err(dev, "Request node failed for %d\n", priv->node_id);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001009 return ret;
1010 }
1011
1012 ret = reset_get_bulk(dev, &priv->resets);
1013 if (ret == -ENOTSUPP || ret == -ENOENT) {
1014 dev_err(dev, "Reset not found\n");
1015 return 0;
1016 } else if (ret) {
1017 dev_err(dev, "Reset failed\n");
1018 return ret;
1019 }
1020
1021 ret = reset_assert_bulk(&priv->resets);
1022 if (ret) {
1023 dev_err(dev, "Reset assert failed\n");
1024 return ret;
1025 }
1026
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001027 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_FIXED, 0);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001028 if (ret) {
1029 dev_err(dev, "SD_CONFIG_FIXED failed\n");
1030 return ret;
1031 }
1032
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001033 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_EMMC_SEL,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001034 dev_read_bool(dev, "non-removable"));
1035 if (ret) {
1036 dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
1037 return ret;
1038 }
1039
1040 ret = clk_get_by_index(dev, 0, &clk);
1041 if (ret < 0) {
1042 dev_err(dev, "failed to get clock\n");
1043 return ret;
1044 }
1045
1046 clock = clk_get_rate(&clk);
1047 if (IS_ERR_VALUE(clock)) {
1048 dev_err(dev, "failed to get rate\n");
1049 return clock;
1050 }
1051
1052 mhz = DIV64_U64_ROUND_UP(clock, 1000000);
1053
Ashok Reddy Soma088febe2022-03-25 13:11:10 +01001054 if (mhz > 100 && mhz <= 200)
1055 mhz = 200;
1056 else if (mhz > 50 && mhz <= 100)
1057 mhz = 100;
1058 else if (mhz > 25 && mhz <= 50)
1059 mhz = 50;
1060 else
1061 mhz = 25;
1062
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001063 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_BASECLK, mhz);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001064 if (ret) {
1065 dev_err(dev, "SD_CONFIG_BASECLK failed\n");
1066 return ret;
1067 }
1068
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001069 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_8BIT,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001070 (dev_read_u32_default(dev, "bus-width", 1) == 8));
1071 if (ret) {
1072 dev_err(dev, "SD_CONFIG_8BIT failed\n");
1073 return ret;
1074 }
1075
1076 ret = reset_deassert_bulk(&priv->resets);
1077 if (ret) {
1078 dev_err(dev, "Reset release failed\n");
1079 return ret;
1080 }
1081
1082 return 0;
1083}
1084#endif
1085
Michal Simek9ecd2682015-11-30 16:13:03 +01001086static int arasan_sdhci_probe(struct udevice *dev)
Michal Simek0dd222b2013-04-22 14:56:49 +02001087{
Simon Glassfa20e932020-12-03 16:55:20 -07001088 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Michal Simek9ecd2682015-11-30 16:13:03 +01001089 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301090 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
1091 struct sdhci_host *host;
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001092 struct clk clk;
1093 unsigned long clock;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001094 int ret;
Michal Simek0dd222b2013-04-22 14:56:49 +02001095
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301096 host = priv->host;
1097
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -07001098#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001099 if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
1100 ret = zynqmp_pm_is_function_supported(PM_IOCTL,
1101 IOCTL_SET_SD_CONFIG);
1102 if (!ret) {
1103 ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
1104 if (ret)
1105 return ret;
1106 }
1107 }
1108#endif
Michal Simekb1fa0d02023-05-17 10:22:48 +02001109 if (device_is_compatible(dev, "xlnx,versal-net-emmc"))
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07001110 priv->internal_phy_reg = true;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001111
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001112 ret = clk_get_by_index(dev, 0, &clk);
1113 if (ret < 0) {
1114 dev_err(dev, "failed to get clock\n");
1115 return ret;
1116 }
1117
1118 clock = clk_get_rate(&clk);
1119 if (IS_ERR_VALUE(clock)) {
1120 dev_err(dev, "failed to get rate\n");
1121 return clock;
1122 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301123
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001124 dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001125
1126 ret = clk_enable(&clk);
Michal Simek41710952021-02-09 15:28:15 +01001127 if (ret) {
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001128 dev_err(dev, "failed to enable clock\n");
1129 return ret;
1130 }
1131
Siva Durga Prasad Paladugu049e0032014-07-08 15:31:04 +05301132 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
Siva Durga Prasad Paladugu0d6891b2014-01-22 09:17:09 +01001133 SDHCI_QUIRK_BROKEN_R1B;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301134
1135#ifdef CONFIG_ZYNQ_HISPD_BROKEN
Hannes Schmelzer94a5bbc2018-03-07 08:00:57 +01001136 host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301137#endif
1138
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001139 if (priv->no_1p8)
1140 host->quirks |= SDHCI_QUIRK_NO_1_8_V;
1141
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001142 if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) &&
Michal Simekb1fa0d02023-05-17 10:22:48 +02001143 device_is_compatible(dev, "xlnx,versal-net-emmc"))
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001144 host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400;
1145
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001146 plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
1147
1148 ret = mmc_of_parse(dev, &plat->cfg);
1149 if (ret)
1150 return ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301151
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001152 host->max_clk = clock;
Stefan Herbrechtsmeierbc47e0e2017-01-17 15:58:48 +01001153
Matwey V. Kornilov194b8602019-08-01 18:00:05 +03001154 host->mmc = &plat->mmc;
1155 host->mmc->dev = dev;
1156 host->mmc->priv = host;
1157
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001158 ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
Jaehoon Chung8a5ffbb2016-07-26 19:06:24 +09001159 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001160 if (ret)
1161 return ret;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001162 upriv->mmc = host->mmc;
Michal Simek9ecd2682015-11-30 16:13:03 +01001163
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001164 /*
1165 * WORKAROUND: Versal platforms have an issue with card detect state.
1166 * Due to this, host controller is switching off voltage to sd card
1167 * causing sd card timeout error. Workaround this by adding a wait for
1168 * 1000msec till the card detect state gets stable.
1169 */
Ashok Reddy Soma6556bff2022-02-23 15:13:32 +01001170 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001171 u32 timeout = 1000000;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001172
1173 while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001174 SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001175 udelay(1);
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001176 timeout--;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001177 }
1178 if (!timeout) {
1179 dev_err(dev, "Sdhci card detect state not stable\n");
1180 return -ETIMEDOUT;
1181 }
1182 }
1183
Simon Glass4cc87fb2016-07-05 17:10:15 -06001184 return sdhci_probe(dev);
Michal Simek0dd222b2013-04-22 14:56:49 +02001185}
Michal Simek9ecd2682015-11-30 16:13:03 +01001186
Simon Glassaad29ae2020-12-03 16:55:21 -07001187static int arasan_sdhci_of_to_plat(struct udevice *dev)
Michal Simek9ecd2682015-11-30 16:13:03 +01001188{
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301189 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001190 u32 pm_info[2];
Michal Simek9ecd2682015-11-30 16:13:03 +01001191
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301192 priv->host = calloc(1, sizeof(struct sdhci_host));
1193 if (!priv->host)
1194 return -1;
1195
1196 priv->host->name = dev->name;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301197
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07001198#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301199 priv->host->ops = &arasan_ops;
Michal Simek33a6b772020-10-23 04:59:00 -06001200 arasan_dt_parse_clk_phases(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301201#endif
Michal Simek9ecd2682015-11-30 16:13:03 +01001202
Johan Jonker8d5d8e02023-03-13 01:32:04 +01001203 priv->host->ioaddr = dev_read_addr_ptr(dev);
1204 if (!priv->host->ioaddr)
1205 return -EINVAL;
Michal Simek921a8de2018-05-16 10:57:07 +02001206
Michal Simeke40ae572020-07-22 17:46:31 +02001207 priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001208 priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
Stefan Herbrechtsmeier5567b422017-01-17 16:27:33 +01001209
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001210 priv->node_id = 0;
1211 if (!dev_read_u32_array(dev, "power-domains", pm_info, ARRAY_SIZE(pm_info)))
1212 priv->node_id = pm_info[1];
1213
Michal Simek9ecd2682015-11-30 16:13:03 +01001214 return 0;
1215}
1216
Simon Glass4cc87fb2016-07-05 17:10:15 -06001217static int arasan_sdhci_bind(struct udevice *dev)
1218{
Simon Glassfa20e932020-12-03 16:55:20 -07001219 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001220
Masahiro Yamadacdb67f32016-09-06 22:17:32 +09001221 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001222}
1223
Michal Simek9ecd2682015-11-30 16:13:03 +01001224static const struct udevice_id arasan_sdhci_ids[] = {
1225 { .compatible = "arasan,sdhci-8.9a" },
Michal Simekb1fa0d02023-05-17 10:22:48 +02001226 { .compatible = "xlnx,versal-net-emmc" },
Michal Simek9ecd2682015-11-30 16:13:03 +01001227 { }
1228};
1229
1230U_BOOT_DRIVER(arasan_sdhci_drv) = {
1231 .name = "arasan_sdhci",
1232 .id = UCLASS_MMC,
1233 .of_match = arasan_sdhci_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001234 .of_to_plat = arasan_sdhci_of_to_plat,
Simon Glass4cc87fb2016-07-05 17:10:15 -06001235 .ops = &sdhci_ops,
1236 .bind = arasan_sdhci_bind,
Michal Simek9ecd2682015-11-30 16:13:03 +01001237 .probe = arasan_sdhci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001238 .priv_auto = sizeof(struct arasan_sdhci_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001239 .plat_auto = sizeof(struct arasan_sdhci_plat),
Michal Simek9ecd2682015-11-30 16:13:03 +01001240};