Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: sdhci-pci-dwc-mshc: synopsys dwc mshc support

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>

authored by

Prabu Thangamuthu and committed by
Ulf Hansson
152f8204 a6e7e407

+97 -1
+7
MAINTAINERS
··· 12745 12745 F: drivers/mmc/host/sdhci* 12746 12746 F: include/linux/mmc/sdhci* 12747 12747 12748 + SYNOPSYS SDHCI COMPLIANT DWC MSHC DRIVER 12749 + M: Prabu Thangamuthu <prabu.t@synopsys.com> 12750 + M: Manjunath M B <manjumb@synopsys.com> 12751 + L: linux-mmc@vger.kernel.org 12752 + S: Maintained 12753 + F: drivers/mmc/host/sdhci-pci-dwc-mshc.c 12754 + 12748 12755 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER 12749 12756 M: Ben Dooks <ben-linux@fluff.org> 12750 12757 M: Jaehoon Chung <jh80.chung@samsung.com>
+2 -1
drivers/mmc/host/Makefile
··· 11 11 obj-$(CONFIG_MMC_MXS) += mxs-mmc.o 12 12 obj-$(CONFIG_MMC_SDHCI) += sdhci.o 13 13 obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o 14 - sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o 14 + sdhci-pci-y += sdhci-pci-core.o sdhci-pci-o2micro.o sdhci-pci-arasan.o \ 15 + sdhci-pci-dwc-mshc.o 15 16 obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o 16 17 obj-$(CONFIG_MMC_SDHCI_ACPI) += sdhci-acpi.o 17 18 obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
+1
drivers/mmc/host/sdhci-pci-core.c
··· 1513 1513 SDHCI_PCI_DEVICE(O2, SEABIRD0, o2), 1514 1514 SDHCI_PCI_DEVICE(O2, SEABIRD1, o2), 1515 1515 SDHCI_PCI_DEVICE(ARASAN, PHY_EMMC, arasan), 1516 + SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps), 1516 1517 SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd), 1517 1518 /* Generic SD host controller */ 1518 1519 {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},
+84
drivers/mmc/host/sdhci-pci-dwc-mshc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * SDHCI driver for Synopsys DWC_MSHC controller 4 + * 5 + * Copyright (C) 2018 Synopsys, Inc. (www.synopsys.com) 6 + * 7 + * Authors: 8 + * Prabu Thangamuthu <prabu.t@synopsys.com> 9 + * Manjunath M B <manjumb@synopsys.com> 10 + */ 11 + 12 + #include "sdhci.h" 13 + #include "sdhci-pci.h" 14 + 15 + #define SDHCI_VENDOR_PTR_R 0xE8 16 + 17 + /* Synopsys vendor specific registers */ 18 + #define SDHC_GPIO_OUT 0x34 19 + #define SDHC_AT_CTRL_R 0x40 20 + #define SDHC_SW_TUNE_EN 0x00000010 21 + 22 + /* MMCM DRP */ 23 + #define SDHC_MMCM_DIV_REG 0x1020 24 + #define DIV_REG_100_MHZ 0x1145 25 + #define DIV_REG_200_MHZ 0x1083 26 + #define SDHC_MMCM_CLKFBOUT 0x1024 27 + #define CLKFBOUT_100_MHZ 0x0000 28 + #define CLKFBOUT_200_MHZ 0x0080 29 + #define SDHC_CCLK_MMCM_RST 0x00000001 30 + 31 + static void sdhci_snps_set_clock(struct sdhci_host *host, unsigned int clock) 32 + { 33 + u16 clk; 34 + u32 reg, vendor_ptr; 35 + 36 + vendor_ptr = sdhci_readw(host, SDHCI_VENDOR_PTR_R); 37 + 38 + /* Disable software managed rx tuning */ 39 + reg = sdhci_readl(host, (SDHC_AT_CTRL_R + vendor_ptr)); 40 + reg &= ~SDHC_SW_TUNE_EN; 41 + sdhci_writel(host, reg, (SDHC_AT_CTRL_R + vendor_ptr)); 42 + 43 + if (clock <= 52000000) { 44 + sdhci_set_clock(host, clock); 45 + } else { 46 + /* Assert reset to MMCM */ 47 + reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr)); 48 + reg |= SDHC_CCLK_MMCM_RST; 49 + sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr)); 50 + 51 + /* Configure MMCM */ 52 + if (clock == 100000000) { 53 + sdhci_writel(host, DIV_REG_100_MHZ, SDHC_MMCM_DIV_REG); 54 + sdhci_writel(host, CLKFBOUT_100_MHZ, 55 + SDHC_MMCM_CLKFBOUT); 56 + } else { 57 + sdhci_writel(host, DIV_REG_200_MHZ, SDHC_MMCM_DIV_REG); 58 + sdhci_writel(host, CLKFBOUT_200_MHZ, 59 + SDHC_MMCM_CLKFBOUT); 60 + } 61 + 62 + /* De-assert reset to MMCM */ 63 + reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr)); 64 + reg &= ~SDHC_CCLK_MMCM_RST; 65 + sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr)); 66 + 67 + /* Enable clock */ 68 + clk = SDHCI_PROG_CLOCK_MODE | SDHCI_CLOCK_INT_EN | 69 + SDHCI_CLOCK_CARD_EN; 70 + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 71 + } 72 + } 73 + 74 + static const struct sdhci_ops sdhci_snps_ops = { 75 + .set_clock = sdhci_snps_set_clock, 76 + .enable_dma = sdhci_pci_enable_dma, 77 + .set_bus_width = sdhci_set_bus_width, 78 + .reset = sdhci_reset, 79 + .set_uhs_signaling = sdhci_set_uhs_signaling, 80 + }; 81 + 82 + const struct sdhci_pci_fixes sdhci_snps = { 83 + .ops = &sdhci_snps_ops, 84 + };
+3
drivers/mmc/host/sdhci-pci.h
··· 61 61 #define PCI_VENDOR_ID_ARASAN 0x16e6 62 62 #define PCI_DEVICE_ID_ARASAN_PHY_EMMC 0x0670 63 63 64 + #define PCI_DEVICE_ID_SYNOPSYS_DWC_MSHC 0xc202 65 + 64 66 /* 65 67 * PCI device class and mask 66 68 */ ··· 186 184 #endif 187 185 188 186 extern const struct sdhci_pci_fixes sdhci_arasan; 187 + extern const struct sdhci_pci_fixes sdhci_snps; 189 188 190 189 #endif /* __SDHCI_PCI_H */