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 struct sdio_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 struct sdio_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 struct sdio_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 struct sdio_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 struct sdio_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 struct sdio_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__,
160 err, addr + i, pdata[i]);
161 break;
162 }
163 }
164 return err;
165 }
166
167 /*
168 * Return:
169 *0 Success
170 *others Fail
171 */
sd_cmd52_write(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,u8 * pdata)172 s32 sd_cmd52_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pdata)
173 {
174 struct adapter *padapter;
175 struct dvobj_priv *psdiodev;
176 struct sdio_data *psdio;
177
178 int err = 0;
179 struct sdio_func *func;
180 bool claim_needed;
181
182 padapter = pintfhdl->padapter;
183 psdiodev = pintfhdl->pintf_dev;
184 psdio = &psdiodev->intf_data;
185
186 if (padapter->bSurpriseRemoved) {
187 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
188 return err;
189 }
190
191 func = psdio->func;
192 claim_needed = rtw_sdio_claim_host_needed(func);
193
194 if (claim_needed)
195 sdio_claim_host(func);
196 err = _sd_cmd52_write(pintfhdl, addr, cnt, pdata);
197 if (claim_needed)
198 sdio_release_host(func);
199 return err;
200 }
201
sd_read8(struct intf_hdl * pintfhdl,u32 addr,s32 * err)202 u8 sd_read8(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
203 {
204 struct adapter *padapter;
205 struct dvobj_priv *psdiodev;
206 struct sdio_data *psdio;
207
208 u8 v = 0;
209 struct sdio_func *func;
210 bool claim_needed;
211
212 padapter = pintfhdl->padapter;
213 psdiodev = pintfhdl->pintf_dev;
214 psdio = &psdiodev->intf_data;
215
216 if (padapter->bSurpriseRemoved) {
217 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
218 return v;
219 }
220
221 func = psdio->func;
222 claim_needed = rtw_sdio_claim_host_needed(func);
223
224 if (claim_needed)
225 sdio_claim_host(func);
226 v = sdio_readb(func, addr, err);
227 if (claim_needed)
228 sdio_release_host(func);
229 if (err && *err)
230 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, *err, addr);
231 return v;
232 }
233
sd_read32(struct intf_hdl * pintfhdl,u32 addr,s32 * err)234 u32 sd_read32(struct intf_hdl *pintfhdl, u32 addr, s32 *err)
235 {
236 struct adapter *padapter;
237 struct dvobj_priv *psdiodev;
238 struct sdio_data *psdio;
239 u32 v = 0;
240 struct sdio_func *func;
241 bool claim_needed;
242
243 padapter = pintfhdl->padapter;
244 psdiodev = pintfhdl->pintf_dev;
245 psdio = &psdiodev->intf_data;
246
247 if (padapter->bSurpriseRemoved) {
248 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
249 return v;
250 }
251
252 func = psdio->func;
253 claim_needed = rtw_sdio_claim_host_needed(func);
254
255 if (claim_needed)
256 sdio_claim_host(func);
257 v = sdio_readl(func, addr, err);
258 if (claim_needed)
259 sdio_release_host(func);
260
261 if (err && *err) {
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 if (claim_needed)
269 sdio_claim_host(func);
270 v = sdio_readl(func, addr, err);
271 if (claim_needed)
272 sdio_release_host(func);
273
274 if (*err == 0) {
275 rtw_reset_continual_io_error(psdiodev);
276 break;
277 } else {
278 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
279 if ((-ESHUTDOWN == *err) || (-ENODEV == *err))
280 padapter->bSurpriseRemoved = true;
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 struct sdio_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 struct sdio_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 int i;
355
356 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v);
357
358 *err = 0;
359 for (i = 0; i < SD_IO_TRY_CNT; i++) {
360 if (claim_needed)
361 sdio_claim_host(func);
362 sdio_writel(func, v, addr, err);
363 if (claim_needed)
364 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 if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
374 padapter->bSurpriseRemoved = true;
375 break;
376 }
377 }
378 }
379
380 if (i == SD_IO_TRY_CNT)
381 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
382 else
383 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
384 }
385 }
386
387 /*
388 * Use CMD53 to read data from SDIO device.
389 * This function MUST be called after sdio_claim_host() or
390 * in SDIO ISR(host had been claimed).
391 *
392 * Parameters:
393 *psdio pointer of SDIO_DATA
394 *addr address to read
395 *cnt amount to read
396 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
397 *
398 * Return:
399 *0 Success
400 *others Fail
401 */
_sd_read(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)402 s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
403 {
404 struct adapter *padapter;
405 struct dvobj_priv *psdiodev;
406 struct sdio_data *psdio;
407
408 int err = -EPERM;
409 struct sdio_func *func;
410
411 padapter = pintfhdl->padapter;
412 psdiodev = pintfhdl->pintf_dev;
413 psdio = &psdiodev->intf_data;
414
415 if (padapter->bSurpriseRemoved) {
416 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
417 return err;
418 }
419
420 func = psdio->func;
421
422 if (unlikely((cnt == 1) || (cnt == 2))) {
423 int i;
424 u8 *pbuf = pdata;
425
426 for (i = 0; i < cnt; i++) {
427 *(pbuf + i) = sdio_readb(func, addr + i, &err);
428
429 if (err) {
430 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr);
431 break;
432 }
433 }
434 return err;
435 }
436
437 err = sdio_memcpy_fromio(func, pdata, addr, cnt);
438 if (err)
439 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d\n", __func__, err, addr, cnt);
440
441 return err;
442 }
443
444 /*
445 * Use CMD53 to read data from SDIO device.
446 *
447 * Parameters:
448 *psdio pointer of SDIO_DATA
449 *addr address to read
450 *cnt amount to read
451 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
452 *
453 * Return:
454 *0 Success
455 *others Fail
456 */
sd_read(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)457 s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
458 {
459 struct adapter *padapter;
460 struct dvobj_priv *psdiodev;
461 struct sdio_data *psdio;
462
463 struct sdio_func *func;
464 bool claim_needed;
465 s32 err = -EPERM;
466
467 padapter = pintfhdl->padapter;
468 psdiodev = pintfhdl->pintf_dev;
469 psdio = &psdiodev->intf_data;
470
471 if (padapter->bSurpriseRemoved) {
472 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
473 return err;
474 }
475 func = psdio->func;
476 claim_needed = rtw_sdio_claim_host_needed(func);
477
478 if (claim_needed)
479 sdio_claim_host(func);
480 err = _sd_read(pintfhdl, addr, cnt, pdata);
481 if (claim_needed)
482 sdio_release_host(func);
483 return err;
484 }
485
486 /*
487 * Use CMD53 to write data to SDIO device.
488 * This function MUST be called after sdio_claim_host() or
489 * in SDIO ISR(host had been claimed).
490 *
491 * Parameters:
492 *psdio pointer of SDIO_DATA
493 *addr address to write
494 *cnt amount to write
495 *pdata data pointer, this should be a "DMA:able scratch buffer"!
496 *
497 * Return:
498 *0 Success
499 *others Fail
500 */
_sd_write(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)501 s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
502 {
503 struct adapter *padapter;
504 struct dvobj_priv *psdiodev;
505 struct sdio_data *psdio;
506
507 struct sdio_func *func;
508 u32 size;
509 s32 err = -EPERM;
510
511 padapter = pintfhdl->padapter;
512 psdiodev = pintfhdl->pintf_dev;
513 psdio = &psdiodev->intf_data;
514
515 if (padapter->bSurpriseRemoved) {
516 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
517 return err;
518 }
519
520 func = psdio->func;
521 /* size = sdio_align_size(func, cnt); */
522
523 if (unlikely((cnt == 1) || (cnt == 2))) {
524 int i;
525 u8 *pbuf = pdata;
526
527 for (i = 0; i < cnt; i++) {
528 sdio_writeb(func, *(pbuf + i), addr + i, &err);
529 if (err) {
530 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n",
531 __func__, err, addr, *(pbuf + i));
532 break;
533 }
534 }
535
536 return err;
537 }
538
539 size = cnt;
540 err = sdio_memcpy_toio(func, addr, pdata, size);
541 if (err)
542 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d(%d)\n", __func__, err, addr, cnt, size);
543
544 return err;
545 }
546
547 /*
548 * Use CMD53 to write data to SDIO device.
549 *
550 * Parameters:
551 * psdio pointer of SDIO_DATA
552 * addr address to write
553 * cnt amount to write
554 * pdata data pointer, this should be a "DMA:able scratch buffer"!
555 *
556 * Return:
557 * 0 Success
558 * others Fail
559 */
sd_write(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)560 s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
561 {
562 struct adapter *padapter;
563 struct dvobj_priv *psdiodev;
564 struct sdio_data *psdio;
565 struct sdio_func *func;
566 bool claim_needed;
567 s32 err = -EPERM;
568
569 padapter = pintfhdl->padapter;
570 psdiodev = pintfhdl->pintf_dev;
571 psdio = &psdiodev->intf_data;
572
573 if (padapter->bSurpriseRemoved) {
574 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
575 return err;
576 }
577
578 func = psdio->func;
579 claim_needed = rtw_sdio_claim_host_needed(func);
580
581 if (claim_needed)
582 sdio_claim_host(func);
583 err = _sd_write(pintfhdl, addr, cnt, pdata);
584 if (claim_needed)
585 sdio_release_host(func);
586 return err;
587 }
588