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