Linux-libre 4.14.14-gnu
[librecmc/linux-libre.git] / drivers / staging / rtl8723bs / os_dep / sdio_ops_linux.c
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 = 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 = 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 }