blob: 95d42ccef44b38eb4c157cb8d0662446b122928e [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek293eb332013-04-22 14:56:49 +02002/*
Michal Simekd9ae52c2015-11-30 16:13:03 +01003 * (C) Copyright 2013 - 2015 Xilinx, Inc.
Michal Simek293eb332013-04-22 14:56:49 +02004 *
5 * Xilinx Zynq SD Host Controller Interface
Michal Simek293eb332013-04-22 14:56:49 +02006 */
7
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +01008#include <clk.h>
Michal Simek293eb332013-04-22 14:56:49 +02009#include <common.h>
Michal Simekd9ae52c2015-11-30 16:13:03 +010010#include <dm.h>
Michal Simek345d3c02014-02-24 11:16:31 +010011#include <fdtdec.h>
Simon Glassc05ed002020-05-10 11:40:11 -060012#include <linux/delay.h>
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053013#include "mmc_private.h"
Simon Glassf7ae49f2020-05-10 11:40:05 -060014#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070015#include <dm/device_compat.h>
Simon Glass61b29b82020-02-03 07:36:15 -070016#include <linux/err.h>
Masahiro Yamadab08c8c42018-03-05 01:20:11 +090017#include <linux/libfdt.h>
Michal Simek293eb332013-04-22 14:56:49 +020018#include <malloc.h>
19#include <sdhci.h>
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053020#include <zynqmp_tap_delay.h>
Michal Simek293eb332013-04-22 14:56:49 +020021
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -060022#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8
23#define SDHCI_ARASAN_ITAPDLY_SEL_MASK GENMASK(7, 0)
24#define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC
25#define SDHCI_ARASAN_OTAPDLY_SEL_MASK GENMASK(5, 0)
26#define SDHCI_ITAPDLY_CHGWIN BIT(9)
27#define SDHCI_ITAPDLY_ENABLE BIT(8)
28#define SDHCI_OTAPDLY_ENABLE BIT(6)
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -060029
Michal Simek9851f502020-10-23 04:58:59 -060030#define SDHCI_TUNING_LOOP_COUNT 40
Michal Simek80355ae2020-10-23 04:59:00 -060031#define MMC_BANK2 0x2
32
33struct arasan_sdhci_clk_data {
34 int clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
35 int clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
36};
Michal Simek9851f502020-10-23 04:58:59 -060037
Simon Glass329a4492016-07-05 17:10:15 -060038struct arasan_sdhci_plat {
39 struct mmc_config cfg;
40 struct mmc mmc;
41};
42
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053043struct arasan_sdhci_priv {
44 struct sdhci_host *host;
Michal Simek80355ae2020-10-23 04:59:00 -060045 struct arasan_sdhci_clk_data clk_data;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053046 u8 deviceid;
47 u8 bank;
Ashok Reddy Soma7a49a162020-10-23 04:58:57 -060048 u8 no_1p8;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053049};
50
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -060051#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
Michal Simek80355ae2020-10-23 04:59:00 -060052/* Default settings for ZynqMP Clock Phases */
53const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0};
54const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0};
55
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -060056/* Default settings for Versal Clock Phases */
57const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0};
58const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
59
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053060static const u8 mode2timing[] = {
Ashok Reddy Soma17a42ab2020-10-23 04:58:58 -060061 [MMC_LEGACY] = MMC_TIMING_LEGACY,
62 [MMC_HS] = MMC_TIMING_MMC_HS,
63 [SD_HS] = MMC_TIMING_SD_HS,
64 [MMC_HS_52] = MMC_TIMING_UHS_SDR50,
65 [MMC_DDR_52] = MMC_TIMING_UHS_DDR50,
66 [UHS_SDR12] = MMC_TIMING_UHS_SDR12,
67 [UHS_SDR25] = MMC_TIMING_UHS_SDR25,
68 [UHS_SDR50] = MMC_TIMING_UHS_SDR50,
69 [UHS_DDR50] = MMC_TIMING_UHS_DDR50,
70 [UHS_SDR104] = MMC_TIMING_UHS_SDR104,
71 [MMC_HS_200] = MMC_TIMING_MMC_HS200,
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053072};
73
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053074static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
75{
76 u16 clk;
77 unsigned long timeout;
78
79 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
80 clk &= ~(SDHCI_CLOCK_CARD_EN);
81 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
82
83 /* Issue DLL Reset */
84 zynqmp_dll_reset(deviceid);
85
86 /* Wait max 20 ms */
87 timeout = 100;
88 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
89 & SDHCI_CLOCK_INT_STABLE)) {
90 if (timeout == 0) {
91 dev_err(mmc_dev(host->mmc),
92 ": Internal clock never stabilised.\n");
93 return;
94 }
95 timeout--;
96 udelay(1000);
97 }
98
99 clk |= SDHCI_CLOCK_CARD_EN;
100 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
101}
102
103static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
104{
105 struct mmc_cmd cmd;
106 struct mmc_data data;
107 u32 ctrl;
108 struct sdhci_host *host;
109 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Michal Simekb6911782018-06-13 09:12:29 +0200110 char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530111 u8 deviceid;
112
113 debug("%s\n", __func__);
114
115 host = priv->host;
116 deviceid = priv->deviceid;
117
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530118 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530119 ctrl |= SDHCI_CTRL_EXEC_TUNING;
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530120 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530121
122 mdelay(1);
123
124 arasan_zynqmp_dll_reset(host, deviceid);
125
126 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
127 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
128
129 do {
130 cmd.cmdidx = opcode;
131 cmd.resp_type = MMC_RSP_R1;
132 cmd.cmdarg = 0;
133
134 data.blocksize = 64;
135 data.blocks = 1;
136 data.flags = MMC_DATA_READ;
137
138 if (tuning_loop_counter-- == 0)
139 break;
140
141 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
142 mmc->bus_width == 8)
143 data.blocksize = 128;
144
145 sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
146 data.blocksize),
147 SDHCI_BLOCK_SIZE);
148 sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
149 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
150
151 mmc_send_cmd(mmc, &cmd, NULL);
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530152 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530153
154 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
155 udelay(1);
156
157 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
158
159 if (tuning_loop_counter < 0) {
160 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530161 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530162 }
163
164 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
165 printf("%s:Tuning failed\n", __func__);
166 return -1;
167 }
168
169 udelay(1);
170 arasan_zynqmp_dll_reset(host, deviceid);
171
172 /* Enable only interrupts served by the SD controller */
173 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
174 SDHCI_INT_ENABLE);
175 /* Mask all sdhci interrupt sources */
176 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
177
178 return 0;
179}
180
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600181/**
182 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
183 *
184 * Set the SD Output Clock Tap Delays for Output path
185 *
186 * @host: Pointer to the sdhci_host structure.
187 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600188 * Return: 0
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600189 */
190static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
191 int degrees)
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530192{
193 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
194 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600195 u8 tap_delay, tap_max = 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600196 int timing = mode2timing[mmc->selected_mode];
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530197
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600198 /*
199 * This is applicable for SDHCI_SPEC_300 and above
200 * ZynqMP does not set phase for <=25MHz clock.
201 * If degrees is zero, no need to do anything.
202 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600203 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600204 return 0;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530205
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600206 switch (timing) {
207 case MMC_TIMING_MMC_HS:
208 case MMC_TIMING_SD_HS:
209 case MMC_TIMING_UHS_SDR25:
210 case MMC_TIMING_UHS_DDR50:
211 case MMC_TIMING_MMC_DDR52:
212 /* For 50MHz clock, 30 Taps are available */
213 tap_max = 30;
214 break;
215 case MMC_TIMING_UHS_SDR50:
216 /* For 100MHz clock, 15 Taps are available */
217 tap_max = 15;
218 break;
219 case MMC_TIMING_UHS_SDR104:
220 case MMC_TIMING_MMC_HS200:
221 /* For 200MHz clock, 8 Taps are available */
222 tap_max = 8;
223 default:
224 break;
225 }
226
227 tap_delay = (degrees * tap_max) / 360;
228
Ashok Reddy Somaa70bdaf2021-07-09 05:53:42 -0600229 /* Limit output tap_delay value to 6 bits */
230 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
231
232 arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600233
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600234 return 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600235}
236
237/**
238 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
239 *
240 * Set the SD Input Clock Tap Delays for Input path
241 *
242 * @host: Pointer to the sdhci_host structure.
243 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600244 * Return: 0
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600245 */
246static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
247 int degrees)
248{
249 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
250 struct mmc *mmc = (struct mmc *)host->mmc;
251 u8 tap_delay, tap_max = 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600252 int timing = mode2timing[mmc->selected_mode];
253
254 /*
255 * This is applicable for SDHCI_SPEC_300 and above
256 * ZynqMP does not set phase for <=25MHz clock.
257 * If degrees is zero, no need to do anything.
258 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600259 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600260 return 0;
261
262 switch (timing) {
263 case MMC_TIMING_MMC_HS:
264 case MMC_TIMING_SD_HS:
265 case MMC_TIMING_UHS_SDR25:
266 case MMC_TIMING_UHS_DDR50:
267 case MMC_TIMING_MMC_DDR52:
268 /* For 50MHz clock, 120 Taps are available */
269 tap_max = 120;
270 break;
271 case MMC_TIMING_UHS_SDR50:
272 /* For 100MHz clock, 60 Taps are available */
273 tap_max = 60;
274 break;
275 case MMC_TIMING_UHS_SDR104:
276 case MMC_TIMING_MMC_HS200:
277 /* For 200MHz clock, 30 Taps are available */
278 tap_max = 30;
279 default:
280 break;
281 }
282
283 tap_delay = (degrees * tap_max) / 360;
284
Ashok Reddy Somaa70bdaf2021-07-09 05:53:42 -0600285 /* Limit input tap_delay value to 8 bits */
286 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
287
288 arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600289
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600290 return 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600291}
292
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600293/**
294 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
295 *
296 * Set the SD Output Clock Tap Delays for Output path
297 *
298 * @host: Pointer to the sdhci_host structure.
299 * @degrees The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600300 * Return: 0
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600301 */
302static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
303 int degrees)
304{
305 struct mmc *mmc = (struct mmc *)host->mmc;
306 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600307 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600308 u32 regval;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600309
310 /*
311 * This is applicable for SDHCI_SPEC_300 and above
312 * Versal does not set phase for <=25MHz clock.
313 * If degrees is zero, no need to do anything.
314 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600315 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600316 return 0;
317
318 switch (timing) {
319 case MMC_TIMING_MMC_HS:
320 case MMC_TIMING_SD_HS:
321 case MMC_TIMING_UHS_SDR25:
322 case MMC_TIMING_UHS_DDR50:
323 case MMC_TIMING_MMC_DDR52:
324 /* For 50MHz clock, 30 Taps are available */
325 tap_max = 30;
326 break;
327 case MMC_TIMING_UHS_SDR50:
328 /* For 100MHz clock, 15 Taps are available */
329 tap_max = 15;
330 break;
331 case MMC_TIMING_UHS_SDR104:
332 case MMC_TIMING_MMC_HS200:
333 /* For 200MHz clock, 8 Taps are available */
334 tap_max = 8;
335 default:
336 break;
337 }
338
339 tap_delay = (degrees * tap_max) / 360;
340
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600341 /* Limit output tap_delay value to 6 bits */
342 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600343
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600344 /* Set the Clock Phase */
345 regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
346 regval |= SDHCI_OTAPDLY_ENABLE;
347 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
348 regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
349 regval |= tap_delay;
350 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600351
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600352 return 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600353}
354
355/**
356 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
357 *
358 * Set the SD Input Clock Tap Delays for Input path
359 *
360 * @host: Pointer to the sdhci_host structure.
361 * @degrees The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600362 * Return: 0
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600363 */
364static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
365 int degrees)
366{
367 struct mmc *mmc = (struct mmc *)host->mmc;
368 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600369 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600370 u32 regval;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600371
372 /*
373 * This is applicable for SDHCI_SPEC_300 and above
374 * Versal does not set phase for <=25MHz clock.
375 * If degrees is zero, no need to do anything.
376 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600377 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600378 return 0;
379
380 switch (timing) {
381 case MMC_TIMING_MMC_HS:
382 case MMC_TIMING_SD_HS:
383 case MMC_TIMING_UHS_SDR25:
384 case MMC_TIMING_UHS_DDR50:
385 case MMC_TIMING_MMC_DDR52:
386 /* For 50MHz clock, 120 Taps are available */
387 tap_max = 120;
388 break;
389 case MMC_TIMING_UHS_SDR50:
390 /* For 100MHz clock, 60 Taps are available */
391 tap_max = 60;
392 break;
393 case MMC_TIMING_UHS_SDR104:
394 case MMC_TIMING_MMC_HS200:
395 /* For 200MHz clock, 30 Taps are available */
396 tap_max = 30;
397 default:
398 break;
399 }
400
401 tap_delay = (degrees * tap_max) / 360;
402
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600403 /* Limit input tap_delay value to 8 bits */
404 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600405
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600406 /* Set the Clock Phase */
407 regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
408 regval |= SDHCI_ITAPDLY_CHGWIN;
409 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
410 regval |= SDHCI_ITAPDLY_ENABLE;
411 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
412 regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
413 regval |= tap_delay;
414 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
415 regval &= ~SDHCI_ITAPDLY_CHGWIN;
416 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600417
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600418 return 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600419}
420
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600421static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
422{
423 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
424 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
425 struct mmc *mmc = (struct mmc *)host->mmc;
426 struct udevice *dev = mmc->dev;
427 u8 timing = mode2timing[mmc->selected_mode];
428 u32 iclk_phase = clk_data->clk_phase_in[timing];
429 u32 oclk_phase = clk_data->clk_phase_out[timing];
430
431 dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
432
433 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
434 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
435 sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
436 sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600437 } else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
438 device_is_compatible(dev, "xlnx,versal-8.9a")) {
439 sdhci_versal_sampleclk_set_phase(host, iclk_phase);
440 sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600441 }
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530442}
443
Michal Simek80355ae2020-10-23 04:59:00 -0600444static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
445 const char *prop)
446{
447 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
448 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
449 u32 clk_phase[2] = {0};
450
451 /*
452 * Read Tap Delay values from DT, if the DT does not contain the
453 * Tap Values then use the pre-defined values
454 */
455 if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
456 dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
457 prop, clk_data->clk_phase_in[timing],
458 clk_data->clk_phase_out[timing]);
459 return;
460 }
461
462 /* The values read are Input and Output Clock Delays in order */
463 clk_data->clk_phase_in[timing] = clk_phase[0];
464 clk_data->clk_phase_out[timing] = clk_phase[1];
465}
466
467/**
468 * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
469 *
470 * Called at initialization to parse the values of Tap Delays.
471 *
472 * @dev: Pointer to our struct udevice.
473 */
474static void arasan_dt_parse_clk_phases(struct udevice *dev)
475{
476 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
477 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
478 int i;
479
480 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
481 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
482 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
483 clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
484 clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
485 }
486
487 if (priv->bank == MMC_BANK2) {
488 clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
489 clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
490 }
491 }
492
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600493 if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
494 device_is_compatible(dev, "xlnx,versal-8.9a")) {
495 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
496 clk_data->clk_phase_in[i] = versal_iclk_phases[i];
497 clk_data->clk_phase_out[i] = versal_oclk_phases[i];
498 }
499 }
500
Michal Simek80355ae2020-10-23 04:59:00 -0600501 arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
502 "clk-phase-legacy");
503 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
504 "clk-phase-mmc-hs");
505 arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
506 "clk-phase-sd-hs");
507 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
508 "clk-phase-uhs-sdr12");
509 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
510 "clk-phase-uhs-sdr25");
511 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
512 "clk-phase-uhs-sdr50");
513 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
514 "clk-phase-uhs-sdr104");
515 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
516 "clk-phase-uhs-ddr50");
517 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
518 "clk-phase-mmc-ddr52");
519 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
520 "clk-phase-mmc-hs200");
521 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
522 "clk-phase-mmc-hs400");
523}
524
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530525static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
526{
527 struct mmc *mmc = (struct mmc *)host->mmc;
528 u32 reg;
529
Siva Durga Prasad Paladugu84333702018-05-29 20:03:11 +0530530 if (!IS_SD(mmc))
531 return;
532
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530533 if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530534 reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
535 reg |= SDHCI_CTRL_VDD_180;
536 sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530537 }
538
539 if (mmc->selected_mode > SD_HS &&
Ashok Reddy Somad3d880b2020-10-23 04:59:03 -0600540 mmc->selected_mode <= MMC_HS_200)
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530541 sdhci_set_uhs_timing(host);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530542}
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530543
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530544const struct sdhci_ops arasan_ops = {
Michal Simek0981ef72020-09-14 13:00:40 +0200545 .platform_execute_tuning = &arasan_sdhci_execute_tuning,
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530546 .set_delay = &arasan_sdhci_set_tapdelay,
547 .set_control_reg = &arasan_sdhci_set_control_reg,
548};
549#endif
550
Michal Simekd9ae52c2015-11-30 16:13:03 +0100551static int arasan_sdhci_probe(struct udevice *dev)
Michal Simek293eb332013-04-22 14:56:49 +0200552{
Simon Glassc69cda22020-12-03 16:55:20 -0700553 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Michal Simekd9ae52c2015-11-30 16:13:03 +0100554 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530555 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
556 struct sdhci_host *host;
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100557 struct clk clk;
558 unsigned long clock;
Simon Glass329a4492016-07-05 17:10:15 -0600559 int ret;
Michal Simek293eb332013-04-22 14:56:49 +0200560
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530561 host = priv->host;
562
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100563 ret = clk_get_by_index(dev, 0, &clk);
564 if (ret < 0) {
565 dev_err(dev, "failed to get clock\n");
566 return ret;
567 }
568
569 clock = clk_get_rate(&clk);
570 if (IS_ERR_VALUE(clock)) {
571 dev_err(dev, "failed to get rate\n");
572 return clock;
573 }
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530574
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100575 debug("%s: CLK %ld\n", __func__, clock);
576
577 ret = clk_enable(&clk);
Michal Simek9b7aac72021-02-09 15:28:15 +0100578 if (ret) {
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100579 dev_err(dev, "failed to enable clock\n");
580 return ret;
581 }
582
Siva Durga Prasad Paladugueddabd12014-07-08 15:31:04 +0530583 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
Siva Durga Prasad Paladuguf9ec45d2014-01-22 09:17:09 +0100584 SDHCI_QUIRK_BROKEN_R1B;
Siva Durga Prasad Paladugub2156142016-01-12 15:12:16 +0530585
586#ifdef CONFIG_ZYNQ_HISPD_BROKEN
Hannes Schmelzer47819212018-03-07 08:00:57 +0100587 host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
Siva Durga Prasad Paladugub2156142016-01-12 15:12:16 +0530588#endif
589
Ashok Reddy Soma7a49a162020-10-23 04:58:57 -0600590 if (priv->no_1p8)
591 host->quirks |= SDHCI_QUIRK_NO_1_8_V;
592
Benedikt Grassl942b5fc2020-04-14 07:32:12 +0200593 plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
594
595 ret = mmc_of_parse(dev, &plat->cfg);
596 if (ret)
597 return ret;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530598
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100599 host->max_clk = clock;
Stefan Herbrechtsmeier6d0e34b2017-01-17 15:58:48 +0100600
Matwey V. Kornilov3148a3c2019-08-01 18:00:05 +0300601 host->mmc = &plat->mmc;
602 host->mmc->dev = dev;
603 host->mmc->priv = host;
604
Benedikt Grassl942b5fc2020-04-14 07:32:12 +0200605 ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
Jaehoon Chung14bed522016-07-26 19:06:24 +0900606 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
Simon Glass329a4492016-07-05 17:10:15 -0600607 if (ret)
608 return ret;
Simon Glass329a4492016-07-05 17:10:15 -0600609 upriv->mmc = host->mmc;
Michal Simekd9ae52c2015-11-30 16:13:03 +0100610
Simon Glass329a4492016-07-05 17:10:15 -0600611 return sdhci_probe(dev);
Michal Simek293eb332013-04-22 14:56:49 +0200612}
Michal Simekd9ae52c2015-11-30 16:13:03 +0100613
Simon Glassd1998a92020-12-03 16:55:21 -0700614static int arasan_sdhci_of_to_plat(struct udevice *dev)
Michal Simekd9ae52c2015-11-30 16:13:03 +0100615{
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530616 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
Michal Simekd9ae52c2015-11-30 16:13:03 +0100617
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530618 priv->host = calloc(1, sizeof(struct sdhci_host));
619 if (!priv->host)
620 return -1;
621
622 priv->host->name = dev->name;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530623
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600624#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530625 priv->host->ops = &arasan_ops;
Michal Simek80355ae2020-10-23 04:59:00 -0600626 arasan_dt_parse_clk_phases(dev);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530627#endif
Michal Simekd9ae52c2015-11-30 16:13:03 +0100628
Michal Simek458e8d82018-05-16 10:57:07 +0200629 priv->host->ioaddr = (void *)dev_read_addr(dev);
630 if (IS_ERR(priv->host->ioaddr))
631 return PTR_ERR(priv->host->ioaddr);
Stefan Herbrechtsmeier61e745d2017-01-17 16:27:33 +0100632
Michal Simek458e8d82018-05-16 10:57:07 +0200633 priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
Michal Simeke8deb222020-07-22 17:46:31 +0200634 priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
Ashok Reddy Soma7a49a162020-10-23 04:58:57 -0600635 priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
Michal Simek458e8d82018-05-16 10:57:07 +0200636
Michal Simekd9ae52c2015-11-30 16:13:03 +0100637 return 0;
638}
639
Simon Glass329a4492016-07-05 17:10:15 -0600640static int arasan_sdhci_bind(struct udevice *dev)
641{
Simon Glassc69cda22020-12-03 16:55:20 -0700642 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Simon Glass329a4492016-07-05 17:10:15 -0600643
Masahiro Yamada24f5aec2016-09-06 22:17:32 +0900644 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Simon Glass329a4492016-07-05 17:10:15 -0600645}
646
Michal Simekd9ae52c2015-11-30 16:13:03 +0100647static const struct udevice_id arasan_sdhci_ids[] = {
648 { .compatible = "arasan,sdhci-8.9a" },
649 { }
650};
651
652U_BOOT_DRIVER(arasan_sdhci_drv) = {
653 .name = "arasan_sdhci",
654 .id = UCLASS_MMC,
655 .of_match = arasan_sdhci_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700656 .of_to_plat = arasan_sdhci_of_to_plat,
Simon Glass329a4492016-07-05 17:10:15 -0600657 .ops = &sdhci_ops,
658 .bind = arasan_sdhci_bind,
Michal Simekd9ae52c2015-11-30 16:13:03 +0100659 .probe = arasan_sdhci_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700660 .priv_auto = sizeof(struct arasan_sdhci_priv),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700661 .plat_auto = sizeof(struct arasan_sdhci_plat),
Michal Simekd9ae52c2015-11-30 16:13:03 +0100662};