xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/core/rtw_sdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 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 _RTW_SDIO_C_
16 
17 #include <drv_types.h>		/* struct dvobj_priv and etc. */
18 #include <drv_types_sdio.h>	/* RTW_SDIO_ADDR_CMD52_GEN */
19 
20 /*
21  * Description:
22  *	Use SDIO cmd52 or cmd53 to read/write data
23  *
24  * Parameters:
25  *	d	pointer of device object(struct dvobj_priv)
26  *	addr	SDIO address, 17 bits
27  *	buf	buffer for I/O
28  *	len	length
29  *	write	0:read, 1:write
30  *	cmd52	0:cmd52, 1:cmd53
31  *
32  * Return:
33  *	_SUCCESS	I/O ok.
34  *	_FAIL		I/O fail.
35  */
sdio_io(struct dvobj_priv * d,u32 addr,void * buf,size_t len,u8 write,u8 cmd52)36 static u8 sdio_io(struct dvobj_priv *d, u32 addr, void *buf, size_t len, u8 write, u8 cmd52)
37 {
38 #ifdef DBG_SDIO
39 #if (DBG_SDIO >= 3)
40 	struct sdio_data *sdio = dvobj_to_sdio(d);
41 #endif /* DBG_SDIO >= 3 */
42 #endif /* DBG_SDIO */
43 	u32 addr_drv;	/* address with driver defined bit */
44 	int err;
45 	u8 retry = 0;
46 	u8 stop_retry = _FALSE;	/* flag for stopping retry or not */
47 
48 	if (dev_is_surprise_removed(d)) {
49 		RTW_ERR("%s: bSurpriseRemoved, skip %s 0x%05x, %zu bytes\n",
50 			__FUNCTION__, write?"write":"read", addr, len);
51 		return _FAIL;
52 	}
53 
54 	addr_drv = addr;
55 	if (cmd52)
56 		addr_drv = RTW_SDIO_ADDR_CMD52_GEN(addr_drv);
57 
58 	do {
59 		if (write)
60 			err = d->intf_ops->write(d, addr_drv, buf, len, 0);
61 		else
62 			err = d->intf_ops->read(d, addr_drv, buf, len, 0);
63 		if (!err) {
64 			if (retry) {
65 				RTW_INFO("%s: Retry %s OK! addr=0x%05x %zu bytes, retry=%u,%u\n",
66 					 __FUNCTION__, write?"write":"read",
67 					 addr, len, retry, ATOMIC_READ(&d->continual_io_error));
68 				RTW_INFO_DUMP("Data: ", buf, len);
69 			}
70 			rtw_reset_continual_io_error(d);
71 			break;
72 		}
73 		RTW_ERR("%s: %s FAIL! error(%d) addr=0x%05x %zu bytes, retry=%u,%u\n",
74 			__FUNCTION__, write?"write":"read", err, addr, len,
75 			retry, ATOMIC_READ(&d->continual_io_error));
76 
77 #ifdef DBG_SDIO
78 #if (DBG_SDIO >= 3)
79 		if (sdio->dbg_enable) {
80 			if (sdio->err_test && sdio->err_test_triggered)
81 				sdio->err_test = 0;
82 
83 			if (sdio->err_stop) {
84 				RTW_ERR("%s: I/O error! Set surprise remove flag ON!\n",
85 					__FUNCTION__);
86 				dev_set_surprise_removed(d);
87 				return _FAIL;
88 			}
89 		}
90 #endif /* DBG_SDIO >= 3 */
91 #endif /* DBG_SDIO */
92 
93 		retry++;
94 		stop_retry = rtw_inc_and_chk_continual_io_error(d);
95 		if ((err == -1) || (stop_retry == _TRUE) || (retry > SD_IO_TRY_CNT)) {
96 			/* critical error, unrecoverable */
97 			RTW_ERR("%s: Fatal error! Set surprise remove flag ON! (retry=%u,%u)\n",
98 				__FUNCTION__, retry, ATOMIC_READ(&d->continual_io_error));
99 			dev_set_surprise_removed(d);
100 			return _FAIL;
101 		}
102 
103 		/* WLAN IOREG or SDIO Local */
104 		if ((addr & 0x10000) || !(addr & 0xE000)) {
105 			RTW_WARN("%s: Retry %s addr=0x%05x %zu bytes, retry=%u,%u\n",
106 				 __FUNCTION__, write?"write":"read", addr, len,
107 				 retry, ATOMIC_READ(&d->continual_io_error));
108 			continue;
109 		}
110 		return _FAIL;
111 	} while (1);
112 
113 	return _SUCCESS;
114 }
115 
rtw_sdio_read_cmd52(struct dvobj_priv * d,u32 addr,void * buf,size_t len)116 u8 rtw_sdio_read_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
117 {
118 	return sdio_io(d, addr, buf, len, 0, 1);
119 }
120 
rtw_sdio_read_cmd53(struct dvobj_priv * d,u32 addr,void * buf,size_t len)121 u8 rtw_sdio_read_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
122 {
123 	return sdio_io(d, addr, buf, len, 0, 0);
124 }
125 
rtw_sdio_write_cmd52(struct dvobj_priv * d,u32 addr,void * buf,size_t len)126 u8 rtw_sdio_write_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
127 {
128 	return sdio_io(d, addr, buf, len, 1, 1);
129 }
130 
rtw_sdio_write_cmd53(struct dvobj_priv * d,u32 addr,void * buf,size_t len)131 u8 rtw_sdio_write_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
132 {
133 	return sdio_io(d, addr, buf, len, 1, 0);
134 }
135 
rtw_sdio_f0_read(struct dvobj_priv * d,u32 addr,void * buf,size_t len)136 u8 rtw_sdio_f0_read(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
137 {
138 	int err;
139 	u8 ret;
140 
141 
142 	ret = _SUCCESS;
143 	addr = RTW_SDIO_ADDR_F0_GEN(addr);
144 
145 	err = d->intf_ops->read(d, addr, buf, len, 0);
146 	if (err)
147 		ret = _FAIL;
148 
149 	return ret;
150 }
151 
152 /**
153  * rtw_sdio_cmd53_align_size() - Align size to one CMD53 could complete
154  * @d		struct dvobj_priv*
155  * @len		length to align
156  *
157  * Adjust len to align block size, and the new size could be transfered by one
158  * CMD53.
159  * If len < block size, it would keep original value, otherwise the value
160  * would be rounded up by block size.
161  *
162  * Return adjusted length.
163  */
rtw_sdio_cmd53_align_size(struct dvobj_priv * d,size_t len)164 size_t rtw_sdio_cmd53_align_size(struct dvobj_priv *d, size_t len)
165 {
166 	u32 blk_sz;
167 
168 
169 	blk_sz = rtw_sdio_get_block_size(d);
170 	if (len <= blk_sz)
171 		return len;
172 
173 	return _RND(len, blk_sz);
174 }
175