162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2019 Genesys Logic, Inc. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Version: v0.9.0 (2019-08-08) 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci#include <linux/bits.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/mmc/mmc.h> 1462306a36Sopenharmony_ci#include <linux/delay.h> 1562306a36Sopenharmony_ci#include <linux/of.h> 1662306a36Sopenharmony_ci#include <linux/iopoll.h> 1762306a36Sopenharmony_ci#include "sdhci.h" 1862306a36Sopenharmony_ci#include "sdhci-cqhci.h" 1962306a36Sopenharmony_ci#include "sdhci-pci.h" 2062306a36Sopenharmony_ci#include "cqhci.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Genesys Logic extra registers */ 2362306a36Sopenharmony_ci#define SDHCI_GLI_9750_WT 0x800 2462306a36Sopenharmony_ci#define SDHCI_GLI_9750_WT_EN BIT(0) 2562306a36Sopenharmony_ci#define GLI_9750_WT_EN_ON 0x1 2662306a36Sopenharmony_ci#define GLI_9750_WT_EN_OFF 0x0 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define PCI_GLI_9750_PM_CTRL 0xFC 2962306a36Sopenharmony_ci#define PCI_GLI_9750_PM_STATE GENMASK(1, 0) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define PCI_GLI_9750_CORRERR_MASK 0x214 3262306a36Sopenharmony_ci#define PCI_GLI_9750_CORRERR_MASK_REPLAY_TIMER_TIMEOUT BIT(12) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define SDHCI_GLI_9750_CFG2 0x848 3562306a36Sopenharmony_ci#define SDHCI_GLI_9750_CFG2_L1DLY GENMASK(28, 24) 3662306a36Sopenharmony_ci#define GLI_9750_CFG2_L1DLY_VALUE 0x1F 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define SDHCI_GLI_9750_DRIVING 0x860 3962306a36Sopenharmony_ci#define SDHCI_GLI_9750_DRIVING_1 GENMASK(11, 0) 4062306a36Sopenharmony_ci#define SDHCI_GLI_9750_DRIVING_2 GENMASK(27, 26) 4162306a36Sopenharmony_ci#define GLI_9750_DRIVING_1_VALUE 0xFFF 4262306a36Sopenharmony_ci#define GLI_9750_DRIVING_2_VALUE 0x3 4362306a36Sopenharmony_ci#define SDHCI_GLI_9750_SEL_1 BIT(29) 4462306a36Sopenharmony_ci#define SDHCI_GLI_9750_SEL_2 BIT(31) 4562306a36Sopenharmony_ci#define SDHCI_GLI_9750_ALL_RST (BIT(24)|BIT(25)|BIT(28)|BIT(30)) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL 0x864 4862306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL_LDIV GENMASK(9, 0) 4962306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL_PDIV GENMASK(14, 12) 5062306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL_DIR BIT(15) 5162306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL_TX2_INV BIT(23) 5262306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLL_TX2_DLY GENMASK(22, 20) 5362306a36Sopenharmony_ci#define GLI_9750_PLL_TX2_INV_VALUE 0x1 5462306a36Sopenharmony_ci#define GLI_9750_PLL_TX2_DLY_VALUE 0x0 5562306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLLSSC_STEP GENMASK(28, 24) 5662306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLLSSC_EN BIT(31) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLLSSC 0x86C 5962306a36Sopenharmony_ci#define SDHCI_GLI_9750_PLLSSC_PPM GENMASK(31, 16) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define SDHCI_GLI_9750_SW_CTRL 0x874 6262306a36Sopenharmony_ci#define SDHCI_GLI_9750_SW_CTRL_4 GENMASK(7, 6) 6362306a36Sopenharmony_ci#define GLI_9750_SW_CTRL_4_VALUE 0x3 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define SDHCI_GLI_9750_MISC 0x878 6662306a36Sopenharmony_ci#define SDHCI_GLI_9750_MISC_TX1_INV BIT(2) 6762306a36Sopenharmony_ci#define SDHCI_GLI_9750_MISC_RX_INV BIT(3) 6862306a36Sopenharmony_ci#define SDHCI_GLI_9750_MISC_TX1_DLY GENMASK(6, 4) 6962306a36Sopenharmony_ci#define GLI_9750_MISC_TX1_INV_VALUE 0x0 7062306a36Sopenharmony_ci#define GLI_9750_MISC_RX_INV_ON 0x1 7162306a36Sopenharmony_ci#define GLI_9750_MISC_RX_INV_OFF 0x0 7262306a36Sopenharmony_ci#define GLI_9750_MISC_RX_INV_VALUE GLI_9750_MISC_RX_INV_OFF 7362306a36Sopenharmony_ci#define GLI_9750_MISC_TX1_DLY_VALUE 0x5 7462306a36Sopenharmony_ci#define SDHCI_GLI_9750_MISC_SSC_OFF BIT(26) 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_CONTROL 0x540 7762306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) 7862306a36Sopenharmony_ci#define GLI_9750_TUNING_CONTROL_EN_ON 0x1 7962306a36Sopenharmony_ci#define GLI_9750_TUNING_CONTROL_EN_OFF 0x0 8062306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1 BIT(16) 8162306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2 GENMASK(20, 19) 8262306a36Sopenharmony_ci#define GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE 0x1 8362306a36Sopenharmony_ci#define GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE 0x2 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_PARAMETERS 0x544 8662306a36Sopenharmony_ci#define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) 8762306a36Sopenharmony_ci#define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define SDHCI_GLI_9763E_CTRL_HS400 0x7 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define SDHCI_GLI_9763E_HS400_ES_REG 0x52C 9262306a36Sopenharmony_ci#define SDHCI_GLI_9763E_HS400_ES_BIT BIT(8) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define PCIE_GLI_9763E_VHS 0x884 9562306a36Sopenharmony_ci#define GLI_9763E_VHS_REV GENMASK(19, 16) 9662306a36Sopenharmony_ci#define GLI_9763E_VHS_REV_R 0x0 9762306a36Sopenharmony_ci#define GLI_9763E_VHS_REV_M 0x1 9862306a36Sopenharmony_ci#define GLI_9763E_VHS_REV_W 0x2 9962306a36Sopenharmony_ci#define PCIE_GLI_9763E_MB 0x888 10062306a36Sopenharmony_ci#define GLI_9763E_MB_CMDQ_OFF BIT(19) 10162306a36Sopenharmony_ci#define GLI_9763E_MB_ERP_ON BIT(7) 10262306a36Sopenharmony_ci#define PCIE_GLI_9763E_SCR 0x8E0 10362306a36Sopenharmony_ci#define GLI_9763E_SCR_AXI_REQ BIT(9) 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define PCIE_GLI_9763E_CFG 0x8A0 10662306a36Sopenharmony_ci#define GLI_9763E_CFG_LPSN_DIS BIT(12) 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#define PCIE_GLI_9763E_CFG2 0x8A4 10962306a36Sopenharmony_ci#define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) 11062306a36Sopenharmony_ci#define GLI_9763E_CFG2_L1DLY_MID 0x54 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define PCIE_GLI_9763E_MMC_CTRL 0x960 11362306a36Sopenharmony_ci#define GLI_9763E_HS400_SLOW BIT(3) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define PCIE_GLI_9763E_CLKRXDLY 0x934 11662306a36Sopenharmony_ci#define GLI_9763E_HS400_RXDLY GENMASK(31, 28) 11762306a36Sopenharmony_ci#define GLI_9763E_HS400_RXDLY_5 0x5 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#define SDHCI_GLI_9763E_CQE_BASE_ADDR 0x200 12062306a36Sopenharmony_ci#define GLI_9763E_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \ 12162306a36Sopenharmony_ci SDHCI_TRNS_BLK_CNT_EN | \ 12262306a36Sopenharmony_ci SDHCI_TRNS_DMA) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define PCI_GLI_9755_WT 0x800 12562306a36Sopenharmony_ci#define PCI_GLI_9755_WT_EN BIT(0) 12662306a36Sopenharmony_ci#define GLI_9755_WT_EN_ON 0x1 12762306a36Sopenharmony_ci#define GLI_9755_WT_EN_OFF 0x0 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci#define PCI_GLI_9755_PECONF 0x44 13062306a36Sopenharmony_ci#define PCI_GLI_9755_LFCLK GENMASK(14, 12) 13162306a36Sopenharmony_ci#define PCI_GLI_9755_DMACLK BIT(29) 13262306a36Sopenharmony_ci#define PCI_GLI_9755_INVERT_CD BIT(30) 13362306a36Sopenharmony_ci#define PCI_GLI_9755_INVERT_WP BIT(31) 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define PCI_GLI_9755_CFG2 0x48 13662306a36Sopenharmony_ci#define PCI_GLI_9755_CFG2_L1DLY GENMASK(28, 24) 13762306a36Sopenharmony_ci#define GLI_9755_CFG2_L1DLY_VALUE 0x1F 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#define PCI_GLI_9755_PLL 0x64 14062306a36Sopenharmony_ci#define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0) 14162306a36Sopenharmony_ci#define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12) 14262306a36Sopenharmony_ci#define PCI_GLI_9755_PLL_DIR BIT(15) 14362306a36Sopenharmony_ci#define PCI_GLI_9755_PLLSSC_STEP GENMASK(28, 24) 14462306a36Sopenharmony_ci#define PCI_GLI_9755_PLLSSC_EN BIT(31) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define PCI_GLI_9755_PLLSSC 0x68 14762306a36Sopenharmony_ci#define PCI_GLI_9755_PLLSSC_PPM GENMASK(15, 0) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci#define PCI_GLI_9755_SerDes 0x70 15062306a36Sopenharmony_ci#define PCI_GLI_9755_SCP_DIS BIT(19) 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#define PCI_GLI_9755_MISC 0x78 15362306a36Sopenharmony_ci#define PCI_GLI_9755_MISC_SSC_OFF BIT(26) 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#define PCI_GLI_9755_PM_CTRL 0xFC 15662306a36Sopenharmony_ci#define PCI_GLI_9755_PM_STATE GENMASK(1, 0) 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#define PCI_GLI_9755_CORRERR_MASK 0x214 15962306a36Sopenharmony_ci#define PCI_GLI_9755_CORRERR_MASK_REPLAY_TIMER_TIMEOUT BIT(12) 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510 16262306a36Sopenharmony_ci#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#define PCIE_GLI_9767_VHS 0x884 16562306a36Sopenharmony_ci#define GLI_9767_VHS_REV GENMASK(19, 16) 16662306a36Sopenharmony_ci#define GLI_9767_VHS_REV_R 0x0 16762306a36Sopenharmony_ci#define GLI_9767_VHS_REV_M 0x1 16862306a36Sopenharmony_ci#define GLI_9767_VHS_REV_W 0x2 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci#define PCIE_GLI_9767_COM_MAILBOX 0x888 17162306a36Sopenharmony_ci#define PCIE_GLI_9767_COM_MAILBOX_SSC_EN BIT(1) 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#define PCIE_GLI_9767_CFG 0x8A0 17462306a36Sopenharmony_ci#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12) 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8 17762306a36Sopenharmony_ci#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6) 17862306a36Sopenharmony_ci#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0 18162306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0) 18262306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12) 18362306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7 18462306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28) 18562306a36Sopenharmony_ci#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR 0x8E0 18862306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6) 18962306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7) 19062306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_AXI_REQ BIT(9) 19162306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10) 19262306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16) 19362306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17) 19462306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21) 19562306a36Sopenharmony_ci#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30) 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define PCIE_GLI_9767_SDHC_CAP 0x91C 19862306a36Sopenharmony_ci#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5) 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL 0x938 20162306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0) 20262306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12) 20362306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN BIT(16) 20462306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL_SSC_EN BIT(19) 20562306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING GENMASK(28, 24) 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL2 0x93C 20862306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM GENMASK(31, 16) 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940 21162306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0) 21262306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1) 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944 21562306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16) 21662306a36Sopenharmony_ci#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950 21962306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0) 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954 22262306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN BIT(0) 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958 22562306a36Sopenharmony_ci#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0) 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#define GLI_MAX_TUNING_LOOP 40 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* Genesys Logic chipset */ 23062306a36Sopenharmony_cistatic inline void gl9750_wt_on(struct sdhci_host *host) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci u32 wt_value; 23362306a36Sopenharmony_ci u32 wt_enable; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 23662306a36Sopenharmony_ci wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (wt_enable == GLI_9750_WT_EN_ON) 23962306a36Sopenharmony_ci return; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci wt_value &= ~SDHCI_GLI_9750_WT_EN; 24262306a36Sopenharmony_ci wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_ON); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline void gl9750_wt_off(struct sdhci_host *host) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci u32 wt_value; 25062306a36Sopenharmony_ci u32 wt_enable; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 25362306a36Sopenharmony_ci wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (wt_enable == GLI_9750_WT_EN_OFF) 25662306a36Sopenharmony_ci return; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci wt_value &= ~SDHCI_GLI_9750_WT_EN; 25962306a36Sopenharmony_ci wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_OFF); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic void gli_set_9750(struct sdhci_host *host) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci u32 driving_value; 26762306a36Sopenharmony_ci u32 pll_value; 26862306a36Sopenharmony_ci u32 sw_ctrl_value; 26962306a36Sopenharmony_ci u32 misc_value; 27062306a36Sopenharmony_ci u32 parameter_value; 27162306a36Sopenharmony_ci u32 control_value; 27262306a36Sopenharmony_ci u16 ctrl2; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci gl9750_wt_on(host); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); 27762306a36Sopenharmony_ci pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); 27862306a36Sopenharmony_ci sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); 27962306a36Sopenharmony_ci misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 28062306a36Sopenharmony_ci parameter_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_PARAMETERS); 28162306a36Sopenharmony_ci control_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_CONTROL); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci driving_value &= ~(SDHCI_GLI_9750_DRIVING_1); 28462306a36Sopenharmony_ci driving_value &= ~(SDHCI_GLI_9750_DRIVING_2); 28562306a36Sopenharmony_ci driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1, 28662306a36Sopenharmony_ci GLI_9750_DRIVING_1_VALUE); 28762306a36Sopenharmony_ci driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2, 28862306a36Sopenharmony_ci GLI_9750_DRIVING_2_VALUE); 28962306a36Sopenharmony_ci driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST); 29062306a36Sopenharmony_ci driving_value |= SDHCI_GLI_9750_SEL_2; 29162306a36Sopenharmony_ci sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4; 29462306a36Sopenharmony_ci sw_ctrl_value |= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4, 29562306a36Sopenharmony_ci GLI_9750_SW_CTRL_4_VALUE); 29662306a36Sopenharmony_ci sdhci_writel(host, sw_ctrl_value, SDHCI_GLI_9750_SW_CTRL); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* reset the tuning flow after reinit and before starting tuning */ 29962306a36Sopenharmony_ci pll_value &= ~SDHCI_GLI_9750_PLL_TX2_INV; 30062306a36Sopenharmony_ci pll_value &= ~SDHCI_GLI_9750_PLL_TX2_DLY; 30162306a36Sopenharmony_ci pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV, 30262306a36Sopenharmony_ci GLI_9750_PLL_TX2_INV_VALUE); 30362306a36Sopenharmony_ci pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY, 30462306a36Sopenharmony_ci GLI_9750_PLL_TX2_DLY_VALUE); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci misc_value &= ~SDHCI_GLI_9750_MISC_TX1_INV; 30762306a36Sopenharmony_ci misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 30862306a36Sopenharmony_ci misc_value &= ~SDHCI_GLI_9750_MISC_TX1_DLY; 30962306a36Sopenharmony_ci misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV, 31062306a36Sopenharmony_ci GLI_9750_MISC_TX1_INV_VALUE); 31162306a36Sopenharmony_ci misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 31262306a36Sopenharmony_ci GLI_9750_MISC_RX_INV_VALUE); 31362306a36Sopenharmony_ci misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY, 31462306a36Sopenharmony_ci GLI_9750_MISC_TX1_DLY_VALUE); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci parameter_value &= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY; 31762306a36Sopenharmony_ci parameter_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY, 31862306a36Sopenharmony_ci GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1; 32162306a36Sopenharmony_ci control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2; 32262306a36Sopenharmony_ci control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1, 32362306a36Sopenharmony_ci GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE); 32462306a36Sopenharmony_ci control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2, 32562306a36Sopenharmony_ci GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci sdhci_writel(host, pll_value, SDHCI_GLI_9750_PLL); 32862306a36Sopenharmony_ci sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* disable tuned clk */ 33162306a36Sopenharmony_ci ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 33262306a36Sopenharmony_ci ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 33362306a36Sopenharmony_ci sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* enable tuning parameters control */ 33662306a36Sopenharmony_ci control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 33762306a36Sopenharmony_ci control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 33862306a36Sopenharmony_ci GLI_9750_TUNING_CONTROL_EN_ON); 33962306a36Sopenharmony_ci sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci /* write tuning parameters */ 34262306a36Sopenharmony_ci sdhci_writel(host, parameter_value, SDHCI_GLI_9750_TUNING_PARAMETERS); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* disable tuning parameters control */ 34562306a36Sopenharmony_ci control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 34662306a36Sopenharmony_ci control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 34762306a36Sopenharmony_ci GLI_9750_TUNING_CONTROL_EN_OFF); 34862306a36Sopenharmony_ci sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* clear tuned clk */ 35162306a36Sopenharmony_ci ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 35262306a36Sopenharmony_ci ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 35362306a36Sopenharmony_ci sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci gl9750_wt_off(host); 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic void gli_set_9750_rx_inv(struct sdhci_host *host, bool b) 35962306a36Sopenharmony_ci{ 36062306a36Sopenharmony_ci u32 misc_value; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci gl9750_wt_on(host); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 36562306a36Sopenharmony_ci misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 36662306a36Sopenharmony_ci if (b) { 36762306a36Sopenharmony_ci misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 36862306a36Sopenharmony_ci GLI_9750_MISC_RX_INV_ON); 36962306a36Sopenharmony_ci } else { 37062306a36Sopenharmony_ci misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 37162306a36Sopenharmony_ci GLI_9750_MISC_RX_INV_OFF); 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci gl9750_wt_off(host); 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic int __sdhci_execute_tuning_9750(struct sdhci_host *host, u32 opcode) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci int i; 38162306a36Sopenharmony_ci int rx_inv; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci for (rx_inv = 0; rx_inv < 2; rx_inv++) { 38462306a36Sopenharmony_ci gli_set_9750_rx_inv(host, !!rx_inv); 38562306a36Sopenharmony_ci sdhci_start_tuning(host); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci for (i = 0; i < GLI_MAX_TUNING_LOOP; i++) { 38862306a36Sopenharmony_ci u16 ctrl; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci sdhci_send_tuning(host, opcode); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (!host->tuning_done) { 39362306a36Sopenharmony_ci sdhci_abort_tuning(host, opcode); 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 39862306a36Sopenharmony_ci if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 39962306a36Sopenharmony_ci if (ctrl & SDHCI_CTRL_TUNED_CLK) 40062306a36Sopenharmony_ci return 0; /* Success! */ 40162306a36Sopenharmony_ci break; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci } 40562306a36Sopenharmony_ci if (!host->tuning_done) { 40662306a36Sopenharmony_ci pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", 40762306a36Sopenharmony_ci mmc_hostname(host->mmc)); 40862306a36Sopenharmony_ci return -ETIMEDOUT; 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 41262306a36Sopenharmony_ci mmc_hostname(host->mmc)); 41362306a36Sopenharmony_ci sdhci_reset_tuning(host); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci return -EAGAIN; 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci host->mmc->retune_period = 0; 42162306a36Sopenharmony_ci if (host->tuning_mode == SDHCI_TUNING_MODE_1) 42262306a36Sopenharmony_ci host->mmc->retune_period = host->tuning_count; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci gli_set_9750(host); 42562306a36Sopenharmony_ci host->tuning_err = __sdhci_execute_tuning_9750(host, opcode); 42662306a36Sopenharmony_ci sdhci_end_tuning(host); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci return 0; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic void gl9750_disable_ssc_pll(struct sdhci_host *host) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci u32 pll; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci gl9750_wt_on(host); 43662306a36Sopenharmony_ci pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 43762306a36Sopenharmony_ci pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN); 43862306a36Sopenharmony_ci sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 43962306a36Sopenharmony_ci gl9750_wt_off(host); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci u32 pll; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci gl9750_wt_on(host); 44762306a36Sopenharmony_ci pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 44862306a36Sopenharmony_ci pll &= ~(SDHCI_GLI_9750_PLL_LDIV | 44962306a36Sopenharmony_ci SDHCI_GLI_9750_PLL_PDIV | 45062306a36Sopenharmony_ci SDHCI_GLI_9750_PLL_DIR); 45162306a36Sopenharmony_ci pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) | 45262306a36Sopenharmony_ci FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) | 45362306a36Sopenharmony_ci FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir); 45462306a36Sopenharmony_ci sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 45562306a36Sopenharmony_ci gl9750_wt_off(host); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* wait for pll stable */ 45862306a36Sopenharmony_ci mdelay(1); 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic bool gl9750_ssc_enable(struct sdhci_host *host) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci u32 misc; 46462306a36Sopenharmony_ci u8 off; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci gl9750_wt_on(host); 46762306a36Sopenharmony_ci misc = sdhci_readl(host, SDHCI_GLI_9750_MISC); 46862306a36Sopenharmony_ci off = FIELD_GET(SDHCI_GLI_9750_MISC_SSC_OFF, misc); 46962306a36Sopenharmony_ci gl9750_wt_off(host); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci return !off; 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci u32 pll; 47762306a36Sopenharmony_ci u32 ssc; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci gl9750_wt_on(host); 48062306a36Sopenharmony_ci pll = sdhci_readl(host, SDHCI_GLI_9750_PLL); 48162306a36Sopenharmony_ci ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC); 48262306a36Sopenharmony_ci pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP | 48362306a36Sopenharmony_ci SDHCI_GLI_9750_PLLSSC_EN); 48462306a36Sopenharmony_ci ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM; 48562306a36Sopenharmony_ci pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) | 48662306a36Sopenharmony_ci FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable); 48762306a36Sopenharmony_ci ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm); 48862306a36Sopenharmony_ci sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC); 48962306a36Sopenharmony_ci sdhci_writel(host, pll, SDHCI_GLI_9750_PLL); 49062306a36Sopenharmony_ci gl9750_wt_off(host); 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host) 49462306a36Sopenharmony_ci{ 49562306a36Sopenharmony_ci bool enable = gl9750_ssc_enable(host); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* set pll to 205MHz and ssc */ 49862306a36Sopenharmony_ci gl9750_set_ssc(host, enable, 0xF, 0x5A1D); 49962306a36Sopenharmony_ci gl9750_set_pll(host, 0x1, 0x246, 0x0); 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_cistatic void gl9750_set_ssc_pll_100mhz(struct sdhci_host *host) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci bool enable = gl9750_ssc_enable(host); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* set pll to 100MHz and ssc */ 50762306a36Sopenharmony_ci gl9750_set_ssc(host, enable, 0xE, 0x51EC); 50862306a36Sopenharmony_ci gl9750_set_pll(host, 0x1, 0x244, 0x1); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic void gl9750_set_ssc_pll_50mhz(struct sdhci_host *host) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci bool enable = gl9750_ssc_enable(host); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci /* set pll to 50MHz and ssc */ 51662306a36Sopenharmony_ci gl9750_set_ssc(host, enable, 0xE, 0x51EC); 51762306a36Sopenharmony_ci gl9750_set_pll(host, 0x1, 0x244, 0x3); 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_cistatic void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci struct mmc_ios *ios = &host->mmc->ios; 52362306a36Sopenharmony_ci u16 clk; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci host->mmc->actual_clock = 0; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci gl9750_disable_ssc_pll(host); 52862306a36Sopenharmony_ci sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci if (clock == 0) 53162306a36Sopenharmony_ci return; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 53462306a36Sopenharmony_ci if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 53562306a36Sopenharmony_ci host->mmc->actual_clock = 205000000; 53662306a36Sopenharmony_ci gl9750_set_ssc_pll_205mhz(host); 53762306a36Sopenharmony_ci } else if (clock == 100000000) { 53862306a36Sopenharmony_ci gl9750_set_ssc_pll_100mhz(host); 53962306a36Sopenharmony_ci } else if (clock == 50000000) { 54062306a36Sopenharmony_ci gl9750_set_ssc_pll_50mhz(host); 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci sdhci_enable_clk(host, clk); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic void gl9750_hw_setting(struct sdhci_host *host) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci struct sdhci_pci_slot *slot = sdhci_priv(host); 54962306a36Sopenharmony_ci struct pci_dev *pdev; 55062306a36Sopenharmony_ci u32 value; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci pdev = slot->chip->pdev; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci gl9750_wt_on(host); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci value = sdhci_readl(host, SDHCI_GLI_9750_CFG2); 55762306a36Sopenharmony_ci value &= ~SDHCI_GLI_9750_CFG2_L1DLY; 55862306a36Sopenharmony_ci /* set ASPM L1 entry delay to 7.9us */ 55962306a36Sopenharmony_ci value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY, 56062306a36Sopenharmony_ci GLI_9750_CFG2_L1DLY_VALUE); 56162306a36Sopenharmony_ci sdhci_writel(host, value, SDHCI_GLI_9750_CFG2); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* toggle PM state to allow GL9750 to enter ASPM L1.2 */ 56462306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9750_PM_CTRL, &value); 56562306a36Sopenharmony_ci value |= PCI_GLI_9750_PM_STATE; 56662306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9750_PM_CTRL, value); 56762306a36Sopenharmony_ci value &= ~PCI_GLI_9750_PM_STATE; 56862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9750_PM_CTRL, value); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* mask the replay timer timeout of AER */ 57162306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9750_CORRERR_MASK, &value); 57262306a36Sopenharmony_ci value |= PCI_GLI_9750_CORRERR_MASK_REPLAY_TIMER_TIMEOUT; 57362306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9750_CORRERR_MASK, value); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci gl9750_wt_off(host); 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_cistatic void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) 57962306a36Sopenharmony_ci{ 58062306a36Sopenharmony_ci int ret; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1, 58362306a36Sopenharmony_ci PCI_IRQ_MSI | PCI_IRQ_MSIX); 58462306a36Sopenharmony_ci if (ret < 0) { 58562306a36Sopenharmony_ci pr_warn("%s: enable PCI MSI failed, error=%d\n", 58662306a36Sopenharmony_ci mmc_hostname(slot->host->mmc), ret); 58762306a36Sopenharmony_ci return; 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci slot->host->irq = pci_irq_vector(slot->chip->pdev, 0); 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_cistatic inline void gl9755_wt_on(struct pci_dev *pdev) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci u32 wt_value; 59662306a36Sopenharmony_ci u32 wt_enable; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 59962306a36Sopenharmony_ci wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (wt_enable == GLI_9755_WT_EN_ON) 60262306a36Sopenharmony_ci return; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci wt_value &= ~PCI_GLI_9755_WT_EN; 60562306a36Sopenharmony_ci wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic inline void gl9755_wt_off(struct pci_dev *pdev) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci u32 wt_value; 61362306a36Sopenharmony_ci u32 wt_enable; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value); 61662306a36Sopenharmony_ci wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value); 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (wt_enable == GLI_9755_WT_EN_OFF) 61962306a36Sopenharmony_ci return; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci wt_value &= ~PCI_GLI_9755_WT_EN; 62262306a36Sopenharmony_ci wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF); 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value); 62562306a36Sopenharmony_ci} 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_cistatic void gl9755_disable_ssc_pll(struct pci_dev *pdev) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci u32 pll; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci gl9755_wt_on(pdev); 63262306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 63362306a36Sopenharmony_ci pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN); 63462306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 63562306a36Sopenharmony_ci gl9755_wt_off(pdev); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci u32 pll; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci gl9755_wt_on(pdev); 64362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 64462306a36Sopenharmony_ci pll &= ~(PCI_GLI_9755_PLL_LDIV | 64562306a36Sopenharmony_ci PCI_GLI_9755_PLL_PDIV | 64662306a36Sopenharmony_ci PCI_GLI_9755_PLL_DIR); 64762306a36Sopenharmony_ci pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) | 64862306a36Sopenharmony_ci FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) | 64962306a36Sopenharmony_ci FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir); 65062306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 65162306a36Sopenharmony_ci gl9755_wt_off(pdev); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci /* wait for pll stable */ 65462306a36Sopenharmony_ci mdelay(1); 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic bool gl9755_ssc_enable(struct pci_dev *pdev) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci u32 misc; 66062306a36Sopenharmony_ci u8 off; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci gl9755_wt_on(pdev); 66362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_MISC, &misc); 66462306a36Sopenharmony_ci off = FIELD_GET(PCI_GLI_9755_MISC_SSC_OFF, misc); 66562306a36Sopenharmony_ci gl9755_wt_off(pdev); 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci return !off; 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci u32 pll; 67362306a36Sopenharmony_ci u32 ssc; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci gl9755_wt_on(pdev); 67662306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll); 67762306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc); 67862306a36Sopenharmony_ci pll &= ~(PCI_GLI_9755_PLLSSC_STEP | 67962306a36Sopenharmony_ci PCI_GLI_9755_PLLSSC_EN); 68062306a36Sopenharmony_ci ssc &= ~PCI_GLI_9755_PLLSSC_PPM; 68162306a36Sopenharmony_ci pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) | 68262306a36Sopenharmony_ci FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable); 68362306a36Sopenharmony_ci ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm); 68462306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc); 68562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll); 68662306a36Sopenharmony_ci gl9755_wt_off(pdev); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci bool enable = gl9755_ssc_enable(pdev); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* set pll to 205MHz and ssc */ 69462306a36Sopenharmony_ci gl9755_set_ssc(pdev, enable, 0xF, 0x5A1D); 69562306a36Sopenharmony_ci gl9755_set_pll(pdev, 0x1, 0x246, 0x0); 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_cistatic void gl9755_set_ssc_pll_100mhz(struct pci_dev *pdev) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci bool enable = gl9755_ssc_enable(pdev); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci /* set pll to 100MHz and ssc */ 70362306a36Sopenharmony_ci gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 70462306a36Sopenharmony_ci gl9755_set_pll(pdev, 0x1, 0x244, 0x1); 70562306a36Sopenharmony_ci} 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_cistatic void gl9755_set_ssc_pll_50mhz(struct pci_dev *pdev) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci bool enable = gl9755_ssc_enable(pdev); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci /* set pll to 50MHz and ssc */ 71262306a36Sopenharmony_ci gl9755_set_ssc(pdev, enable, 0xE, 0x51EC); 71362306a36Sopenharmony_ci gl9755_set_pll(pdev, 0x1, 0x244, 0x3); 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci struct sdhci_pci_slot *slot = sdhci_priv(host); 71962306a36Sopenharmony_ci struct mmc_ios *ios = &host->mmc->ios; 72062306a36Sopenharmony_ci struct pci_dev *pdev; 72162306a36Sopenharmony_ci u16 clk; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci pdev = slot->chip->pdev; 72462306a36Sopenharmony_ci host->mmc->actual_clock = 0; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci gl9755_disable_ssc_pll(pdev); 72762306a36Sopenharmony_ci sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (clock == 0) 73062306a36Sopenharmony_ci return; 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 73362306a36Sopenharmony_ci if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 73462306a36Sopenharmony_ci host->mmc->actual_clock = 205000000; 73562306a36Sopenharmony_ci gl9755_set_ssc_pll_205mhz(pdev); 73662306a36Sopenharmony_ci } else if (clock == 100000000) { 73762306a36Sopenharmony_ci gl9755_set_ssc_pll_100mhz(pdev); 73862306a36Sopenharmony_ci } else if (clock == 50000000) { 73962306a36Sopenharmony_ci gl9755_set_ssc_pll_50mhz(pdev); 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci sdhci_enable_clk(host, clk); 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic void gl9755_hw_setting(struct sdhci_pci_slot *slot) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci struct pci_dev *pdev = slot->chip->pdev; 74862306a36Sopenharmony_ci u32 value; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci gl9755_wt_on(pdev); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value); 75362306a36Sopenharmony_ci /* 75462306a36Sopenharmony_ci * Apple ARM64 platforms using these chips may have 75562306a36Sopenharmony_ci * inverted CD/WP detection. 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci if (of_property_read_bool(pdev->dev.of_node, "cd-inverted")) 75862306a36Sopenharmony_ci value |= PCI_GLI_9755_INVERT_CD; 75962306a36Sopenharmony_ci if (of_property_read_bool(pdev->dev.of_node, "wp-inverted")) 76062306a36Sopenharmony_ci value |= PCI_GLI_9755_INVERT_WP; 76162306a36Sopenharmony_ci value &= ~PCI_GLI_9755_LFCLK; 76262306a36Sopenharmony_ci value &= ~PCI_GLI_9755_DMACLK; 76362306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci /* enable short circuit protection */ 76662306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &value); 76762306a36Sopenharmony_ci value &= ~PCI_GLI_9755_SCP_DIS; 76862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value); 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, &value); 77162306a36Sopenharmony_ci value &= ~PCI_GLI_9755_CFG2_L1DLY; 77262306a36Sopenharmony_ci /* set ASPM L1 entry delay to 7.9us */ 77362306a36Sopenharmony_ci value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY, 77462306a36Sopenharmony_ci GLI_9755_CFG2_L1DLY_VALUE); 77562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* toggle PM state to allow GL9755 to enter ASPM L1.2 */ 77862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_PM_CTRL, &value); 77962306a36Sopenharmony_ci value |= PCI_GLI_9755_PM_STATE; 78062306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 78162306a36Sopenharmony_ci value &= ~PCI_GLI_9755_PM_STATE; 78262306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_PM_CTRL, value); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci /* mask the replay timer timeout of AER */ 78562306a36Sopenharmony_ci pci_read_config_dword(pdev, PCI_GLI_9755_CORRERR_MASK, &value); 78662306a36Sopenharmony_ci value |= PCI_GLI_9755_CORRERR_MASK_REPLAY_TIMER_TIMEOUT; 78762306a36Sopenharmony_ci pci_write_config_dword(pdev, PCI_GLI_9755_CORRERR_MASK, value); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci gl9755_wt_off(pdev); 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic inline void gl9767_vhs_read(struct pci_dev *pdev) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci u32 vhs_enable; 79562306a36Sopenharmony_ci u32 vhs_value; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 79862306a36Sopenharmony_ci vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (vhs_enable == GLI_9767_VHS_REV_R) 80162306a36Sopenharmony_ci return; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci vhs_value &= ~GLI_9767_VHS_REV; 80462306a36Sopenharmony_ci vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_cistatic inline void gl9767_vhs_write(struct pci_dev *pdev) 81062306a36Sopenharmony_ci{ 81162306a36Sopenharmony_ci u32 vhs_enable; 81262306a36Sopenharmony_ci u32 vhs_value; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value); 81562306a36Sopenharmony_ci vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (vhs_enable == GLI_9767_VHS_REV_W) 81862306a36Sopenharmony_ci return; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci vhs_value &= ~GLI_9767_VHS_REV; 82162306a36Sopenharmony_ci vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_cistatic bool gl9767_ssc_enable(struct pci_dev *pdev) 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci u32 value; 82962306a36Sopenharmony_ci u8 enable; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci gl9767_vhs_write(pdev); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_COM_MAILBOX, &value); 83462306a36Sopenharmony_ci enable = FIELD_GET(PCIE_GLI_9767_COM_MAILBOX_SSC_EN, value); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci gl9767_vhs_read(pdev); 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci return enable; 83962306a36Sopenharmony_ci} 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_cistatic void gl9767_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci u32 pll; 84462306a36Sopenharmony_ci u32 ssc; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci gl9767_vhs_write(pdev); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 84962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, &ssc); 85062306a36Sopenharmony_ci pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING | 85162306a36Sopenharmony_ci PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 85262306a36Sopenharmony_ci ssc &= ~PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM; 85362306a36Sopenharmony_ci pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_STEP_SETTING, step) | 85462306a36Sopenharmony_ci FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_SSC_EN, enable); 85562306a36Sopenharmony_ci ssc |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL2_PLLSSC_PPM, ppm); 85662306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL2, ssc); 85762306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci gl9767_vhs_read(pdev); 86062306a36Sopenharmony_ci} 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic void gl9767_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv) 86362306a36Sopenharmony_ci{ 86462306a36Sopenharmony_ci u32 pll; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci gl9767_vhs_write(pdev); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 86962306a36Sopenharmony_ci pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV | 87062306a36Sopenharmony_ci PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV | 87162306a36Sopenharmony_ci PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN); 87262306a36Sopenharmony_ci pll |= FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV, ldiv) | 87362306a36Sopenharmony_ci FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV, pdiv) | 87462306a36Sopenharmony_ci FIELD_PREP(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN, dir); 87562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci gl9767_vhs_read(pdev); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* wait for pll stable */ 88062306a36Sopenharmony_ci usleep_range(1000, 1100); 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic void gl9767_set_ssc_pll_205mhz(struct pci_dev *pdev) 88462306a36Sopenharmony_ci{ 88562306a36Sopenharmony_ci bool enable = gl9767_ssc_enable(pdev); 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci /* set pll to 205MHz and ssc */ 88862306a36Sopenharmony_ci gl9767_set_ssc(pdev, enable, 0x1F, 0xF5C3); 88962306a36Sopenharmony_ci gl9767_set_pll(pdev, 0x1, 0x246, 0x0); 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic void gl9767_disable_ssc_pll(struct pci_dev *pdev) 89362306a36Sopenharmony_ci{ 89462306a36Sopenharmony_ci u32 pll; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci gl9767_vhs_write(pdev); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, &pll); 89962306a36Sopenharmony_ci pll &= ~(PCIE_GLI_9767_SD_PLL_CTL_PLL_DIR_EN | PCIE_GLI_9767_SD_PLL_CTL_SSC_EN); 90062306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_PLL_CTL, pll); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci gl9767_vhs_read(pdev); 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cistatic void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci struct sdhci_pci_slot *slot = sdhci_priv(host); 90862306a36Sopenharmony_ci struct mmc_ios *ios = &host->mmc->ios; 90962306a36Sopenharmony_ci struct pci_dev *pdev; 91062306a36Sopenharmony_ci u32 value; 91162306a36Sopenharmony_ci u16 clk; 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci pdev = slot->chip->pdev; 91462306a36Sopenharmony_ci host->mmc->actual_clock = 0; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci gl9767_vhs_write(pdev); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 91962306a36Sopenharmony_ci value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; 92062306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci gl9767_disable_ssc_pll(pdev); 92362306a36Sopenharmony_ci sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci if (clock == 0) 92662306a36Sopenharmony_ci return; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); 92962306a36Sopenharmony_ci if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { 93062306a36Sopenharmony_ci host->mmc->actual_clock = 205000000; 93162306a36Sopenharmony_ci gl9767_set_ssc_pll_205mhz(pdev); 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci sdhci_enable_clk(host, clk); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 93762306a36Sopenharmony_ci value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF; 93862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci gl9767_vhs_read(pdev); 94162306a36Sopenharmony_ci} 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_cistatic void gli_set_9767(struct sdhci_host *host) 94462306a36Sopenharmony_ci{ 94562306a36Sopenharmony_ci u32 value; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE); 94862306a36Sopenharmony_ci value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET; 94962306a36Sopenharmony_ci sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE); 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_cistatic void gl9767_hw_setting(struct sdhci_pci_slot *slot) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci struct pci_dev *pdev = slot->chip->pdev; 95562306a36Sopenharmony_ci u32 value; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci gl9767_vhs_write(pdev); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value); 96062306a36Sopenharmony_ci value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 96162306a36Sopenharmony_ci PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE | 96262306a36Sopenharmony_ci PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL); 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE | 96562306a36Sopenharmony_ci FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE, 96662306a36Sopenharmony_ci PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) | 96762306a36Sopenharmony_ci FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL, 96862306a36Sopenharmony_ci PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE); 96962306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value); 97262306a36Sopenharmony_ci value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 | 97362306a36Sopenharmony_ci PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 | 97462306a36Sopenharmony_ci PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST | 97762306a36Sopenharmony_ci PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST | 97862306a36Sopenharmony_ci PCIE_GLI_9767_SCR_AXI_REQ | 97962306a36Sopenharmony_ci PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN | 98062306a36Sopenharmony_ci PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF; 98162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci gl9767_vhs_read(pdev); 98462306a36Sopenharmony_ci} 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_cistatic void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci sdhci_reset(host, mask); 98962306a36Sopenharmony_ci gli_set_9767(host); 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci struct sdhci_host *host = mmc_priv(mmc); 99562306a36Sopenharmony_ci struct sdhci_pci_slot *slot = sdhci_priv(host); 99662306a36Sopenharmony_ci struct pci_dev *pdev; 99762306a36Sopenharmony_ci u32 value; 99862306a36Sopenharmony_ci int i; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci pdev = slot->chip->pdev; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (mmc->ops->get_ro(mmc)) { 100362306a36Sopenharmony_ci mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); 100462306a36Sopenharmony_ci return 0; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci gl9767_vhs_write(pdev); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value); 101062306a36Sopenharmony_ci value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN); 101162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value); 101462306a36Sopenharmony_ci value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME; 101562306a36Sopenharmony_ci value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME, 101662306a36Sopenharmony_ci PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE); 101762306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value); 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); 102062306a36Sopenharmony_ci value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE; 102162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value); 102462306a36Sopenharmony_ci value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN; 102562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value); 102862306a36Sopenharmony_ci value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN; 102962306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); 103262306a36Sopenharmony_ci value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; 103362306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 103662306a36Sopenharmony_ci value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); 103762306a36Sopenharmony_ci sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci value = sdhci_readb(host, SDHCI_POWER_CONTROL); 104062306a36Sopenharmony_ci value |= (SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); 104162306a36Sopenharmony_ci sdhci_writeb(host, value, SDHCI_POWER_CONTROL); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); 104462306a36Sopenharmony_ci value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE; 104562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci for (i = 0; i < 2; i++) { 104862306a36Sopenharmony_ci usleep_range(10000, 10100); 104962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); 105062306a36Sopenharmony_ci if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) { 105162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, 105262306a36Sopenharmony_ci value); 105362306a36Sopenharmony_ci break; 105462306a36Sopenharmony_ci } 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value); 105862306a36Sopenharmony_ci if (value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) { 105962306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); 106062306a36Sopenharmony_ci value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE; 106162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); 106262306a36Sopenharmony_ci } else { 106362306a36Sopenharmony_ci mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci value = sdhci_readb(host, SDHCI_POWER_CONTROL); 106662306a36Sopenharmony_ci value &= ~(SDHCI_VDD2_POWER_180 | SDHCI_VDD2_POWER_ON); 106762306a36Sopenharmony_ci sdhci_writeb(host, value, SDHCI_POWER_CONTROL); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 107062306a36Sopenharmony_ci value |= (SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); 107162306a36Sopenharmony_ci sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); 107262306a36Sopenharmony_ci } 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci gl9767_vhs_read(pdev); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci return 0; 107762306a36Sopenharmony_ci} 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_cistatic int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci gl9750_hw_setting(host); 108462306a36Sopenharmony_ci gli_pcie_enable_msi(slot); 108562306a36Sopenharmony_ci slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 108662306a36Sopenharmony_ci sdhci_enable_v4_mode(host); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci return 0; 108962306a36Sopenharmony_ci} 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_cistatic int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) 109262306a36Sopenharmony_ci{ 109362306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci gl9755_hw_setting(slot); 109662306a36Sopenharmony_ci gli_pcie_enable_msi(slot); 109762306a36Sopenharmony_ci slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 109862306a36Sopenharmony_ci sdhci_enable_v4_mode(host); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci return 0; 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot) 110462306a36Sopenharmony_ci{ 110562306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci gli_set_9767(host); 110862306a36Sopenharmony_ci gl9767_hw_setting(slot); 110962306a36Sopenharmony_ci gli_pcie_enable_msi(slot); 111062306a36Sopenharmony_ci slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 111162306a36Sopenharmony_ci host->mmc->caps2 |= MMC_CAP2_SD_EXP; 111262306a36Sopenharmony_ci host->mmc_host_ops.init_sd_express = gl9767_init_sd_express; 111362306a36Sopenharmony_ci sdhci_enable_v4_mode(host); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci return 0; 111662306a36Sopenharmony_ci} 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_cistatic void sdhci_gli_voltage_switch(struct sdhci_host *host) 111962306a36Sopenharmony_ci{ 112062306a36Sopenharmony_ci /* 112162306a36Sopenharmony_ci * According to Section 3.6.1 signal voltage switch procedure in 112262306a36Sopenharmony_ci * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 112362306a36Sopenharmony_ci * follows: 112462306a36Sopenharmony_ci * (6) Set 1.8V Signal Enable in the Host Control 2 register. 112562306a36Sopenharmony_ci * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 112662306a36Sopenharmony_ci * period. 112762306a36Sopenharmony_ci * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 112862306a36Sopenharmony_ci * step (12). 112962306a36Sopenharmony_ci * 113062306a36Sopenharmony_ci * Wait 5ms after set 1.8V signal enable in Host Control 2 register 113162306a36Sopenharmony_ci * to ensure 1.8V signal enable bit is set by GL9750/GL9755. 113262306a36Sopenharmony_ci * 113362306a36Sopenharmony_ci * ...however, the controller in the NUC10i3FNK4 (a 9755) requires 113462306a36Sopenharmony_ci * slightly longer than 5ms before the control register reports that 113562306a36Sopenharmony_ci * 1.8V is ready, and far longer still before the card will actually 113662306a36Sopenharmony_ci * work reliably. 113762306a36Sopenharmony_ci */ 113862306a36Sopenharmony_ci usleep_range(100000, 110000); 113962306a36Sopenharmony_ci} 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_cistatic void sdhci_gl9767_voltage_switch(struct sdhci_host *host) 114262306a36Sopenharmony_ci{ 114362306a36Sopenharmony_ci /* 114462306a36Sopenharmony_ci * According to Section 3.6.1 signal voltage switch procedure in 114562306a36Sopenharmony_ci * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 114662306a36Sopenharmony_ci * follows: 114762306a36Sopenharmony_ci * (6) Set 1.8V Signal Enable in the Host Control 2 register. 114862306a36Sopenharmony_ci * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 114962306a36Sopenharmony_ci * period. 115062306a36Sopenharmony_ci * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 115162306a36Sopenharmony_ci * step (12). 115262306a36Sopenharmony_ci * 115362306a36Sopenharmony_ci * Wait 5ms after set 1.8V signal enable in Host Control 2 register 115462306a36Sopenharmony_ci * to ensure 1.8V signal enable bit is set by GL9767. 115562306a36Sopenharmony_ci * 115662306a36Sopenharmony_ci */ 115762306a36Sopenharmony_ci usleep_range(5000, 5500); 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_cistatic void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask) 116162306a36Sopenharmony_ci{ 116262306a36Sopenharmony_ci sdhci_reset(host, mask); 116362306a36Sopenharmony_ci gli_set_9750(host); 116462306a36Sopenharmony_ci} 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_cistatic u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci u32 value; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci value = readl(host->ioaddr + reg); 117162306a36Sopenharmony_ci if (unlikely(reg == SDHCI_MAX_CURRENT && !(value & 0xff))) 117262306a36Sopenharmony_ci value |= 0xc8; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci return value; 117562306a36Sopenharmony_ci} 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_cistatic void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, 117862306a36Sopenharmony_ci struct mmc_ios *ios) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci struct sdhci_host *host = mmc_priv(mmc); 118162306a36Sopenharmony_ci u32 val; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG); 118462306a36Sopenharmony_ci if (ios->enhanced_strobe) 118562306a36Sopenharmony_ci val |= SDHCI_GLI_9763E_HS400_ES_BIT; 118662306a36Sopenharmony_ci else 118762306a36Sopenharmony_ci val &= ~SDHCI_GLI_9763E_HS400_ES_BIT; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); 119062306a36Sopenharmony_ci} 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_cistatic void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, 119362306a36Sopenharmony_ci bool enable) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci struct pci_dev *pdev = slot->chip->pdev; 119662306a36Sopenharmony_ci u32 value; 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 119962306a36Sopenharmony_ci value &= ~GLI_9763E_VHS_REV; 120062306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 120162306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci if (enable) 120662306a36Sopenharmony_ci value &= ~GLI_9763E_CFG_LPSN_DIS; 120762306a36Sopenharmony_ci else 120862306a36Sopenharmony_ci value |= GLI_9763E_CFG_LPSN_DIS; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 121362306a36Sopenharmony_ci value &= ~GLI_9763E_VHS_REV; 121462306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 121562306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistatic void sdhci_set_gl9763e_signaling(struct sdhci_host *host, 121962306a36Sopenharmony_ci unsigned int timing) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci u16 ctrl_2; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 122462306a36Sopenharmony_ci ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; 122562306a36Sopenharmony_ci if (timing == MMC_TIMING_MMC_HS200) 122662306a36Sopenharmony_ci ctrl_2 |= SDHCI_CTRL_UHS_SDR104; 122762306a36Sopenharmony_ci else if (timing == MMC_TIMING_MMC_HS) 122862306a36Sopenharmony_ci ctrl_2 |= SDHCI_CTRL_UHS_SDR25; 122962306a36Sopenharmony_ci else if (timing == MMC_TIMING_MMC_DDR52) 123062306a36Sopenharmony_ci ctrl_2 |= SDHCI_CTRL_UHS_DDR50; 123162306a36Sopenharmony_ci else if (timing == MMC_TIMING_MMC_HS400) 123262306a36Sopenharmony_ci ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); 123562306a36Sopenharmony_ci} 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_cistatic void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) 123862306a36Sopenharmony_ci{ 123962306a36Sopenharmony_ci sdhci_dumpregs(mmc_priv(mmc)); 124062306a36Sopenharmony_ci} 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_cistatic void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) 124362306a36Sopenharmony_ci{ 124462306a36Sopenharmony_ci struct cqhci_host *cq_host = mmc->cqe_private; 124562306a36Sopenharmony_ci u32 value; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci value = cqhci_readl(cq_host, CQHCI_CFG); 124862306a36Sopenharmony_ci value |= CQHCI_ENABLE; 124962306a36Sopenharmony_ci cqhci_writel(cq_host, value, CQHCI_CFG); 125062306a36Sopenharmony_ci} 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_cistatic void sdhci_gl9763e_cqe_enable(struct mmc_host *mmc) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci struct sdhci_host *host = mmc_priv(mmc); 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci sdhci_writew(host, GLI_9763E_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); 125762306a36Sopenharmony_ci sdhci_cqe_enable(mmc); 125862306a36Sopenharmony_ci} 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_cistatic u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask) 126162306a36Sopenharmony_ci{ 126262306a36Sopenharmony_ci int cmd_error = 0; 126362306a36Sopenharmony_ci int data_error = 0; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) 126662306a36Sopenharmony_ci return intmask; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci cqhci_irq(host->mmc, intmask, cmd_error, data_error); 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci return 0; 127162306a36Sopenharmony_ci} 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_cistatic void sdhci_gl9763e_cqe_post_disable(struct mmc_host *mmc) 127462306a36Sopenharmony_ci{ 127562306a36Sopenharmony_ci struct sdhci_host *host = mmc_priv(mmc); 127662306a36Sopenharmony_ci struct cqhci_host *cq_host = mmc->cqe_private; 127762306a36Sopenharmony_ci u32 value; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci value = cqhci_readl(cq_host, CQHCI_CFG); 128062306a36Sopenharmony_ci value &= ~CQHCI_ENABLE; 128162306a36Sopenharmony_ci cqhci_writel(cq_host, value, CQHCI_CFG); 128262306a36Sopenharmony_ci sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); 128362306a36Sopenharmony_ci} 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_cistatic const struct cqhci_host_ops sdhci_gl9763e_cqhci_ops = { 128662306a36Sopenharmony_ci .enable = sdhci_gl9763e_cqe_enable, 128762306a36Sopenharmony_ci .disable = sdhci_cqe_disable, 128862306a36Sopenharmony_ci .dumpregs = sdhci_gl9763e_dumpregs, 128962306a36Sopenharmony_ci .pre_enable = sdhci_gl9763e_cqe_pre_enable, 129062306a36Sopenharmony_ci .post_disable = sdhci_gl9763e_cqe_post_disable, 129162306a36Sopenharmony_ci}; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_cistatic int gl9763e_add_host(struct sdhci_pci_slot *slot) 129462306a36Sopenharmony_ci{ 129562306a36Sopenharmony_ci struct device *dev = &slot->chip->pdev->dev; 129662306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 129762306a36Sopenharmony_ci struct cqhci_host *cq_host; 129862306a36Sopenharmony_ci bool dma64; 129962306a36Sopenharmony_ci int ret; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci ret = sdhci_setup_host(host); 130262306a36Sopenharmony_ci if (ret) 130362306a36Sopenharmony_ci return ret; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci cq_host = devm_kzalloc(dev, sizeof(*cq_host), GFP_KERNEL); 130662306a36Sopenharmony_ci if (!cq_host) { 130762306a36Sopenharmony_ci ret = -ENOMEM; 130862306a36Sopenharmony_ci goto cleanup; 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci cq_host->mmio = host->ioaddr + SDHCI_GLI_9763E_CQE_BASE_ADDR; 131262306a36Sopenharmony_ci cq_host->ops = &sdhci_gl9763e_cqhci_ops; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci dma64 = host->flags & SDHCI_USE_64_BIT_DMA; 131562306a36Sopenharmony_ci if (dma64) 131662306a36Sopenharmony_ci cq_host->caps |= CQHCI_TASK_DESC_SZ_128; 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci ret = cqhci_init(cq_host, host->mmc, dma64); 131962306a36Sopenharmony_ci if (ret) 132062306a36Sopenharmony_ci goto cleanup; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci ret = __sdhci_add_host(host); 132362306a36Sopenharmony_ci if (ret) 132462306a36Sopenharmony_ci goto cleanup; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci /* Disable LPM negotiation to avoid entering L1 state. */ 132762306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, false); 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci return 0; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cicleanup: 133262306a36Sopenharmony_ci sdhci_cleanup_host(host); 133362306a36Sopenharmony_ci return ret; 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_cistatic void gli_set_gl9763e(struct sdhci_pci_slot *slot) 133762306a36Sopenharmony_ci{ 133862306a36Sopenharmony_ci struct pci_dev *pdev = slot->chip->pdev; 133962306a36Sopenharmony_ci u32 value; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 134262306a36Sopenharmony_ci value &= ~GLI_9763E_VHS_REV; 134362306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); 134462306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value); 134762306a36Sopenharmony_ci value |= GLI_9763E_SCR_AXI_REQ; 134862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, &value); 135162306a36Sopenharmony_ci value &= ~GLI_9763E_HS400_SLOW; 135262306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, value); 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value); 135562306a36Sopenharmony_ci value &= ~GLI_9763E_CFG2_L1DLY; 135662306a36Sopenharmony_ci /* set ASPM L1 entry delay to 21us */ 135762306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); 135862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); 136162306a36Sopenharmony_ci value &= ~GLI_9763E_HS400_RXDLY; 136262306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); 136362306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); 136662306a36Sopenharmony_ci value &= ~GLI_9763E_VHS_REV; 136762306a36Sopenharmony_ci value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); 136862306a36Sopenharmony_ci pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); 136962306a36Sopenharmony_ci} 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci#ifdef CONFIG_PM 137262306a36Sopenharmony_cistatic int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) 137362306a36Sopenharmony_ci{ 137462306a36Sopenharmony_ci struct sdhci_pci_slot *slot = chip->slots[0]; 137562306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 137662306a36Sopenharmony_ci u16 clock; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* Enable LPM negotiation to allow entering L1 state */ 137962306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, true); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 138262306a36Sopenharmony_ci clock &= ~(SDHCI_CLOCK_PLL_EN | SDHCI_CLOCK_CARD_EN); 138362306a36Sopenharmony_ci sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci return 0; 138662306a36Sopenharmony_ci} 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_cistatic int gl9763e_runtime_resume(struct sdhci_pci_chip *chip) 138962306a36Sopenharmony_ci{ 139062306a36Sopenharmony_ci struct sdhci_pci_slot *slot = chip->slots[0]; 139162306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 139262306a36Sopenharmony_ci u16 clock; 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci if (host->mmc->ios.power_mode != MMC_POWER_ON) 139562306a36Sopenharmony_ci return 0; 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci clock |= SDHCI_CLOCK_PLL_EN; 140062306a36Sopenharmony_ci clock &= ~SDHCI_CLOCK_INT_STABLE; 140162306a36Sopenharmony_ci sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* Wait max 150 ms */ 140462306a36Sopenharmony_ci if (read_poll_timeout(sdhci_readw, clock, (clock & SDHCI_CLOCK_INT_STABLE), 140562306a36Sopenharmony_ci 1000, 150000, false, host, SDHCI_CLOCK_CONTROL)) { 140662306a36Sopenharmony_ci pr_err("%s: PLL clock never stabilised.\n", 140762306a36Sopenharmony_ci mmc_hostname(host->mmc)); 140862306a36Sopenharmony_ci sdhci_dumpregs(host); 140962306a36Sopenharmony_ci } 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci clock |= SDHCI_CLOCK_CARD_EN; 141262306a36Sopenharmony_ci sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci /* Disable LPM negotiation to avoid entering L1 state. */ 141562306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, false); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci return 0; 141862306a36Sopenharmony_ci} 141962306a36Sopenharmony_ci#endif 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 142262306a36Sopenharmony_cistatic int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) 142362306a36Sopenharmony_ci{ 142462306a36Sopenharmony_ci struct sdhci_pci_slot *slot = chip->slots[0]; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci pci_free_irq_vectors(slot->chip->pdev); 142762306a36Sopenharmony_ci gli_pcie_enable_msi(slot); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci return sdhci_pci_resume_host(chip); 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cistatic int gl9763e_resume(struct sdhci_pci_chip *chip) 143362306a36Sopenharmony_ci{ 143462306a36Sopenharmony_ci struct sdhci_pci_slot *slot = chip->slots[0]; 143562306a36Sopenharmony_ci int ret; 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci ret = sdhci_pci_gli_resume(chip); 143862306a36Sopenharmony_ci if (ret) 143962306a36Sopenharmony_ci return ret; 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci ret = cqhci_resume(slot->host->mmc); 144262306a36Sopenharmony_ci if (ret) 144362306a36Sopenharmony_ci return ret; 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci /* 144662306a36Sopenharmony_ci * Disable LPM negotiation to bring device back in sync 144762306a36Sopenharmony_ci * with its runtime_pm state. 144862306a36Sopenharmony_ci */ 144962306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, false); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci return 0; 145262306a36Sopenharmony_ci} 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_cistatic int gl9763e_suspend(struct sdhci_pci_chip *chip) 145562306a36Sopenharmony_ci{ 145662306a36Sopenharmony_ci struct sdhci_pci_slot *slot = chip->slots[0]; 145762306a36Sopenharmony_ci int ret; 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci /* 146062306a36Sopenharmony_ci * Certain SoCs can suspend only with the bus in low- 146162306a36Sopenharmony_ci * power state, notably x86 SoCs when using S0ix. 146262306a36Sopenharmony_ci * Re-enable LPM negotiation to allow entering L1 state 146362306a36Sopenharmony_ci * and entering system suspend. 146462306a36Sopenharmony_ci */ 146562306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, true); 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci ret = cqhci_suspend(slot->host->mmc); 146862306a36Sopenharmony_ci if (ret) 146962306a36Sopenharmony_ci goto err_suspend; 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci ret = sdhci_suspend_host(slot->host); 147262306a36Sopenharmony_ci if (ret) 147362306a36Sopenharmony_ci goto err_suspend_host; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci return 0; 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_cierr_suspend_host: 147862306a36Sopenharmony_ci cqhci_resume(slot->host->mmc); 147962306a36Sopenharmony_cierr_suspend: 148062306a36Sopenharmony_ci gl9763e_set_low_power_negotiation(slot, false); 148162306a36Sopenharmony_ci return ret; 148262306a36Sopenharmony_ci} 148362306a36Sopenharmony_ci#endif 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_cistatic int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) 148662306a36Sopenharmony_ci{ 148762306a36Sopenharmony_ci struct pci_dev *pdev = slot->chip->pdev; 148862306a36Sopenharmony_ci struct sdhci_host *host = slot->host; 148962306a36Sopenharmony_ci u32 value; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci host->mmc->caps |= MMC_CAP_8_BIT_DATA | 149262306a36Sopenharmony_ci MMC_CAP_1_8V_DDR | 149362306a36Sopenharmony_ci MMC_CAP_NONREMOVABLE; 149462306a36Sopenharmony_ci host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR | 149562306a36Sopenharmony_ci MMC_CAP2_HS400_1_8V | 149662306a36Sopenharmony_ci MMC_CAP2_HS400_ES | 149762306a36Sopenharmony_ci MMC_CAP2_NO_SDIO | 149862306a36Sopenharmony_ci MMC_CAP2_NO_SD; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci pci_read_config_dword(pdev, PCIE_GLI_9763E_MB, &value); 150162306a36Sopenharmony_ci if (!(value & GLI_9763E_MB_CMDQ_OFF)) 150262306a36Sopenharmony_ci if (value & GLI_9763E_MB_ERP_ON) 150362306a36Sopenharmony_ci host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci gli_pcie_enable_msi(slot); 150662306a36Sopenharmony_ci host->mmc_host_ops.hs400_enhanced_strobe = 150762306a36Sopenharmony_ci gl9763e_hs400_enhanced_strobe; 150862306a36Sopenharmony_ci gli_set_gl9763e(slot); 150962306a36Sopenharmony_ci sdhci_enable_v4_mode(host); 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci return 0; 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci#define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18) 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_cistatic u16 sdhci_gli_readw(struct sdhci_host *host, int reg) 151762306a36Sopenharmony_ci{ 151862306a36Sopenharmony_ci u32 val = readl(host->ioaddr + (reg & ~3)); 151962306a36Sopenharmony_ci u16 word; 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci word = (val >> REG_OFFSET_IN_BITS(reg)) & 0xffff; 152262306a36Sopenharmony_ci return word; 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_cistatic u8 sdhci_gli_readb(struct sdhci_host *host, int reg) 152662306a36Sopenharmony_ci{ 152762306a36Sopenharmony_ci u32 val = readl(host->ioaddr + (reg & ~3)); 152862306a36Sopenharmony_ci u8 byte = (val >> REG_OFFSET_IN_BITS(reg)) & 0xff; 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci return byte; 153162306a36Sopenharmony_ci} 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_cistatic const struct sdhci_ops sdhci_gl9755_ops = { 153462306a36Sopenharmony_ci .read_w = sdhci_gli_readw, 153562306a36Sopenharmony_ci .read_b = sdhci_gli_readb, 153662306a36Sopenharmony_ci .set_clock = sdhci_gl9755_set_clock, 153762306a36Sopenharmony_ci .enable_dma = sdhci_pci_enable_dma, 153862306a36Sopenharmony_ci .set_bus_width = sdhci_set_bus_width, 153962306a36Sopenharmony_ci .reset = sdhci_reset, 154062306a36Sopenharmony_ci .set_uhs_signaling = sdhci_set_uhs_signaling, 154162306a36Sopenharmony_ci .voltage_switch = sdhci_gli_voltage_switch, 154262306a36Sopenharmony_ci}; 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ciconst struct sdhci_pci_fixes sdhci_gl9755 = { 154562306a36Sopenharmony_ci .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 154662306a36Sopenharmony_ci .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 154762306a36Sopenharmony_ci .probe_slot = gli_probe_slot_gl9755, 154862306a36Sopenharmony_ci .ops = &sdhci_gl9755_ops, 154962306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 155062306a36Sopenharmony_ci .resume = sdhci_pci_gli_resume, 155162306a36Sopenharmony_ci#endif 155262306a36Sopenharmony_ci}; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_cistatic const struct sdhci_ops sdhci_gl9750_ops = { 155562306a36Sopenharmony_ci .read_w = sdhci_gli_readw, 155662306a36Sopenharmony_ci .read_b = sdhci_gli_readb, 155762306a36Sopenharmony_ci .read_l = sdhci_gl9750_readl, 155862306a36Sopenharmony_ci .set_clock = sdhci_gl9750_set_clock, 155962306a36Sopenharmony_ci .enable_dma = sdhci_pci_enable_dma, 156062306a36Sopenharmony_ci .set_bus_width = sdhci_set_bus_width, 156162306a36Sopenharmony_ci .reset = sdhci_gl9750_reset, 156262306a36Sopenharmony_ci .set_uhs_signaling = sdhci_set_uhs_signaling, 156362306a36Sopenharmony_ci .voltage_switch = sdhci_gli_voltage_switch, 156462306a36Sopenharmony_ci .platform_execute_tuning = gl9750_execute_tuning, 156562306a36Sopenharmony_ci}; 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ciconst struct sdhci_pci_fixes sdhci_gl9750 = { 156862306a36Sopenharmony_ci .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 156962306a36Sopenharmony_ci .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 157062306a36Sopenharmony_ci .probe_slot = gli_probe_slot_gl9750, 157162306a36Sopenharmony_ci .ops = &sdhci_gl9750_ops, 157262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 157362306a36Sopenharmony_ci .resume = sdhci_pci_gli_resume, 157462306a36Sopenharmony_ci#endif 157562306a36Sopenharmony_ci}; 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_cistatic const struct sdhci_ops sdhci_gl9763e_ops = { 157862306a36Sopenharmony_ci .set_clock = sdhci_set_clock, 157962306a36Sopenharmony_ci .enable_dma = sdhci_pci_enable_dma, 158062306a36Sopenharmony_ci .set_bus_width = sdhci_set_bus_width, 158162306a36Sopenharmony_ci .reset = sdhci_and_cqhci_reset, 158262306a36Sopenharmony_ci .set_uhs_signaling = sdhci_set_gl9763e_signaling, 158362306a36Sopenharmony_ci .voltage_switch = sdhci_gli_voltage_switch, 158462306a36Sopenharmony_ci .irq = sdhci_gl9763e_cqhci_irq, 158562306a36Sopenharmony_ci}; 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ciconst struct sdhci_pci_fixes sdhci_gl9763e = { 158862306a36Sopenharmony_ci .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 158962306a36Sopenharmony_ci .probe_slot = gli_probe_slot_gl9763e, 159062306a36Sopenharmony_ci .ops = &sdhci_gl9763e_ops, 159162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 159262306a36Sopenharmony_ci .resume = gl9763e_resume, 159362306a36Sopenharmony_ci .suspend = gl9763e_suspend, 159462306a36Sopenharmony_ci#endif 159562306a36Sopenharmony_ci#ifdef CONFIG_PM 159662306a36Sopenharmony_ci .runtime_suspend = gl9763e_runtime_suspend, 159762306a36Sopenharmony_ci .runtime_resume = gl9763e_runtime_resume, 159862306a36Sopenharmony_ci .allow_runtime_pm = true, 159962306a36Sopenharmony_ci#endif 160062306a36Sopenharmony_ci .add_host = gl9763e_add_host, 160162306a36Sopenharmony_ci}; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_cistatic const struct sdhci_ops sdhci_gl9767_ops = { 160462306a36Sopenharmony_ci .set_clock = sdhci_gl9767_set_clock, 160562306a36Sopenharmony_ci .enable_dma = sdhci_pci_enable_dma, 160662306a36Sopenharmony_ci .set_bus_width = sdhci_set_bus_width, 160762306a36Sopenharmony_ci .reset = sdhci_gl9767_reset, 160862306a36Sopenharmony_ci .set_uhs_signaling = sdhci_set_uhs_signaling, 160962306a36Sopenharmony_ci .voltage_switch = sdhci_gl9767_voltage_switch, 161062306a36Sopenharmony_ci}; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ciconst struct sdhci_pci_fixes sdhci_gl9767 = { 161362306a36Sopenharmony_ci .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 161462306a36Sopenharmony_ci .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 161562306a36Sopenharmony_ci .probe_slot = gli_probe_slot_gl9767, 161662306a36Sopenharmony_ci .ops = &sdhci_gl9767_ops, 161762306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 161862306a36Sopenharmony_ci .resume = sdhci_pci_gli_resume, 161962306a36Sopenharmony_ci#endif 162062306a36Sopenharmony_ci}; 1621