| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- /******************************************************************************
- *
- * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- *
- ******************************************************************************/
- #define _RTL8821CE_IO_C_
- #include <drv_types.h> /* PADAPTER and etc. */
- #ifdef RTK_129X_PLATFORM
- #include <soc/realtek/rtd129x_lockapi.h>
- #define IO_2K_MASK 0xFFFFF800
- #define IO_4K_MASK 0xFFFFF000
- #define MAX_RETRY 5
- static u32 pci_io_read_129x(struct dvobj_priv *pdvobjpriv, u32 addr, u8 size)
- {
- unsigned long mask_addr = pdvobjpriv->mask_addr;
- unsigned long tran_addr = pdvobjpriv->tran_addr;
- u8 busnumber = pdvobjpriv->pcipriv.busnumber;
- u32 rval = 0;
- u32 mask;
- u32 translate_val = 0;
- u32 tmp_addr = addr & 0xFFF;
- _irqL irqL;
- u32 pci_error_status = 0;
- int retry_cnt = 0;
- unsigned long flags;
- _enter_critical(&pdvobjpriv->io_reg_lock, &irqL);
- /* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
- * can't be used because of 1295 hardware issue.
- */
- if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
- (tmp_addr == 0xC68))) {
- mask = IO_2K_MASK;
- writel(0xFFFFF800, (u8 *)mask_addr);
- translate_val = readl((u8 *)tran_addr);
- writel(translate_val|(addr&mask), (u8 *)tran_addr);
- } else if (addr >= 0x1000) {
- mask = IO_4K_MASK;
- translate_val = readl((u8 *)tran_addr);
- writel(translate_val|(addr&mask), (u8 *)tran_addr);
- } else
- mask = 0x0;
- pci_read_129x_retry:
- /* All RBUS1 driver need to have a workaround for emmc hardware error */
- /* Need to protect 0xXXXX_X8XX~ 0xXXXX_X9XX */
- if ((tmp_addr > 0x7FF) && (tmp_addr < 0xA00))
- rtk_lockapi_lock(flags, __func__);
- switch (size) {
- case 1:
- rval = readb((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- case 2:
- rval = readw((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- case 4:
- rval = readl((u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- default:
- RTW_WARN("RTD129X: %s: wrong size %d\n", __func__, size);
- break;
- }
- if ((tmp_addr > 0x7FF) && (tmp_addr < 0xA00))
- rtk_lockapi_unlock(flags, __func__);
- /* DLLP error patch*/
- pci_error_status = readl((u8 *)(pdvobjpriv->ctrl_start + 0x7C));
- if (pci_error_status & 0x1F) {
- writel(pci_error_status, (u8 *)(pdvobjpriv->ctrl_start + 0x7C));
- RTW_WARN("RTD129X: %s: DLLP(#%d) 0x%x reg=0x%x val=0x%x\n",
- __func__, retry_cnt, pci_error_status, addr, rval);
- if (retry_cnt < MAX_RETRY) {
- retry_cnt++;
- goto pci_read_129x_retry;
- }
- }
- /* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
- * can't be used because of 1295 hardware issue.
- */
- if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
- (tmp_addr == 0xC68))) {
- writel(translate_val, (u8 *)tran_addr);
- writel(0xFFFFF000, (u8 *)mask_addr);
- } else if (addr >= 0x1000) {
- writel(translate_val, (u8 *)tran_addr);
- }
- _exit_critical(&pdvobjpriv->io_reg_lock, &irqL);
- return rval;
- }
- static void pci_io_write_129x(struct dvobj_priv *pdvobjpriv,
- u32 addr, u8 size, u32 wval)
- {
- unsigned long mask_addr = pdvobjpriv->mask_addr;
- unsigned long tran_addr = pdvobjpriv->tran_addr;
- u8 busnumber = pdvobjpriv->pcipriv.busnumber;
- u32 mask;
- u32 translate_val = 0;
- u32 tmp_addr = addr & 0xFFF;
- _irqL irqL;
- unsigned long flags;
- _enter_critical(&pdvobjpriv->io_reg_lock, &irqL);
- /* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
- * can't be used because of 1295 hardware issue.
- */
- if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
- (tmp_addr == 0xC68))) {
- mask = IO_2K_MASK;
- writel(0xFFFFF800, (u8 *)mask_addr);
- translate_val = readl((u8 *)tran_addr);
- writel(translate_val|(addr&mask), (u8 *)tran_addr);
- } else if (addr >= 0x1000) {
- mask = IO_4K_MASK;
- translate_val = readl((u8 *)tran_addr);
- writel(translate_val|(addr&mask), (u8 *)tran_addr);
- } else
- mask = 0x0;
- /* All RBUS1 driver need to have a workaround for emmc hardware error */
- /* Need to protect 0xXXXX_X8XX~ 0xXXXX_X9XX */
- if ((tmp_addr > 0x7FF) && (tmp_addr < 0xA00))
- rtk_lockapi_lock(flags, __func__);
- switch (size) {
- case 1:
- writeb((u8)wval,
- (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- case 2:
- writew((u16)wval,
- (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- case 4:
- writel((u32)wval,
- (u8 *)pdvobjpriv->pci_mem_start + (addr&~mask));
- break;
- default:
- RTW_WARN("RTD129X: %s: wrong size %d\n", __func__, size);
- break;
- }
- if ((tmp_addr > 0x7FF) && (tmp_addr < 0xA00))
- rtk_lockapi_unlock(flags, __func__);
- /* PCIE1.1 0x9804FCEC, PCIE2.0 0x9803CCEC & 0x9803CC68
- * can't be used because of 1295 hardware issue.
- */
- if ((tmp_addr == 0xCEC) || ((busnumber == 0x01) &&
- (tmp_addr == 0xC68))) {
- writel(translate_val, (u8 *)tran_addr);
- writel(0xFFFFF000, (u8 *)mask_addr);
- } else if (addr >= 0x1000) {
- writel(translate_val, (u8 *)tran_addr);
- }
- _exit_critical(&pdvobjpriv->io_reg_lock, &irqL);
- }
- static u8 pci_read8_129x(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return (u8)pci_io_read_129x(pdvobjpriv, addr, 1);
- }
- static u16 pci_read16_129x(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return (u16)pci_io_read_129x(pdvobjpriv, addr, 2);
- }
- static u32 pci_read32_129x(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return (u32)pci_io_read_129x(pdvobjpriv, addr, 4);
- }
- /*
- * 2009.12.23. by tynli. Suggested by SD1 victorh.
- * For ASPM hang on AMD and Nvidia.
- * 20100212 Tynli: Do read IO operation after write for
- * all PCI bridge suggested by SD1. Origianally this is only for INTEL.
- */
- static int pci_write8_129x(struct intf_hdl *phdl, u32 addr, u8 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- pci_io_write_129x(pdvobjpriv, addr, 1, val);
- return 1;
- }
- static int pci_write16_129x(struct intf_hdl *phdl, u32 addr, u16 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- pci_io_write_129x(pdvobjpriv, addr, 2, val);
- return 2;
- }
- static int pci_write32_129x(struct intf_hdl *phdl, u32 addr, u32 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- pci_io_write_129x(pdvobjpriv, addr, 4, val);
- return 4;
- }
- #else /* original*/
- static u8 pci_read8(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return 0xff & readb((u8 *)pdvobjpriv->pci_mem_start + addr);
- }
- static u16 pci_read16(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return readw((u8 *)pdvobjpriv->pci_mem_start + addr);
- }
- static u32 pci_read32(struct intf_hdl *phdl, u32 addr)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- return readl((u8 *)pdvobjpriv->pci_mem_start + addr);
- }
- /*
- * 2009.12.23. by tynli. Suggested by SD1 victorh.
- * For ASPM hang on AMD and Nvidia.
- * 20100212 Tynli: Do read IO operation after write for
- * all PCI bridge suggested by SD1. Origianally this is only for INTEL.
- */
- static int pci_write8(struct intf_hdl *phdl, u32 addr, u8 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- writeb(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
- return 1;
- }
- static int pci_write16(struct intf_hdl *phdl, u32 addr, u16 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- writew(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
- return 2;
- }
- static int pci_write32(struct intf_hdl *phdl, u32 addr, u32 val)
- {
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)phdl->pintf_dev;
- writel(val, (u8 *)pdvobjpriv->pci_mem_start + addr);
- return 4;
- }
- #endif /* RTK_129X_PLATFORM */
- static void pci_read_mem(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *rmem)
- {
- RTW_INFO("%s(%d)fake function\n", __func__, __LINE__);
- }
- static void pci_write_mem(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *wmem)
- {
- RTW_INFO("%s(%d)fake function\n", __func__, __LINE__);
- }
- static u32 pci_read_port(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *rmem)
- {
- return 0;
- }
- static u32 pci_write_port(struct intf_hdl *phdl, u32 addr, u32 cnt, u8 *wmem)
- {
- _adapter *padapter = (_adapter *)phdl->padapter;
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
- netif_trans_update(padapter->pnetdev);
- #else
- padapter->pnetdev->trans_start = jiffies;
- #endif
- return 0;
- }
- void rtl8821ce_set_intf_ops(struct _io_ops *pops)
- {
- _rtw_memset((u8 *)pops, 0, sizeof(struct _io_ops));
- #ifdef RTK_129X_PLATFORM
- pops->_read8 = &pci_read8_129x;
- pops->_read16 = &pci_read16_129x;
- pops->_read32 = &pci_read32_129x;
- #else
- pops->_read8 = &pci_read8;
- pops->_read16 = &pci_read16;
- pops->_read32 = &pci_read32;
- #endif /* RTK_129X_PLATFORM */
- pops->_read_mem = &pci_read_mem;
- pops->_read_port = &pci_read_port;
- #ifdef RTK_129X_PLATFORM
- pops->_write8 = &pci_write8_129x;
- pops->_write16 = &pci_write16_129x;
- pops->_write32 = &pci_write32_129x;
- #else
- pops->_write8 = &pci_write8;
- pops->_write16 = &pci_write16;
- pops->_write32 = &pci_write32;
- #endif /* RTK_129X_PLATFORM */
- pops->_write_mem = &pci_write_mem;
- pops->_write_port = &pci_write_port;
- }
|