summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c')
-rwxr-xr-xdrivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c432
1 files changed, 432 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c b/drivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c
new file mode 100755
index 000000000000..8600f059634b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8723as/os_dep/linux/gspi_ops_linux.c
@@ -0,0 +1,432 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 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 _GSPI_OPS_LINUX_C_
+
+#include <drv_types.h>
+#include <linux/spi/spi.h>
+
+#include "rtl8723a_hal.h"
+#include "rtl8723a_spec.h"
+#include "gspi_ops.h"
+
+int spi_send_msg(PADAPTER Adapter, struct spi_transfer xfers[], u32 IoAction)
+{
+ struct dvobj_priv *psddev;
+ struct spi_device *spi;
+ struct spi_message msg;
+ int ret = 1;
+
+ if (Adapter == NULL) {
+ DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
+ return 1;
+ }
+
+ psddev = adapter_to_dvobj(Adapter);
+ spi = psddev->intf_data.func;
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfers[0], &msg);
+ spi_message_add_tail(&xfers[1], &msg);
+ spi_message_add_tail(&xfers[2], &msg);
+ ret = spi_sync(spi, &msg);
+ if (ret) {
+ DBG_8192C("%s: FAIL!\n", __func__);
+ }
+
+ return ret;
+}
+
+int addr_convert(u32 addr)
+{
+ u32 domain_id = 0 ;
+ u32 temp_addr = addr&0xffff0000;
+
+ if (temp_addr == 0 ) {
+ domain_id = WLAN_IOREG_DOMAIN;
+ return domain_id;
+ }
+
+ switch (temp_addr) {
+ case SPI_LOCAL_OFFSET:
+ domain_id = SPI_LOCAL_DOMAIN;
+ break;
+ case WLAN_IOREG_OFFSET:
+ domain_id = WLAN_IOREG_DOMAIN;
+ break;
+ case FW_FIFO_OFFSET:
+ domain_id = FW_FIFO_DOMAIN;
+ break;
+ case TX_HIQ_OFFSET:
+ domain_id = TX_HIQ_DOMAIN;
+ break;
+ case TX_MIQ_OFFSET:
+ domain_id = TX_MIQ_DOMAIN;
+ break;
+ case TX_LOQ_OFFSET:
+ domain_id = TX_LOQ_DOMAIN;
+ break;
+ case RX_RXOFF_OFFSET:
+ domain_id = RX_RXFIFO_DOMAIN;
+ break;
+ default:
+ break;
+ }
+ //sys_mib.Spi_Transation_record.domain_id =domain_id;
+ return domain_id;
+}
+
+static u32 buf_endian_reverse(u32 src)
+{
+ return (((src&0x000000ff)<<24)|((src&0x0000ff00)<<8)|
+ ((src&0x00ff0000)>>8)|((src&0xff000000)>>24));
+}
+
+void spi_get_status_info(ADAPTER* Adapter, unsigned char *status)
+{
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
+
+ pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX] = GET_STATUS_PUB_PAGE_NUM(status);
+ pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX] = GET_STATUS_HI_PAGE_NUM(status);
+ pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX] = GET_STATUS_MID_PAGE_NUM(status);
+ pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX] = GET_STATUS_LOW_PAGE_NUM(status);
+
+ //DBG_8192C("%s: Free page for HIQ(%#x),MIDQ(%#x),LOWQ(%#x),PUBQ(%#x)\n",
+ // __FUNCTION__,
+ // pHalData->SdioTxFIFOFreePage[HI_QUEUE_IDX],
+ // pHalData->SdioTxFIFOFreePage[MID_QUEUE_IDX],
+ // pHalData->SdioTxFIFOFreePage[LOW_QUEUE_IDX],
+ // pHalData->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]);
+}
+
+int spi_read_write_reg(PADAPTER pAdapter, int write_flag, u32 addr, char * buf, int len, u32 eddien)
+{
+ int fun = 1, domain_id = 0x0; //LOCAL
+ unsigned int cmd = 0 ;
+ int byte_en = 0 ;//,i = 0 ;
+ int ret = 0;
+ unsigned char status[8] = {0};
+ unsigned int data_tmp = 0;
+ //u32 force_bigendian = !eddien;
+ u32 force_bigendian = eddien;
+
+ if (len!=1 && len!=2 && len != 4) {
+ return -1;
+ }
+
+ domain_id = addr_convert(addr);
+
+ addr &= 0x7fff;
+ len &= 0xff;
+ if (write_flag) //write register
+ {
+ int remainder = addr % 4;
+ u32 val32 = *(u32 *)buf;
+ switch(len) {
+ case 1:
+ byte_en = (0x1 << remainder);
+ data_tmp = (val32& 0xff)<< (remainder*8);
+ break;
+ case 2:
+ byte_en = (0x3 << remainder);
+ data_tmp = (val32 & 0xffff)<< (remainder*8);
+ break;
+ case 4:
+ byte_en = 0xf;
+ data_tmp = val32 & 0xffffffff;
+ break;
+ default:
+ byte_en = 0xf;
+ data_tmp = val32 & 0xffffffff;
+ break;
+ }
+ }
+ else //read register
+ {
+ switch(len) {
+ case 1:
+ byte_en = 0x1;
+ break;
+ case 2:
+ byte_en = 0x3;
+ break;
+ case 4:
+ byte_en = 0xf;
+ break;
+ default:
+ byte_en = 0xf;
+ break;
+ }
+ }
+
+ //addr = 0xF0 4byte: 0x2800f00f
+ REG_LEN_FORMAT(&cmd, byte_en);
+ REG_ADDR_FORMAT(&cmd, (addr&0xfffffffc));
+ REG_DOMAIN_ID_FORMAT(&cmd, domain_id);
+ REG_FUN_FORMAT(&cmd, fun);
+ REG_RW_FORMAT(&cmd, write_flag);
+
+ //DBG_8192C("spi_read_write_reg cmd1: %x, data_tmp is %x\n",cmd, data_tmp);
+
+ if (force_bigendian) {
+ cmd = buf_endian_reverse(cmd);
+ }
+
+ //io is one by one, so we do not need fwps_lock here
+ //rtw_spin_lock(&padapter->halpriv.fwps_lock);
+ //padapter->io_fifo_processing = _TRUE;
+ if (!write_flag && (domain_id!= RX_RXFIFO_DOMAIN)) {
+ u32 read_data = 0;
+ struct spi_transfer xfers[3];
+ _rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
+ _rtw_memset(buf, 0x0, len);
+
+ xfers[0].tx_buf = &cmd;
+ xfers[0].len = 4;
+
+ xfers[1].rx_buf = status;
+ xfers[1].len = 8;
+
+ xfers[2].rx_buf = &read_data;
+ xfers[2].len = 4;
+
+ //DBG_8192C("spi_read_write_reg: read_data is %x\n", read_data);
+ ret = spi_send_msg(pAdapter, xfers, 0);
+ if (ret) {
+ DBG_8192C(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, ret, addr);
+ read_data = 0;
+ _rtw_memset(status, 0, 8);
+ }
+
+ //DBG_8192C("spi_read_write_reg: read_data is %x\n", read_data);
+ read_data = EF4Byte(read_data);
+ //add for 8810
+#ifdef CONFIG_BIG_ENDIAN
+ if (!force_bigendian)
+ read_data = buf_endian_reverse(read_data);
+#else
+ if (force_bigendian)
+ read_data = buf_endian_reverse(read_data);
+#endif
+ *(u32*)buf = read_data;
+ //DBG_8192C("spi_read_write_reg: read: buf is %x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
+ } else if (write_flag ) {
+ struct spi_transfer xfers[3];
+ _rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
+
+ xfers[0].tx_buf = &cmd;
+ xfers[0].len = 4;
+
+ xfers[1].tx_buf = &data_tmp;
+ xfers[1].len = 4;
+
+ xfers[2].rx_buf = status;
+ xfers[2].len = 8;
+
+ //DBG_8192C("spi_read_write_reg data_tmp 111: %x\n",data_tmp);
+#ifdef CONFIG_BIG_ENDIAN
+ if (!force_bigendian)
+ data_tmp = buf_endian_reverse(data_tmp);
+#else
+ if (force_bigendian)
+ data_tmp = buf_endian_reverse(data_tmp);
+#endif
+ ret = spi_send_msg(pAdapter, xfers, 0);
+ if (ret) {
+ DBG_8192C(KERN_ERR "%s: FAIL!(%d) addr=0x%05x\n", __func__, ret, addr);
+ _rtw_memset(status, 0, 8);
+ }
+ }
+
+ //padapter->io_fifo_processing = _FALSE;
+
+ spi_get_status_info(pAdapter, (unsigned char*)status);
+
+ return ret;
+}
+
+u8 spi_read8(ADAPTER *Adapter, unsigned int addr, s32 *err)
+{
+ unsigned int ret = 0;
+ int val32 = 0 , remainder = 0 ;
+ s32 _err = 0;
+
+ _err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
+ remainder = addr % 4;
+ val32 = ret;
+ val32 = (val32& (0xff<< (remainder<<3)))>>(remainder<<3);
+
+ if (err)
+ *err = _err;
+
+ return (u8)val32;
+
+}
+
+u16 spi_read16(ADAPTER *Adapter, u32 addr, s32 *err)
+{
+ unsigned int ret = 0;
+ int val32 = 0 , remainder = 0 ;
+ s32 _err = 0;
+
+ _err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
+ remainder = addr % 4;
+ val32 = ret;
+ val32 = (val32& (0xffff<< (remainder<<3)))>>(remainder<<3);
+
+ if (err)
+ *err = _err;
+
+ return (u16)val32;
+}
+
+u32 spi_read32(ADAPTER *Adapter, u32 addr, s32 *err)
+{
+ unsigned int ret = 0;
+ s32 _err = 0;
+
+ _err = spi_read_write_reg(Adapter,0,addr&0xFFFFFFFC,(char *)&ret,4,0);
+ if (err)
+ *err = _err;
+
+ return ret;
+}
+
+void spi_write8(ADAPTER *Adapter, u32 addr, u8 buf, s32 *err)
+{
+ int ret = 0;
+
+ ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,1,0);
+ if (err)
+ *err = ret;
+}
+
+void spi_write16(ADAPTER *Adapter, u32 addr, u16 buf, s32 *err)
+{
+ int ret = 0;
+
+ ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,2,0);
+ if (err)
+ *err = ret;
+}
+
+void spi_write32(ADAPTER *Adapter, u32 addr, u32 buf, s32 *err)
+{
+ int ret = 0;
+
+ ret = spi_read_write_reg(Adapter, 1,addr,(char *)&buf,4,0);
+ if (err)
+ *err = ret;
+}
+
+unsigned int spi_write8_endian(ADAPTER *Adapter, unsigned int addr, unsigned int buf, u32 big)
+{
+ int ret = 0;
+
+ ret = spi_read_write_reg(Adapter,1,addr,(char *)&buf,1, big);
+ return ret;
+}
+
+void spi_write_tx_fifo(ADAPTER *Adapter, u8 *buf, int len, u32 fifo)
+{
+ int fun =1; //TX_HIQ_FIFO
+ unsigned int cmd = 0;
+ unsigned char status[8];
+ u8 more_data = 0;
+ int ret = 0;
+
+ struct spi_transfer xfers[3];
+ _rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
+
+ xfers[0].tx_buf = &cmd;
+ xfers[0].len = 4;
+
+ xfers[1].tx_buf = buf;
+ xfers[1].len = len;//len/4;
+
+ xfers[2].rx_buf = status;
+ xfers[2].len = 8;
+
+_func_enter_;
+
+ FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
+ FIFO_DOMAIN_ID_FORMAT(&cmd, fifo);
+ FIFO_FUN_FORMAT(&cmd, fun);
+ FIFO_RW_FORMAT(&cmd, (unsigned int)1); //write
+
+ _rtw_memset(status, 0x00, 8);
+
+ ret = spi_send_msg(Adapter, xfers, 1);
+ if (ret) {
+ DBG_8192C("%s: FAIL!(%d)\n", __func__, ret);
+ _rtw_memset(status, 0, 8);
+ }
+
+ spi_get_status_info(Adapter, status);
+
+ more_data = GET_STATUS_HISR_LOW8BIT(status) & BIT(0);
+ //if(more_data) {
+ // rtw_queue_delayed_work(Adapter->recv_wq, &Adapter->recv_work, 0, (void*)Adapter);
+ //}
+
+_func_exit_;
+
+ return;
+}
+
+int spi_read_rx_fifo(ADAPTER *Adapter, unsigned char *buf, int len, struct spi_more_data *pmore_data)
+{
+ int fun =1, domain_id = 0x1f; //RX_FIFO
+ unsigned int cmd = 0;
+ unsigned char status[8];
+ int ret = 0;
+ struct spi_transfer xfers[3];
+
+ _rtw_memset(xfers, 0x00, 3*sizeof(struct spi_transfer));
+
+ xfers[0].tx_buf = &cmd;
+ xfers[0].len = 4;
+
+ xfers[1].rx_buf = buf;
+ xfers[1].len = len;
+
+ xfers[2].rx_buf = status;
+ xfers[2].len = 8;
+
+ FIFO_LEN_FORMAT(&cmd, len); //TX Agg len
+ FIFO_DOMAIN_ID_FORMAT(&cmd, domain_id);
+ FIFO_FUN_FORMAT(&cmd, fun);
+ FIFO_RW_FORMAT(&cmd, 0); //read
+
+ _rtw_memset(status, 0x00, 8);
+ _rtw_memset(buf, 0x0, len);
+
+ ret = spi_send_msg(Adapter, xfers, 1);
+ if (ret) {
+ DBG_8192C(KERN_ERR "%s: FAIL!(%d)\n", __func__, ret);
+ _rtw_memset(status, 0x00, 8);
+ _rtw_memset(buf, 0x0, len);
+ return _FAIL;
+ }
+
+ spi_get_status_info(Adapter, (unsigned char*)status);
+ pmore_data->more_data = GET_STATUS_HISR_LOW8BIT(status) & BIT(0);
+ pmore_data->len = GET_STATUS_RX_LENGTH(status);
+
+ return _SUCCESS;
+}