sdhci-pci-dwc-mshc.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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 <[email protected]>
  9. * Manjunath M B <[email protected]>
  10. */
  11. #include "sdhci.h"
  12. #include "sdhci-pci.h"
  13. #define SDHCI_VENDOR_PTR_R 0xE8
  14. /* Synopsys vendor specific registers */
  15. #define SDHC_GPIO_OUT 0x34
  16. #define SDHC_AT_CTRL_R 0x40
  17. #define SDHC_SW_TUNE_EN 0x00000010
  18. /* MMCM DRP */
  19. #define SDHC_MMCM_DIV_REG 0x1020
  20. #define DIV_REG_100_MHZ 0x1145
  21. #define DIV_REG_200_MHZ 0x1083
  22. #define SDHC_MMCM_CLKFBOUT 0x1024
  23. #define CLKFBOUT_100_MHZ 0x0000
  24. #define CLKFBOUT_200_MHZ 0x0080
  25. #define SDHC_CCLK_MMCM_RST 0x00000001
  26. static void sdhci_snps_set_clock(struct sdhci_host *host, unsigned int clock)
  27. {
  28. u16 clk;
  29. u32 reg, vendor_ptr;
  30. vendor_ptr = sdhci_readw(host, SDHCI_VENDOR_PTR_R);
  31. /* Disable software managed rx tuning */
  32. reg = sdhci_readl(host, (SDHC_AT_CTRL_R + vendor_ptr));
  33. reg &= ~SDHC_SW_TUNE_EN;
  34. sdhci_writel(host, reg, (SDHC_AT_CTRL_R + vendor_ptr));
  35. if (clock <= 52000000) {
  36. sdhci_set_clock(host, clock);
  37. } else {
  38. /* Assert reset to MMCM */
  39. reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
  40. reg |= SDHC_CCLK_MMCM_RST;
  41. sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
  42. /* Configure MMCM */
  43. if (clock == 100000000) {
  44. sdhci_writel(host, DIV_REG_100_MHZ, SDHC_MMCM_DIV_REG);
  45. sdhci_writel(host, CLKFBOUT_100_MHZ,
  46. SDHC_MMCM_CLKFBOUT);
  47. } else {
  48. sdhci_writel(host, DIV_REG_200_MHZ, SDHC_MMCM_DIV_REG);
  49. sdhci_writel(host, CLKFBOUT_200_MHZ,
  50. SDHC_MMCM_CLKFBOUT);
  51. }
  52. /* De-assert reset to MMCM */
  53. reg = sdhci_readl(host, (SDHC_GPIO_OUT + vendor_ptr));
  54. reg &= ~SDHC_CCLK_MMCM_RST;
  55. sdhci_writel(host, reg, (SDHC_GPIO_OUT + vendor_ptr));
  56. /* Enable clock */
  57. clk = SDHCI_PROG_CLOCK_MODE | SDHCI_CLOCK_INT_EN |
  58. SDHCI_CLOCK_CARD_EN;
  59. sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
  60. }
  61. }
  62. static const struct sdhci_ops sdhci_snps_ops = {
  63. .set_clock = sdhci_snps_set_clock,
  64. .enable_dma = sdhci_pci_enable_dma,
  65. .set_bus_width = sdhci_set_bus_width,
  66. .reset = sdhci_reset,
  67. .set_uhs_signaling = sdhci_set_uhs_signaling,
  68. };
  69. const struct sdhci_pci_fixes sdhci_snps = {
  70. .ops = &sdhci_snps_ops,
  71. };