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__, 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 struct sdio_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 struct sdio_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 struct sdio_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 int i;
262
263 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x\n", __func__, *err, addr, v);
264
265 *err = 0;
266 for (i = 0; i < SD_IO_TRY_CNT; i++) {
267 if (claim_needed) sdio_claim_host(func);
268 v = sdio_readl(func, addr, err);
269 if (claim_needed) sdio_release_host(func);
270
271 if (*err == 0) {
272 rtw_reset_continual_io_error(psdiodev);
273 break;
274 } else {
275 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
276 if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
277 padapter->bSurpriseRemoved = true;
278 }
279
280 if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
281 padapter->bSurpriseRemoved = true;
282 break;
283 }
284 }
285 }
286
287 if (i == SD_IO_TRY_CNT)
288 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
289 else
290 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
291
292 }
293 return v;
294 }
295
sd_write8(struct intf_hdl * pintfhdl,u32 addr,u8 v,s32 * err)296 void sd_write8(struct intf_hdl *pintfhdl, u32 addr, u8 v, s32 *err)
297 {
298 struct adapter *padapter;
299 struct dvobj_priv *psdiodev;
300 struct sdio_data *psdio;
301 struct sdio_func *func;
302 bool claim_needed;
303
304 padapter = pintfhdl->padapter;
305 psdiodev = pintfhdl->pintf_dev;
306 psdio = &psdiodev->intf_data;
307
308 if (padapter->bSurpriseRemoved) {
309 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
310 return;
311 }
312
313 func = psdio->func;
314 claim_needed = rtw_sdio_claim_host_needed(func);
315
316 if (claim_needed)
317 sdio_claim_host(func);
318 sdio_writeb(func, v, addr, err);
319 if (claim_needed)
320 sdio_release_host(func);
321 if (err && *err)
322 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, *err, addr, v);
323 }
324
sd_write32(struct intf_hdl * pintfhdl,u32 addr,u32 v,s32 * err)325 void sd_write32(struct intf_hdl *pintfhdl, u32 addr, u32 v, s32 *err)
326 {
327 struct adapter *padapter;
328 struct dvobj_priv *psdiodev;
329 struct sdio_data *psdio;
330 struct sdio_func *func;
331 bool claim_needed;
332
333 padapter = pintfhdl->padapter;
334 psdiodev = pintfhdl->pintf_dev;
335 psdio = &psdiodev->intf_data;
336
337 if (padapter->bSurpriseRemoved) {
338 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
339 return;
340 }
341
342 func = psdio->func;
343 claim_needed = rtw_sdio_claim_host_needed(func);
344
345 if (claim_needed)
346 sdio_claim_host(func);
347 sdio_writel(func, v, addr, err);
348 if (claim_needed)
349 sdio_release_host(func);
350
351 if (err && *err) {
352 int i;
353
354 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x\n", __func__, *err, addr, v);
355
356 *err = 0;
357 for (i = 0; i < SD_IO_TRY_CNT; i++) {
358 if (claim_needed) sdio_claim_host(func);
359 sdio_writel(func, v, addr, err);
360 if (claim_needed) sdio_release_host(func);
361 if (*err == 0) {
362 rtw_reset_continual_io_error(psdiodev);
363 break;
364 } else {
365 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x, val = 0x%x, try_cnt =%d\n", __func__, *err, addr, v, i);
366 if ((-ESHUTDOWN == *err) || (-ENODEV == *err)) {
367 padapter->bSurpriseRemoved = true;
368 }
369
370 if (rtw_inc_and_chk_continual_io_error(psdiodev) == true) {
371 padapter->bSurpriseRemoved = true;
372 break;
373 }
374 }
375 }
376
377 if (i == SD_IO_TRY_CNT)
378 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
379 else
380 DBG_871X(KERN_ERR "%s: (%d) addr = 0x%05x val = 0x%08x, try_cnt =%d\n", __func__, *err, addr, v, i);
381 }
382 }
383
384 /*
385 * Use CMD53 to read data from SDIO device.
386 * This function MUST be called after sdio_claim_host() or
387 * in SDIO ISR(host had been claimed).
388 *
389 * Parameters:
390 *psdio pointer of SDIO_DATA
391 *addr address to read
392 *cnt amount to read
393 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
394 *
395 * Return:
396 *0 Success
397 *others Fail
398 */
_sd_read(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)399 s32 _sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
400 {
401 struct adapter *padapter;
402 struct dvobj_priv *psdiodev;
403 struct sdio_data *psdio;
404
405 int err = -EPERM;
406 struct sdio_func *func;
407
408 padapter = pintfhdl->padapter;
409 psdiodev = pintfhdl->pintf_dev;
410 psdio = &psdiodev->intf_data;
411
412 if (padapter->bSurpriseRemoved) {
413 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
414 return err;
415 }
416
417 func = psdio->func;
418
419 if (unlikely((cnt == 1) || (cnt == 2))) {
420 int i;
421 u8 *pbuf = pdata;
422
423 for (i = 0; i < cnt; i++) {
424 *(pbuf+i) = sdio_readb(func, addr+i, &err);
425
426 if (err) {
427 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x\n", __func__, err, addr);
428 break;
429 }
430 }
431 return err;
432 }
433
434 err = sdio_memcpy_fromio(func, pdata, addr, cnt);
435 if (err) {
436 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d\n", __func__, err, addr, cnt);
437 }
438 return err;
439 }
440
441 /*
442 * Use CMD53 to read data from SDIO device.
443 *
444 * Parameters:
445 *psdio pointer of SDIO_DATA
446 *addr address to read
447 *cnt amount to read
448 *pdata pointer to put data, this should be a "DMA:able scratch buffer"!
449 *
450 * Return:
451 *0 Success
452 *others Fail
453 */
sd_read(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)454 s32 sd_read(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
455 {
456 struct adapter *padapter;
457 struct dvobj_priv *psdiodev;
458 struct sdio_data *psdio;
459
460 struct sdio_func *func;
461 bool claim_needed;
462 s32 err = -EPERM;
463
464 padapter = pintfhdl->padapter;
465 psdiodev = pintfhdl->pintf_dev;
466 psdio = &psdiodev->intf_data;
467
468 if (padapter->bSurpriseRemoved) {
469 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
470 return err;
471 }
472 func = psdio->func;
473 claim_needed = rtw_sdio_claim_host_needed(func);
474
475 if (claim_needed)
476 sdio_claim_host(func);
477 err = _sd_read(pintfhdl, addr, cnt, pdata);
478 if (claim_needed)
479 sdio_release_host(func);
480 return err;
481 }
482
483 /*
484 * Use CMD53 to write data to SDIO device.
485 * This function MUST be called after sdio_claim_host() or
486 * in SDIO ISR(host had been claimed).
487 *
488 * Parameters:
489 *psdio pointer of SDIO_DATA
490 *addr address to write
491 *cnt amount to write
492 *pdata data pointer, this should be a "DMA:able scratch buffer"!
493 *
494 * Return:
495 *0 Success
496 *others Fail
497 */
_sd_write(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)498 s32 _sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
499 {
500 struct adapter *padapter;
501 struct dvobj_priv *psdiodev;
502 struct sdio_data *psdio;
503
504 struct sdio_func *func;
505 u32 size;
506 s32 err = -EPERM;
507
508 padapter = pintfhdl->padapter;
509 psdiodev = pintfhdl->pintf_dev;
510 psdio = &psdiodev->intf_data;
511
512 if (padapter->bSurpriseRemoved) {
513 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
514 return err;
515 }
516
517 func = psdio->func;
518 /* size = sdio_align_size(func, cnt); */
519
520 if (unlikely((cnt == 1) || (cnt == 2))) {
521 int i;
522 u8 *pbuf = pdata;
523
524 for (i = 0; i < cnt; i++) {
525 sdio_writeb(func, *(pbuf+i), addr+i, &err);
526 if (err) {
527 DBG_871X(KERN_ERR "%s: FAIL!(%d) addr = 0x%05x val = 0x%02x\n", __func__, err, addr, *(pbuf+i));
528 break;
529 }
530 }
531
532 return err;
533 }
534
535 size = cnt;
536 err = sdio_memcpy_toio(func, addr, pdata, size);
537 if (err) {
538 DBG_871X(KERN_ERR "%s: FAIL(%d)! ADDR =%#x Size =%d(%d)\n", __func__, err, addr, cnt, size);
539 }
540 return err;
541 }
542
543 /*
544 * Use CMD53 to write data to SDIO device.
545 *
546 * Parameters:
547 * psdio pointer of SDIO_DATA
548 * addr address to write
549 * cnt amount to write
550 * pdata data pointer, this should be a "DMA:able scratch buffer"!
551 *
552 * Return:
553 * 0 Success
554 * others Fail
555 */
sd_write(struct intf_hdl * pintfhdl,u32 addr,u32 cnt,void * pdata)556 s32 sd_write(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, void *pdata)
557 {
558 struct adapter *padapter;
559 struct dvobj_priv *psdiodev;
560 struct sdio_data *psdio;
561 struct sdio_func *func;
562 bool claim_needed;
563 s32 err = -EPERM;
564
565 padapter = pintfhdl->padapter;
566 psdiodev = pintfhdl->pintf_dev;
567 psdio = &psdiodev->intf_data;
568
569 if (padapter->bSurpriseRemoved) {
570 /* DBG_871X(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n", __func__); */
571 return err;
572 }
573
574 func = psdio->func;
575 claim_needed = rtw_sdio_claim_host_needed(func);
576
577 if (claim_needed)
578 sdio_claim_host(func);
579 err = _sd_write(pintfhdl, addr, cnt, pdata);
580 if (claim_needed)
581 sdio_release_host(func);
582 return err;
583 }
584