xref: /OK3568_Linux_fs/kernel/drivers/mmc/host/sdhci-pci-gli.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2019 Genesys Logic, Inc.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Version: v0.9.0 (2019-08-08)
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/bitfield.h>
11*4882a593Smuzhiyun #include <linux/bits.h>
12*4882a593Smuzhiyun #include <linux/pci.h>
13*4882a593Smuzhiyun #include <linux/mmc/mmc.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include "sdhci.h"
16*4882a593Smuzhiyun #include "sdhci-pci.h"
17*4882a593Smuzhiyun #include "cqhci.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*  Genesys Logic extra registers */
20*4882a593Smuzhiyun #define SDHCI_GLI_9750_WT         0x800
21*4882a593Smuzhiyun #define   SDHCI_GLI_9750_WT_EN      BIT(0)
22*4882a593Smuzhiyun #define   GLI_9750_WT_EN_ON	    0x1
23*4882a593Smuzhiyun #define   GLI_9750_WT_EN_OFF	    0x0
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define SDHCI_GLI_9750_DRIVING      0x860
26*4882a593Smuzhiyun #define   SDHCI_GLI_9750_DRIVING_1    GENMASK(11, 0)
27*4882a593Smuzhiyun #define   SDHCI_GLI_9750_DRIVING_2    GENMASK(27, 26)
28*4882a593Smuzhiyun #define   GLI_9750_DRIVING_1_VALUE    0xFFF
29*4882a593Smuzhiyun #define   GLI_9750_DRIVING_2_VALUE    0x3
30*4882a593Smuzhiyun #define   SDHCI_GLI_9750_SEL_1        BIT(29)
31*4882a593Smuzhiyun #define   SDHCI_GLI_9750_SEL_2        BIT(31)
32*4882a593Smuzhiyun #define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define SDHCI_GLI_9750_PLL	      0x864
35*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLL_LDIV       GENMASK(9, 0)
36*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLL_PDIV       GENMASK(14, 12)
37*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLL_DIR        BIT(15)
38*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
39*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLL_TX2_DLY    GENMASK(22, 20)
40*4882a593Smuzhiyun #define   GLI_9750_PLL_TX2_INV_VALUE    0x1
41*4882a593Smuzhiyun #define   GLI_9750_PLL_TX2_DLY_VALUE    0x0
42*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLLSSC_STEP    GENMASK(28, 24)
43*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLLSSC_EN      BIT(31)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define SDHCI_GLI_9750_PLLSSC        0x86C
46*4882a593Smuzhiyun #define   SDHCI_GLI_9750_PLLSSC_PPM    GENMASK(31, 16)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define SDHCI_GLI_9750_SW_CTRL      0x874
49*4882a593Smuzhiyun #define   SDHCI_GLI_9750_SW_CTRL_4    GENMASK(7, 6)
50*4882a593Smuzhiyun #define   GLI_9750_SW_CTRL_4_VALUE    0x3
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #define SDHCI_GLI_9750_MISC            0x878
53*4882a593Smuzhiyun #define   SDHCI_GLI_9750_MISC_TX1_INV    BIT(2)
54*4882a593Smuzhiyun #define   SDHCI_GLI_9750_MISC_RX_INV     BIT(3)
55*4882a593Smuzhiyun #define   SDHCI_GLI_9750_MISC_TX1_DLY    GENMASK(6, 4)
56*4882a593Smuzhiyun #define   GLI_9750_MISC_TX1_INV_VALUE    0x0
57*4882a593Smuzhiyun #define   GLI_9750_MISC_RX_INV_ON        0x1
58*4882a593Smuzhiyun #define   GLI_9750_MISC_RX_INV_OFF       0x0
59*4882a593Smuzhiyun #define   GLI_9750_MISC_RX_INV_VALUE     GLI_9750_MISC_RX_INV_OFF
60*4882a593Smuzhiyun #define   GLI_9750_MISC_TX1_DLY_VALUE    0x5
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define SDHCI_GLI_9750_TUNING_CONTROL	          0x540
63*4882a593Smuzhiyun #define   SDHCI_GLI_9750_TUNING_CONTROL_EN          BIT(4)
64*4882a593Smuzhiyun #define   GLI_9750_TUNING_CONTROL_EN_ON             0x1
65*4882a593Smuzhiyun #define   GLI_9750_TUNING_CONTROL_EN_OFF            0x0
66*4882a593Smuzhiyun #define   SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1    BIT(16)
67*4882a593Smuzhiyun #define   SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2    GENMASK(20, 19)
68*4882a593Smuzhiyun #define   GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE    0x1
69*4882a593Smuzhiyun #define   GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE    0x2
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define SDHCI_GLI_9750_TUNING_PARAMETERS           0x544
72*4882a593Smuzhiyun #define   SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY    GENMASK(2, 0)
73*4882a593Smuzhiyun #define   GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE    0x1
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define SDHCI_GLI_9763E_CTRL_HS400  0x7
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define SDHCI_GLI_9763E_HS400_ES_REG      0x52C
78*4882a593Smuzhiyun #define   SDHCI_GLI_9763E_HS400_ES_BIT      BIT(8)
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define PCIE_GLI_9763E_VHS	 0x884
81*4882a593Smuzhiyun #define   GLI_9763E_VHS_REV	   GENMASK(19, 16)
82*4882a593Smuzhiyun #define   GLI_9763E_VHS_REV_R      0x0
83*4882a593Smuzhiyun #define   GLI_9763E_VHS_REV_M      0x1
84*4882a593Smuzhiyun #define   GLI_9763E_VHS_REV_W      0x2
85*4882a593Smuzhiyun #define PCIE_GLI_9763E_MB	 0x888
86*4882a593Smuzhiyun #define   GLI_9763E_MB_CMDQ_OFF	   BIT(19)
87*4882a593Smuzhiyun #define PCIE_GLI_9763E_SCR	 0x8E0
88*4882a593Smuzhiyun #define   GLI_9763E_SCR_AXI_REQ	   BIT(9)
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun #define SDHCI_GLI_9763E_CQE_BASE_ADDR	 0x200
91*4882a593Smuzhiyun #define GLI_9763E_CQE_TRNS_MODE	   (SDHCI_TRNS_MULTI | \
92*4882a593Smuzhiyun 				    SDHCI_TRNS_BLK_CNT_EN | \
93*4882a593Smuzhiyun 				    SDHCI_TRNS_DMA)
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #define PCI_GLI_9755_WT       0x800
96*4882a593Smuzhiyun #define   PCI_GLI_9755_WT_EN    BIT(0)
97*4882a593Smuzhiyun #define   GLI_9755_WT_EN_ON     0x1
98*4882a593Smuzhiyun #define   GLI_9755_WT_EN_OFF    0x0
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun #define PCI_GLI_9755_PLL            0x64
101*4882a593Smuzhiyun #define   PCI_GLI_9755_PLL_LDIV       GENMASK(9, 0)
102*4882a593Smuzhiyun #define   PCI_GLI_9755_PLL_PDIV       GENMASK(14, 12)
103*4882a593Smuzhiyun #define   PCI_GLI_9755_PLL_DIR        BIT(15)
104*4882a593Smuzhiyun #define   PCI_GLI_9755_PLLSSC_STEP    GENMASK(28, 24)
105*4882a593Smuzhiyun #define   PCI_GLI_9755_PLLSSC_EN      BIT(31)
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun #define PCI_GLI_9755_PLLSSC        0x68
108*4882a593Smuzhiyun #define   PCI_GLI_9755_PLLSSC_PPM    GENMASK(15, 0)
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun #define GLI_MAX_TUNING_LOOP 40
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /* Genesys Logic chipset */
gl9750_wt_on(struct sdhci_host * host)113*4882a593Smuzhiyun static inline void gl9750_wt_on(struct sdhci_host *host)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	u32 wt_value;
116*4882a593Smuzhiyun 	u32 wt_enable;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT);
119*4882a593Smuzhiyun 	wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	if (wt_enable == GLI_9750_WT_EN_ON)
122*4882a593Smuzhiyun 		return;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	wt_value &= ~SDHCI_GLI_9750_WT_EN;
125*4882a593Smuzhiyun 	wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_ON);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
gl9750_wt_off(struct sdhci_host * host)130*4882a593Smuzhiyun static inline void gl9750_wt_off(struct sdhci_host *host)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	u32 wt_value;
133*4882a593Smuzhiyun 	u32 wt_enable;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT);
136*4882a593Smuzhiyun 	wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	if (wt_enable == GLI_9750_WT_EN_OFF)
139*4882a593Smuzhiyun 		return;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	wt_value &= ~SDHCI_GLI_9750_WT_EN;
142*4882a593Smuzhiyun 	wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_OFF);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
gli_set_9750(struct sdhci_host * host)147*4882a593Smuzhiyun static void gli_set_9750(struct sdhci_host *host)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	u32 driving_value;
150*4882a593Smuzhiyun 	u32 pll_value;
151*4882a593Smuzhiyun 	u32 sw_ctrl_value;
152*4882a593Smuzhiyun 	u32 misc_value;
153*4882a593Smuzhiyun 	u32 parameter_value;
154*4882a593Smuzhiyun 	u32 control_value;
155*4882a593Smuzhiyun 	u16 ctrl2;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	gl9750_wt_on(host);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING);
160*4882a593Smuzhiyun 	pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL);
161*4882a593Smuzhiyun 	sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL);
162*4882a593Smuzhiyun 	misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC);
163*4882a593Smuzhiyun 	parameter_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_PARAMETERS);
164*4882a593Smuzhiyun 	control_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_CONTROL);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	driving_value &= ~(SDHCI_GLI_9750_DRIVING_1);
167*4882a593Smuzhiyun 	driving_value &= ~(SDHCI_GLI_9750_DRIVING_2);
168*4882a593Smuzhiyun 	driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1,
169*4882a593Smuzhiyun 				    GLI_9750_DRIVING_1_VALUE);
170*4882a593Smuzhiyun 	driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2,
171*4882a593Smuzhiyun 				    GLI_9750_DRIVING_2_VALUE);
172*4882a593Smuzhiyun 	driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST);
173*4882a593Smuzhiyun 	driving_value |= SDHCI_GLI_9750_SEL_2;
174*4882a593Smuzhiyun 	sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4;
177*4882a593Smuzhiyun 	sw_ctrl_value |= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4,
178*4882a593Smuzhiyun 				    GLI_9750_SW_CTRL_4_VALUE);
179*4882a593Smuzhiyun 	sdhci_writel(host, sw_ctrl_value, SDHCI_GLI_9750_SW_CTRL);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	/* reset the tuning flow after reinit and before starting tuning */
182*4882a593Smuzhiyun 	pll_value &= ~SDHCI_GLI_9750_PLL_TX2_INV;
183*4882a593Smuzhiyun 	pll_value &= ~SDHCI_GLI_9750_PLL_TX2_DLY;
184*4882a593Smuzhiyun 	pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV,
185*4882a593Smuzhiyun 				GLI_9750_PLL_TX2_INV_VALUE);
186*4882a593Smuzhiyun 	pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY,
187*4882a593Smuzhiyun 				GLI_9750_PLL_TX2_DLY_VALUE);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	misc_value &= ~SDHCI_GLI_9750_MISC_TX1_INV;
190*4882a593Smuzhiyun 	misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV;
191*4882a593Smuzhiyun 	misc_value &= ~SDHCI_GLI_9750_MISC_TX1_DLY;
192*4882a593Smuzhiyun 	misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV,
193*4882a593Smuzhiyun 				 GLI_9750_MISC_TX1_INV_VALUE);
194*4882a593Smuzhiyun 	misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV,
195*4882a593Smuzhiyun 				 GLI_9750_MISC_RX_INV_VALUE);
196*4882a593Smuzhiyun 	misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY,
197*4882a593Smuzhiyun 				 GLI_9750_MISC_TX1_DLY_VALUE);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	parameter_value &= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY;
200*4882a593Smuzhiyun 	parameter_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY,
201*4882a593Smuzhiyun 				      GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1;
204*4882a593Smuzhiyun 	control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2;
205*4882a593Smuzhiyun 	control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1,
206*4882a593Smuzhiyun 				    GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE);
207*4882a593Smuzhiyun 	control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2,
208*4882a593Smuzhiyun 				    GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	sdhci_writel(host, pll_value, SDHCI_GLI_9750_PLL);
211*4882a593Smuzhiyun 	sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	/* disable tuned clk */
214*4882a593Smuzhiyun 	ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
215*4882a593Smuzhiyun 	ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
216*4882a593Smuzhiyun 	sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* enable tuning parameters control */
219*4882a593Smuzhiyun 	control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN;
220*4882a593Smuzhiyun 	control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN,
221*4882a593Smuzhiyun 				    GLI_9750_TUNING_CONTROL_EN_ON);
222*4882a593Smuzhiyun 	sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	/* write tuning parameters */
225*4882a593Smuzhiyun 	sdhci_writel(host, parameter_value, SDHCI_GLI_9750_TUNING_PARAMETERS);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	/* disable tuning parameters control */
228*4882a593Smuzhiyun 	control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN;
229*4882a593Smuzhiyun 	control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN,
230*4882a593Smuzhiyun 				    GLI_9750_TUNING_CONTROL_EN_OFF);
231*4882a593Smuzhiyun 	sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	/* clear tuned clk */
234*4882a593Smuzhiyun 	ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
235*4882a593Smuzhiyun 	ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
236*4882a593Smuzhiyun 	sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	gl9750_wt_off(host);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
gli_set_9750_rx_inv(struct sdhci_host * host,bool b)241*4882a593Smuzhiyun static void gli_set_9750_rx_inv(struct sdhci_host *host, bool b)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	u32 misc_value;
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	gl9750_wt_on(host);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC);
248*4882a593Smuzhiyun 	misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV;
249*4882a593Smuzhiyun 	if (b) {
250*4882a593Smuzhiyun 		misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV,
251*4882a593Smuzhiyun 					 GLI_9750_MISC_RX_INV_ON);
252*4882a593Smuzhiyun 	} else {
253*4882a593Smuzhiyun 		misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV,
254*4882a593Smuzhiyun 					 GLI_9750_MISC_RX_INV_OFF);
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	gl9750_wt_off(host);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
__sdhci_execute_tuning_9750(struct sdhci_host * host,u32 opcode)261*4882a593Smuzhiyun static int __sdhci_execute_tuning_9750(struct sdhci_host *host, u32 opcode)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun 	int i;
264*4882a593Smuzhiyun 	int rx_inv;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	for (rx_inv = 0; rx_inv < 2; rx_inv++) {
267*4882a593Smuzhiyun 		gli_set_9750_rx_inv(host, !!rx_inv);
268*4882a593Smuzhiyun 		sdhci_start_tuning(host);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 		for (i = 0; i < GLI_MAX_TUNING_LOOP; i++) {
271*4882a593Smuzhiyun 			u16 ctrl;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 			sdhci_send_tuning(host, opcode);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 			if (!host->tuning_done) {
276*4882a593Smuzhiyun 				sdhci_abort_tuning(host, opcode);
277*4882a593Smuzhiyun 				break;
278*4882a593Smuzhiyun 			}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 			ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
281*4882a593Smuzhiyun 			if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
282*4882a593Smuzhiyun 				if (ctrl & SDHCI_CTRL_TUNED_CLK)
283*4882a593Smuzhiyun 					return 0; /* Success! */
284*4882a593Smuzhiyun 				break;
285*4882a593Smuzhiyun 			}
286*4882a593Smuzhiyun 		}
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 	if (!host->tuning_done) {
289*4882a593Smuzhiyun 		pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
290*4882a593Smuzhiyun 			mmc_hostname(host->mmc));
291*4882a593Smuzhiyun 		return -ETIMEDOUT;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
295*4882a593Smuzhiyun 		mmc_hostname(host->mmc));
296*4882a593Smuzhiyun 	sdhci_reset_tuning(host);
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	return -EAGAIN;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
gl9750_execute_tuning(struct sdhci_host * host,u32 opcode)301*4882a593Smuzhiyun static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
302*4882a593Smuzhiyun {
303*4882a593Smuzhiyun 	host->mmc->retune_period = 0;
304*4882a593Smuzhiyun 	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
305*4882a593Smuzhiyun 		host->mmc->retune_period = host->tuning_count;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	gli_set_9750(host);
308*4882a593Smuzhiyun 	host->tuning_err = __sdhci_execute_tuning_9750(host, opcode);
309*4882a593Smuzhiyun 	sdhci_end_tuning(host);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	return 0;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
gl9750_disable_ssc_pll(struct sdhci_host * host)314*4882a593Smuzhiyun static void gl9750_disable_ssc_pll(struct sdhci_host *host)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	u32 pll;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	gl9750_wt_on(host);
319*4882a593Smuzhiyun 	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
320*4882a593Smuzhiyun 	pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
321*4882a593Smuzhiyun 	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
322*4882a593Smuzhiyun 	gl9750_wt_off(host);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
gl9750_set_pll(struct sdhci_host * host,u8 dir,u16 ldiv,u8 pdiv)325*4882a593Smuzhiyun static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	u32 pll;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	gl9750_wt_on(host);
330*4882a593Smuzhiyun 	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
331*4882a593Smuzhiyun 	pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
332*4882a593Smuzhiyun 		 SDHCI_GLI_9750_PLL_PDIV |
333*4882a593Smuzhiyun 		 SDHCI_GLI_9750_PLL_DIR);
334*4882a593Smuzhiyun 	pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
335*4882a593Smuzhiyun 	       FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
336*4882a593Smuzhiyun 	       FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
337*4882a593Smuzhiyun 	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
338*4882a593Smuzhiyun 	gl9750_wt_off(host);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* wait for pll stable */
341*4882a593Smuzhiyun 	mdelay(1);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
gl9750_set_ssc(struct sdhci_host * host,u8 enable,u8 step,u16 ppm)344*4882a593Smuzhiyun static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	u32 pll;
347*4882a593Smuzhiyun 	u32 ssc;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	gl9750_wt_on(host);
350*4882a593Smuzhiyun 	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
351*4882a593Smuzhiyun 	ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);
352*4882a593Smuzhiyun 	pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP |
353*4882a593Smuzhiyun 		 SDHCI_GLI_9750_PLLSSC_EN);
354*4882a593Smuzhiyun 	ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM;
355*4882a593Smuzhiyun 	pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) |
356*4882a593Smuzhiyun 	       FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable);
357*4882a593Smuzhiyun 	ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm);
358*4882a593Smuzhiyun 	sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC);
359*4882a593Smuzhiyun 	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
360*4882a593Smuzhiyun 	gl9750_wt_off(host);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun 
gl9750_set_ssc_pll_205mhz(struct sdhci_host * host)363*4882a593Smuzhiyun static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun 	/* set pll to 205MHz and enable ssc */
366*4882a593Smuzhiyun 	gl9750_set_ssc(host, 0x1, 0x1F, 0xFFE7);
367*4882a593Smuzhiyun 	gl9750_set_pll(host, 0x1, 0x246, 0x0);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
sdhci_gl9750_set_clock(struct sdhci_host * host,unsigned int clock)370*4882a593Smuzhiyun static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct mmc_ios *ios = &host->mmc->ios;
373*4882a593Smuzhiyun 	u16 clk;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	host->mmc->actual_clock = 0;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	gl9750_disable_ssc_pll(host);
378*4882a593Smuzhiyun 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (clock == 0)
381*4882a593Smuzhiyun 		return;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
384*4882a593Smuzhiyun 	if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
385*4882a593Smuzhiyun 		host->mmc->actual_clock = 205000000;
386*4882a593Smuzhiyun 		gl9750_set_ssc_pll_205mhz(host);
387*4882a593Smuzhiyun 	}
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	sdhci_enable_clk(host, clk);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
gli_pcie_enable_msi(struct sdhci_pci_slot * slot)392*4882a593Smuzhiyun static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	int ret;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1,
397*4882a593Smuzhiyun 				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
398*4882a593Smuzhiyun 	if (ret < 0) {
399*4882a593Smuzhiyun 		pr_warn("%s: enable PCI MSI failed, error=%d\n",
400*4882a593Smuzhiyun 		       mmc_hostname(slot->host->mmc), ret);
401*4882a593Smuzhiyun 		return;
402*4882a593Smuzhiyun 	}
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun 
gl9755_wt_on(struct pci_dev * pdev)407*4882a593Smuzhiyun static inline void gl9755_wt_on(struct pci_dev *pdev)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	u32 wt_value;
410*4882a593Smuzhiyun 	u32 wt_enable;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
413*4882a593Smuzhiyun 	wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	if (wt_enable == GLI_9755_WT_EN_ON)
416*4882a593Smuzhiyun 		return;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	wt_value &= ~PCI_GLI_9755_WT_EN;
419*4882a593Smuzhiyun 	wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
gl9755_wt_off(struct pci_dev * pdev)424*4882a593Smuzhiyun static inline void gl9755_wt_off(struct pci_dev *pdev)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	u32 wt_value;
427*4882a593Smuzhiyun 	u32 wt_enable;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
430*4882a593Smuzhiyun 	wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	if (wt_enable == GLI_9755_WT_EN_OFF)
433*4882a593Smuzhiyun 		return;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	wt_value &= ~PCI_GLI_9755_WT_EN;
436*4882a593Smuzhiyun 	wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
gl9755_disable_ssc_pll(struct pci_dev * pdev)441*4882a593Smuzhiyun static void gl9755_disable_ssc_pll(struct pci_dev *pdev)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun 	u32 pll;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	gl9755_wt_on(pdev);
446*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
447*4882a593Smuzhiyun 	pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN);
448*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
449*4882a593Smuzhiyun 	gl9755_wt_off(pdev);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun 
gl9755_set_pll(struct pci_dev * pdev,u8 dir,u16 ldiv,u8 pdiv)452*4882a593Smuzhiyun static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun 	u32 pll;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	gl9755_wt_on(pdev);
457*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
458*4882a593Smuzhiyun 	pll &= ~(PCI_GLI_9755_PLL_LDIV |
459*4882a593Smuzhiyun 		 PCI_GLI_9755_PLL_PDIV |
460*4882a593Smuzhiyun 		 PCI_GLI_9755_PLL_DIR);
461*4882a593Smuzhiyun 	pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) |
462*4882a593Smuzhiyun 	       FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) |
463*4882a593Smuzhiyun 	       FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir);
464*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
465*4882a593Smuzhiyun 	gl9755_wt_off(pdev);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	/* wait for pll stable */
468*4882a593Smuzhiyun 	mdelay(1);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
gl9755_set_ssc(struct pci_dev * pdev,u8 enable,u8 step,u16 ppm)471*4882a593Smuzhiyun static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	u32 pll;
474*4882a593Smuzhiyun 	u32 ssc;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	gl9755_wt_on(pdev);
477*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
478*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc);
479*4882a593Smuzhiyun 	pll &= ~(PCI_GLI_9755_PLLSSC_STEP |
480*4882a593Smuzhiyun 		 PCI_GLI_9755_PLLSSC_EN);
481*4882a593Smuzhiyun 	ssc &= ~PCI_GLI_9755_PLLSSC_PPM;
482*4882a593Smuzhiyun 	pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) |
483*4882a593Smuzhiyun 	       FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable);
484*4882a593Smuzhiyun 	ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm);
485*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc);
486*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
487*4882a593Smuzhiyun 	gl9755_wt_off(pdev);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
gl9755_set_ssc_pll_205mhz(struct pci_dev * pdev)490*4882a593Smuzhiyun static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	/* set pll to 205MHz and enable ssc */
493*4882a593Smuzhiyun 	gl9755_set_ssc(pdev, 0x1, 0x1F, 0xFFE7);
494*4882a593Smuzhiyun 	gl9755_set_pll(pdev, 0x1, 0x246, 0x0);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun 
sdhci_gl9755_set_clock(struct sdhci_host * host,unsigned int clock)497*4882a593Smuzhiyun static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
498*4882a593Smuzhiyun {
499*4882a593Smuzhiyun 	struct sdhci_pci_slot *slot = sdhci_priv(host);
500*4882a593Smuzhiyun 	struct mmc_ios *ios = &host->mmc->ios;
501*4882a593Smuzhiyun 	struct pci_dev *pdev;
502*4882a593Smuzhiyun 	u16 clk;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	pdev = slot->chip->pdev;
505*4882a593Smuzhiyun 	host->mmc->actual_clock = 0;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	gl9755_disable_ssc_pll(pdev);
508*4882a593Smuzhiyun 	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	if (clock == 0)
511*4882a593Smuzhiyun 		return;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
514*4882a593Smuzhiyun 	if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
515*4882a593Smuzhiyun 		host->mmc->actual_clock = 205000000;
516*4882a593Smuzhiyun 		gl9755_set_ssc_pll_205mhz(pdev);
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	sdhci_enable_clk(host, clk);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun 
gli_probe_slot_gl9750(struct sdhci_pci_slot * slot)522*4882a593Smuzhiyun static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
523*4882a593Smuzhiyun {
524*4882a593Smuzhiyun 	struct sdhci_host *host = slot->host;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	gli_pcie_enable_msi(slot);
527*4882a593Smuzhiyun 	slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
528*4882a593Smuzhiyun 	sdhci_enable_v4_mode(host);
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	return 0;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun 
gli_probe_slot_gl9755(struct sdhci_pci_slot * slot)533*4882a593Smuzhiyun static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun 	struct sdhci_host *host = slot->host;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	gli_pcie_enable_msi(slot);
538*4882a593Smuzhiyun 	slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
539*4882a593Smuzhiyun 	sdhci_enable_v4_mode(host);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	return 0;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
sdhci_gli_voltage_switch(struct sdhci_host * host)544*4882a593Smuzhiyun static void sdhci_gli_voltage_switch(struct sdhci_host *host)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun 	/*
547*4882a593Smuzhiyun 	 * According to Section 3.6.1 signal voltage switch procedure in
548*4882a593Smuzhiyun 	 * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as
549*4882a593Smuzhiyun 	 * follows:
550*4882a593Smuzhiyun 	 * (6) Set 1.8V Signal Enable in the Host Control 2 register.
551*4882a593Smuzhiyun 	 * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this
552*4882a593Smuzhiyun 	 *     period.
553*4882a593Smuzhiyun 	 * (8) If 1.8V Signal Enable is cleared by Host Controller, go to
554*4882a593Smuzhiyun 	 *     step (12).
555*4882a593Smuzhiyun 	 *
556*4882a593Smuzhiyun 	 * Wait 5ms after set 1.8V signal enable in Host Control 2 register
557*4882a593Smuzhiyun 	 * to ensure 1.8V signal enable bit is set by GL9750/GL9755.
558*4882a593Smuzhiyun 	 *
559*4882a593Smuzhiyun 	 * ...however, the controller in the NUC10i3FNK4 (a 9755) requires
560*4882a593Smuzhiyun 	 * slightly longer than 5ms before the control register reports that
561*4882a593Smuzhiyun 	 * 1.8V is ready, and far longer still before the card will actually
562*4882a593Smuzhiyun 	 * work reliably.
563*4882a593Smuzhiyun 	 */
564*4882a593Smuzhiyun 	usleep_range(100000, 110000);
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
sdhci_gl9750_reset(struct sdhci_host * host,u8 mask)567*4882a593Smuzhiyun static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	sdhci_reset(host, mask);
570*4882a593Smuzhiyun 	gli_set_9750(host);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
sdhci_gl9750_readl(struct sdhci_host * host,int reg)573*4882a593Smuzhiyun static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun 	u32 value;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	value = readl(host->ioaddr + reg);
578*4882a593Smuzhiyun 	if (unlikely(reg == SDHCI_MAX_CURRENT && !(value & 0xff)))
579*4882a593Smuzhiyun 		value |= 0xc8;
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	return value;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
sdhci_pci_gli_resume(struct sdhci_pci_chip * chip)585*4882a593Smuzhiyun static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun 	struct sdhci_pci_slot *slot = chip->slots[0];
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	pci_free_irq_vectors(slot->chip->pdev);
590*4882a593Smuzhiyun 	gli_pcie_enable_msi(slot);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	return sdhci_pci_resume_host(chip);
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun 
sdhci_cqhci_gli_resume(struct sdhci_pci_chip * chip)595*4882a593Smuzhiyun static int sdhci_cqhci_gli_resume(struct sdhci_pci_chip *chip)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun 	struct sdhci_pci_slot *slot = chip->slots[0];
598*4882a593Smuzhiyun 	int ret;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	ret = sdhci_pci_gli_resume(chip);
601*4882a593Smuzhiyun 	if (ret)
602*4882a593Smuzhiyun 		return ret;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	return cqhci_resume(slot->host->mmc);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
sdhci_cqhci_gli_suspend(struct sdhci_pci_chip * chip)607*4882a593Smuzhiyun static int sdhci_cqhci_gli_suspend(struct sdhci_pci_chip *chip)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	struct sdhci_pci_slot *slot = chip->slots[0];
610*4882a593Smuzhiyun 	int ret;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	ret = cqhci_suspend(slot->host->mmc);
613*4882a593Smuzhiyun 	if (ret)
614*4882a593Smuzhiyun 		return ret;
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	return sdhci_suspend_host(slot->host);
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun #endif
619*4882a593Smuzhiyun 
gl9763e_hs400_enhanced_strobe(struct mmc_host * mmc,struct mmc_ios * ios)620*4882a593Smuzhiyun static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc,
621*4882a593Smuzhiyun 					  struct mmc_ios *ios)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun 	struct sdhci_host *host = mmc_priv(mmc);
624*4882a593Smuzhiyun 	u32 val;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG);
627*4882a593Smuzhiyun 	if (ios->enhanced_strobe)
628*4882a593Smuzhiyun 		val |= SDHCI_GLI_9763E_HS400_ES_BIT;
629*4882a593Smuzhiyun 	else
630*4882a593Smuzhiyun 		val &= ~SDHCI_GLI_9763E_HS400_ES_BIT;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 	sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG);
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun 
sdhci_set_gl9763e_signaling(struct sdhci_host * host,unsigned int timing)635*4882a593Smuzhiyun static void sdhci_set_gl9763e_signaling(struct sdhci_host *host,
636*4882a593Smuzhiyun 					unsigned int timing)
637*4882a593Smuzhiyun {
638*4882a593Smuzhiyun 	u16 ctrl_2;
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
641*4882a593Smuzhiyun 	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
642*4882a593Smuzhiyun 	if (timing == MMC_TIMING_MMC_HS200)
643*4882a593Smuzhiyun 		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
644*4882a593Smuzhiyun 	else if (timing == MMC_TIMING_MMC_HS)
645*4882a593Smuzhiyun 		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
646*4882a593Smuzhiyun 	else if (timing == MMC_TIMING_MMC_DDR52)
647*4882a593Smuzhiyun 		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
648*4882a593Smuzhiyun 	else if (timing == MMC_TIMING_MMC_HS400)
649*4882a593Smuzhiyun 		ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun 
sdhci_gl9763e_dumpregs(struct mmc_host * mmc)654*4882a593Smuzhiyun static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun 	sdhci_dumpregs(mmc_priv(mmc));
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun 
sdhci_gl9763e_cqe_pre_enable(struct mmc_host * mmc)659*4882a593Smuzhiyun static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun 	struct cqhci_host *cq_host = mmc->cqe_private;
662*4882a593Smuzhiyun 	u32 value;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	value = cqhci_readl(cq_host, CQHCI_CFG);
665*4882a593Smuzhiyun 	value |= CQHCI_ENABLE;
666*4882a593Smuzhiyun 	cqhci_writel(cq_host, value, CQHCI_CFG);
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun 
sdhci_gl9763e_cqe_enable(struct mmc_host * mmc)669*4882a593Smuzhiyun static void sdhci_gl9763e_cqe_enable(struct mmc_host *mmc)
670*4882a593Smuzhiyun {
671*4882a593Smuzhiyun 	struct sdhci_host *host = mmc_priv(mmc);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	sdhci_writew(host, GLI_9763E_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);
674*4882a593Smuzhiyun 	sdhci_cqe_enable(mmc);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun 
sdhci_gl9763e_cqhci_irq(struct sdhci_host * host,u32 intmask)677*4882a593Smuzhiyun static u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun 	int cmd_error = 0;
680*4882a593Smuzhiyun 	int data_error = 0;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
683*4882a593Smuzhiyun 		return intmask;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	cqhci_irq(host->mmc, intmask, cmd_error, data_error);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	return 0;
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun 
sdhci_gl9763e_cqe_post_disable(struct mmc_host * mmc)690*4882a593Smuzhiyun static void sdhci_gl9763e_cqe_post_disable(struct mmc_host *mmc)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun 	struct sdhci_host *host = mmc_priv(mmc);
693*4882a593Smuzhiyun 	struct cqhci_host *cq_host = mmc->cqe_private;
694*4882a593Smuzhiyun 	u32 value;
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	value = cqhci_readl(cq_host, CQHCI_CFG);
697*4882a593Smuzhiyun 	value &= ~CQHCI_ENABLE;
698*4882a593Smuzhiyun 	cqhci_writel(cq_host, value, CQHCI_CFG);
699*4882a593Smuzhiyun 	sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun static const struct cqhci_host_ops sdhci_gl9763e_cqhci_ops = {
703*4882a593Smuzhiyun 	.enable         = sdhci_gl9763e_cqe_enable,
704*4882a593Smuzhiyun 	.disable        = sdhci_cqe_disable,
705*4882a593Smuzhiyun 	.dumpregs       = sdhci_gl9763e_dumpregs,
706*4882a593Smuzhiyun 	.pre_enable     = sdhci_gl9763e_cqe_pre_enable,
707*4882a593Smuzhiyun 	.post_disable   = sdhci_gl9763e_cqe_post_disable,
708*4882a593Smuzhiyun };
709*4882a593Smuzhiyun 
gl9763e_add_host(struct sdhci_pci_slot * slot)710*4882a593Smuzhiyun static int gl9763e_add_host(struct sdhci_pci_slot *slot)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun 	struct device *dev = &slot->chip->pdev->dev;
713*4882a593Smuzhiyun 	struct sdhci_host *host = slot->host;
714*4882a593Smuzhiyun 	struct cqhci_host *cq_host;
715*4882a593Smuzhiyun 	bool dma64;
716*4882a593Smuzhiyun 	int ret;
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	ret = sdhci_setup_host(host);
719*4882a593Smuzhiyun 	if (ret)
720*4882a593Smuzhiyun 		return ret;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	cq_host = devm_kzalloc(dev, sizeof(*cq_host), GFP_KERNEL);
723*4882a593Smuzhiyun 	if (!cq_host) {
724*4882a593Smuzhiyun 		ret = -ENOMEM;
725*4882a593Smuzhiyun 		goto cleanup;
726*4882a593Smuzhiyun 	}
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	cq_host->mmio = host->ioaddr + SDHCI_GLI_9763E_CQE_BASE_ADDR;
729*4882a593Smuzhiyun 	cq_host->ops = &sdhci_gl9763e_cqhci_ops;
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
732*4882a593Smuzhiyun 	if (dma64)
733*4882a593Smuzhiyun 		cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	ret = cqhci_init(cq_host, host->mmc, dma64);
736*4882a593Smuzhiyun 	if (ret)
737*4882a593Smuzhiyun 		goto cleanup;
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	ret = __sdhci_add_host(host);
740*4882a593Smuzhiyun 	if (ret)
741*4882a593Smuzhiyun 		goto cleanup;
742*4882a593Smuzhiyun 
743*4882a593Smuzhiyun 	return 0;
744*4882a593Smuzhiyun 
745*4882a593Smuzhiyun cleanup:
746*4882a593Smuzhiyun 	sdhci_cleanup_host(host);
747*4882a593Smuzhiyun 	return ret;
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun 
sdhci_gl9763e_reset(struct sdhci_host * host,u8 mask)750*4882a593Smuzhiyun static void sdhci_gl9763e_reset(struct sdhci_host *host, u8 mask)
751*4882a593Smuzhiyun {
752*4882a593Smuzhiyun 	if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
753*4882a593Smuzhiyun 	    host->mmc->cqe_private)
754*4882a593Smuzhiyun 		cqhci_deactivate(host->mmc);
755*4882a593Smuzhiyun 	sdhci_reset(host, mask);
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun 
gli_set_gl9763e(struct sdhci_pci_slot * slot)758*4882a593Smuzhiyun static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
759*4882a593Smuzhiyun {
760*4882a593Smuzhiyun 	struct pci_dev *pdev = slot->chip->pdev;
761*4882a593Smuzhiyun 	u32 value;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
764*4882a593Smuzhiyun 	value &= ~GLI_9763E_VHS_REV;
765*4882a593Smuzhiyun 	value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W);
766*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
767*4882a593Smuzhiyun 
768*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value);
769*4882a593Smuzhiyun 	value |= GLI_9763E_SCR_AXI_REQ;
770*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value);
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
773*4882a593Smuzhiyun 	value &= ~GLI_9763E_VHS_REV;
774*4882a593Smuzhiyun 	value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);
775*4882a593Smuzhiyun 	pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun 
gli_probe_slot_gl9763e(struct sdhci_pci_slot * slot)778*4882a593Smuzhiyun static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
779*4882a593Smuzhiyun {
780*4882a593Smuzhiyun 	struct pci_dev *pdev = slot->chip->pdev;
781*4882a593Smuzhiyun 	struct sdhci_host *host = slot->host;
782*4882a593Smuzhiyun 	u32 value;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun 	host->mmc->caps |= MMC_CAP_8_BIT_DATA |
785*4882a593Smuzhiyun 			   MMC_CAP_1_8V_DDR |
786*4882a593Smuzhiyun 			   MMC_CAP_NONREMOVABLE;
787*4882a593Smuzhiyun 	host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR |
788*4882a593Smuzhiyun 			    MMC_CAP2_HS400_1_8V |
789*4882a593Smuzhiyun 			    MMC_CAP2_HS400_ES |
790*4882a593Smuzhiyun 			    MMC_CAP2_NO_SDIO |
791*4882a593Smuzhiyun 			    MMC_CAP2_NO_SD;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 	pci_read_config_dword(pdev, PCIE_GLI_9763E_MB, &value);
794*4882a593Smuzhiyun 	if (!(value & GLI_9763E_MB_CMDQ_OFF))
795*4882a593Smuzhiyun 		host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	gli_pcie_enable_msi(slot);
798*4882a593Smuzhiyun 	host->mmc_host_ops.hs400_enhanced_strobe =
799*4882a593Smuzhiyun 					gl9763e_hs400_enhanced_strobe;
800*4882a593Smuzhiyun 	gli_set_gl9763e(slot);
801*4882a593Smuzhiyun 	sdhci_enable_v4_mode(host);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	return 0;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun static const struct sdhci_ops sdhci_gl9755_ops = {
807*4882a593Smuzhiyun 	.set_clock		= sdhci_gl9755_set_clock,
808*4882a593Smuzhiyun 	.enable_dma		= sdhci_pci_enable_dma,
809*4882a593Smuzhiyun 	.set_bus_width		= sdhci_set_bus_width,
810*4882a593Smuzhiyun 	.reset			= sdhci_reset,
811*4882a593Smuzhiyun 	.set_uhs_signaling	= sdhci_set_uhs_signaling,
812*4882a593Smuzhiyun 	.voltage_switch		= sdhci_gli_voltage_switch,
813*4882a593Smuzhiyun };
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun const struct sdhci_pci_fixes sdhci_gl9755 = {
816*4882a593Smuzhiyun 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
817*4882a593Smuzhiyun 	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
818*4882a593Smuzhiyun 	.probe_slot	= gli_probe_slot_gl9755,
819*4882a593Smuzhiyun 	.ops            = &sdhci_gl9755_ops,
820*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
821*4882a593Smuzhiyun 	.resume         = sdhci_pci_gli_resume,
822*4882a593Smuzhiyun #endif
823*4882a593Smuzhiyun };
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun static const struct sdhci_ops sdhci_gl9750_ops = {
826*4882a593Smuzhiyun 	.read_l                 = sdhci_gl9750_readl,
827*4882a593Smuzhiyun 	.set_clock		= sdhci_gl9750_set_clock,
828*4882a593Smuzhiyun 	.enable_dma		= sdhci_pci_enable_dma,
829*4882a593Smuzhiyun 	.set_bus_width		= sdhci_set_bus_width,
830*4882a593Smuzhiyun 	.reset			= sdhci_gl9750_reset,
831*4882a593Smuzhiyun 	.set_uhs_signaling	= sdhci_set_uhs_signaling,
832*4882a593Smuzhiyun 	.voltage_switch		= sdhci_gli_voltage_switch,
833*4882a593Smuzhiyun 	.platform_execute_tuning = gl9750_execute_tuning,
834*4882a593Smuzhiyun };
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun const struct sdhci_pci_fixes sdhci_gl9750 = {
837*4882a593Smuzhiyun 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
838*4882a593Smuzhiyun 	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
839*4882a593Smuzhiyun 	.probe_slot	= gli_probe_slot_gl9750,
840*4882a593Smuzhiyun 	.ops            = &sdhci_gl9750_ops,
841*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
842*4882a593Smuzhiyun 	.resume         = sdhci_pci_gli_resume,
843*4882a593Smuzhiyun #endif
844*4882a593Smuzhiyun };
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun static const struct sdhci_ops sdhci_gl9763e_ops = {
847*4882a593Smuzhiyun 	.set_clock		= sdhci_set_clock,
848*4882a593Smuzhiyun 	.enable_dma		= sdhci_pci_enable_dma,
849*4882a593Smuzhiyun 	.set_bus_width		= sdhci_set_bus_width,
850*4882a593Smuzhiyun 	.reset			= sdhci_gl9763e_reset,
851*4882a593Smuzhiyun 	.set_uhs_signaling	= sdhci_set_gl9763e_signaling,
852*4882a593Smuzhiyun 	.voltage_switch		= sdhci_gli_voltage_switch,
853*4882a593Smuzhiyun 	.irq                    = sdhci_gl9763e_cqhci_irq,
854*4882a593Smuzhiyun };
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun const struct sdhci_pci_fixes sdhci_gl9763e = {
857*4882a593Smuzhiyun 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
858*4882a593Smuzhiyun 	.probe_slot	= gli_probe_slot_gl9763e,
859*4882a593Smuzhiyun 	.ops            = &sdhci_gl9763e_ops,
860*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
861*4882a593Smuzhiyun 	.resume		= sdhci_cqhci_gli_resume,
862*4882a593Smuzhiyun 	.suspend	= sdhci_cqhci_gli_suspend,
863*4882a593Smuzhiyun #endif
864*4882a593Smuzhiyun 	.add_host       = gl9763e_add_host,
865*4882a593Smuzhiyun };
866