.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Arasan Secure Digital Host Controller Interface. |
---|
3 | 4 | * Copyright (C) 2011 - 2012 Michal Simek <monstr@monstr.eu> |
---|
.. | .. |
---|
12 | 13 | * |
---|
13 | 14 | * Authors: Xiaobo Xie <X.Xie@freescale.com> |
---|
14 | 15 | * Anton Vorontsov <avorontsov@ru.mvista.com> |
---|
15 | | - * |
---|
16 | | - * This program is free software; you can redistribute it and/or modify |
---|
17 | | - * it under the terms of the GNU General Public License as published by |
---|
18 | | - * the Free Software Foundation; either version 2 of the License, or (at |
---|
19 | | - * your option) any later version. |
---|
20 | 16 | */ |
---|
21 | 17 | |
---|
22 | 18 | #include <linux/clk-provider.h> |
---|
.. | .. |
---|
26 | 22 | #include <linux/phy/phy.h> |
---|
27 | 23 | #include <linux/regmap.h> |
---|
28 | 24 | #include <linux/of.h> |
---|
| 25 | +#include <linux/firmware/xlnx-zynqmp.h> |
---|
29 | 26 | |
---|
30 | 27 | #include "cqhci.h" |
---|
| 28 | +#include "sdhci-cqhci.h" |
---|
31 | 29 | #include "sdhci-pltfm.h" |
---|
32 | 30 | |
---|
33 | 31 | #define SDHCI_ARASAN_VENDOR_REGISTER 0x78 |
---|
| 32 | + |
---|
| 33 | +#define SDHCI_ARASAN_ITAPDLY_REGISTER 0xF0F8 |
---|
| 34 | +#define SDHCI_ARASAN_ITAPDLY_SEL_MASK 0xFF |
---|
| 35 | + |
---|
| 36 | +#define SDHCI_ARASAN_OTAPDLY_REGISTER 0xF0FC |
---|
| 37 | +#define SDHCI_ARASAN_OTAPDLY_SEL_MASK 0x3F |
---|
| 38 | + |
---|
34 | 39 | #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200 |
---|
35 | 40 | #define VENDOR_ENHANCED_STROBE BIT(0) |
---|
36 | 41 | |
---|
37 | 42 | #define PHY_CLK_TOO_SLOW_HZ 400000 |
---|
| 43 | + |
---|
| 44 | +#define SDHCI_ITAPDLY_CHGWIN 0x200 |
---|
| 45 | +#define SDHCI_ITAPDLY_ENABLE 0x100 |
---|
| 46 | +#define SDHCI_OTAPDLY_ENABLE 0x40 |
---|
| 47 | + |
---|
| 48 | +/* Default settings for ZynqMP Clock Phases */ |
---|
| 49 | +#define ZYNQMP_ICLK_PHASE {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0} |
---|
| 50 | +#define ZYNQMP_OCLK_PHASE {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0} |
---|
| 51 | + |
---|
| 52 | +#define VERSAL_ICLK_PHASE {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0} |
---|
| 53 | +#define VERSAL_OCLK_PHASE {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0} |
---|
38 | 54 | |
---|
39 | 55 | /* |
---|
40 | 56 | * On some SoCs the syscon area has a feature where the upper 16-bits of |
---|
.. | .. |
---|
61 | 77 | /** |
---|
62 | 78 | * struct sdhci_arasan_soc_ctl_map - Map in syscon to corecfg registers |
---|
63 | 79 | * |
---|
| 80 | + * @baseclkfreq: Where to find corecfg_baseclkfreq |
---|
| 81 | + * @clockmultiplier: Where to find corecfg_clockmultiplier |
---|
| 82 | + * @support64b: Where to find SUPPORT64B bit |
---|
| 83 | + * @hiword_update: If true, use HIWORD_UPDATE to access the syscon |
---|
| 84 | + * |
---|
64 | 85 | * It's up to the licensee of the Arsan IP block to make these available |
---|
65 | 86 | * somewhere if needed. Presumably these will be scattered somewhere that's |
---|
66 | 87 | * accessible via the syscon API. |
---|
67 | | - * |
---|
68 | | - * @baseclkfreq: Where to find corecfg_baseclkfreq |
---|
69 | | - * @clockmultiplier: Where to find corecfg_clockmultiplier |
---|
70 | | - * @hiword_update: If true, use HIWORD_UPDATE to access the syscon |
---|
71 | 88 | */ |
---|
72 | 89 | struct sdhci_arasan_soc_ctl_map { |
---|
73 | 90 | struct sdhci_arasan_soc_ctl_field baseclkfreq; |
---|
74 | 91 | struct sdhci_arasan_soc_ctl_field clockmultiplier; |
---|
| 92 | + struct sdhci_arasan_soc_ctl_field support64b; |
---|
75 | 93 | bool hiword_update; |
---|
76 | 94 | }; |
---|
77 | 95 | |
---|
78 | 96 | /** |
---|
79 | | - * struct sdhci_arasan_data |
---|
| 97 | + * struct sdhci_arasan_clk_ops - Clock Operations for Arasan SD controller |
---|
| 98 | + * |
---|
| 99 | + * @sdcardclk_ops: The output clock related operations |
---|
| 100 | + * @sampleclk_ops: The sample clock related operations |
---|
| 101 | + */ |
---|
| 102 | +struct sdhci_arasan_clk_ops { |
---|
| 103 | + const struct clk_ops *sdcardclk_ops; |
---|
| 104 | + const struct clk_ops *sampleclk_ops; |
---|
| 105 | +}; |
---|
| 106 | + |
---|
| 107 | +/** |
---|
| 108 | + * struct sdhci_arasan_clk_data - Arasan Controller Clock Data. |
---|
| 109 | + * |
---|
| 110 | + * @sdcardclk_hw: Struct for the clock we might provide to a PHY. |
---|
| 111 | + * @sdcardclk: Pointer to normal 'struct clock' for sdcardclk_hw. |
---|
| 112 | + * @sampleclk_hw: Struct for the clock we might provide to a PHY. |
---|
| 113 | + * @sampleclk: Pointer to normal 'struct clock' for sampleclk_hw. |
---|
| 114 | + * @clk_phase_in: Array of Input Clock Phase Delays for all speed modes |
---|
| 115 | + * @clk_phase_out: Array of Output Clock Phase Delays for all speed modes |
---|
| 116 | + * @set_clk_delays: Function pointer for setting Clock Delays |
---|
| 117 | + * @clk_of_data: Platform specific runtime clock data storage pointer |
---|
| 118 | + */ |
---|
| 119 | +struct sdhci_arasan_clk_data { |
---|
| 120 | + struct clk_hw sdcardclk_hw; |
---|
| 121 | + struct clk *sdcardclk; |
---|
| 122 | + struct clk_hw sampleclk_hw; |
---|
| 123 | + struct clk *sampleclk; |
---|
| 124 | + int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; |
---|
| 125 | + int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; |
---|
| 126 | + void (*set_clk_delays)(struct sdhci_host *host); |
---|
| 127 | + void *clk_of_data; |
---|
| 128 | +}; |
---|
| 129 | + |
---|
| 130 | +/** |
---|
| 131 | + * struct sdhci_arasan_data - Arasan Controller Data |
---|
| 132 | + * |
---|
80 | 133 | * @host: Pointer to the main SDHCI host structure. |
---|
81 | 134 | * @clk_ahb: Pointer to the AHB clock |
---|
82 | 135 | * @phy: Pointer to the generic phy |
---|
83 | 136 | * @is_phy_on: True if the PHY is on; false if not. |
---|
84 | | - * @sdcardclk_hw: Struct for the clock we might provide to a PHY. |
---|
85 | | - * @sdcardclk: Pointer to normal 'struct clock' for sdcardclk_hw. |
---|
| 137 | + * @has_cqe: True if controller has command queuing engine. |
---|
| 138 | + * @clk_data: Struct for the Arasan Controller Clock Data. |
---|
| 139 | + * @clk_ops: Struct for the Arasan Controller Clock Operations. |
---|
86 | 140 | * @soc_ctl_base: Pointer to regmap for syscon for soc_ctl registers. |
---|
87 | 141 | * @soc_ctl_map: Map to get offsets into soc_ctl registers. |
---|
| 142 | + * @quirks: Arasan deviations from spec. |
---|
88 | 143 | */ |
---|
89 | 144 | struct sdhci_arasan_data { |
---|
90 | 145 | struct sdhci_host *host; |
---|
.. | .. |
---|
93 | 148 | bool is_phy_on; |
---|
94 | 149 | |
---|
95 | 150 | bool has_cqe; |
---|
96 | | - struct clk_hw sdcardclk_hw; |
---|
97 | | - struct clk *sdcardclk; |
---|
| 151 | + struct sdhci_arasan_clk_data clk_data; |
---|
| 152 | + const struct sdhci_arasan_clk_ops *clk_ops; |
---|
98 | 153 | |
---|
99 | 154 | struct regmap *soc_ctl_base; |
---|
100 | 155 | const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; |
---|
101 | | - unsigned int quirks; /* Arasan deviations from spec */ |
---|
| 156 | + unsigned int quirks; |
---|
102 | 157 | |
---|
103 | 158 | /* Controller does not have CD wired and will not function normally without */ |
---|
104 | 159 | #define SDHCI_ARASAN_QUIRK_FORCE_CDTEST BIT(0) |
---|
105 | 160 | /* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the |
---|
106 | 161 | * internal clock even when the clock isn't stable */ |
---|
107 | 162 | #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1) |
---|
| 163 | +/* |
---|
| 164 | + * Some of the Arasan variations might not have timing requirements |
---|
| 165 | + * met at 25MHz for Default Speed mode, those controllers work at |
---|
| 166 | + * 19MHz instead |
---|
| 167 | + */ |
---|
| 168 | +#define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2) |
---|
| 169 | +}; |
---|
| 170 | + |
---|
| 171 | +struct sdhci_arasan_of_data { |
---|
| 172 | + const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; |
---|
| 173 | + const struct sdhci_pltfm_data *pdata; |
---|
| 174 | + const struct sdhci_arasan_clk_ops *clk_ops; |
---|
108 | 175 | }; |
---|
109 | 176 | |
---|
110 | 177 | static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = { |
---|
.. | .. |
---|
113 | 180 | .hiword_update = true, |
---|
114 | 181 | }; |
---|
115 | 182 | |
---|
| 183 | +static const struct sdhci_arasan_soc_ctl_map intel_lgm_emmc_soc_ctl_map = { |
---|
| 184 | + .baseclkfreq = { .reg = 0xa0, .width = 8, .shift = 2 }, |
---|
| 185 | + .clockmultiplier = { .reg = 0, .width = -1, .shift = -1 }, |
---|
| 186 | + .hiword_update = false, |
---|
| 187 | +}; |
---|
| 188 | + |
---|
| 189 | +static const struct sdhci_arasan_soc_ctl_map intel_lgm_sdxc_soc_ctl_map = { |
---|
| 190 | + .baseclkfreq = { .reg = 0x80, .width = 8, .shift = 2 }, |
---|
| 191 | + .clockmultiplier = { .reg = 0, .width = -1, .shift = -1 }, |
---|
| 192 | + .hiword_update = false, |
---|
| 193 | +}; |
---|
| 194 | + |
---|
| 195 | +static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map = { |
---|
| 196 | + .baseclkfreq = { .reg = 0x0, .width = 8, .shift = 14 }, |
---|
| 197 | + .clockmultiplier = { .reg = 0x4, .width = 8, .shift = 14 }, |
---|
| 198 | + .support64b = { .reg = 0x4, .width = 1, .shift = 24 }, |
---|
| 199 | + .hiword_update = false, |
---|
| 200 | +}; |
---|
| 201 | + |
---|
116 | 202 | /** |
---|
117 | 203 | * sdhci_arasan_syscon_write - Write to a field in soc_ctl registers |
---|
| 204 | + * |
---|
| 205 | + * @host: The sdhci_host |
---|
| 206 | + * @fld: The field to write to |
---|
| 207 | + * @val: The value to write |
---|
118 | 208 | * |
---|
119 | 209 | * This function allows writing to fields in sdhci_arasan_soc_ctl_map. |
---|
120 | 210 | * Note that if a field is specified as not available (shift < 0) then |
---|
121 | 211 | * this function will silently return an error code. It will be noisy |
---|
122 | 212 | * and print errors for any other (unexpected) errors. |
---|
123 | 213 | * |
---|
124 | | - * @host: The sdhci_host |
---|
125 | | - * @fld: The field to write to |
---|
126 | | - * @val: The value to write |
---|
| 214 | + * Return: 0 on success and error value on error |
---|
127 | 215 | */ |
---|
128 | 216 | static int sdhci_arasan_syscon_write(struct sdhci_host *host, |
---|
129 | 217 | const struct sdhci_arasan_soc_ctl_field *fld, |
---|
.. | .. |
---|
167 | 255 | { |
---|
168 | 256 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
169 | 257 | struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
| 258 | + struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data; |
---|
170 | 259 | bool ctrl_phy = false; |
---|
171 | 260 | |
---|
172 | 261 | if (!IS_ERR(sdhci_arasan->phy)) { |
---|
.. | .. |
---|
213 | 302 | sdhci_arasan->is_phy_on = false; |
---|
214 | 303 | } |
---|
215 | 304 | |
---|
| 305 | + if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN) { |
---|
| 306 | + /* |
---|
| 307 | + * Some of the Arasan variations might not have timing |
---|
| 308 | + * requirements met at 25MHz for Default Speed mode, |
---|
| 309 | + * those controllers work at 19MHz instead. |
---|
| 310 | + */ |
---|
| 311 | + if (clock == DEFAULT_SPEED_MAX_DTR) |
---|
| 312 | + clock = (DEFAULT_SPEED_MAX_DTR * 19) / 25; |
---|
| 313 | + } |
---|
| 314 | + |
---|
| 315 | + /* Set the Input and Output Clock Phase Delays */ |
---|
| 316 | + if (clk_data->set_clk_delays) |
---|
| 317 | + clk_data->set_clk_delays(host); |
---|
| 318 | + |
---|
216 | 319 | sdhci_set_clock(host, clock); |
---|
217 | 320 | |
---|
218 | 321 | if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE) |
---|
.. | .. |
---|
257 | 360 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
258 | 361 | struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
259 | 362 | |
---|
260 | | - sdhci_reset(host, mask); |
---|
| 363 | + sdhci_and_cqhci_reset(host, mask); |
---|
261 | 364 | |
---|
262 | 365 | if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) { |
---|
263 | 366 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
---|
.. | .. |
---|
288 | 391 | return -EINVAL; |
---|
289 | 392 | } |
---|
290 | 393 | |
---|
291 | | -static void sdhci_arasan_set_power(struct sdhci_host *host, unsigned char mode, |
---|
292 | | - unsigned short vdd) |
---|
293 | | -{ |
---|
294 | | - if (!IS_ERR(host->mmc->supply.vmmc)) { |
---|
295 | | - struct mmc_host *mmc = host->mmc; |
---|
296 | | - |
---|
297 | | - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd); |
---|
298 | | - } |
---|
299 | | - sdhci_set_power_noreg(host, mode, vdd); |
---|
300 | | -} |
---|
301 | | - |
---|
302 | 394 | static const struct sdhci_ops sdhci_arasan_ops = { |
---|
303 | 395 | .set_clock = sdhci_arasan_set_clock, |
---|
304 | 396 | .get_max_clock = sdhci_pltfm_clk_get_max_clock, |
---|
.. | .. |
---|
306 | 398 | .set_bus_width = sdhci_set_bus_width, |
---|
307 | 399 | .reset = sdhci_arasan_reset, |
---|
308 | 400 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
---|
309 | | - .set_power = sdhci_arasan_set_power, |
---|
310 | | -}; |
---|
311 | | - |
---|
312 | | -static const struct sdhci_pltfm_data sdhci_arasan_pdata = { |
---|
313 | | - .ops = &sdhci_arasan_ops, |
---|
314 | | - .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, |
---|
315 | | - .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
316 | | - SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
317 | | - SDHCI_QUIRK2_STOP_WITH_TC, |
---|
| 401 | + .set_power = sdhci_set_power_and_bus_voltage, |
---|
318 | 402 | }; |
---|
319 | 403 | |
---|
320 | 404 | static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask) |
---|
.. | .. |
---|
362 | 446 | .set_bus_width = sdhci_set_bus_width, |
---|
363 | 447 | .reset = sdhci_arasan_reset, |
---|
364 | 448 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
---|
365 | | - .set_power = sdhci_arasan_set_power, |
---|
| 449 | + .set_power = sdhci_set_power_and_bus_voltage, |
---|
366 | 450 | .irq = sdhci_arasan_cqhci_irq, |
---|
367 | 451 | }; |
---|
368 | 452 | |
---|
.. | .. |
---|
377 | 461 | /** |
---|
378 | 462 | * sdhci_arasan_suspend - Suspend method for the driver |
---|
379 | 463 | * @dev: Address of the device structure |
---|
380 | | - * Returns 0 on success and error value on error |
---|
381 | 464 | * |
---|
382 | 465 | * Put the device in a low power state. |
---|
| 466 | + * |
---|
| 467 | + * Return: 0 on success and error value on error |
---|
383 | 468 | */ |
---|
384 | 469 | static int sdhci_arasan_suspend(struct device *dev) |
---|
385 | 470 | { |
---|
.. | .. |
---|
422 | 507 | /** |
---|
423 | 508 | * sdhci_arasan_resume - Resume method for the driver |
---|
424 | 509 | * @dev: Address of the device structure |
---|
425 | | - * Returns 0 on success and error value on error |
---|
426 | 510 | * |
---|
427 | 511 | * Resume operation after suspend |
---|
| 512 | + * |
---|
| 513 | + * Return: 0 on success and error value on error |
---|
428 | 514 | */ |
---|
429 | 515 | static int sdhci_arasan_resume(struct device *dev) |
---|
430 | 516 | { |
---|
.. | .. |
---|
470 | 556 | static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend, |
---|
471 | 557 | sdhci_arasan_resume); |
---|
472 | 558 | |
---|
473 | | -static const struct of_device_id sdhci_arasan_of_match[] = { |
---|
474 | | - /* SoC-specific compatible strings w/ soc_ctl_map */ |
---|
475 | | - { |
---|
476 | | - .compatible = "rockchip,rk3399-sdhci-5.1", |
---|
477 | | - .data = &rk3399_soc_ctl_map, |
---|
478 | | - }, |
---|
479 | | - |
---|
480 | | - /* Generic compatible below here */ |
---|
481 | | - { .compatible = "arasan,sdhci-8.9a" }, |
---|
482 | | - { .compatible = "arasan,sdhci-5.1" }, |
---|
483 | | - { .compatible = "arasan,sdhci-4.9a" }, |
---|
484 | | - |
---|
485 | | - { /* sentinel */ } |
---|
486 | | -}; |
---|
487 | | -MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); |
---|
488 | | - |
---|
489 | 559 | /** |
---|
490 | 560 | * sdhci_arasan_sdcardclk_recalc_rate - Return the card clock rate |
---|
| 561 | + * |
---|
| 562 | + * @hw: Pointer to the hardware clock structure. |
---|
| 563 | + * @parent_rate: The parent rate (should be rate of clk_xin). |
---|
491 | 564 | * |
---|
492 | 565 | * Return the current actual rate of the SD card clock. This can be used |
---|
493 | 566 | * to communicate with out PHY. |
---|
494 | 567 | * |
---|
495 | | - * @hw: Pointer to the hardware clock structure. |
---|
496 | | - * @parent_rate The parent rate (should be rate of clk_xin). |
---|
497 | | - * Returns the card clock rate. |
---|
| 568 | + * Return: The card clock rate. |
---|
498 | 569 | */ |
---|
499 | 570 | static unsigned long sdhci_arasan_sdcardclk_recalc_rate(struct clk_hw *hw, |
---|
500 | 571 | unsigned long parent_rate) |
---|
501 | | - |
---|
502 | 572 | { |
---|
| 573 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 574 | + container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw); |
---|
503 | 575 | struct sdhci_arasan_data *sdhci_arasan = |
---|
504 | | - container_of(hw, struct sdhci_arasan_data, sdcardclk_hw); |
---|
| 576 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
505 | 577 | struct sdhci_host *host = sdhci_arasan->host; |
---|
506 | 578 | |
---|
507 | 579 | return host->mmc->actual_clock; |
---|
.. | .. |
---|
512 | 584 | }; |
---|
513 | 585 | |
---|
514 | 586 | /** |
---|
| 587 | + * sdhci_arasan_sampleclk_recalc_rate - Return the sampling clock rate |
---|
| 588 | + * |
---|
| 589 | + * @hw: Pointer to the hardware clock structure. |
---|
| 590 | + * @parent_rate: The parent rate (should be rate of clk_xin). |
---|
| 591 | + * |
---|
| 592 | + * Return the current actual rate of the sampling clock. This can be used |
---|
| 593 | + * to communicate with out PHY. |
---|
| 594 | + * |
---|
| 595 | + * Return: The sample clock rate. |
---|
| 596 | + */ |
---|
| 597 | +static unsigned long sdhci_arasan_sampleclk_recalc_rate(struct clk_hw *hw, |
---|
| 598 | + unsigned long parent_rate) |
---|
| 599 | +{ |
---|
| 600 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 601 | + container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw); |
---|
| 602 | + struct sdhci_arasan_data *sdhci_arasan = |
---|
| 603 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
| 604 | + struct sdhci_host *host = sdhci_arasan->host; |
---|
| 605 | + |
---|
| 606 | + return host->mmc->actual_clock; |
---|
| 607 | +} |
---|
| 608 | + |
---|
| 609 | +static const struct clk_ops arasan_sampleclk_ops = { |
---|
| 610 | + .recalc_rate = sdhci_arasan_sampleclk_recalc_rate, |
---|
| 611 | +}; |
---|
| 612 | + |
---|
| 613 | +/** |
---|
| 614 | + * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays |
---|
| 615 | + * |
---|
| 616 | + * @hw: Pointer to the hardware clock structure. |
---|
| 617 | + * @degrees: The clock phase shift between 0 - 359. |
---|
| 618 | + * |
---|
| 619 | + * Set the SD Output Clock Tap Delays for Output path |
---|
| 620 | + * |
---|
| 621 | + * Return: 0 on success and error value on error |
---|
| 622 | + */ |
---|
| 623 | +static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees) |
---|
| 624 | +{ |
---|
| 625 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 626 | + container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw); |
---|
| 627 | + struct sdhci_arasan_data *sdhci_arasan = |
---|
| 628 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
| 629 | + struct sdhci_host *host = sdhci_arasan->host; |
---|
| 630 | + const char *clk_name = clk_hw_get_name(hw); |
---|
| 631 | + u32 node_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : NODE_SD_1; |
---|
| 632 | + u8 tap_delay, tap_max = 0; |
---|
| 633 | + int ret; |
---|
| 634 | + |
---|
| 635 | + /* This is applicable for SDHCI_SPEC_300 and above */ |
---|
| 636 | + if (host->version < SDHCI_SPEC_300) |
---|
| 637 | + return 0; |
---|
| 638 | + |
---|
| 639 | + switch (host->timing) { |
---|
| 640 | + case MMC_TIMING_MMC_HS: |
---|
| 641 | + case MMC_TIMING_SD_HS: |
---|
| 642 | + case MMC_TIMING_UHS_SDR25: |
---|
| 643 | + case MMC_TIMING_UHS_DDR50: |
---|
| 644 | + case MMC_TIMING_MMC_DDR52: |
---|
| 645 | + /* For 50MHz clock, 30 Taps are available */ |
---|
| 646 | + tap_max = 30; |
---|
| 647 | + break; |
---|
| 648 | + case MMC_TIMING_UHS_SDR50: |
---|
| 649 | + /* For 100MHz clock, 15 Taps are available */ |
---|
| 650 | + tap_max = 15; |
---|
| 651 | + break; |
---|
| 652 | + case MMC_TIMING_UHS_SDR104: |
---|
| 653 | + case MMC_TIMING_MMC_HS200: |
---|
| 654 | + /* For 200MHz clock, 8 Taps are available */ |
---|
| 655 | + tap_max = 8; |
---|
| 656 | + default: |
---|
| 657 | + break; |
---|
| 658 | + } |
---|
| 659 | + |
---|
| 660 | + tap_delay = (degrees * tap_max) / 360; |
---|
| 661 | + |
---|
| 662 | + /* Set the Clock Phase */ |
---|
| 663 | + ret = zynqmp_pm_set_sd_tapdelay(node_id, PM_TAPDELAY_OUTPUT, tap_delay); |
---|
| 664 | + if (ret) |
---|
| 665 | + pr_err("Error setting Output Tap Delay\n"); |
---|
| 666 | + |
---|
| 667 | + /* Release DLL Reset */ |
---|
| 668 | + zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_RELEASE); |
---|
| 669 | + |
---|
| 670 | + return ret; |
---|
| 671 | +} |
---|
| 672 | + |
---|
| 673 | +static const struct clk_ops zynqmp_sdcardclk_ops = { |
---|
| 674 | + .recalc_rate = sdhci_arasan_sdcardclk_recalc_rate, |
---|
| 675 | + .set_phase = sdhci_zynqmp_sdcardclk_set_phase, |
---|
| 676 | +}; |
---|
| 677 | + |
---|
| 678 | +/** |
---|
| 679 | + * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays |
---|
| 680 | + * |
---|
| 681 | + * @hw: Pointer to the hardware clock structure. |
---|
| 682 | + * @degrees: The clock phase shift between 0 - 359. |
---|
| 683 | + * |
---|
| 684 | + * Set the SD Input Clock Tap Delays for Input path |
---|
| 685 | + * |
---|
| 686 | + * Return: 0 on success and error value on error |
---|
| 687 | + */ |
---|
| 688 | +static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees) |
---|
| 689 | +{ |
---|
| 690 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 691 | + container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw); |
---|
| 692 | + struct sdhci_arasan_data *sdhci_arasan = |
---|
| 693 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
| 694 | + struct sdhci_host *host = sdhci_arasan->host; |
---|
| 695 | + const char *clk_name = clk_hw_get_name(hw); |
---|
| 696 | + u32 node_id = !strcmp(clk_name, "clk_in_sd0") ? NODE_SD_0 : NODE_SD_1; |
---|
| 697 | + u8 tap_delay, tap_max = 0; |
---|
| 698 | + int ret; |
---|
| 699 | + |
---|
| 700 | + /* This is applicable for SDHCI_SPEC_300 and above */ |
---|
| 701 | + if (host->version < SDHCI_SPEC_300) |
---|
| 702 | + return 0; |
---|
| 703 | + |
---|
| 704 | + /* Assert DLL Reset */ |
---|
| 705 | + zynqmp_pm_sd_dll_reset(node_id, PM_DLL_RESET_ASSERT); |
---|
| 706 | + |
---|
| 707 | + switch (host->timing) { |
---|
| 708 | + case MMC_TIMING_MMC_HS: |
---|
| 709 | + case MMC_TIMING_SD_HS: |
---|
| 710 | + case MMC_TIMING_UHS_SDR25: |
---|
| 711 | + case MMC_TIMING_UHS_DDR50: |
---|
| 712 | + case MMC_TIMING_MMC_DDR52: |
---|
| 713 | + /* For 50MHz clock, 120 Taps are available */ |
---|
| 714 | + tap_max = 120; |
---|
| 715 | + break; |
---|
| 716 | + case MMC_TIMING_UHS_SDR50: |
---|
| 717 | + /* For 100MHz clock, 60 Taps are available */ |
---|
| 718 | + tap_max = 60; |
---|
| 719 | + break; |
---|
| 720 | + case MMC_TIMING_UHS_SDR104: |
---|
| 721 | + case MMC_TIMING_MMC_HS200: |
---|
| 722 | + /* For 200MHz clock, 30 Taps are available */ |
---|
| 723 | + tap_max = 30; |
---|
| 724 | + default: |
---|
| 725 | + break; |
---|
| 726 | + } |
---|
| 727 | + |
---|
| 728 | + tap_delay = (degrees * tap_max) / 360; |
---|
| 729 | + |
---|
| 730 | + /* Set the Clock Phase */ |
---|
| 731 | + ret = zynqmp_pm_set_sd_tapdelay(node_id, PM_TAPDELAY_INPUT, tap_delay); |
---|
| 732 | + if (ret) |
---|
| 733 | + pr_err("Error setting Input Tap Delay\n"); |
---|
| 734 | + |
---|
| 735 | + return ret; |
---|
| 736 | +} |
---|
| 737 | + |
---|
| 738 | +static const struct clk_ops zynqmp_sampleclk_ops = { |
---|
| 739 | + .recalc_rate = sdhci_arasan_sampleclk_recalc_rate, |
---|
| 740 | + .set_phase = sdhci_zynqmp_sampleclk_set_phase, |
---|
| 741 | +}; |
---|
| 742 | + |
---|
| 743 | +/** |
---|
| 744 | + * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays |
---|
| 745 | + * |
---|
| 746 | + * @hw: Pointer to the hardware clock structure. |
---|
| 747 | + * @degrees: The clock phase shift between 0 - 359. |
---|
| 748 | + * |
---|
| 749 | + * Set the SD Output Clock Tap Delays for Output path |
---|
| 750 | + * |
---|
| 751 | + * Return: 0 on success and error value on error |
---|
| 752 | + */ |
---|
| 753 | +static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees) |
---|
| 754 | +{ |
---|
| 755 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 756 | + container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw); |
---|
| 757 | + struct sdhci_arasan_data *sdhci_arasan = |
---|
| 758 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
| 759 | + struct sdhci_host *host = sdhci_arasan->host; |
---|
| 760 | + u8 tap_delay, tap_max = 0; |
---|
| 761 | + |
---|
| 762 | + /* This is applicable for SDHCI_SPEC_300 and above */ |
---|
| 763 | + if (host->version < SDHCI_SPEC_300) |
---|
| 764 | + return 0; |
---|
| 765 | + |
---|
| 766 | + switch (host->timing) { |
---|
| 767 | + case MMC_TIMING_MMC_HS: |
---|
| 768 | + case MMC_TIMING_SD_HS: |
---|
| 769 | + case MMC_TIMING_UHS_SDR25: |
---|
| 770 | + case MMC_TIMING_UHS_DDR50: |
---|
| 771 | + case MMC_TIMING_MMC_DDR52: |
---|
| 772 | + /* For 50MHz clock, 30 Taps are available */ |
---|
| 773 | + tap_max = 30; |
---|
| 774 | + break; |
---|
| 775 | + case MMC_TIMING_UHS_SDR50: |
---|
| 776 | + /* For 100MHz clock, 15 Taps are available */ |
---|
| 777 | + tap_max = 15; |
---|
| 778 | + break; |
---|
| 779 | + case MMC_TIMING_UHS_SDR104: |
---|
| 780 | + case MMC_TIMING_MMC_HS200: |
---|
| 781 | + /* For 200MHz clock, 8 Taps are available */ |
---|
| 782 | + tap_max = 8; |
---|
| 783 | + default: |
---|
| 784 | + break; |
---|
| 785 | + } |
---|
| 786 | + |
---|
| 787 | + tap_delay = (degrees * tap_max) / 360; |
---|
| 788 | + |
---|
| 789 | + /* Set the Clock Phase */ |
---|
| 790 | + if (tap_delay) { |
---|
| 791 | + u32 regval; |
---|
| 792 | + |
---|
| 793 | + regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER); |
---|
| 794 | + regval |= SDHCI_OTAPDLY_ENABLE; |
---|
| 795 | + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); |
---|
| 796 | + regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK; |
---|
| 797 | + regval |= tap_delay; |
---|
| 798 | + sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER); |
---|
| 799 | + } |
---|
| 800 | + |
---|
| 801 | + return 0; |
---|
| 802 | +} |
---|
| 803 | + |
---|
| 804 | +static const struct clk_ops versal_sdcardclk_ops = { |
---|
| 805 | + .recalc_rate = sdhci_arasan_sdcardclk_recalc_rate, |
---|
| 806 | + .set_phase = sdhci_versal_sdcardclk_set_phase, |
---|
| 807 | +}; |
---|
| 808 | + |
---|
| 809 | +/** |
---|
| 810 | + * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays |
---|
| 811 | + * |
---|
| 812 | + * @hw: Pointer to the hardware clock structure. |
---|
| 813 | + * @degrees: The clock phase shift between 0 - 359. |
---|
| 814 | + * |
---|
| 815 | + * Set the SD Input Clock Tap Delays for Input path |
---|
| 816 | + * |
---|
| 817 | + * Return: 0 on success and error value on error |
---|
| 818 | + */ |
---|
| 819 | +static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees) |
---|
| 820 | +{ |
---|
| 821 | + struct sdhci_arasan_clk_data *clk_data = |
---|
| 822 | + container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw); |
---|
| 823 | + struct sdhci_arasan_data *sdhci_arasan = |
---|
| 824 | + container_of(clk_data, struct sdhci_arasan_data, clk_data); |
---|
| 825 | + struct sdhci_host *host = sdhci_arasan->host; |
---|
| 826 | + u8 tap_delay, tap_max = 0; |
---|
| 827 | + |
---|
| 828 | + /* This is applicable for SDHCI_SPEC_300 and above */ |
---|
| 829 | + if (host->version < SDHCI_SPEC_300) |
---|
| 830 | + return 0; |
---|
| 831 | + |
---|
| 832 | + switch (host->timing) { |
---|
| 833 | + case MMC_TIMING_MMC_HS: |
---|
| 834 | + case MMC_TIMING_SD_HS: |
---|
| 835 | + case MMC_TIMING_UHS_SDR25: |
---|
| 836 | + case MMC_TIMING_UHS_DDR50: |
---|
| 837 | + case MMC_TIMING_MMC_DDR52: |
---|
| 838 | + /* For 50MHz clock, 120 Taps are available */ |
---|
| 839 | + tap_max = 120; |
---|
| 840 | + break; |
---|
| 841 | + case MMC_TIMING_UHS_SDR50: |
---|
| 842 | + /* For 100MHz clock, 60 Taps are available */ |
---|
| 843 | + tap_max = 60; |
---|
| 844 | + break; |
---|
| 845 | + case MMC_TIMING_UHS_SDR104: |
---|
| 846 | + case MMC_TIMING_MMC_HS200: |
---|
| 847 | + /* For 200MHz clock, 30 Taps are available */ |
---|
| 848 | + tap_max = 30; |
---|
| 849 | + default: |
---|
| 850 | + break; |
---|
| 851 | + } |
---|
| 852 | + |
---|
| 853 | + tap_delay = (degrees * tap_max) / 360; |
---|
| 854 | + |
---|
| 855 | + /* Set the Clock Phase */ |
---|
| 856 | + if (tap_delay) { |
---|
| 857 | + u32 regval; |
---|
| 858 | + |
---|
| 859 | + regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER); |
---|
| 860 | + regval |= SDHCI_ITAPDLY_CHGWIN; |
---|
| 861 | + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
---|
| 862 | + regval |= SDHCI_ITAPDLY_ENABLE; |
---|
| 863 | + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
---|
| 864 | + regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK; |
---|
| 865 | + regval |= tap_delay; |
---|
| 866 | + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
---|
| 867 | + regval &= ~SDHCI_ITAPDLY_CHGWIN; |
---|
| 868 | + sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER); |
---|
| 869 | + } |
---|
| 870 | + |
---|
| 871 | + return 0; |
---|
| 872 | +} |
---|
| 873 | + |
---|
| 874 | +static const struct clk_ops versal_sampleclk_ops = { |
---|
| 875 | + .recalc_rate = sdhci_arasan_sampleclk_recalc_rate, |
---|
| 876 | + .set_phase = sdhci_versal_sampleclk_set_phase, |
---|
| 877 | +}; |
---|
| 878 | + |
---|
| 879 | +static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 deviceid) |
---|
| 880 | +{ |
---|
| 881 | + u16 clk; |
---|
| 882 | + |
---|
| 883 | + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
---|
| 884 | + clk &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN); |
---|
| 885 | + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
---|
| 886 | + |
---|
| 887 | + /* Issue DLL Reset */ |
---|
| 888 | + zynqmp_pm_sd_dll_reset(deviceid, PM_DLL_RESET_PULSE); |
---|
| 889 | + |
---|
| 890 | + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
---|
| 891 | + |
---|
| 892 | + sdhci_enable_clk(host, clk); |
---|
| 893 | +} |
---|
| 894 | + |
---|
| 895 | +static int arasan_zynqmp_execute_tuning(struct mmc_host *mmc, u32 opcode) |
---|
| 896 | +{ |
---|
| 897 | + struct sdhci_host *host = mmc_priv(mmc); |
---|
| 898 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 899 | + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
| 900 | + struct clk_hw *hw = &sdhci_arasan->clk_data.sdcardclk_hw; |
---|
| 901 | + const char *clk_name = clk_hw_get_name(hw); |
---|
| 902 | + u32 device_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : |
---|
| 903 | + NODE_SD_1; |
---|
| 904 | + int err; |
---|
| 905 | + |
---|
| 906 | + arasan_zynqmp_dll_reset(host, device_id); |
---|
| 907 | + |
---|
| 908 | + err = sdhci_execute_tuning(mmc, opcode); |
---|
| 909 | + if (err) |
---|
| 910 | + return err; |
---|
| 911 | + |
---|
| 912 | + arasan_zynqmp_dll_reset(host, device_id); |
---|
| 913 | + |
---|
| 914 | + return 0; |
---|
| 915 | +} |
---|
| 916 | + |
---|
| 917 | +/** |
---|
515 | 918 | * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier |
---|
| 919 | + * |
---|
| 920 | + * @host: The sdhci_host |
---|
| 921 | + * @value: The value to write |
---|
516 | 922 | * |
---|
517 | 923 | * The corecfg_clockmultiplier is supposed to contain clock multiplier |
---|
518 | 924 | * value of programmable clock generator. |
---|
.. | .. |
---|
525 | 931 | * - The value of corecfg_clockmultiplier should sync with that of corresponding |
---|
526 | 932 | * value reading from sdhci_capability_register. So this function is called |
---|
527 | 933 | * once at probe time and never called again. |
---|
528 | | - * |
---|
529 | | - * @host: The sdhci_host |
---|
530 | 934 | */ |
---|
531 | 935 | static void sdhci_arasan_update_clockmultiplier(struct sdhci_host *host, |
---|
532 | 936 | u32 value) |
---|
.. | .. |
---|
553 | 957 | /** |
---|
554 | 958 | * sdhci_arasan_update_baseclkfreq - Set corecfg_baseclkfreq |
---|
555 | 959 | * |
---|
| 960 | + * @host: The sdhci_host |
---|
| 961 | + * |
---|
556 | 962 | * The corecfg_baseclkfreq is supposed to contain the MHz of clk_xin. This |
---|
557 | 963 | * function can be used to make that happen. |
---|
558 | 964 | * |
---|
.. | .. |
---|
564 | 970 | * - It's assumed that clk_xin is not dynamic and that we use the SDHCI divider |
---|
565 | 971 | * to achieve lower clock rates. That means that this function is called once |
---|
566 | 972 | * at probe time and never called again. |
---|
567 | | - * |
---|
568 | | - * @host: The sdhci_host |
---|
569 | 973 | */ |
---|
570 | 974 | static void sdhci_arasan_update_baseclkfreq(struct sdhci_host *host) |
---|
571 | 975 | { |
---|
.. | .. |
---|
589 | 993 | sdhci_arasan_syscon_write(host, &soc_ctl_map->baseclkfreq, mhz); |
---|
590 | 994 | } |
---|
591 | 995 | |
---|
| 996 | +static void sdhci_arasan_set_clk_delays(struct sdhci_host *host) |
---|
| 997 | +{ |
---|
| 998 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 999 | + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
| 1000 | + struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data; |
---|
| 1001 | + |
---|
| 1002 | + clk_set_phase(clk_data->sampleclk, |
---|
| 1003 | + clk_data->clk_phase_in[host->timing]); |
---|
| 1004 | + clk_set_phase(clk_data->sdcardclk, |
---|
| 1005 | + clk_data->clk_phase_out[host->timing]); |
---|
| 1006 | +} |
---|
| 1007 | + |
---|
| 1008 | +static void arasan_dt_read_clk_phase(struct device *dev, |
---|
| 1009 | + struct sdhci_arasan_clk_data *clk_data, |
---|
| 1010 | + unsigned int timing, const char *prop) |
---|
| 1011 | +{ |
---|
| 1012 | + struct device_node *np = dev->of_node; |
---|
| 1013 | + |
---|
| 1014 | + int clk_phase[2] = {0}; |
---|
| 1015 | + |
---|
| 1016 | + /* |
---|
| 1017 | + * Read Tap Delay values from DT, if the DT does not contain the |
---|
| 1018 | + * Tap Values then use the pre-defined values. |
---|
| 1019 | + */ |
---|
| 1020 | + if (of_property_read_variable_u32_array(np, prop, &clk_phase[0], |
---|
| 1021 | + 2, 0)) { |
---|
| 1022 | + dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n", |
---|
| 1023 | + prop, clk_data->clk_phase_in[timing], |
---|
| 1024 | + clk_data->clk_phase_out[timing]); |
---|
| 1025 | + return; |
---|
| 1026 | + } |
---|
| 1027 | + |
---|
| 1028 | + /* The values read are Input and Output Clock Delays in order */ |
---|
| 1029 | + clk_data->clk_phase_in[timing] = clk_phase[0]; |
---|
| 1030 | + clk_data->clk_phase_out[timing] = clk_phase[1]; |
---|
| 1031 | +} |
---|
| 1032 | + |
---|
592 | 1033 | /** |
---|
593 | | - * sdhci_arasan_register_sdclk - Register the sdclk for a PHY to use |
---|
| 1034 | + * arasan_dt_parse_clk_phases - Read Clock Delay values from DT |
---|
| 1035 | + * |
---|
| 1036 | + * @dev: Pointer to our struct device. |
---|
| 1037 | + * @clk_data: Pointer to the Clock Data structure |
---|
| 1038 | + * |
---|
| 1039 | + * Called at initialization to parse the values of Clock Delays. |
---|
| 1040 | + */ |
---|
| 1041 | +static void arasan_dt_parse_clk_phases(struct device *dev, |
---|
| 1042 | + struct sdhci_arasan_clk_data *clk_data) |
---|
| 1043 | +{ |
---|
| 1044 | + u32 mio_bank = 0; |
---|
| 1045 | + int i; |
---|
| 1046 | + |
---|
| 1047 | + /* |
---|
| 1048 | + * This has been kept as a pointer and is assigned a function here. |
---|
| 1049 | + * So that different controller variants can assign their own handling |
---|
| 1050 | + * function. |
---|
| 1051 | + */ |
---|
| 1052 | + clk_data->set_clk_delays = sdhci_arasan_set_clk_delays; |
---|
| 1053 | + |
---|
| 1054 | + if (of_device_is_compatible(dev->of_node, "xlnx,zynqmp-8.9a")) { |
---|
| 1055 | + u32 zynqmp_iclk_phase[MMC_TIMING_MMC_HS400 + 1] = |
---|
| 1056 | + ZYNQMP_ICLK_PHASE; |
---|
| 1057 | + u32 zynqmp_oclk_phase[MMC_TIMING_MMC_HS400 + 1] = |
---|
| 1058 | + ZYNQMP_OCLK_PHASE; |
---|
| 1059 | + |
---|
| 1060 | + of_property_read_u32(dev->of_node, "xlnx,mio-bank", &mio_bank); |
---|
| 1061 | + if (mio_bank == 2) { |
---|
| 1062 | + zynqmp_oclk_phase[MMC_TIMING_UHS_SDR104] = 90; |
---|
| 1063 | + zynqmp_oclk_phase[MMC_TIMING_MMC_HS200] = 90; |
---|
| 1064 | + } |
---|
| 1065 | + |
---|
| 1066 | + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { |
---|
| 1067 | + clk_data->clk_phase_in[i] = zynqmp_iclk_phase[i]; |
---|
| 1068 | + clk_data->clk_phase_out[i] = zynqmp_oclk_phase[i]; |
---|
| 1069 | + } |
---|
| 1070 | + } |
---|
| 1071 | + |
---|
| 1072 | + if (of_device_is_compatible(dev->of_node, "xlnx,versal-8.9a")) { |
---|
| 1073 | + u32 versal_iclk_phase[MMC_TIMING_MMC_HS400 + 1] = |
---|
| 1074 | + VERSAL_ICLK_PHASE; |
---|
| 1075 | + u32 versal_oclk_phase[MMC_TIMING_MMC_HS400 + 1] = |
---|
| 1076 | + VERSAL_OCLK_PHASE; |
---|
| 1077 | + |
---|
| 1078 | + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { |
---|
| 1079 | + clk_data->clk_phase_in[i] = versal_iclk_phase[i]; |
---|
| 1080 | + clk_data->clk_phase_out[i] = versal_oclk_phase[i]; |
---|
| 1081 | + } |
---|
| 1082 | + } |
---|
| 1083 | + |
---|
| 1084 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_LEGACY, |
---|
| 1085 | + "clk-phase-legacy"); |
---|
| 1086 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS, |
---|
| 1087 | + "clk-phase-mmc-hs"); |
---|
| 1088 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_SD_HS, |
---|
| 1089 | + "clk-phase-sd-hs"); |
---|
| 1090 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR12, |
---|
| 1091 | + "clk-phase-uhs-sdr12"); |
---|
| 1092 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR25, |
---|
| 1093 | + "clk-phase-uhs-sdr25"); |
---|
| 1094 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR50, |
---|
| 1095 | + "clk-phase-uhs-sdr50"); |
---|
| 1096 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR104, |
---|
| 1097 | + "clk-phase-uhs-sdr104"); |
---|
| 1098 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_DDR50, |
---|
| 1099 | + "clk-phase-uhs-ddr50"); |
---|
| 1100 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_DDR52, |
---|
| 1101 | + "clk-phase-mmc-ddr52"); |
---|
| 1102 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS200, |
---|
| 1103 | + "clk-phase-mmc-hs200"); |
---|
| 1104 | + arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS400, |
---|
| 1105 | + "clk-phase-mmc-hs400"); |
---|
| 1106 | +} |
---|
| 1107 | + |
---|
| 1108 | +static const struct sdhci_pltfm_data sdhci_arasan_pdata = { |
---|
| 1109 | + .ops = &sdhci_arasan_ops, |
---|
| 1110 | + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, |
---|
| 1111 | + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
| 1112 | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
| 1113 | + SDHCI_QUIRK2_STOP_WITH_TC, |
---|
| 1114 | +}; |
---|
| 1115 | + |
---|
| 1116 | +static const struct sdhci_arasan_clk_ops arasan_clk_ops = { |
---|
| 1117 | + .sdcardclk_ops = &arasan_sdcardclk_ops, |
---|
| 1118 | + .sampleclk_ops = &arasan_sampleclk_ops, |
---|
| 1119 | +}; |
---|
| 1120 | + |
---|
| 1121 | +static struct sdhci_arasan_of_data sdhci_arasan_generic_data = { |
---|
| 1122 | + .pdata = &sdhci_arasan_pdata, |
---|
| 1123 | + .clk_ops = &arasan_clk_ops, |
---|
| 1124 | +}; |
---|
| 1125 | + |
---|
| 1126 | +static const struct sdhci_pltfm_data sdhci_keembay_emmc_pdata = { |
---|
| 1127 | + .ops = &sdhci_arasan_cqe_ops, |
---|
| 1128 | + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | |
---|
| 1129 | + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
---|
| 1130 | + SDHCI_QUIRK_NO_LED | |
---|
| 1131 | + SDHCI_QUIRK_32BIT_DMA_ADDR | |
---|
| 1132 | + SDHCI_QUIRK_32BIT_DMA_SIZE | |
---|
| 1133 | + SDHCI_QUIRK_32BIT_ADMA_SIZE, |
---|
| 1134 | + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
| 1135 | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
| 1136 | + SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 | |
---|
| 1137 | + SDHCI_QUIRK2_STOP_WITH_TC | |
---|
| 1138 | + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, |
---|
| 1139 | +}; |
---|
| 1140 | + |
---|
| 1141 | +static const struct sdhci_pltfm_data sdhci_keembay_sd_pdata = { |
---|
| 1142 | + .ops = &sdhci_arasan_ops, |
---|
| 1143 | + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | |
---|
| 1144 | + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
---|
| 1145 | + SDHCI_QUIRK_NO_LED | |
---|
| 1146 | + SDHCI_QUIRK_32BIT_DMA_ADDR | |
---|
| 1147 | + SDHCI_QUIRK_32BIT_DMA_SIZE | |
---|
| 1148 | + SDHCI_QUIRK_32BIT_ADMA_SIZE, |
---|
| 1149 | + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
| 1150 | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
| 1151 | + SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | |
---|
| 1152 | + SDHCI_QUIRK2_STOP_WITH_TC | |
---|
| 1153 | + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, |
---|
| 1154 | +}; |
---|
| 1155 | + |
---|
| 1156 | +static const struct sdhci_pltfm_data sdhci_keembay_sdio_pdata = { |
---|
| 1157 | + .ops = &sdhci_arasan_ops, |
---|
| 1158 | + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | |
---|
| 1159 | + SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
---|
| 1160 | + SDHCI_QUIRK_NO_LED | |
---|
| 1161 | + SDHCI_QUIRK_32BIT_DMA_ADDR | |
---|
| 1162 | + SDHCI_QUIRK_32BIT_DMA_SIZE | |
---|
| 1163 | + SDHCI_QUIRK_32BIT_ADMA_SIZE, |
---|
| 1164 | + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
| 1165 | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
| 1166 | + SDHCI_QUIRK2_HOST_OFF_CARD_ON | |
---|
| 1167 | + SDHCI_QUIRK2_BROKEN_64_BIT_DMA, |
---|
| 1168 | +}; |
---|
| 1169 | + |
---|
| 1170 | +static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data = { |
---|
| 1171 | + .soc_ctl_map = &rk3399_soc_ctl_map, |
---|
| 1172 | + .pdata = &sdhci_arasan_cqe_pdata, |
---|
| 1173 | + .clk_ops = &arasan_clk_ops, |
---|
| 1174 | +}; |
---|
| 1175 | + |
---|
| 1176 | +static struct sdhci_arasan_of_data intel_lgm_emmc_data = { |
---|
| 1177 | + .soc_ctl_map = &intel_lgm_emmc_soc_ctl_map, |
---|
| 1178 | + .pdata = &sdhci_arasan_cqe_pdata, |
---|
| 1179 | + .clk_ops = &arasan_clk_ops, |
---|
| 1180 | +}; |
---|
| 1181 | + |
---|
| 1182 | +static struct sdhci_arasan_of_data intel_lgm_sdxc_data = { |
---|
| 1183 | + .soc_ctl_map = &intel_lgm_sdxc_soc_ctl_map, |
---|
| 1184 | + .pdata = &sdhci_arasan_cqe_pdata, |
---|
| 1185 | + .clk_ops = &arasan_clk_ops, |
---|
| 1186 | +}; |
---|
| 1187 | + |
---|
| 1188 | +static const struct sdhci_pltfm_data sdhci_arasan_zynqmp_pdata = { |
---|
| 1189 | + .ops = &sdhci_arasan_ops, |
---|
| 1190 | + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | |
---|
| 1191 | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | |
---|
| 1192 | + SDHCI_QUIRK2_STOP_WITH_TC, |
---|
| 1193 | +}; |
---|
| 1194 | + |
---|
| 1195 | +static const struct sdhci_arasan_clk_ops zynqmp_clk_ops = { |
---|
| 1196 | + .sdcardclk_ops = &zynqmp_sdcardclk_ops, |
---|
| 1197 | + .sampleclk_ops = &zynqmp_sampleclk_ops, |
---|
| 1198 | +}; |
---|
| 1199 | + |
---|
| 1200 | +static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = { |
---|
| 1201 | + .pdata = &sdhci_arasan_zynqmp_pdata, |
---|
| 1202 | + .clk_ops = &zynqmp_clk_ops, |
---|
| 1203 | +}; |
---|
| 1204 | + |
---|
| 1205 | +static const struct sdhci_arasan_clk_ops versal_clk_ops = { |
---|
| 1206 | + .sdcardclk_ops = &versal_sdcardclk_ops, |
---|
| 1207 | + .sampleclk_ops = &versal_sampleclk_ops, |
---|
| 1208 | +}; |
---|
| 1209 | + |
---|
| 1210 | +static struct sdhci_arasan_of_data sdhci_arasan_versal_data = { |
---|
| 1211 | + .pdata = &sdhci_arasan_zynqmp_pdata, |
---|
| 1212 | + .clk_ops = &versal_clk_ops, |
---|
| 1213 | +}; |
---|
| 1214 | + |
---|
| 1215 | +static struct sdhci_arasan_of_data intel_keembay_emmc_data = { |
---|
| 1216 | + .soc_ctl_map = &intel_keembay_soc_ctl_map, |
---|
| 1217 | + .pdata = &sdhci_keembay_emmc_pdata, |
---|
| 1218 | + .clk_ops = &arasan_clk_ops, |
---|
| 1219 | +}; |
---|
| 1220 | + |
---|
| 1221 | +static struct sdhci_arasan_of_data intel_keembay_sd_data = { |
---|
| 1222 | + .soc_ctl_map = &intel_keembay_soc_ctl_map, |
---|
| 1223 | + .pdata = &sdhci_keembay_sd_pdata, |
---|
| 1224 | + .clk_ops = &arasan_clk_ops, |
---|
| 1225 | +}; |
---|
| 1226 | + |
---|
| 1227 | +static struct sdhci_arasan_of_data intel_keembay_sdio_data = { |
---|
| 1228 | + .soc_ctl_map = &intel_keembay_soc_ctl_map, |
---|
| 1229 | + .pdata = &sdhci_keembay_sdio_pdata, |
---|
| 1230 | + .clk_ops = &arasan_clk_ops, |
---|
| 1231 | +}; |
---|
| 1232 | + |
---|
| 1233 | +static const struct of_device_id sdhci_arasan_of_match[] = { |
---|
| 1234 | + /* SoC-specific compatible strings w/ soc_ctl_map */ |
---|
| 1235 | + { |
---|
| 1236 | + .compatible = "rockchip,rk3399-sdhci-5.1", |
---|
| 1237 | + .data = &sdhci_arasan_rk3399_data, |
---|
| 1238 | + }, |
---|
| 1239 | + { |
---|
| 1240 | + .compatible = "intel,lgm-sdhci-5.1-emmc", |
---|
| 1241 | + .data = &intel_lgm_emmc_data, |
---|
| 1242 | + }, |
---|
| 1243 | + { |
---|
| 1244 | + .compatible = "intel,lgm-sdhci-5.1-sdxc", |
---|
| 1245 | + .data = &intel_lgm_sdxc_data, |
---|
| 1246 | + }, |
---|
| 1247 | + { |
---|
| 1248 | + .compatible = "intel,keembay-sdhci-5.1-emmc", |
---|
| 1249 | + .data = &intel_keembay_emmc_data, |
---|
| 1250 | + }, |
---|
| 1251 | + { |
---|
| 1252 | + .compatible = "intel,keembay-sdhci-5.1-sd", |
---|
| 1253 | + .data = &intel_keembay_sd_data, |
---|
| 1254 | + }, |
---|
| 1255 | + { |
---|
| 1256 | + .compatible = "intel,keembay-sdhci-5.1-sdio", |
---|
| 1257 | + .data = &intel_keembay_sdio_data, |
---|
| 1258 | + }, |
---|
| 1259 | + /* Generic compatible below here */ |
---|
| 1260 | + { |
---|
| 1261 | + .compatible = "arasan,sdhci-8.9a", |
---|
| 1262 | + .data = &sdhci_arasan_generic_data, |
---|
| 1263 | + }, |
---|
| 1264 | + { |
---|
| 1265 | + .compatible = "arasan,sdhci-5.1", |
---|
| 1266 | + .data = &sdhci_arasan_generic_data, |
---|
| 1267 | + }, |
---|
| 1268 | + { |
---|
| 1269 | + .compatible = "arasan,sdhci-4.9a", |
---|
| 1270 | + .data = &sdhci_arasan_generic_data, |
---|
| 1271 | + }, |
---|
| 1272 | + { |
---|
| 1273 | + .compatible = "xlnx,zynqmp-8.9a", |
---|
| 1274 | + .data = &sdhci_arasan_zynqmp_data, |
---|
| 1275 | + }, |
---|
| 1276 | + { |
---|
| 1277 | + .compatible = "xlnx,versal-8.9a", |
---|
| 1278 | + .data = &sdhci_arasan_versal_data, |
---|
| 1279 | + }, |
---|
| 1280 | + { /* sentinel */ } |
---|
| 1281 | +}; |
---|
| 1282 | +MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match); |
---|
| 1283 | + |
---|
| 1284 | +/** |
---|
| 1285 | + * sdhci_arasan_register_sdcardclk - Register the sdcardclk for a PHY to use |
---|
| 1286 | + * |
---|
| 1287 | + * @sdhci_arasan: Our private data structure. |
---|
| 1288 | + * @clk_xin: Pointer to the functional clock |
---|
| 1289 | + * @dev: Pointer to our struct device. |
---|
| 1290 | + * |
---|
| 1291 | + * Some PHY devices need to know what the actual card clock is. In order for |
---|
| 1292 | + * them to find out, we'll provide a clock through the common clock framework |
---|
| 1293 | + * for them to query. |
---|
| 1294 | + * |
---|
| 1295 | + * Return: 0 on success and error value on error |
---|
| 1296 | + */ |
---|
| 1297 | +static int |
---|
| 1298 | +sdhci_arasan_register_sdcardclk(struct sdhci_arasan_data *sdhci_arasan, |
---|
| 1299 | + struct clk *clk_xin, |
---|
| 1300 | + struct device *dev) |
---|
| 1301 | +{ |
---|
| 1302 | + struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data; |
---|
| 1303 | + struct device_node *np = dev->of_node; |
---|
| 1304 | + struct clk_init_data sdcardclk_init; |
---|
| 1305 | + const char *parent_clk_name; |
---|
| 1306 | + int ret; |
---|
| 1307 | + |
---|
| 1308 | + ret = of_property_read_string_index(np, "clock-output-names", 0, |
---|
| 1309 | + &sdcardclk_init.name); |
---|
| 1310 | + if (ret) { |
---|
| 1311 | + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); |
---|
| 1312 | + return ret; |
---|
| 1313 | + } |
---|
| 1314 | + |
---|
| 1315 | + parent_clk_name = __clk_get_name(clk_xin); |
---|
| 1316 | + sdcardclk_init.parent_names = &parent_clk_name; |
---|
| 1317 | + sdcardclk_init.num_parents = 1; |
---|
| 1318 | + sdcardclk_init.flags = CLK_GET_RATE_NOCACHE; |
---|
| 1319 | + sdcardclk_init.ops = sdhci_arasan->clk_ops->sdcardclk_ops; |
---|
| 1320 | + |
---|
| 1321 | + clk_data->sdcardclk_hw.init = &sdcardclk_init; |
---|
| 1322 | + clk_data->sdcardclk = |
---|
| 1323 | + devm_clk_register(dev, &clk_data->sdcardclk_hw); |
---|
| 1324 | + if (IS_ERR(clk_data->sdcardclk)) |
---|
| 1325 | + return PTR_ERR(clk_data->sdcardclk); |
---|
| 1326 | + clk_data->sdcardclk_hw.init = NULL; |
---|
| 1327 | + |
---|
| 1328 | + ret = of_clk_add_provider(np, of_clk_src_simple_get, |
---|
| 1329 | + clk_data->sdcardclk); |
---|
| 1330 | + if (ret) |
---|
| 1331 | + dev_err(dev, "Failed to add sdcard clock provider\n"); |
---|
| 1332 | + |
---|
| 1333 | + return ret; |
---|
| 1334 | +} |
---|
| 1335 | + |
---|
| 1336 | +/** |
---|
| 1337 | + * sdhci_arasan_register_sampleclk - Register the sampleclk for a PHY to use |
---|
| 1338 | + * |
---|
| 1339 | + * @sdhci_arasan: Our private data structure. |
---|
| 1340 | + * @clk_xin: Pointer to the functional clock |
---|
| 1341 | + * @dev: Pointer to our struct device. |
---|
| 1342 | + * |
---|
| 1343 | + * Some PHY devices need to know what the actual card clock is. In order for |
---|
| 1344 | + * them to find out, we'll provide a clock through the common clock framework |
---|
| 1345 | + * for them to query. |
---|
| 1346 | + * |
---|
| 1347 | + * Return: 0 on success and error value on error |
---|
| 1348 | + */ |
---|
| 1349 | +static int |
---|
| 1350 | +sdhci_arasan_register_sampleclk(struct sdhci_arasan_data *sdhci_arasan, |
---|
| 1351 | + struct clk *clk_xin, |
---|
| 1352 | + struct device *dev) |
---|
| 1353 | +{ |
---|
| 1354 | + struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data; |
---|
| 1355 | + struct device_node *np = dev->of_node; |
---|
| 1356 | + struct clk_init_data sampleclk_init; |
---|
| 1357 | + const char *parent_clk_name; |
---|
| 1358 | + int ret; |
---|
| 1359 | + |
---|
| 1360 | + ret = of_property_read_string_index(np, "clock-output-names", 1, |
---|
| 1361 | + &sampleclk_init.name); |
---|
| 1362 | + if (ret) { |
---|
| 1363 | + dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); |
---|
| 1364 | + return ret; |
---|
| 1365 | + } |
---|
| 1366 | + |
---|
| 1367 | + parent_clk_name = __clk_get_name(clk_xin); |
---|
| 1368 | + sampleclk_init.parent_names = &parent_clk_name; |
---|
| 1369 | + sampleclk_init.num_parents = 1; |
---|
| 1370 | + sampleclk_init.flags = CLK_GET_RATE_NOCACHE; |
---|
| 1371 | + sampleclk_init.ops = sdhci_arasan->clk_ops->sampleclk_ops; |
---|
| 1372 | + |
---|
| 1373 | + clk_data->sampleclk_hw.init = &sampleclk_init; |
---|
| 1374 | + clk_data->sampleclk = |
---|
| 1375 | + devm_clk_register(dev, &clk_data->sampleclk_hw); |
---|
| 1376 | + if (IS_ERR(clk_data->sampleclk)) |
---|
| 1377 | + return PTR_ERR(clk_data->sampleclk); |
---|
| 1378 | + clk_data->sampleclk_hw.init = NULL; |
---|
| 1379 | + |
---|
| 1380 | + ret = of_clk_add_provider(np, of_clk_src_simple_get, |
---|
| 1381 | + clk_data->sampleclk); |
---|
| 1382 | + if (ret) |
---|
| 1383 | + dev_err(dev, "Failed to add sample clock provider\n"); |
---|
| 1384 | + |
---|
| 1385 | + return ret; |
---|
| 1386 | +} |
---|
| 1387 | + |
---|
| 1388 | +/** |
---|
| 1389 | + * sdhci_arasan_unregister_sdclk - Undoes sdhci_arasan_register_sdclk() |
---|
| 1390 | + * |
---|
| 1391 | + * @dev: Pointer to our struct device. |
---|
| 1392 | + * |
---|
| 1393 | + * Should be called any time we're exiting and sdhci_arasan_register_sdclk() |
---|
| 1394 | + * returned success. |
---|
| 1395 | + */ |
---|
| 1396 | +static void sdhci_arasan_unregister_sdclk(struct device *dev) |
---|
| 1397 | +{ |
---|
| 1398 | + struct device_node *np = dev->of_node; |
---|
| 1399 | + |
---|
| 1400 | + if (!of_find_property(np, "#clock-cells", NULL)) |
---|
| 1401 | + return; |
---|
| 1402 | + |
---|
| 1403 | + of_clk_del_provider(dev->of_node); |
---|
| 1404 | +} |
---|
| 1405 | + |
---|
| 1406 | +/** |
---|
| 1407 | + * sdhci_arasan_update_support64b - Set SUPPORT_64B (64-bit System Bus Support) |
---|
| 1408 | + * |
---|
| 1409 | + * This should be set based on the System Address Bus. |
---|
| 1410 | + * 0: the Core supports only 32-bit System Address Bus. |
---|
| 1411 | + * 1: the Core supports 64-bit System Address Bus. |
---|
| 1412 | + * |
---|
| 1413 | + * NOTES: |
---|
| 1414 | + * - For Keem Bay, it is required to clear this bit. Its default value is 1'b1. |
---|
| 1415 | + * Keem Bay does not support 64-bit access. |
---|
| 1416 | + * |
---|
| 1417 | + * @host: The sdhci_host |
---|
| 1418 | + * @value: The value to write |
---|
| 1419 | + */ |
---|
| 1420 | +static void sdhci_arasan_update_support64b(struct sdhci_host *host, u32 value) |
---|
| 1421 | +{ |
---|
| 1422 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
---|
| 1423 | + struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
| 1424 | + const struct sdhci_arasan_soc_ctl_map *soc_ctl_map = |
---|
| 1425 | + sdhci_arasan->soc_ctl_map; |
---|
| 1426 | + |
---|
| 1427 | + /* Having a map is optional */ |
---|
| 1428 | + if (!soc_ctl_map) |
---|
| 1429 | + return; |
---|
| 1430 | + |
---|
| 1431 | + /* If we have a map, we expect to have a syscon */ |
---|
| 1432 | + if (!sdhci_arasan->soc_ctl_base) { |
---|
| 1433 | + pr_warn("%s: Have regmap, but no soc-ctl-syscon\n", |
---|
| 1434 | + mmc_hostname(host->mmc)); |
---|
| 1435 | + return; |
---|
| 1436 | + } |
---|
| 1437 | + |
---|
| 1438 | + sdhci_arasan_syscon_write(host, &soc_ctl_map->support64b, value); |
---|
| 1439 | +} |
---|
| 1440 | + |
---|
| 1441 | +/** |
---|
| 1442 | + * sdhci_arasan_register_sdclk - Register the sdcardclk for a PHY to use |
---|
| 1443 | + * |
---|
| 1444 | + * @sdhci_arasan: Our private data structure. |
---|
| 1445 | + * @clk_xin: Pointer to the functional clock |
---|
| 1446 | + * @dev: Pointer to our struct device. |
---|
594 | 1447 | * |
---|
595 | 1448 | * Some PHY devices need to know what the actual card clock is. In order for |
---|
596 | 1449 | * them to find out, we'll provide a clock through the common clock framework |
---|
.. | .. |
---|
604 | 1457 | * to create nice clean device tree bindings and later (if needed) we can try |
---|
605 | 1458 | * re-architecting SDHCI if we see some benefit to it. |
---|
606 | 1459 | * |
---|
607 | | - * @sdhci_arasan: Our private data structure. |
---|
608 | | - * @clk_xin: Pointer to the functional clock |
---|
609 | | - * @dev: Pointer to our struct device. |
---|
610 | | - * Returns 0 on success and error value on error |
---|
| 1460 | + * Return: 0 on success and error value on error |
---|
611 | 1461 | */ |
---|
612 | 1462 | static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan, |
---|
613 | 1463 | struct clk *clk_xin, |
---|
614 | 1464 | struct device *dev) |
---|
615 | 1465 | { |
---|
616 | 1466 | struct device_node *np = dev->of_node; |
---|
617 | | - struct clk_init_data sdcardclk_init; |
---|
618 | | - const char *parent_clk_name; |
---|
| 1467 | + u32 num_clks = 0; |
---|
619 | 1468 | int ret; |
---|
620 | 1469 | |
---|
621 | 1470 | /* Providing a clock to the PHY is optional; no error if missing */ |
---|
622 | | - if (!of_find_property(np, "#clock-cells", NULL)) |
---|
| 1471 | + if (of_property_read_u32(np, "#clock-cells", &num_clks) < 0) |
---|
623 | 1472 | return 0; |
---|
624 | 1473 | |
---|
625 | | - ret = of_property_read_string_index(np, "clock-output-names", 0, |
---|
626 | | - &sdcardclk_init.name); |
---|
627 | | - if (ret) { |
---|
628 | | - dev_err(dev, "DT has #clock-cells but no clock-output-names\n"); |
---|
| 1474 | + ret = sdhci_arasan_register_sdcardclk(sdhci_arasan, clk_xin, dev); |
---|
| 1475 | + if (ret) |
---|
629 | 1476 | return ret; |
---|
| 1477 | + |
---|
| 1478 | + if (num_clks) { |
---|
| 1479 | + ret = sdhci_arasan_register_sampleclk(sdhci_arasan, clk_xin, |
---|
| 1480 | + dev); |
---|
| 1481 | + if (ret) { |
---|
| 1482 | + sdhci_arasan_unregister_sdclk(dev); |
---|
| 1483 | + return ret; |
---|
| 1484 | + } |
---|
630 | 1485 | } |
---|
631 | 1486 | |
---|
632 | | - parent_clk_name = __clk_get_name(clk_xin); |
---|
633 | | - sdcardclk_init.parent_names = &parent_clk_name; |
---|
634 | | - sdcardclk_init.num_parents = 1; |
---|
635 | | - sdcardclk_init.flags = CLK_GET_RATE_NOCACHE; |
---|
636 | | - sdcardclk_init.ops = &arasan_sdcardclk_ops; |
---|
637 | | - |
---|
638 | | - sdhci_arasan->sdcardclk_hw.init = &sdcardclk_init; |
---|
639 | | - sdhci_arasan->sdcardclk = |
---|
640 | | - devm_clk_register(dev, &sdhci_arasan->sdcardclk_hw); |
---|
641 | | - sdhci_arasan->sdcardclk_hw.init = NULL; |
---|
642 | | - |
---|
643 | | - ret = of_clk_add_provider(np, of_clk_src_simple_get, |
---|
644 | | - sdhci_arasan->sdcardclk); |
---|
645 | | - if (ret) |
---|
646 | | - dev_err(dev, "Failed to add clock provider\n"); |
---|
647 | | - |
---|
648 | | - return ret; |
---|
649 | | -} |
---|
650 | | - |
---|
651 | | -/** |
---|
652 | | - * sdhci_arasan_unregister_sdclk - Undoes sdhci_arasan_register_sdclk() |
---|
653 | | - * |
---|
654 | | - * Should be called any time we're exiting and sdhci_arasan_register_sdclk() |
---|
655 | | - * returned success. |
---|
656 | | - * |
---|
657 | | - * @dev: Pointer to our struct device. |
---|
658 | | - */ |
---|
659 | | -static void sdhci_arasan_unregister_sdclk(struct device *dev) |
---|
660 | | -{ |
---|
661 | | - struct device_node *np = dev->of_node; |
---|
662 | | - |
---|
663 | | - if (!of_find_property(np, "#clock-cells", NULL)) |
---|
664 | | - return; |
---|
665 | | - |
---|
666 | | - of_clk_del_provider(dev->of_node); |
---|
| 1487 | + return 0; |
---|
667 | 1488 | } |
---|
668 | 1489 | |
---|
669 | 1490 | static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan) |
---|
.. | .. |
---|
719 | 1540 | struct sdhci_pltfm_host *pltfm_host; |
---|
720 | 1541 | struct sdhci_arasan_data *sdhci_arasan; |
---|
721 | 1542 | struct device_node *np = pdev->dev.of_node; |
---|
722 | | - const struct sdhci_pltfm_data *pdata; |
---|
| 1543 | + const struct sdhci_arasan_of_data *data; |
---|
723 | 1544 | |
---|
724 | | - if (of_device_is_compatible(pdev->dev.of_node, "arasan,sdhci-5.1")) |
---|
725 | | - pdata = &sdhci_arasan_cqe_pdata; |
---|
726 | | - else |
---|
727 | | - pdata = &sdhci_arasan_pdata; |
---|
728 | | - |
---|
729 | | - host = sdhci_pltfm_init(pdev, pdata, sizeof(*sdhci_arasan)); |
---|
| 1545 | + match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node); |
---|
| 1546 | + data = match->data; |
---|
| 1547 | + host = sdhci_pltfm_init(pdev, data->pdata, sizeof(*sdhci_arasan)); |
---|
730 | 1548 | |
---|
731 | 1549 | if (IS_ERR(host)) |
---|
732 | 1550 | return PTR_ERR(host); |
---|
.. | .. |
---|
735 | 1553 | sdhci_arasan = sdhci_pltfm_priv(pltfm_host); |
---|
736 | 1554 | sdhci_arasan->host = host; |
---|
737 | 1555 | |
---|
738 | | - match = of_match_node(sdhci_arasan_of_match, pdev->dev.of_node); |
---|
739 | | - sdhci_arasan->soc_ctl_map = match->data; |
---|
| 1556 | + sdhci_arasan->soc_ctl_map = data->soc_ctl_map; |
---|
| 1557 | + sdhci_arasan->clk_ops = data->clk_ops; |
---|
740 | 1558 | |
---|
741 | 1559 | node = of_parse_phandle(pdev->dev.of_node, "arasan,soc-ctl-syscon", 0); |
---|
742 | 1560 | if (node) { |
---|
.. | .. |
---|
744 | 1562 | of_node_put(node); |
---|
745 | 1563 | |
---|
746 | 1564 | if (IS_ERR(sdhci_arasan->soc_ctl_base)) { |
---|
747 | | - ret = PTR_ERR(sdhci_arasan->soc_ctl_base); |
---|
748 | | - if (ret != -EPROBE_DEFER) |
---|
749 | | - dev_err(&pdev->dev, "Can't get syscon: %d\n", |
---|
750 | | - ret); |
---|
| 1565 | + ret = dev_err_probe(&pdev->dev, |
---|
| 1566 | + PTR_ERR(sdhci_arasan->soc_ctl_base), |
---|
| 1567 | + "Can't get syscon\n"); |
---|
751 | 1568 | goto err_pltfm_free; |
---|
752 | 1569 | } |
---|
753 | 1570 | } |
---|
.. | .. |
---|
792 | 1609 | "rockchip,rk3399-sdhci-5.1")) |
---|
793 | 1610 | sdhci_arasan_update_clockmultiplier(host, 0x0); |
---|
794 | 1611 | |
---|
| 1612 | + if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || |
---|
| 1613 | + of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || |
---|
| 1614 | + of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) { |
---|
| 1615 | + sdhci_arasan_update_clockmultiplier(host, 0x0); |
---|
| 1616 | + sdhci_arasan_update_support64b(host, 0x0); |
---|
| 1617 | + |
---|
| 1618 | + host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; |
---|
| 1619 | + } |
---|
| 1620 | + |
---|
795 | 1621 | sdhci_arasan_update_baseclkfreq(host); |
---|
796 | 1622 | |
---|
797 | 1623 | ret = sdhci_arasan_register_sdclk(sdhci_arasan, clk_xin, &pdev->dev); |
---|
798 | 1624 | if (ret) |
---|
799 | 1625 | goto clk_disable_all; |
---|
800 | 1626 | |
---|
| 1627 | + if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a")) { |
---|
| 1628 | + host->mmc_host_ops.execute_tuning = |
---|
| 1629 | + arasan_zynqmp_execute_tuning; |
---|
| 1630 | + |
---|
| 1631 | + sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN; |
---|
| 1632 | + } |
---|
| 1633 | + |
---|
| 1634 | + arasan_dt_parse_clk_phases(&pdev->dev, &sdhci_arasan->clk_data); |
---|
| 1635 | + |
---|
801 | 1636 | ret = mmc_of_parse(host->mmc); |
---|
802 | 1637 | if (ret) { |
---|
803 | 1638 | if (ret != -EPROBE_DEFER) |
---|