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