rtl8821ce_io.c 9.6 KB

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