xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/microchip/wilc1000/sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
4*4882a593Smuzhiyun  * All rights reserved.
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/mmc/sdio_func.h>
9*4882a593Smuzhiyun #include <linux/mmc/sdio_ids.h>
10*4882a593Smuzhiyun #include <linux/mmc/host.h>
11*4882a593Smuzhiyun #include <linux/mmc/sdio.h>
12*4882a593Smuzhiyun #include <linux/of_irq.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "netdev.h"
15*4882a593Smuzhiyun #include "cfg80211.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define SDIO_MODALIAS "wilc1000_sdio"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static const struct sdio_device_id wilc_sdio_ids[] = {
20*4882a593Smuzhiyun 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MICROCHIP_WILC, SDIO_DEVICE_ID_MICROCHIP_WILC1000) },
21*4882a593Smuzhiyun 	{ },
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define WILC_SDIO_BLOCK_SIZE 512
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun struct wilc_sdio {
27*4882a593Smuzhiyun 	bool irq_gpio;
28*4882a593Smuzhiyun 	u32 block_size;
29*4882a593Smuzhiyun 	int has_thrpt_enh3;
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun struct sdio_cmd52 {
33*4882a593Smuzhiyun 	u32 read_write:		1;
34*4882a593Smuzhiyun 	u32 function:		3;
35*4882a593Smuzhiyun 	u32 raw:		1;
36*4882a593Smuzhiyun 	u32 address:		17;
37*4882a593Smuzhiyun 	u32 data:		8;
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun struct sdio_cmd53 {
41*4882a593Smuzhiyun 	u32 read_write:		1;
42*4882a593Smuzhiyun 	u32 function:		3;
43*4882a593Smuzhiyun 	u32 block_mode:		1;
44*4882a593Smuzhiyun 	u32 increment:		1;
45*4882a593Smuzhiyun 	u32 address:		17;
46*4882a593Smuzhiyun 	u32 count:		9;
47*4882a593Smuzhiyun 	u8 *buffer;
48*4882a593Smuzhiyun 	u32 block_size;
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static const struct wilc_hif_func wilc_hif_sdio;
52*4882a593Smuzhiyun 
wilc_sdio_interrupt(struct sdio_func * func)53*4882a593Smuzhiyun static void wilc_sdio_interrupt(struct sdio_func *func)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	sdio_release_host(func);
56*4882a593Smuzhiyun 	wilc_handle_isr(sdio_get_drvdata(func));
57*4882a593Smuzhiyun 	sdio_claim_host(func);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
wilc_sdio_cmd52(struct wilc * wilc,struct sdio_cmd52 * cmd)60*4882a593Smuzhiyun static int wilc_sdio_cmd52(struct wilc *wilc, struct sdio_cmd52 *cmd)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
63*4882a593Smuzhiyun 	int ret;
64*4882a593Smuzhiyun 	u8 data;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	sdio_claim_host(func);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	func->num = cmd->function;
69*4882a593Smuzhiyun 	if (cmd->read_write) {  /* write */
70*4882a593Smuzhiyun 		if (cmd->raw) {
71*4882a593Smuzhiyun 			sdio_writeb(func, cmd->data, cmd->address, &ret);
72*4882a593Smuzhiyun 			data = sdio_readb(func, cmd->address, &ret);
73*4882a593Smuzhiyun 			cmd->data = data;
74*4882a593Smuzhiyun 		} else {
75*4882a593Smuzhiyun 			sdio_writeb(func, cmd->data, cmd->address, &ret);
76*4882a593Smuzhiyun 		}
77*4882a593Smuzhiyun 	} else {        /* read */
78*4882a593Smuzhiyun 		data = sdio_readb(func, cmd->address, &ret);
79*4882a593Smuzhiyun 		cmd->data = data;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	sdio_release_host(func);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (ret)
85*4882a593Smuzhiyun 		dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret);
86*4882a593Smuzhiyun 	return ret;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun 
wilc_sdio_cmd53(struct wilc * wilc,struct sdio_cmd53 * cmd)89*4882a593Smuzhiyun static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
92*4882a593Smuzhiyun 	int size, ret;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	sdio_claim_host(func);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	func->num = cmd->function;
97*4882a593Smuzhiyun 	func->cur_blksize = cmd->block_size;
98*4882a593Smuzhiyun 	if (cmd->block_mode)
99*4882a593Smuzhiyun 		size = cmd->count * cmd->block_size;
100*4882a593Smuzhiyun 	else
101*4882a593Smuzhiyun 		size = cmd->count;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	if (cmd->read_write) {  /* write */
104*4882a593Smuzhiyun 		ret = sdio_memcpy_toio(func, cmd->address,
105*4882a593Smuzhiyun 				       (void *)cmd->buffer, size);
106*4882a593Smuzhiyun 	} else {        /* read */
107*4882a593Smuzhiyun 		ret = sdio_memcpy_fromio(func, (void *)cmd->buffer,
108*4882a593Smuzhiyun 					 cmd->address,  size);
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	sdio_release_host(func);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	if (ret)
114*4882a593Smuzhiyun 		dev_err(&func->dev, "%s..failed, err(%d)\n", __func__,  ret);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return ret;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
wilc_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)119*4882a593Smuzhiyun static int wilc_sdio_probe(struct sdio_func *func,
120*4882a593Smuzhiyun 			   const struct sdio_device_id *id)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	struct wilc *wilc;
123*4882a593Smuzhiyun 	int ret;
124*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	sdio_priv = kzalloc(sizeof(*sdio_priv), GFP_KERNEL);
127*4882a593Smuzhiyun 	if (!sdio_priv)
128*4882a593Smuzhiyun 		return -ENOMEM;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
131*4882a593Smuzhiyun 				 &wilc_hif_sdio);
132*4882a593Smuzhiyun 	if (ret) {
133*4882a593Smuzhiyun 		kfree(sdio_priv);
134*4882a593Smuzhiyun 		return ret;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	if (IS_ENABLED(CONFIG_WILC1000_HW_OOB_INTR)) {
138*4882a593Smuzhiyun 		struct device_node *np = func->card->dev.of_node;
139*4882a593Smuzhiyun 		int irq_num = of_irq_get(np, 0);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 		if (irq_num > 0) {
142*4882a593Smuzhiyun 			wilc->dev_irq_num = irq_num;
143*4882a593Smuzhiyun 			sdio_priv->irq_gpio = true;
144*4882a593Smuzhiyun 		}
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	sdio_set_drvdata(func, wilc);
148*4882a593Smuzhiyun 	wilc->bus_data = sdio_priv;
149*4882a593Smuzhiyun 	wilc->dev = &func->dev;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	wilc->rtc_clk = devm_clk_get(&func->card->dev, "rtc");
152*4882a593Smuzhiyun 	if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER) {
153*4882a593Smuzhiyun 		kfree(sdio_priv);
154*4882a593Smuzhiyun 		return -EPROBE_DEFER;
155*4882a593Smuzhiyun 	} else if (!IS_ERR(wilc->rtc_clk))
156*4882a593Smuzhiyun 		clk_prepare_enable(wilc->rtc_clk);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	dev_info(&func->dev, "Driver Initializing success\n");
159*4882a593Smuzhiyun 	return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
wilc_sdio_remove(struct sdio_func * func)162*4882a593Smuzhiyun static void wilc_sdio_remove(struct sdio_func *func)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	struct wilc *wilc = sdio_get_drvdata(func);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (!IS_ERR(wilc->rtc_clk))
167*4882a593Smuzhiyun 		clk_disable_unprepare(wilc->rtc_clk);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	wilc_netdev_cleanup(wilc);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
wilc_sdio_reset(struct wilc * wilc)172*4882a593Smuzhiyun static int wilc_sdio_reset(struct wilc *wilc)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
175*4882a593Smuzhiyun 	int ret;
176*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	cmd.read_write = 1;
179*4882a593Smuzhiyun 	cmd.function = 0;
180*4882a593Smuzhiyun 	cmd.raw = 0;
181*4882a593Smuzhiyun 	cmd.address = SDIO_CCCR_ABORT;
182*4882a593Smuzhiyun 	cmd.data = WILC_SDIO_CCCR_ABORT_RESET;
183*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
184*4882a593Smuzhiyun 	if (ret) {
185*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n");
186*4882a593Smuzhiyun 		return ret;
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
wilc_sdio_suspend(struct device * dev)191*4882a593Smuzhiyun static int wilc_sdio_suspend(struct device *dev)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(dev);
194*4882a593Smuzhiyun 	struct wilc *wilc = sdio_get_drvdata(func);
195*4882a593Smuzhiyun 	int ret;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	dev_info(dev, "sdio suspend\n");
198*4882a593Smuzhiyun 	chip_wakeup(wilc);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (!IS_ERR(wilc->rtc_clk))
201*4882a593Smuzhiyun 		clk_disable_unprepare(wilc->rtc_clk);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (wilc->suspend_event) {
204*4882a593Smuzhiyun 		host_sleep_notify(wilc);
205*4882a593Smuzhiyun 		chip_allow_sleep(wilc);
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	ret = wilc_sdio_reset(wilc);
209*4882a593Smuzhiyun 	if (ret) {
210*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail reset sdio\n");
211*4882a593Smuzhiyun 		return ret;
212*4882a593Smuzhiyun 	}
213*4882a593Smuzhiyun 	sdio_claim_host(func);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	return 0;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun 
wilc_sdio_enable_interrupt(struct wilc * dev)218*4882a593Smuzhiyun static int wilc_sdio_enable_interrupt(struct wilc *dev)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun 	struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev);
221*4882a593Smuzhiyun 	int ret = 0;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	sdio_claim_host(func);
224*4882a593Smuzhiyun 	ret = sdio_claim_irq(func, wilc_sdio_interrupt);
225*4882a593Smuzhiyun 	sdio_release_host(func);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	if (ret < 0) {
228*4882a593Smuzhiyun 		dev_err(&func->dev, "can't claim sdio_irq, err(%d)\n", ret);
229*4882a593Smuzhiyun 		ret = -EIO;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 	return ret;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
wilc_sdio_disable_interrupt(struct wilc * dev)234*4882a593Smuzhiyun static void wilc_sdio_disable_interrupt(struct wilc *dev)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev);
237*4882a593Smuzhiyun 	int ret;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	sdio_claim_host(func);
240*4882a593Smuzhiyun 	ret = sdio_release_irq(func);
241*4882a593Smuzhiyun 	if (ret < 0)
242*4882a593Smuzhiyun 		dev_err(&func->dev, "can't release sdio_irq, err(%d)\n", ret);
243*4882a593Smuzhiyun 	sdio_release_host(func);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /********************************************
247*4882a593Smuzhiyun  *
248*4882a593Smuzhiyun  *      Function 0
249*4882a593Smuzhiyun  *
250*4882a593Smuzhiyun  ********************************************/
251*4882a593Smuzhiyun 
wilc_sdio_set_func0_csa_address(struct wilc * wilc,u32 adr)252*4882a593Smuzhiyun static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
255*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
256*4882a593Smuzhiyun 	int ret;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	/**
259*4882a593Smuzhiyun 	 *      Review: BIG ENDIAN
260*4882a593Smuzhiyun 	 **/
261*4882a593Smuzhiyun 	cmd.read_write = 1;
262*4882a593Smuzhiyun 	cmd.function = 0;
263*4882a593Smuzhiyun 	cmd.raw = 0;
264*4882a593Smuzhiyun 	cmd.address = WILC_SDIO_FBR_CSA_REG;
265*4882a593Smuzhiyun 	cmd.data = (u8)adr;
266*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
267*4882a593Smuzhiyun 	if (ret) {
268*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
269*4882a593Smuzhiyun 			cmd.address);
270*4882a593Smuzhiyun 		return ret;
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	cmd.address = WILC_SDIO_FBR_CSA_REG + 1;
274*4882a593Smuzhiyun 	cmd.data = (u8)(adr >> 8);
275*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
276*4882a593Smuzhiyun 	if (ret) {
277*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
278*4882a593Smuzhiyun 			cmd.address);
279*4882a593Smuzhiyun 		return ret;
280*4882a593Smuzhiyun 	}
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	cmd.address = WILC_SDIO_FBR_CSA_REG + 2;
283*4882a593Smuzhiyun 	cmd.data = (u8)(adr >> 16);
284*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
285*4882a593Smuzhiyun 	if (ret) {
286*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
287*4882a593Smuzhiyun 			cmd.address);
288*4882a593Smuzhiyun 		return ret;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	return 0;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
wilc_sdio_set_block_size(struct wilc * wilc,u8 func_num,u32 block_size)294*4882a593Smuzhiyun static int wilc_sdio_set_block_size(struct wilc *wilc, u8 func_num,
295*4882a593Smuzhiyun 				    u32 block_size)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
298*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
299*4882a593Smuzhiyun 	int ret;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	cmd.read_write = 1;
302*4882a593Smuzhiyun 	cmd.function = 0;
303*4882a593Smuzhiyun 	cmd.raw = 0;
304*4882a593Smuzhiyun 	cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE;
305*4882a593Smuzhiyun 	cmd.data = (u8)block_size;
306*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
307*4882a593Smuzhiyun 	if (ret) {
308*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
309*4882a593Smuzhiyun 			cmd.address);
310*4882a593Smuzhiyun 		return ret;
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE +  1;
314*4882a593Smuzhiyun 	cmd.data = (u8)(block_size >> 8);
315*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
316*4882a593Smuzhiyun 	if (ret) {
317*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
318*4882a593Smuzhiyun 			cmd.address);
319*4882a593Smuzhiyun 		return ret;
320*4882a593Smuzhiyun 	}
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	return 0;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun /********************************************
326*4882a593Smuzhiyun  *
327*4882a593Smuzhiyun  *      Sdio interfaces
328*4882a593Smuzhiyun  *
329*4882a593Smuzhiyun  ********************************************/
wilc_sdio_write_reg(struct wilc * wilc,u32 addr,u32 data)330*4882a593Smuzhiyun static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
333*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
334*4882a593Smuzhiyun 	int ret;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	cpu_to_le32s(&data);
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */
339*4882a593Smuzhiyun 		struct sdio_cmd52 cmd;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 		cmd.read_write = 1;
342*4882a593Smuzhiyun 		cmd.function = 0;
343*4882a593Smuzhiyun 		cmd.raw = 0;
344*4882a593Smuzhiyun 		cmd.address = addr;
345*4882a593Smuzhiyun 		cmd.data = data;
346*4882a593Smuzhiyun 		ret = wilc_sdio_cmd52(wilc, &cmd);
347*4882a593Smuzhiyun 		if (ret)
348*4882a593Smuzhiyun 			dev_err(&func->dev,
349*4882a593Smuzhiyun 				"Failed cmd 52, read reg (%08x) ...\n", addr);
350*4882a593Smuzhiyun 	} else {
351*4882a593Smuzhiyun 		struct sdio_cmd53 cmd;
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 		/**
354*4882a593Smuzhiyun 		 *      set the AHB address
355*4882a593Smuzhiyun 		 **/
356*4882a593Smuzhiyun 		ret = wilc_sdio_set_func0_csa_address(wilc, addr);
357*4882a593Smuzhiyun 		if (ret)
358*4882a593Smuzhiyun 			return ret;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 		cmd.read_write = 1;
361*4882a593Smuzhiyun 		cmd.function = 0;
362*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_FBR_DATA_REG;
363*4882a593Smuzhiyun 		cmd.block_mode = 0;
364*4882a593Smuzhiyun 		cmd.increment = 1;
365*4882a593Smuzhiyun 		cmd.count = 4;
366*4882a593Smuzhiyun 		cmd.buffer = (u8 *)&data;
367*4882a593Smuzhiyun 		cmd.block_size = sdio_priv->block_size;
368*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
369*4882a593Smuzhiyun 		if (ret)
370*4882a593Smuzhiyun 			dev_err(&func->dev,
371*4882a593Smuzhiyun 				"Failed cmd53, write reg (%08x)...\n", addr);
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	return ret;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun 
wilc_sdio_write(struct wilc * wilc,u32 addr,u8 * buf,u32 size)377*4882a593Smuzhiyun static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
380*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
381*4882a593Smuzhiyun 	u32 block_size = sdio_priv->block_size;
382*4882a593Smuzhiyun 	struct sdio_cmd53 cmd;
383*4882a593Smuzhiyun 	int nblk, nleft, ret;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	cmd.read_write = 1;
386*4882a593Smuzhiyun 	if (addr > 0) {
387*4882a593Smuzhiyun 		/**
388*4882a593Smuzhiyun 		 *      func 0 access
389*4882a593Smuzhiyun 		 **/
390*4882a593Smuzhiyun 		cmd.function = 0;
391*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_FBR_DATA_REG;
392*4882a593Smuzhiyun 	} else {
393*4882a593Smuzhiyun 		/**
394*4882a593Smuzhiyun 		 *      func 1 access
395*4882a593Smuzhiyun 		 **/
396*4882a593Smuzhiyun 		cmd.function = 1;
397*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_F1_DATA_REG;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	size = ALIGN(size, 4);
401*4882a593Smuzhiyun 	nblk = size / block_size;
402*4882a593Smuzhiyun 	nleft = size % block_size;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	if (nblk > 0) {
405*4882a593Smuzhiyun 		cmd.block_mode = 1;
406*4882a593Smuzhiyun 		cmd.increment = 1;
407*4882a593Smuzhiyun 		cmd.count = nblk;
408*4882a593Smuzhiyun 		cmd.buffer = buf;
409*4882a593Smuzhiyun 		cmd.block_size = block_size;
410*4882a593Smuzhiyun 		if (addr > 0) {
411*4882a593Smuzhiyun 			ret = wilc_sdio_set_func0_csa_address(wilc, addr);
412*4882a593Smuzhiyun 			if (ret)
413*4882a593Smuzhiyun 				return ret;
414*4882a593Smuzhiyun 		}
415*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
416*4882a593Smuzhiyun 		if (ret) {
417*4882a593Smuzhiyun 			dev_err(&func->dev,
418*4882a593Smuzhiyun 				"Failed cmd53 [%x], block send...\n", addr);
419*4882a593Smuzhiyun 			return ret;
420*4882a593Smuzhiyun 		}
421*4882a593Smuzhiyun 		if (addr > 0)
422*4882a593Smuzhiyun 			addr += nblk * block_size;
423*4882a593Smuzhiyun 		buf += nblk * block_size;
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	if (nleft > 0) {
427*4882a593Smuzhiyun 		cmd.block_mode = 0;
428*4882a593Smuzhiyun 		cmd.increment = 1;
429*4882a593Smuzhiyun 		cmd.count = nleft;
430*4882a593Smuzhiyun 		cmd.buffer = buf;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 		cmd.block_size = block_size;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 		if (addr > 0) {
435*4882a593Smuzhiyun 			ret = wilc_sdio_set_func0_csa_address(wilc, addr);
436*4882a593Smuzhiyun 			if (ret)
437*4882a593Smuzhiyun 				return ret;
438*4882a593Smuzhiyun 		}
439*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
440*4882a593Smuzhiyun 		if (ret) {
441*4882a593Smuzhiyun 			dev_err(&func->dev,
442*4882a593Smuzhiyun 				"Failed cmd53 [%x], bytes send...\n", addr);
443*4882a593Smuzhiyun 			return ret;
444*4882a593Smuzhiyun 		}
445*4882a593Smuzhiyun 	}
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	return 0;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
wilc_sdio_read_reg(struct wilc * wilc,u32 addr,u32 * data)450*4882a593Smuzhiyun static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
453*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
454*4882a593Smuzhiyun 	int ret;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */
457*4882a593Smuzhiyun 		struct sdio_cmd52 cmd;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		cmd.read_write = 0;
460*4882a593Smuzhiyun 		cmd.function = 0;
461*4882a593Smuzhiyun 		cmd.raw = 0;
462*4882a593Smuzhiyun 		cmd.address = addr;
463*4882a593Smuzhiyun 		ret = wilc_sdio_cmd52(wilc, &cmd);
464*4882a593Smuzhiyun 		if (ret) {
465*4882a593Smuzhiyun 			dev_err(&func->dev,
466*4882a593Smuzhiyun 				"Failed cmd 52, read reg (%08x) ...\n", addr);
467*4882a593Smuzhiyun 			return ret;
468*4882a593Smuzhiyun 		}
469*4882a593Smuzhiyun 		*data = cmd.data;
470*4882a593Smuzhiyun 	} else {
471*4882a593Smuzhiyun 		struct sdio_cmd53 cmd;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 		ret = wilc_sdio_set_func0_csa_address(wilc, addr);
474*4882a593Smuzhiyun 		if (ret)
475*4882a593Smuzhiyun 			return ret;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 		cmd.read_write = 0;
478*4882a593Smuzhiyun 		cmd.function = 0;
479*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_FBR_DATA_REG;
480*4882a593Smuzhiyun 		cmd.block_mode = 0;
481*4882a593Smuzhiyun 		cmd.increment = 1;
482*4882a593Smuzhiyun 		cmd.count = 4;
483*4882a593Smuzhiyun 		cmd.buffer = (u8 *)data;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		cmd.block_size = sdio_priv->block_size;
486*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
487*4882a593Smuzhiyun 		if (ret) {
488*4882a593Smuzhiyun 			dev_err(&func->dev,
489*4882a593Smuzhiyun 				"Failed cmd53, read reg (%08x)...\n", addr);
490*4882a593Smuzhiyun 			return ret;
491*4882a593Smuzhiyun 		}
492*4882a593Smuzhiyun 	}
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	le32_to_cpus(data);
495*4882a593Smuzhiyun 	return 0;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun 
wilc_sdio_read(struct wilc * wilc,u32 addr,u8 * buf,u32 size)498*4882a593Smuzhiyun static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
501*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
502*4882a593Smuzhiyun 	u32 block_size = sdio_priv->block_size;
503*4882a593Smuzhiyun 	struct sdio_cmd53 cmd;
504*4882a593Smuzhiyun 	int nblk, nleft, ret;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	cmd.read_write = 0;
507*4882a593Smuzhiyun 	if (addr > 0) {
508*4882a593Smuzhiyun 		/**
509*4882a593Smuzhiyun 		 *      func 0 access
510*4882a593Smuzhiyun 		 **/
511*4882a593Smuzhiyun 		cmd.function = 0;
512*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_FBR_DATA_REG;
513*4882a593Smuzhiyun 	} else {
514*4882a593Smuzhiyun 		/**
515*4882a593Smuzhiyun 		 *      func 1 access
516*4882a593Smuzhiyun 		 **/
517*4882a593Smuzhiyun 		cmd.function = 1;
518*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_F1_DATA_REG;
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	size = ALIGN(size, 4);
522*4882a593Smuzhiyun 	nblk = size / block_size;
523*4882a593Smuzhiyun 	nleft = size % block_size;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	if (nblk > 0) {
526*4882a593Smuzhiyun 		cmd.block_mode = 1;
527*4882a593Smuzhiyun 		cmd.increment = 1;
528*4882a593Smuzhiyun 		cmd.count = nblk;
529*4882a593Smuzhiyun 		cmd.buffer = buf;
530*4882a593Smuzhiyun 		cmd.block_size = block_size;
531*4882a593Smuzhiyun 		if (addr > 0) {
532*4882a593Smuzhiyun 			ret = wilc_sdio_set_func0_csa_address(wilc, addr);
533*4882a593Smuzhiyun 			if (ret)
534*4882a593Smuzhiyun 				return ret;
535*4882a593Smuzhiyun 		}
536*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
537*4882a593Smuzhiyun 		if (ret) {
538*4882a593Smuzhiyun 			dev_err(&func->dev,
539*4882a593Smuzhiyun 				"Failed cmd53 [%x], block read...\n", addr);
540*4882a593Smuzhiyun 			return ret;
541*4882a593Smuzhiyun 		}
542*4882a593Smuzhiyun 		if (addr > 0)
543*4882a593Smuzhiyun 			addr += nblk * block_size;
544*4882a593Smuzhiyun 		buf += nblk * block_size;
545*4882a593Smuzhiyun 	}       /* if (nblk > 0) */
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	if (nleft > 0) {
548*4882a593Smuzhiyun 		cmd.block_mode = 0;
549*4882a593Smuzhiyun 		cmd.increment = 1;
550*4882a593Smuzhiyun 		cmd.count = nleft;
551*4882a593Smuzhiyun 		cmd.buffer = buf;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 		cmd.block_size = block_size;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 		if (addr > 0) {
556*4882a593Smuzhiyun 			ret = wilc_sdio_set_func0_csa_address(wilc, addr);
557*4882a593Smuzhiyun 			if (ret)
558*4882a593Smuzhiyun 				return ret;
559*4882a593Smuzhiyun 		}
560*4882a593Smuzhiyun 		ret = wilc_sdio_cmd53(wilc, &cmd);
561*4882a593Smuzhiyun 		if (ret) {
562*4882a593Smuzhiyun 			dev_err(&func->dev,
563*4882a593Smuzhiyun 				"Failed cmd53 [%x], bytes read...\n", addr);
564*4882a593Smuzhiyun 			return ret;
565*4882a593Smuzhiyun 		}
566*4882a593Smuzhiyun 	}
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	return 0;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun /********************************************
572*4882a593Smuzhiyun  *
573*4882a593Smuzhiyun  *      Bus interfaces
574*4882a593Smuzhiyun  *
575*4882a593Smuzhiyun  ********************************************/
576*4882a593Smuzhiyun 
wilc_sdio_deinit(struct wilc * wilc)577*4882a593Smuzhiyun static int wilc_sdio_deinit(struct wilc *wilc)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun 	return 0;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
wilc_sdio_init(struct wilc * wilc,bool resume)582*4882a593Smuzhiyun static int wilc_sdio_init(struct wilc *wilc, bool resume)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
585*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
586*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
587*4882a593Smuzhiyun 	int loop, ret;
588*4882a593Smuzhiyun 	u32 chipid;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	/**
591*4882a593Smuzhiyun 	 *      function 0 csa enable
592*4882a593Smuzhiyun 	 **/
593*4882a593Smuzhiyun 	cmd.read_write = 1;
594*4882a593Smuzhiyun 	cmd.function = 0;
595*4882a593Smuzhiyun 	cmd.raw = 1;
596*4882a593Smuzhiyun 	cmd.address = SDIO_FBR_BASE(func->num);
597*4882a593Smuzhiyun 	cmd.data = SDIO_FBR_ENABLE_CSA;
598*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
599*4882a593Smuzhiyun 	if (ret) {
600*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail cmd 52, enable csa...\n");
601*4882a593Smuzhiyun 		return ret;
602*4882a593Smuzhiyun 	}
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	/**
605*4882a593Smuzhiyun 	 *      function 0 block size
606*4882a593Smuzhiyun 	 **/
607*4882a593Smuzhiyun 	ret = wilc_sdio_set_block_size(wilc, 0, WILC_SDIO_BLOCK_SIZE);
608*4882a593Smuzhiyun 	if (ret) {
609*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n");
610*4882a593Smuzhiyun 		return ret;
611*4882a593Smuzhiyun 	}
612*4882a593Smuzhiyun 	sdio_priv->block_size = WILC_SDIO_BLOCK_SIZE;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	/**
615*4882a593Smuzhiyun 	 *      enable func1 IO
616*4882a593Smuzhiyun 	 **/
617*4882a593Smuzhiyun 	cmd.read_write = 1;
618*4882a593Smuzhiyun 	cmd.function = 0;
619*4882a593Smuzhiyun 	cmd.raw = 1;
620*4882a593Smuzhiyun 	cmd.address = SDIO_CCCR_IOEx;
621*4882a593Smuzhiyun 	cmd.data = WILC_SDIO_CCCR_IO_EN_FUNC1;
622*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
623*4882a593Smuzhiyun 	if (ret) {
624*4882a593Smuzhiyun 		dev_err(&func->dev,
625*4882a593Smuzhiyun 			"Fail cmd 52, set IOE register...\n");
626*4882a593Smuzhiyun 		return ret;
627*4882a593Smuzhiyun 	}
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	/**
630*4882a593Smuzhiyun 	 *      make sure func 1 is up
631*4882a593Smuzhiyun 	 **/
632*4882a593Smuzhiyun 	cmd.read_write = 0;
633*4882a593Smuzhiyun 	cmd.function = 0;
634*4882a593Smuzhiyun 	cmd.raw = 0;
635*4882a593Smuzhiyun 	cmd.address = SDIO_CCCR_IORx;
636*4882a593Smuzhiyun 	loop = 3;
637*4882a593Smuzhiyun 	do {
638*4882a593Smuzhiyun 		cmd.data = 0;
639*4882a593Smuzhiyun 		ret = wilc_sdio_cmd52(wilc, &cmd);
640*4882a593Smuzhiyun 		if (ret) {
641*4882a593Smuzhiyun 			dev_err(&func->dev,
642*4882a593Smuzhiyun 				"Fail cmd 52, get IOR register...\n");
643*4882a593Smuzhiyun 			return ret;
644*4882a593Smuzhiyun 		}
645*4882a593Smuzhiyun 		if (cmd.data == WILC_SDIO_CCCR_IO_EN_FUNC1)
646*4882a593Smuzhiyun 			break;
647*4882a593Smuzhiyun 	} while (loop--);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	if (loop <= 0) {
650*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail func 1 is not ready...\n");
651*4882a593Smuzhiyun 		return -EINVAL;
652*4882a593Smuzhiyun 	}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 	/**
655*4882a593Smuzhiyun 	 *      func 1 is ready, set func 1 block size
656*4882a593Smuzhiyun 	 **/
657*4882a593Smuzhiyun 	ret = wilc_sdio_set_block_size(wilc, 1, WILC_SDIO_BLOCK_SIZE);
658*4882a593Smuzhiyun 	if (ret) {
659*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail set func 1 block size...\n");
660*4882a593Smuzhiyun 		return ret;
661*4882a593Smuzhiyun 	}
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	/**
664*4882a593Smuzhiyun 	 *      func 1 interrupt enable
665*4882a593Smuzhiyun 	 **/
666*4882a593Smuzhiyun 	cmd.read_write = 1;
667*4882a593Smuzhiyun 	cmd.function = 0;
668*4882a593Smuzhiyun 	cmd.raw = 1;
669*4882a593Smuzhiyun 	cmd.address = SDIO_CCCR_IENx;
670*4882a593Smuzhiyun 	cmd.data = WILC_SDIO_CCCR_IEN_MASTER | WILC_SDIO_CCCR_IEN_FUNC1;
671*4882a593Smuzhiyun 	ret = wilc_sdio_cmd52(wilc, &cmd);
672*4882a593Smuzhiyun 	if (ret) {
673*4882a593Smuzhiyun 		dev_err(&func->dev, "Fail cmd 52, set IEN register...\n");
674*4882a593Smuzhiyun 		return ret;
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	/**
678*4882a593Smuzhiyun 	 *      make sure can read back chip id correctly
679*4882a593Smuzhiyun 	 **/
680*4882a593Smuzhiyun 	if (!resume) {
681*4882a593Smuzhiyun 		int rev;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 		ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
684*4882a593Smuzhiyun 		if (ret) {
685*4882a593Smuzhiyun 			dev_err(&func->dev, "Fail cmd read chip id...\n");
686*4882a593Smuzhiyun 			return ret;
687*4882a593Smuzhiyun 		}
688*4882a593Smuzhiyun 		dev_err(&func->dev, "chipid (%08x)\n", chipid);
689*4882a593Smuzhiyun 		rev = FIELD_GET(WILC_CHIP_REV_FIELD, chipid);
690*4882a593Smuzhiyun 		if (rev > FIELD_GET(WILC_CHIP_REV_FIELD, WILC_1000_BASE_ID_2A))
691*4882a593Smuzhiyun 			sdio_priv->has_thrpt_enh3 = 1;
692*4882a593Smuzhiyun 		else
693*4882a593Smuzhiyun 			sdio_priv->has_thrpt_enh3 = 0;
694*4882a593Smuzhiyun 		dev_info(&func->dev, "has_thrpt_enh3 = %d...\n",
695*4882a593Smuzhiyun 			 sdio_priv->has_thrpt_enh3);
696*4882a593Smuzhiyun 	}
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun 	return 0;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun 
wilc_sdio_read_size(struct wilc * wilc,u32 * size)701*4882a593Smuzhiyun static int wilc_sdio_read_size(struct wilc *wilc, u32 *size)
702*4882a593Smuzhiyun {
703*4882a593Smuzhiyun 	u32 tmp;
704*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	/**
707*4882a593Smuzhiyun 	 *      Read DMA count in words
708*4882a593Smuzhiyun 	 **/
709*4882a593Smuzhiyun 	cmd.read_write = 0;
710*4882a593Smuzhiyun 	cmd.function = 0;
711*4882a593Smuzhiyun 	cmd.raw = 0;
712*4882a593Smuzhiyun 	cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG;
713*4882a593Smuzhiyun 	cmd.data = 0;
714*4882a593Smuzhiyun 	wilc_sdio_cmd52(wilc, &cmd);
715*4882a593Smuzhiyun 	tmp = cmd.data;
716*4882a593Smuzhiyun 
717*4882a593Smuzhiyun 	cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG + 1;
718*4882a593Smuzhiyun 	cmd.data = 0;
719*4882a593Smuzhiyun 	wilc_sdio_cmd52(wilc, &cmd);
720*4882a593Smuzhiyun 	tmp |= (cmd.data << 8);
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 	*size = tmp;
723*4882a593Smuzhiyun 	return 0;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun 
wilc_sdio_read_int(struct wilc * wilc,u32 * int_status)726*4882a593Smuzhiyun static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status)
727*4882a593Smuzhiyun {
728*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
729*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
730*4882a593Smuzhiyun 	u32 tmp;
731*4882a593Smuzhiyun 	u8 irq_flags;
732*4882a593Smuzhiyun 	struct sdio_cmd52 cmd;
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	wilc_sdio_read_size(wilc, &tmp);
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	/**
737*4882a593Smuzhiyun 	 *      Read IRQ flags
738*4882a593Smuzhiyun 	 **/
739*4882a593Smuzhiyun 	if (!sdio_priv->irq_gpio) {
740*4882a593Smuzhiyun 		cmd.function = 1;
741*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG;
742*4882a593Smuzhiyun 	} else {
743*4882a593Smuzhiyun 		cmd.function = 0;
744*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_IRQ_FLAG_REG;
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun 	cmd.raw = 0;
747*4882a593Smuzhiyun 	cmd.read_write = 0;
748*4882a593Smuzhiyun 	cmd.data = 0;
749*4882a593Smuzhiyun 	wilc_sdio_cmd52(wilc, &cmd);
750*4882a593Smuzhiyun 	irq_flags = cmd.data;
751*4882a593Smuzhiyun 	tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags))
754*4882a593Smuzhiyun 		dev_err(&func->dev, "Unexpected interrupt (1) int=%lx\n",
755*4882a593Smuzhiyun 			FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags));
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	*int_status = tmp;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	return 0;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun 
wilc_sdio_clear_int_ext(struct wilc * wilc,u32 val)762*4882a593Smuzhiyun static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
765*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
766*4882a593Smuzhiyun 	int ret;
767*4882a593Smuzhiyun 	int vmm_ctl;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	if (sdio_priv->has_thrpt_enh3) {
770*4882a593Smuzhiyun 		u32 reg = 0;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 		if (sdio_priv->irq_gpio)
773*4882a593Smuzhiyun 			reg = val & (BIT(MAX_NUM_INT) - 1);
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 		/* select VMM table 0 */
776*4882a593Smuzhiyun 		if (val & SEL_VMM_TBL0)
777*4882a593Smuzhiyun 			reg |= BIT(5);
778*4882a593Smuzhiyun 		/* select VMM table 1 */
779*4882a593Smuzhiyun 		if (val & SEL_VMM_TBL1)
780*4882a593Smuzhiyun 			reg |= BIT(6);
781*4882a593Smuzhiyun 		/* enable VMM */
782*4882a593Smuzhiyun 		if (val & EN_VMM)
783*4882a593Smuzhiyun 			reg |= BIT(7);
784*4882a593Smuzhiyun 		if (reg) {
785*4882a593Smuzhiyun 			struct sdio_cmd52 cmd;
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 			cmd.read_write = 1;
788*4882a593Smuzhiyun 			cmd.function = 0;
789*4882a593Smuzhiyun 			cmd.raw = 0;
790*4882a593Smuzhiyun 			cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG;
791*4882a593Smuzhiyun 			cmd.data = reg;
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun 			ret = wilc_sdio_cmd52(wilc, &cmd);
794*4882a593Smuzhiyun 			if (ret) {
795*4882a593Smuzhiyun 				dev_err(&func->dev,
796*4882a593Smuzhiyun 					"Failed cmd52, set (%02x) data (%d) ...\n",
797*4882a593Smuzhiyun 					cmd.address, __LINE__);
798*4882a593Smuzhiyun 				return ret;
799*4882a593Smuzhiyun 			}
800*4882a593Smuzhiyun 		}
801*4882a593Smuzhiyun 		return 0;
802*4882a593Smuzhiyun 	}
803*4882a593Smuzhiyun 	if (sdio_priv->irq_gpio) {
804*4882a593Smuzhiyun 		/* has_thrpt_enh2 uses register 0xf8 to clear interrupts. */
805*4882a593Smuzhiyun 		/*
806*4882a593Smuzhiyun 		 * Cannot clear multiple interrupts.
807*4882a593Smuzhiyun 		 * Must clear each interrupt individually.
808*4882a593Smuzhiyun 		 */
809*4882a593Smuzhiyun 		u32 flags;
810*4882a593Smuzhiyun 		int i;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 		flags = val & (BIT(MAX_NUM_INT) - 1);
813*4882a593Smuzhiyun 		for (i = 0; i < NUM_INT_EXT && flags; i++) {
814*4882a593Smuzhiyun 			if (flags & BIT(i)) {
815*4882a593Smuzhiyun 				struct sdio_cmd52 cmd;
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 				cmd.read_write = 1;
818*4882a593Smuzhiyun 				cmd.function = 0;
819*4882a593Smuzhiyun 				cmd.raw = 0;
820*4882a593Smuzhiyun 				cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG;
821*4882a593Smuzhiyun 				cmd.data = BIT(i);
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 				ret = wilc_sdio_cmd52(wilc, &cmd);
824*4882a593Smuzhiyun 				if (ret) {
825*4882a593Smuzhiyun 					dev_err(&func->dev,
826*4882a593Smuzhiyun 						"Failed cmd52, set (%02x) data (%d) ...\n",
827*4882a593Smuzhiyun 						cmd.address, __LINE__);
828*4882a593Smuzhiyun 					return ret;
829*4882a593Smuzhiyun 				}
830*4882a593Smuzhiyun 				flags &= ~BIT(i);
831*4882a593Smuzhiyun 			}
832*4882a593Smuzhiyun 		}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 		for (i = NUM_INT_EXT; i < MAX_NUM_INT && flags; i++) {
835*4882a593Smuzhiyun 			if (flags & BIT(i)) {
836*4882a593Smuzhiyun 				dev_err(&func->dev,
837*4882a593Smuzhiyun 					"Unexpected interrupt cleared %d...\n",
838*4882a593Smuzhiyun 					i);
839*4882a593Smuzhiyun 				flags &= ~BIT(i);
840*4882a593Smuzhiyun 			}
841*4882a593Smuzhiyun 		}
842*4882a593Smuzhiyun 	}
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	vmm_ctl = 0;
845*4882a593Smuzhiyun 	/* select VMM table 0 */
846*4882a593Smuzhiyun 	if (val & SEL_VMM_TBL0)
847*4882a593Smuzhiyun 		vmm_ctl |= BIT(0);
848*4882a593Smuzhiyun 	/* select VMM table 1 */
849*4882a593Smuzhiyun 	if (val & SEL_VMM_TBL1)
850*4882a593Smuzhiyun 		vmm_ctl |= BIT(1);
851*4882a593Smuzhiyun 	/* enable VMM */
852*4882a593Smuzhiyun 	if (val & EN_VMM)
853*4882a593Smuzhiyun 		vmm_ctl |= BIT(2);
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	if (vmm_ctl) {
856*4882a593Smuzhiyun 		struct sdio_cmd52 cmd;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 		cmd.read_write = 1;
859*4882a593Smuzhiyun 		cmd.function = 0;
860*4882a593Smuzhiyun 		cmd.raw = 0;
861*4882a593Smuzhiyun 		cmd.address = WILC_SDIO_VMM_TBL_CTRL_REG;
862*4882a593Smuzhiyun 		cmd.data = vmm_ctl;
863*4882a593Smuzhiyun 		ret = wilc_sdio_cmd52(wilc, &cmd);
864*4882a593Smuzhiyun 		if (ret) {
865*4882a593Smuzhiyun 			dev_err(&func->dev,
866*4882a593Smuzhiyun 				"Failed cmd52, set (%02x) data (%d) ...\n",
867*4882a593Smuzhiyun 				cmd.address, __LINE__);
868*4882a593Smuzhiyun 			return ret;
869*4882a593Smuzhiyun 		}
870*4882a593Smuzhiyun 	}
871*4882a593Smuzhiyun 	return 0;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun 
wilc_sdio_sync_ext(struct wilc * wilc,int nint)874*4882a593Smuzhiyun static int wilc_sdio_sync_ext(struct wilc *wilc, int nint)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(wilc->dev);
877*4882a593Smuzhiyun 	struct wilc_sdio *sdio_priv = wilc->bus_data;
878*4882a593Smuzhiyun 	u32 reg;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	if (nint > MAX_NUM_INT) {
881*4882a593Smuzhiyun 		dev_err(&func->dev, "Too many interrupts (%d)...\n", nint);
882*4882a593Smuzhiyun 		return -EINVAL;
883*4882a593Smuzhiyun 	}
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 	/**
886*4882a593Smuzhiyun 	 *      Disable power sequencer
887*4882a593Smuzhiyun 	 **/
888*4882a593Smuzhiyun 	if (wilc_sdio_read_reg(wilc, WILC_MISC, &reg)) {
889*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed read misc reg...\n");
890*4882a593Smuzhiyun 		return -EINVAL;
891*4882a593Smuzhiyun 	}
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 	reg &= ~BIT(8);
894*4882a593Smuzhiyun 	if (wilc_sdio_write_reg(wilc, WILC_MISC, reg)) {
895*4882a593Smuzhiyun 		dev_err(&func->dev, "Failed write misc reg...\n");
896*4882a593Smuzhiyun 		return -EINVAL;
897*4882a593Smuzhiyun 	}
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	if (sdio_priv->irq_gpio) {
900*4882a593Smuzhiyun 		u32 reg;
901*4882a593Smuzhiyun 		int ret, i;
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 		/**
904*4882a593Smuzhiyun 		 *      interrupt pin mux select
905*4882a593Smuzhiyun 		 **/
906*4882a593Smuzhiyun 		ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, &reg);
907*4882a593Smuzhiyun 		if (ret) {
908*4882a593Smuzhiyun 			dev_err(&func->dev, "Failed read reg (%08x)...\n",
909*4882a593Smuzhiyun 				WILC_PIN_MUX_0);
910*4882a593Smuzhiyun 			return ret;
911*4882a593Smuzhiyun 		}
912*4882a593Smuzhiyun 		reg |= BIT(8);
913*4882a593Smuzhiyun 		ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg);
914*4882a593Smuzhiyun 		if (ret) {
915*4882a593Smuzhiyun 			dev_err(&func->dev, "Failed write reg (%08x)...\n",
916*4882a593Smuzhiyun 				WILC_PIN_MUX_0);
917*4882a593Smuzhiyun 			return ret;
918*4882a593Smuzhiyun 		}
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun 		/**
921*4882a593Smuzhiyun 		 *      interrupt enable
922*4882a593Smuzhiyun 		 **/
923*4882a593Smuzhiyun 		ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, &reg);
924*4882a593Smuzhiyun 		if (ret) {
925*4882a593Smuzhiyun 			dev_err(&func->dev, "Failed read reg (%08x)...\n",
926*4882a593Smuzhiyun 				WILC_INTR_ENABLE);
927*4882a593Smuzhiyun 			return ret;
928*4882a593Smuzhiyun 		}
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 		for (i = 0; (i < 5) && (nint > 0); i++, nint--)
931*4882a593Smuzhiyun 			reg |= BIT((27 + i));
932*4882a593Smuzhiyun 		ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg);
933*4882a593Smuzhiyun 		if (ret) {
934*4882a593Smuzhiyun 			dev_err(&func->dev, "Failed write reg (%08x)...\n",
935*4882a593Smuzhiyun 				WILC_INTR_ENABLE);
936*4882a593Smuzhiyun 			return ret;
937*4882a593Smuzhiyun 		}
938*4882a593Smuzhiyun 		if (nint) {
939*4882a593Smuzhiyun 			ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
940*4882a593Smuzhiyun 			if (ret) {
941*4882a593Smuzhiyun 				dev_err(&func->dev,
942*4882a593Smuzhiyun 					"Failed read reg (%08x)...\n",
943*4882a593Smuzhiyun 					WILC_INTR2_ENABLE);
944*4882a593Smuzhiyun 				return ret;
945*4882a593Smuzhiyun 			}
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun 			for (i = 0; (i < 3) && (nint > 0); i++, nint--)
948*4882a593Smuzhiyun 				reg |= BIT(i);
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 			ret = wilc_sdio_write_reg(wilc, WILC_INTR2_ENABLE, reg);
951*4882a593Smuzhiyun 			if (ret) {
952*4882a593Smuzhiyun 				dev_err(&func->dev,
953*4882a593Smuzhiyun 					"Failed write reg (%08x)...\n",
954*4882a593Smuzhiyun 					WILC_INTR2_ENABLE);
955*4882a593Smuzhiyun 				return ret;
956*4882a593Smuzhiyun 			}
957*4882a593Smuzhiyun 		}
958*4882a593Smuzhiyun 	}
959*4882a593Smuzhiyun 	return 0;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun /* Global sdio HIF function table */
963*4882a593Smuzhiyun static const struct wilc_hif_func wilc_hif_sdio = {
964*4882a593Smuzhiyun 	.hif_init = wilc_sdio_init,
965*4882a593Smuzhiyun 	.hif_deinit = wilc_sdio_deinit,
966*4882a593Smuzhiyun 	.hif_read_reg = wilc_sdio_read_reg,
967*4882a593Smuzhiyun 	.hif_write_reg = wilc_sdio_write_reg,
968*4882a593Smuzhiyun 	.hif_block_rx = wilc_sdio_read,
969*4882a593Smuzhiyun 	.hif_block_tx = wilc_sdio_write,
970*4882a593Smuzhiyun 	.hif_read_int = wilc_sdio_read_int,
971*4882a593Smuzhiyun 	.hif_clear_int_ext = wilc_sdio_clear_int_ext,
972*4882a593Smuzhiyun 	.hif_read_size = wilc_sdio_read_size,
973*4882a593Smuzhiyun 	.hif_block_tx_ext = wilc_sdio_write,
974*4882a593Smuzhiyun 	.hif_block_rx_ext = wilc_sdio_read,
975*4882a593Smuzhiyun 	.hif_sync_ext = wilc_sdio_sync_ext,
976*4882a593Smuzhiyun 	.enable_interrupt = wilc_sdio_enable_interrupt,
977*4882a593Smuzhiyun 	.disable_interrupt = wilc_sdio_disable_interrupt,
978*4882a593Smuzhiyun };
979*4882a593Smuzhiyun 
wilc_sdio_resume(struct device * dev)980*4882a593Smuzhiyun static int wilc_sdio_resume(struct device *dev)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun 	struct sdio_func *func = dev_to_sdio_func(dev);
983*4882a593Smuzhiyun 	struct wilc *wilc = sdio_get_drvdata(func);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	dev_info(dev, "sdio resume\n");
986*4882a593Smuzhiyun 	sdio_release_host(func);
987*4882a593Smuzhiyun 	chip_wakeup(wilc);
988*4882a593Smuzhiyun 	wilc_sdio_init(wilc, true);
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	if (wilc->suspend_event)
991*4882a593Smuzhiyun 		host_wakeup_notify(wilc);
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	chip_allow_sleep(wilc);
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	return 0;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun static const struct of_device_id wilc_of_match[] = {
999*4882a593Smuzhiyun 	{ .compatible = "microchip,wilc1000", },
1000*4882a593Smuzhiyun 	{ /* sentinel */ }
1001*4882a593Smuzhiyun };
1002*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, wilc_of_match);
1003*4882a593Smuzhiyun 
1004*4882a593Smuzhiyun static const struct dev_pm_ops wilc_sdio_pm_ops = {
1005*4882a593Smuzhiyun 	.suspend = wilc_sdio_suspend,
1006*4882a593Smuzhiyun 	.resume = wilc_sdio_resume,
1007*4882a593Smuzhiyun };
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun static struct sdio_driver wilc_sdio_driver = {
1010*4882a593Smuzhiyun 	.name		= SDIO_MODALIAS,
1011*4882a593Smuzhiyun 	.id_table	= wilc_sdio_ids,
1012*4882a593Smuzhiyun 	.probe		= wilc_sdio_probe,
1013*4882a593Smuzhiyun 	.remove		= wilc_sdio_remove,
1014*4882a593Smuzhiyun 	.drv = {
1015*4882a593Smuzhiyun 		.pm = &wilc_sdio_pm_ops,
1016*4882a593Smuzhiyun 		.of_match_table = wilc_of_match,
1017*4882a593Smuzhiyun 	}
1018*4882a593Smuzhiyun };
1019*4882a593Smuzhiyun module_driver(wilc_sdio_driver,
1020*4882a593Smuzhiyun 	      sdio_register_driver,
1021*4882a593Smuzhiyun 	      sdio_unregister_driver);
1022*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1023