xref: /linux/drivers/mmc/host/sdhci-pci-arasan.c (revision 552c69b36ebd966186573b9c7a286b390935cce1)
1*d72d72cdSAtul Garg // SPDX-License-Identifier: GPL-2.0
2*d72d72cdSAtul Garg /*
3*d72d72cdSAtul Garg  * sdhci-pci-arasan.c - Driver for Arasan PCI Controller with
4*d72d72cdSAtul Garg  * integrated phy.
5*d72d72cdSAtul Garg  *
6*d72d72cdSAtul Garg  * Copyright (C) 2017 Arasan Chip Systems Inc.
7*d72d72cdSAtul Garg  *
8*d72d72cdSAtul Garg  * Author: Atul Garg <agarg@arasan.com>
9*d72d72cdSAtul Garg  */
10*d72d72cdSAtul Garg 
11*d72d72cdSAtul Garg #include <linux/pci.h>
12*d72d72cdSAtul Garg #include <linux/delay.h>
13*d72d72cdSAtul Garg 
14*d72d72cdSAtul Garg #include "sdhci.h"
15*d72d72cdSAtul Garg #include "sdhci-pci.h"
16*d72d72cdSAtul Garg 
17*d72d72cdSAtul Garg /* Extra registers for Arasan SD/SDIO/MMC Host Controller with PHY */
18*d72d72cdSAtul Garg #define PHY_ADDR_REG	0x300
19*d72d72cdSAtul Garg #define PHY_DAT_REG	0x304
20*d72d72cdSAtul Garg 
21*d72d72cdSAtul Garg #define PHY_WRITE	BIT(8)
22*d72d72cdSAtul Garg #define PHY_BUSY	BIT(9)
23*d72d72cdSAtul Garg #define DATA_MASK	0xFF
24*d72d72cdSAtul Garg 
25*d72d72cdSAtul Garg /* PHY Specific Registers */
26*d72d72cdSAtul Garg #define DLL_STATUS	0x00
27*d72d72cdSAtul Garg #define IPAD_CTRL1	0x01
28*d72d72cdSAtul Garg #define IPAD_CTRL2	0x02
29*d72d72cdSAtul Garg #define IPAD_STS	0x03
30*d72d72cdSAtul Garg #define IOREN_CTRL1	0x06
31*d72d72cdSAtul Garg #define IOREN_CTRL2	0x07
32*d72d72cdSAtul Garg #define IOPU_CTRL1	0x08
33*d72d72cdSAtul Garg #define IOPU_CTRL2	0x09
34*d72d72cdSAtul Garg #define ITAP_DELAY	0x0C
35*d72d72cdSAtul Garg #define OTAP_DELAY	0x0D
36*d72d72cdSAtul Garg #define STRB_SEL	0x0E
37*d72d72cdSAtul Garg #define CLKBUF_SEL	0x0F
38*d72d72cdSAtul Garg #define MODE_CTRL	0x11
39*d72d72cdSAtul Garg #define DLL_TRIM	0x12
40*d72d72cdSAtul Garg #define CMD_CTRL	0x20
41*d72d72cdSAtul Garg #define DATA_CTRL	0x21
42*d72d72cdSAtul Garg #define STRB_CTRL	0x22
43*d72d72cdSAtul Garg #define CLK_CTRL	0x23
44*d72d72cdSAtul Garg #define PHY_CTRL	0x24
45*d72d72cdSAtul Garg 
46*d72d72cdSAtul Garg #define DLL_ENBL	BIT(3)
47*d72d72cdSAtul Garg #define RTRIM_EN	BIT(1)
48*d72d72cdSAtul Garg #define PDB_ENBL	BIT(1)
49*d72d72cdSAtul Garg #define RETB_ENBL	BIT(6)
50*d72d72cdSAtul Garg #define ODEN_CMD	BIT(1)
51*d72d72cdSAtul Garg #define ODEN_DAT	0xFF
52*d72d72cdSAtul Garg #define REN_STRB	BIT(0)
53*d72d72cdSAtul Garg #define REN_CMND	BIT(1)
54*d72d72cdSAtul Garg #define REN_DATA	0xFF
55*d72d72cdSAtul Garg #define PU_CMD		BIT(1)
56*d72d72cdSAtul Garg #define PU_DAT		0xFF
57*d72d72cdSAtul Garg #define ITAPDLY_EN	BIT(0)
58*d72d72cdSAtul Garg #define OTAPDLY_EN	BIT(0)
59*d72d72cdSAtul Garg #define OD_REL_CMD	BIT(1)
60*d72d72cdSAtul Garg #define OD_REL_DAT	0xFF
61*d72d72cdSAtul Garg #define DLLTRM_ICP	0x8
62*d72d72cdSAtul Garg #define PDB_CMND	BIT(0)
63*d72d72cdSAtul Garg #define PDB_DATA	0xFF
64*d72d72cdSAtul Garg #define PDB_STRB	BIT(0)
65*d72d72cdSAtul Garg #define PDB_CLOCK	BIT(0)
66*d72d72cdSAtul Garg #define CALDONE_MASK	0x10
67*d72d72cdSAtul Garg #define DLL_RDY_MASK	0x10
68*d72d72cdSAtul Garg #define MAX_CLK_BUF	0x7
69*d72d72cdSAtul Garg 
70*d72d72cdSAtul Garg /* Mode Controls */
71*d72d72cdSAtul Garg #define ENHSTRB_MODE	BIT(0)
72*d72d72cdSAtul Garg #define HS400_MODE	BIT(1)
73*d72d72cdSAtul Garg #define LEGACY_MODE	BIT(2)
74*d72d72cdSAtul Garg #define DDR50_MODE	BIT(3)
75*d72d72cdSAtul Garg 
76*d72d72cdSAtul Garg /*
77*d72d72cdSAtul Garg  * Controller has no specific bits for HS200/HS.
78*d72d72cdSAtul Garg  * Used BIT(4), BIT(5) for software programming.
79*d72d72cdSAtul Garg  */
80*d72d72cdSAtul Garg #define HS200_MODE	BIT(4)
81*d72d72cdSAtul Garg #define HISPD_MODE	BIT(5)
82*d72d72cdSAtul Garg 
83*d72d72cdSAtul Garg #define OTAPDLY(x)	(((x) << 1) | OTAPDLY_EN)
84*d72d72cdSAtul Garg #define ITAPDLY(x)	(((x) << 1) | ITAPDLY_EN)
85*d72d72cdSAtul Garg #define FREQSEL(x)	(((x) << 5) | DLL_ENBL)
86*d72d72cdSAtul Garg #define IOPAD(x, y)	((x) | ((y) << 2))
87*d72d72cdSAtul Garg 
88*d72d72cdSAtul Garg /* Arasan private data */
89*d72d72cdSAtul Garg struct arasan_host {
90*d72d72cdSAtul Garg 	u32 chg_clk;
91*d72d72cdSAtul Garg };
92*d72d72cdSAtul Garg 
arasan_phy_addr_poll(struct sdhci_host * host,u32 offset,u32 mask)93*d72d72cdSAtul Garg static int arasan_phy_addr_poll(struct sdhci_host *host, u32 offset, u32 mask)
94*d72d72cdSAtul Garg {
95*d72d72cdSAtul Garg 	ktime_t timeout = ktime_add_us(ktime_get(), 100);
96*d72d72cdSAtul Garg 	bool failed;
97*d72d72cdSAtul Garg 	u8 val = 0;
98*d72d72cdSAtul Garg 
99*d72d72cdSAtul Garg 	while (1) {
100*d72d72cdSAtul Garg 		failed = ktime_after(ktime_get(), timeout);
101*d72d72cdSAtul Garg 		val = sdhci_readw(host, PHY_ADDR_REG);
102*d72d72cdSAtul Garg 		if (!(val & mask))
103*d72d72cdSAtul Garg 			return 0;
104*d72d72cdSAtul Garg 		if (failed)
105*d72d72cdSAtul Garg 			return -EBUSY;
106*d72d72cdSAtul Garg 	}
107*d72d72cdSAtul Garg }
108*d72d72cdSAtul Garg 
arasan_phy_write(struct sdhci_host * host,u8 data,u8 offset)109*d72d72cdSAtul Garg static int arasan_phy_write(struct sdhci_host *host, u8 data, u8 offset)
110*d72d72cdSAtul Garg {
111*d72d72cdSAtul Garg 	sdhci_writew(host, data, PHY_DAT_REG);
112*d72d72cdSAtul Garg 	sdhci_writew(host, (PHY_WRITE | offset), PHY_ADDR_REG);
113*d72d72cdSAtul Garg 	return arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);
114*d72d72cdSAtul Garg }
115*d72d72cdSAtul Garg 
arasan_phy_read(struct sdhci_host * host,u8 offset,u8 * data)116*d72d72cdSAtul Garg static int arasan_phy_read(struct sdhci_host *host, u8 offset, u8 *data)
117*d72d72cdSAtul Garg {
118*d72d72cdSAtul Garg 	int ret;
119*d72d72cdSAtul Garg 
120*d72d72cdSAtul Garg 	sdhci_writew(host, 0, PHY_DAT_REG);
121*d72d72cdSAtul Garg 	sdhci_writew(host, offset, PHY_ADDR_REG);
122*d72d72cdSAtul Garg 	ret = arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY);
123*d72d72cdSAtul Garg 
124*d72d72cdSAtul Garg 	/* Masking valid data bits */
125*d72d72cdSAtul Garg 	*data = sdhci_readw(host, PHY_DAT_REG) & DATA_MASK;
126*d72d72cdSAtul Garg 	return ret;
127*d72d72cdSAtul Garg }
128*d72d72cdSAtul Garg 
arasan_phy_sts_poll(struct sdhci_host * host,u32 offset,u32 mask)129*d72d72cdSAtul Garg static int arasan_phy_sts_poll(struct sdhci_host *host, u32 offset, u32 mask)
130*d72d72cdSAtul Garg {
131*d72d72cdSAtul Garg 	int ret;
132*d72d72cdSAtul Garg 	ktime_t timeout = ktime_add_us(ktime_get(), 100);
133*d72d72cdSAtul Garg 	bool failed;
134*d72d72cdSAtul Garg 	u8 val = 0;
135*d72d72cdSAtul Garg 
136*d72d72cdSAtul Garg 	while (1) {
137*d72d72cdSAtul Garg 		failed = ktime_after(ktime_get(), timeout);
138*d72d72cdSAtul Garg 		ret = arasan_phy_read(host, offset, &val);
139*d72d72cdSAtul Garg 		if (ret)
140*d72d72cdSAtul Garg 			return -EBUSY;
141*d72d72cdSAtul Garg 		else if (val & mask)
142*d72d72cdSAtul Garg 			return 0;
143*d72d72cdSAtul Garg 		if (failed)
144*d72d72cdSAtul Garg 			return -EBUSY;
145*d72d72cdSAtul Garg 	}
146*d72d72cdSAtul Garg }
147*d72d72cdSAtul Garg 
148*d72d72cdSAtul Garg /* Initialize the Arasan PHY */
arasan_phy_init(struct sdhci_host * host)149*d72d72cdSAtul Garg static int arasan_phy_init(struct sdhci_host *host)
150*d72d72cdSAtul Garg {
151*d72d72cdSAtul Garg 	int ret;
152*d72d72cdSAtul Garg 	u8 val;
153*d72d72cdSAtul Garg 
154*d72d72cdSAtul Garg 	/* Program IOPADs and wait for calibration to be done */
155*d72d72cdSAtul Garg 	if (arasan_phy_read(host, IPAD_CTRL1, &val) ||
156*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | RETB_ENBL | PDB_ENBL, IPAD_CTRL1) ||
157*d72d72cdSAtul Garg 	    arasan_phy_read(host, IPAD_CTRL2, &val) ||
158*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | RTRIM_EN, IPAD_CTRL2))
159*d72d72cdSAtul Garg 		return -EBUSY;
160*d72d72cdSAtul Garg 	ret = arasan_phy_sts_poll(host, IPAD_STS, CALDONE_MASK);
161*d72d72cdSAtul Garg 	if (ret)
162*d72d72cdSAtul Garg 		return -EBUSY;
163*d72d72cdSAtul Garg 
164*d72d72cdSAtul Garg 	/* Program CMD/Data lines */
165*d72d72cdSAtul Garg 	if (arasan_phy_read(host, IOREN_CTRL1, &val) ||
166*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | REN_CMND | REN_STRB, IOREN_CTRL1) ||
167*d72d72cdSAtul Garg 	    arasan_phy_read(host, IOPU_CTRL1, &val) ||
168*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PU_CMD, IOPU_CTRL1) ||
169*d72d72cdSAtul Garg 	    arasan_phy_read(host, CMD_CTRL, &val) ||
170*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PDB_CMND, CMD_CTRL) ||
171*d72d72cdSAtul Garg 	    arasan_phy_read(host, IOREN_CTRL2, &val) ||
172*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | REN_DATA, IOREN_CTRL2) ||
173*d72d72cdSAtul Garg 	    arasan_phy_read(host, IOPU_CTRL2, &val) ||
174*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PU_DAT, IOPU_CTRL2) ||
175*d72d72cdSAtul Garg 	    arasan_phy_read(host, DATA_CTRL, &val) ||
176*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PDB_DATA, DATA_CTRL) ||
177*d72d72cdSAtul Garg 	    arasan_phy_read(host, STRB_CTRL, &val) ||
178*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PDB_STRB, STRB_CTRL) ||
179*d72d72cdSAtul Garg 	    arasan_phy_read(host, CLK_CTRL, &val) ||
180*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | PDB_CLOCK, CLK_CTRL) ||
181*d72d72cdSAtul Garg 	    arasan_phy_read(host, CLKBUF_SEL, &val) ||
182*d72d72cdSAtul Garg 	    arasan_phy_write(host, val | MAX_CLK_BUF, CLKBUF_SEL) ||
183*d72d72cdSAtul Garg 	    arasan_phy_write(host, LEGACY_MODE, MODE_CTRL))
184*d72d72cdSAtul Garg 		return -EBUSY;
185*d72d72cdSAtul Garg 	return 0;
186*d72d72cdSAtul Garg }
187*d72d72cdSAtul Garg 
188*d72d72cdSAtul Garg /* Set Arasan PHY for different modes */
arasan_phy_set(struct sdhci_host * host,u8 mode,u8 otap,u8 drv_type,u8 itap,u8 trim,u8 clk)189*d72d72cdSAtul Garg static int arasan_phy_set(struct sdhci_host *host, u8 mode, u8 otap,
190*d72d72cdSAtul Garg 			  u8 drv_type, u8 itap, u8 trim, u8 clk)
191*d72d72cdSAtul Garg {
192*d72d72cdSAtul Garg 	u8 val;
193*d72d72cdSAtul Garg 	int ret;
194*d72d72cdSAtul Garg 
195*d72d72cdSAtul Garg 	if (mode == HISPD_MODE || mode == HS200_MODE)
196*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, 0x0, MODE_CTRL);
197*d72d72cdSAtul Garg 	else
198*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, mode, MODE_CTRL);
199*d72d72cdSAtul Garg 	if (ret)
200*d72d72cdSAtul Garg 		return ret;
201*d72d72cdSAtul Garg 	if (mode == HS400_MODE || mode == HS200_MODE) {
202*d72d72cdSAtul Garg 		ret = arasan_phy_read(host, IPAD_CTRL1, &val);
203*d72d72cdSAtul Garg 		if (ret)
204*d72d72cdSAtul Garg 			return ret;
205*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, IOPAD(val, drv_type), IPAD_CTRL1);
206*d72d72cdSAtul Garg 		if (ret)
207*d72d72cdSAtul Garg 			return ret;
208*d72d72cdSAtul Garg 	}
209*d72d72cdSAtul Garg 	if (mode == LEGACY_MODE) {
210*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, 0x0, OTAP_DELAY);
211*d72d72cdSAtul Garg 		if (ret)
212*d72d72cdSAtul Garg 			return ret;
213*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, 0x0, ITAP_DELAY);
214*d72d72cdSAtul Garg 	} else {
215*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, OTAPDLY(otap), OTAP_DELAY);
216*d72d72cdSAtul Garg 		if (ret)
217*d72d72cdSAtul Garg 			return ret;
218*d72d72cdSAtul Garg 		if (mode != HS200_MODE)
219*d72d72cdSAtul Garg 			ret = arasan_phy_write(host, ITAPDLY(itap), ITAP_DELAY);
220*d72d72cdSAtul Garg 		else
221*d72d72cdSAtul Garg 			ret = arasan_phy_write(host, 0x0, ITAP_DELAY);
222*d72d72cdSAtul Garg 	}
223*d72d72cdSAtul Garg 	if (ret)
224*d72d72cdSAtul Garg 		return ret;
225*d72d72cdSAtul Garg 	if (mode != LEGACY_MODE) {
226*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, trim, DLL_TRIM);
227*d72d72cdSAtul Garg 		if (ret)
228*d72d72cdSAtul Garg 			return ret;
229*d72d72cdSAtul Garg 	}
230*d72d72cdSAtul Garg 	ret = arasan_phy_write(host, 0, DLL_STATUS);
231*d72d72cdSAtul Garg 	if (ret)
232*d72d72cdSAtul Garg 		return ret;
233*d72d72cdSAtul Garg 	if (mode != LEGACY_MODE) {
234*d72d72cdSAtul Garg 		ret = arasan_phy_write(host, FREQSEL(clk), DLL_STATUS);
235*d72d72cdSAtul Garg 		if (ret)
236*d72d72cdSAtul Garg 			return ret;
237*d72d72cdSAtul Garg 		ret = arasan_phy_sts_poll(host, DLL_STATUS, DLL_RDY_MASK);
238*d72d72cdSAtul Garg 		if (ret)
239*d72d72cdSAtul Garg 			return -EBUSY;
240*d72d72cdSAtul Garg 	}
241*d72d72cdSAtul Garg 	return 0;
242*d72d72cdSAtul Garg }
243*d72d72cdSAtul Garg 
arasan_select_phy_clock(struct sdhci_host * host)244*d72d72cdSAtul Garg static int arasan_select_phy_clock(struct sdhci_host *host)
245*d72d72cdSAtul Garg {
246*d72d72cdSAtul Garg 	struct sdhci_pci_slot *slot = sdhci_priv(host);
247*d72d72cdSAtul Garg 	struct arasan_host *arasan_host = sdhci_pci_priv(slot);
248*d72d72cdSAtul Garg 	u8 clk;
249*d72d72cdSAtul Garg 
250*d72d72cdSAtul Garg 	if (arasan_host->chg_clk == host->mmc->ios.clock)
251*d72d72cdSAtul Garg 		return 0;
252*d72d72cdSAtul Garg 
253*d72d72cdSAtul Garg 	arasan_host->chg_clk = host->mmc->ios.clock;
254*d72d72cdSAtul Garg 	if (host->mmc->ios.clock == 200000000)
255*d72d72cdSAtul Garg 		clk = 0x0;
256*d72d72cdSAtul Garg 	else if (host->mmc->ios.clock == 100000000)
257*d72d72cdSAtul Garg 		clk = 0x2;
258*d72d72cdSAtul Garg 	else if (host->mmc->ios.clock == 50000000)
259*d72d72cdSAtul Garg 		clk = 0x1;
260*d72d72cdSAtul Garg 	else
261*d72d72cdSAtul Garg 		clk = 0x0;
262*d72d72cdSAtul Garg 
263*d72d72cdSAtul Garg 	if (host->mmc_host_ops.hs400_enhanced_strobe) {
264*d72d72cdSAtul Garg 		arasan_phy_set(host, ENHSTRB_MODE, 1, 0x0, 0x0,
265*d72d72cdSAtul Garg 			       DLLTRM_ICP, clk);
266*d72d72cdSAtul Garg 	} else {
267*d72d72cdSAtul Garg 		switch (host->mmc->ios.timing) {
268*d72d72cdSAtul Garg 		case MMC_TIMING_LEGACY:
269*d72d72cdSAtul Garg 			arasan_phy_set(host, LEGACY_MODE, 0x0, 0x0, 0x0,
270*d72d72cdSAtul Garg 				       0x0, 0x0);
271*d72d72cdSAtul Garg 			break;
272*d72d72cdSAtul Garg 		case MMC_TIMING_MMC_HS:
273*d72d72cdSAtul Garg 		case MMC_TIMING_SD_HS:
274*d72d72cdSAtul Garg 			arasan_phy_set(host, HISPD_MODE, 0x3, 0x0, 0x2,
275*d72d72cdSAtul Garg 				       DLLTRM_ICP, clk);
276*d72d72cdSAtul Garg 			break;
277*d72d72cdSAtul Garg 		case MMC_TIMING_MMC_HS200:
278*d72d72cdSAtul Garg 		case MMC_TIMING_UHS_SDR104:
279*d72d72cdSAtul Garg 			arasan_phy_set(host, HS200_MODE, 0x2,
280*d72d72cdSAtul Garg 				       host->mmc->ios.drv_type, 0x0,
281*d72d72cdSAtul Garg 				       DLLTRM_ICP, clk);
282*d72d72cdSAtul Garg 			break;
283*d72d72cdSAtul Garg 		case MMC_TIMING_MMC_DDR52:
284*d72d72cdSAtul Garg 		case MMC_TIMING_UHS_DDR50:
285*d72d72cdSAtul Garg 			arasan_phy_set(host, DDR50_MODE, 0x1, 0x0,
286*d72d72cdSAtul Garg 				       0x0, DLLTRM_ICP, clk);
287*d72d72cdSAtul Garg 			break;
288*d72d72cdSAtul Garg 		case MMC_TIMING_MMC_HS400:
289*d72d72cdSAtul Garg 			arasan_phy_set(host, HS400_MODE, 0x1,
290*d72d72cdSAtul Garg 				       host->mmc->ios.drv_type, 0xa,
291*d72d72cdSAtul Garg 				       DLLTRM_ICP, clk);
292*d72d72cdSAtul Garg 			break;
293*d72d72cdSAtul Garg 		default:
294*d72d72cdSAtul Garg 			break;
295*d72d72cdSAtul Garg 		}
296*d72d72cdSAtul Garg 	}
297*d72d72cdSAtul Garg 	return 0;
298*d72d72cdSAtul Garg }
299*d72d72cdSAtul Garg 
arasan_pci_probe_slot(struct sdhci_pci_slot * slot)300*d72d72cdSAtul Garg static int arasan_pci_probe_slot(struct sdhci_pci_slot *slot)
301*d72d72cdSAtul Garg {
302*d72d72cdSAtul Garg 	int err;
303*d72d72cdSAtul Garg 
304*d72d72cdSAtul Garg 	slot->host->mmc->caps |= MMC_CAP_NONREMOVABLE | MMC_CAP_8_BIT_DATA;
305*d72d72cdSAtul Garg 	err = arasan_phy_init(slot->host);
306*d72d72cdSAtul Garg 	if (err)
307*d72d72cdSAtul Garg 		return -ENODEV;
308*d72d72cdSAtul Garg 	return 0;
309*d72d72cdSAtul Garg }
310*d72d72cdSAtul Garg 
arasan_sdhci_set_clock(struct sdhci_host * host,unsigned int clock)311*d72d72cdSAtul Garg static void arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
312*d72d72cdSAtul Garg {
313*d72d72cdSAtul Garg 	sdhci_set_clock(host, clock);
314*d72d72cdSAtul Garg 
315*d72d72cdSAtul Garg 	/* Change phy settings for the new clock */
316*d72d72cdSAtul Garg 	arasan_select_phy_clock(host);
317*d72d72cdSAtul Garg }
318*d72d72cdSAtul Garg 
319*d72d72cdSAtul Garg static const struct sdhci_ops arasan_sdhci_pci_ops = {
320*d72d72cdSAtul Garg 	.set_clock	= arasan_sdhci_set_clock,
321*d72d72cdSAtul Garg 	.enable_dma	= sdhci_pci_enable_dma,
322*d72d72cdSAtul Garg 	.set_bus_width	= sdhci_set_bus_width,
323*d72d72cdSAtul Garg 	.reset		= sdhci_reset,
324*d72d72cdSAtul Garg 	.set_uhs_signaling	= sdhci_set_uhs_signaling,
325*d72d72cdSAtul Garg };
326*d72d72cdSAtul Garg 
327*d72d72cdSAtul Garg const struct sdhci_pci_fixes sdhci_arasan = {
328*d72d72cdSAtul Garg 	.probe_slot = arasan_pci_probe_slot,
329*d72d72cdSAtul Garg 	.ops        = &arasan_sdhci_pci_ops,
330*d72d72cdSAtul Garg 	.priv_size  = sizeof(struct arasan_host),
331*d72d72cdSAtul Garg };
332