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

source code of linux/drivers/staging/rtl8723bs/os_dep/sdio_ops_linux.c