blob: 0e2bdab4e7e1cbf2f453c73b656c4b7ce5c82a60 [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
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530108enum arasan_sdhci_compatible {
109 SDHCI_COMPATIBLE_SDHCI_89A,
110 SDHCI_COMPATIBLE_VERSAL_NET_EMMC,
111};
112
113static bool arasan_sdhci_is_compatible(struct udevice *dev,
114 enum arasan_sdhci_compatible family)
115{
116 enum arasan_sdhci_compatible compat = dev_get_driver_data(dev);
117
118 return compat == family;
119}
120
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600121/* For Versal platforms zynqmp_mmio_write() won't be available */
122__weak int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value)
123{
124 return 0;
125}
126
T Karthik Reddyd0618272021-10-01 16:38:38 +0530127__weak int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 arg2,
128 u32 arg3, u32 *ret_payload)
129{
130 return 0;
131}
132
T Karthik Reddy0b35fa22022-04-27 10:27:12 +0200133__weak int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
134{
135 return 1;
136}
137
Michal Simek534a9342024-05-29 16:48:00 +0200138#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || \
139 defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Michal Simek33a6b772020-10-23 04:59:00 -0600140/* Default settings for ZynqMP Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600141static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0,
142 0, 183, 54, 0, 0};
143static const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72,
144 135, 48, 72, 135, 0};
Michal Simek33a6b772020-10-23 04:59:00 -0600145
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600146/* Default settings for Versal Clock Phases */
Michal Simek635cf4a2021-07-09 05:53:44 -0600147static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132,
148 0, 0, 162, 90, 0, 0};
149static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72,
150 90, 36, 60, 90, 0};
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600151
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700152/* Default settings for versal-net eMMC Clock Phases */
153static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39,
154 0, 0};
155static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0,
156 113, 79, 45};
157
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530158static const u8 mode2timing[] = {
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600159 [MMC_LEGACY] = MMC_TIMING_LEGACY,
160 [MMC_HS] = MMC_TIMING_MMC_HS,
161 [SD_HS] = MMC_TIMING_SD_HS,
Ashok Reddy Soma5ff7acf2022-06-27 14:22:45 +0530162 [MMC_HS_52] = MMC_TIMING_MMC_HS,
163 [MMC_DDR_52] = MMC_TIMING_MMC_DDR52,
Ashok Reddy Soma0afdfe32020-10-23 04:58:58 -0600164 [UHS_SDR12] = MMC_TIMING_UHS_SDR12,
165 [UHS_SDR25] = MMC_TIMING_UHS_SDR25,
166 [UHS_SDR50] = MMC_TIMING_UHS_SDR50,
167 [UHS_DDR50] = MMC_TIMING_UHS_DDR50,
168 [UHS_SDR104] = MMC_TIMING_UHS_SDR104,
169 [MMC_HS_200] = MMC_TIMING_MMC_HS200,
Ashok Reddy Soma407a5612023-01-10 04:31:24 -0700170 [MMC_HS_400] = MMC_TIMING_MMC_HS400,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530171};
172
Michal Simek534a9342024-05-29 16:48:00 +0200173#if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700174/**
175 * arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock
176 *
177 * @host: Pointer to the sdhci_host structure
178 * @enable: Enable or disable Delay chain based Tx and Rx clock
179 * Return: None
180 *
181 * Enable or disable eMMC delay chain based Input and Output clock in
182 * PHY_CTRL_REG2
183 */
184static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable)
185{
186 u32 reg;
187
188 reg = sdhci_readw(host, PHY_CTRL_REG2);
189 if (enable)
190 reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK;
191 else
192 reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK);
193
194 sdhci_writew(host, reg, PHY_CTRL_REG2);
195}
196
197/**
198 * arasan_phy_set_dll - Set eMMC DLL clock
199 *
200 * @host: Pointer to the sdhci_host structure
201 * @enable: Enable or disable DLL clock
202 * Return: 0 if success or timeout error
203 *
204 * Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is
205 * set, wait till DLL is locked
206 */
207static int arasan_phy_set_dll(struct sdhci_host *host, bool enable)
208{
209 u32 reg;
210
211 reg = sdhci_readw(host, PHY_CTRL_REG2);
212 if (enable)
213 reg |= PHY_CTRL_EN_DLL_MASK;
214 else
215 reg &= ~PHY_CTRL_EN_DLL_MASK;
216
217 sdhci_writew(host, reg, PHY_CTRL_REG2);
218
219 /* If DLL is disabled return success */
220 if (!enable)
221 return 0;
222
223 /* If DLL is enabled wait till DLL loop is locked, which is
224 * indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2
225 */
226 return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg,
227 (reg & PHY_CTRL_DLL_RDY_MASK),
228 1000 * PHY_DLL_TIMEOUT_MS);
229}
230
231/**
232 * arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC
233 *
234 * @host: Pointer to the sdhci_host structure
235 * @clock: clock value
236 * Return: None
237 *
238 * Set frequency range bits based on the selected clock for eMMC
239 */
240static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock)
241{
242 u32 reg, freq_sel, freq;
243
244 freq = DIV_ROUND_CLOSEST(clock, 1000000);
245 if (freq <= 200 && freq > 170)
246 freq_sel = FREQSEL_200M_170M;
247 else if (freq <= 170 && freq > 140)
248 freq_sel = FREQSEL_170M_140M;
249 else if (freq <= 140 && freq > 110)
250 freq_sel = FREQSEL_140M_110M;
251 else if (freq <= 110 && freq > 80)
252 freq_sel = FREQSEL_110M_80M;
253 else
254 freq_sel = FREQSEL_80M_50M;
255
256 reg = sdhci_readw(host, PHY_CTRL_REG2);
257 reg &= ~PHY_CTRL_FREQ_SEL_MASK;
258 reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT);
259 sdhci_writew(host, reg, PHY_CTRL_REG2);
260}
261
262static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable)
263{
264 struct mmc *mmc = (struct mmc *)host->mmc;
265 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
266
267 if (enable) {
268 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable)
269 arasan_phy_set_dll(host, 1);
270 return 0;
271 }
272
273 if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) {
274 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
275 arasan_phy_set_dll(host, 0);
276 arasan_phy_set_delaychain(host, 0);
277 arasan_phy_dll_set_freq(host, clock);
278 return 0;
279 }
280
281 sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
282 arasan_phy_set_delaychain(host, 1);
283
284 return 0;
285}
286#endif
287
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600288static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600289{
290 int ret;
291
Simon Glass7ec24132024-09-29 19:49:48 -0600292 if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) {
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600293 if (node_id == NODE_SD_0) {
294 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN,
295 SD0_ITAPCHGWIN);
296 if (ret)
297 return ret;
298
299 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYENA,
300 SD0_ITAPDLYENA);
301 if (ret)
302 return ret;
303
304 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPDLYSEL_MASK,
305 itap_delay);
306 if (ret)
307 return ret;
308
309 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD0_ITAPCHGWIN, 0);
310 if (ret)
311 return ret;
312 }
313 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN,
314 SD1_ITAPCHGWIN);
315 if (ret)
316 return ret;
317
318 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYENA,
319 SD1_ITAPDLYENA);
320 if (ret)
321 return ret;
322
323 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPDLYSEL_MASK,
324 (itap_delay << 16));
325 if (ret)
326 return ret;
327
328 ret = zynqmp_mmio_write(SD_ITAP_DLY, SD1_ITAPCHGWIN, 0);
329 if (ret)
330 return ret;
331 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600332 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600333 IOCTL_SET_SD_TAPDELAY,
334 PM_TAPDELAY_INPUT, itap_delay, NULL);
335 }
336
337 return 0;
338}
339
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600340static inline int arasan_zynqmp_set_out_tapdelay(u32 node_id, u32 otap_delay)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600341{
Simon Glass7ec24132024-09-29 19:49:48 -0600342 if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) {
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600343 if (node_id == NODE_SD_0)
344 return zynqmp_mmio_write(SD_OTAP_DLY,
345 SD0_OTAPDLYSEL_MASK,
346 otap_delay);
347
348 return zynqmp_mmio_write(SD_OTAP_DLY, SD1_OTAPDLYSEL_MASK,
349 (otap_delay << 16));
350 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600351 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600352 IOCTL_SET_SD_TAPDELAY,
353 PM_TAPDELAY_OUTPUT, otap_delay, NULL);
354 }
355}
356
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600357static inline int zynqmp_dll_reset(u32 node_id, u32 type)
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600358{
Simon Glass7ec24132024-09-29 19:49:48 -0600359 if (IS_ENABLED(CONFIG_XPL_BUILD) || current_el() == 3) {
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600360 if (node_id == NODE_SD_0)
361 return zynqmp_mmio_write(SD_DLL_CTRL, SD0_DLL_RST,
362 type == PM_DLL_RESET_ASSERT ?
363 SD0_DLL_RST : 0);
364
365 return zynqmp_mmio_write(SD_DLL_CTRL, SD1_DLL_RST,
366 type == PM_DLL_RESET_ASSERT ?
367 SD1_DLL_RST : 0);
368 } else {
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600369 return xilinx_pm_request(PM_IOCTL, node_id,
Ashok Reddy Soma7a5f8102021-08-02 23:20:44 -0600370 IOCTL_SD_DLL_RESET, type, 0, NULL);
371 }
372}
373
Ashok Reddy Somaa23e6ee2022-09-30 03:25:46 -0600374static int arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 node_id)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530375{
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600376 struct mmc *mmc = (struct mmc *)host->mmc;
377 struct udevice *dev = mmc->dev;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530378 unsigned long timeout;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600379 int ret;
380 u16 clk;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530381
382 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
383 clk &= ~(SDHCI_CLOCK_CARD_EN);
384 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
385
386 /* Issue DLL Reset */
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600387 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_ASSERT);
388 if (ret) {
389 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
390 return ret;
391 }
392
393 /* Allow atleast 1ms delay for proper DLL reset */
394 mdelay(1);
395 ret = zynqmp_dll_reset(node_id, PM_DLL_RESET_RELEASE);
396 if (ret) {
397 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
398 return ret;
399 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530400
401 /* Wait max 20 ms */
402 timeout = 100;
403 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
404 & SDHCI_CLOCK_INT_STABLE)) {
405 if (timeout == 0) {
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600406 dev_err(dev, ": Internal clock never stabilised.\n");
407 return -EBUSY;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530408 }
409 timeout--;
410 udelay(1000);
411 }
412
413 clk |= SDHCI_CLOCK_CARD_EN;
414 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600415
416 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530417}
418
419static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
420{
421 struct mmc_cmd cmd;
422 struct mmc_data data;
423 u32 ctrl;
424 struct sdhci_host *host;
425 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Algapally Santosh Sagar99a98ca2023-01-19 22:36:17 -0700426 int tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530427
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +0100428 dev_dbg(mmc->dev, "%s\n", __func__);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530429
430 host = priv->host;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530431
Faiz Abbas2eddc002019-06-11 00:43:40 +0530432 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530433 ctrl |= SDHCI_CTRL_EXEC_TUNING;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530434 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530435
436 mdelay(1);
437
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530438 if (arasan_sdhci_is_compatible(mmc->dev, SDHCI_COMPATIBLE_SDHCI_89A))
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200439 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530440
441 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
442 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
443
444 do {
445 cmd.cmdidx = opcode;
446 cmd.resp_type = MMC_RSP_R1;
447 cmd.cmdarg = 0;
448
449 data.blocksize = 64;
450 data.blocks = 1;
451 data.flags = MMC_DATA_READ;
452
453 if (tuning_loop_counter-- == 0)
454 break;
455
456 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
457 mmc->bus_width == 8)
458 data.blocksize = 128;
459
460 sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
461 data.blocksize),
462 SDHCI_BLOCK_SIZE);
463 sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
464 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
465
466 mmc_send_cmd(mmc, &cmd, NULL);
Faiz Abbas2eddc002019-06-11 00:43:40 +0530467 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530468
469 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
470 udelay(1);
471
472 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
473
474 if (tuning_loop_counter < 0) {
475 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
Faiz Abbas2eddc002019-06-11 00:43:40 +0530476 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530477 }
478
479 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
480 printf("%s:Tuning failed\n", __func__);
481 return -1;
482 }
483
484 udelay(1);
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200485
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530486 if (arasan_sdhci_is_compatible(mmc->dev, SDHCI_COMPATIBLE_SDHCI_89A))
Ashok Reddy Soma00d98c22023-07-10 14:11:59 +0200487 arasan_zynqmp_dll_reset(host, priv->node_id);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530488
489 /* Enable only interrupts served by the SD controller */
490 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
491 SDHCI_INT_ENABLE);
492 /* Mask all sdhci interrupt sources */
493 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
494
495 return 0;
496}
497
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600498/**
499 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
500 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600501 * @host: Pointer to the sdhci_host structure.
502 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600503 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600504 *
505 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600506 */
507static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
508 int degrees)
509{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600510 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600511 struct udevice *dev = mmc->dev;
512 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600513 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600514 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600515 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600516
517 /*
518 * This is applicable for SDHCI_SPEC_300 and above
519 * ZynqMP does not set phase for <=25MHz clock.
520 * If degrees is zero, no need to do anything.
521 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600522 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600523 return 0;
524
525 switch (timing) {
526 case MMC_TIMING_MMC_HS:
527 case MMC_TIMING_SD_HS:
528 case MMC_TIMING_UHS_SDR25:
529 case MMC_TIMING_UHS_DDR50:
530 case MMC_TIMING_MMC_DDR52:
531 /* For 50MHz clock, 30 Taps are available */
532 tap_max = 30;
533 break;
534 case MMC_TIMING_UHS_SDR50:
535 /* For 100MHz clock, 15 Taps are available */
536 tap_max = 15;
537 break;
538 case MMC_TIMING_UHS_SDR104:
539 case MMC_TIMING_MMC_HS200:
540 /* For 200MHz clock, 8 Taps are available */
541 tap_max = 8;
542 default:
543 break;
544 }
545
546 tap_delay = (degrees * tap_max) / 360;
547
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600548 /* Limit output tap_delay value to 6 bits */
549 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
550
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600551 /* Set the Clock Phase */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600552 ret = arasan_zynqmp_set_out_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600553 if (ret) {
554 dev_err(dev, "Error setting output Tap Delay\n");
555 return ret;
556 }
557
558 /* Release DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600559 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_RELEASE);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600560 if (ret) {
561 dev_err(dev, "dll_reset release failed with err: %d\n", ret);
562 return ret;
563 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600564
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600565 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600566}
567
568/**
569 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
570 *
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600571 * @host: Pointer to the sdhci_host structure.
572 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600573 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600574 *
575 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600576 */
577static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
578 int degrees)
579{
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600580 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600581 struct udevice *dev = mmc->dev;
582 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600583 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600584 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600585 int ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600586
587 /*
588 * This is applicable for SDHCI_SPEC_300 and above
589 * ZynqMP does not set phase for <=25MHz clock.
590 * If degrees is zero, no need to do anything.
591 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600592 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600593 return 0;
594
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600595 /* Assert DLL Reset */
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600596 ret = zynqmp_dll_reset(priv->node_id, PM_DLL_RESET_ASSERT);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600597 if (ret) {
598 dev_err(dev, "dll_reset assert failed with err: %d\n", ret);
599 return ret;
600 }
601
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600602 switch (timing) {
603 case MMC_TIMING_MMC_HS:
604 case MMC_TIMING_SD_HS:
605 case MMC_TIMING_UHS_SDR25:
606 case MMC_TIMING_UHS_DDR50:
607 case MMC_TIMING_MMC_DDR52:
608 /* For 50MHz clock, 120 Taps are available */
609 tap_max = 120;
610 break;
611 case MMC_TIMING_UHS_SDR50:
612 /* For 100MHz clock, 60 Taps are available */
613 tap_max = 60;
614 break;
615 case MMC_TIMING_UHS_SDR104:
616 case MMC_TIMING_MMC_HS200:
617 /* For 200MHz clock, 30 Taps are available */
618 tap_max = 30;
619 default:
620 break;
621 }
622
623 tap_delay = (degrees * tap_max) / 360;
624
Ashok Reddy Soma39a177a2021-07-09 05:53:42 -0600625 /* Limit input tap_delay value to 8 bits */
626 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
627
Ashok Reddy Soma33154532022-09-30 03:25:47 -0600628 ret = arasan_zynqmp_set_in_tapdelay(priv->node_id, tap_delay);
Ashok Reddy Soma467d0782021-08-02 23:20:43 -0600629 if (ret) {
630 dev_err(dev, "Error setting Input Tap Delay\n");
631 return ret;
632 }
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600633
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600634 return 0;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600635}
636
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600637/**
638 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
639 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600640 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600641 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600642 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600643 *
644 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600645 */
646static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
647 int degrees)
648{
649 struct mmc *mmc = (struct mmc *)host->mmc;
650 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600651 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600652 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600653
654 /*
655 * This is applicable for SDHCI_SPEC_300 and above
656 * Versal does not set phase for <=25MHz clock.
657 * If degrees is zero, no need to do anything.
658 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600659 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600660 return 0;
661
662 switch (timing) {
663 case MMC_TIMING_MMC_HS:
664 case MMC_TIMING_SD_HS:
665 case MMC_TIMING_UHS_SDR25:
666 case MMC_TIMING_UHS_DDR50:
667 case MMC_TIMING_MMC_DDR52:
668 /* For 50MHz clock, 30 Taps are available */
669 tap_max = 30;
670 break;
671 case MMC_TIMING_UHS_SDR50:
672 /* For 100MHz clock, 15 Taps are available */
673 tap_max = 15;
674 break;
675 case MMC_TIMING_UHS_SDR104:
676 case MMC_TIMING_MMC_HS200:
677 /* For 200MHz clock, 8 Taps are available */
678 tap_max = 8;
679 default:
680 break;
681 }
682
683 tap_delay = (degrees * tap_max) / 360;
684
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600685 /* Limit output tap_delay value to 6 bits */
686 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600687
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600688 /* Set the Clock Phase */
689 regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
690 regval |= SDHCI_OTAPDLY_ENABLE;
691 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
692 regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
693 regval |= tap_delay;
694 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600695
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600696 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600697}
698
699/**
700 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
701 *
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600702 * @host: Pointer to the sdhci_host structure.
Michal Simek2a43ab82021-07-09 05:53:43 -0600703 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600704 * Return: 0
Michal Simek2a43ab82021-07-09 05:53:43 -0600705 *
706 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600707 */
708static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
709 int degrees)
710{
711 struct mmc *mmc = (struct mmc *)host->mmc;
712 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600713 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600714 u32 regval;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600715
716 /*
717 * This is applicable for SDHCI_SPEC_300 and above
718 * Versal does not set phase for <=25MHz clock.
719 * If degrees is zero, no need to do anything.
720 */
Ashok Reddy Soma6f645382021-07-09 05:53:40 -0600721 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600722 return 0;
723
724 switch (timing) {
725 case MMC_TIMING_MMC_HS:
726 case MMC_TIMING_SD_HS:
727 case MMC_TIMING_UHS_SDR25:
728 case MMC_TIMING_UHS_DDR50:
729 case MMC_TIMING_MMC_DDR52:
730 /* For 50MHz clock, 120 Taps are available */
731 tap_max = 120;
732 break;
733 case MMC_TIMING_UHS_SDR50:
734 /* For 100MHz clock, 60 Taps are available */
735 tap_max = 60;
736 break;
737 case MMC_TIMING_UHS_SDR104:
738 case MMC_TIMING_MMC_HS200:
739 /* For 200MHz clock, 30 Taps are available */
740 tap_max = 30;
741 default:
742 break;
743 }
744
745 tap_delay = (degrees * tap_max) / 360;
746
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600747 /* Limit input tap_delay value to 8 bits */
748 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600749
Ashok Reddy Soma24a51072021-07-09 05:53:41 -0600750 /* Set the Clock Phase */
751 regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
752 regval |= SDHCI_ITAPDLY_CHGWIN;
753 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
754 regval |= SDHCI_ITAPDLY_ENABLE;
755 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
756 regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
757 regval |= tap_delay;
758 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
759 regval &= ~SDHCI_ITAPDLY_CHGWIN;
760 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600761
Ashok Reddy Soma94a755d2021-07-09 05:53:39 -0600762 return 0;
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600763}
764
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700765/**
766 * sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays
767 *
768 * @host: Pointer to the sdhci_host structure.
769 * @degrees: The clock phase shift between 0 - 359.
770 * Return: 0
771 *
772 * Set eMMC Output Clock Tap Delays for Output path
773 */
774static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees)
775{
776 struct mmc *mmc = (struct mmc *)host->mmc;
777 int timing = mode2timing[mmc->selected_mode];
778 u8 tap_delay, tap_max = 0;
779 u32 regval;
780
781 switch (timing) {
782 case MMC_TIMING_MMC_HS:
783 case MMC_TIMING_MMC_DDR52:
784 tap_max = 16;
785 break;
786 case MMC_TIMING_MMC_HS200:
787 case MMC_TIMING_MMC_HS400:
788 /* For 200MHz clock, 32 Taps are available */
789 tap_max = 32;
790 break;
791 default:
792 break;
793 }
794
795 tap_delay = (degrees * tap_max) / 360;
796 /* Set the Clock Phase */
797 if (tap_delay) {
798 regval = sdhci_readl(host, PHY_CTRL_REG1);
799 regval |= PHY_CTRL_OTAPDLY_ENA_MASK;
800 sdhci_writel(host, regval, PHY_CTRL_REG1);
801 regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK;
802 regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT;
803 sdhci_writel(host, regval, PHY_CTRL_REG1);
804 }
805
806 return 0;
807}
808
809/**
810 * sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays
811 *
812 * @host: Pointer to the sdhci_host structure.
813 * @degrees: The clock phase shift between 0 - 359.
814 * Return: 0
815 *
816 * Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected,
817 * set strobe90 and strobe180 in PHY_CTRL_REG1.
818 */
819static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees)
820{
821 struct mmc *mmc = (struct mmc *)host->mmc;
822 int timing = mode2timing[mmc->selected_mode];
823 u8 tap_delay, tap_max = 0;
824 u32 regval;
825
826 switch (timing) {
827 case MMC_TIMING_MMC_HS:
828 case MMC_TIMING_MMC_DDR52:
829 tap_max = 32;
830 break;
831 case MMC_TIMING_MMC_HS400:
832 /* Strobe select tap point for strb90 and strb180 */
833 regval = sdhci_readl(host, PHY_CTRL_REG1);
834 regval &= ~PHY_CTRL_STRB_SEL_MASK;
835 regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT;
836 sdhci_writel(host, regval, PHY_CTRL_REG1);
837 break;
838 default:
839 break;
840 }
841
842 tap_delay = (degrees * tap_max) / 360;
843 /* Set the Clock Phase */
844 if (tap_delay) {
845 regval = sdhci_readl(host, PHY_CTRL_REG1);
846 regval |= PHY_CTRL_ITAP_CHG_WIN_MASK;
847 sdhci_writel(host, regval, PHY_CTRL_REG1);
848 regval |= PHY_CTRL_ITAPDLY_ENA_MASK;
849 sdhci_writel(host, regval, PHY_CTRL_REG1);
850 regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK;
851 regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT;
852 sdhci_writel(host, regval, PHY_CTRL_REG1);
853 regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK;
854 sdhci_writel(host, regval, PHY_CTRL_REG1);
855 }
856
857 return 0;
858}
859
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600860static int arasan_sdhci_set_tapdelay(struct sdhci_host *host)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530861{
862 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600863 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530864 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600865 struct udevice *dev = mmc->dev;
866 u8 timing = mode2timing[mmc->selected_mode];
867 u32 iclk_phase = clk_data->clk_phase_in[timing];
868 u32 oclk_phase = clk_data->clk_phase_out[timing];
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600869 int ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530870
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600871 dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530872
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600873 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530874 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600875 ret = sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
876 if (ret)
877 return ret;
878
879 ret = sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
880 if (ret)
881 return ret;
Simek, Michald78ea252024-04-17 20:06:13 -1200882 } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
Michal Simek534a9342024-05-29 16:48:00 +0200883 IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
884 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530885 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) {
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600886 ret = sdhci_versal_sampleclk_set_phase(host, iclk_phase);
887 if (ret)
888 return ret;
889
890 ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
891 if (ret)
892 return ret;
Michal Simek534a9342024-05-29 16:48:00 +0200893 } else if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
894 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530895 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700896 if (mmc->clock >= MIN_PHY_CLK_HZ)
897 if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN)
898 iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL;
899
900 ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase);
901 if (ret)
902 return ret;
903
904 ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase);
905 if (ret)
906 return ret;
Ashok Reddy Soma8f629862020-10-23 04:59:01 -0600907 }
Ashok Reddy Soma21fd7632021-08-02 23:20:40 -0600908
909 return 0;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +0530910}
911
Michal Simek33a6b772020-10-23 04:59:00 -0600912static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
913 const char *prop)
914{
915 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
916 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
917 u32 clk_phase[2] = {0};
918
919 /*
920 * Read Tap Delay values from DT, if the DT does not contain the
921 * Tap Values then use the pre-defined values
922 */
923 if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
924 dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
925 prop, clk_data->clk_phase_in[timing],
926 clk_data->clk_phase_out[timing]);
927 return;
928 }
929
930 /* The values read are Input and Output Clock Delays in order */
931 clk_data->clk_phase_in[timing] = clk_phase[0];
932 clk_data->clk_phase_out[timing] = clk_phase[1];
933}
934
935/**
936 * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
937 *
Michal Simek33a6b772020-10-23 04:59:00 -0600938 * @dev: Pointer to our struct udevice.
Michal Simek2a43ab82021-07-09 05:53:43 -0600939 *
940 * Called at initialization to parse the values of Tap Delays.
Michal Simek33a6b772020-10-23 04:59:00 -0600941 */
942static void arasan_dt_parse_clk_phases(struct udevice *dev)
943{
944 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
945 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
946 int i;
947
948 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530949 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) {
Michal Simek33a6b772020-10-23 04:59:00 -0600950 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
951 clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
952 clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
953 }
954
955 if (priv->bank == MMC_BANK2) {
956 clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
957 clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
958 }
959 }
960
Simek, Michald78ea252024-04-17 20:06:13 -1200961 if ((IS_ENABLED(CONFIG_ARCH_VERSAL) ||
Michal Simek534a9342024-05-29 16:48:00 +0200962 IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
963 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530964 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) {
Ashok Reddy Soma568edfd2020-10-23 04:59:02 -0600965 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
966 clk_data->clk_phase_in[i] = versal_iclk_phases[i];
967 clk_data->clk_phase_out[i] = versal_oclk_phases[i];
968 }
969 }
970
Michal Simek534a9342024-05-29 16:48:00 +0200971 if ((IS_ENABLED(CONFIG_ARCH_VERSAL_NET) ||
972 IS_ENABLED(CONFIG_ARCH_VERSAL2)) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +0530973 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC)) {
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -0700974 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
975 clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i];
976 clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i];
977 }
978 }
979
Michal Simek33a6b772020-10-23 04:59:00 -0600980 arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
981 "clk-phase-legacy");
982 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
983 "clk-phase-mmc-hs");
984 arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
985 "clk-phase-sd-hs");
986 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
987 "clk-phase-uhs-sdr12");
988 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
989 "clk-phase-uhs-sdr25");
990 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
991 "clk-phase-uhs-sdr50");
992 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
993 "clk-phase-uhs-sdr104");
994 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
995 "clk-phase-uhs-ddr50");
996 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
997 "clk-phase-mmc-ddr52");
998 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
999 "clk-phase-mmc-hs200");
1000 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
1001 "clk-phase-mmc-hs400");
1002}
1003
Michal Simek635cf4a2021-07-09 05:53:44 -06001004static const struct sdhci_ops arasan_ops = {
1005 .platform_execute_tuning = &arasan_sdhci_execute_tuning,
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301006 .set_delay = &arasan_sdhci_set_tapdelay,
Ashok Reddy Soma8ee49f02021-08-02 23:20:46 -06001007 .set_control_reg = &sdhci_set_control_reg,
Michal Simek534a9342024-05-29 16:48:00 +02001008#if defined(CONFIG_ARCH_VERSAL_NET) || defined(CONFIG_ARCH_VERSAL2)
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07001009 .config_dll = &arasan_sdhci_config_dll,
1010#endif
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301011};
1012#endif
1013
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -07001014#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001015static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
1016 struct udevice *dev)
1017{
1018 int ret;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001019 struct clk clk;
1020 unsigned long clock, mhz;
1021
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001022 ret = xilinx_pm_request(PM_REQUEST_NODE, priv->node_id,
1023 ZYNQMP_PM_CAPABILITY_ACCESS, ZYNQMP_PM_MAX_QOS,
1024 ZYNQMP_PM_REQUEST_ACK_NO, NULL);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001025 if (ret) {
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001026 dev_err(dev, "Request node failed for %d\n", priv->node_id);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001027 return ret;
1028 }
1029
1030 ret = reset_get_bulk(dev, &priv->resets);
1031 if (ret == -ENOTSUPP || ret == -ENOENT) {
1032 dev_err(dev, "Reset not found\n");
1033 return 0;
1034 } else if (ret) {
1035 dev_err(dev, "Reset failed\n");
1036 return ret;
1037 }
1038
1039 ret = reset_assert_bulk(&priv->resets);
1040 if (ret) {
1041 dev_err(dev, "Reset assert failed\n");
1042 return ret;
1043 }
1044
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001045 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_FIXED, 0);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001046 if (ret) {
1047 dev_err(dev, "SD_CONFIG_FIXED failed\n");
1048 return ret;
1049 }
1050
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001051 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_EMMC_SEL,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001052 dev_read_bool(dev, "non-removable"));
1053 if (ret) {
1054 dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
1055 return ret;
1056 }
1057
1058 ret = clk_get_by_index(dev, 0, &clk);
1059 if (ret < 0) {
1060 dev_err(dev, "failed to get clock\n");
1061 return ret;
1062 }
1063
1064 clock = clk_get_rate(&clk);
1065 if (IS_ERR_VALUE(clock)) {
1066 dev_err(dev, "failed to get rate\n");
1067 return clock;
1068 }
1069
1070 mhz = DIV64_U64_ROUND_UP(clock, 1000000);
1071
Ashok Reddy Soma088febe2022-03-25 13:11:10 +01001072 if (mhz > 100 && mhz <= 200)
1073 mhz = 200;
1074 else if (mhz > 50 && mhz <= 100)
1075 mhz = 100;
1076 else if (mhz > 25 && mhz <= 50)
1077 mhz = 50;
1078 else
1079 mhz = 25;
1080
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001081 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_BASECLK, mhz);
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001082 if (ret) {
1083 dev_err(dev, "SD_CONFIG_BASECLK failed\n");
1084 return ret;
1085 }
1086
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001087 ret = zynqmp_pm_set_sd_config(priv->node_id, SD_CONFIG_8BIT,
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001088 (dev_read_u32_default(dev, "bus-width", 1) == 8));
1089 if (ret) {
1090 dev_err(dev, "SD_CONFIG_8BIT failed\n");
1091 return ret;
1092 }
1093
1094 ret = reset_deassert_bulk(&priv->resets);
1095 if (ret) {
1096 dev_err(dev, "Reset release failed\n");
1097 return ret;
1098 }
1099
1100 return 0;
1101}
1102#endif
1103
Michal Simek9ecd2682015-11-30 16:13:03 +01001104static int arasan_sdhci_probe(struct udevice *dev)
Michal Simek0dd222b2013-04-22 14:56:49 +02001105{
Simon Glassfa20e932020-12-03 16:55:20 -07001106 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Michal Simek9ecd2682015-11-30 16:13:03 +01001107 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301108 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
1109 struct sdhci_host *host;
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001110 struct clk clk;
1111 unsigned long clock;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001112 int ret;
Michal Simek0dd222b2013-04-22 14:56:49 +02001113
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301114 host = priv->host;
1115
Algapally Santosh Sagarbf34dd42023-02-01 02:55:53 -07001116#if defined(CONFIG_ARCH_ZYNQMP) && defined(CONFIG_ZYNQMP_FIRMWARE)
Padmarao Begaricc0a2832024-09-13 15:01:57 +05301117 if (arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_SDHCI_89A)) {
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001118 ret = zynqmp_pm_is_function_supported(PM_IOCTL,
1119 IOCTL_SET_SD_CONFIG);
1120 if (!ret) {
1121 ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
1122 if (ret)
1123 return ret;
1124 }
1125 }
1126#endif
Padmarao Begaricc0a2832024-09-13 15:01:57 +05301127 if (arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC))
Ashok Reddy Soma0ab38fd2023-01-10 04:31:21 -07001128 priv->internal_phy_reg = true;
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001129
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001130 ret = clk_get_by_index(dev, 0, &clk);
1131 if (ret < 0) {
1132 dev_err(dev, "failed to get clock\n");
1133 return ret;
1134 }
1135
1136 clock = clk_get_rate(&clk);
1137 if (IS_ERR_VALUE(clock)) {
1138 dev_err(dev, "failed to get rate\n");
1139 return clock;
1140 }
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301141
Ashok Reddy Somaca7d8472022-02-23 15:36:05 +01001142 dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001143
1144 ret = clk_enable(&clk);
Michal Simek41710952021-02-09 15:28:15 +01001145 if (ret) {
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001146 dev_err(dev, "failed to enable clock\n");
1147 return ret;
1148 }
1149
Siva Durga Prasad Paladugu049e0032014-07-08 15:31:04 +05301150 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
Siva Durga Prasad Paladugu0d6891b2014-01-22 09:17:09 +01001151 SDHCI_QUIRK_BROKEN_R1B;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301152
1153#ifdef CONFIG_ZYNQ_HISPD_BROKEN
Hannes Schmelzer94a5bbc2018-03-07 08:00:57 +01001154 host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
Siva Durga Prasad Paladugua1619fe2016-01-12 15:12:16 +05301155#endif
1156
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001157 if (priv->no_1p8)
1158 host->quirks |= SDHCI_QUIRK_NO_1_8_V;
1159
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001160 if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) &&
Padmarao Begaricc0a2832024-09-13 15:01:57 +05301161 arasan_sdhci_is_compatible(dev, SDHCI_COMPATIBLE_VERSAL_NET_EMMC))
Ashok Reddy Soma407a5612023-01-10 04:31:24 -07001162 host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400;
1163
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001164 plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
1165
1166 ret = mmc_of_parse(dev, &plat->cfg);
1167 if (ret)
1168 return ret;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301169
Stefan Herbrechtsmeier739ae402017-01-17 16:27:32 +01001170 host->max_clk = clock;
Stefan Herbrechtsmeierbc47e0e2017-01-17 15:58:48 +01001171
Matwey V. Kornilov194b8602019-08-01 18:00:05 +03001172 host->mmc = &plat->mmc;
1173 host->mmc->dev = dev;
1174 host->mmc->priv = host;
1175
Benedikt Grassl529e6f02020-04-14 07:32:12 +02001176 ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
Jaehoon Chung8a5ffbb2016-07-26 19:06:24 +09001177 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001178 if (ret)
1179 return ret;
Simon Glass4cc87fb2016-07-05 17:10:15 -06001180 upriv->mmc = host->mmc;
Michal Simek9ecd2682015-11-30 16:13:03 +01001181
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001182 /*
1183 * WORKAROUND: Versal platforms have an issue with card detect state.
1184 * Due to this, host controller is switching off voltage to sd card
1185 * causing sd card timeout error. Workaround this by adding a wait for
1186 * 1000msec till the card detect state gets stable.
1187 */
Ashok Reddy Soma6556bff2022-02-23 15:13:32 +01001188 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001189 u32 timeout = 1000000;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001190
1191 while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001192 SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
Ashok Reddy Somadd745772022-02-23 15:13:31 +01001193 udelay(1);
Ashok Reddy Soma09f38902022-02-23 15:13:30 +01001194 timeout--;
T Karthik Reddyab0a7492021-08-02 23:20:45 -06001195 }
1196 if (!timeout) {
1197 dev_err(dev, "Sdhci card detect state not stable\n");
1198 return -ETIMEDOUT;
1199 }
1200 }
1201
Simon Glass4cc87fb2016-07-05 17:10:15 -06001202 return sdhci_probe(dev);
Michal Simek0dd222b2013-04-22 14:56:49 +02001203}
Michal Simek9ecd2682015-11-30 16:13:03 +01001204
Simon Glassaad29ae2020-12-03 16:55:21 -07001205static int arasan_sdhci_of_to_plat(struct udevice *dev)
Michal Simek9ecd2682015-11-30 16:13:03 +01001206{
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301207 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001208 u32 pm_info[2];
Michal Simek9ecd2682015-11-30 16:13:03 +01001209
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301210 priv->host = calloc(1, sizeof(struct sdhci_host));
1211 if (!priv->host)
1212 return -1;
1213
1214 priv->host->name = dev->name;
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301215
Michal Simek534a9342024-05-29 16:48:00 +02001216#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) || \
1217 defined(CONFIG_ARCH_VERSAL2)
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301218 priv->host->ops = &arasan_ops;
Michal Simek33a6b772020-10-23 04:59:00 -06001219 arasan_dt_parse_clk_phases(dev);
Siva Durga Prasad Paladugucad14a82018-04-19 12:37:09 +05301220#endif
Michal Simek9ecd2682015-11-30 16:13:03 +01001221
Johan Jonker8d5d8e02023-03-13 01:32:04 +01001222 priv->host->ioaddr = dev_read_addr_ptr(dev);
1223 if (!priv->host->ioaddr)
1224 return -EINVAL;
Michal Simek921a8de2018-05-16 10:57:07 +02001225
Michal Simeke40ae572020-07-22 17:46:31 +02001226 priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
Ashok Reddy Soma61e0df92020-10-23 04:58:57 -06001227 priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
Stefan Herbrechtsmeier5567b422017-01-17 16:27:33 +01001228
Ashok Reddy Soma33154532022-09-30 03:25:47 -06001229 priv->node_id = 0;
1230 if (!dev_read_u32_array(dev, "power-domains", pm_info, ARRAY_SIZE(pm_info)))
1231 priv->node_id = pm_info[1];
1232
Michal Simek9ecd2682015-11-30 16:13:03 +01001233 return 0;
1234}
1235
Simon Glass4cc87fb2016-07-05 17:10:15 -06001236static int arasan_sdhci_bind(struct udevice *dev)
1237{
Simon Glassfa20e932020-12-03 16:55:20 -07001238 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001239
Masahiro Yamadacdb67f32016-09-06 22:17:32 +09001240 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Simon Glass4cc87fb2016-07-05 17:10:15 -06001241}
1242
Michal Simek9ecd2682015-11-30 16:13:03 +01001243static const struct udevice_id arasan_sdhci_ids[] = {
Padmarao Begaricc0a2832024-09-13 15:01:57 +05301244 { .compatible = "arasan,sdhci-8.9a", .data = SDHCI_COMPATIBLE_SDHCI_89A },
1245 { .compatible = "xlnx,versal-net-emmc", .data = SDHCI_COMPATIBLE_VERSAL_NET_EMMC },
Michal Simek9ecd2682015-11-30 16:13:03 +01001246 { }
1247};
1248
1249U_BOOT_DRIVER(arasan_sdhci_drv) = {
1250 .name = "arasan_sdhci",
1251 .id = UCLASS_MMC,
1252 .of_match = arasan_sdhci_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001253 .of_to_plat = arasan_sdhci_of_to_plat,
Simon Glass4cc87fb2016-07-05 17:10:15 -06001254 .ops = &sdhci_ops,
1255 .bind = arasan_sdhci_bind,
Michal Simek9ecd2682015-11-30 16:13:03 +01001256 .probe = arasan_sdhci_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001257 .priv_auto = sizeof(struct arasan_sdhci_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001258 .plat_auto = sizeof(struct arasan_sdhci_plat),
Michal Simek9ecd2682015-11-30 16:13:03 +01001259};