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 }; 85