]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mmc: sdhci-pci-dwc-mshc: synopsys dwc mshc support
authorPrabu Thangamuthu <Prabu.T@synopsys.com>
Wed, 11 Jul 2018 07:56:17 +0000 (13:26 +0530)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 16 Jul 2018 09:21:45 +0000 (11:21 +0200)
Synopsys has DWC MSHC controller on HPAS-DX platform connected using PCIe
interface with SD card slot and eMMC device slots. This patch is to
enable SD cards connected on this platform. As Clock generation logic
is implemented using MMCM module of HAPS-DX platform, we have separate
functions to control the MMCM to generate required clocks with respect
to speed mode.

Signed-off-by: Prabu Thangamuthu <prabu.t@synopsys.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
MAINTAINERS
drivers/mmc/host/Makefile
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci-pci-dwc-mshc.c [new file with mode: 0644]
drivers/mmc/host/sdhci-pci.h

index 192d7f73fd017255d0697bad499244655463b366..aa50f070b3b57764a29886a62a4da1eaa7caed35 100644 (file)
@@ -12745,6 +12745,13 @@ S:     Maintained
 F:     drivers/mmc/host/sdhci*
 F:     include/linux/mmc/sdhci*
 
+SYNOPSYS SDHCI COMPLIANT DWC MSHC DRIVER
+M:     Prabu Thangamuthu <prabu.t@synopsys.com>
+M:     Manjunath M B <manjumb@synopsys.com>
+L:     linux-mmc@vger.kernel.org
+S:     Maintained
+F:     drivers/mmc/host/sdhci-pci-dwc-mshc.c
+
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
 M:     Ben Dooks <ben-linux@fluff.org>
 M:     Jaehoon Chung <jh80.chung@samsung.com>
index a18fbba1b97e792578f713d991eaf967ab470392..ce8398e6f2c0e49395c4a818c95ecb1e69d6b87e 100644 (file)
@@ -11,7 +11,8 @@ obj-$(CONFIG_MMC_MXC)         += mxcmmc.o
 obj-$(CONFIG_MMC_MXS)          += mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
-sdhci-pci-y                    += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o
+sdhci-pci-y                    += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \
+                                  sdhci-pci-dwc-mshc.o
 obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI))       += sdhci-pci-data.o
 obj-$(CONFIG_MMC_SDHCI_ACPI)   += sdhci-acpi.o
 obj-$(CONFIG_MMC_SDHCI_PXAV3)  += sdhci-pxav3.o
index 3d367613275b8002d35214e4b63b107ab774ee5a..7bfd366d970dae374bae6acd36624eb23f719506 100644 (file)
@@ -1513,6 +1513,7 @@ static const struct pci_device_id pci_ids[] = {
        SDHCI_PCI_DEVICE(O2, SEABIRD0, o2),
        SDHCI_PCI_DEVICE(O2, SEABIRD1, o2),
        SDHCI_PCI_DEVICE(ARASAN, PHY_EMMC, arasan),
+       SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps),
        SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd),
        /* Generic SD host controller */
        {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},
diff --git a/drivers/mmc/host/sdhci-pci-dwc-mshc.c b/drivers/mmc/host/sdhci-pci-dwc-mshc.c
new file mode 100644 (file)
index 0000000..f78d654
--- /dev/null
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SDHCI driver for Synopsys DWC_MSHC controller
+ *
+ * Copyright (C) 2018 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Authors:
+ *     Prabu Thangamuthu <prabu.t@synopsys.com>
+ *     Manjunath M B <manjumb@synopsys.com>
+ */
+
+#include "sdhci.h"
+#include "sdhci-pci.h"
+
+#define SDHCI_VENDOR_PTR_R     0xE8
+
+/* Synopsys vendor specific registers */
+#define SDHC_GPIO_OUT          0x34
+#define SDHC_AT_CTRL_R         0x40
+#define SDHC_SW_TUNE_EN                0x00000010
+
+/* MMCM DRP */
+#define SDHC_MMCM_DIV_REG      0x1020
+#define DIV_REG_100_MHZ                0x1145
+#define DIV_REG_200_MHZ                0x1083
+#define SDHC_MMCM_CLKFBOUT     0x1024
+#define CLKFBOUT_100_MHZ       0x0000
+#define CLKFBOUT_200_MHZ       0x0080
+#define SDHC_CCLK_MMCM_RST     0x00000001
+
+static void sdhci_snps_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+       u16 clk;
+       u32 reg, vendor_ptr;
+
+       vendor_ptr = sdhci_readw(host, SDHCI_VENDOR_PTR_R);
+
+       /* Disable software managed rx tuning */
+       reg = sdhci_readl(host, (SDHC_AT_CTRL_R + vendor_ptr));
+       reg &= ~SDHC_SW_TUNE_EN;
+       sdhci_writel(host, reg, (SDHC_AT_CTRL_R + vendor_ptr));
+
+       if (clock <= 52000000) {
+               sdhci_set_clock(host, clock);
+       } else {
+               /* Assert reset to MMCM */
+               reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
+               reg |= SDHC_CCLK_MMCM_RST;
+               sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
+
+               /* Configure MMCM */
+               if (clock == 100000000) {
+                       sdhci_writel(host, DIV_REG_100_MHZ, SDHC_MMCM_DIV_REG);
+                       sdhci_writel(host, CLKFBOUT_100_MHZ,
+                                       SDHC_MMCM_CLKFBOUT);
+               } else {
+                       sdhci_writel(host, DIV_REG_200_MHZ, SDHC_MMCM_DIV_REG);
+                       sdhci_writel(host, CLKFBOUT_200_MHZ,
+                                       SDHC_MMCM_CLKFBOUT);
+               }
+
+               /* De-assert reset to MMCM */
+               reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
+               reg &= ~SDHC_CCLK_MMCM_RST;
+               sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
+
+               /* Enable clock */
+               clk = SDHCI_PROG_CLOCK_MODE | SDHCI_CLOCK_INT_EN |
+                       SDHCI_CLOCK_CARD_EN;
+               sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+       }
+}
+
+static const struct sdhci_ops sdhci_snps_ops = {
+       .set_clock      = sdhci_snps_set_clock,
+       .enable_dma     = sdhci_pci_enable_dma,
+       .set_bus_width  = sdhci_set_bus_width,
+       .reset          = sdhci_reset,
+       .set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+const struct sdhci_pci_fixes sdhci_snps = {
+       .ops            = &sdhci_snps_ops,
+};
index 59af2886631f6cc2a7b15f977d08beb58950c781..2ef0bdca919743baaf51ae78d4cce8e215c5e65b 100644 (file)
@@ -61,6 +61,8 @@
 #define PCI_VENDOR_ID_ARASAN           0x16e6
 #define PCI_DEVICE_ID_ARASAN_PHY_EMMC  0x0670
 
+#define PCI_DEVICE_ID_SYNOPSYS_DWC_MSHC 0xc202
+
 /*
  * PCI device class and mask
  */
@@ -184,5 +186,6 @@ int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip);
 #endif
 
 extern const struct sdhci_pci_fixes sdhci_arasan;
+extern const struct sdhci_pci_fixes sdhci_snps;
 
 #endif /* __SDHCI_PCI_H */