xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/rtl8822b/pci/rtl8822be_io.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2015 - 2016 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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTL8822BE_IO_C_
21 
22 #include <drv_types.h>		/* PADAPTER and etc. */
23 
24 #ifdef RTK_129X_PLATFORM
25 #include <soc/realtek/rtd129x_lockapi.h>
26 
27 #define IO_2K_MASK 0xFFFFF800
28 #define IO_4K_MASK 0xFFFFF000
29 #define MAX_RETRY 5
30 
pci_io_read_129x(struct dvobj_priv * pdvobjpriv,u32 addr,u8 size)31 static u32 pci_io_read_129x(struct dvobj_priv *pdvobjpriv, u32 addr, u8 size)
32 {
33 	unsigned long mask_addr = pdvobjpriv->mask_addr;
34 	unsigned long tran_addr = pdvobjpriv->tran_addr;
35 	u8 busnumber = pdvobjpriv->pcipriv.busnumber;
36 	u32 rval = 0;
37 	u32 mask;
38 	u32 translate_val = 0;
39 	u32 tmp_addr = addr & 0xFFF;
40 	_irqL irqL;
41 	u32 pci_error_status = 0;
42 	int retry_cnt = 0;
43 	unsigned long flags;
44 
45 	_enter_critical(&pdvobjpriv->io_reg_lock, &irqL);
46 
47 	/* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
48 	 * can't be used because of 1295 hardware issue.
49 	 */
50 	if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
51 	    (tmp_addr == 0xC68))) {
52 		mask = IO_2K_MASK;
53 		writel(0xFFFFF800, (u8 *)mask_addr);
54 		translate_val = readl((u8 *)tran_addr);
55 		writel(translate_val|(addr&mask), (u8 *)tran_addr);
56 	} else if (addr >= 0x1000) {
57 		mask = IO_4K_MASK;
58 		translate_val = readl((u8 *)tran_addr);
59 		writel(translate_val|(addr&mask), (u8 *)tran_addr);
60 	} else
61 		mask = 0x0;
62 
63 pci_read_129x_retry:
64 
65 	/* All RBUS1 driver need to have a workaround for emmc hardware error */
66 	/* Need to protect 0xXXXX_X8XX~ 0xXXXX_X9XX */
67 	if ((tmp_addr>0x7FF) && (tmp_addr<0xA00))
68 		rtk_lockapi_lock(flags, __func__);
69 
70 	switch (size) {
71 	case 1:
72 		rval = readb((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
73 		break;
74 	case 2:
75 		rval = readw((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
76 		break;
77 	case 4:
78 		rval = readl((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
79 		break;
80 	default:
81 		RTW_WARN("RTD129X: %s: wrong size %d\n", __func__, size);
82 		break;
83 	}
84 
85 	if ((tmp_addr>0x7FF) && (tmp_addr<0xA00))
86 		rtk_lockapi_unlock(flags, __func__);
87 
88 	//DLLP error patch
89 	pci_error_status = readl( (u8 *)(pdvobjpriv->ctrl_start + 0x7C));
90 	if(pci_error_status & 0x1F) {
91 		writel(pci_error_status, (u8 *)(pdvobjpriv->ctrl_start + 0x7C));
92 		RTW_WARN("RTD129X: %s: DLLP(#%d) 0x%x reg=0x%x val=0x%x\n", __func__, retry_cnt, pci_error_status, addr, rval);
93 
94 		if(retry_cnt < MAX_RETRY) {
95 			retry_cnt++;
96 			goto pci_read_129x_retry;
97 		}
98 	}
99 
100 	/* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
101 	 * can't be used because of 1295 hardware issue.
102 	 */
103 	if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
104 	    (tmp_addr == 0xC68))) {
105 		writel(translate_val, (u8 *)tran_addr);
106 		writel(0xFFFFF000, (u8 *)mask_addr);
107 	} else if (addr >= 0x1000) {
108 		writel(translate_val, (u8 *)tran_addr);
109 	}
110 
111 	_exit_critical(&pdvobjpriv->io_reg_lock, &irqL);
112 
113 	return rval;
114 }
115 
pci_io_write_129x(struct dvobj_priv * pdvobjpriv,u32 addr,u8 size,u32 wval)116 static void pci_io_write_129x(struct dvobj_priv *pdvobjpriv,
117 			      u32 addr, u8 size, u32 wval)
118 {
119 	unsigned long mask_addr = pdvobjpriv->mask_addr;
120 	unsigned long tran_addr = pdvobjpriv->tran_addr;
121 	u8 busnumber = pdvobjpriv->pcipriv.busnumber;
122 	u32 mask;
123 	u32 translate_val = 0;
124 	u32 tmp_addr = addr & 0xFFF;
125 	_irqL irqL;
126 	unsigned long flags;
127 
128 	_enter_critical(&pdvobjpriv->io_reg_lock, &irqL);
129 
130 	/* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
131 	 * can't be used because of 1295 hardware issue.
132 	 */
133 	if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
134 	    (tmp_addr == 0xC68))) {
135 		mask = IO_2K_MASK;
136 		writel(0xFFFFF800, (u8 *)mask_addr);
137 		translate_val = readl((u8 *)tran_addr);
138 		writel(translate_val|(addr&mask), (u8 *)tran_addr);
139 	} else if (addr >= 0x1000) {
140 		mask = IO_4K_MASK;
141 		translate_val = readl((u8 *)tran_addr);
142 		writel(translate_val|(addr&mask), (u8 *)tran_addr);
143 	} else
144 		mask = 0x0;
145 
146 	/* All RBUS1 driver need to have a workaround for emmc hardware error */
147 	/* Need to protect 0xXXXX_X8XX~ 0xXXXX_X9XX */
148 	if ((tmp_addr>0x7FF) && (tmp_addr<0xA00))
149 		rtk_lockapi_lock(flags, __func__);
150 
151 	switch (size) {
152 	case 1:
153 		writeb((u8)wval,
154 		       (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
155 		break;
156 	case 2:
157 		writew((u16)wval,
158 		       (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
159 		break;
160 	case 4:
161 		writel((u32)wval,
162 		       (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
163 		break;
164 	default:
165 		RTW_WARN("RTD129X: %s: wrong size %d\n", __func__, size);
166 		break;
167 	}
168 
169 	if ((tmp_addr>0x7FF) && (tmp_addr<0xA00))
170 		rtk_lockapi_unlock(flags, __func__);
171 
172 	/* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
173 	 * can't be used because of 1295 hardware issue.
174 	 */
175 	if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
176 	    (tmp_addr == 0xC68))) {
177 		writel(translate_val, (u8 *)tran_addr);
178 		writel(0xFFFFF000, (u8 *)mask_addr);
179 	} else if (addr >= 0x1000) {
180 		writel(translate_val, (u8 *)tran_addr);
181 	}
182 
183 	_exit_critical(&pdvobjpriv->io_reg_lock, &irqL);
184 }
185 
pci_read8_129x(struct intf_hdl * phdl,u32 addr)186 static u8 pci_read8_129x(struct intf_hdl *phdl, u32 addr)
187 {
188 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
189 
190 	return (u8)pci_io_read_129x(pdvobjpriv, addr, 1);
191 }
192 
pci_read16_129x(struct intf_hdl * phdl,u32 addr)193 static u16 pci_read16_129x(struct intf_hdl *phdl, u32 addr)
194 {
195 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
196 
197 	return (u16)pci_io_read_129x(pdvobjpriv, addr, 2);
198 }
199 
pci_read32_129x(struct intf_hdl * phdl,u32 addr)200 static u32 pci_read32_129x(struct intf_hdl *phdl, u32 addr)
201 {
202 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
203 
204 	return (u32)pci_io_read_129x(pdvobjpriv, addr, 4);
205 }
206 
207 /*
208  * 2009.12.23. by tynli. Suggested by SD1 victorh.
209  * For ASPM hang on AMD and Nvidia.
210  * 20100212 Tynli: Do read IO operation after write for
211  * all PCI bridge suggested by SD1. Origianally this is only for INTEL.
212  */
pci_write8_129x(struct intf_hdl * phdl,u32 addr,u8 val)213 static int pci_write8_129x(struct intf_hdl *phdl, u32 addr, u8 val)
214 {
215 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
216 
217 	pci_io_write_129x(pdvobjpriv, addr, 1, val);
218 	return 1;
219 }
220 
pci_write16_129x(struct intf_hdl * phdl,u32 addr,u16 val)221 static int pci_write16_129x(struct intf_hdl *phdl, u32 addr, u16 val)
222 {
223 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
224 
225 	pci_io_write_129x(pdvobjpriv, addr, 2, val);
226 	return 2;
227 }
228 
pci_write32_129x(struct intf_hdl * phdl,u32 addr,u32 val)229 static int pci_write32_129x(struct intf_hdl *phdl, u32 addr, u32 val)
230 {
231 	struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)phdl->pintf_dev;
232 
233 	pci_io_write_129x(pdvobjpriv, addr, 4, val);
234 	return 4;
235 }
236 
237 #else /* original*/
238 
pci_read8(struct intf_hdl * phdl,u32 addr)239 static u8 pci_read8(struct intf_hdl *phdl, u32 addr)
240 {
241 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
242 
243 	return 0xff & readb((u8 *)pdvobjpriv->pci_mem_start + addr);
244 }
245 
pci_read16(struct intf_hdl * phdl,u32 addr)246 static u16 pci_read16(struct intf_hdl *phdl, u32 addr)
247 {
248 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
249 
250 	return readw((u8 *)pdvobjpriv->pci_mem_start + addr);
251 }
252 
pci_read32(struct intf_hdl * phdl,u32 addr)253 static u32 pci_read32(struct intf_hdl *phdl, u32 addr)
254 {
255 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
256 
257 	return readl((u8 *)pdvobjpriv->pci_mem_start + addr);
258 }
259 
260 /*
261  * 2009.12.23. by tynli. Suggested by SD1 victorh.
262  * For ASPM hang on AMD and Nvidia.
263  * 20100212 Tynli: Do read IO operation after write for
264  * all PCI bridge suggested by SD1. Origianally this is only for INTEL.
265  */
pci_write8(struct intf_hdl * phdl,u32 addr,u8 val)266 static int pci_write8(struct intf_hdl *phdl, u32 addr, u8 val)
267 {
268 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
269 
270 	writeb(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
271 	return 1;
272 }
273 
pci_write16(struct intf_hdl * phdl,u32 addr,u16 val)274 static int pci_write16(struct intf_hdl *phdl, u32 addr, u16 val)
275 {
276 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
277 
278 	writew(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
279 	return 2;
280 }
281 
pci_write32(struct intf_hdl * phdl,u32 addr,u32 val)282 static int pci_write32(struct intf_hdl *phdl, u32 addr, u32 val)
283 {
284 	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
285 
286 	writel(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
287 	return 4;
288 }
289 #endif /* RTK_129X_PLATFORM */
290 
pci_read_mem(struct intf_hdl * phdl,u32 addr,u32 cnt,u8 * rmem)291 static void pci_read_mem(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *rmem)
292 {
293 	RTW_INFO("%s(%d)fake function\n", __func__, __LINE__);
294 }
295 
pci_write_mem(struct intf_hdl * phdl,u32 addr,u32 cnt,u8 * wmem)296 static void pci_write_mem(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *wmem)
297 {
298 	RTW_INFO("%s(%d)fake function\n", __func__, __LINE__);
299 }
300 
pci_read_port(struct intf_hdl * phdl,u32 addr,u32 cnt,u8 * rmem)301 static u32 pci_read_port(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *rmem)
302 {
303 	return 0;
304 }
305 
pci_write_port(struct intf_hdl * phdl,u32 addr,u32 cnt,u8 * wmem)306 static u32 pci_write_port(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *wmem)
307 {
308 	_adapter *padapter = (_adapter *)phdl->padapter;
309 
310 	padapter->pnetdev->trans_start = jiffies;
311 
312 	return 0;
313 }
314 
rtl8822be_set_intf_ops(struct _io_ops * pops)315 void rtl8822be_set_intf_ops(struct _io_ops *pops)
316 {
317 	_func_enter_;
318 
319 	_rtw_memset((u8 *)pops, 0, sizeof(struct _io_ops));
320 
321 #ifdef RTK_129X_PLATFORM
322 	pops->_read8 = &pci_read8_129x;
323 	pops->_read16 = &pci_read16_129x;
324 	pops->_read32 = &pci_read32_129x;
325 #else
326 	pops->_read8 = &pci_read8;
327 	pops->_read16 = &pci_read16;
328 	pops->_read32 = &pci_read32;
329 #endif /* RTK_129X_PLATFORM */
330 
331 	pops->_read_mem = &pci_read_mem;
332 	pops->_read_port = &pci_read_port;
333 
334 #ifdef RTK_129X_PLATFORM
335 	pops->_write8 = &pci_write8_129x;
336 	pops->_write16 = &pci_write16_129x;
337 	pops->_write32 = &pci_write32_129x;
338 #else
339 	pops->_write8 = &pci_write8;
340 	pops->_write16 = &pci_write16;
341 	pops->_write32 = &pci_write32;
342 #endif /* RTK_129X_PLATFORM */
343 
344 	pops->_write_mem = &pci_write_mem;
345 	pops->_write_port = &pci_write_port;
346 
347 	_func_exit_;
348 
349 }
350