aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch270
1 files changed, 270 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch
new file mode 100644
index 00000000..a11eeb1a
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/0853-AMD-eMMC-5.0-support.patch
@@ -0,0 +1,270 @@
+From 78fc88276c47e54dd7378827f404b2abcd4e009d Mon Sep 17 00:00:00 2001
+From: Sudheesh Mavila <sudheesh.mavila@amd.com>
+Date: Wed, 31 Jan 2018 16:01:25 +0530
+Subject: [PATCH 0853/4131] AMD eMMC 5.0 support
+
+Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
+---
+ drivers/acpi/resource.c | 5 +++
+ drivers/mmc/core/mmc.c | 6 +--
+ drivers/mmc/host/sdhci-acpi.c | 87 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/mmc/host/sdhci.c | 3 +-
+ drivers/mmc/host/sdhci.h | 5 +++
+ include/linux/mmc/host.h | 6 +++
+ 6 files changed, 108 insertions(+), 4 deletions(-)
+ mode change 100644 => 100755 drivers/acpi/resource.c
+ mode change 100644 => 100755 drivers/mmc/core/mmc.c
+ mode change 100644 => 100755 drivers/mmc/host/sdhci-acpi.c
+ mode change 100644 => 100755 drivers/mmc/host/sdhci.c
+ mode change 100644 => 100755 drivers/mmc/host/sdhci.h
+ mode change 100644 => 100755 include/linux/mmc/host.h
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+old mode 100644
+new mode 100755
+index d85e010..e82b5a7
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -425,6 +425,11 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
+ triggering = trig;
+ polarity = pol;
+ }
++ if (gsi == 5) {
++ polarity = ACPI_ACTIVE_LOW;
++ pr_warning("ACPI: IRQ %d do not override to %s, %s\n", gsi,
++ t ? "level" : "edge", p ? "low" : "high");
++ }
+ }
+
+ res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
+diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
+old mode 100644
+new mode 100755
+index bad5c1b..7ba25a2
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -1164,7 +1164,7 @@ static int mmc_select_hs400(struct mmc_card *card)
+
+ /* Set host controller to HS timing */
+ mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
+-
++ host->ios.transition = HS200_TO_HS_TO_HS400;
+ /* Reduce frequency to HS frequency */
+ max_dtr = card->ext_csd.hs_max_dtr;
+ mmc_set_clock(host, max_dtr);
+@@ -1196,7 +1196,7 @@ static int mmc_select_hs400(struct mmc_card *card)
+ mmc_hostname(host), err);
+ return err;
+ }
+-
++ host->ios.transition = SWITCHING_TO_HS400;
+ /* Set host controller to HS400 timing and frequency */
+ mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+ mmc_set_bus_speed(card);
+@@ -1204,7 +1204,7 @@ static int mmc_select_hs400(struct mmc_card *card)
+ err = mmc_switch_status(card);
+ if (err)
+ goto out_err;
+-
++ host->ios.transition = SWITCHED_TO_HS400;
+ return 0;
+
+ out_err:
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+old mode 100644
+new mode 100755
+index 08ae0ff..aac8f1f
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -89,6 +89,47 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
+ return c->slot && (c->slot->flags & flag);
+ }
+
++ /*AMD Driver Strength function*/
++
++static int amd_select_drive_strength(struct mmc_card *card,
++ unsigned int max_dtr, int host_drv,
++ int card_drv, int *drv_type)
++{
++ return MMC_SET_DRIVER_TYPE_A;
++}
++
++static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host)
++{
++ /*AMD Platform requires dll setting*/
++ sdhci_writel(host, 0x40003210, SDHCI_AMD_REST_DLL_REGISTER);
++ udelay(10);
++ sdhci_writel(host, 0x40033210, SDHCI_AMD_REST_DLL_REGISTER);
++}
++
++/*
++ * 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.
++ */
++
++static void sdhci_amd_set_hs400_transition(struct sdhci_host *host)
++{
++ switch (host->mmc->ios.transition) {
++ case HS200_TO_HS_TO_HS400:
++ sdhci_writew(host, 0x9, SDHCI_HOST_CONTROL2);
++ break;
++
++ case SWITCHING_TO_HS400:
++ sdhci_writew(host, 0x80, SDHCI_HOST_CONTROL2);
++ sdhci_acpi_amd_hs400_dll(host);
++ break;
++
++ case SWITCHED_TO_HS400:
++ default:
++ break;
++ }
++}
++
+ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)
+ {
+ u8 reg;
+@@ -123,6 +164,18 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
+ .ops = &sdhci_acpi_ops_int,
+ };
+
++static const struct sdhci_ops sdhci_acpi_ops_amd = {
++ .set_clock = sdhci_set_clock,
++ .set_bus_width = sdhci_set_bus_width,
++ .reset = sdhci_reset,
++ .set_uhs_signaling = sdhci_set_uhs_signaling,
++ .set_platform_hs400_transition = sdhci_amd_set_hs400_transition,
++};
++
++static const struct sdhci_acpi_chip sdhci_acpi_chip_amd = {
++ .ops = &sdhci_acpi_ops_amd,
++};
++
+ #ifdef CONFIG_X86
+
+ static bool sdhci_acpi_byt(void)
+@@ -269,6 +322,31 @@ static int bxt_get_cd(struct mmc_host *mmc)
+ return ret;
+ }
+
++static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev,
++ const char *hid, const char *uid)
++{
++ struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
++ struct sdhci_host *host;
++ unsigned int caps1, caps;
++ if (!c || !c->host)
++ return 0;
++
++ host = c->host;
++
++ caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
++ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
++
++ if (caps1 & SDHCI_SUPPORT_DDR50)
++ host->mmc->caps = MMC_CAP_1_8V_DDR;
++
++ if ((caps1 & SDHCI_SUPPORT_SDR104) &&
++ (host->mmc->caps & MMC_CAP_1_8V_DDR))
++ host->mmc->caps2 = MMC_CAP2_HS400_1_8V;
++
++ host->mmc_host_ops.select_drive_strength = amd_select_drive_strength;
++ return 0;
++}
++
+ static int sdhci_acpi_emmc_probe_slot(struct platform_device *pdev,
+ const char *hid, const char *uid)
+ {
+@@ -367,6 +445,13 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_qcom_sd = {
+ .caps = MMC_CAP_NONREMOVABLE,
+ };
+
++static const struct sdhci_acpi_slot sdhci_acpi_slot_amd_emmc = {
++ .chip = &sdhci_acpi_chip_amd,
++ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET,
++ .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE |
++ SDHCI_QUIRK_32BIT_ADMA_SIZE,
++ .probe_slot = sdhci_acpi_emmc_amd_probe_slot,
++};
+ struct sdhci_acpi_uid_slot {
+ const char *hid;
+ const char *uid;
+@@ -390,6 +475,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
+ { "PNP0D40" },
+ { "QCOM8051", NULL, &sdhci_acpi_slot_qcom_sd_3v },
+ { "QCOM8052", NULL, &sdhci_acpi_slot_qcom_sd },
++ { "AMDI0040", NULL, &sdhci_acpi_slot_amd_emmc},
+ { },
+ };
+
+@@ -406,6 +492,7 @@ static const struct acpi_device_id sdhci_acpi_ids[] = {
+ { "PNP0D40" },
+ { "QCOM8051" },
+ { "QCOM8052" },
++ { "AMDI0040" },
+ { },
+ };
+ MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+old mode 100644
+new mode 100755
+index d35deb7..da341b0
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -1687,7 +1687,8 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+ host->ops->set_power(host, ios->power_mode, ios->vdd);
+ else
+ sdhci_set_power(host, ios->power_mode, ios->vdd);
+-
++ if (host->ops->set_platform_hs400_transition)
++ host->ops->set_platform_hs400_transition(host);
+ if (host->ops->platform_send_init_74_clocks)
+ host->ops->platform_send_init_74_clocks(host, ios->power_mode);
+
+diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
+old mode 100644
+new mode 100755
+index 1d7d61e..c6569ba
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -271,6 +271,9 @@
+ #define SDHCI_SPEC_200 1
+ #define SDHCI_SPEC_300 2
+
++/* AMD sdhci reset dll register.*/
++#define SDHCI_AMD_REST_DLL_REGISTER 0x908
++
+ /*
+ * End of controller registers.
+ */
+@@ -579,6 +582,8 @@ struct sdhci_ops {
+ void (*set_bus_width)(struct sdhci_host *host, int width);
+ void (*platform_send_init_74_clocks)(struct sdhci_host *host,
+ u8 power_mode);
++ /* ios for transiton phase for going to hs400 */
++ void (*set_platform_hs400_transition)(struct sdhci_host *host);
+ unsigned int (*get_ro)(struct sdhci_host *host);
+ void (*reset)(struct sdhci_host *host, u8 mask);
+ int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode);
+diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
+old mode 100644
+new mode 100755
+index 9a43763..ae16bc5
+--- a/include/linux/mmc/host.h
++++ b/include/linux/mmc/host.h
+@@ -77,6 +77,12 @@ struct mmc_ios {
+ #define MMC_SET_DRIVER_TYPE_D 3
+
+ bool enhanced_strobe; /* hs400es selection */
++
++ unsigned int transition; /* track transition modes (hs200 hs400) */
++
++#define HS200_TO_HS_TO_HS400 1
++#define SWITCHING_TO_HS400 2
++#define SWITCHED_TO_HS400 3
+ };
+
+ struct mmc_host;
+--
+2.7.4
+