MMC host:
- sdhci-acpi: Fix HS400 tuning for AMDI0040 - sdhci-pci: Fix reset of CQHCI for Intel GLK-based controllers - sdhci-tegra: Use correct timeout clock for Tegra186/194/210 - mtk-sd: Fix eMMC mounting on mt7622/Bpi-64 -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAl9M2g4XHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCkmBA//YUe2Wx6bFAEawUI0AxUxPLXO 6zXgwKiJgCLbgdICSbhzS/I4N8iTyT+tiRUyk78UukgKOfDH/yIkeNenqf+gWINq lWDJGqboj9Hn1Cm0D2qSTqPs2AJL0k6WhBFBUFvtSYtqqk/j0VVRkrpRqb96X2MK bGXnv0hTTed8uX/VtjHTzmj+8CMtVmHzzlC0eALYLJpNOklmbn3agDpXbpGbIDsk 5oaTqLmRRROcvxQDes/y5HnckdQ9q13LHEiI10BSIFG6qDQ4t8KsoJGdGgola3Hq +oD6R/WcikM+dwuAB8jNmnSpsot6vltg2czdQ+y18RtccPpwPzpRrICFBKoayPDu QXG/5cd6kgS+XX/25eF5GrkR66ztEjckQm1aOgpx3yfPZJLuXhy3Rkt1DGUa+HOT rVaz3dngUJapO/pCl8Oy89e59zBd9yDsUVAmmUFchIiI2dthn7UReEaP7wnSc5uh 5pK+GZfBSXK3h1E5ky7QwEY2DJ8LmqqkdyCCZHeQUPoS7lemVWH47BbuJ/zmnNoW VyBd+BwmW3RCn4XwpjqsOp2Ppb8MeLpPBD6m+1vd7J9eNdhgClQfpnldOzVmzG8E 4baveGrPRIGQPXoXRAOjZfd/bTx7TfteT3vIZCH+pwkTItw0x2xi1NLwjOGXPDDE YLhYfGFfNFPX206UiRw= =rYDw -----END PGP SIGNATURE----- Merge tag 'mmc-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: - Fix HS400 tuning for ACPI ID AMDI0040 - Fix reset of CQHCI for Intel GLK-based controllers - Use correct timeout clock for Tegra186/194/210 - Fix eMMC mounting on mt7622/Bpi-64 * tag 'mmc-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: sdhci: tegra: Add missing TMCLK for data timeout arm64: tegra: Add missing timeout clock to Tegra194 SDMMC nodes arm64: tegra: Add missing timeout clock to Tegra186 SDMMC nodes arm64: tegra: Add missing timeout clock to Tegra210 SDMMC dt-bindings: mmc: tegra: Add tmclk for Tegra210 and later sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra186 sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra210 arm64: dts: mt7622: add reset node for mmc device dt-bindings: mmc: Add missing description for clk_in/out_sd1 mmc: mediatek: add optional module reset property mmc: dt-bindings: Add resets/reset-names for Mediatek MMC bindings mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based controllers mmc: sdhci-acpi: Fix HS400 tuning for AMDI0040
This commit is contained in:
commit
59815d6d1c
@ -30,9 +30,13 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
clock-output-names:
|
||||
items:
|
||||
- const: clk_out_sd0
|
||||
- const: clk_in_sd0
|
||||
oneOf:
|
||||
- items:
|
||||
- const: clk_out_sd0
|
||||
- const: clk_in_sd0
|
||||
- items:
|
||||
- const: clk_out_sd1
|
||||
- const: clk_in_sd1
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -50,6 +50,8 @@ Optional properties:
|
||||
error caused by stop clock(fifo full)
|
||||
Valid range = [0:0x7]. if not present, default value is 0.
|
||||
applied to compatible "mediatek,mt2701-mmc".
|
||||
- resets: Phandle and reset specifier pair to softreset line of MSDC IP.
|
||||
- reset-names: Should be "hrst".
|
||||
|
||||
Examples:
|
||||
mmc0: mmc@11230000 {
|
||||
|
@ -15,8 +15,15 @@ Required properties:
|
||||
- "nvidia,tegra210-sdhci": for Tegra210
|
||||
- "nvidia,tegra186-sdhci": for Tegra186
|
||||
- "nvidia,tegra194-sdhci": for Tegra194
|
||||
- clocks : Must contain one entry, for the module clock.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- clocks: For Tegra210, Tegra186 and Tegra194 must contain two entries.
|
||||
One for the module clock and one for the timeout clock.
|
||||
For all other Tegra devices, must contain a single entry for
|
||||
the module clock. See ../clocks/clock-bindings.txt for details.
|
||||
- clock-names: For Tegra210, Tegra186 and Tegra194 must contain the
|
||||
strings 'sdhci' and 'tmclk' to represent the module and
|
||||
the timeout clocks, respectively.
|
||||
For all other Tegra devices must contain the string 'sdhci'
|
||||
to represent the module clock.
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names : Must include the following entries:
|
||||
@ -99,7 +106,7 @@ Optional properties for Tegra210, Tegra186 and Tegra194:
|
||||
|
||||
Example:
|
||||
sdhci@700b0000 {
|
||||
compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
|
||||
compatible = "nvidia,tegra124-sdhci";
|
||||
reg = <0x0 0x700b0000 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC1>;
|
||||
@ -115,3 +122,22 @@ sdhci@700b0000 {
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdhci@700b0000 {
|
||||
compatible = "nvidia,tegra210-sdhci";
|
||||
reg = <0x0 0x700b0000 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
|
||||
<&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&tegra_car 14>;
|
||||
reset-names = "sdhci";
|
||||
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
|
||||
pinctrl-0 = <&sdmmc1_3v3>;
|
||||
pinctrl-1 = <&sdmmc1_1v8>;
|
||||
nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
|
||||
nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
|
||||
nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
|
||||
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -686,6 +686,8 @@
|
||||
clocks = <&pericfg CLK_PERI_MSDC30_0_PD>,
|
||||
<&topckgen CLK_TOP_MSDC50_0_SEL>;
|
||||
clock-names = "source", "hclk";
|
||||
resets = <&pericfg MT7622_PERI_MSDC0_SW_RST>;
|
||||
reset-names = "hrst";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -337,8 +337,9 @@
|
||||
compatible = "nvidia,tegra186-sdhci";
|
||||
reg = <0x0 0x03400000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC1>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC1>,
|
||||
<&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&bpmp TEGRA186_RESET_SDMMC1>;
|
||||
reset-names = "sdhci";
|
||||
interconnects = <&mc TEGRA186_MEMORY_CLIENT_SDMMCRA &emc>,
|
||||
@ -366,8 +367,9 @@
|
||||
compatible = "nvidia,tegra186-sdhci";
|
||||
reg = <0x0 0x03420000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC2>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC2>,
|
||||
<&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&bpmp TEGRA186_RESET_SDMMC2>;
|
||||
reset-names = "sdhci";
|
||||
interconnects = <&mc TEGRA186_MEMORY_CLIENT_SDMMCRAA &emc>,
|
||||
@ -390,8 +392,9 @@
|
||||
compatible = "nvidia,tegra186-sdhci";
|
||||
reg = <0x0 0x03440000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC3>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC3>,
|
||||
<&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&bpmp TEGRA186_RESET_SDMMC3>;
|
||||
reset-names = "sdhci";
|
||||
interconnects = <&mc TEGRA186_MEMORY_CLIENT_SDMMCR &emc>,
|
||||
@ -416,8 +419,9 @@
|
||||
compatible = "nvidia,tegra186-sdhci";
|
||||
reg = <0x0 0x03460000 0x0 0x10000>;
|
||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC4>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA186_CLK_SDMMC4>,
|
||||
<&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
assigned-clocks = <&bpmp TEGRA186_CLK_SDMMC4>,
|
||||
<&bpmp TEGRA186_CLK_PLLC4_VCO>;
|
||||
assigned-clock-parents = <&bpmp TEGRA186_CLK_PLLC4_VCO>;
|
||||
|
@ -460,8 +460,9 @@
|
||||
compatible = "nvidia,tegra194-sdhci";
|
||||
reg = <0x03400000 0x10000>;
|
||||
interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC1>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC1>,
|
||||
<&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&bpmp TEGRA194_RESET_SDMMC1>;
|
||||
reset-names = "sdhci";
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_SDMMCRA &emc>,
|
||||
@ -485,8 +486,9 @@
|
||||
compatible = "nvidia,tegra194-sdhci";
|
||||
reg = <0x03440000 0x10000>;
|
||||
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC3>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC3>,
|
||||
<&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&bpmp TEGRA194_RESET_SDMMC3>;
|
||||
reset-names = "sdhci";
|
||||
interconnects = <&mc TEGRA194_MEMORY_CLIENT_SDMMCR &emc>,
|
||||
@ -511,8 +513,9 @@
|
||||
compatible = "nvidia,tegra194-sdhci";
|
||||
reg = <0x03460000 0x10000>;
|
||||
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC4>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&bpmp TEGRA194_CLK_SDMMC4>,
|
||||
<&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
assigned-clocks = <&bpmp TEGRA194_CLK_SDMMC4>,
|
||||
<&bpmp TEGRA194_CLK_PLLC4>;
|
||||
assigned-clock-parents =
|
||||
|
@ -1194,8 +1194,9 @@
|
||||
compatible = "nvidia,tegra210-sdhci";
|
||||
reg = <0x0 0x700b0000 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC1>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
|
||||
<&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&tegra_car 14>;
|
||||
reset-names = "sdhci";
|
||||
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8",
|
||||
@ -1222,8 +1223,9 @@
|
||||
compatible = "nvidia,tegra210-sdhci";
|
||||
reg = <0x0 0x700b0200 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC2>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC2>,
|
||||
<&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&tegra_car 9>;
|
||||
reset-names = "sdhci";
|
||||
pinctrl-names = "sdmmc-1v8-drv";
|
||||
@ -1239,8 +1241,9 @@
|
||||
compatible = "nvidia,tegra210-sdhci";
|
||||
reg = <0x0 0x700b0400 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC3>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC3>,
|
||||
<&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&tegra_car 69>;
|
||||
reset-names = "sdhci";
|
||||
pinctrl-names = "sdmmc-3v3", "sdmmc-1v8",
|
||||
@ -1262,8 +1265,9 @@
|
||||
compatible = "nvidia,tegra210-sdhci";
|
||||
reg = <0x0 0x700b0600 0x0 0x200>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC4>;
|
||||
clock-names = "sdhci";
|
||||
clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
|
||||
<&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
|
||||
clock-names = "sdhci", "tmclk";
|
||||
resets = <&tegra_car 15>;
|
||||
reset-names = "sdhci";
|
||||
pinctrl-names = "sdmmc-3v3-drv", "sdmmc-1v8-drv";
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/core.h>
|
||||
@ -419,6 +420,7 @@ struct msdc_host {
|
||||
struct pinctrl_state *pins_uhs;
|
||||
struct delayed_work req_timeout;
|
||||
int irq; /* host interrupt */
|
||||
struct reset_control *reset;
|
||||
|
||||
struct clk *src_clk; /* msdc source clock */
|
||||
struct clk *h_clk; /* msdc h_clk */
|
||||
@ -1592,6 +1594,12 @@ static void msdc_init_hw(struct msdc_host *host)
|
||||
u32 val;
|
||||
u32 tune_reg = host->dev_comp->pad_tune_reg;
|
||||
|
||||
if (host->reset) {
|
||||
reset_control_assert(host->reset);
|
||||
usleep_range(10, 50);
|
||||
reset_control_deassert(host->reset);
|
||||
}
|
||||
|
||||
/* Configure to MMC/SD mode, clock free running */
|
||||
sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
|
||||
|
||||
@ -2390,6 +2398,11 @@ static int msdc_drv_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(host->src_clk_cg))
|
||||
host->src_clk_cg = NULL;
|
||||
|
||||
host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
|
||||
"hrst");
|
||||
if (IS_ERR(host->reset))
|
||||
return PTR_ERR(host->reset);
|
||||
|
||||
host->irq = platform_get_irq(pdev, 0);
|
||||
if (host->irq < 0) {
|
||||
ret = -EINVAL;
|
||||
|
@ -535,6 +535,11 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd = {
|
||||
.caps = MMC_CAP_NONREMOVABLE,
|
||||
};
|
||||
|
||||
struct amd_sdhci_host {
|
||||
bool tuned_clock;
|
||||
bool dll_enabled;
|
||||
};
|
||||
|
||||
/* AMD sdhci reset dll register. */
|
||||
#define SDHCI_AMD_RESET_DLL_REGISTER 0x908
|
||||
|
||||
@ -555,26 +560,66 @@ static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host)
|
||||
}
|
||||
|
||||
/*
|
||||
* For AMD Platform it is required to disable the tuning
|
||||
* bit first controller to bring to HS Mode from HS200
|
||||
* mode, later enable to tune to HS400 mode.
|
||||
* The initialization sequence for HS400 is:
|
||||
* HS->HS200->Perform Tuning->HS->HS400
|
||||
*
|
||||
* The re-tuning sequence is:
|
||||
* HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400
|
||||
*
|
||||
* The AMD eMMC Controller can only use the tuned clock while in HS200 and HS400
|
||||
* mode. If we switch to a different mode, we need to disable the tuned clock.
|
||||
* If we have previously performed tuning and switch back to HS200 or
|
||||
* HS400, we can re-enable the tuned clock.
|
||||
*
|
||||
*/
|
||||
static void amd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
|
||||
struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
|
||||
unsigned int old_timing = host->timing;
|
||||
u16 val;
|
||||
|
||||
sdhci_set_ios(mmc, ios);
|
||||
if (old_timing == MMC_TIMING_MMC_HS200 &&
|
||||
ios->timing == MMC_TIMING_MMC_HS)
|
||||
sdhci_writew(host, 0x9, SDHCI_HOST_CONTROL2);
|
||||
if (old_timing != MMC_TIMING_MMC_HS400 &&
|
||||
ios->timing == MMC_TIMING_MMC_HS400) {
|
||||
sdhci_writew(host, 0x80, SDHCI_HOST_CONTROL2);
|
||||
sdhci_acpi_amd_hs400_dll(host);
|
||||
|
||||
if (old_timing != host->timing && amd_host->tuned_clock) {
|
||||
if (host->timing == MMC_TIMING_MMC_HS400 ||
|
||||
host->timing == MMC_TIMING_MMC_HS200) {
|
||||
val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
val |= SDHCI_CTRL_TUNED_CLK;
|
||||
sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
|
||||
} else {
|
||||
val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
val &= ~SDHCI_CTRL_TUNED_CLK;
|
||||
sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
|
||||
}
|
||||
|
||||
/* DLL is only required for HS400 */
|
||||
if (host->timing == MMC_TIMING_MMC_HS400 &&
|
||||
!amd_host->dll_enabled) {
|
||||
sdhci_acpi_amd_hs400_dll(host);
|
||||
amd_host->dll_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
{
|
||||
int err;
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
|
||||
struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
|
||||
|
||||
amd_host->tuned_clock = false;
|
||||
|
||||
err = sdhci_execute_tuning(mmc, opcode);
|
||||
|
||||
if (!err && !host->tuning_err)
|
||||
amd_host->tuned_clock = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct sdhci_ops sdhci_acpi_ops_amd = {
|
||||
.set_clock = sdhci_set_clock,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
@ -602,6 +647,7 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev,
|
||||
|
||||
host->mmc_host_ops.select_drive_strength = amd_select_drive_strength;
|
||||
host->mmc_host_ops.set_ios = amd_set_ios;
|
||||
host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -613,6 +659,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_amd_emmc = {
|
||||
SDHCI_QUIRK_32BIT_ADMA_SIZE,
|
||||
.quirks2 = SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
|
||||
.probe_slot = sdhci_acpi_emmc_amd_probe_slot,
|
||||
.priv_size = sizeof(struct amd_sdhci_host),
|
||||
};
|
||||
|
||||
struct sdhci_acpi_uid_slot {
|
||||
|
@ -232,6 +232,14 @@ static void sdhci_pci_dumpregs(struct mmc_host *mmc)
|
||||
sdhci_dumpregs(mmc_priv(mmc));
|
||||
}
|
||||
|
||||
static void sdhci_cqhci_reset(struct sdhci_host *host, u8 mask)
|
||||
{
|
||||
if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
|
||||
host->mmc->cqe_private)
|
||||
cqhci_deactivate(host->mmc);
|
||||
sdhci_reset(host, mask);
|
||||
}
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* Hardware specific quirk handling *
|
||||
@ -718,7 +726,7 @@ static const struct sdhci_ops sdhci_intel_glk_ops = {
|
||||
.set_power = sdhci_intel_set_power,
|
||||
.enable_dma = sdhci_pci_enable_dma,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.reset = sdhci_reset,
|
||||
.reset = sdhci_cqhci_reset,
|
||||
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
.hw_reset = sdhci_pci_hw_reset,
|
||||
.irq = sdhci_cqhci_irq,
|
||||
|
@ -110,6 +110,12 @@
|
||||
#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
|
||||
#define NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING BIT(9)
|
||||
|
||||
/*
|
||||
* NVQUIRK_HAS_TMCLK is for SoC's having separate timeout clock for Tegra
|
||||
* SDMMC hardware data timeout.
|
||||
*/
|
||||
#define NVQUIRK_HAS_TMCLK BIT(10)
|
||||
|
||||
/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
|
||||
#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
|
||||
|
||||
@ -140,6 +146,7 @@ struct sdhci_tegra_autocal_offsets {
|
||||
struct sdhci_tegra {
|
||||
const struct sdhci_tegra_soc_data *soc_data;
|
||||
struct gpio_desc *power_gpio;
|
||||
struct clk *tmclk;
|
||||
bool ddr_signaling;
|
||||
bool pad_calib_required;
|
||||
bool pad_control_available;
|
||||
@ -1418,7 +1425,6 @@ static const struct sdhci_ops tegra210_sdhci_ops = {
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
|
||||
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
|
||||
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
|
||||
SDHCI_QUIRK_SINGLE_POWER_WRITE |
|
||||
SDHCI_QUIRK_NO_HISPD_BIT |
|
||||
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
|
||||
@ -1434,7 +1440,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
|
||||
NVQUIRK_HAS_PADCALIB |
|
||||
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
||||
NVQUIRK_ENABLE_SDR50 |
|
||||
NVQUIRK_ENABLE_SDR104,
|
||||
NVQUIRK_ENABLE_SDR104 |
|
||||
NVQUIRK_HAS_TMCLK,
|
||||
.min_tap_delay = 106,
|
||||
.max_tap_delay = 185,
|
||||
};
|
||||
@ -1456,7 +1463,6 @@ static const struct sdhci_ops tegra186_sdhci_ops = {
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
|
||||
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
|
||||
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
|
||||
SDHCI_QUIRK_SINGLE_POWER_WRITE |
|
||||
SDHCI_QUIRK_NO_HISPD_BIT |
|
||||
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
|
||||
@ -1473,6 +1479,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
|
||||
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
||||
NVQUIRK_ENABLE_SDR50 |
|
||||
NVQUIRK_ENABLE_SDR104 |
|
||||
NVQUIRK_HAS_TMCLK |
|
||||
NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING,
|
||||
.min_tap_delay = 84,
|
||||
.max_tap_delay = 136,
|
||||
@ -1485,7 +1492,8 @@ static const struct sdhci_tegra_soc_data soc_data_tegra194 = {
|
||||
NVQUIRK_HAS_PADCALIB |
|
||||
NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
|
||||
NVQUIRK_ENABLE_SDR50 |
|
||||
NVQUIRK_ENABLE_SDR104,
|
||||
NVQUIRK_ENABLE_SDR104 |
|
||||
NVQUIRK_HAS_TMCLK,
|
||||
.min_tap_delay = 96,
|
||||
.max_tap_delay = 139,
|
||||
};
|
||||
@ -1613,6 +1621,43 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
|
||||
goto err_power_req;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tegra210 has a separate SDMMC_LEGACY_TM clock used for host
|
||||
* timeout clock and SW can choose TMCLK or SDCLK for hardware
|
||||
* data timeout through the bit USE_TMCLK_FOR_DATA_TIMEOUT of
|
||||
* the register SDHCI_TEGRA_VENDOR_SYS_SW_CTRL.
|
||||
*
|
||||
* USE_TMCLK_FOR_DATA_TIMEOUT bit default is set to 1 and SDMMC uses
|
||||
* 12Mhz TMCLK which is advertised in host capability register.
|
||||
* With TMCLK of 12Mhz provides maximum data timeout period that can
|
||||
* be achieved is 11s better than using SDCLK for data timeout.
|
||||
*
|
||||
* So, TMCLK is set to 12Mhz and kept enabled all the time on SoC's
|
||||
* supporting separate TMCLK.
|
||||
*/
|
||||
|
||||
if (soc_data->nvquirks & NVQUIRK_HAS_TMCLK) {
|
||||
clk = devm_clk_get(&pdev->dev, "tmclk");
|
||||
if (IS_ERR(clk)) {
|
||||
rc = PTR_ERR(clk);
|
||||
if (rc == -EPROBE_DEFER)
|
||||
goto err_power_req;
|
||||
|
||||
dev_warn(&pdev->dev, "failed to get tmclk: %d\n", rc);
|
||||
clk = NULL;
|
||||
}
|
||||
|
||||
clk_set_rate(clk, 12000000);
|
||||
rc = clk_prepare_enable(clk);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to enable tmclk: %d\n", rc);
|
||||
goto err_power_req;
|
||||
}
|
||||
|
||||
tegra_host->tmclk = clk;
|
||||
}
|
||||
|
||||
clk = devm_clk_get(mmc_dev(host->mmc), NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
rc = PTR_ERR(clk);
|
||||
@ -1656,6 +1701,7 @@ err_add_host:
|
||||
err_rst_get:
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
err_clk_get:
|
||||
clk_disable_unprepare(tegra_host->tmclk);
|
||||
err_power_req:
|
||||
err_parse_dt:
|
||||
sdhci_pltfm_free(pdev);
|
||||
@ -1673,6 +1719,7 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
|
||||
reset_control_assert(tegra_host->rst);
|
||||
usleep_range(2000, 4000);
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
clk_disable_unprepare(tegra_host->tmclk);
|
||||
|
||||
sdhci_pltfm_free(pdev);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user