^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SDHCI driver for Synopsys DWC_MSHC controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2018 Synopsys, Inc. (www.synopsys.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Prabu Thangamuthu <prabu.t@synopsys.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Manjunath M B <manjumb@synopsys.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "sdhci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "sdhci-pci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define SDHCI_VENDOR_PTR_R 0xE8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Synopsys vendor specific registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define SDHC_GPIO_OUT 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SDHC_AT_CTRL_R 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SDHC_SW_TUNE_EN 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* MMCM DRP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SDHC_MMCM_DIV_REG 0x1020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DIV_REG_100_MHZ 0x1145
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define DIV_REG_200_MHZ 0x1083
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SDHC_MMCM_CLKFBOUT 0x1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define CLKFBOUT_100_MHZ 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define CLKFBOUT_200_MHZ 0x0080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SDHC_CCLK_MMCM_RST 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static void sdhci_snps_set_clock(struct sdhci_host *host, unsigned int clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u16 clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 reg, vendor_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) vendor_ptr = sdhci_readw(host, SDHCI_VENDOR_PTR_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Disable software managed rx tuning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) reg = sdhci_readl(host, (SDHC_AT_CTRL_R + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) reg &= ~SDHC_SW_TUNE_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) sdhci_writel(host, reg, (SDHC_AT_CTRL_R + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (clock <= 52000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) sdhci_set_clock(host, clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Assert reset to MMCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) reg |= SDHC_CCLK_MMCM_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Configure MMCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (clock == 100000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) sdhci_writel(host, DIV_REG_100_MHZ, SDHC_MMCM_DIV_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) sdhci_writel(host, CLKFBOUT_100_MHZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SDHC_MMCM_CLKFBOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) sdhci_writel(host, DIV_REG_200_MHZ, SDHC_MMCM_DIV_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) sdhci_writel(host, CLKFBOUT_200_MHZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) SDHC_MMCM_CLKFBOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* De-assert reset to MMCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) reg &= ~SDHC_CCLK_MMCM_RST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Enable clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) clk = SDHCI_PROG_CLOCK_MODE | SDHCI_CLOCK_INT_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) SDHCI_CLOCK_CARD_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static const struct sdhci_ops sdhci_snps_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .set_clock = sdhci_snps_set_clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .enable_dma = sdhci_pci_enable_dma,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .set_bus_width = sdhci_set_bus_width,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .reset = sdhci_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .set_uhs_signaling = sdhci_set_uhs_signaling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) const struct sdhci_pci_fixes sdhci_snps = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .ops = &sdhci_snps_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };