1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *******************************************************************************/
15 #define _SDIO_OPS_LINUX_C_
16 
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 
20 static bool rtw_sdio_claim_host_needed(struct sdio_func *func)
21 {
22 	struct dvobj_priv *dvobj = sdio_get_drvdata(func);
23 	PSDIO_DATA sdio_data = &dvobj->intf_data;
24 
25 	if (sdio_data->sys_sdio_irq_thd && sdio_data->sys_sdio_irq_thd == current)
26 		return false;
27 	return true;
28 }
29 
30 inline void rtw_sdio_set_irq_thd(struct dvobj_priv *dvobj, void *thd_hdl)
31 {
32 	PSDIO_DATA sdio_data = &dvobj->intf_data;
33 
34 	sdio_data->sys_sdio_irq_thd = thd_hdl;
35 }
36 
37 u8 sd_f0_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
38 {
39 	struct adapter *padapter;
40 	struct dvobj_priv *psdiodev;
41 	PSDIO_DATA psdio;
42 
43 	u8 v = 0;
44 	struct sdio_func *func;
45 	bool claim_needed;
46 
47 	padapter = pintfhdl->padapter;
48 	psdiodev = pintfhdl->pintf_dev;
49 	psdio = &psdiodev->intf_data;
50 
51 	if (padapter->bSurpriseRemoved) {
52 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
53 		return v;
54 	}
55 
56 	func = psdio->func;
57 	claim_needed = rtw_sdio_claim_host_needed(func);
58 
59 	if (claim_needed)
60 		sdio_claim_host(func);
61 	v = sdio_f0_readb(func, addr, err);
62 	if (claim_needed)
63 		sdio_release_host(func);
64 	if (err && *err)
65 		DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, *err, addr);
66 	return v;
67 }
68 
69 /*
70  * Return:
71  *0		Success
72  *others	Fail
73  */
74 s32 _sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
75 {
76 	struct adapter *padapter;
77 	struct dvobj_priv *psdiodev;
78 	PSDIO_DATA psdio;
79 
80 	int err = 0, i;
81 	struct sdio_func *func;
82 
83 	padapter = pintfhdl->padapter;
84 	psdiodev = pintfhdl->pintf_dev;
85 	psdio = &psdiodev->intf_data;
86 
87 	if (padapter->bSurpriseRemoved) {
88 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
89 		return err;
90 	}
91 
92 	func = psdio->func;
93 
94 	for (i = 0; i < cnt; i++) {
95 		pdata[i] = sdio_readb(func, addr+i, &err);
96 		if (err) {
97 			DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr+i);
98 			break;
99 		}
100 	}
101 	return err;
102 }
103 
104 /*
105  * Return:
106  *0		Success
107  *others	Fail
108  */
109 s32 sd_cmd52_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
110 {
111 	struct adapter *padapter;
112 	struct dvobj_priv *psdiodev;
113 	PSDIO_DATA psdio;
114 
115 	int err = 0;
116 	struct sdio_func *func;
117 	bool claim_needed;
118 
119 	padapter = pintfhdl->padapter;
120 	psdiodev = pintfhdl->pintf_dev;
121 	psdio = &psdiodev->intf_data;
122 
123 	if (padapter->bSurpriseRemoved) {
124 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
125 		return err;
126 	}
127 
128 	func = psdio->func;
129 	claim_needed = rtw_sdio_claim_host_needed(func);
130 
131 	if (claim_needed)
132 		sdio_claim_host(func);
133 	err = _sd_cmd52_read(pintfhdl, addr, cnt, pdata);
134 	if (claim_needed)
135 		sdio_release_host(func);
136 	return err;
137 }
138 
139 /*
140  * Return:
141  *0		Success
142  *others	Fail
143  */
144 s32 _sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
145 {
146 	struct adapter *padapter;
147 	struct dvobj_priv *psdiodev;
148 	PSDIO_DATA psdio;
149 
150 	int err = 0, i;
151 	struct sdio_func *func;
152 
153 	padapter = pintfhdl->padapter;
154 	psdiodev = pintfhdl->pintf_dev;
155 	psdio = &psdiodev->intf_data;
156 
157 	if (padapter->bSurpriseRemoved) {
158 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
159 		return err;
160 	}
161 
162 	func = psdio->func;
163 
164 	for (i = 0; i < cnt; i++) {
165 		sdio_writeb(func, pdata[i], addr+i, &err);
166 		if (err) {
167 			DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr+i, pdata[i]);
168 			break;
169 		}
170 	}
171 	return err;
172 }
173 
174 /*
175  * Return:
176  *0		Success
177  *others	Fail
178  */
179 s32 sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
180 {
181 	struct adapter *padapter;
182 	struct dvobj_priv *psdiodev;
183 	PSDIO_DATA psdio;
184 
185 	int err = 0;
186 	struct sdio_func *func;
187 	bool claim_needed;
188 
189 	padapter = pintfhdl->padapter;
190 	psdiodev = pintfhdl->pintf_dev;
191 	psdio = &psdiodev->intf_data;
192 
193 	if (padapter->bSurpriseRemoved) {
194 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
195 		return err;
196 	}
197 
198 	func = psdio->func;
199 	claim_needed = rtw_sdio_claim_host_needed(func);
200 
201 	if (claim_needed)
202 		sdio_claim_host(func);
203 	err = _sd_cmd52_write(pintfhdl, addr, cnt, pdata);
204 	if (claim_needed)
205 		sdio_release_host(func);
206 	return err;
207 }
208 
209 u8 sd_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
210 {
211 	struct adapter *padapter;
212 	struct dvobj_priv *psdiodev;
213 	PSDIO_DATA psdio;
214 
215 	u8 v = 0;
216 	struct sdio_func *func;
217 	bool claim_needed;
218 
219 	padapter = pintfhdl->padapter;
220 	psdiodev = pintfhdl->pintf_dev;
221 	psdio = &psdiodev->intf_data;
222 
223 	if (padapter->bSurpriseRemoved) {
224 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
225 		return v;
226 	}
227 
228 	func = psdio->func;
229 	claim_needed = rtw_sdio_claim_host_needed(func);
230 
231 	if (claim_needed)
232 		sdio_claim_host(func);
233 	v = sdio_readb(func, addr, err);
234 	if (claim_needed)
235 		sdio_release_host(func);
236 	if (err && *err)
237 		DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, *err, addr);
238 	return v;
239 }
240 
241 u32 sd_read32(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
242 {
243 	struct adapter *padapter;
244 	struct dvobj_priv *psdiodev;
245 	PSDIO_DATA psdio;
246 	u32 v = 0;
247 	struct sdio_func *func;
248 	bool claim_needed;
249 
250 	padapter = pintfhdl->padapter;
251 	psdiodev = pintfhdl->pintf_dev;
252 	psdio = &psdiodev->intf_data;
253 
254 	if (padapter->bSurpriseRemoved) {
255 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
256 		return v;
257 	}
258 
259 	func = psdio->func;
260 	claim_needed = rtw_sdio_claim_host_needed(func);
261 
262 	if (claim_needed)
263 		sdio_claim_host(func);
264 	v = sdio_readl(func, addr, err);
265 	if (claim_needed)
266 		sdio_release_host(func);
267 
268 	if (err && *err)
269 	{
270 		int i;
271 
272 		DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x\n", __func__, *err, addr, v);
273 
274 		*err = 0;
275 		for (i = 0; i < SD_IO_TRY_CNT; i++)
276 		{
277 			if (claim_needed) sdio_claim_host(func);
278 			v = sdio_readl(func, addr, err);
279 			if (claim_needed) sdio_release_host(func);
280 
281 			if (*err == 0) {
282 				rtw_reset_continual_io_error(psdiodev);
283 				break;
284 			} else {
285 				DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
286 				if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
287 					padapter->bSurpriseRemoved = true;
288 				}
289 
290 				if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
291 					padapter->bSurpriseRemoved = true;
292 					break;
293 				}
294 			}
295 		}
296 
297 		if (i == SD_IO_TRY_CNT)
298 			DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
299 		else
300 			DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
301 
302 	}
303 	return  v;
304 }
305 
306 void sd_write8(struct intf_hdl *pintfhdl, u32 addr, u8 v, s32 *err)
307 {
308 	struct adapter *padapter;
309 	struct dvobj_priv *psdiodev;
310 	PSDIO_DATA psdio;
311 	struct sdio_func *func;
312 	bool claim_needed;
313 
314 	padapter = pintfhdl->padapter;
315 	psdiodev = pintfhdl->pintf_dev;
316 	psdio = &psdiodev->intf_data;
317 
318 	if (padapter->bSurpriseRemoved) {
319 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
320 		return;
321 	}
322 
323 	func = psdio->func;
324 	claim_needed = rtw_sdio_claim_host_needed(func);
325 
326 	if (claim_needed)
327 		sdio_claim_host(func);
328 	sdio_writeb(func, v, addr, err);
329 	if (claim_needed)
330 		sdio_release_host(func);
331 	if (err && *err)
332 		DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, *err, addr, v);
333 }
334 
335 void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
336 {
337 	struct adapter *padapter;
338 	struct dvobj_priv *psdiodev;
339 	PSDIO_DATA psdio;
340 	struct sdio_func *func;
341 	bool claim_needed;
342 
343 	padapter = pintfhdl->padapter;
344 	psdiodev = pintfhdl->pintf_dev;
345 	psdio = &psdiodev->intf_data;
346 
347 	if (padapter->bSurpriseRemoved) {
348 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
349 		return;
350 	}
351 
352 	func = psdio->func;
353 	claim_needed = rtw_sdio_claim_host_needed(func);
354 
355 	if (claim_needed)
356 		sdio_claim_host(func);
357 	sdio_writel(func, v, addr, err);
358 	if (claim_needed)
359 		sdio_release_host(func);
360 
361 	if (err && *err)
362 	{
363 		int i;
364 
365 		DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v);
366 
367 		*err = 0;
368 		for (i = 0; i < SD_IO_TRY_CNT; i++)
369 		{
370 			if (claim_needed) sdio_claim_host(func);
371 			sdio_writel(func, v, addr, err);
372 			if (claim_needed) sdio_release_host(func);
373 			if (*err == 0) {
374 				rtw_reset_continual_io_error(psdiodev);
375 				break;
376 			} else {
377 				DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
378 				if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
379 					padapter->bSurpriseRemoved = true;
380 				}
381 
382 				if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
383 					padapter->bSurpriseRemoved = true;
384 					break;
385 				}
386 			}
387 		}
388 
389 		if (i == SD_IO_TRY_CNT)
390 			DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
391 		else
392 			DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
393 	}
394 }
395 
396 /*
397  * Use CMD53 to read data from SDIO device.
398  * This function MUST be called after sdio_claim_host() or
399  * in SDIO ISR(host had been claimed).
400  *
401  * Parameters:
402  *psdio	pointer of SDIO_DATA
403  *addr	address to read
404  *cnt		amount to read
405  *pdata	pointer to put data, this should be a "DMA:able scratch buffer"!
406  *
407  * Return:
408  *0		Success
409  *others	Fail
410  */
411 s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
412 {
413 	struct adapter *padapter;
414 	struct dvobj_priv *psdiodev;
415 	PSDIO_DATA psdio;
416 
417 	int err = -EPERM;
418 	struct sdio_func *func;
419 
420 	padapter = pintfhdl->padapter;
421 	psdiodev = pintfhdl->pintf_dev;
422 	psdio = &psdiodev->intf_data;
423 
424 	if (padapter->bSurpriseRemoved) {
425 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
426 		return err;
427 	}
428 
429 	func = psdio->func;
430 
431 	if (unlikely((cnt == 1) || (cnt == 2)))
432 	{
433 		int i;
434 		u8 *pbuf = (u8 *)pdata;
435 
436 		for (i = 0; i < cnt; i++)
437 		{
438 			*(pbuf+i) = sdio_readb(func, addr+i, &err);
439 
440 			if (err) {
441 				DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr);
442 				break;
443 			}
444 		}
445 		return err;
446 	}
447 
448 	err = sdio_memcpy_fromio(func, pdata, addr, cnt);
449 	if (err) {
450 		DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d\n", __func__, err, addr, cnt);
451 	}
452 	return err;
453 }
454 
455 /*
456  * Use CMD53 to read data from SDIO device.
457  *
458  * Parameters:
459  *psdio	pointer of SDIO_DATA
460  *addr	address to read
461  *cnt		amount to read
462  *pdata	pointer to put data, this should be a "DMA:able scratch buffer"!
463  *
464  * Return:
465  *0		Success
466  *others	Fail
467  */
468 s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
469 {
470 	struct adapter *padapter;
471 	struct dvobj_priv *psdiodev;
472 	PSDIO_DATA psdio;
473 
474 	struct sdio_func *func;
475 	bool claim_needed;
476 	s32 err = -EPERM;
477 
478 	padapter = pintfhdl->padapter;
479 	psdiodev = pintfhdl->pintf_dev;
480 	psdio = &psdiodev->intf_data;
481 
482 	if (padapter->bSurpriseRemoved) {
483 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
484 		return err;
485 	}
486 	func = psdio->func;
487 	claim_needed = rtw_sdio_claim_host_needed(func);
488 
489 	if (claim_needed)
490 		sdio_claim_host(func);
491 	err = _sd_read(pintfhdl, addr, cnt, pdata);
492 	if (claim_needed)
493 		sdio_release_host(func);
494 	return err;
495 }
496 
497 /*
498  * Use CMD53 to write data to SDIO device.
499  * This function MUST be called after sdio_claim_host() or
500  * in SDIO ISR(host had been claimed).
501  *
502  * Parameters:
503  *psdio	pointer of SDIO_DATA
504  *addr	address to write
505  *cnt		amount to write
506  *pdata	data pointer, this should be a "DMA:able scratch buffer"!
507  *
508  * Return:
509  *0		Success
510  *others	Fail
511  */
512 s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
513 {
514 	struct adapter *padapter;
515 	struct dvobj_priv *psdiodev;
516 	PSDIO_DATA psdio;
517 
518 	struct sdio_func *func;
519 	u32 size;
520 	s32 err =  -EPERM;
521 
522 	padapter = pintfhdl->padapter;
523 	psdiodev = pintfhdl->pintf_dev;
524 	psdio = &psdiodev->intf_data;
525 
526 	if (padapter->bSurpriseRemoved) {
527 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
528 		return err;
529 	}
530 
531 	func = psdio->func;
532 /*	size = sdio_align_size(func, cnt); */
533 
534 	if (unlikely((cnt == 1) || (cnt == 2)))
535 	{
536 		int i;
537 		u8 *pbuf = (u8 *)pdata;
538 
539 		for (i = 0; i < cnt; i++)
540 		{
541 			sdio_writeb(func, *(pbuf+i), addr+i, &err);
542 			if (err) {
543 				DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr, *(pbuf+i));
544 				break;
545 			}
546 		}
547 
548 		return err;
549 	}
550 
551 	size = cnt;
552 	err = sdio_memcpy_toio(func, addr, pdata, size);
553 	if (err) {
554 		DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d(%d)\n", __func__, err, addr, cnt, size);
555 	}
556 	return err;
557 }
558 
559 /*
560  * Use CMD53 to write data to SDIO device.
561  *
562  * Parameters:
563  *  psdio	pointer of SDIO_DATA
564  *  addr	address to write
565  *  cnt		amount to write
566  *  pdata	data pointer, this should be a "DMA:able scratch buffer"!
567  *
568  * Return:
569  *  0		Success
570  *  others	Fail
571  */
572 s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
573 {
574 	struct adapter *padapter;
575 	struct dvobj_priv *psdiodev;
576 	PSDIO_DATA psdio;
577 	struct sdio_func *func;
578 	bool claim_needed;
579 	s32 err =  -EPERM;
580 
581 	padapter = pintfhdl->padapter;
582 	psdiodev = pintfhdl->pintf_dev;
583 	psdio = &psdiodev->intf_data;
584 
585 	if (padapter->bSurpriseRemoved) {
586 		/* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
587 		return err;
588 	}
589 
590 	func = psdio->func;
591 	claim_needed = rtw_sdio_claim_host_needed(func);
592 
593 	if (claim_needed)
594 		sdio_claim_host(func);
595 	err = _sd_write(pintfhdl, addr, cnt, pdata);
596 	if (claim_needed)
597 		sdio_release_host(func);
598 	return err;
599 }
600