1e51df6ceSBen Chuang // SPDX-License-Identifier: GPL-2.0+ 2e51df6ceSBen Chuang /* 3e51df6ceSBen Chuang * Copyright (C) 2019 Genesys Logic, Inc. 4e51df6ceSBen Chuang * 5e51df6ceSBen Chuang * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw> 6e51df6ceSBen Chuang * 7e51df6ceSBen Chuang * Version: v0.9.0 (2019-08-08) 8e51df6ceSBen Chuang */ 9e51df6ceSBen Chuang 10e51df6ceSBen Chuang #include <linux/bitfield.h> 11e51df6ceSBen Chuang #include <linux/bits.h> 12e51df6ceSBen Chuang #include <linux/pci.h> 13e51df6ceSBen Chuang #include <linux/mmc/mmc.h> 14e51df6ceSBen Chuang #include <linux/delay.h> 15189f1d9bSHector Martin #include <linux/of.h> 16d607667bSBen Chuang #include <linux/iopoll.h> 17e51df6ceSBen Chuang #include "sdhci.h" 1808b863bbSBrian Norris #include "sdhci-cqhci.h" 19e51df6ceSBen Chuang #include "sdhci-pci.h" 20347f6be1SBen Chuang #include "cqhci.h" 21e51df6ceSBen Chuang 22e51df6ceSBen Chuang /* Genesys Logic extra registers */ 23e51df6ceSBen Chuang #define SDHCI_GLI_9750_WT 0x800 24e51df6ceSBen Chuang #define SDHCI_GLI_9750_WT_EN BIT(0) 25e51df6ceSBen Chuang #define GLI_9750_WT_EN_ON 0x1 26e51df6ceSBen Chuang #define GLI_9750_WT_EN_OFF 0x0 27e51df6ceSBen Chuang 289751baccSBen Chuang #define SDHCI_GLI_9750_CFG2 0x848 299751baccSBen Chuang #define SDHCI_GLI_9750_CFG2_L1DLY GENMASK(28, 24) 309751baccSBen Chuang #define GLI_9750_CFG2_L1DLY_VALUE 0x1F 319751baccSBen Chuang 32e51df6ceSBen Chuang #define SDHCI_GLI_9750_DRIVING 0x860 33e51df6ceSBen Chuang #define SDHCI_GLI_9750_DRIVING_1 GENMASK(11, 0) 34e51df6ceSBen Chuang #define SDHCI_GLI_9750_DRIVING_2 GENMASK(27, 26) 35e51df6ceSBen Chuang #define GLI_9750_DRIVING_1_VALUE 0xFFF 36e51df6ceSBen Chuang #define GLI_9750_DRIVING_2_VALUE 0x3 37b56ff195SBen Chuang #define SDHCI_GLI_9750_SEL_1 BIT(29) 38b56ff195SBen Chuang #define SDHCI_GLI_9750_SEL_2 BIT(31) 39b56ff195SBen Chuang #define SDHCI_GLI_9750_ALL_RST (BIT(24)|BIT(25)|BIT(28)|BIT(30)) 40e51df6ceSBen Chuang 41e51df6ceSBen Chuang #define SDHCI_GLI_9750_PLL 0x864 42786d33c8SBen Chuang #define SDHCI_GLI_9750_PLL_LDIV GENMASK(9, 0) 43786d33c8SBen Chuang #define SDHCI_GLI_9750_PLL_PDIV GENMASK(14, 12) 44786d33c8SBen Chuang #define SDHCI_GLI_9750_PLL_DIR BIT(15) 45e51df6ceSBen Chuang #define SDHCI_GLI_9750_PLL_TX2_INV BIT(23) 46e51df6ceSBen Chuang #define SDHCI_GLI_9750_PLL_TX2_DLY GENMASK(22, 20) 47e51df6ceSBen Chuang #define GLI_9750_PLL_TX2_INV_VALUE 0x1 48e51df6ceSBen Chuang #define GLI_9750_PLL_TX2_DLY_VALUE 0x0 49786d33c8SBen Chuang #define SDHCI_GLI_9750_PLLSSC_STEP GENMASK(28, 24) 50786d33c8SBen Chuang #define SDHCI_GLI_9750_PLLSSC_EN BIT(31) 51786d33c8SBen Chuang 52786d33c8SBen Chuang #define SDHCI_GLI_9750_PLLSSC 0x86C 53786d33c8SBen Chuang #define SDHCI_GLI_9750_PLLSSC_PPM GENMASK(31, 16) 54e51df6ceSBen Chuang 55e51df6ceSBen Chuang #define SDHCI_GLI_9750_SW_CTRL 0x874 56e51df6ceSBen Chuang #define SDHCI_GLI_9750_SW_CTRL_4 GENMASK(7, 6) 57e51df6ceSBen Chuang #define GLI_9750_SW_CTRL_4_VALUE 0x3 58e51df6ceSBen Chuang 59e51df6ceSBen Chuang #define SDHCI_GLI_9750_MISC 0x878 60e51df6ceSBen Chuang #define SDHCI_GLI_9750_MISC_TX1_INV BIT(2) 61e51df6ceSBen Chuang #define SDHCI_GLI_9750_MISC_RX_INV BIT(3) 62e51df6ceSBen Chuang #define SDHCI_GLI_9750_MISC_TX1_DLY GENMASK(6, 4) 63e51df6ceSBen Chuang #define GLI_9750_MISC_TX1_INV_VALUE 0x0 64e51df6ceSBen Chuang #define GLI_9750_MISC_RX_INV_ON 0x1 65e51df6ceSBen Chuang #define GLI_9750_MISC_RX_INV_OFF 0x0 66e51df6ceSBen Chuang #define GLI_9750_MISC_RX_INV_VALUE GLI_9750_MISC_RX_INV_OFF 67e51df6ceSBen Chuang #define GLI_9750_MISC_TX1_DLY_VALUE 0x5 6808df1a50SBen Chuang #define SDHCI_GLI_9750_MISC_SSC_OFF BIT(26) 69e51df6ceSBen Chuang 70e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_CONTROL 0x540 71e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) 72e51df6ceSBen Chuang #define GLI_9750_TUNING_CONTROL_EN_ON 0x1 73e51df6ceSBen Chuang #define GLI_9750_TUNING_CONTROL_EN_OFF 0x0 74e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1 BIT(16) 75e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2 GENMASK(20, 19) 76e51df6ceSBen Chuang #define GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE 0x1 77e51df6ceSBen Chuang #define GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE 0x2 78e51df6ceSBen Chuang 79e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_PARAMETERS 0x544 80e51df6ceSBen Chuang #define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) 81e51df6ceSBen Chuang #define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 82e51df6ceSBen Chuang 831ae1d2d6SBen Chuang #define SDHCI_GLI_9763E_CTRL_HS400 0x7 841ae1d2d6SBen Chuang 851ae1d2d6SBen Chuang #define SDHCI_GLI_9763E_HS400_ES_REG 0x52C 861ae1d2d6SBen Chuang #define SDHCI_GLI_9763E_HS400_ES_BIT BIT(8) 871ae1d2d6SBen Chuang 881ae1d2d6SBen Chuang #define PCIE_GLI_9763E_VHS 0x884 891ae1d2d6SBen Chuang #define GLI_9763E_VHS_REV GENMASK(19, 16) 901ae1d2d6SBen Chuang #define GLI_9763E_VHS_REV_R 0x0 911ae1d2d6SBen Chuang #define GLI_9763E_VHS_REV_M 0x1 921ae1d2d6SBen Chuang #define GLI_9763E_VHS_REV_W 0x2 93347f6be1SBen Chuang #define PCIE_GLI_9763E_MB 0x888 94347f6be1SBen Chuang #define GLI_9763E_MB_CMDQ_OFF BIT(19) 9515f908faSRenius Chen #define GLI_9763E_MB_ERP_ON BIT(7) 961ae1d2d6SBen Chuang #define PCIE_GLI_9763E_SCR 0x8E0 971ae1d2d6SBen Chuang #define GLI_9763E_SCR_AXI_REQ BIT(9) 981ae1d2d6SBen Chuang 99f9e5b339SJason Lai #define PCIE_GLI_9763E_CFG 0x8A0 100f9e5b339SJason Lai #define GLI_9763E_CFG_LPSN_DIS BIT(12) 101f9e5b339SJason Lai 102edee82f7SRenius Chen #define PCIE_GLI_9763E_CFG2 0x8A4 103edee82f7SRenius Chen #define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) 10434dd3cccSBen Chuang #define GLI_9763E_CFG2_L1DLY_MID 0x54 105edee82f7SRenius Chen 10698991b18SBen Chuang #define PCIE_GLI_9763E_MMC_CTRL 0x960 10798991b18SBen Chuang #define GLI_9763E_HS400_SLOW BIT(3) 10898991b18SBen Chuang 109c58c5950SRenius Chen #define PCIE_GLI_9763E_CLKRXDLY 0x934 110c58c5950SRenius Chen #define GLI_9763E_HS400_RXDLY GENMASK(31, 28) 111c58c5950SRenius Chen #define GLI_9763E_HS400_RXDLY_5 0x5 112c58c5950SRenius Chen 113347f6be1SBen Chuang #define SDHCI_GLI_9763E_CQE_BASE_ADDR 0x200 114347f6be1SBen Chuang #define GLI_9763E_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \ 115347f6be1SBen Chuang SDHCI_TRNS_BLK_CNT_EN | \ 116347f6be1SBen Chuang SDHCI_TRNS_DMA) 117347f6be1SBen Chuang 118786d33c8SBen Chuang #define PCI_GLI_9755_WT 0x800 119786d33c8SBen Chuang #define PCI_GLI_9755_WT_EN BIT(0) 120786d33c8SBen Chuang #define GLI_9755_WT_EN_ON 0x1 121786d33c8SBen Chuang #define GLI_9755_WT_EN_OFF 0x0 122786d33c8SBen Chuang 1230f1d9961SBen Chuang #define PCI_GLI_9755_PECONF 0x44 1240f1d9961SBen Chuang #define PCI_GLI_9755_LFCLK GENMASK(14, 12) 1250f1d9961SBen Chuang #define PCI_GLI_9755_DMACLK BIT(29) 126189f1d9bSHector Martin #define PCI_GLI_9755_INVERT_CD BIT(30) 127189f1d9bSHector Martin #define PCI_GLI_9755_INVERT_WP BIT(31) 1280f1d9961SBen Chuang 1299751baccSBen Chuang #define PCI_GLI_9755_CFG2 0x48 1309751baccSBen Chuang #define PCI_GLI_9755_CFG2_L1DLY GENMASK(28, 24) 1319751baccSBen Chuang #define GLI_9755_CFG2_L1DLY_VALUE 0x1F 1329751baccSBen Chuang 133786d33c8SBen Chuang #define PCI_GLI_9755_PLL 0x64 134786d33c8SBen Chuang #define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0) 135786d33c8SBen Chuang #define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12) 136786d33c8SBen Chuang #define PCI_GLI_9755_PLL_DIR BIT(15) 137786d33c8SBen Chuang #define PCI_GLI_9755_PLLSSC_STEP GENMASK(28, 24) 138786d33c8SBen Chuang #define PCI_GLI_9755_PLLSSC_EN BIT(31) 139786d33c8SBen Chuang 140786d33c8SBen Chuang #define PCI_GLI_9755_PLLSSC 0x68 141786d33c8SBen Chuang #define PCI_GLI_9755_PLLSSC_PPM GENMASK(15, 0) 142786d33c8SBen Chuang 143f46b54ccSRenius Chen #define PCI_GLI_9755_SerDes 0x70 144f46b54ccSRenius Chen #define PCI_GLI_9755_SCP_DIS BIT(19) 145f46b54ccSRenius Chen 14608df1a50SBen Chuang #define PCI_GLI_9755_MISC 0x78 14708df1a50SBen Chuang #define PCI_GLI_9755_MISC_SSC_OFF BIT(26) 14808df1a50SBen Chuang 14936ed2fd3SBen Chuang #define PCI_GLI_9755_PM_CTRL 0xFC 15036ed2fd3SBen Chuang #define PCI_GLI_9755_PM_STATE GENMASK(1, 0) 15136ed2fd3SBen Chuang 152f3a5b56cSVictor Shih #define SDHCI_GLI_9767_GM_BURST_SIZE 0x510 153f3a5b56cSVictor Shih #define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8) 154f3a5b56cSVictor Shih 155f3a5b56cSVictor Shih #define PCIE_GLI_9767_VHS 0x884 156f3a5b56cSVictor Shih #define GLI_9767_VHS_REV GENMASK(19, 16) 157f3a5b56cSVictor Shih #define GLI_9767_VHS_REV_R 0x0 158f3a5b56cSVictor Shih #define GLI_9767_VHS_REV_M 0x1 159f3a5b56cSVictor Shih #define GLI_9767_VHS_REV_W 0x2 160f3a5b56cSVictor Shih 161d2754355SVictor Shih #define PCIE_GLI_9767_COM_MAILBOX 0x888 162d2754355SVictor Shih #define PCIE_GLI_9767_COM_MAILBOX_SSC_EN BIT(1) 163d2754355SVictor Shih 164d2754355SVictor Shih #define PCIE_GLI_9767_CFG 0x8A0 165d2754355SVictor Shih #define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12) 166d2754355SVictor Shih 167*0e92aec2SVictor Shih #define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8 168*0e92aec2SVictor Shih #define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6) 169*0e92aec2SVictor Shih #define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10) 170*0e92aec2SVictor Shih 171f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0 172f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0) 173f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12) 174f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7 175f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28) 176f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3 177f3a5b56cSVictor Shih 178f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR 0x8E0 179f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6) 180f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7) 181f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AXI_REQ BIT(9) 182f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10) 183f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16) 184f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17) 185f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21) 186f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30) 187f3a5b56cSVictor Shih 188*0e92aec2SVictor Shih #define PCIE_GLI_9767_SDHC_CAP 0x91C 189*0e92aec2SVictor Shih #define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5) 190*0e92aec2SVictor Shih 191d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL 0x938 192d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0) 193d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12) 194d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN BIT(16) 195d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_SSC_EN BIT(19) 196d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING GENMASK(28, 24) 197d2754355SVictor Shih 198d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL2 0x93C 199d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM GENMASK(31, 16) 200d2754355SVictor Shih 201*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940 202*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0) 203*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1) 204*0e92aec2SVictor Shih 205*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944 206*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16) 207*0e92aec2SVictor Shih #define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64 208*0e92aec2SVictor Shih 209*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950 210*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0) 211*0e92aec2SVictor Shih 212*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954 213*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN BIT(0) 214*0e92aec2SVictor Shih 215*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958 216*0e92aec2SVictor Shih #define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0) 217*0e92aec2SVictor Shih 218e51df6ceSBen Chuang #define GLI_MAX_TUNING_LOOP 40 219e51df6ceSBen Chuang 220e51df6ceSBen Chuang /* Genesys Logic chipset */ 221e51df6ceSBen Chuang static inline void gl9750_wt_on(struct sdhci_host *host) 222e51df6ceSBen Chuang { 223e51df6ceSBen Chuang u32 wt_value; 224e51df6ceSBen Chuang u32 wt_enable; 225e51df6ceSBen Chuang 226e51df6ceSBen Chuang wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 227e51df6ceSBen Chuang wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 228e51df6ceSBen Chuang 229e51df6ceSBen Chuang if (wt_enable == GLI_9750_WT_EN_ON) 230e51df6ceSBen Chuang return; 231e51df6ceSBen Chuang 232e51df6ceSBen Chuang wt_value &= ~SDHCI_GLI_9750_WT_EN; 233e51df6ceSBen Chuang wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_ON); 234e51df6ceSBen Chuang 235e51df6ceSBen Chuang sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 236e51df6ceSBen Chuang } 237e51df6ceSBen Chuang 238e51df6ceSBen Chuang static inline void gl9750_wt_off(struct sdhci_host *host) 239e51df6ceSBen Chuang { 240e51df6ceSBen Chuang u32 wt_value; 241e51df6ceSBen Chuang u32 wt_enable; 242e51df6ceSBen Chuang 243e51df6ceSBen Chuang wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 244e51df6ceSBen Chuang wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 245e51df6ceSBen Chuang 246e51df6ceSBen Chuang if (wt_enable == GLI_9750_WT_EN_OFF) 247e51df6ceSBen Chuang return; 248e51df6ceSBen Chuang 249e51df6ceSBen Chuang wt_value &= ~SDHCI_GLI_9750_WT_EN; 250e51df6ceSBen Chuang wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_OFF); 251e51df6ceSBen Chuang 252e51df6ceSBen Chuang sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 253e51df6ceSBen Chuang } 254e51df6ceSBen Chuang 255e51df6ceSBen Chuang static void gli_set_9750(struct sdhci_host *host) 256e51df6ceSBen Chuang { 257e51df6ceSBen Chuang u32 driving_value; 258e51df6ceSBen Chuang u32 pll_value; 259e51df6ceSBen Chuang u32 sw_ctrl_value; 260e51df6ceSBen Chuang u32 misc_value; 261e51df6ceSBen Chuang u32 parameter_value; 262e51df6ceSBen Chuang u32 control_value; 263e51df6ceSBen Chuang u16 ctrl2; 264e51df6ceSBen Chuang 265e51df6ceSBen Chuang gl9750_wt_on(host); 266e51df6ceSBen Chuang 267e51df6ceSBen Chuang driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); 268e51df6ceSBen Chuang pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); 269e51df6ceSBen Chuang sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); 270e51df6ceSBen Chuang misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 271e51df6ceSBen Chuang parameter_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_PARAMETERS); 272e51df6ceSBen Chuang control_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_CONTROL); 273e51df6ceSBen Chuang 274e51df6ceSBen Chuang driving_value &= ~(SDHCI_GLI_9750_DRIVING_1); 275e51df6ceSBen Chuang driving_value &= ~(SDHCI_GLI_9750_DRIVING_2); 276e51df6ceSBen Chuang driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1, 277e51df6ceSBen Chuang GLI_9750_DRIVING_1_VALUE); 278e51df6ceSBen Chuang driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2, 279e51df6ceSBen Chuang GLI_9750_DRIVING_2_VALUE); 280b56ff195SBen Chuang driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST); 281b56ff195SBen Chuang driving_value |= SDHCI_GLI_9750_SEL_2; 282e51df6ceSBen Chuang sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING); 283e51df6ceSBen Chuang 284e51df6ceSBen Chuang sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4; 285e51df6ceSBen Chuang sw_ctrl_value |= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4, 286e51df6ceSBen Chuang GLI_9750_SW_CTRL_4_VALUE); 287e51df6ceSBen Chuang sdhci_writel(host, sw_ctrl_value, SDHCI_GLI_9750_SW_CTRL); 288e51df6ceSBen Chuang 289e51df6ceSBen Chuang /* reset the tuning flow after reinit and before starting tuning */ 290e51df6ceSBen Chuang pll_value &= ~SDHCI_GLI_9750_PLL_TX2_INV; 291e51df6ceSBen Chuang pll_value &= ~SDHCI_GLI_9750_PLL_TX2_DLY; 292e51df6ceSBen Chuang pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV, 293e51df6ceSBen Chuang GLI_9750_PLL_TX2_INV_VALUE); 294e51df6ceSBen Chuang pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY, 295e51df6ceSBen Chuang GLI_9750_PLL_TX2_DLY_VALUE); 296e51df6ceSBen Chuang 297e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_TX1_INV; 298e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 299e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_TX1_DLY; 300e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV, 301e51df6ceSBen Chuang GLI_9750_MISC_TX1_INV_VALUE); 302e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 303e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_VALUE); 304e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY, 305e51df6ceSBen Chuang GLI_9750_MISC_TX1_DLY_VALUE); 306e51df6ceSBen Chuang 307e51df6ceSBen Chuang parameter_value &= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY; 308e51df6ceSBen Chuang parameter_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY, 309e51df6ceSBen Chuang GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE); 310e51df6ceSBen Chuang 311e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1; 312e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2; 313e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1, 314e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE); 315e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2, 316e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE); 317e51df6ceSBen Chuang 318e51df6ceSBen Chuang sdhci_writel(host, pll_value, SDHCI_GLI_9750_PLL); 319e51df6ceSBen Chuang sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 320e51df6ceSBen Chuang 321e51df6ceSBen Chuang /* disable tuned clk */ 322e51df6ceSBen Chuang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 323e51df6ceSBen Chuang ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 324e51df6ceSBen Chuang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 325e51df6ceSBen Chuang 326e51df6ceSBen Chuang /* enable tuning parameters control */ 327e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 328e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 329e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_EN_ON); 330e51df6ceSBen Chuang sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 331e51df6ceSBen Chuang 332e51df6ceSBen Chuang /* write tuning parameters */ 333e51df6ceSBen Chuang sdhci_writel(host, parameter_value, SDHCI_GLI_9750_TUNING_PARAMETERS); 334e51df6ceSBen Chuang 335e51df6ceSBen Chuang /* disable tuning parameters control */ 336e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 337e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 338e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_EN_OFF); 339e51df6ceSBen Chuang sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 340e51df6ceSBen Chuang 341e51df6ceSBen Chuang /* clear tuned clk */ 342e51df6ceSBen Chuang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 343e51df6ceSBen Chuang ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 344e51df6ceSBen Chuang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 345e51df6ceSBen Chuang 346e51df6ceSBen Chuang gl9750_wt_off(host); 347e51df6ceSBen Chuang } 348e51df6ceSBen Chuang 349e51df6ceSBen Chuang static void gli_set_9750_rx_inv(struct sdhci_host *host, bool b) 350e51df6ceSBen Chuang { 351e51df6ceSBen Chuang u32 misc_value; 352e51df6ceSBen Chuang 353e51df6ceSBen Chuang gl9750_wt_on(host); 354e51df6ceSBen Chuang 355e51df6ceSBen Chuang misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 356e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 357e51df6ceSBen Chuang if (b) { 358e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 359e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_ON); 360e51df6ceSBen Chuang } else { 361e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 362e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_OFF); 363e51df6ceSBen Chuang } 364e51df6ceSBen Chuang sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 365e51df6ceSBen Chuang 366e51df6ceSBen Chuang gl9750_wt_off(host); 367e51df6ceSBen Chuang } 368e51df6ceSBen Chuang 369e51df6ceSBen Chuang static int __sdhci_execute_tuning_9750(struct sdhci_host *host, u32 opcode) 370e51df6ceSBen Chuang { 371e51df6ceSBen Chuang int i; 372e51df6ceSBen Chuang int rx_inv; 373e51df6ceSBen Chuang 374e51df6ceSBen Chuang for (rx_inv = 0; rx_inv < 2; rx_inv++) { 375e51df6ceSBen Chuang gli_set_9750_rx_inv(host, !!rx_inv); 376e51df6ceSBen Chuang sdhci_start_tuning(host); 377e51df6ceSBen Chuang 378e51df6ceSBen Chuang for (i = 0; i < GLI_MAX_TUNING_LOOP; i++) { 379e51df6ceSBen Chuang u16 ctrl; 380e51df6ceSBen Chuang 381e51df6ceSBen Chuang sdhci_send_tuning(host, opcode); 382e51df6ceSBen Chuang 383e51df6ceSBen Chuang if (!host->tuning_done) { 384e51df6ceSBen Chuang sdhci_abort_tuning(host, opcode); 385e51df6ceSBen Chuang break; 386e51df6ceSBen Chuang } 387e51df6ceSBen Chuang 388e51df6ceSBen Chuang ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 389e51df6ceSBen Chuang if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 390e51df6ceSBen Chuang if (ctrl & SDHCI_CTRL_TUNED_CLK) 391e51df6ceSBen Chuang return 0; /* Success! */ 392e51df6ceSBen Chuang break; 393e51df6ceSBen Chuang } 394e51df6ceSBen Chuang } 395e51df6ceSBen Chuang } 396e51df6ceSBen Chuang if (!host->tuning_done) { 397e51df6ceSBen Chuang pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", 398e51df6ceSBen Chuang mmc_hostname(host->mmc)); 399e51df6ceSBen Chuang return -ETIMEDOUT; 400e51df6ceSBen Chuang } 401e51df6ceSBen Chuang 402e51df6ceSBen Chuang pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 403e51df6ceSBen Chuang mmc_hostname(host->mmc)); 404e51df6ceSBen Chuang sdhci_reset_tuning(host); 405e51df6ceSBen Chuang 406e51df6ceSBen Chuang return -EAGAIN; 407e51df6ceSBen Chuang } 408e51df6ceSBen Chuang 409e51df6ceSBen Chuang static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode) 410e51df6ceSBen Chuang { 411e51df6ceSBen Chuang host->mmc->retune_period = 0; 412e51df6ceSBen Chuang if (host->tuning_mode == SDHCI_TUNING_MODE_1) 413e51df6ceSBen Chuang host->mmc->retune_period = host->tuning_count; 414e51df6ceSBen Chuang 415e51df6ceSBen Chuang gli_set_9750(host); 416e51df6ceSBen Chuang host->tuning_err = __sdhci_execute_tuning_9750(host, opcode); 417e51df6ceSBen Chuang sdhci_end_tuning(host); 418e51df6ceSBen Chuang 419e51df6ceSBen Chuang return 0; 420e51df6ceSBen Chuang } 421e51df6ceSBen Chuang 422786d33c8SBen Chuang static void gl9750_disable_ssc_pll(struct sdhci_host *host) 423786d33c8SBen Chuang { 424786d33c8SBen Chuang u32 pll; 425786d33c8SBen Chuang 426786d33c8SBen Chuang gl9750_wt_on(host); 427786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 428786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN); 429786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 430786d33c8SBen Chuang gl9750_wt_off(host); 431786d33c8SBen Chuang } 432786d33c8SBen Chuang 433786d33c8SBen Chuang static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv) 434786d33c8SBen Chuang { 435786d33c8SBen Chuang u32 pll; 436786d33c8SBen Chuang 437786d33c8SBen Chuang gl9750_wt_on(host); 438786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 439786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLL_LDIV | 440786d33c8SBen Chuang SDHCI_GLI_9750_PLL_PDIV | 441786d33c8SBen Chuang SDHCI_GLI_9750_PLL_DIR); 442786d33c8SBen Chuang pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) | 443786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) | 444786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir); 445786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 446786d33c8SBen Chuang gl9750_wt_off(host); 447786d33c8SBen Chuang 448786d33c8SBen Chuang /* wait for pll stable */ 449786d33c8SBen Chuang mdelay(1); 450786d33c8SBen Chuang } 451786d33c8SBen Chuang 45208df1a50SBen Chuang static bool gl9750_ssc_enable(struct sdhci_host *host) 45308df1a50SBen Chuang { 45408df1a50SBen Chuang u32 misc; 45508df1a50SBen Chuang u8 off; 45608df1a50SBen Chuang 45708df1a50SBen Chuang gl9750_wt_on(host); 45808df1a50SBen Chuang misc = sdhci_readl(host, SDHCI_GLI_9750_MISC); 45908df1a50SBen Chuang off = FIELD_GET(SDHCI_GLI_9750_MISC_SSC_OFF, misc); 46008df1a50SBen Chuang gl9750_wt_off(host); 46108df1a50SBen Chuang 46208df1a50SBen Chuang return !off; 46308df1a50SBen Chuang } 46408df1a50SBen Chuang 465786d33c8SBen Chuang static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm) 466786d33c8SBen Chuang { 467786d33c8SBen Chuang u32 pll; 468786d33c8SBen Chuang u32 ssc; 469786d33c8SBen Chuang 470786d33c8SBen Chuang gl9750_wt_on(host); 471786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 472786d33c8SBen Chuang ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC); 473786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP | 474786d33c8SBen Chuang SDHCI_GLI_9750_PLLSSC_EN); 475786d33c8SBen Chuang ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM; 476786d33c8SBen Chuang pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) | 477786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable); 478786d33c8SBen Chuang ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm); 479786d33c8SBen Chuang sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC); 480786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 481786d33c8SBen Chuang gl9750_wt_off(host); 482786d33c8SBen Chuang } 483786d33c8SBen Chuang 484786d33c8SBen Chuang static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host) 485786d33c8SBen Chuang { 48608df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 48708df1a50SBen Chuang 48808df1a50SBen Chuang /* set pll to 205MHz and ssc */ 48908df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xF, 0x5A1D); 490786d33c8SBen Chuang gl9750_set_pll(host, 0x1, 0x246, 0x0); 491786d33c8SBen Chuang } 492786d33c8SBen Chuang 493d3c6bdb6SBen Chuang static void gl9750_set_ssc_pll_100mhz(struct sdhci_host *host) 494d3c6bdb6SBen Chuang { 49508df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 49608df1a50SBen Chuang 49708df1a50SBen Chuang /* set pll to 100MHz and ssc */ 49808df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xE, 0x51EC); 499d3c6bdb6SBen Chuang gl9750_set_pll(host, 0x1, 0x244, 0x1); 500d3c6bdb6SBen Chuang } 501d3c6bdb6SBen Chuang 502d3c6bdb6SBen Chuang static void gl9750_set_ssc_pll_50mhz(struct sdhci_host *host) 503d3c6bdb6SBen Chuang { 50408df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 50508df1a50SBen Chuang 50608df1a50SBen Chuang /* set pll to 50MHz and ssc */ 50708df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xE, 0x51EC); 508d3c6bdb6SBen Chuang gl9750_set_pll(host, 0x1, 0x244, 0x3); 509d3c6bdb6SBen Chuang } 510d3c6bdb6SBen Chuang 511786d33c8SBen Chuang static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock) 512786d33c8SBen Chuang { 513786d33c8SBen Chuang struct mmc_ios *ios = &host->mmc->ios; 514786d33c8SBen Chuang u16 clk; 515786d33c8SBen Chuang 516786d33c8SBen Chuang host->mmc->actual_clock = 0; 517786d33c8SBen Chuang 518786d33c8SBen Chuang gl9750_disable_ssc_pll(host); 519786d33c8SBen Chuang sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 520786d33c8SBen Chuang 521786d33c8SBen Chuang if (clock == 0) 522786d33c8SBen Chuang return; 523786d33c8SBen Chuang 524786d33c8SBen Chuang clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 525786d33c8SBen Chuang if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 526786d33c8SBen Chuang host->mmc->actual_clock = 205000000; 527786d33c8SBen Chuang gl9750_set_ssc_pll_205mhz(host); 528d3c6bdb6SBen Chuang } else if (clock == 100000000) { 529d3c6bdb6SBen Chuang gl9750_set_ssc_pll_100mhz(host); 530d3c6bdb6SBen Chuang } else if (clock == 50000000) { 531d3c6bdb6SBen Chuang gl9750_set_ssc_pll_50mhz(host); 532786d33c8SBen Chuang } 533786d33c8SBen Chuang 534786d33c8SBen Chuang sdhci_enable_clk(host, clk); 535786d33c8SBen Chuang } 536786d33c8SBen Chuang 5379751baccSBen Chuang static void gl9750_hw_setting(struct sdhci_host *host) 5389751baccSBen Chuang { 5399751baccSBen Chuang u32 value; 5409751baccSBen Chuang 5419751baccSBen Chuang gl9750_wt_on(host); 5429751baccSBen Chuang 5439751baccSBen Chuang value = sdhci_readl(host, SDHCI_GLI_9750_CFG2); 5449751baccSBen Chuang value &= ~SDHCI_GLI_9750_CFG2_L1DLY; 5459751baccSBen Chuang /* set ASPM L1 entry delay to 7.9us */ 5469751baccSBen Chuang value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY, 5479751baccSBen Chuang GLI_9750_CFG2_L1DLY_VALUE); 5489751baccSBen Chuang sdhci_writel(host, value, SDHCI_GLI_9750_CFG2); 5499751baccSBen Chuang 5509751baccSBen Chuang gl9750_wt_off(host); 5519751baccSBen Chuang } 5529751baccSBen Chuang 55331e43f31SBen Chuang static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) 55431e43f31SBen Chuang { 55531e43f31SBen Chuang int ret; 55631e43f31SBen Chuang 55731e43f31SBen Chuang ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1, 55831e43f31SBen Chuang PCI_IRQ_MSI | PCI_IRQ_MSIX); 55931e43f31SBen Chuang if (ret < 0) { 56031e43f31SBen Chuang pr_warn("%s: enable PCI MSI failed, error=%d\n", 56131e43f31SBen Chuang mmc_hostname(slot->host->mmc), ret); 56231e43f31SBen Chuang return; 56331e43f31SBen Chuang } 56431e43f31SBen Chuang 56531e43f31SBen Chuang slot->host->irq = pci_irq_vector(slot->chip->pdev, 0); 56631e43f31SBen Chuang } 56731e43f31SBen Chuang 568786d33c8SBen Chuang static inline void gl9755_wt_on(struct pci_dev *pdev) 569786d33c8SBen Chuang { 570786d33c8SBen Chuang u32 wt_value; 571786d33c8SBen Chuang u32 wt_enable; 572786d33c8SBen Chuang 573786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 574786d33c8SBen Chuang wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 575786d33c8SBen Chuang 576786d33c8SBen Chuang if (wt_enable == GLI_9755_WT_EN_ON) 577786d33c8SBen Chuang return; 578786d33c8SBen Chuang 579786d33c8SBen Chuang wt_value &= ~PCI_GLI_9755_WT_EN; 580786d33c8SBen Chuang wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON); 581786d33c8SBen Chuang 582786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 583786d33c8SBen Chuang } 584786d33c8SBen Chuang 585786d33c8SBen Chuang static inline void gl9755_wt_off(struct pci_dev *pdev) 586786d33c8SBen Chuang { 587786d33c8SBen Chuang u32 wt_value; 588786d33c8SBen Chuang u32 wt_enable; 589786d33c8SBen Chuang 590786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 591786d33c8SBen Chuang wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 592786d33c8SBen Chuang 593786d33c8SBen Chuang if (wt_enable == GLI_9755_WT_EN_OFF) 594786d33c8SBen Chuang return; 595786d33c8SBen Chuang 596786d33c8SBen Chuang wt_value &= ~PCI_GLI_9755_WT_EN; 597786d33c8SBen Chuang wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF); 598786d33c8SBen Chuang 599786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 600786d33c8SBen Chuang } 601786d33c8SBen Chuang 602786d33c8SBen Chuang static void gl9755_disable_ssc_pll(struct pci_dev *pdev) 603786d33c8SBen Chuang { 604786d33c8SBen Chuang u32 pll; 605786d33c8SBen Chuang 606786d33c8SBen Chuang gl9755_wt_on(pdev); 607786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 608786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN); 609786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 610786d33c8SBen Chuang gl9755_wt_off(pdev); 611786d33c8SBen Chuang } 612786d33c8SBen Chuang 613786d33c8SBen Chuang static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 614786d33c8SBen Chuang { 615786d33c8SBen Chuang u32 pll; 616786d33c8SBen Chuang 617786d33c8SBen Chuang gl9755_wt_on(pdev); 618786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 619786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLL_LDIV | 620786d33c8SBen Chuang PCI_GLI_9755_PLL_PDIV | 621786d33c8SBen Chuang PCI_GLI_9755_PLL_DIR); 622786d33c8SBen Chuang pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) | 623786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) | 624786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir); 625786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 626786d33c8SBen Chuang gl9755_wt_off(pdev); 627786d33c8SBen Chuang 628786d33c8SBen Chuang /* wait for pll stable */ 629786d33c8SBen Chuang mdelay(1); 630786d33c8SBen Chuang } 631786d33c8SBen Chuang 63208df1a50SBen Chuang static bool gl9755_ssc_enable(struct pci_dev *pdev) 63308df1a50SBen Chuang { 63408df1a50SBen Chuang u32 misc; 63508df1a50SBen Chuang u8 off; 63608df1a50SBen Chuang 63708df1a50SBen Chuang gl9755_wt_on(pdev); 63808df1a50SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_MISC, &misc); 63908df1a50SBen Chuang off = FIELD_GET(PCI_GLI_9755_MISC_SSC_OFF, misc); 64008df1a50SBen Chuang gl9755_wt_off(pdev); 64108df1a50SBen Chuang 64208df1a50SBen Chuang return !off; 64308df1a50SBen Chuang } 64408df1a50SBen Chuang 645786d33c8SBen Chuang static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 646786d33c8SBen Chuang { 647786d33c8SBen Chuang u32 pll; 648786d33c8SBen Chuang u32 ssc; 649786d33c8SBen Chuang 650786d33c8SBen Chuang gl9755_wt_on(pdev); 651786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 652786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc); 653786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLLSSC_STEP | 654786d33c8SBen Chuang PCI_GLI_9755_PLLSSC_EN); 655786d33c8SBen Chuang ssc &= ~PCI_GLI_9755_PLLSSC_PPM; 656786d33c8SBen Chuang pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) | 657786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable); 658786d33c8SBen Chuang ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm); 659786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc); 660786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 661786d33c8SBen Chuang gl9755_wt_off(pdev); 662786d33c8SBen Chuang } 663786d33c8SBen Chuang 664786d33c8SBen Chuang static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev) 665786d33c8SBen Chuang { 66608df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 66708df1a50SBen Chuang 66808df1a50SBen Chuang /* set pll to 205MHz and ssc */ 66908df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xF, 0x5A1D); 670786d33c8SBen Chuang gl9755_set_pll(pdev, 0x1, 0x246, 0x0); 671786d33c8SBen Chuang } 672786d33c8SBen Chuang 673d3c6bdb6SBen Chuang static void gl9755_set_ssc_pll_100mhz(struct pci_dev *pdev) 674d3c6bdb6SBen Chuang { 67508df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 67608df1a50SBen Chuang 67708df1a50SBen Chuang /* set pll to 100MHz and ssc */ 67808df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 679d3c6bdb6SBen Chuang gl9755_set_pll(pdev, 0x1, 0x244, 0x1); 680d3c6bdb6SBen Chuang } 681d3c6bdb6SBen Chuang 682d3c6bdb6SBen Chuang static void gl9755_set_ssc_pll_50mhz(struct pci_dev *pdev) 683d3c6bdb6SBen Chuang { 68408df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 68508df1a50SBen Chuang 68608df1a50SBen Chuang /* set pll to 50MHz and ssc */ 68708df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 688d3c6bdb6SBen Chuang gl9755_set_pll(pdev, 0x1, 0x244, 0x3); 689d3c6bdb6SBen Chuang } 690d3c6bdb6SBen Chuang 691786d33c8SBen Chuang static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock) 692786d33c8SBen Chuang { 693786d33c8SBen Chuang struct sdhci_pci_slot *slot = sdhci_priv(host); 694786d33c8SBen Chuang struct mmc_ios *ios = &host->mmc->ios; 695786d33c8SBen Chuang struct pci_dev *pdev; 696786d33c8SBen Chuang u16 clk; 697786d33c8SBen Chuang 698786d33c8SBen Chuang pdev = slot->chip->pdev; 699786d33c8SBen Chuang host->mmc->actual_clock = 0; 700786d33c8SBen Chuang 701786d33c8SBen Chuang gl9755_disable_ssc_pll(pdev); 702786d33c8SBen Chuang sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 703786d33c8SBen Chuang 704786d33c8SBen Chuang if (clock == 0) 705786d33c8SBen Chuang return; 706786d33c8SBen Chuang 707786d33c8SBen Chuang clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 708786d33c8SBen Chuang if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 709786d33c8SBen Chuang host->mmc->actual_clock = 205000000; 710786d33c8SBen Chuang gl9755_set_ssc_pll_205mhz(pdev); 711d3c6bdb6SBen Chuang } else if (clock == 100000000) { 712d3c6bdb6SBen Chuang gl9755_set_ssc_pll_100mhz(pdev); 713d3c6bdb6SBen Chuang } else if (clock == 50000000) { 714d3c6bdb6SBen Chuang gl9755_set_ssc_pll_50mhz(pdev); 715786d33c8SBen Chuang } 716786d33c8SBen Chuang 717786d33c8SBen Chuang sdhci_enable_clk(host, clk); 718786d33c8SBen Chuang } 719786d33c8SBen Chuang 7200f1d9961SBen Chuang static void gl9755_hw_setting(struct sdhci_pci_slot *slot) 7210f1d9961SBen Chuang { 7220f1d9961SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 7230f1d9961SBen Chuang u32 value; 7240f1d9961SBen Chuang 7250f1d9961SBen Chuang gl9755_wt_on(pdev); 7260f1d9961SBen Chuang 7270f1d9961SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value); 728189f1d9bSHector Martin /* 729189f1d9bSHector Martin * Apple ARM64 platforms using these chips may have 730189f1d9bSHector Martin * inverted CD/WP detection. 731189f1d9bSHector Martin */ 732189f1d9bSHector Martin if (of_property_read_bool(pdev->dev.of_node, "cd-inverted")) 733189f1d9bSHector Martin value |= PCI_GLI_9755_INVERT_CD; 734189f1d9bSHector Martin if (of_property_read_bool(pdev->dev.of_node, "wp-inverted")) 735189f1d9bSHector Martin value |= PCI_GLI_9755_INVERT_WP; 7360f1d9961SBen Chuang value &= ~PCI_GLI_9755_LFCLK; 7370f1d9961SBen Chuang value &= ~PCI_GLI_9755_DMACLK; 7380f1d9961SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); 7390f1d9961SBen Chuang 740f46b54ccSRenius Chen /* enable short circuit protection */ 741f46b54ccSRenius Chen pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &value); 742f46b54ccSRenius Chen value &= ~PCI_GLI_9755_SCP_DIS; 743f46b54ccSRenius Chen pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value); 744f46b54ccSRenius Chen 7459751baccSBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, &value); 7469751baccSBen Chuang value &= ~PCI_GLI_9755_CFG2_L1DLY; 7479751baccSBen Chuang /* set ASPM L1 entry delay to 7.9us */ 7489751baccSBen Chuang value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY, 7499751baccSBen Chuang GLI_9755_CFG2_L1DLY_VALUE); 7509751baccSBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); 7519751baccSBen Chuang 75236ed2fd3SBen Chuang /* toggle PM state to allow GL9755 to enter ASPM L1.2 */ 75336ed2fd3SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PM_CTRL, &value); 75436ed2fd3SBen Chuang value |= PCI_GLI_9755_PM_STATE; 75536ed2fd3SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 75636ed2fd3SBen Chuang value &= ~PCI_GLI_9755_PM_STATE; 75736ed2fd3SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 75836ed2fd3SBen Chuang 7590f1d9961SBen Chuang gl9755_wt_off(pdev); 7600f1d9961SBen Chuang } 7610f1d9961SBen Chuang 762f3a5b56cSVictor Shih static inline void gl9767_vhs_read(struct pci_dev *pdev) 763f3a5b56cSVictor Shih { 764f3a5b56cSVictor Shih u32 vhs_enable; 765f3a5b56cSVictor Shih u32 vhs_value; 766f3a5b56cSVictor Shih 767f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 768f3a5b56cSVictor Shih vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 769f3a5b56cSVictor Shih 770f3a5b56cSVictor Shih if (vhs_enable == GLI_9767_VHS_REV_R) 771f3a5b56cSVictor Shih return; 772f3a5b56cSVictor Shih 773f3a5b56cSVictor Shih vhs_value &= ~GLI_9767_VHS_REV; 774f3a5b56cSVictor Shih vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R); 775f3a5b56cSVictor Shih 776f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 777f3a5b56cSVictor Shih } 778f3a5b56cSVictor Shih 779f3a5b56cSVictor Shih static inline void gl9767_vhs_write(struct pci_dev *pdev) 780f3a5b56cSVictor Shih { 781f3a5b56cSVictor Shih u32 vhs_enable; 782f3a5b56cSVictor Shih u32 vhs_value; 783f3a5b56cSVictor Shih 784f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 785f3a5b56cSVictor Shih vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 786f3a5b56cSVictor Shih 787f3a5b56cSVictor Shih if (vhs_enable == GLI_9767_VHS_REV_W) 788f3a5b56cSVictor Shih return; 789f3a5b56cSVictor Shih 790f3a5b56cSVictor Shih vhs_value &= ~GLI_9767_VHS_REV; 791f3a5b56cSVictor Shih vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W); 792f3a5b56cSVictor Shih 793f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 794f3a5b56cSVictor Shih } 795f3a5b56cSVictor Shih 796d2754355SVictor Shih static bool gl9767_ssc_enable(struct pci_dev *pdev) 797d2754355SVictor Shih { 798d2754355SVictor Shih u32 value; 799d2754355SVictor Shih u8 enable; 800d2754355SVictor Shih 801d2754355SVictor Shih gl9767_vhs_write(pdev); 802d2754355SVictor Shih 803d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_COM_MAILBOX, &value); 804d2754355SVictor Shih enable = FIELD_GET(PCIE_GLI_9767_COM_MAILBOX_SSC_EN, value); 805d2754355SVictor Shih 806d2754355SVictor Shih gl9767_vhs_read(pdev); 807d2754355SVictor Shih 808d2754355SVictor Shih return enable; 809d2754355SVictor Shih } 810d2754355SVictor Shih 811d2754355SVictor Shih static void gl9767_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 812d2754355SVictor Shih { 813d2754355SVictor Shih u32 pll; 814d2754355SVictor Shih u32 ssc; 815d2754355SVictor Shih 816d2754355SVictor Shih gl9767_vhs_write(pdev); 817d2754355SVictor Shih 818d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 819d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, &ssc); 820d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING | 821d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 822d2754355SVictor Shih ssc &= ~PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM; 823d2754355SVictor Shih pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING, step) | 824d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_EN, enable); 825d2754355SVictor Shih ssc |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM, ppm); 826d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, ssc); 827d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 828d2754355SVictor Shih 829d2754355SVictor Shih gl9767_vhs_read(pdev); 830d2754355SVictor Shih } 831d2754355SVictor Shih 832d2754355SVictor Shih static void gl9767_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 833d2754355SVictor Shih { 834d2754355SVictor Shih u32 pll; 835d2754355SVictor Shih 836d2754355SVictor Shih gl9767_vhs_write(pdev); 837d2754355SVictor Shih 838d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 839d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV | 840d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV | 841d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN); 842d2754355SVictor Shih pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV, ldiv) | 843d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV, pdiv) | 844d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN, dir); 845d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 846d2754355SVictor Shih 847d2754355SVictor Shih gl9767_vhs_read(pdev); 848d2754355SVictor Shih 849d2754355SVictor Shih /* wait for pll stable */ 850d2754355SVictor Shih usleep_range(1000, 1100); 851d2754355SVictor Shih } 852d2754355SVictor Shih 853d2754355SVictor Shih static void gl9767_set_ssc_pll_205mhz(struct pci_dev *pdev) 854d2754355SVictor Shih { 855d2754355SVictor Shih bool enable = gl9767_ssc_enable(pdev); 856d2754355SVictor Shih 857d2754355SVictor Shih /* set pll to 205MHz and ssc */ 858d2754355SVictor Shih gl9767_set_ssc(pdev, enable, 0x1F, 0xF5C3); 859d2754355SVictor Shih gl9767_set_pll(pdev, 0x1, 0x246, 0x0); 860d2754355SVictor Shih } 861d2754355SVictor Shih 862d2754355SVictor Shih static void gl9767_disable_ssc_pll(struct pci_dev *pdev) 863d2754355SVictor Shih { 864d2754355SVictor Shih u32 pll; 865d2754355SVictor Shih 866d2754355SVictor Shih gl9767_vhs_write(pdev); 867d2754355SVictor Shih 868d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 869d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN | PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 870d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 871d2754355SVictor Shih 872d2754355SVictor Shih gl9767_vhs_read(pdev); 873d2754355SVictor Shih } 874d2754355SVictor Shih 875d2754355SVictor Shih static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock) 876d2754355SVictor Shih { 877d2754355SVictor Shih struct sdhci_pci_slot *slot = sdhci_priv(host); 878d2754355SVictor Shih struct mmc_ios *ios = &host->mmc->ios; 879d2754355SVictor Shih struct pci_dev *pdev; 880d2754355SVictor Shih u32 value; 881d2754355SVictor Shih u16 clk; 882d2754355SVictor Shih 883d2754355SVictor Shih pdev = slot->chip->pdev; 884d2754355SVictor Shih host->mmc->actual_clock = 0; 885d2754355SVictor Shih 886d2754355SVictor Shih gl9767_vhs_write(pdev); 887d2754355SVictor Shih 888d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 889d2754355SVictor Shih value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; 890d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 891d2754355SVictor Shih 892d2754355SVictor Shih gl9767_disable_ssc_pll(pdev); 893d2754355SVictor Shih sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 894d2754355SVictor Shih 895d2754355SVictor Shih if (clock == 0) 896d2754355SVictor Shih return; 897d2754355SVictor Shih 898d2754355SVictor Shih clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 899d2754355SVictor Shih if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 900d2754355SVictor Shih host->mmc->actual_clock = 205000000; 901d2754355SVictor Shih gl9767_set_ssc_pll_205mhz(pdev); 902d2754355SVictor Shih } 903d2754355SVictor Shih 904d2754355SVictor Shih sdhci_enable_clk(host, clk); 905d2754355SVictor Shih 906d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 907d2754355SVictor Shih value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF; 908d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 909d2754355SVictor Shih 910d2754355SVictor Shih gl9767_vhs_read(pdev); 911d2754355SVictor Shih } 912d2754355SVictor Shih 913f3a5b56cSVictor Shih static void gli_set_9767(struct sdhci_host *host) 914f3a5b56cSVictor Shih { 915f3a5b56cSVictor Shih u32 value; 916f3a5b56cSVictor Shih 917f3a5b56cSVictor Shih value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE); 918f3a5b56cSVictor Shih value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET; 919f3a5b56cSVictor Shih sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE); 920f3a5b56cSVictor Shih } 921f3a5b56cSVictor Shih 922f3a5b56cSVictor Shih static void gl9767_hw_setting(struct sdhci_pci_slot *slot) 923f3a5b56cSVictor Shih { 924f3a5b56cSVictor Shih struct pci_dev *pdev = slot->chip->pdev; 925f3a5b56cSVictor Shih u32 value; 926f3a5b56cSVictor Shih 927f3a5b56cSVictor Shih gl9767_vhs_write(pdev); 928f3a5b56cSVictor Shih 929f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value); 930f3a5b56cSVictor Shih value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 931f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE | 932f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL); 933f3a5b56cSVictor Shih 934f3a5b56cSVictor Shih value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 935f3a5b56cSVictor Shih FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE, 936f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) | 937f3a5b56cSVictor Shih FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL, 938f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE); 939f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value); 940f3a5b56cSVictor Shih 941f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value); 942f3a5b56cSVictor Shih value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 | 943f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 | 944f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN); 945f3a5b56cSVictor Shih 946f3a5b56cSVictor Shih value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST | 947f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST | 948f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_AXI_REQ | 949f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN | 950f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF; 951f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value); 952f3a5b56cSVictor Shih 953f3a5b56cSVictor Shih gl9767_vhs_read(pdev); 954f3a5b56cSVictor Shih } 955f3a5b56cSVictor Shih 956f3a5b56cSVictor Shih static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask) 957f3a5b56cSVictor Shih { 958f3a5b56cSVictor Shih sdhci_reset(host, mask); 959f3a5b56cSVictor Shih gli_set_9767(host); 960f3a5b56cSVictor Shih } 961f3a5b56cSVictor Shih 962*0e92aec2SVictor Shih static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) 963*0e92aec2SVictor Shih { 964*0e92aec2SVictor Shih struct sdhci_host *host = mmc_priv(mmc); 965*0e92aec2SVictor Shih struct sdhci_pci_slot *slot = sdhci_priv(host); 966*0e92aec2SVictor Shih struct pci_dev *pdev; 967*0e92aec2SVictor Shih u32 value; 968*0e92aec2SVictor Shih int i; 969*0e92aec2SVictor Shih 970*0e92aec2SVictor Shih pdev = slot->chip->pdev; 971*0e92aec2SVictor Shih 972*0e92aec2SVictor Shih if (mmc->ops->get_ro(mmc)) { 973*0e92aec2SVictor Shih mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); 974*0e92aec2SVictor Shih return 0; 975*0e92aec2SVictor Shih } 976*0e92aec2SVictor Shih 977*0e92aec2SVictor Shih gl9767_vhs_write(pdev); 978*0e92aec2SVictor Shih 979*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value); 980*0e92aec2SVictor Shih value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN); 981*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value); 982*0e92aec2SVictor Shih 983*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value); 984*0e92aec2SVictor Shih value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME; 985*0e92aec2SVictor Shih value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME, 986*0e92aec2SVictor Shih PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE); 987*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value); 988*0e92aec2SVictor Shih 989*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); 990*0e92aec2SVictor Shih value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE; 991*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value); 992*0e92aec2SVictor Shih 993*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value); 994*0e92aec2SVictor Shih value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN; 995*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value); 996*0e92aec2SVictor Shih 997*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value); 998*0e92aec2SVictor Shih value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN; 999*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value); 1000*0e92aec2SVictor Shih 1001*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 1002*0e92aec2SVictor Shih value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; 1003*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 1004*0e92aec2SVictor Shih 1005*0e92aec2SVictor Shih value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1006*0e92aec2SVictor Shih value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); 1007*0e92aec2SVictor Shih sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); 1008*0e92aec2SVictor Shih 1009*0e92aec2SVictor Shih value = sdhci_readb(host, SDHCI_POWER_CONTROL); 1010*0e92aec2SVictor Shih value |= (SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); 1011*0e92aec2SVictor Shih sdhci_writeb(host, value, SDHCI_POWER_CONTROL); 1012*0e92aec2SVictor Shih 1013*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); 1014*0e92aec2SVictor Shih value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE; 1015*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); 1016*0e92aec2SVictor Shih 1017*0e92aec2SVictor Shih for (i = 0; i < 2; i++) { 1018*0e92aec2SVictor Shih usleep_range(10000, 10100); 1019*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); 1020*0e92aec2SVictor Shih if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) { 1021*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, 1022*0e92aec2SVictor Shih value); 1023*0e92aec2SVictor Shih break; 1024*0e92aec2SVictor Shih } 1025*0e92aec2SVictor Shih } 1026*0e92aec2SVictor Shih 1027*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value); 1028*0e92aec2SVictor Shih if (value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) { 1029*0e92aec2SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); 1030*0e92aec2SVictor Shih value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE; 1031*0e92aec2SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); 1032*0e92aec2SVictor Shih } else { 1033*0e92aec2SVictor Shih mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); 1034*0e92aec2SVictor Shih 1035*0e92aec2SVictor Shih value = sdhci_readb(host, SDHCI_POWER_CONTROL); 1036*0e92aec2SVictor Shih value &= ~(SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); 1037*0e92aec2SVictor Shih sdhci_writeb(host, value, SDHCI_POWER_CONTROL); 1038*0e92aec2SVictor Shih 1039*0e92aec2SVictor Shih value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1040*0e92aec2SVictor Shih value |= (SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); 1041*0e92aec2SVictor Shih sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); 1042*0e92aec2SVictor Shih } 1043*0e92aec2SVictor Shih 1044*0e92aec2SVictor Shih gl9767_vhs_read(pdev); 1045*0e92aec2SVictor Shih 1046*0e92aec2SVictor Shih return 0; 1047*0e92aec2SVictor Shih } 1048*0e92aec2SVictor Shih 1049e51df6ceSBen Chuang static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) 1050e51df6ceSBen Chuang { 1051e51df6ceSBen Chuang struct sdhci_host *host = slot->host; 1052e51df6ceSBen Chuang 10539751baccSBen Chuang gl9750_hw_setting(host); 105431e43f31SBen Chuang gli_pcie_enable_msi(slot); 1055e51df6ceSBen Chuang slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 1056e51df6ceSBen Chuang sdhci_enable_v4_mode(host); 1057e51df6ceSBen Chuang 1058e51df6ceSBen Chuang return 0; 1059e51df6ceSBen Chuang } 1060e51df6ceSBen Chuang 1061e51df6ceSBen Chuang static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) 1062e51df6ceSBen Chuang { 1063e51df6ceSBen Chuang struct sdhci_host *host = slot->host; 1064e51df6ceSBen Chuang 10650f1d9961SBen Chuang gl9755_hw_setting(slot); 106631e43f31SBen Chuang gli_pcie_enable_msi(slot); 1067e51df6ceSBen Chuang slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 1068e51df6ceSBen Chuang sdhci_enable_v4_mode(host); 1069e51df6ceSBen Chuang 1070e51df6ceSBen Chuang return 0; 1071e51df6ceSBen Chuang } 1072e51df6ceSBen Chuang 1073f3a5b56cSVictor Shih static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot) 1074f3a5b56cSVictor Shih { 1075f3a5b56cSVictor Shih struct sdhci_host *host = slot->host; 1076f3a5b56cSVictor Shih 1077f3a5b56cSVictor Shih gli_set_9767(host); 1078f3a5b56cSVictor Shih gl9767_hw_setting(slot); 1079f3a5b56cSVictor Shih gli_pcie_enable_msi(slot); 1080f3a5b56cSVictor Shih slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 1081*0e92aec2SVictor Shih host->mmc->caps2 |= MMC_CAP2_SD_EXP; 1082*0e92aec2SVictor Shih host->mmc_host_ops.init_sd_express = gl9767_init_sd_express; 1083f3a5b56cSVictor Shih sdhci_enable_v4_mode(host); 1084f3a5b56cSVictor Shih 1085f3a5b56cSVictor Shih return 0; 1086f3a5b56cSVictor Shih } 1087f3a5b56cSVictor Shih 1088e51df6ceSBen Chuang static void sdhci_gli_voltage_switch(struct sdhci_host *host) 1089e51df6ceSBen Chuang { 1090e51df6ceSBen Chuang /* 1091e51df6ceSBen Chuang * According to Section 3.6.1 signal voltage switch procedure in 1092e51df6ceSBen Chuang * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 1093e51df6ceSBen Chuang * follows: 1094e51df6ceSBen Chuang * (6) Set 1.8V Signal Enable in the Host Control 2 register. 1095e51df6ceSBen Chuang * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 1096e51df6ceSBen Chuang * period. 1097e51df6ceSBen Chuang * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 1098e51df6ceSBen Chuang * step (12). 1099e51df6ceSBen Chuang * 1100e51df6ceSBen Chuang * Wait 5ms after set 1.8V signal enable in Host Control 2 register 1101e51df6ceSBen Chuang * to ensure 1.8V signal enable bit is set by GL9750/GL9755. 1102a1149a6cSDaniel Beer * 1103a1149a6cSDaniel Beer * ...however, the controller in the NUC10i3FNK4 (a 9755) requires 1104a1149a6cSDaniel Beer * slightly longer than 5ms before the control register reports that 1105a1149a6cSDaniel Beer * 1.8V is ready, and far longer still before the card will actually 1106a1149a6cSDaniel Beer * work reliably. 1107e51df6ceSBen Chuang */ 1108a1149a6cSDaniel Beer usleep_range(100000, 110000); 1109e51df6ceSBen Chuang } 1110e51df6ceSBen Chuang 1111f3a5b56cSVictor Shih static void sdhci_gl9767_voltage_switch(struct sdhci_host *host) 1112f3a5b56cSVictor Shih { 1113f3a5b56cSVictor Shih /* 1114f3a5b56cSVictor Shih * According to Section 3.6.1 signal voltage switch procedure in 1115f3a5b56cSVictor Shih * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 1116f3a5b56cSVictor Shih * follows: 1117f3a5b56cSVictor Shih * (6) Set 1.8V Signal Enable in the Host Control 2 register. 1118f3a5b56cSVictor Shih * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 1119f3a5b56cSVictor Shih * period. 1120f3a5b56cSVictor Shih * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 1121f3a5b56cSVictor Shih * step (12). 1122f3a5b56cSVictor Shih * 1123f3a5b56cSVictor Shih * Wait 5ms after set 1.8V signal enable in Host Control 2 register 1124f3a5b56cSVictor Shih * to ensure 1.8V signal enable bit is set by GL9767. 1125f3a5b56cSVictor Shih * 1126f3a5b56cSVictor Shih */ 1127f3a5b56cSVictor Shih usleep_range(5000, 5500); 1128f3a5b56cSVictor Shih } 1129f3a5b56cSVictor Shih 1130e51df6ceSBen Chuang static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask) 1131e51df6ceSBen Chuang { 1132e51df6ceSBen Chuang sdhci_reset(host, mask); 1133e51df6ceSBen Chuang gli_set_9750(host); 1134e51df6ceSBen Chuang } 1135e51df6ceSBen Chuang 1136e51df6ceSBen Chuang static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg) 1137e51df6ceSBen Chuang { 1138e51df6ceSBen Chuang u32 value; 1139e51df6ceSBen Chuang 1140e51df6ceSBen Chuang value = readl(host->ioaddr + reg); 1141e51df6ceSBen Chuang if (unlikely(reg == SDHCI_MAX_CURRENT && !(value & 0xff))) 1142e51df6ceSBen Chuang value |= 0xc8; 1143e51df6ceSBen Chuang 1144e51df6ceSBen Chuang return value; 1145e51df6ceSBen Chuang } 1146e51df6ceSBen Chuang 1147282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1148282ede76SBen Chuang static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) 1149282ede76SBen Chuang { 1150282ede76SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1151282ede76SBen Chuang 1152282ede76SBen Chuang pci_free_irq_vectors(slot->chip->pdev); 1153282ede76SBen Chuang gli_pcie_enable_msi(slot); 1154282ede76SBen Chuang 1155282ede76SBen Chuang return sdhci_pci_resume_host(chip); 1156282ede76SBen Chuang } 1157347f6be1SBen Chuang 1158347f6be1SBen Chuang static int sdhci_cqhci_gli_resume(struct sdhci_pci_chip *chip) 1159347f6be1SBen Chuang { 1160347f6be1SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1161347f6be1SBen Chuang int ret; 1162347f6be1SBen Chuang 1163347f6be1SBen Chuang ret = sdhci_pci_gli_resume(chip); 1164347f6be1SBen Chuang if (ret) 1165347f6be1SBen Chuang return ret; 1166347f6be1SBen Chuang 1167347f6be1SBen Chuang return cqhci_resume(slot->host->mmc); 1168347f6be1SBen Chuang } 1169347f6be1SBen Chuang 1170347f6be1SBen Chuang static int sdhci_cqhci_gli_suspend(struct sdhci_pci_chip *chip) 1171347f6be1SBen Chuang { 1172347f6be1SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1173347f6be1SBen Chuang int ret; 1174347f6be1SBen Chuang 1175347f6be1SBen Chuang ret = cqhci_suspend(slot->host->mmc); 1176347f6be1SBen Chuang if (ret) 1177347f6be1SBen Chuang return ret; 1178347f6be1SBen Chuang 1179347f6be1SBen Chuang return sdhci_suspend_host(slot->host); 1180347f6be1SBen Chuang } 1181282ede76SBen Chuang #endif 1182282ede76SBen Chuang 11831ae1d2d6SBen Chuang static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, 11841ae1d2d6SBen Chuang struct mmc_ios *ios) 11851ae1d2d6SBen Chuang { 11861ae1d2d6SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 11871ae1d2d6SBen Chuang u32 val; 11881ae1d2d6SBen Chuang 11891ae1d2d6SBen Chuang val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG); 11901ae1d2d6SBen Chuang if (ios->enhanced_strobe) 11911ae1d2d6SBen Chuang val |= SDHCI_GLI_9763E_HS400_ES_BIT; 11921ae1d2d6SBen Chuang else 11931ae1d2d6SBen Chuang val &= ~SDHCI_GLI_9763E_HS400_ES_BIT; 11941ae1d2d6SBen Chuang 11951ae1d2d6SBen Chuang sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); 11961ae1d2d6SBen Chuang } 11971ae1d2d6SBen Chuang 11981ae1d2d6SBen Chuang static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, 11991ae1d2d6SBen Chuang unsigned int timing) 12001ae1d2d6SBen Chuang { 12011ae1d2d6SBen Chuang u16 ctrl_2; 12021ae1d2d6SBen Chuang 12031ae1d2d6SBen Chuang ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 12041ae1d2d6SBen Chuang ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 12051ae1d2d6SBen Chuang if (timing == MMC_TIMING_MMC_HS200) 12061ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 12071ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_HS) 12081ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 12091ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_DDR52) 12101ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 12111ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_HS400) 12121ae1d2d6SBen Chuang ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400; 12131ae1d2d6SBen Chuang 12141ae1d2d6SBen Chuang sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 12151ae1d2d6SBen Chuang } 12161ae1d2d6SBen Chuang 1217347f6be1SBen Chuang static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) 1218347f6be1SBen Chuang { 1219347f6be1SBen Chuang sdhci_dumpregs(mmc_priv(mmc)); 1220347f6be1SBen Chuang } 1221347f6be1SBen Chuang 1222347f6be1SBen Chuang static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) 1223347f6be1SBen Chuang { 1224347f6be1SBen Chuang struct cqhci_host *cq_host = mmc->cqe_private; 1225347f6be1SBen Chuang u32 value; 1226347f6be1SBen Chuang 1227347f6be1SBen Chuang value = cqhci_readl(cq_host, CQHCI_CFG); 1228347f6be1SBen Chuang value |= CQHCI_ENABLE; 1229347f6be1SBen Chuang cqhci_writel(cq_host, value, CQHCI_CFG); 1230347f6be1SBen Chuang } 1231347f6be1SBen Chuang 1232347f6be1SBen Chuang static void sdhci_gl9763e_cqe_enable(struct mmc_host *mmc) 1233347f6be1SBen Chuang { 1234347f6be1SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 1235347f6be1SBen Chuang 1236347f6be1SBen Chuang sdhci_writew(host, GLI_9763E_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); 1237347f6be1SBen Chuang sdhci_cqe_enable(mmc); 1238347f6be1SBen Chuang } 1239347f6be1SBen Chuang 1240347f6be1SBen Chuang static u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask) 1241347f6be1SBen Chuang { 1242347f6be1SBen Chuang int cmd_error = 0; 1243347f6be1SBen Chuang int data_error = 0; 1244347f6be1SBen Chuang 1245347f6be1SBen Chuang if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) 1246347f6be1SBen Chuang return intmask; 1247347f6be1SBen Chuang 1248347f6be1SBen Chuang cqhci_irq(host->mmc, intmask, cmd_error, data_error); 1249347f6be1SBen Chuang 1250347f6be1SBen Chuang return 0; 1251347f6be1SBen Chuang } 1252347f6be1SBen Chuang 1253347f6be1SBen Chuang static void sdhci_gl9763e_cqe_post_disable(struct mmc_host *mmc) 1254347f6be1SBen Chuang { 1255347f6be1SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 1256347f6be1SBen Chuang struct cqhci_host *cq_host = mmc->cqe_private; 1257347f6be1SBen Chuang u32 value; 1258347f6be1SBen Chuang 1259347f6be1SBen Chuang value = cqhci_readl(cq_host, CQHCI_CFG); 1260347f6be1SBen Chuang value &= ~CQHCI_ENABLE; 1261347f6be1SBen Chuang cqhci_writel(cq_host, value, CQHCI_CFG); 1262347f6be1SBen Chuang sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 1263347f6be1SBen Chuang } 1264347f6be1SBen Chuang 1265347f6be1SBen Chuang static const struct cqhci_host_ops sdhci_gl9763e_cqhci_ops = { 1266347f6be1SBen Chuang .enable = sdhci_gl9763e_cqe_enable, 1267347f6be1SBen Chuang .disable = sdhci_cqe_disable, 1268347f6be1SBen Chuang .dumpregs = sdhci_gl9763e_dumpregs, 1269347f6be1SBen Chuang .pre_enable = sdhci_gl9763e_cqe_pre_enable, 1270347f6be1SBen Chuang .post_disable = sdhci_gl9763e_cqe_post_disable, 1271347f6be1SBen Chuang }; 1272347f6be1SBen Chuang 1273347f6be1SBen Chuang static int gl9763e_add_host(struct sdhci_pci_slot *slot) 1274347f6be1SBen Chuang { 1275347f6be1SBen Chuang struct device *dev = &slot->chip->pdev->dev; 1276347f6be1SBen Chuang struct sdhci_host *host = slot->host; 1277347f6be1SBen Chuang struct cqhci_host *cq_host; 1278347f6be1SBen Chuang bool dma64; 1279347f6be1SBen Chuang int ret; 1280347f6be1SBen Chuang 1281347f6be1SBen Chuang ret = sdhci_setup_host(host); 1282347f6be1SBen Chuang if (ret) 1283347f6be1SBen Chuang return ret; 1284347f6be1SBen Chuang 1285347f6be1SBen Chuang cq_host = devm_kzalloc(dev, sizeof(*cq_host), GFP_KERNEL); 1286347f6be1SBen Chuang if (!cq_host) { 1287347f6be1SBen Chuang ret = -ENOMEM; 1288347f6be1SBen Chuang goto cleanup; 1289347f6be1SBen Chuang } 1290347f6be1SBen Chuang 1291347f6be1SBen Chuang cq_host->mmio = host->ioaddr + SDHCI_GLI_9763E_CQE_BASE_ADDR; 1292347f6be1SBen Chuang cq_host->ops = &sdhci_gl9763e_cqhci_ops; 1293347f6be1SBen Chuang 1294347f6be1SBen Chuang dma64 = host->flags & SDHCI_USE_64_BIT_DMA; 1295347f6be1SBen Chuang if (dma64) 1296347f6be1SBen Chuang cq_host->caps |= CQHCI_TASK_DESC_SZ_128; 1297347f6be1SBen Chuang 1298347f6be1SBen Chuang ret = cqhci_init(cq_host, host->mmc, dma64); 1299347f6be1SBen Chuang if (ret) 1300347f6be1SBen Chuang goto cleanup; 1301347f6be1SBen Chuang 1302347f6be1SBen Chuang ret = __sdhci_add_host(host); 1303347f6be1SBen Chuang if (ret) 1304347f6be1SBen Chuang goto cleanup; 1305347f6be1SBen Chuang 1306347f6be1SBen Chuang return 0; 1307347f6be1SBen Chuang 1308347f6be1SBen Chuang cleanup: 1309347f6be1SBen Chuang sdhci_cleanup_host(host); 1310347f6be1SBen Chuang return ret; 1311347f6be1SBen Chuang } 1312347f6be1SBen Chuang 13131ae1d2d6SBen Chuang static void gli_set_gl9763e(struct sdhci_pci_slot *slot) 13141ae1d2d6SBen Chuang { 13151ae1d2d6SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 13161ae1d2d6SBen Chuang u32 value; 13171ae1d2d6SBen Chuang 13181ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 13191ae1d2d6SBen Chuang value &= ~GLI_9763E_VHS_REV; 13201ae1d2d6SBen Chuang value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 13211ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 13221ae1d2d6SBen Chuang 13231ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value); 13241ae1d2d6SBen Chuang value |= GLI_9763E_SCR_AXI_REQ; 13251ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); 13261ae1d2d6SBen Chuang 132798991b18SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, &value); 132898991b18SBen Chuang value &= ~GLI_9763E_HS400_SLOW; 132998991b18SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, value); 133098991b18SBen Chuang 1331edee82f7SRenius Chen pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value); 1332edee82f7SRenius Chen value &= ~GLI_9763E_CFG2_L1DLY; 133334dd3cccSBen Chuang /* set ASPM L1 entry delay to 21us */ 1334baaaf55dSBen Chuang value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); 1335edee82f7SRenius Chen pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); 1336edee82f7SRenius Chen 1337c58c5950SRenius Chen pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); 1338c58c5950SRenius Chen value &= ~GLI_9763E_HS400_RXDLY; 1339c58c5950SRenius Chen value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); 1340c58c5950SRenius Chen pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value); 1341c58c5950SRenius Chen 13421ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 13431ae1d2d6SBen Chuang value &= ~GLI_9763E_VHS_REV; 13441ae1d2d6SBen Chuang value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 13451ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 13461ae1d2d6SBen Chuang } 13471ae1d2d6SBen Chuang 1348d607667bSBen Chuang #ifdef CONFIG_PM 13491c5fd973SRen Zhijie static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) 13501c5fd973SRen Zhijie { 13511c5fd973SRen Zhijie struct pci_dev *pdev = slot->chip->pdev; 13521c5fd973SRen Zhijie u32 value; 13531c5fd973SRen Zhijie 13541c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 13551c5fd973SRen Zhijie value &= ~GLI_9763E_VHS_REV; 13561c5fd973SRen Zhijie value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 13571c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 13581c5fd973SRen Zhijie 13591c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); 13601c5fd973SRen Zhijie 13611c5fd973SRen Zhijie if (enable) 13621c5fd973SRen Zhijie value &= ~GLI_9763E_CFG_LPSN_DIS; 13631c5fd973SRen Zhijie else 13641c5fd973SRen Zhijie value |= GLI_9763E_CFG_LPSN_DIS; 13651c5fd973SRen Zhijie 13661c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); 13671c5fd973SRen Zhijie 13681c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 13691c5fd973SRen Zhijie value &= ~GLI_9763E_VHS_REV; 13701c5fd973SRen Zhijie value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 13711c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 13721c5fd973SRen Zhijie } 13731c5fd973SRen Zhijie 1374d607667bSBen Chuang static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) 1375d607667bSBen Chuang { 1376d607667bSBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1377d607667bSBen Chuang struct sdhci_host *host = slot->host; 1378d607667bSBen Chuang u16 clock; 1379d607667bSBen Chuang 1380f9e5b339SJason Lai /* Enable LPM negotiation to allow entering L1 state */ 1381f9e5b339SJason Lai gl9763e_set_low_power_negotiation(slot, true); 1382f9e5b339SJason Lai 1383d607667bSBen Chuang clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1384d607667bSBen Chuang clock &= ~(SDHCI_CLOCK_PLL_EN | SDHCI_CLOCK_CARD_EN); 1385d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1386d607667bSBen Chuang 1387d607667bSBen Chuang return 0; 1388d607667bSBen Chuang } 1389d607667bSBen Chuang 1390d607667bSBen Chuang static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) 1391d607667bSBen Chuang { 1392d607667bSBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1393d607667bSBen Chuang struct sdhci_host *host = slot->host; 1394d607667bSBen Chuang u16 clock; 1395d607667bSBen Chuang 1396291e7d52SBen Chuang if (host->mmc->ios.power_mode != MMC_POWER_ON) 1397291e7d52SBen Chuang return 0; 1398291e7d52SBen Chuang 1399d607667bSBen Chuang clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1400d607667bSBen Chuang 1401d607667bSBen Chuang clock |= SDHCI_CLOCK_PLL_EN; 1402d607667bSBen Chuang clock &= ~SDHCI_CLOCK_INT_STABLE; 1403d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1404d607667bSBen Chuang 1405d607667bSBen Chuang /* Wait max 150 ms */ 1406d607667bSBen Chuang if (read_poll_timeout(sdhci_readw, clock, (clock & SDHCI_CLOCK_INT_STABLE), 1407d607667bSBen Chuang 1000, 150000, false, host, SDHCI_CLOCK_CONTROL)) { 1408d607667bSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 1409d607667bSBen Chuang mmc_hostname(host->mmc)); 1410d607667bSBen Chuang sdhci_dumpregs(host); 1411d607667bSBen Chuang } 1412d607667bSBen Chuang 1413d607667bSBen Chuang clock |= SDHCI_CLOCK_CARD_EN; 1414d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1415d607667bSBen Chuang 1416f9e5b339SJason Lai /* Disable LPM negotiation to avoid entering L1 state. */ 1417f9e5b339SJason Lai gl9763e_set_low_power_negotiation(slot, false); 1418f9e5b339SJason Lai 1419d607667bSBen Chuang return 0; 1420d607667bSBen Chuang } 1421d607667bSBen Chuang #endif 1422d607667bSBen Chuang 14231ae1d2d6SBen Chuang static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) 14241ae1d2d6SBen Chuang { 1425347f6be1SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 14261ae1d2d6SBen Chuang struct sdhci_host *host = slot->host; 1427347f6be1SBen Chuang u32 value; 14281ae1d2d6SBen Chuang 14291ae1d2d6SBen Chuang host->mmc->caps |= MMC_CAP_8_BIT_DATA | 14301ae1d2d6SBen Chuang MMC_CAP_1_8V_DDR | 14311ae1d2d6SBen Chuang MMC_CAP_NONREMOVABLE; 14321ae1d2d6SBen Chuang host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR | 14331ae1d2d6SBen Chuang MMC_CAP2_HS400_1_8V | 14341ae1d2d6SBen Chuang MMC_CAP2_HS400_ES | 14351ae1d2d6SBen Chuang MMC_CAP2_NO_SDIO | 14361ae1d2d6SBen Chuang MMC_CAP2_NO_SD; 1437347f6be1SBen Chuang 1438347f6be1SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_MB, &value); 1439347f6be1SBen Chuang if (!(value & GLI_9763E_MB_CMDQ_OFF)) 144015f908faSRenius Chen if (value & GLI_9763E_MB_ERP_ON) 1441347f6be1SBen Chuang host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; 1442347f6be1SBen Chuang 14431ae1d2d6SBen Chuang gli_pcie_enable_msi(slot); 14441ae1d2d6SBen Chuang host->mmc_host_ops.hs400_enhanced_strobe = 14451ae1d2d6SBen Chuang gl9763e_hs400_enhanced_strobe; 14461ae1d2d6SBen Chuang gli_set_gl9763e(slot); 14471ae1d2d6SBen Chuang sdhci_enable_v4_mode(host); 14481ae1d2d6SBen Chuang 14491ae1d2d6SBen Chuang return 0; 14501ae1d2d6SBen Chuang } 14511ae1d2d6SBen Chuang 1452c064bb5cSHector Martin #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18) 1453c064bb5cSHector Martin 1454c064bb5cSHector Martin static u16 sdhci_gli_readw(struct sdhci_host *host, int reg) 1455c064bb5cSHector Martin { 1456c064bb5cSHector Martin u32 val = readl(host->ioaddr + (reg & ~3)); 1457c064bb5cSHector Martin u16 word; 1458c064bb5cSHector Martin 1459c064bb5cSHector Martin word = (val >> REG_OFFSET_IN_BITS(reg)) & 0xffff; 1460c064bb5cSHector Martin return word; 1461c064bb5cSHector Martin } 1462c064bb5cSHector Martin 1463c064bb5cSHector Martin static u8 sdhci_gli_readb(struct sdhci_host *host, int reg) 1464c064bb5cSHector Martin { 1465c064bb5cSHector Martin u32 val = readl(host->ioaddr + (reg & ~3)); 1466c064bb5cSHector Martin u8 byte = (val >> REG_OFFSET_IN_BITS(reg)) & 0xff; 1467c064bb5cSHector Martin 1468c064bb5cSHector Martin return byte; 1469c064bb5cSHector Martin } 1470c064bb5cSHector Martin 1471e51df6ceSBen Chuang static const struct sdhci_ops sdhci_gl9755_ops = { 1472c064bb5cSHector Martin .read_w = sdhci_gli_readw, 1473c064bb5cSHector Martin .read_b = sdhci_gli_readb, 1474786d33c8SBen Chuang .set_clock = sdhci_gl9755_set_clock, 1475e51df6ceSBen Chuang .enable_dma = sdhci_pci_enable_dma, 1476e51df6ceSBen Chuang .set_bus_width = sdhci_set_bus_width, 1477e51df6ceSBen Chuang .reset = sdhci_reset, 1478e51df6ceSBen Chuang .set_uhs_signaling = sdhci_set_uhs_signaling, 1479e51df6ceSBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1480e51df6ceSBen Chuang }; 1481e51df6ceSBen Chuang 1482e51df6ceSBen Chuang const struct sdhci_pci_fixes sdhci_gl9755 = { 1483e51df6ceSBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1484e51df6ceSBen Chuang .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1485e51df6ceSBen Chuang .probe_slot = gli_probe_slot_gl9755, 1486e51df6ceSBen Chuang .ops = &sdhci_gl9755_ops, 1487282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1488282ede76SBen Chuang .resume = sdhci_pci_gli_resume, 1489282ede76SBen Chuang #endif 1490e51df6ceSBen Chuang }; 1491e51df6ceSBen Chuang 1492e51df6ceSBen Chuang static const struct sdhci_ops sdhci_gl9750_ops = { 1493c064bb5cSHector Martin .read_w = sdhci_gli_readw, 1494c064bb5cSHector Martin .read_b = sdhci_gli_readb, 1495e51df6ceSBen Chuang .read_l = sdhci_gl9750_readl, 1496786d33c8SBen Chuang .set_clock = sdhci_gl9750_set_clock, 1497e51df6ceSBen Chuang .enable_dma = sdhci_pci_enable_dma, 1498e51df6ceSBen Chuang .set_bus_width = sdhci_set_bus_width, 1499e51df6ceSBen Chuang .reset = sdhci_gl9750_reset, 1500e51df6ceSBen Chuang .set_uhs_signaling = sdhci_set_uhs_signaling, 1501e51df6ceSBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1502e51df6ceSBen Chuang .platform_execute_tuning = gl9750_execute_tuning, 1503e51df6ceSBen Chuang }; 1504e51df6ceSBen Chuang 1505e51df6ceSBen Chuang const struct sdhci_pci_fixes sdhci_gl9750 = { 1506e51df6ceSBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1507e51df6ceSBen Chuang .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1508e51df6ceSBen Chuang .probe_slot = gli_probe_slot_gl9750, 1509e51df6ceSBen Chuang .ops = &sdhci_gl9750_ops, 1510282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1511282ede76SBen Chuang .resume = sdhci_pci_gli_resume, 1512282ede76SBen Chuang #endif 1513e51df6ceSBen Chuang }; 15141ae1d2d6SBen Chuang 15151ae1d2d6SBen Chuang static const struct sdhci_ops sdhci_gl9763e_ops = { 15161ae1d2d6SBen Chuang .set_clock = sdhci_set_clock, 15171ae1d2d6SBen Chuang .enable_dma = sdhci_pci_enable_dma, 15181ae1d2d6SBen Chuang .set_bus_width = sdhci_set_bus_width, 151908b863bbSBrian Norris .reset = sdhci_and_cqhci_reset, 15201ae1d2d6SBen Chuang .set_uhs_signaling = sdhci_set_gl9763e_signaling, 15211ae1d2d6SBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1522347f6be1SBen Chuang .irq = sdhci_gl9763e_cqhci_irq, 15231ae1d2d6SBen Chuang }; 15241ae1d2d6SBen Chuang 15251ae1d2d6SBen Chuang const struct sdhci_pci_fixes sdhci_gl9763e = { 15261ae1d2d6SBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 15271ae1d2d6SBen Chuang .probe_slot = gli_probe_slot_gl9763e, 15281ae1d2d6SBen Chuang .ops = &sdhci_gl9763e_ops, 15291ae1d2d6SBen Chuang #ifdef CONFIG_PM_SLEEP 1530347f6be1SBen Chuang .resume = sdhci_cqhci_gli_resume, 1531347f6be1SBen Chuang .suspend = sdhci_cqhci_gli_suspend, 15321ae1d2d6SBen Chuang #endif 1533d607667bSBen Chuang #ifdef CONFIG_PM 1534d607667bSBen Chuang .runtime_suspend = gl9763e_runtime_suspend, 1535d607667bSBen Chuang .runtime_resume = gl9763e_runtime_resume, 1536d607667bSBen Chuang .allow_runtime_pm = true, 1537d607667bSBen Chuang #endif 1538347f6be1SBen Chuang .add_host = gl9763e_add_host, 15391ae1d2d6SBen Chuang }; 1540f3a5b56cSVictor Shih 1541f3a5b56cSVictor Shih static const struct sdhci_ops sdhci_gl9767_ops = { 1542d2754355SVictor Shih .set_clock = sdhci_gl9767_set_clock, 1543f3a5b56cSVictor Shih .enable_dma = sdhci_pci_enable_dma, 1544f3a5b56cSVictor Shih .set_bus_width = sdhci_set_bus_width, 1545f3a5b56cSVictor Shih .reset = sdhci_gl9767_reset, 1546f3a5b56cSVictor Shih .set_uhs_signaling = sdhci_set_uhs_signaling, 1547f3a5b56cSVictor Shih .voltage_switch = sdhci_gl9767_voltage_switch, 1548f3a5b56cSVictor Shih }; 1549f3a5b56cSVictor Shih 1550f3a5b56cSVictor Shih const struct sdhci_pci_fixes sdhci_gl9767 = { 1551f3a5b56cSVictor Shih .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1552f3a5b56cSVictor Shih .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1553f3a5b56cSVictor Shih .probe_slot = gli_probe_slot_gl9767, 1554f3a5b56cSVictor Shih .ops = &sdhci_gl9767_ops, 1555f3a5b56cSVictor Shih #ifdef CONFIG_PM_SLEEP 1556f3a5b56cSVictor Shih .resume = sdhci_pci_gli_resume, 1557f3a5b56cSVictor Shih #endif 1558f3a5b56cSVictor Shih }; 1559