1 /******************************************************************************
2 *
3 * Copyright(c) 2015 - 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;
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
49 #ifdef DBG_SDIO
50 #if (DBG_SDIO >= 3)
51 sdio = &d->intf_data;
52 #endif /* DBG_SDIO >= 3 */
53 #endif /* DBG_SDIO */
54
55 if (rtw_is_surprise_removed(dvobj_get_primary_adapter(d))) {
56 RTW_ERR("%s: bSurpriseRemoved, skip %s 0x%05x, %zu bytes\n",
57 __FUNCTION__, write?"write":"read", addr, len);
58 return _FAIL;
59 }
60
61 addr_drv = addr;
62 if (cmd52)
63 addr_drv = RTW_SDIO_ADDR_CMD52_GEN(addr_drv);
64
65 do {
66 if (write)
67 err = d->intf_ops->write(d, addr_drv, buf, len, 0);
68 else
69 err = d->intf_ops->read(d, addr_drv, buf, len, 0);
70 if (!err) {
71 if (retry) {
72 RTW_INFO("%s: Retry %s OK! addr=0x%05x %zu bytes, retry=%u,%u\n",
73 __FUNCTION__, write?"write":"read",
74 addr, len, retry, ATOMIC_READ(&d->continual_io_error));
75 RTW_INFO_DUMP("Data: ", buf, len);
76 }
77 rtw_reset_continual_io_error(d);
78 break;
79 }
80 RTW_ERR("%s: %s FAIL! error(%d) addr=0x%05x %zu bytes, retry=%u,%u\n",
81 __FUNCTION__, write?"write":"read", err, addr, len,
82 retry, ATOMIC_READ(&d->continual_io_error));
83
84 #ifdef DBG_SDIO
85 #if (DBG_SDIO >= 3)
86 if (sdio->dbg_enable) {
87 if (sdio->err_test && sdio->err_test_triggered)
88 sdio->err_test = 0;
89
90 if (sdio->err_stop) {
91 RTW_ERR("%s: I/O error! Set surprise remove flag ON!\n",
92 __FUNCTION__);
93 rtw_set_surprise_removed(dvobj_get_primary_adapter(d));
94 return _FAIL;
95 }
96 }
97 #endif /* DBG_SDIO >= 3 */
98 #endif /* DBG_SDIO */
99
100 retry++;
101 stop_retry = rtw_inc_and_chk_continual_io_error(d);
102 if ((err == -1) || (stop_retry == _TRUE) || (retry > SD_IO_TRY_CNT)) {
103 /* critical error, unrecoverable */
104 RTW_ERR("%s: Fatal error! Set surprise remove flag ON! (retry=%u,%u)\n",
105 __FUNCTION__, retry, ATOMIC_READ(&d->continual_io_error));
106 rtw_set_surprise_removed(dvobj_get_primary_adapter(d));
107 return _FAIL;
108 }
109
110 /* WLAN IOREG or SDIO Local */
111 if ((addr & 0x10000) || !(addr & 0xE000)) {
112 RTW_WARN("%s: Retry %s addr=0x%05x %zu bytes, retry=%u,%u\n",
113 __FUNCTION__, write?"write":"read", addr, len,
114 retry, ATOMIC_READ(&d->continual_io_error));
115 continue;
116 }
117 return _FAIL;
118 } while (1);
119
120 return _SUCCESS;
121 }
122
rtw_sdio_read_cmd52(struct dvobj_priv * d,u32 addr,void * buf,size_t len)123 u8 rtw_sdio_read_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
124 {
125 return sdio_io(d, addr, buf, len, 0, 1);
126 }
127
rtw_sdio_read_cmd53(struct dvobj_priv * d,u32 addr,void * buf,size_t len)128 u8 rtw_sdio_read_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
129 {
130 return sdio_io(d, addr, buf, len, 0, 0);
131 }
132
rtw_sdio_write_cmd52(struct dvobj_priv * d,u32 addr,void * buf,size_t len)133 u8 rtw_sdio_write_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
134 {
135 return sdio_io(d, addr, buf, len, 1, 1);
136 }
137
rtw_sdio_write_cmd53(struct dvobj_priv * d,u32 addr,void * buf,size_t len)138 u8 rtw_sdio_write_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
139 {
140 return sdio_io(d, addr, buf, len, 1, 0);
141 }
142
rtw_sdio_f0_read(struct dvobj_priv * d,u32 addr,void * buf,size_t len)143 u8 rtw_sdio_f0_read(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
144 {
145 int err;
146 u8 ret;
147
148
149 ret = _SUCCESS;
150 addr = RTW_SDIO_ADDR_F0_GEN(addr);
151
152 err = d->intf_ops->read(d, addr, buf, len, 0);
153 if (err)
154 ret = _FAIL;
155
156 return ret;
157 }
158