GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / staging / rtl8723bs / os_dep / sdio_ops_linux.c
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
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
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
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  */
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  */
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  */
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  */
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
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
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
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
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  */
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  */
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  */
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  */
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 }