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 161*d2754355SVictor Shih #define PCIE_GLI_9767_COM_MAILBOX 0x888 162*d2754355SVictor Shih #define PCIE_GLI_9767_COM_MAILBOX_SSC_EN BIT(1) 163*d2754355SVictor Shih 164*d2754355SVictor Shih #define PCIE_GLI_9767_CFG 0x8A0 165*d2754355SVictor Shih #define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12) 166*d2754355SVictor Shih 167f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0 168f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0) 169f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12) 170f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7 171f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28) 172f3a5b56cSVictor Shih #define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3 173f3a5b56cSVictor Shih 174f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR 0x8E0 175f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6) 176f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7) 177f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_AXI_REQ BIT(9) 178f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10) 179f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16) 180f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17) 181f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21) 182f3a5b56cSVictor Shih #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30) 183f3a5b56cSVictor Shih 184*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL 0x938 185*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0) 186*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12) 187*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN BIT(16) 188*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_SSC_EN BIT(19) 189*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING GENMASK(28, 24) 190*d2754355SVictor Shih 191*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL2 0x93C 192*d2754355SVictor Shih #define PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM GENMASK(31, 16) 193*d2754355SVictor Shih 194e51df6ceSBen Chuang #define GLI_MAX_TUNING_LOOP 40 195e51df6ceSBen Chuang 196e51df6ceSBen Chuang /* Genesys Logic chipset */ 197e51df6ceSBen Chuang static inline void gl9750_wt_on(struct sdhci_host *host) 198e51df6ceSBen Chuang { 199e51df6ceSBen Chuang u32 wt_value; 200e51df6ceSBen Chuang u32 wt_enable; 201e51df6ceSBen Chuang 202e51df6ceSBen Chuang wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 203e51df6ceSBen Chuang wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 204e51df6ceSBen Chuang 205e51df6ceSBen Chuang if (wt_enable == GLI_9750_WT_EN_ON) 206e51df6ceSBen Chuang return; 207e51df6ceSBen Chuang 208e51df6ceSBen Chuang wt_value &= ~SDHCI_GLI_9750_WT_EN; 209e51df6ceSBen Chuang wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_ON); 210e51df6ceSBen Chuang 211e51df6ceSBen Chuang sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 212e51df6ceSBen Chuang } 213e51df6ceSBen Chuang 214e51df6ceSBen Chuang static inline void gl9750_wt_off(struct sdhci_host *host) 215e51df6ceSBen Chuang { 216e51df6ceSBen Chuang u32 wt_value; 217e51df6ceSBen Chuang u32 wt_enable; 218e51df6ceSBen Chuang 219e51df6ceSBen Chuang wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 220e51df6ceSBen Chuang wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 221e51df6ceSBen Chuang 222e51df6ceSBen Chuang if (wt_enable == GLI_9750_WT_EN_OFF) 223e51df6ceSBen Chuang return; 224e51df6ceSBen Chuang 225e51df6ceSBen Chuang wt_value &= ~SDHCI_GLI_9750_WT_EN; 226e51df6ceSBen Chuang wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_OFF); 227e51df6ceSBen Chuang 228e51df6ceSBen Chuang sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 229e51df6ceSBen Chuang } 230e51df6ceSBen Chuang 231e51df6ceSBen Chuang static void gli_set_9750(struct sdhci_host *host) 232e51df6ceSBen Chuang { 233e51df6ceSBen Chuang u32 driving_value; 234e51df6ceSBen Chuang u32 pll_value; 235e51df6ceSBen Chuang u32 sw_ctrl_value; 236e51df6ceSBen Chuang u32 misc_value; 237e51df6ceSBen Chuang u32 parameter_value; 238e51df6ceSBen Chuang u32 control_value; 239e51df6ceSBen Chuang u16 ctrl2; 240e51df6ceSBen Chuang 241e51df6ceSBen Chuang gl9750_wt_on(host); 242e51df6ceSBen Chuang 243e51df6ceSBen Chuang driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); 244e51df6ceSBen Chuang pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); 245e51df6ceSBen Chuang sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); 246e51df6ceSBen Chuang misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 247e51df6ceSBen Chuang parameter_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_PARAMETERS); 248e51df6ceSBen Chuang control_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_CONTROL); 249e51df6ceSBen Chuang 250e51df6ceSBen Chuang driving_value &= ~(SDHCI_GLI_9750_DRIVING_1); 251e51df6ceSBen Chuang driving_value &= ~(SDHCI_GLI_9750_DRIVING_2); 252e51df6ceSBen Chuang driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1, 253e51df6ceSBen Chuang GLI_9750_DRIVING_1_VALUE); 254e51df6ceSBen Chuang driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2, 255e51df6ceSBen Chuang GLI_9750_DRIVING_2_VALUE); 256b56ff195SBen Chuang driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST); 257b56ff195SBen Chuang driving_value |= SDHCI_GLI_9750_SEL_2; 258e51df6ceSBen Chuang sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING); 259e51df6ceSBen Chuang 260e51df6ceSBen Chuang sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4; 261e51df6ceSBen Chuang sw_ctrl_value |= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4, 262e51df6ceSBen Chuang GLI_9750_SW_CTRL_4_VALUE); 263e51df6ceSBen Chuang sdhci_writel(host, sw_ctrl_value, SDHCI_GLI_9750_SW_CTRL); 264e51df6ceSBen Chuang 265e51df6ceSBen Chuang /* reset the tuning flow after reinit and before starting tuning */ 266e51df6ceSBen Chuang pll_value &= ~SDHCI_GLI_9750_PLL_TX2_INV; 267e51df6ceSBen Chuang pll_value &= ~SDHCI_GLI_9750_PLL_TX2_DLY; 268e51df6ceSBen Chuang pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV, 269e51df6ceSBen Chuang GLI_9750_PLL_TX2_INV_VALUE); 270e51df6ceSBen Chuang pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY, 271e51df6ceSBen Chuang GLI_9750_PLL_TX2_DLY_VALUE); 272e51df6ceSBen Chuang 273e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_TX1_INV; 274e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 275e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_TX1_DLY; 276e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV, 277e51df6ceSBen Chuang GLI_9750_MISC_TX1_INV_VALUE); 278e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 279e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_VALUE); 280e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY, 281e51df6ceSBen Chuang GLI_9750_MISC_TX1_DLY_VALUE); 282e51df6ceSBen Chuang 283e51df6ceSBen Chuang parameter_value &= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY; 284e51df6ceSBen Chuang parameter_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY, 285e51df6ceSBen Chuang GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE); 286e51df6ceSBen Chuang 287e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1; 288e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2; 289e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1, 290e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE); 291e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2, 292e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE); 293e51df6ceSBen Chuang 294e51df6ceSBen Chuang sdhci_writel(host, pll_value, SDHCI_GLI_9750_PLL); 295e51df6ceSBen Chuang sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 296e51df6ceSBen Chuang 297e51df6ceSBen Chuang /* disable tuned clk */ 298e51df6ceSBen Chuang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 299e51df6ceSBen Chuang ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 300e51df6ceSBen Chuang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 301e51df6ceSBen Chuang 302e51df6ceSBen Chuang /* enable tuning parameters control */ 303e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 304e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 305e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_EN_ON); 306e51df6ceSBen Chuang sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 307e51df6ceSBen Chuang 308e51df6ceSBen Chuang /* write tuning parameters */ 309e51df6ceSBen Chuang sdhci_writel(host, parameter_value, SDHCI_GLI_9750_TUNING_PARAMETERS); 310e51df6ceSBen Chuang 311e51df6ceSBen Chuang /* disable tuning parameters control */ 312e51df6ceSBen Chuang control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 313e51df6ceSBen Chuang control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 314e51df6ceSBen Chuang GLI_9750_TUNING_CONTROL_EN_OFF); 315e51df6ceSBen Chuang sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 316e51df6ceSBen Chuang 317e51df6ceSBen Chuang /* clear tuned clk */ 318e51df6ceSBen Chuang ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 319e51df6ceSBen Chuang ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 320e51df6ceSBen Chuang sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 321e51df6ceSBen Chuang 322e51df6ceSBen Chuang gl9750_wt_off(host); 323e51df6ceSBen Chuang } 324e51df6ceSBen Chuang 325e51df6ceSBen Chuang static void gli_set_9750_rx_inv(struct sdhci_host *host, bool b) 326e51df6ceSBen Chuang { 327e51df6ceSBen Chuang u32 misc_value; 328e51df6ceSBen Chuang 329e51df6ceSBen Chuang gl9750_wt_on(host); 330e51df6ceSBen Chuang 331e51df6ceSBen Chuang misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 332e51df6ceSBen Chuang misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 333e51df6ceSBen Chuang if (b) { 334e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 335e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_ON); 336e51df6ceSBen Chuang } else { 337e51df6ceSBen Chuang misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 338e51df6ceSBen Chuang GLI_9750_MISC_RX_INV_OFF); 339e51df6ceSBen Chuang } 340e51df6ceSBen Chuang sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 341e51df6ceSBen Chuang 342e51df6ceSBen Chuang gl9750_wt_off(host); 343e51df6ceSBen Chuang } 344e51df6ceSBen Chuang 345e51df6ceSBen Chuang static int __sdhci_execute_tuning_9750(struct sdhci_host *host, u32 opcode) 346e51df6ceSBen Chuang { 347e51df6ceSBen Chuang int i; 348e51df6ceSBen Chuang int rx_inv; 349e51df6ceSBen Chuang 350e51df6ceSBen Chuang for (rx_inv = 0; rx_inv < 2; rx_inv++) { 351e51df6ceSBen Chuang gli_set_9750_rx_inv(host, !!rx_inv); 352e51df6ceSBen Chuang sdhci_start_tuning(host); 353e51df6ceSBen Chuang 354e51df6ceSBen Chuang for (i = 0; i < GLI_MAX_TUNING_LOOP; i++) { 355e51df6ceSBen Chuang u16 ctrl; 356e51df6ceSBen Chuang 357e51df6ceSBen Chuang sdhci_send_tuning(host, opcode); 358e51df6ceSBen Chuang 359e51df6ceSBen Chuang if (!host->tuning_done) { 360e51df6ceSBen Chuang sdhci_abort_tuning(host, opcode); 361e51df6ceSBen Chuang break; 362e51df6ceSBen Chuang } 363e51df6ceSBen Chuang 364e51df6ceSBen Chuang ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 365e51df6ceSBen Chuang if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 366e51df6ceSBen Chuang if (ctrl & SDHCI_CTRL_TUNED_CLK) 367e51df6ceSBen Chuang return 0; /* Success! */ 368e51df6ceSBen Chuang break; 369e51df6ceSBen Chuang } 370e51df6ceSBen Chuang } 371e51df6ceSBen Chuang } 372e51df6ceSBen Chuang if (!host->tuning_done) { 373e51df6ceSBen Chuang pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", 374e51df6ceSBen Chuang mmc_hostname(host->mmc)); 375e51df6ceSBen Chuang return -ETIMEDOUT; 376e51df6ceSBen Chuang } 377e51df6ceSBen Chuang 378e51df6ceSBen Chuang pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 379e51df6ceSBen Chuang mmc_hostname(host->mmc)); 380e51df6ceSBen Chuang sdhci_reset_tuning(host); 381e51df6ceSBen Chuang 382e51df6ceSBen Chuang return -EAGAIN; 383e51df6ceSBen Chuang } 384e51df6ceSBen Chuang 385e51df6ceSBen Chuang static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode) 386e51df6ceSBen Chuang { 387e51df6ceSBen Chuang host->mmc->retune_period = 0; 388e51df6ceSBen Chuang if (host->tuning_mode == SDHCI_TUNING_MODE_1) 389e51df6ceSBen Chuang host->mmc->retune_period = host->tuning_count; 390e51df6ceSBen Chuang 391e51df6ceSBen Chuang gli_set_9750(host); 392e51df6ceSBen Chuang host->tuning_err = __sdhci_execute_tuning_9750(host, opcode); 393e51df6ceSBen Chuang sdhci_end_tuning(host); 394e51df6ceSBen Chuang 395e51df6ceSBen Chuang return 0; 396e51df6ceSBen Chuang } 397e51df6ceSBen Chuang 398786d33c8SBen Chuang static void gl9750_disable_ssc_pll(struct sdhci_host *host) 399786d33c8SBen Chuang { 400786d33c8SBen Chuang u32 pll; 401786d33c8SBen Chuang 402786d33c8SBen Chuang gl9750_wt_on(host); 403786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 404786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN); 405786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 406786d33c8SBen Chuang gl9750_wt_off(host); 407786d33c8SBen Chuang } 408786d33c8SBen Chuang 409786d33c8SBen Chuang static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv) 410786d33c8SBen Chuang { 411786d33c8SBen Chuang u32 pll; 412786d33c8SBen Chuang 413786d33c8SBen Chuang gl9750_wt_on(host); 414786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 415786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLL_LDIV | 416786d33c8SBen Chuang SDHCI_GLI_9750_PLL_PDIV | 417786d33c8SBen Chuang SDHCI_GLI_9750_PLL_DIR); 418786d33c8SBen Chuang pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) | 419786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) | 420786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir); 421786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 422786d33c8SBen Chuang gl9750_wt_off(host); 423786d33c8SBen Chuang 424786d33c8SBen Chuang /* wait for pll stable */ 425786d33c8SBen Chuang mdelay(1); 426786d33c8SBen Chuang } 427786d33c8SBen Chuang 42808df1a50SBen Chuang static bool gl9750_ssc_enable(struct sdhci_host *host) 42908df1a50SBen Chuang { 43008df1a50SBen Chuang u32 misc; 43108df1a50SBen Chuang u8 off; 43208df1a50SBen Chuang 43308df1a50SBen Chuang gl9750_wt_on(host); 43408df1a50SBen Chuang misc = sdhci_readl(host, SDHCI_GLI_9750_MISC); 43508df1a50SBen Chuang off = FIELD_GET(SDHCI_GLI_9750_MISC_SSC_OFF, misc); 43608df1a50SBen Chuang gl9750_wt_off(host); 43708df1a50SBen Chuang 43808df1a50SBen Chuang return !off; 43908df1a50SBen Chuang } 44008df1a50SBen Chuang 441786d33c8SBen Chuang static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm) 442786d33c8SBen Chuang { 443786d33c8SBen Chuang u32 pll; 444786d33c8SBen Chuang u32 ssc; 445786d33c8SBen Chuang 446786d33c8SBen Chuang gl9750_wt_on(host); 447786d33c8SBen Chuang pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 448786d33c8SBen Chuang ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC); 449786d33c8SBen Chuang pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP | 450786d33c8SBen Chuang SDHCI_GLI_9750_PLLSSC_EN); 451786d33c8SBen Chuang ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM; 452786d33c8SBen Chuang pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) | 453786d33c8SBen Chuang FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable); 454786d33c8SBen Chuang ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm); 455786d33c8SBen Chuang sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC); 456786d33c8SBen Chuang sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 457786d33c8SBen Chuang gl9750_wt_off(host); 458786d33c8SBen Chuang } 459786d33c8SBen Chuang 460786d33c8SBen Chuang static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host) 461786d33c8SBen Chuang { 46208df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 46308df1a50SBen Chuang 46408df1a50SBen Chuang /* set pll to 205MHz and ssc */ 46508df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xF, 0x5A1D); 466786d33c8SBen Chuang gl9750_set_pll(host, 0x1, 0x246, 0x0); 467786d33c8SBen Chuang } 468786d33c8SBen Chuang 469d3c6bdb6SBen Chuang static void gl9750_set_ssc_pll_100mhz(struct sdhci_host *host) 470d3c6bdb6SBen Chuang { 47108df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 47208df1a50SBen Chuang 47308df1a50SBen Chuang /* set pll to 100MHz and ssc */ 47408df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xE, 0x51EC); 475d3c6bdb6SBen Chuang gl9750_set_pll(host, 0x1, 0x244, 0x1); 476d3c6bdb6SBen Chuang } 477d3c6bdb6SBen Chuang 478d3c6bdb6SBen Chuang static void gl9750_set_ssc_pll_50mhz(struct sdhci_host *host) 479d3c6bdb6SBen Chuang { 48008df1a50SBen Chuang bool enable = gl9750_ssc_enable(host); 48108df1a50SBen Chuang 48208df1a50SBen Chuang /* set pll to 50MHz and ssc */ 48308df1a50SBen Chuang gl9750_set_ssc(host, enable, 0xE, 0x51EC); 484d3c6bdb6SBen Chuang gl9750_set_pll(host, 0x1, 0x244, 0x3); 485d3c6bdb6SBen Chuang } 486d3c6bdb6SBen Chuang 487786d33c8SBen Chuang static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock) 488786d33c8SBen Chuang { 489786d33c8SBen Chuang struct mmc_ios *ios = &host->mmc->ios; 490786d33c8SBen Chuang u16 clk; 491786d33c8SBen Chuang 492786d33c8SBen Chuang host->mmc->actual_clock = 0; 493786d33c8SBen Chuang 494786d33c8SBen Chuang gl9750_disable_ssc_pll(host); 495786d33c8SBen Chuang sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 496786d33c8SBen Chuang 497786d33c8SBen Chuang if (clock == 0) 498786d33c8SBen Chuang return; 499786d33c8SBen Chuang 500786d33c8SBen Chuang clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 501786d33c8SBen Chuang if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 502786d33c8SBen Chuang host->mmc->actual_clock = 205000000; 503786d33c8SBen Chuang gl9750_set_ssc_pll_205mhz(host); 504d3c6bdb6SBen Chuang } else if (clock == 100000000) { 505d3c6bdb6SBen Chuang gl9750_set_ssc_pll_100mhz(host); 506d3c6bdb6SBen Chuang } else if (clock == 50000000) { 507d3c6bdb6SBen Chuang gl9750_set_ssc_pll_50mhz(host); 508786d33c8SBen Chuang } 509786d33c8SBen Chuang 510786d33c8SBen Chuang sdhci_enable_clk(host, clk); 511786d33c8SBen Chuang } 512786d33c8SBen Chuang 5139751baccSBen Chuang static void gl9750_hw_setting(struct sdhci_host *host) 5149751baccSBen Chuang { 5159751baccSBen Chuang u32 value; 5169751baccSBen Chuang 5179751baccSBen Chuang gl9750_wt_on(host); 5189751baccSBen Chuang 5199751baccSBen Chuang value = sdhci_readl(host, SDHCI_GLI_9750_CFG2); 5209751baccSBen Chuang value &= ~SDHCI_GLI_9750_CFG2_L1DLY; 5219751baccSBen Chuang /* set ASPM L1 entry delay to 7.9us */ 5229751baccSBen Chuang value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY, 5239751baccSBen Chuang GLI_9750_CFG2_L1DLY_VALUE); 5249751baccSBen Chuang sdhci_writel(host, value, SDHCI_GLI_9750_CFG2); 5259751baccSBen Chuang 5269751baccSBen Chuang gl9750_wt_off(host); 5279751baccSBen Chuang } 5289751baccSBen Chuang 52931e43f31SBen Chuang static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) 53031e43f31SBen Chuang { 53131e43f31SBen Chuang int ret; 53231e43f31SBen Chuang 53331e43f31SBen Chuang ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1, 53431e43f31SBen Chuang PCI_IRQ_MSI | PCI_IRQ_MSIX); 53531e43f31SBen Chuang if (ret < 0) { 53631e43f31SBen Chuang pr_warn("%s: enable PCI MSI failed, error=%d\n", 53731e43f31SBen Chuang mmc_hostname(slot->host->mmc), ret); 53831e43f31SBen Chuang return; 53931e43f31SBen Chuang } 54031e43f31SBen Chuang 54131e43f31SBen Chuang slot->host->irq = pci_irq_vector(slot->chip->pdev, 0); 54231e43f31SBen Chuang } 54331e43f31SBen Chuang 544786d33c8SBen Chuang static inline void gl9755_wt_on(struct pci_dev *pdev) 545786d33c8SBen Chuang { 546786d33c8SBen Chuang u32 wt_value; 547786d33c8SBen Chuang u32 wt_enable; 548786d33c8SBen Chuang 549786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 550786d33c8SBen Chuang wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 551786d33c8SBen Chuang 552786d33c8SBen Chuang if (wt_enable == GLI_9755_WT_EN_ON) 553786d33c8SBen Chuang return; 554786d33c8SBen Chuang 555786d33c8SBen Chuang wt_value &= ~PCI_GLI_9755_WT_EN; 556786d33c8SBen Chuang wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON); 557786d33c8SBen Chuang 558786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 559786d33c8SBen Chuang } 560786d33c8SBen Chuang 561786d33c8SBen Chuang static inline void gl9755_wt_off(struct pci_dev *pdev) 562786d33c8SBen Chuang { 563786d33c8SBen Chuang u32 wt_value; 564786d33c8SBen Chuang u32 wt_enable; 565786d33c8SBen Chuang 566786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 567786d33c8SBen Chuang wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 568786d33c8SBen Chuang 569786d33c8SBen Chuang if (wt_enable == GLI_9755_WT_EN_OFF) 570786d33c8SBen Chuang return; 571786d33c8SBen Chuang 572786d33c8SBen Chuang wt_value &= ~PCI_GLI_9755_WT_EN; 573786d33c8SBen Chuang wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF); 574786d33c8SBen Chuang 575786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 576786d33c8SBen Chuang } 577786d33c8SBen Chuang 578786d33c8SBen Chuang static void gl9755_disable_ssc_pll(struct pci_dev *pdev) 579786d33c8SBen Chuang { 580786d33c8SBen Chuang u32 pll; 581786d33c8SBen Chuang 582786d33c8SBen Chuang gl9755_wt_on(pdev); 583786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 584786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN); 585786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 586786d33c8SBen Chuang gl9755_wt_off(pdev); 587786d33c8SBen Chuang } 588786d33c8SBen Chuang 589786d33c8SBen Chuang static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 590786d33c8SBen Chuang { 591786d33c8SBen Chuang u32 pll; 592786d33c8SBen Chuang 593786d33c8SBen Chuang gl9755_wt_on(pdev); 594786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 595786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLL_LDIV | 596786d33c8SBen Chuang PCI_GLI_9755_PLL_PDIV | 597786d33c8SBen Chuang PCI_GLI_9755_PLL_DIR); 598786d33c8SBen Chuang pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) | 599786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) | 600786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir); 601786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 602786d33c8SBen Chuang gl9755_wt_off(pdev); 603786d33c8SBen Chuang 604786d33c8SBen Chuang /* wait for pll stable */ 605786d33c8SBen Chuang mdelay(1); 606786d33c8SBen Chuang } 607786d33c8SBen Chuang 60808df1a50SBen Chuang static bool gl9755_ssc_enable(struct pci_dev *pdev) 60908df1a50SBen Chuang { 61008df1a50SBen Chuang u32 misc; 61108df1a50SBen Chuang u8 off; 61208df1a50SBen Chuang 61308df1a50SBen Chuang gl9755_wt_on(pdev); 61408df1a50SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_MISC, &misc); 61508df1a50SBen Chuang off = FIELD_GET(PCI_GLI_9755_MISC_SSC_OFF, misc); 61608df1a50SBen Chuang gl9755_wt_off(pdev); 61708df1a50SBen Chuang 61808df1a50SBen Chuang return !off; 61908df1a50SBen Chuang } 62008df1a50SBen Chuang 621786d33c8SBen Chuang static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 622786d33c8SBen Chuang { 623786d33c8SBen Chuang u32 pll; 624786d33c8SBen Chuang u32 ssc; 625786d33c8SBen Chuang 626786d33c8SBen Chuang gl9755_wt_on(pdev); 627786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 628786d33c8SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc); 629786d33c8SBen Chuang pll &= ~(PCI_GLI_9755_PLLSSC_STEP | 630786d33c8SBen Chuang PCI_GLI_9755_PLLSSC_EN); 631786d33c8SBen Chuang ssc &= ~PCI_GLI_9755_PLLSSC_PPM; 632786d33c8SBen Chuang pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) | 633786d33c8SBen Chuang FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable); 634786d33c8SBen Chuang ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm); 635786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc); 636786d33c8SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 637786d33c8SBen Chuang gl9755_wt_off(pdev); 638786d33c8SBen Chuang } 639786d33c8SBen Chuang 640786d33c8SBen Chuang static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev) 641786d33c8SBen Chuang { 64208df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 64308df1a50SBen Chuang 64408df1a50SBen Chuang /* set pll to 205MHz and ssc */ 64508df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xF, 0x5A1D); 646786d33c8SBen Chuang gl9755_set_pll(pdev, 0x1, 0x246, 0x0); 647786d33c8SBen Chuang } 648786d33c8SBen Chuang 649d3c6bdb6SBen Chuang static void gl9755_set_ssc_pll_100mhz(struct pci_dev *pdev) 650d3c6bdb6SBen Chuang { 65108df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 65208df1a50SBen Chuang 65308df1a50SBen Chuang /* set pll to 100MHz and ssc */ 65408df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 655d3c6bdb6SBen Chuang gl9755_set_pll(pdev, 0x1, 0x244, 0x1); 656d3c6bdb6SBen Chuang } 657d3c6bdb6SBen Chuang 658d3c6bdb6SBen Chuang static void gl9755_set_ssc_pll_50mhz(struct pci_dev *pdev) 659d3c6bdb6SBen Chuang { 66008df1a50SBen Chuang bool enable = gl9755_ssc_enable(pdev); 66108df1a50SBen Chuang 66208df1a50SBen Chuang /* set pll to 50MHz and ssc */ 66308df1a50SBen Chuang gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 664d3c6bdb6SBen Chuang gl9755_set_pll(pdev, 0x1, 0x244, 0x3); 665d3c6bdb6SBen Chuang } 666d3c6bdb6SBen Chuang 667786d33c8SBen Chuang static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock) 668786d33c8SBen Chuang { 669786d33c8SBen Chuang struct sdhci_pci_slot *slot = sdhci_priv(host); 670786d33c8SBen Chuang struct mmc_ios *ios = &host->mmc->ios; 671786d33c8SBen Chuang struct pci_dev *pdev; 672786d33c8SBen Chuang u16 clk; 673786d33c8SBen Chuang 674786d33c8SBen Chuang pdev = slot->chip->pdev; 675786d33c8SBen Chuang host->mmc->actual_clock = 0; 676786d33c8SBen Chuang 677786d33c8SBen Chuang gl9755_disable_ssc_pll(pdev); 678786d33c8SBen Chuang sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 679786d33c8SBen Chuang 680786d33c8SBen Chuang if (clock == 0) 681786d33c8SBen Chuang return; 682786d33c8SBen Chuang 683786d33c8SBen Chuang clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 684786d33c8SBen Chuang if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 685786d33c8SBen Chuang host->mmc->actual_clock = 205000000; 686786d33c8SBen Chuang gl9755_set_ssc_pll_205mhz(pdev); 687d3c6bdb6SBen Chuang } else if (clock == 100000000) { 688d3c6bdb6SBen Chuang gl9755_set_ssc_pll_100mhz(pdev); 689d3c6bdb6SBen Chuang } else if (clock == 50000000) { 690d3c6bdb6SBen Chuang gl9755_set_ssc_pll_50mhz(pdev); 691786d33c8SBen Chuang } 692786d33c8SBen Chuang 693786d33c8SBen Chuang sdhci_enable_clk(host, clk); 694786d33c8SBen Chuang } 695786d33c8SBen Chuang 6960f1d9961SBen Chuang static void gl9755_hw_setting(struct sdhci_pci_slot *slot) 6970f1d9961SBen Chuang { 6980f1d9961SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 6990f1d9961SBen Chuang u32 value; 7000f1d9961SBen Chuang 7010f1d9961SBen Chuang gl9755_wt_on(pdev); 7020f1d9961SBen Chuang 7030f1d9961SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value); 704189f1d9bSHector Martin /* 705189f1d9bSHector Martin * Apple ARM64 platforms using these chips may have 706189f1d9bSHector Martin * inverted CD/WP detection. 707189f1d9bSHector Martin */ 708189f1d9bSHector Martin if (of_property_read_bool(pdev->dev.of_node, "cd-inverted")) 709189f1d9bSHector Martin value |= PCI_GLI_9755_INVERT_CD; 710189f1d9bSHector Martin if (of_property_read_bool(pdev->dev.of_node, "wp-inverted")) 711189f1d9bSHector Martin value |= PCI_GLI_9755_INVERT_WP; 7120f1d9961SBen Chuang value &= ~PCI_GLI_9755_LFCLK; 7130f1d9961SBen Chuang value &= ~PCI_GLI_9755_DMACLK; 7140f1d9961SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); 7150f1d9961SBen Chuang 716f46b54ccSRenius Chen /* enable short circuit protection */ 717f46b54ccSRenius Chen pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &value); 718f46b54ccSRenius Chen value &= ~PCI_GLI_9755_SCP_DIS; 719f46b54ccSRenius Chen pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value); 720f46b54ccSRenius Chen 7219751baccSBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, &value); 7229751baccSBen Chuang value &= ~PCI_GLI_9755_CFG2_L1DLY; 7239751baccSBen Chuang /* set ASPM L1 entry delay to 7.9us */ 7249751baccSBen Chuang value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY, 7259751baccSBen Chuang GLI_9755_CFG2_L1DLY_VALUE); 7269751baccSBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); 7279751baccSBen Chuang 72836ed2fd3SBen Chuang /* toggle PM state to allow GL9755 to enter ASPM L1.2 */ 72936ed2fd3SBen Chuang pci_read_config_dword(pdev, PCI_GLI_9755_PM_CTRL, &value); 73036ed2fd3SBen Chuang value |= PCI_GLI_9755_PM_STATE; 73136ed2fd3SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 73236ed2fd3SBen Chuang value &= ~PCI_GLI_9755_PM_STATE; 73336ed2fd3SBen Chuang pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 73436ed2fd3SBen Chuang 7350f1d9961SBen Chuang gl9755_wt_off(pdev); 7360f1d9961SBen Chuang } 7370f1d9961SBen Chuang 738f3a5b56cSVictor Shih static inline void gl9767_vhs_read(struct pci_dev *pdev) 739f3a5b56cSVictor Shih { 740f3a5b56cSVictor Shih u32 vhs_enable; 741f3a5b56cSVictor Shih u32 vhs_value; 742f3a5b56cSVictor Shih 743f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 744f3a5b56cSVictor Shih vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 745f3a5b56cSVictor Shih 746f3a5b56cSVictor Shih if (vhs_enable == GLI_9767_VHS_REV_R) 747f3a5b56cSVictor Shih return; 748f3a5b56cSVictor Shih 749f3a5b56cSVictor Shih vhs_value &= ~GLI_9767_VHS_REV; 750f3a5b56cSVictor Shih vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R); 751f3a5b56cSVictor Shih 752f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 753f3a5b56cSVictor Shih } 754f3a5b56cSVictor Shih 755f3a5b56cSVictor Shih static inline void gl9767_vhs_write(struct pci_dev *pdev) 756f3a5b56cSVictor Shih { 757f3a5b56cSVictor Shih u32 vhs_enable; 758f3a5b56cSVictor Shih u32 vhs_value; 759f3a5b56cSVictor Shih 760f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 761f3a5b56cSVictor Shih vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 762f3a5b56cSVictor Shih 763f3a5b56cSVictor Shih if (vhs_enable == GLI_9767_VHS_REV_W) 764f3a5b56cSVictor Shih return; 765f3a5b56cSVictor Shih 766f3a5b56cSVictor Shih vhs_value &= ~GLI_9767_VHS_REV; 767f3a5b56cSVictor Shih vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W); 768f3a5b56cSVictor Shih 769f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 770f3a5b56cSVictor Shih } 771f3a5b56cSVictor Shih 772*d2754355SVictor Shih static bool gl9767_ssc_enable(struct pci_dev *pdev) 773*d2754355SVictor Shih { 774*d2754355SVictor Shih u32 value; 775*d2754355SVictor Shih u8 enable; 776*d2754355SVictor Shih 777*d2754355SVictor Shih gl9767_vhs_write(pdev); 778*d2754355SVictor Shih 779*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_COM_MAILBOX, &value); 780*d2754355SVictor Shih enable = FIELD_GET(PCIE_GLI_9767_COM_MAILBOX_SSC_EN, value); 781*d2754355SVictor Shih 782*d2754355SVictor Shih gl9767_vhs_read(pdev); 783*d2754355SVictor Shih 784*d2754355SVictor Shih return enable; 785*d2754355SVictor Shih } 786*d2754355SVictor Shih 787*d2754355SVictor Shih static void gl9767_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 788*d2754355SVictor Shih { 789*d2754355SVictor Shih u32 pll; 790*d2754355SVictor Shih u32 ssc; 791*d2754355SVictor Shih 792*d2754355SVictor Shih gl9767_vhs_write(pdev); 793*d2754355SVictor Shih 794*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 795*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, &ssc); 796*d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING | 797*d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 798*d2754355SVictor Shih ssc &= ~PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM; 799*d2754355SVictor Shih pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING, step) | 800*d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_EN, enable); 801*d2754355SVictor Shih ssc |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM, ppm); 802*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, ssc); 803*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 804*d2754355SVictor Shih 805*d2754355SVictor Shih gl9767_vhs_read(pdev); 806*d2754355SVictor Shih } 807*d2754355SVictor Shih 808*d2754355SVictor Shih static void gl9767_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 809*d2754355SVictor Shih { 810*d2754355SVictor Shih u32 pll; 811*d2754355SVictor Shih 812*d2754355SVictor Shih gl9767_vhs_write(pdev); 813*d2754355SVictor Shih 814*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 815*d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV | 816*d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV | 817*d2754355SVictor Shih PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN); 818*d2754355SVictor Shih pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV, ldiv) | 819*d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV, pdiv) | 820*d2754355SVictor Shih FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN, dir); 821*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 822*d2754355SVictor Shih 823*d2754355SVictor Shih gl9767_vhs_read(pdev); 824*d2754355SVictor Shih 825*d2754355SVictor Shih /* wait for pll stable */ 826*d2754355SVictor Shih usleep_range(1000, 1100); 827*d2754355SVictor Shih } 828*d2754355SVictor Shih 829*d2754355SVictor Shih static void gl9767_set_ssc_pll_205mhz(struct pci_dev *pdev) 830*d2754355SVictor Shih { 831*d2754355SVictor Shih bool enable = gl9767_ssc_enable(pdev); 832*d2754355SVictor Shih 833*d2754355SVictor Shih /* set pll to 205MHz and ssc */ 834*d2754355SVictor Shih gl9767_set_ssc(pdev, enable, 0x1F, 0xF5C3); 835*d2754355SVictor Shih gl9767_set_pll(pdev, 0x1, 0x246, 0x0); 836*d2754355SVictor Shih } 837*d2754355SVictor Shih 838*d2754355SVictor Shih static void gl9767_disable_ssc_pll(struct pci_dev *pdev) 839*d2754355SVictor Shih { 840*d2754355SVictor Shih u32 pll; 841*d2754355SVictor Shih 842*d2754355SVictor Shih gl9767_vhs_write(pdev); 843*d2754355SVictor Shih 844*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 845*d2754355SVictor Shih pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN | PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 846*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 847*d2754355SVictor Shih 848*d2754355SVictor Shih gl9767_vhs_read(pdev); 849*d2754355SVictor Shih } 850*d2754355SVictor Shih 851*d2754355SVictor Shih static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock) 852*d2754355SVictor Shih { 853*d2754355SVictor Shih struct sdhci_pci_slot *slot = sdhci_priv(host); 854*d2754355SVictor Shih struct mmc_ios *ios = &host->mmc->ios; 855*d2754355SVictor Shih struct pci_dev *pdev; 856*d2754355SVictor Shih u32 value; 857*d2754355SVictor Shih u16 clk; 858*d2754355SVictor Shih 859*d2754355SVictor Shih pdev = slot->chip->pdev; 860*d2754355SVictor Shih host->mmc->actual_clock = 0; 861*d2754355SVictor Shih 862*d2754355SVictor Shih gl9767_vhs_write(pdev); 863*d2754355SVictor Shih 864*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 865*d2754355SVictor Shih value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; 866*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 867*d2754355SVictor Shih 868*d2754355SVictor Shih gl9767_disable_ssc_pll(pdev); 869*d2754355SVictor Shih sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 870*d2754355SVictor Shih 871*d2754355SVictor Shih if (clock == 0) 872*d2754355SVictor Shih return; 873*d2754355SVictor Shih 874*d2754355SVictor Shih clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 875*d2754355SVictor Shih if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 876*d2754355SVictor Shih host->mmc->actual_clock = 205000000; 877*d2754355SVictor Shih gl9767_set_ssc_pll_205mhz(pdev); 878*d2754355SVictor Shih } 879*d2754355SVictor Shih 880*d2754355SVictor Shih sdhci_enable_clk(host, clk); 881*d2754355SVictor Shih 882*d2754355SVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 883*d2754355SVictor Shih value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF; 884*d2754355SVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 885*d2754355SVictor Shih 886*d2754355SVictor Shih gl9767_vhs_read(pdev); 887*d2754355SVictor Shih } 888*d2754355SVictor Shih 889f3a5b56cSVictor Shih static void gli_set_9767(struct sdhci_host *host) 890f3a5b56cSVictor Shih { 891f3a5b56cSVictor Shih u32 value; 892f3a5b56cSVictor Shih 893f3a5b56cSVictor Shih value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE); 894f3a5b56cSVictor Shih value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET; 895f3a5b56cSVictor Shih sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE); 896f3a5b56cSVictor Shih } 897f3a5b56cSVictor Shih 898f3a5b56cSVictor Shih static void gl9767_hw_setting(struct sdhci_pci_slot *slot) 899f3a5b56cSVictor Shih { 900f3a5b56cSVictor Shih struct pci_dev *pdev = slot->chip->pdev; 901f3a5b56cSVictor Shih u32 value; 902f3a5b56cSVictor Shih 903f3a5b56cSVictor Shih gl9767_vhs_write(pdev); 904f3a5b56cSVictor Shih 905f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value); 906f3a5b56cSVictor Shih value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 907f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE | 908f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL); 909f3a5b56cSVictor Shih 910f3a5b56cSVictor Shih value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 911f3a5b56cSVictor Shih FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE, 912f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) | 913f3a5b56cSVictor Shih FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL, 914f3a5b56cSVictor Shih PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE); 915f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value); 916f3a5b56cSVictor Shih 917f3a5b56cSVictor Shih pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value); 918f3a5b56cSVictor Shih value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 | 919f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 | 920f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN); 921f3a5b56cSVictor Shih 922f3a5b56cSVictor Shih value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST | 923f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST | 924f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_AXI_REQ | 925f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN | 926f3a5b56cSVictor Shih PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF; 927f3a5b56cSVictor Shih pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value); 928f3a5b56cSVictor Shih 929f3a5b56cSVictor Shih gl9767_vhs_read(pdev); 930f3a5b56cSVictor Shih } 931f3a5b56cSVictor Shih 932f3a5b56cSVictor Shih static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask) 933f3a5b56cSVictor Shih { 934f3a5b56cSVictor Shih sdhci_reset(host, mask); 935f3a5b56cSVictor Shih gli_set_9767(host); 936f3a5b56cSVictor Shih } 937f3a5b56cSVictor Shih 938e51df6ceSBen Chuang static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) 939e51df6ceSBen Chuang { 940e51df6ceSBen Chuang struct sdhci_host *host = slot->host; 941e51df6ceSBen Chuang 9429751baccSBen Chuang gl9750_hw_setting(host); 94331e43f31SBen Chuang gli_pcie_enable_msi(slot); 944e51df6ceSBen Chuang slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 945e51df6ceSBen Chuang sdhci_enable_v4_mode(host); 946e51df6ceSBen Chuang 947e51df6ceSBen Chuang return 0; 948e51df6ceSBen Chuang } 949e51df6ceSBen Chuang 950e51df6ceSBen Chuang static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) 951e51df6ceSBen Chuang { 952e51df6ceSBen Chuang struct sdhci_host *host = slot->host; 953e51df6ceSBen Chuang 9540f1d9961SBen Chuang gl9755_hw_setting(slot); 95531e43f31SBen Chuang gli_pcie_enable_msi(slot); 956e51df6ceSBen Chuang slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 957e51df6ceSBen Chuang sdhci_enable_v4_mode(host); 958e51df6ceSBen Chuang 959e51df6ceSBen Chuang return 0; 960e51df6ceSBen Chuang } 961e51df6ceSBen Chuang 962f3a5b56cSVictor Shih static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot) 963f3a5b56cSVictor Shih { 964f3a5b56cSVictor Shih struct sdhci_host *host = slot->host; 965f3a5b56cSVictor Shih 966f3a5b56cSVictor Shih gli_set_9767(host); 967f3a5b56cSVictor Shih gl9767_hw_setting(slot); 968f3a5b56cSVictor Shih gli_pcie_enable_msi(slot); 969f3a5b56cSVictor Shih slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 970f3a5b56cSVictor Shih sdhci_enable_v4_mode(host); 971f3a5b56cSVictor Shih 972f3a5b56cSVictor Shih return 0; 973f3a5b56cSVictor Shih } 974f3a5b56cSVictor Shih 975e51df6ceSBen Chuang static void sdhci_gli_voltage_switch(struct sdhci_host *host) 976e51df6ceSBen Chuang { 977e51df6ceSBen Chuang /* 978e51df6ceSBen Chuang * According to Section 3.6.1 signal voltage switch procedure in 979e51df6ceSBen Chuang * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 980e51df6ceSBen Chuang * follows: 981e51df6ceSBen Chuang * (6) Set 1.8V Signal Enable in the Host Control 2 register. 982e51df6ceSBen Chuang * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 983e51df6ceSBen Chuang * period. 984e51df6ceSBen Chuang * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 985e51df6ceSBen Chuang * step (12). 986e51df6ceSBen Chuang * 987e51df6ceSBen Chuang * Wait 5ms after set 1.8V signal enable in Host Control 2 register 988e51df6ceSBen Chuang * to ensure 1.8V signal enable bit is set by GL9750/GL9755. 989a1149a6cSDaniel Beer * 990a1149a6cSDaniel Beer * ...however, the controller in the NUC10i3FNK4 (a 9755) requires 991a1149a6cSDaniel Beer * slightly longer than 5ms before the control register reports that 992a1149a6cSDaniel Beer * 1.8V is ready, and far longer still before the card will actually 993a1149a6cSDaniel Beer * work reliably. 994e51df6ceSBen Chuang */ 995a1149a6cSDaniel Beer usleep_range(100000, 110000); 996e51df6ceSBen Chuang } 997e51df6ceSBen Chuang 998f3a5b56cSVictor Shih static void sdhci_gl9767_voltage_switch(struct sdhci_host *host) 999f3a5b56cSVictor Shih { 1000f3a5b56cSVictor Shih /* 1001f3a5b56cSVictor Shih * According to Section 3.6.1 signal voltage switch procedure in 1002f3a5b56cSVictor Shih * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 1003f3a5b56cSVictor Shih * follows: 1004f3a5b56cSVictor Shih * (6) Set 1.8V Signal Enable in the Host Control 2 register. 1005f3a5b56cSVictor Shih * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 1006f3a5b56cSVictor Shih * period. 1007f3a5b56cSVictor Shih * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 1008f3a5b56cSVictor Shih * step (12). 1009f3a5b56cSVictor Shih * 1010f3a5b56cSVictor Shih * Wait 5ms after set 1.8V signal enable in Host Control 2 register 1011f3a5b56cSVictor Shih * to ensure 1.8V signal enable bit is set by GL9767. 1012f3a5b56cSVictor Shih * 1013f3a5b56cSVictor Shih */ 1014f3a5b56cSVictor Shih usleep_range(5000, 5500); 1015f3a5b56cSVictor Shih } 1016f3a5b56cSVictor Shih 1017e51df6ceSBen Chuang static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask) 1018e51df6ceSBen Chuang { 1019e51df6ceSBen Chuang sdhci_reset(host, mask); 1020e51df6ceSBen Chuang gli_set_9750(host); 1021e51df6ceSBen Chuang } 1022e51df6ceSBen Chuang 1023e51df6ceSBen Chuang static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg) 1024e51df6ceSBen Chuang { 1025e51df6ceSBen Chuang u32 value; 1026e51df6ceSBen Chuang 1027e51df6ceSBen Chuang value = readl(host->ioaddr + reg); 1028e51df6ceSBen Chuang if (unlikely(reg == SDHCI_MAX_CURRENT && !(value & 0xff))) 1029e51df6ceSBen Chuang value |= 0xc8; 1030e51df6ceSBen Chuang 1031e51df6ceSBen Chuang return value; 1032e51df6ceSBen Chuang } 1033e51df6ceSBen Chuang 1034282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1035282ede76SBen Chuang static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) 1036282ede76SBen Chuang { 1037282ede76SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1038282ede76SBen Chuang 1039282ede76SBen Chuang pci_free_irq_vectors(slot->chip->pdev); 1040282ede76SBen Chuang gli_pcie_enable_msi(slot); 1041282ede76SBen Chuang 1042282ede76SBen Chuang return sdhci_pci_resume_host(chip); 1043282ede76SBen Chuang } 1044347f6be1SBen Chuang 1045347f6be1SBen Chuang static int sdhci_cqhci_gli_resume(struct sdhci_pci_chip *chip) 1046347f6be1SBen Chuang { 1047347f6be1SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1048347f6be1SBen Chuang int ret; 1049347f6be1SBen Chuang 1050347f6be1SBen Chuang ret = sdhci_pci_gli_resume(chip); 1051347f6be1SBen Chuang if (ret) 1052347f6be1SBen Chuang return ret; 1053347f6be1SBen Chuang 1054347f6be1SBen Chuang return cqhci_resume(slot->host->mmc); 1055347f6be1SBen Chuang } 1056347f6be1SBen Chuang 1057347f6be1SBen Chuang static int sdhci_cqhci_gli_suspend(struct sdhci_pci_chip *chip) 1058347f6be1SBen Chuang { 1059347f6be1SBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1060347f6be1SBen Chuang int ret; 1061347f6be1SBen Chuang 1062347f6be1SBen Chuang ret = cqhci_suspend(slot->host->mmc); 1063347f6be1SBen Chuang if (ret) 1064347f6be1SBen Chuang return ret; 1065347f6be1SBen Chuang 1066347f6be1SBen Chuang return sdhci_suspend_host(slot->host); 1067347f6be1SBen Chuang } 1068282ede76SBen Chuang #endif 1069282ede76SBen Chuang 10701ae1d2d6SBen Chuang static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, 10711ae1d2d6SBen Chuang struct mmc_ios *ios) 10721ae1d2d6SBen Chuang { 10731ae1d2d6SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 10741ae1d2d6SBen Chuang u32 val; 10751ae1d2d6SBen Chuang 10761ae1d2d6SBen Chuang val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG); 10771ae1d2d6SBen Chuang if (ios->enhanced_strobe) 10781ae1d2d6SBen Chuang val |= SDHCI_GLI_9763E_HS400_ES_BIT; 10791ae1d2d6SBen Chuang else 10801ae1d2d6SBen Chuang val &= ~SDHCI_GLI_9763E_HS400_ES_BIT; 10811ae1d2d6SBen Chuang 10821ae1d2d6SBen Chuang sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); 10831ae1d2d6SBen Chuang } 10841ae1d2d6SBen Chuang 10851ae1d2d6SBen Chuang static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, 10861ae1d2d6SBen Chuang unsigned int timing) 10871ae1d2d6SBen Chuang { 10881ae1d2d6SBen Chuang u16 ctrl_2; 10891ae1d2d6SBen Chuang 10901ae1d2d6SBen Chuang ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 10911ae1d2d6SBen Chuang ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 10921ae1d2d6SBen Chuang if (timing == MMC_TIMING_MMC_HS200) 10931ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 10941ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_HS) 10951ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 10961ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_DDR52) 10971ae1d2d6SBen Chuang ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 10981ae1d2d6SBen Chuang else if (timing == MMC_TIMING_MMC_HS400) 10991ae1d2d6SBen Chuang ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400; 11001ae1d2d6SBen Chuang 11011ae1d2d6SBen Chuang sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 11021ae1d2d6SBen Chuang } 11031ae1d2d6SBen Chuang 1104347f6be1SBen Chuang static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) 1105347f6be1SBen Chuang { 1106347f6be1SBen Chuang sdhci_dumpregs(mmc_priv(mmc)); 1107347f6be1SBen Chuang } 1108347f6be1SBen Chuang 1109347f6be1SBen Chuang static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) 1110347f6be1SBen Chuang { 1111347f6be1SBen Chuang struct cqhci_host *cq_host = mmc->cqe_private; 1112347f6be1SBen Chuang u32 value; 1113347f6be1SBen Chuang 1114347f6be1SBen Chuang value = cqhci_readl(cq_host, CQHCI_CFG); 1115347f6be1SBen Chuang value |= CQHCI_ENABLE; 1116347f6be1SBen Chuang cqhci_writel(cq_host, value, CQHCI_CFG); 1117347f6be1SBen Chuang } 1118347f6be1SBen Chuang 1119347f6be1SBen Chuang static void sdhci_gl9763e_cqe_enable(struct mmc_host *mmc) 1120347f6be1SBen Chuang { 1121347f6be1SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 1122347f6be1SBen Chuang 1123347f6be1SBen Chuang sdhci_writew(host, GLI_9763E_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); 1124347f6be1SBen Chuang sdhci_cqe_enable(mmc); 1125347f6be1SBen Chuang } 1126347f6be1SBen Chuang 1127347f6be1SBen Chuang static u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask) 1128347f6be1SBen Chuang { 1129347f6be1SBen Chuang int cmd_error = 0; 1130347f6be1SBen Chuang int data_error = 0; 1131347f6be1SBen Chuang 1132347f6be1SBen Chuang if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) 1133347f6be1SBen Chuang return intmask; 1134347f6be1SBen Chuang 1135347f6be1SBen Chuang cqhci_irq(host->mmc, intmask, cmd_error, data_error); 1136347f6be1SBen Chuang 1137347f6be1SBen Chuang return 0; 1138347f6be1SBen Chuang } 1139347f6be1SBen Chuang 1140347f6be1SBen Chuang static void sdhci_gl9763e_cqe_post_disable(struct mmc_host *mmc) 1141347f6be1SBen Chuang { 1142347f6be1SBen Chuang struct sdhci_host *host = mmc_priv(mmc); 1143347f6be1SBen Chuang struct cqhci_host *cq_host = mmc->cqe_private; 1144347f6be1SBen Chuang u32 value; 1145347f6be1SBen Chuang 1146347f6be1SBen Chuang value = cqhci_readl(cq_host, CQHCI_CFG); 1147347f6be1SBen Chuang value &= ~CQHCI_ENABLE; 1148347f6be1SBen Chuang cqhci_writel(cq_host, value, CQHCI_CFG); 1149347f6be1SBen Chuang sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 1150347f6be1SBen Chuang } 1151347f6be1SBen Chuang 1152347f6be1SBen Chuang static const struct cqhci_host_ops sdhci_gl9763e_cqhci_ops = { 1153347f6be1SBen Chuang .enable = sdhci_gl9763e_cqe_enable, 1154347f6be1SBen Chuang .disable = sdhci_cqe_disable, 1155347f6be1SBen Chuang .dumpregs = sdhci_gl9763e_dumpregs, 1156347f6be1SBen Chuang .pre_enable = sdhci_gl9763e_cqe_pre_enable, 1157347f6be1SBen Chuang .post_disable = sdhci_gl9763e_cqe_post_disable, 1158347f6be1SBen Chuang }; 1159347f6be1SBen Chuang 1160347f6be1SBen Chuang static int gl9763e_add_host(struct sdhci_pci_slot *slot) 1161347f6be1SBen Chuang { 1162347f6be1SBen Chuang struct device *dev = &slot->chip->pdev->dev; 1163347f6be1SBen Chuang struct sdhci_host *host = slot->host; 1164347f6be1SBen Chuang struct cqhci_host *cq_host; 1165347f6be1SBen Chuang bool dma64; 1166347f6be1SBen Chuang int ret; 1167347f6be1SBen Chuang 1168347f6be1SBen Chuang ret = sdhci_setup_host(host); 1169347f6be1SBen Chuang if (ret) 1170347f6be1SBen Chuang return ret; 1171347f6be1SBen Chuang 1172347f6be1SBen Chuang cq_host = devm_kzalloc(dev, sizeof(*cq_host), GFP_KERNEL); 1173347f6be1SBen Chuang if (!cq_host) { 1174347f6be1SBen Chuang ret = -ENOMEM; 1175347f6be1SBen Chuang goto cleanup; 1176347f6be1SBen Chuang } 1177347f6be1SBen Chuang 1178347f6be1SBen Chuang cq_host->mmio = host->ioaddr + SDHCI_GLI_9763E_CQE_BASE_ADDR; 1179347f6be1SBen Chuang cq_host->ops = &sdhci_gl9763e_cqhci_ops; 1180347f6be1SBen Chuang 1181347f6be1SBen Chuang dma64 = host->flags & SDHCI_USE_64_BIT_DMA; 1182347f6be1SBen Chuang if (dma64) 1183347f6be1SBen Chuang cq_host->caps |= CQHCI_TASK_DESC_SZ_128; 1184347f6be1SBen Chuang 1185347f6be1SBen Chuang ret = cqhci_init(cq_host, host->mmc, dma64); 1186347f6be1SBen Chuang if (ret) 1187347f6be1SBen Chuang goto cleanup; 1188347f6be1SBen Chuang 1189347f6be1SBen Chuang ret = __sdhci_add_host(host); 1190347f6be1SBen Chuang if (ret) 1191347f6be1SBen Chuang goto cleanup; 1192347f6be1SBen Chuang 1193347f6be1SBen Chuang return 0; 1194347f6be1SBen Chuang 1195347f6be1SBen Chuang cleanup: 1196347f6be1SBen Chuang sdhci_cleanup_host(host); 1197347f6be1SBen Chuang return ret; 1198347f6be1SBen Chuang } 1199347f6be1SBen Chuang 12001ae1d2d6SBen Chuang static void gli_set_gl9763e(struct sdhci_pci_slot *slot) 12011ae1d2d6SBen Chuang { 12021ae1d2d6SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 12031ae1d2d6SBen Chuang u32 value; 12041ae1d2d6SBen Chuang 12051ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 12061ae1d2d6SBen Chuang value &= ~GLI_9763E_VHS_REV; 12071ae1d2d6SBen Chuang value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 12081ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 12091ae1d2d6SBen Chuang 12101ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value); 12111ae1d2d6SBen Chuang value |= GLI_9763E_SCR_AXI_REQ; 12121ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); 12131ae1d2d6SBen Chuang 121498991b18SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, &value); 121598991b18SBen Chuang value &= ~GLI_9763E_HS400_SLOW; 121698991b18SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, value); 121798991b18SBen Chuang 1218edee82f7SRenius Chen pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value); 1219edee82f7SRenius Chen value &= ~GLI_9763E_CFG2_L1DLY; 122034dd3cccSBen Chuang /* set ASPM L1 entry delay to 21us */ 1221baaaf55dSBen Chuang value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); 1222edee82f7SRenius Chen pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); 1223edee82f7SRenius Chen 1224c58c5950SRenius Chen pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); 1225c58c5950SRenius Chen value &= ~GLI_9763E_HS400_RXDLY; 1226c58c5950SRenius Chen value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); 1227c58c5950SRenius Chen pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value); 1228c58c5950SRenius Chen 12291ae1d2d6SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 12301ae1d2d6SBen Chuang value &= ~GLI_9763E_VHS_REV; 12311ae1d2d6SBen Chuang value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 12321ae1d2d6SBen Chuang pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 12331ae1d2d6SBen Chuang } 12341ae1d2d6SBen Chuang 1235d607667bSBen Chuang #ifdef CONFIG_PM 12361c5fd973SRen Zhijie static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) 12371c5fd973SRen Zhijie { 12381c5fd973SRen Zhijie struct pci_dev *pdev = slot->chip->pdev; 12391c5fd973SRen Zhijie u32 value; 12401c5fd973SRen Zhijie 12411c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 12421c5fd973SRen Zhijie value &= ~GLI_9763E_VHS_REV; 12431c5fd973SRen Zhijie value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 12441c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 12451c5fd973SRen Zhijie 12461c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); 12471c5fd973SRen Zhijie 12481c5fd973SRen Zhijie if (enable) 12491c5fd973SRen Zhijie value &= ~GLI_9763E_CFG_LPSN_DIS; 12501c5fd973SRen Zhijie else 12511c5fd973SRen Zhijie value |= GLI_9763E_CFG_LPSN_DIS; 12521c5fd973SRen Zhijie 12531c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); 12541c5fd973SRen Zhijie 12551c5fd973SRen Zhijie pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 12561c5fd973SRen Zhijie value &= ~GLI_9763E_VHS_REV; 12571c5fd973SRen Zhijie value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 12581c5fd973SRen Zhijie pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 12591c5fd973SRen Zhijie } 12601c5fd973SRen Zhijie 1261d607667bSBen Chuang static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) 1262d607667bSBen Chuang { 1263d607667bSBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1264d607667bSBen Chuang struct sdhci_host *host = slot->host; 1265d607667bSBen Chuang u16 clock; 1266d607667bSBen Chuang 1267f9e5b339SJason Lai /* Enable LPM negotiation to allow entering L1 state */ 1268f9e5b339SJason Lai gl9763e_set_low_power_negotiation(slot, true); 1269f9e5b339SJason Lai 1270d607667bSBen Chuang clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1271d607667bSBen Chuang clock &= ~(SDHCI_CLOCK_PLL_EN | SDHCI_CLOCK_CARD_EN); 1272d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1273d607667bSBen Chuang 1274d607667bSBen Chuang return 0; 1275d607667bSBen Chuang } 1276d607667bSBen Chuang 1277d607667bSBen Chuang static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) 1278d607667bSBen Chuang { 1279d607667bSBen Chuang struct sdhci_pci_slot *slot = chip->slots[0]; 1280d607667bSBen Chuang struct sdhci_host *host = slot->host; 1281d607667bSBen Chuang u16 clock; 1282d607667bSBen Chuang 1283291e7d52SBen Chuang if (host->mmc->ios.power_mode != MMC_POWER_ON) 1284291e7d52SBen Chuang return 0; 1285291e7d52SBen Chuang 1286d607667bSBen Chuang clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 1287d607667bSBen Chuang 1288d607667bSBen Chuang clock |= SDHCI_CLOCK_PLL_EN; 1289d607667bSBen Chuang clock &= ~SDHCI_CLOCK_INT_STABLE; 1290d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1291d607667bSBen Chuang 1292d607667bSBen Chuang /* Wait max 150 ms */ 1293d607667bSBen Chuang if (read_poll_timeout(sdhci_readw, clock, (clock & SDHCI_CLOCK_INT_STABLE), 1294d607667bSBen Chuang 1000, 150000, false, host, SDHCI_CLOCK_CONTROL)) { 1295d607667bSBen Chuang pr_err("%s: PLL clock never stabilised.\n", 1296d607667bSBen Chuang mmc_hostname(host->mmc)); 1297d607667bSBen Chuang sdhci_dumpregs(host); 1298d607667bSBen Chuang } 1299d607667bSBen Chuang 1300d607667bSBen Chuang clock |= SDHCI_CLOCK_CARD_EN; 1301d607667bSBen Chuang sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 1302d607667bSBen Chuang 1303f9e5b339SJason Lai /* Disable LPM negotiation to avoid entering L1 state. */ 1304f9e5b339SJason Lai gl9763e_set_low_power_negotiation(slot, false); 1305f9e5b339SJason Lai 1306d607667bSBen Chuang return 0; 1307d607667bSBen Chuang } 1308d607667bSBen Chuang #endif 1309d607667bSBen Chuang 13101ae1d2d6SBen Chuang static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) 13111ae1d2d6SBen Chuang { 1312347f6be1SBen Chuang struct pci_dev *pdev = slot->chip->pdev; 13131ae1d2d6SBen Chuang struct sdhci_host *host = slot->host; 1314347f6be1SBen Chuang u32 value; 13151ae1d2d6SBen Chuang 13161ae1d2d6SBen Chuang host->mmc->caps |= MMC_CAP_8_BIT_DATA | 13171ae1d2d6SBen Chuang MMC_CAP_1_8V_DDR | 13181ae1d2d6SBen Chuang MMC_CAP_NONREMOVABLE; 13191ae1d2d6SBen Chuang host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR | 13201ae1d2d6SBen Chuang MMC_CAP2_HS400_1_8V | 13211ae1d2d6SBen Chuang MMC_CAP2_HS400_ES | 13221ae1d2d6SBen Chuang MMC_CAP2_NO_SDIO | 13231ae1d2d6SBen Chuang MMC_CAP2_NO_SD; 1324347f6be1SBen Chuang 1325347f6be1SBen Chuang pci_read_config_dword(pdev, PCIE_GLI_9763E_MB, &value); 1326347f6be1SBen Chuang if (!(value & GLI_9763E_MB_CMDQ_OFF)) 132715f908faSRenius Chen if (value & GLI_9763E_MB_ERP_ON) 1328347f6be1SBen Chuang host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; 1329347f6be1SBen Chuang 13301ae1d2d6SBen Chuang gli_pcie_enable_msi(slot); 13311ae1d2d6SBen Chuang host->mmc_host_ops.hs400_enhanced_strobe = 13321ae1d2d6SBen Chuang gl9763e_hs400_enhanced_strobe; 13331ae1d2d6SBen Chuang gli_set_gl9763e(slot); 13341ae1d2d6SBen Chuang sdhci_enable_v4_mode(host); 13351ae1d2d6SBen Chuang 13361ae1d2d6SBen Chuang return 0; 13371ae1d2d6SBen Chuang } 13381ae1d2d6SBen Chuang 1339c064bb5cSHector Martin #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18) 1340c064bb5cSHector Martin 1341c064bb5cSHector Martin static u16 sdhci_gli_readw(struct sdhci_host *host, int reg) 1342c064bb5cSHector Martin { 1343c064bb5cSHector Martin u32 val = readl(host->ioaddr + (reg & ~3)); 1344c064bb5cSHector Martin u16 word; 1345c064bb5cSHector Martin 1346c064bb5cSHector Martin word = (val >> REG_OFFSET_IN_BITS(reg)) & 0xffff; 1347c064bb5cSHector Martin return word; 1348c064bb5cSHector Martin } 1349c064bb5cSHector Martin 1350c064bb5cSHector Martin static u8 sdhci_gli_readb(struct sdhci_host *host, int reg) 1351c064bb5cSHector Martin { 1352c064bb5cSHector Martin u32 val = readl(host->ioaddr + (reg & ~3)); 1353c064bb5cSHector Martin u8 byte = (val >> REG_OFFSET_IN_BITS(reg)) & 0xff; 1354c064bb5cSHector Martin 1355c064bb5cSHector Martin return byte; 1356c064bb5cSHector Martin } 1357c064bb5cSHector Martin 1358e51df6ceSBen Chuang static const struct sdhci_ops sdhci_gl9755_ops = { 1359c064bb5cSHector Martin .read_w = sdhci_gli_readw, 1360c064bb5cSHector Martin .read_b = sdhci_gli_readb, 1361786d33c8SBen Chuang .set_clock = sdhci_gl9755_set_clock, 1362e51df6ceSBen Chuang .enable_dma = sdhci_pci_enable_dma, 1363e51df6ceSBen Chuang .set_bus_width = sdhci_set_bus_width, 1364e51df6ceSBen Chuang .reset = sdhci_reset, 1365e51df6ceSBen Chuang .set_uhs_signaling = sdhci_set_uhs_signaling, 1366e51df6ceSBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1367e51df6ceSBen Chuang }; 1368e51df6ceSBen Chuang 1369e51df6ceSBen Chuang const struct sdhci_pci_fixes sdhci_gl9755 = { 1370e51df6ceSBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1371e51df6ceSBen Chuang .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1372e51df6ceSBen Chuang .probe_slot = gli_probe_slot_gl9755, 1373e51df6ceSBen Chuang .ops = &sdhci_gl9755_ops, 1374282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1375282ede76SBen Chuang .resume = sdhci_pci_gli_resume, 1376282ede76SBen Chuang #endif 1377e51df6ceSBen Chuang }; 1378e51df6ceSBen Chuang 1379e51df6ceSBen Chuang static const struct sdhci_ops sdhci_gl9750_ops = { 1380c064bb5cSHector Martin .read_w = sdhci_gli_readw, 1381c064bb5cSHector Martin .read_b = sdhci_gli_readb, 1382e51df6ceSBen Chuang .read_l = sdhci_gl9750_readl, 1383786d33c8SBen Chuang .set_clock = sdhci_gl9750_set_clock, 1384e51df6ceSBen Chuang .enable_dma = sdhci_pci_enable_dma, 1385e51df6ceSBen Chuang .set_bus_width = sdhci_set_bus_width, 1386e51df6ceSBen Chuang .reset = sdhci_gl9750_reset, 1387e51df6ceSBen Chuang .set_uhs_signaling = sdhci_set_uhs_signaling, 1388e51df6ceSBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1389e51df6ceSBen Chuang .platform_execute_tuning = gl9750_execute_tuning, 1390e51df6ceSBen Chuang }; 1391e51df6ceSBen Chuang 1392e51df6ceSBen Chuang const struct sdhci_pci_fixes sdhci_gl9750 = { 1393e51df6ceSBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1394e51df6ceSBen Chuang .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1395e51df6ceSBen Chuang .probe_slot = gli_probe_slot_gl9750, 1396e51df6ceSBen Chuang .ops = &sdhci_gl9750_ops, 1397282ede76SBen Chuang #ifdef CONFIG_PM_SLEEP 1398282ede76SBen Chuang .resume = sdhci_pci_gli_resume, 1399282ede76SBen Chuang #endif 1400e51df6ceSBen Chuang }; 14011ae1d2d6SBen Chuang 14021ae1d2d6SBen Chuang static const struct sdhci_ops sdhci_gl9763e_ops = { 14031ae1d2d6SBen Chuang .set_clock = sdhci_set_clock, 14041ae1d2d6SBen Chuang .enable_dma = sdhci_pci_enable_dma, 14051ae1d2d6SBen Chuang .set_bus_width = sdhci_set_bus_width, 140608b863bbSBrian Norris .reset = sdhci_and_cqhci_reset, 14071ae1d2d6SBen Chuang .set_uhs_signaling = sdhci_set_gl9763e_signaling, 14081ae1d2d6SBen Chuang .voltage_switch = sdhci_gli_voltage_switch, 1409347f6be1SBen Chuang .irq = sdhci_gl9763e_cqhci_irq, 14101ae1d2d6SBen Chuang }; 14111ae1d2d6SBen Chuang 14121ae1d2d6SBen Chuang const struct sdhci_pci_fixes sdhci_gl9763e = { 14131ae1d2d6SBen Chuang .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 14141ae1d2d6SBen Chuang .probe_slot = gli_probe_slot_gl9763e, 14151ae1d2d6SBen Chuang .ops = &sdhci_gl9763e_ops, 14161ae1d2d6SBen Chuang #ifdef CONFIG_PM_SLEEP 1417347f6be1SBen Chuang .resume = sdhci_cqhci_gli_resume, 1418347f6be1SBen Chuang .suspend = sdhci_cqhci_gli_suspend, 14191ae1d2d6SBen Chuang #endif 1420d607667bSBen Chuang #ifdef CONFIG_PM 1421d607667bSBen Chuang .runtime_suspend = gl9763e_runtime_suspend, 1422d607667bSBen Chuang .runtime_resume = gl9763e_runtime_resume, 1423d607667bSBen Chuang .allow_runtime_pm = true, 1424d607667bSBen Chuang #endif 1425347f6be1SBen Chuang .add_host = gl9763e_add_host, 14261ae1d2d6SBen Chuang }; 1427f3a5b56cSVictor Shih 1428f3a5b56cSVictor Shih static const struct sdhci_ops sdhci_gl9767_ops = { 1429*d2754355SVictor Shih .set_clock = sdhci_gl9767_set_clock, 1430f3a5b56cSVictor Shih .enable_dma = sdhci_pci_enable_dma, 1431f3a5b56cSVictor Shih .set_bus_width = sdhci_set_bus_width, 1432f3a5b56cSVictor Shih .reset = sdhci_gl9767_reset, 1433f3a5b56cSVictor Shih .set_uhs_signaling = sdhci_set_uhs_signaling, 1434f3a5b56cSVictor Shih .voltage_switch = sdhci_gl9767_voltage_switch, 1435f3a5b56cSVictor Shih }; 1436f3a5b56cSVictor Shih 1437f3a5b56cSVictor Shih const struct sdhci_pci_fixes sdhci_gl9767 = { 1438f3a5b56cSVictor Shih .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 1439f3a5b56cSVictor Shih .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 1440f3a5b56cSVictor Shih .probe_slot = gli_probe_slot_gl9767, 1441f3a5b56cSVictor Shih .ops = &sdhci_gl9767_ops, 1442f3a5b56cSVictor Shih #ifdef CONFIG_PM_SLEEP 1443f3a5b56cSVictor Shih .resume = sdhci_pci_gli_resume, 1444f3a5b56cSVictor Shih #endif 1445f3a5b56cSVictor Shih }; 1446