blob: ba87ee8dd5bd12c520da8e0c720d6f5bee7b3578 [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 */
Michal Simek419b4a82021-07-09 05:53:44 -060053static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0,
54 0, 183, 54, 0, 0};
55static const u32 zynqmp_oclk_phases[] = {0, 72, 60, 0, 60, 72,
56 135, 48, 72, 135, 0};
Michal Simek80355ae2020-10-23 04:59:00 -060057
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -060058/* Default settings for Versal Clock Phases */
Michal Simek419b4a82021-07-09 05:53:44 -060059static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132,
60 0, 0, 162, 90, 0, 0};
61static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72,
62 90, 36, 60, 90, 0};
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -060063
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053064static const u8 mode2timing[] = {
Ashok Reddy Soma17a42ab2020-10-23 04:58:58 -060065 [MMC_LEGACY] = MMC_TIMING_LEGACY,
66 [MMC_HS] = MMC_TIMING_MMC_HS,
67 [SD_HS] = MMC_TIMING_SD_HS,
68 [MMC_HS_52] = MMC_TIMING_UHS_SDR50,
69 [MMC_DDR_52] = MMC_TIMING_UHS_DDR50,
70 [UHS_SDR12] = MMC_TIMING_UHS_SDR12,
71 [UHS_SDR25] = MMC_TIMING_UHS_SDR25,
72 [UHS_SDR50] = MMC_TIMING_UHS_SDR50,
73 [UHS_DDR50] = MMC_TIMING_UHS_DDR50,
74 [UHS_SDR104] = MMC_TIMING_UHS_SDR104,
75 [MMC_HS_200] = MMC_TIMING_MMC_HS200,
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053076};
77
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +053078static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u8 deviceid)
79{
80 u16 clk;
81 unsigned long timeout;
82
83 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
84 clk &= ~(SDHCI_CLOCK_CARD_EN);
85 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
86
87 /* Issue DLL Reset */
88 zynqmp_dll_reset(deviceid);
89
90 /* Wait max 20 ms */
91 timeout = 100;
92 while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
93 & SDHCI_CLOCK_INT_STABLE)) {
94 if (timeout == 0) {
95 dev_err(mmc_dev(host->mmc),
96 ": Internal clock never stabilised.\n");
97 return;
98 }
99 timeout--;
100 udelay(1000);
101 }
102
103 clk |= SDHCI_CLOCK_CARD_EN;
104 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
105}
106
107static int arasan_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
108{
109 struct mmc_cmd cmd;
110 struct mmc_data data;
111 u32 ctrl;
112 struct sdhci_host *host;
113 struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
Michal Simekb6911782018-06-13 09:12:29 +0200114 char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530115 u8 deviceid;
116
117 debug("%s\n", __func__);
118
119 host = priv->host;
120 deviceid = priv->deviceid;
121
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530122 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530123 ctrl |= SDHCI_CTRL_EXEC_TUNING;
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530124 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530125
126 mdelay(1);
127
128 arasan_zynqmp_dll_reset(host, deviceid);
129
130 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
131 sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
132
133 do {
134 cmd.cmdidx = opcode;
135 cmd.resp_type = MMC_RSP_R1;
136 cmd.cmdarg = 0;
137
138 data.blocksize = 64;
139 data.blocks = 1;
140 data.flags = MMC_DATA_READ;
141
142 if (tuning_loop_counter-- == 0)
143 break;
144
145 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200 &&
146 mmc->bus_width == 8)
147 data.blocksize = 128;
148
149 sdhci_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG,
150 data.blocksize),
151 SDHCI_BLOCK_SIZE);
152 sdhci_writew(host, data.blocks, SDHCI_BLOCK_COUNT);
153 sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
154
155 mmc_send_cmd(mmc, &cmd, NULL);
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530156 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530157
158 if (cmd.cmdidx == MMC_CMD_SEND_TUNING_BLOCK)
159 udelay(1);
160
161 } while (ctrl & SDHCI_CTRL_EXEC_TUNING);
162
163 if (tuning_loop_counter < 0) {
164 ctrl &= ~SDHCI_CTRL_TUNED_CLK;
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530165 sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530166 }
167
168 if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
169 printf("%s:Tuning failed\n", __func__);
170 return -1;
171 }
172
173 udelay(1);
174 arasan_zynqmp_dll_reset(host, deviceid);
175
176 /* Enable only interrupts served by the SD controller */
177 sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK,
178 SDHCI_INT_ENABLE);
179 /* Mask all sdhci interrupt sources */
180 sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
181
182 return 0;
183}
184
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600185/**
186 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
187 *
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600188 * @host: Pointer to the sdhci_host structure.
189 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600190 * Return: 0
Michal Simekc0436fc2021-07-09 05:53:43 -0600191 *
192 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600193 */
194static int sdhci_zynqmp_sdcardclk_set_phase(struct sdhci_host *host,
195 int degrees)
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530196{
197 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
198 struct mmc *mmc = (struct mmc *)host->mmc;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600199 u8 tap_delay, tap_max = 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600200 int timing = mode2timing[mmc->selected_mode];
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530201
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600202 /*
203 * This is applicable for SDHCI_SPEC_300 and above
204 * ZynqMP does not set phase for <=25MHz clock.
205 * If degrees is zero, no need to do anything.
206 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600207 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600208 return 0;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530209
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600210 switch (timing) {
211 case MMC_TIMING_MMC_HS:
212 case MMC_TIMING_SD_HS:
213 case MMC_TIMING_UHS_SDR25:
214 case MMC_TIMING_UHS_DDR50:
215 case MMC_TIMING_MMC_DDR52:
216 /* For 50MHz clock, 30 Taps are available */
217 tap_max = 30;
218 break;
219 case MMC_TIMING_UHS_SDR50:
220 /* For 100MHz clock, 15 Taps are available */
221 tap_max = 15;
222 break;
223 case MMC_TIMING_UHS_SDR104:
224 case MMC_TIMING_MMC_HS200:
225 /* For 200MHz clock, 8 Taps are available */
226 tap_max = 8;
227 default:
228 break;
229 }
230
231 tap_delay = (degrees * tap_max) / 360;
232
Ashok Reddy Somaa70bdaf2021-07-09 05:53:42 -0600233 /* Limit output tap_delay value to 6 bits */
234 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
235
236 arasan_zynqmp_set_out_tapdelay(priv->deviceid, tap_delay);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600237
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600238 return 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600239}
240
241/**
242 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
243 *
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600244 * @host: Pointer to the sdhci_host structure.
245 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600246 * Return: 0
Michal Simekc0436fc2021-07-09 05:53:43 -0600247 *
248 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600249 */
250static int sdhci_zynqmp_sampleclk_set_phase(struct sdhci_host *host,
251 int degrees)
252{
253 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
254 struct mmc *mmc = (struct mmc *)host->mmc;
255 u8 tap_delay, tap_max = 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600256 int timing = mode2timing[mmc->selected_mode];
257
258 /*
259 * This is applicable for SDHCI_SPEC_300 and above
260 * ZynqMP does not set phase for <=25MHz clock.
261 * If degrees is zero, no need to do anything.
262 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600263 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600264 return 0;
265
266 switch (timing) {
267 case MMC_TIMING_MMC_HS:
268 case MMC_TIMING_SD_HS:
269 case MMC_TIMING_UHS_SDR25:
270 case MMC_TIMING_UHS_DDR50:
271 case MMC_TIMING_MMC_DDR52:
272 /* For 50MHz clock, 120 Taps are available */
273 tap_max = 120;
274 break;
275 case MMC_TIMING_UHS_SDR50:
276 /* For 100MHz clock, 60 Taps are available */
277 tap_max = 60;
278 break;
279 case MMC_TIMING_UHS_SDR104:
280 case MMC_TIMING_MMC_HS200:
281 /* For 200MHz clock, 30 Taps are available */
282 tap_max = 30;
283 default:
284 break;
285 }
286
287 tap_delay = (degrees * tap_max) / 360;
288
Ashok Reddy Somaa70bdaf2021-07-09 05:53:42 -0600289 /* Limit input tap_delay value to 8 bits */
290 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
291
292 arasan_zynqmp_set_in_tapdelay(priv->deviceid, tap_delay);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600293
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600294 return 0;
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600295}
296
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600297/**
298 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
299 *
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600300 * @host: Pointer to the sdhci_host structure.
Michal Simekc0436fc2021-07-09 05:53:43 -0600301 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600302 * Return: 0
Michal Simekc0436fc2021-07-09 05:53:43 -0600303 *
304 * Set the SD Output Clock Tap Delays for Output path
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600305 */
306static int sdhci_versal_sdcardclk_set_phase(struct sdhci_host *host,
307 int degrees)
308{
309 struct mmc *mmc = (struct mmc *)host->mmc;
310 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600311 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600312 u32 regval;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600313
314 /*
315 * This is applicable for SDHCI_SPEC_300 and above
316 * Versal does not set phase for <=25MHz clock.
317 * If degrees is zero, no need to do anything.
318 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600319 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600320 return 0;
321
322 switch (timing) {
323 case MMC_TIMING_MMC_HS:
324 case MMC_TIMING_SD_HS:
325 case MMC_TIMING_UHS_SDR25:
326 case MMC_TIMING_UHS_DDR50:
327 case MMC_TIMING_MMC_DDR52:
328 /* For 50MHz clock, 30 Taps are available */
329 tap_max = 30;
330 break;
331 case MMC_TIMING_UHS_SDR50:
332 /* For 100MHz clock, 15 Taps are available */
333 tap_max = 15;
334 break;
335 case MMC_TIMING_UHS_SDR104:
336 case MMC_TIMING_MMC_HS200:
337 /* For 200MHz clock, 8 Taps are available */
338 tap_max = 8;
339 default:
340 break;
341 }
342
343 tap_delay = (degrees * tap_max) / 360;
344
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600345 /* Limit output tap_delay value to 6 bits */
346 tap_delay &= SDHCI_ARASAN_OTAPDLY_SEL_MASK;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600347
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600348 /* Set the Clock Phase */
349 regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
350 regval |= SDHCI_OTAPDLY_ENABLE;
351 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
352 regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
353 regval |= tap_delay;
354 sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600355
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600356 return 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600357}
358
359/**
360 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
361 *
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600362 * @host: Pointer to the sdhci_host structure.
Michal Simekc0436fc2021-07-09 05:53:43 -0600363 * @degrees: The clock phase shift between 0 - 359.
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600364 * Return: 0
Michal Simekc0436fc2021-07-09 05:53:43 -0600365 *
366 * Set the SD Input Clock Tap Delays for Input path
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600367 */
368static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host,
369 int degrees)
370{
371 struct mmc *mmc = (struct mmc *)host->mmc;
372 u8 tap_delay, tap_max = 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600373 int timing = mode2timing[mmc->selected_mode];
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600374 u32 regval;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600375
376 /*
377 * This is applicable for SDHCI_SPEC_300 and above
378 * Versal does not set phase for <=25MHz clock.
379 * If degrees is zero, no need to do anything.
380 */
Ashok Reddy Somaaffcba72021-07-09 05:53:40 -0600381 if (SDHCI_GET_VERSION(host) < SDHCI_SPEC_300)
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600382 return 0;
383
384 switch (timing) {
385 case MMC_TIMING_MMC_HS:
386 case MMC_TIMING_SD_HS:
387 case MMC_TIMING_UHS_SDR25:
388 case MMC_TIMING_UHS_DDR50:
389 case MMC_TIMING_MMC_DDR52:
390 /* For 50MHz clock, 120 Taps are available */
391 tap_max = 120;
392 break;
393 case MMC_TIMING_UHS_SDR50:
394 /* For 100MHz clock, 60 Taps are available */
395 tap_max = 60;
396 break;
397 case MMC_TIMING_UHS_SDR104:
398 case MMC_TIMING_MMC_HS200:
399 /* For 200MHz clock, 30 Taps are available */
400 tap_max = 30;
401 default:
402 break;
403 }
404
405 tap_delay = (degrees * tap_max) / 360;
406
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600407 /* Limit input tap_delay value to 8 bits */
408 tap_delay &= SDHCI_ARASAN_ITAPDLY_SEL_MASK;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600409
Ashok Reddy Somaee9ae002021-07-09 05:53:41 -0600410 /* Set the Clock Phase */
411 regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
412 regval |= SDHCI_ITAPDLY_CHGWIN;
413 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
414 regval |= SDHCI_ITAPDLY_ENABLE;
415 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
416 regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
417 regval |= tap_delay;
418 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
419 regval &= ~SDHCI_ITAPDLY_CHGWIN;
420 sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600421
Ashok Reddy Soma8e34aa02021-07-09 05:53:39 -0600422 return 0;
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600423}
424
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600425static void arasan_sdhci_set_tapdelay(struct sdhci_host *host)
426{
427 struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev);
428 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
429 struct mmc *mmc = (struct mmc *)host->mmc;
430 struct udevice *dev = mmc->dev;
431 u8 timing = mode2timing[mmc->selected_mode];
432 u32 iclk_phase = clk_data->clk_phase_in[timing];
433 u32 oclk_phase = clk_data->clk_phase_out[timing];
434
435 dev_dbg(dev, "%s, host:%s, mode:%d\n", __func__, host->name, timing);
436
437 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
438 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
439 sdhci_zynqmp_sampleclk_set_phase(host, iclk_phase);
440 sdhci_zynqmp_sdcardclk_set_phase(host, oclk_phase);
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600441 } else if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
442 device_is_compatible(dev, "xlnx,versal-8.9a")) {
443 sdhci_versal_sampleclk_set_phase(host, iclk_phase);
444 sdhci_versal_sdcardclk_set_phase(host, oclk_phase);
Ashok Reddy Somaf4b297b2020-10-23 04:59:01 -0600445 }
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530446}
447
Michal Simek80355ae2020-10-23 04:59:00 -0600448static void arasan_dt_read_clk_phase(struct udevice *dev, unsigned char timing,
449 const char *prop)
450{
451 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
452 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
453 u32 clk_phase[2] = {0};
454
455 /*
456 * Read Tap Delay values from DT, if the DT does not contain the
457 * Tap Values then use the pre-defined values
458 */
459 if (dev_read_u32_array(dev, prop, &clk_phase[0], 2)) {
460 dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
461 prop, clk_data->clk_phase_in[timing],
462 clk_data->clk_phase_out[timing]);
463 return;
464 }
465
466 /* The values read are Input and Output Clock Delays in order */
467 clk_data->clk_phase_in[timing] = clk_phase[0];
468 clk_data->clk_phase_out[timing] = clk_phase[1];
469}
470
471/**
472 * arasan_dt_parse_clk_phases - Read Tap Delay values from DT
473 *
Michal Simek80355ae2020-10-23 04:59:00 -0600474 * @dev: Pointer to our struct udevice.
Michal Simekc0436fc2021-07-09 05:53:43 -0600475 *
476 * Called at initialization to parse the values of Tap Delays.
Michal Simek80355ae2020-10-23 04:59:00 -0600477 */
478static void arasan_dt_parse_clk_phases(struct udevice *dev)
479{
480 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
481 struct arasan_sdhci_clk_data *clk_data = &priv->clk_data;
482 int i;
483
484 if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) &&
485 device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
486 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
487 clk_data->clk_phase_in[i] = zynqmp_iclk_phases[i];
488 clk_data->clk_phase_out[i] = zynqmp_oclk_phases[i];
489 }
490
491 if (priv->bank == MMC_BANK2) {
492 clk_data->clk_phase_out[MMC_TIMING_UHS_SDR104] = 90;
493 clk_data->clk_phase_out[MMC_TIMING_MMC_HS200] = 90;
494 }
495 }
496
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600497 if (IS_ENABLED(CONFIG_ARCH_VERSAL) &&
498 device_is_compatible(dev, "xlnx,versal-8.9a")) {
499 for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
500 clk_data->clk_phase_in[i] = versal_iclk_phases[i];
501 clk_data->clk_phase_out[i] = versal_oclk_phases[i];
502 }
503 }
504
Michal Simek80355ae2020-10-23 04:59:00 -0600505 arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY,
506 "clk-phase-legacy");
507 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
508 "clk-phase-mmc-hs");
509 arasan_dt_read_clk_phase(dev, MMC_TIMING_SD_HS,
510 "clk-phase-sd-hs");
511 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR12,
512 "clk-phase-uhs-sdr12");
513 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR25,
514 "clk-phase-uhs-sdr25");
515 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR50,
516 "clk-phase-uhs-sdr50");
517 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_SDR104,
518 "clk-phase-uhs-sdr104");
519 arasan_dt_read_clk_phase(dev, MMC_TIMING_UHS_DDR50,
520 "clk-phase-uhs-ddr50");
521 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_DDR52,
522 "clk-phase-mmc-ddr52");
523 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS200,
524 "clk-phase-mmc-hs200");
525 arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS400,
526 "clk-phase-mmc-hs400");
527}
528
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530529static void arasan_sdhci_set_control_reg(struct sdhci_host *host)
530{
531 struct mmc *mmc = (struct mmc *)host->mmc;
532 u32 reg;
533
Siva Durga Prasad Paladugu84333702018-05-29 20:03:11 +0530534 if (!IS_SD(mmc))
535 return;
536
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530537 if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530538 reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
539 reg |= SDHCI_CTRL_VDD_180;
540 sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530541 }
542
543 if (mmc->selected_mode > SD_HS &&
Ashok Reddy Somad3d880b2020-10-23 04:59:03 -0600544 mmc->selected_mode <= MMC_HS_200)
Faiz Abbasd1c0a222019-06-11 00:43:40 +0530545 sdhci_set_uhs_timing(host);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530546}
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530547
Michal Simek419b4a82021-07-09 05:53:44 -0600548static const struct sdhci_ops arasan_ops = {
549 .platform_execute_tuning = &arasan_sdhci_execute_tuning,
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530550 .set_delay = &arasan_sdhci_set_tapdelay,
551 .set_control_reg = &arasan_sdhci_set_control_reg,
552};
553#endif
554
Michal Simekd9ae52c2015-11-30 16:13:03 +0100555static int arasan_sdhci_probe(struct udevice *dev)
Michal Simek293eb332013-04-22 14:56:49 +0200556{
Simon Glassc69cda22020-12-03 16:55:20 -0700557 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Michal Simekd9ae52c2015-11-30 16:13:03 +0100558 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530559 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
560 struct sdhci_host *host;
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100561 struct clk clk;
562 unsigned long clock;
Simon Glass329a4492016-07-05 17:10:15 -0600563 int ret;
Michal Simek293eb332013-04-22 14:56:49 +0200564
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530565 host = priv->host;
566
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100567 ret = clk_get_by_index(dev, 0, &clk);
568 if (ret < 0) {
569 dev_err(dev, "failed to get clock\n");
570 return ret;
571 }
572
573 clock = clk_get_rate(&clk);
574 if (IS_ERR_VALUE(clock)) {
575 dev_err(dev, "failed to get rate\n");
576 return clock;
577 }
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530578
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100579 debug("%s: CLK %ld\n", __func__, clock);
580
581 ret = clk_enable(&clk);
Michal Simek9b7aac72021-02-09 15:28:15 +0100582 if (ret) {
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100583 dev_err(dev, "failed to enable clock\n");
584 return ret;
585 }
586
Siva Durga Prasad Paladugueddabd12014-07-08 15:31:04 +0530587 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD |
Siva Durga Prasad Paladuguf9ec45d2014-01-22 09:17:09 +0100588 SDHCI_QUIRK_BROKEN_R1B;
Siva Durga Prasad Paladugub2156142016-01-12 15:12:16 +0530589
590#ifdef CONFIG_ZYNQ_HISPD_BROKEN
Hannes Schmelzer47819212018-03-07 08:00:57 +0100591 host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE;
Siva Durga Prasad Paladugub2156142016-01-12 15:12:16 +0530592#endif
593
Ashok Reddy Soma7a49a162020-10-23 04:58:57 -0600594 if (priv->no_1p8)
595 host->quirks |= SDHCI_QUIRK_NO_1_8_V;
596
Benedikt Grassl942b5fc2020-04-14 07:32:12 +0200597 plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
598
599 ret = mmc_of_parse(dev, &plat->cfg);
600 if (ret)
601 return ret;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530602
Stefan Herbrechtsmeiere0f4de12017-01-17 16:27:32 +0100603 host->max_clk = clock;
Stefan Herbrechtsmeier6d0e34b2017-01-17 15:58:48 +0100604
Matwey V. Kornilov3148a3c2019-08-01 18:00:05 +0300605 host->mmc = &plat->mmc;
606 host->mmc->dev = dev;
607 host->mmc->priv = host;
608
Benedikt Grassl942b5fc2020-04-14 07:32:12 +0200609 ret = sdhci_setup_cfg(&plat->cfg, host, plat->cfg.f_max,
Jaehoon Chung14bed522016-07-26 19:06:24 +0900610 CONFIG_ZYNQ_SDHCI_MIN_FREQ);
Simon Glass329a4492016-07-05 17:10:15 -0600611 if (ret)
612 return ret;
Simon Glass329a4492016-07-05 17:10:15 -0600613 upriv->mmc = host->mmc;
Michal Simekd9ae52c2015-11-30 16:13:03 +0100614
Simon Glass329a4492016-07-05 17:10:15 -0600615 return sdhci_probe(dev);
Michal Simek293eb332013-04-22 14:56:49 +0200616}
Michal Simekd9ae52c2015-11-30 16:13:03 +0100617
Simon Glassd1998a92020-12-03 16:55:21 -0700618static int arasan_sdhci_of_to_plat(struct udevice *dev)
Michal Simekd9ae52c2015-11-30 16:13:03 +0100619{
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530620 struct arasan_sdhci_priv *priv = dev_get_priv(dev);
Michal Simekd9ae52c2015-11-30 16:13:03 +0100621
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530622 priv->host = calloc(1, sizeof(struct sdhci_host));
623 if (!priv->host)
624 return -1;
625
626 priv->host->name = dev->name;
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530627
Ashok Reddy Soma2e819a72020-10-23 04:59:02 -0600628#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL)
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530629 priv->host->ops = &arasan_ops;
Michal Simek80355ae2020-10-23 04:59:00 -0600630 arasan_dt_parse_clk_phases(dev);
Siva Durga Prasad Paladugud1f4e392018-04-19 12:37:09 +0530631#endif
Michal Simekd9ae52c2015-11-30 16:13:03 +0100632
Michal Simek458e8d82018-05-16 10:57:07 +0200633 priv->host->ioaddr = (void *)dev_read_addr(dev);
634 if (IS_ERR(priv->host->ioaddr))
635 return PTR_ERR(priv->host->ioaddr);
Stefan Herbrechtsmeier61e745d2017-01-17 16:27:33 +0100636
Michal Simek458e8d82018-05-16 10:57:07 +0200637 priv->deviceid = dev_read_u32_default(dev, "xlnx,device_id", -1);
Michal Simeke8deb222020-07-22 17:46:31 +0200638 priv->bank = dev_read_u32_default(dev, "xlnx,mio-bank", 0);
Ashok Reddy Soma7a49a162020-10-23 04:58:57 -0600639 priv->no_1p8 = dev_read_bool(dev, "no-1-8-v");
Michal Simek458e8d82018-05-16 10:57:07 +0200640
Michal Simekd9ae52c2015-11-30 16:13:03 +0100641 return 0;
642}
643
Simon Glass329a4492016-07-05 17:10:15 -0600644static int arasan_sdhci_bind(struct udevice *dev)
645{
Simon Glassc69cda22020-12-03 16:55:20 -0700646 struct arasan_sdhci_plat *plat = dev_get_plat(dev);
Simon Glass329a4492016-07-05 17:10:15 -0600647
Masahiro Yamada24f5aec2016-09-06 22:17:32 +0900648 return sdhci_bind(dev, &plat->mmc, &plat->cfg);
Simon Glass329a4492016-07-05 17:10:15 -0600649}
650
Michal Simekd9ae52c2015-11-30 16:13:03 +0100651static const struct udevice_id arasan_sdhci_ids[] = {
652 { .compatible = "arasan,sdhci-8.9a" },
653 { }
654};
655
656U_BOOT_DRIVER(arasan_sdhci_drv) = {
657 .name = "arasan_sdhci",
658 .id = UCLASS_MMC,
659 .of_match = arasan_sdhci_ids,
Simon Glassd1998a92020-12-03 16:55:21 -0700660 .of_to_plat = arasan_sdhci_of_to_plat,
Simon Glass329a4492016-07-05 17:10:15 -0600661 .ops = &sdhci_ops,
662 .bind = arasan_sdhci_bind,
Michal Simekd9ae52c2015-11-30 16:13:03 +0100663 .probe = arasan_sdhci_probe,
Simon Glass41575d82020-12-03 16:55:17 -0700664 .priv_auto = sizeof(struct arasan_sdhci_priv),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700665 .plat_auto = sizeof(struct arasan_sdhci_plat),
Michal Simekd9ae52c2015-11-30 16:13:03 +0100666};