xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/os_dep/linux/sdio_ops_linux.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2020 Realtek Corporation.
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 
rtw_is_sdio30(struct dvobj_priv * dvobj)19 inline bool rtw_is_sdio30(struct dvobj_priv *dvobj)
20 {
21 	PSDIO_DATA psdio_data = dvobj_to_sdio(dvobj);
22 
23 	return (psdio_data->sd3_bus_mode) ? _TRUE : _FALSE;
24 }
25 /* The unit of return value is Hz */
rtw_sdio_get_clock(struct dvobj_priv * d)26 inline u32 rtw_sdio_get_clock(struct dvobj_priv *d)
27 {
28 	return dvobj_to_sdio(d)->clock;
29 }
30 
rtw_sdio_claim_host_needed(struct sdio_func * func)31 static bool rtw_sdio_claim_host_needed(struct sdio_func *func)
32 {
33 	struct dvobj_priv *dvobj = sdio_get_drvdata(func);
34 	PSDIO_DATA sdio_data = dvobj_to_sdio(dvobj);
35 
36 	if (sdio_data->sys_sdio_irq_thd && sdio_data->sys_sdio_irq_thd == current)
37 		return _FALSE;
38 	return _TRUE;
39 }
40 
rtw_sdio_set_irq_thd(struct dvobj_priv * dvobj,_thread_hdl_ thd_hdl)41 inline void rtw_sdio_set_irq_thd(struct dvobj_priv *dvobj, _thread_hdl_ thd_hdl)
42 {
43 	PSDIO_DATA sdio_data = dvobj_to_sdio(dvobj);
44 
45 	sdio_data->sys_sdio_irq_thd = thd_hdl;
46 }
47 
48 /*
49  * Use CMD53 to read data from SDIO device.
50  * This function MUST be called after sdio_claim_host() or
51  * in SDIO ISR(host had been claimed).
52  *
53  * Parameters:
54  *	psdio	pointer of SDIO_DATA
55  *	addr	address to read
56  *	cnt		amount to read
57  *	pdata	pointer to put data, this should be a "DMA:able scratch buffer"!
58  *
59  * Return:
60  *	0		Success
61  *	others	Fail
62  */
_sd_read(struct dvobj_priv * dvobj,u32 addr,u32 cnt,void * pdata)63 s32 _sd_read(struct dvobj_priv *dvobj, u32 addr, u32 cnt, void *pdata)
64 {
65 	PSDIO_DATA psdio;
66 	int err = -EPERM;
67 	struct sdio_func *func;
68 
69 	psdio = dvobj_to_sdio(dvobj);
70 
71 	if (dev_is_surprise_removed(dvobj)) {
72 		/* RTW_INFO(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",__FUNCTION__); */
73 		return err;
74 	}
75 
76 	func = psdio->func;
77 
78 	if (unlikely((cnt == 1) || (cnt == 2))) {
79 		int i;
80 		u8 *pbuf = (u8 *)pdata;
81 
82 		for (i = 0; i < cnt; i++) {
83 			*(pbuf + i) = sdio_readb(func, addr + i, &err);
84 
85 			if (err) {
86 				RTW_ERR("%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
87 				break;
88 			}
89 		}
90 		return err;
91 	}
92 
93 	err = sdio_memcpy_fromio(func, pdata, addr, cnt);
94 	if (err)
95 		RTW_ERR("%s: FAIL(%d)! ADDR=%#x Size=%d\n", __func__, err, addr, cnt);
96 
97 	if (err == (-ESHUTDOWN) || err == (-ENODEV) || err == (-ENOMEDIUM) || err == (-ETIMEDOUT))
98 		dev_set_surprise_removed(dvobj);
99 
100 
101 	return err;
102 }
103 
104 /*
105  * Use CMD53 to read data from SDIO device.
106  *
107  * Parameters:
108  *	psdio	pointer of SDIO_DATA
109  *	addr	address to read
110  *	cnt		amount to read
111  *	pdata	pointer to put data, this should be a "DMA:able scratch buffer"!
112  *
113  * Return:
114  *	0		Success
115  *	others	Fail
116  */
sd_read(struct dvobj_priv * dvobj,u32 addr,u32 cnt,void * pdata)117 s32 sd_read(struct dvobj_priv *dvobj, u32 addr, u32 cnt, void *pdata)
118 {
119 	PSDIO_DATA psdio;
120 	struct sdio_func *func;
121 	bool claim_needed;
122 	s32 err = -EPERM;
123 
124 	psdio = dvobj_to_sdio(dvobj);
125 	if (dev_is_surprise_removed(dvobj)) {
126 		/* RTW_INFO(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",__FUNCTION__); */
127 		return err;
128 	}
129 	func = psdio->func;
130 	claim_needed = rtw_sdio_claim_host_needed(func);
131 
132 	if (claim_needed)
133 		sdio_claim_host(func);
134 	err = _sd_read(dvobj, addr, cnt, pdata);
135 	if (claim_needed)
136 		sdio_release_host(func);
137 	return err;
138 }
139 
140 /*
141  * Use CMD53 to write data to SDIO device.
142  * This function MUST be called after sdio_claim_host() or
143  * in SDIO ISR(host had been claimed).
144  *
145  * Parameters:
146  *	psdio	pointer of SDIO_DATA
147  *	addr	address to write
148  *	cnt		amount to write
149  *	pdata	data pointer, this should be a "DMA:able scratch buffer"!
150  *
151  * Return:
152  *	0		Success
153  *	others	Fail
154  */
_sd_write(struct dvobj_priv * dvobj,u32 addr,u32 cnt,void * pdata)155 s32 _sd_write(struct dvobj_priv *dvobj, u32 addr, u32 cnt, void *pdata)
156 {
157 	PSDIO_DATA psdio;
158 
159 	struct sdio_func *func;
160 	u32 size;
161 	s32 err = -EPERM;
162 
163 	psdio = dvobj_to_sdio(dvobj);
164 
165 	if (dev_is_surprise_removed(dvobj)) {
166 		/* RTW_INFO(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",__FUNCTION__); */
167 		return err;
168 	}
169 
170 	func = psdio->func;
171 	/*	size = sdio_align_size(func, cnt); */
172 
173 	if (unlikely((cnt == 1) || (cnt == 2))) {
174 		int i;
175 		u8 *pbuf = (u8 *)pdata;
176 
177 		for (i = 0; i < cnt; i++) {
178 			sdio_writeb(func, *(pbuf + i), addr + i, &err);
179 			if (err) {
180 				RTW_ERR("%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, *(pbuf + i));
181 				break;
182 			}
183 		}
184 
185 		return err;
186 	}
187 
188 	size = cnt;
189 	err = sdio_memcpy_toio(func, addr, pdata, size);
190 	if (err)
191 		RTW_ERR("%s: FAIL(%d)! ADDR=%#x Size=%d(%d)\n", __func__, err, addr, cnt, size);
192 
193 
194 	return err;
195 }
196 
197 /*
198  * Use CMD53 to write data to SDIO device.
199  *
200  * Parameters:
201  *  psdio	pointer of SDIO_DATA
202  *  addr	address to write
203  *  cnt		amount to write
204  *  pdata	data pointer, this should be a "DMA:able scratch buffer"!
205  *
206  * Return:
207  *  0		Success
208  *  others	Fail
209  */
sd_write(struct dvobj_priv * dvobj,u32 addr,u32 cnt,void * pdata)210 s32 sd_write(struct dvobj_priv *dvobj, u32 addr, u32 cnt, void *pdata)
211 {
212 	PSDIO_DATA psdio;
213 	struct sdio_func *func;
214 	bool claim_needed;
215 	s32 err = -EPERM;
216 
217 	psdio = dvobj_to_sdio(dvobj);
218 
219 	if (dev_is_surprise_removed(dvobj)) {
220 		/* RTW_INFO(" %s (padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n",__FUNCTION__); */
221 		return err;
222 	}
223 
224 	func = psdio->func;
225 	claim_needed = rtw_sdio_claim_host_needed(func);
226 
227 	if (claim_needed)
228 		sdio_claim_host(func);
229 	err = _sd_write(dvobj, addr, cnt, pdata);
230 	if (claim_needed)
231 		sdio_release_host(func);
232 	return err;
233 }
234 
235 /*#define RTW_SDIO_DUMP*/
236 #ifdef RTW_SDIO_DUMP
237 #define DUMP_LEN_LMT	0	/* buffer dump size limit */
238 				/* unit: byte, 0 for no limit */
239 #else
240 #define DUMP_LEN_LMT	32
241 #endif
242 #define GET_DUMP_LEN(len)	(DUMP_LEN_LMT ? rtw_min(len, DUMP_LEN_LMT) : len)
243 
244 #ifdef DBG_SDIO
245 #if (DBG_SDIO >= 1)
sdio_dump_reg_by_cmd52(struct dvobj_priv * d,u32 addr,size_t len,u8 * buf)246 static void sdio_dump_reg_by_cmd52(struct dvobj_priv *d,
247 				   u32 addr, size_t len, u8 *buf)
248 {
249 	struct sdio_func *func;
250 	size_t i;
251 	u8 val;
252 	u8 str[80], used = 0;
253 	u8 read_twice = 0;
254 	int error;
255 
256 
257 	if (buf)
258 		_rtw_memset(buf, 0xAE, len);
259 	func = dvobj_to_sdio_func(d);
260 	/*
261 	 * When register is WLAN IOREG,
262 	 * read twice to guarantee the result is correct.
263 	 */
264 	if (addr & 0x10000)
265 		read_twice = 1;
266 
267 	_rtw_memset(str, 0, 80);
268 	used = 0;
269 	if (addr & 0xF) {
270 		used += snprintf(str+used, (80-used), "0x%02x:\t", addr&~0xF);
271 		used += snprintf(str+used, (80-used), "%*s", (addr&0xF)*5, "");
272 	}
273 	for (i = 0; i < len; i++, addr++) {
274 		val = sdio_readb(func, addr, &error);
275 		if (read_twice)
276 			val = sdio_readb(func, addr, &error);
277 		if (error)
278 			break;
279 
280 		if (buf)
281 			buf[i] = val;
282 
283 		if (!(addr & 0xF))
284 			used += snprintf(str+used, (80-used), "0x%02x:\t", addr&~0xF);
285 		used += snprintf(str+used, (80-used), "%02x ", val);
286 		if (((i + 1) < len) && ((addr + 1) & 0xF) == 0) {
287 			dev_err(&func->dev, "%s", str);
288 			_rtw_memset(str, 0, 80);
289 			used = 0;
290 		}
291 	}
292 
293 	if (used) {
294 		dev_err(&func->dev, "%s", str);
295 		_rtw_memset(str, 0, 80);
296 		used = 0;
297 	}
298 
299 	if (error)
300 		dev_err(&func->dev, "rtw_sdio_dbg: READ 0x%02x FAIL!", addr);
301 }
302 
sdio_dump_cia(struct dvobj_priv * d,u32 addr,size_t len,u8 * buf)303 static void sdio_dump_cia(struct dvobj_priv *d, u32 addr, size_t len, u8 *buf)
304 {
305 	struct sdio_func *func;
306 	size_t i;
307 	u8 val;
308 	u8 str[80], used = 0;
309 	int error;
310 
311 
312 	if (buf)
313 		_rtw_memset(buf, 0xAE, len);
314 	func = dvobj_to_sdio_func(d);
315 
316 	_rtw_memset(str, 0, 80);
317 	used = 0;
318 	if (addr & 0xF) {
319 		used += snprintf(str+used, (80-used), "0x%02x:\t", addr&~0xF);
320 		used += snprintf(str+used, (80-used), "%*s", (addr&0xF)*5, "");
321 	}
322 	for (i = 0; i < len; i++, addr++) {
323 		val = sdio_f0_readb(func, addr, &error);
324 		if (error)
325 			break;
326 
327 		if (buf)
328 			buf[i] = val;
329 
330 		if (!(addr & 0xF))
331 			used += snprintf(str+used, (80-used), "0x%02x:\t", addr&~0xF);
332 		used += snprintf(str+used, (80-used), "%02x ", val);
333 		if (((i + 1) < len) && ((addr + 1) & 0xF) == 0) {
334 			dev_err(&func->dev, "%s", str);
335 			_rtw_memset(str, 0, 80);
336 			used = 0;
337 		}
338 	}
339 
340 	if (used) {
341 		dev_err(&func->dev, "%s", str);
342 		_rtw_memset(str, 0, 80);
343 		used = 0;
344 	}
345 
346 	if (error)
347 		dev_err(&func->dev, "rtw_sdio_dbg: READ CIA 0x%02x FAIL!",
348 			addr);
349 }
350 
351 #if (DBG_SDIO >= 2)
352 void rtw_sdio_dbg_reg_alloc(struct dvobj_priv *d);
353 #endif /* DBG_SDIO >= 2 */
354 
355 /*
356  * Dump register when CMD53 fail
357  */
sdio_dump_dbg_reg(struct dvobj_priv * d,u8 write,unsigned int addr,size_t len)358 static void sdio_dump_dbg_reg(struct dvobj_priv *d, u8 write,
359 			      unsigned int addr, size_t len)
360 {
361 	struct sdio_data *sdio;
362 	struct sdio_func *func;
363 	u8 *buf = NULL;
364 #if (DBG_SDIO >= 2)
365 	u8 *msg;
366 #endif /* DBG_SDIO >= 2 */
367 
368 
369 	sdio = dvobj_to_sdio(d);
370 	if (sdio->reg_dump_mark)
371 		return;
372 	func = dvobj_to_sdio_func(d);
373 
374 	sdio->reg_dump_mark = sdio->cmd53_err_cnt;
375 
376 #if (DBG_SDIO >= 2)
377 	if (!sdio->dbg_msg) {
378 		msg = rtw_zmalloc(80);
379 		if (msg) {
380 			sdio->dbg_msg = msg;
381 			sdio->dbg_msg_size = 80;
382 		}
383 	}
384 	if (sdio->dbg_msg_size) {
385 		snprintf(sdio->dbg_msg, sdio->dbg_msg_size,
386 			 "CMD53 %s 0x%05x, %zu bytes FAIL "
387 			 "at err_cnt=%d",
388 			 write?"WRITE":"READ",
389 			 addr, len, sdio->reg_dump_mark);
390 	}
391 
392 	rtw_sdio_dbg_reg_alloc(d);
393 #endif /* DBG_SDIO >= 2 */
394 
395 	/* MAC register */
396 	dev_err(&func->dev, "MAC register:");
397 #if (DBG_SDIO >= 2)
398 	buf = sdio->reg_mac;
399 #endif /* DBG_SDIO >= 2 */
400 	sdio_dump_reg_by_cmd52(d, 0x10000, 0x800, buf);
401 	dev_err(&func->dev, "MAC Extend register:");
402 #if (DBG_SDIO >= 2)
403 	buf = sdio->reg_mac_ext;
404 #endif /* DBG_SDIO >= 2 */
405 	sdio_dump_reg_by_cmd52(d, 0x11000, 0x800, buf);
406 
407 	/* SDIO local register */
408 	dev_err(&func->dev, "SDIO Local register:");
409 #if (DBG_SDIO >= 2)
410 	buf = sdio->reg_local;
411 #endif /* DBG_SDIO >= 2 */
412 	sdio_dump_reg_by_cmd52(d, 0x0, 0x100, buf);
413 
414 	/* F0 */
415 	dev_err(&func->dev, "f0 register:");
416 #if (DBG_SDIO >= 2)
417 	buf = sdio->reg_cia;
418 #endif /* DBG_SDIO >= 2 */
419 	sdio_dump_cia(d, 0x0, 0x200, buf);
420 }
421 #endif /* DBG_SDIO >= 1 */
422 #endif /* DBG_SDIO */
423 
424 /**
425  *	Returns driver error code,
426  *	0	no error
427  *	-1	Level 1 error, critical error and can't be recovered
428  *	-2	Level 2 error, normal error, retry to recover is possible
429  */
linux_io_err_to_drv_err(int err)430 static int linux_io_err_to_drv_err(int err)
431 {
432 	if (!err)
433 		return 0;
434 
435 	/* critical error */
436 	if ((err == -ESHUTDOWN) ||
437 	    (err == -ENODEV) ||
438 	    (err == -ENOMEDIUM))
439 		return -1;
440 
441 	/* other error */
442 	return -2;
443 }
444 
445 /**
446  *	rtw_sdio_raw_read - Read from SDIO device
447  *	@d: driver object private data
448  *	@addr: address to read
449  *	@buf: buffer to store the data
450  *	@len: number of bytes to read
451  *	@fixed:
452  *
453  *	Reads from the address space of a SDIO device.
454  *	Return value indicates if the transfer succeeded or not.
455  */
rtw_sdio_raw_read(struct dvobj_priv * d,unsigned int addr,void * buf,size_t len,bool fixed)456 int __must_check rtw_sdio_raw_read(struct dvobj_priv *d, unsigned int addr,
457 				   void *buf, size_t len, bool fixed)
458 {
459 	int error = -EPERM;
460 	bool f0, cmd52;
461 	struct sdio_func *func;
462 	bool claim_needed;
463 	u32 offset, i;
464 	struct sdio_data *sdio;
465 	u8 *tmpbuf = NULL;
466 
467 
468 	func = dvobj_to_sdio_func(d);
469 	claim_needed = rtw_sdio_claim_host_needed(func);
470 	f0 = RTW_SDIO_ADDR_F0_CHK(addr);
471 	cmd52 = RTW_SDIO_ADDR_CMD52_CHK(addr);
472 	sdio = dvobj_to_sdio(d);
473 
474 	/*
475 	 * Mask addr to remove driver defined bit and
476 	 * make sure addr is in valid range
477 	 */
478 	if (f0)
479 		addr &= 0xFFF;
480 	else
481 		addr &= 0x1FFFF;
482 
483 #ifdef RTW_SDIO_DUMP
484 	if (f0)
485 		dev_dbg(&func->dev, "RTW_SDIO: READ F0\n");
486 	else if (cmd52)
487 		dev_dbg(&func->dev, "RTW_SDIO: READ use CMD52\n");
488 	else
489 		dev_dbg(&func->dev, "RTW_SDIO: READ use CMD53\n");
490 
491 	dev_dbg(&func->dev, "RTW_SDIO: READ from 0x%05x\n", addr);
492 #endif /* RTW_SDIO_DUMP */
493 
494 	if (claim_needed)
495 		sdio_claim_host(func);
496 
497 	if (f0) {
498 		offset = addr;
499 		for (i = 0; i < len; i++, offset++) {
500 			((u8 *)buf)[i] = sdio_f0_readb(func, offset, &error);
501 			if (error)
502 				break;
503 #if 0
504 			dev_info(&func->dev, "%s: sdio f0 read 52 addr 0x%x, byte 0x%02x\n",
505 				 __func__, offset, ((u8 *)buf)[i]);
506 #endif
507 		}
508 	} else {
509 		if (cmd52) {
510 #ifdef RTW_SDIO_IO_DBG
511 			dev_info(&func->dev, "%s: sdio read 52 addr 0x%x, %zu bytes\n",
512 				 __func__, addr, len);
513 #endif
514 			offset = addr;
515 			for (i = 0; i < len; i++) {
516 				((u8 *)buf)[i] = sdio_readb(func, offset, &error);
517 				if (error)
518 					break;
519 #if 0
520 				dev_info(&func->dev, "%s: sdio read 52 addr 0x%x, byte 0x%02x\n",
521 					 __func__, offset, ((u8 *)buf)[i]);
522 #endif
523 				if (!fixed)
524 					offset++;
525 			}
526 		} else {
527 #ifdef RTW_SDIO_IO_DBG
528 			dev_info(&func->dev, "%s: sdio read 53 addr 0x%x, %zu bytes\n",
529 				 __func__, addr, len);
530 #endif
531 			if (len <= sdio->tmpbuf_sz) {
532 				tmpbuf = buf;
533 				buf = sdio->tmpbuf;
534 			}
535 			if (fixed)
536 				error = sdio_readsb(func, buf, addr, len);
537 			else
538 				error = sdio_memcpy_fromio(func, buf, addr, len);
539 			if (!error && tmpbuf)
540 				_rtw_memcpy(tmpbuf, buf, len);
541 		}
542 	}
543 
544 #ifdef DBG_SDIO
545 #if (DBG_SDIO >= 3)
546 	if (!error && !f0 && !cmd52
547 	    && (sdio->dbg_enable
548 		&& sdio->err_test && !sdio->err_test_triggered
549 		&& ((addr & 0x10000)
550 		    || (!(addr & 0xE000)
551 			&& !((addr >= 0x40) && (addr < 0x48)))))) {
552 		sdio->err_test_triggered = 1;
553 		error = -ETIMEDOUT;
554 		dev_warn(&func->dev, "Simulate error(%d) READ addr=0x%05x %zu bytes",
555 			 error, addr, len);
556 	}
557 #endif /* DBG_SDIO >= 3 */
558 
559 	if (error) {
560 		if (f0 || cmd52) {
561 			sdio->cmd52_err_cnt++;
562 		} else {
563 			sdio->cmd53_err_cnt++;
564 #if (DBG_SDIO >= 1)
565 			sdio_dump_dbg_reg(d, 0, addr, len);
566 #endif /* DBG_SDIO >= 1 */
567 		}
568 	}
569 #endif /* DBG_SDIO */
570 
571 	if (claim_needed)
572 		sdio_release_host(func);
573 
574 #ifdef RTW_SDIO_DUMP
575 	print_hex_dump(KERN_DEBUG, "RTW_SDIO: READ ",
576 		       DUMP_PREFIX_OFFSET, 16, 1,
577 		       buf, GET_DUMP_LEN(len), false);
578 #endif /* RTW_SDIO_DUMP */
579 
580 	if (WARN_ON(error)) {
581 		dev_err(&func->dev, "%s: sdio read failed (%d)\n", __func__, error);
582 #ifndef RTW_SDIO_DUMP
583 		if (f0)
584 			dev_err(&func->dev, "RTW_SDIO: READ F0\n");
585 		if (cmd52)
586 			dev_err(&func->dev, "RTW_SDIO: READ use CMD52\n");
587 		else
588 			dev_err(&func->dev, "RTW_SDIO: READ use CMD53\n");
589 		dev_err(&func->dev, "RTW_SDIO: READ from 0x%05x, %zu bytes\n", addr, len);
590 		print_hex_dump(KERN_ERR, "RTW_SDIO: READ ",
591 			       DUMP_PREFIX_OFFSET, 16, 1,
592 			       buf, GET_DUMP_LEN(len), false);
593 #endif /* !RTW_SDIO_DUMP */
594 	}
595 
596 	return linux_io_err_to_drv_err(error);
597 }
598 
599 /**
600  *	rtw_sdio_raw_write - Write to SDIO device
601  *	@d: driver object private data
602  *	@addr: address to write
603  *	@buf: buffer that contains the data to write
604  *	@len: number of bytes to write
605  *	@fixed: address is fixed(FIFO) or incremented
606  *
607  *	Writes to the address space of a SDIO device.
608  *	Return value indicates if the transfer succeeded or not.
609  */
rtw_sdio_raw_write(struct dvobj_priv * d,unsigned int addr,void * buf,size_t len,bool fixed)610 int __must_check rtw_sdio_raw_write(struct dvobj_priv *d, unsigned int addr,
611 				    void *buf, size_t len, bool fixed)
612 {
613 	int error = -EPERM;
614 	bool f0, cmd52;
615 	struct sdio_func *func;
616 	bool claim_needed;
617 	u32 offset, i;
618 	struct sdio_data *sdio;
619 
620 
621 	func = dvobj_to_sdio_func(d);
622 	claim_needed = rtw_sdio_claim_host_needed(func);
623 	f0 = RTW_SDIO_ADDR_F0_CHK(addr);
624 	cmd52 = RTW_SDIO_ADDR_CMD52_CHK(addr);
625 	sdio = dvobj_to_sdio(d);
626 
627 	/*
628 	 * Mask addr to remove driver defined bit and
629 	 * make sure addr is in valid range
630 	 */
631 	if (f0)
632 		addr &= 0xFFF;
633 	else
634 		addr &= 0x1FFFF;
635 
636 #ifdef RTW_SDIO_DUMP
637 	if (f0)
638 		dev_dbg(&func->dev, "RTW_SDIO: WRITE F0\n");
639 	else if (cmd52)
640 		dev_dbg(&func->dev, "RTW_SDIO: WRITE use CMD52\n");
641 	else
642 		dev_dbg(&func->dev, "RTW_SDIO: WRITE use CMD53\n");
643 	dev_dbg(&func->dev, "RTW_SDIO: WRITE to 0x%05x\n", addr);
644 	print_hex_dump(KERN_DEBUG, "RTW_SDIO: WRITE ",
645 		       DUMP_PREFIX_OFFSET, 16, 1,
646 		       buf, GET_DUMP_LEN(len), false);
647 #endif /* RTW_SDIO_DUMP */
648 
649 	if (claim_needed)
650 		sdio_claim_host(func);
651 
652 	if (f0) {
653 		offset = addr;
654 		for (i = 0; i < len; i++, offset++) {
655 			sdio_f0_writeb(func, ((u8 *)buf)[i], offset, &error);
656 			if (error)
657 				break;
658 #if 0
659 			dev_info(&func->dev, "%s: sdio f0 write 52 addr 0x%x, byte 0x%02x\n",
660 				 __func__, offset, ((u8 *)buf)[i]);
661 #endif
662 		}
663 	} else {
664 		if (cmd52) {
665 #ifdef RTW_SDIO_IO_DBG
666 			dev_info(&func->dev, "%s: sdio write 52 addr 0x%x, %zu bytes\n",
667 				 __func__, addr, len);
668 #endif
669 			offset = addr;
670 			for (i = 0; i < len; i++) {
671 				sdio_writeb(func, ((u8 *)buf)[i], offset, &error);
672 				if (error)
673 					break;
674 #if 0
675 				dev_info(&func->dev, "%s: sdio write 52 addr 0x%x, byte 0x%02x\n",
676 					 __func__, offset, ((u8 *)buf)[i]);
677 #endif
678 				if (!fixed)
679 					offset++;
680 			}
681 		} else {
682 #ifdef RTW_SDIO_IO_DBG
683 			dev_info(&func->dev, "%s: sdio write 53 addr 0x%x, %zu bytes\n",
684 				 __func__, addr, len);
685 #endif
686 			if (len <= sdio->tmpbuf_sz) {
687 				_rtw_memcpy(sdio->tmpbuf, buf, len);
688 				buf = sdio->tmpbuf;
689 			}
690 			if (fixed)
691 				error = sdio_writesb(func, addr, buf, len);
692 			else
693 				error = sdio_memcpy_toio(func, addr, buf, len);
694 		}
695 	}
696 
697 #ifdef DBG_SDIO
698 	if (error) {
699 		if (f0 || cmd52) {
700 			sdio->cmd52_err_cnt++;
701 		} else {
702 			sdio->cmd53_err_cnt++;
703 #if (DBG_SDIO >= 1)
704 			sdio_dump_dbg_reg(d, 1, addr, len);
705 #endif /* DBG_SDIO >= 1 */
706 		}
707 	}
708 #endif /* DBG_SDIO */
709 
710 	if (claim_needed)
711 		sdio_release_host(func);
712 
713 	if (WARN_ON(error)) {
714 		dev_err(&func->dev, "%s: sdio write failed (%d)\n", __func__, error);
715 #ifndef RTW_SDIO_DUMP
716 		if (f0)
717 			dev_err(&func->dev, "RTW_SDIO: WRITE F0\n");
718 		if (cmd52)
719 			dev_err(&func->dev, "RTW_SDIO: WRITE use CMD52\n");
720 		else
721 			dev_err(&func->dev, "RTW_SDIO: WRITE use CMD53\n");
722 		dev_err(&func->dev, "RTW_SDIO: WRITE to 0x%05x, %zu bytes\n", addr, len);
723 		print_hex_dump(KERN_ERR, "RTW_SDIO: WRITE ",
724 			       DUMP_PREFIX_OFFSET, 16, 1,
725 			       buf, GET_DUMP_LEN(len), false);
726 #endif /* !RTW_SDIO_DUMP */
727 	}
728 
729 	return linux_io_err_to_drv_err(error);
730 }
731