diff options
Diffstat (limited to 'drivers/staging/rtlwifi/halmac/halmac_88xx')
25 files changed, 15958 insertions, 0 deletions
diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_cfg.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_cfg.h new file mode 100644 index 000000000000..04e44aed9b45 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_cfg.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_8822B_CFG_H_ +#define _HALMAC_8822B_CFG_H_ + +#include "halmac_8822b_pwr_seq.h" +#include "halmac_api_8822b.h" +#include "halmac_api_8822b_usb.h" +#include "halmac_api_8822b_sdio.h" +#include "halmac_api_8822b_pcie.h" +#include "../../halmac_bit2.h" +#include "../../halmac_reg2.h" +#include "../../halmac_api.h" + +#define HALMAC_TX_FIFO_SIZE_8822B 262144 /* 256k */ +#define HALMAC_TX_FIFO_SIZE_LA_8822B 131072 /* 128k */ +#define HALMAC_RX_FIFO_SIZE_8822B 24576 /* 24k */ +#define HALMAC_TX_PAGE_SIZE_8822B 128 /* PageSize 128Byte */ +#define HALMAC_TX_ALIGN_SIZE_8822B 8 +#define HALMAC_TX_PAGE_SIZE_2_POWER_8822B 7 /* 128 = 2^7 */ +#define HALMAC_SECURITY_CAM_ENTRY_NUM_8822B 64 /* CAM Entry size */ +#define HALMAC_TX_AGG_ALIGNMENT_SIZE_8822B 8 +#define HALMAC_TX_DESC_SIZE_8822B 48 +#define HALMAC_RX_DESC_SIZE_8822B 24 +#define HALMAC_RX_DESC_DUMMY_SIZE_MAX_8822B 120 +#define HALMAC_C2H_PKT_BUF_8822B 256 +#define HALMAC_RX_FIFO_EXPANDING_MODE_PKT_SIZE_MAX_8822B 80 /* align 8 Byte*/ +#define HALMAC_RX_FIFO_EXPANDING_UNIT_8822B \ + (HALMAC_RX_DESC_SIZE_8822B + HALMAC_RX_DESC_DUMMY_SIZE_MAX_8822B + \ + HALMAC_RX_FIFO_EXPANDING_MODE_PKT_SIZE) /* align 8 Byte*/ +#define HALMAC_RX_FIFO_EXPANDING_UNIT_MAX_8822B \ + (HALMAC_RX_DESC_SIZE_8822B + HALMAC_RX_DESC_DUMMY_SIZE_MAX_8822B + \ + HALMAC_RX_FIFO_EXPANDING_MODE_PKT_SIZE_MAX_8822B) /* align 8 Byte*/ + +#define HALMAC_TX_FIFO_SIZE_EX_1_BLK_8822B 196608 /* 192k */ +#define HALMAC_RX_FIFO_SIZE_EX_1_BLK_8822B \ + ((((HALMAC_RX_FIFO_EXPANDING_UNIT_8822B << 8) - 1) >> 10) \ + << 10) /* < 56k*/ +#define HALMAC_RX_FIFO_SIZE_EX_1_BLK_MAX_8822B \ + ((((HALMAC_RX_FIFO_EXPANDING_UNIT_MAX_8822B << 8) - 1) >> 10) \ + << 10) /* 55k*/ +#define HALMAC_TX_FIFO_SIZE_EX_2_BLK_8822B 131072 /* 128k */ +#define HALMAC_RX_FIFO_SIZE_EX_2_BLK_8822B 155648 /* 152k */ +#define HALMAC_TX_FIFO_SIZE_EX_3_BLK_8822B 65536 /* 64k */ +#define HALMAC_RX_FIFO_SIZE_EX_3_BLK_8822B 221184 /* 216k */ + +/* TXFIFO LAYOUT + * HIGH_QUEUE + * NORMAL_QUEUE + * LOW_QUEUE + * EXTRA_QUEUE + * PUBLIC_QUEUE -- decided after all other queue are defined + * GAP_QUEUE -- Used to separate AC queue and Rsvd page + * + * RSVD_DRIVER -- Driver used rsvd page area + * RSVD_H2C_EXTRAINFO -- Extra Information for h2c + * RSVD_H2C_QUEUE -- h2c queue in rsvd page + * RSVD_CPU_INSTRUCTION -- extend fw code + * RSVD_FW_TXBUFF -- fw used this area to send packet + * + * Symbol: HALMAC_MODE_QUEUE_UNIT_CHIP, ex: HALMAC_LB_2BULKOUT_FWCMD_PGNUM_8822B + */ +#define HALMAC_EXTRA_INFO_BUFF_SIZE_FULL_FIFO_8822B \ + 16384 /*16K, only used in init case*/ + +#define HALMAC_RSVD_DRV_PGNUM_8822B 16 /*2048*/ +#define HALMAC_RSVD_H2C_EXTRAINFO_PGNUM_8822B 32 /*4096*/ +#define HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B 8 /*1024*/ +#define HALMAC_RSVD_CPU_INSTRUCTION_PGNUM_8822B 0 /*0*/ +#define HALMAC_RSVD_FW_TXBUFF_PGNUM_8822B 4 /*512*/ + +#define HALMAC_EFUSE_SIZE_8822B 1024 /* 0x400 */ +#define HALMAC_BT_EFUSE_SIZE_8822B 128 /* 0x80 */ +#define HALMAC_EEPROM_SIZE_8822B 0x300 +#define HALMAC_CR_TRX_ENABLE_8822B \ + (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | BIT_RXDMA_EN | \ + BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | BIT_MACTXEN | BIT_MACRXEN) + +#define HALMAC_BLK_DESC_NUM_8822B 0x3 /* Only for USB */ + +/* AMPDU max time (unit : 32us) */ +#define HALMAC_AMPDU_MAX_TIME_8822B 0x70 + +/* Protect mode control */ +#define HALMAC_PROT_RTS_LEN_TH_8822B 0xFF +#define HALMAC_PROT_RTS_TX_TIME_TH_8822B 0x08 +#define HALMAC_PROT_MAX_AGG_PKT_LIMIT_8822B 0x20 +#define HALMAC_PROT_RTS_MAX_AGG_PKT_LIMIT_8822B 0x20 + +/* Fast EDCA setting */ +#define HALMAC_FAST_EDCA_VO_TH_8822B 0x06 +#define HALMAC_FAST_EDCA_VI_TH_8822B 0x06 +#define HALMAC_FAST_EDCA_BE_TH_8822B 0x06 +#define HALMAC_FAST_EDCA_BK_TH_8822B 0x06 + +/* BAR setting */ +#define HALMAC_BAR_RETRY_LIMIT_8822B 0x01 +#define HALMAC_RA_TRY_RATE_AGG_LIMIT_8822B 0x08 + +enum halmac_normal_rxagg_th_to_8822b { + HALMAC_NORMAL_RXAGG_THRESHOLD_8822B = 0xFF, + HALMAC_NORMAL_RXAGG_TIMEOUT_8822B = 0x01, +}; + +enum halmac_loopback_rxagg_th_to_8822b { + HALMAC_LOOPBACK_RXAGG_THRESHOLD_8822B = 0xFF, + HALMAC_LOOPBACK_RXAGG_TIMEOUT_8822B = 0x01, +}; + +#endif diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_phy.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_phy.c new file mode 100644 index 000000000000..b2a5aed75dca --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_phy.c @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "../halmac_88xx_cfg.h" +#include "halmac_8822b_cfg.h" + +/** + * ============ip sel item list============ + * HALMAC_IP_SEL_INTF_PHY + * USB2 : usb2 phy, 1byte value + * USB3 : usb3 phy, 2byte value + * PCIE1 : pcie gen1 mdio, 2byte value + * PCIE2 : pcie gen2 mdio, 2byte value + * HALMAC_IP_SEL_MAC + * USB2, USB3, PCIE1, PCIE2 : mac ip, 1byte value + * HALMAC_IP_SEL_PCIE_DBI + * USB2 USB3 : none + * PCIE1, PCIE2 : pcie dbi, 1byte value + */ + +struct halmac_intf_phy_para_ HALMAC_RTL8822B_USB2_PHY[] = { + /* {offset, value, ip sel, cut mask, platform mask} */ + {0xFFFF, 0x00, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_ALL, + HALMAC_INTF_PHY_PLATFORM_ALL}, +}; + +struct halmac_intf_phy_para_ HALMAC_RTL8822B_USB3_PHY[] = { + /* {offset, value, ip sel, cut mask, platform mask} */ + {0x0001, 0xA841, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_D, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_ALL, + HALMAC_INTF_PHY_PLATFORM_ALL}, +}; + +struct halmac_intf_phy_para_ HALMAC_RTL8822B_PCIE_PHY_GEN1[] = { + /* {offset, value, ip sel, cut mask, platform mask} */ + {0x0001, 0xA841, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0002, 0x60C6, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0008, 0x3596, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0009, 0x321C, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x000A, 0x9623, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0020, 0x94FF, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0021, 0xFFCF, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0026, 0xC006, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0029, 0xFF0E, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x002A, 0x1840, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_ALL, + HALMAC_INTF_PHY_PLATFORM_ALL}, +}; + +struct halmac_intf_phy_para_ HALMAC_RTL8822B_PCIE_PHY_GEN2[] = { + /* {offset, value, ip sel, cut mask, platform mask} */ + {0x0001, 0xA841, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0002, 0x60C6, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0008, 0x3597, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0009, 0x321C, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x000A, 0x9623, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0020, 0x94FF, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0021, 0xFFCF, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0026, 0xC006, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x0029, 0xFF0E, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0x002A, 0x3040, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_C, + HALMAC_INTF_PHY_PLATFORM_ALL}, + {0xFFFF, 0x0000, HALMAC_IP_SEL_INTF_PHY, HALMAC_INTF_PHY_CUT_ALL, + HALMAC_INTF_PHY_PLATFORM_ALL}, +}; diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c new file mode 100644 index 000000000000..0edd1f5a04a8 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.c @@ -0,0 +1,563 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "../halmac_88xx_cfg.h" +#include "halmac_8822b_cfg.h" + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_CARDEMU_TO_ACT[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0012, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*SWR OCP = SWR OCP = 010 1382.40*/ + {0x0012, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /*SWR OCP = 010 1382.40 */ + {0x0020, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(0), + BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ + {0x0001, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_DELAY, 1, + HALMAC_PWRSEQ_DELAY_MS}, /*Delay 1ms*/ + {0x0000, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(5), + 0}, /*0x00[5] = 1b'0 release analog Ips to digital ,1:isolation*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + (BIT(4) | BIT(3) | BIT(2)), + 0}, /* disable SW LPS 0x04[10]=0 and WLSUS_EN 0x04[12:11]=0*/ + {0x0075, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* Disable USB suspend */ + {0x0006, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(1), + BIT(1)}, /* wait till 0x04[17] = 1 power ready*/ + {0x0075, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), 0}, /* Enable USB suspend */ + {0xFF1A, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, /*0xFF1A = 0 to release resume signals*/ + {0x0006, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* release WLON reset 0x04[16]=1*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(7), 0}, /* disable HWPDN 0x04[15]=0*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + (BIT(4) | BIT(3)), 0}, /* disable WL suspend*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* polling until return 0*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(0), 0}, + {0x0020, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3), BIT(3)}, /*Enable XTAL_CLK*/ + {0x10A8, HALMAC_PWR_CUT_C_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, /*NFC pad enabled*/ + {0x10A9, HALMAC_PWR_CUT_C_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xef}, /*NFC pad enabled*/ + {0x10AA, HALMAC_PWR_CUT_C_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x0c}, /*NFC pad enabled*/ + {0x0068, HALMAC_PWR_CUT_C_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(4), BIT(4)}, /*SDIO pad power down disabled*/ + {0x0029, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xF9}, /*PLL seting*/ + {0x0024, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(2), 0}, /*Improve TX EVM of CH13 and some 5G channles */ + {0x0074, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(5), BIT(5)}, /*PCIE WAKE# enabled*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_ACT_TO_CARDEMU[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0003, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(2), 0}, /*0x02[10] = 0 Disable MCU Core*/ + {0x0093, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3), 0}, /*LPS option 0x93[3]=0 , SWR PFM*/ + {0x001F, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, /*0x1F[7:0] = 0 turn off RF*/ + {0x00EF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, /*0xEF[7:0] = 0 turn off RF*/ + {0xFF1A, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x30}, /*0xFF1A = 0x30 to block resume signals*/ + {0x0049, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*Enable rising edge triggering interrupt*/ + {0x0006, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* release WLON reset 0x04[16]=1*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /* Whole BB is reset */ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(1), + 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ + {0x0020, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3), 0}, /* XTAL_CLK gated*/ + {0x0000, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(5), + BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital ,1:isolation*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_CARDEMU_TO_SUS[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(4) | BIT(3), + (BIT(4) | BIT(3))}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(3) | BIT(4), + BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ + {0x0007, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, 0xFF, + 0x20}, /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3) | BIT(4), + BIT(3) | BIT(4)}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(0), + BIT(0)}, /*Set SDIO suspend local register*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_SUS_TO_CARDEMU[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_POLLING, BIT(1), + BIT(1)}, /*wait power state to suspend*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3) | BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_CARDEMU_TO_CARDDIS[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(7), + BIT(7)}, /*suspend enable and power down enable*/ + {0x0007, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, 0xFF, + 0x20}, /*0x07=0x20 , SOP option to disable BG/MB*/ + {0x0067, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(5), 0}, /*0x67[5]=0 , BIT_PAPE_WLBT_SEL*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_SDIO_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(3) | BIT(4), + BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(2), BIT(2)}, /*0x04[10] = 1, enable SW LPS*/ + {0x004A, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ + {0x0067, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(5), + 0}, /* 0: BT PAPE control ; 1: WL BB LNAON control*/ + {0x0067, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(4), + 0}, /* 0: BT GPIO[11:10] control ; 1: WL BB LNAON control*/ + {0x004F, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(0), 0}, /* 0: BT Control*/ + {0x0067, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(1), + 0}, /* turn off BT_3DD_SYNC_B and BT_GPIO[18] */ + {0x0046, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(6), BIT(6)}, /* GPIO[6] : Output mode*/ + {0x0067, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(2), 0}, /* turn off BT_GPIO[16] */ + {0x0046, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(7), BIT(7)}, /* GPIO[7] : Output mode*/ + {0x0062, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_WRITE, BIT(4), BIT(4)}, /* GPIO[12] : Output mode */ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(0), + BIT(0)}, /*Set SDIO suspend local register*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK | HALMAC_PWR_INTF_PCI_MSK, + HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, BIT(1), + 0}, /*0x90[1]=0 , disable 32k clock*/ + {0x0044, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, 0xFF, + 0}, /*0x90[1]=0 , disable 32k clock by indirect access*/ + {0x0040, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, 0xFF, + 0x90}, /*0x90[1]=0 , disable 32k clock by indirect access*/ + {0x0041, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, 0xFF, + 0x00}, /*0x90[1]=0 , disable 32k clock by indirect access*/ + {0x0042, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, 0xFF, + 0x04}, /*0x90[1]=0 , disable 32k clock by indirect access*/ + {0x0081, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(7), 0}, /*0x80[15]clean fw init ready bit*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_CARDDIS_TO_CARDEMU[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ + {0x0086, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_POLLING, BIT(1), + BIT(1)}, /*wait power state to suspend*/ + {0x004A, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ + {0x0005, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3) | BIT(4) | BIT(7), + 0}, /*clear suspend enable and power down enable*/ + {0x0301, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_ACT_TO_LPS[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(2), BIT(2)}, /*Enable 32k calibration and thermal meter*/ + {0x0199, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3), BIT(3)}, /*Register write data of 32K calibration*/ + {0x019B, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(7), BIT(7)}, /*Enable 32k calibration reg write*/ + {0x1138, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0) | BIT(1), BIT(0) | BIT(1)}, /*set RPWM IMR*/ + {0x0194, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* enable 32K CLK*/ + {0x0093, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x42}, /* LPS Option MAC OFF enable*/ + {0x0092, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x20}, /* LPS Option Enable memory to deep sleep mode*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), BIT(1)}, /* enable reg use 32K CLK*/ + {0x0301, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*PCIe DMA stop*/ + {0x0522, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*Tx Pause*/ + {0x05F8, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05F9, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05FA, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05FB, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), 0}, /*CCK and OFDM are disabled,and clock are gated*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_DELAY, + 0, HALMAC_PWRSEQ_DELAY_US}, /*Delay 1us*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*Whole BB is reset*/ + {0x0100, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x3F}, /*Reset MAC TRX*/ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*check if removed later*/ + {0x0553, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(5), BIT(5)}, /*Respond TxOK to scheduler*/ + {0x0008, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(4), BIT(4)}, /* switch TSF clock to 32K*/ + {0x0109, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(7), + BIT(7)}, /*Polling 0x109[7]=0 TSF in 40M*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* enable WL_LPS_EN*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_ACT_TO_DEEP_LPS[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(2), BIT(2)}, /*Enable 32k calibration and thermal meter*/ + {0x0199, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(3), BIT(3)}, /*Register write data of 32K calibration*/ + {0x019B, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(7), BIT(7)}, /*Enable 32k calibration reg write*/ + {0x1138, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0) | BIT(1), BIT(0) | BIT(1)}, /*set RPWM IMR*/ + {0x0194, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* enable 32K CLK*/ + {0x0093, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x40}, /* LPS Option MAC OFF enable*/ + {0x0092, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x20}, /* LPS Option Enable memory to deep sleep mode*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), BIT(1)}, /* enable reg use 32K CLK*/ + {0x0301, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*PCIe DMA stop*/ + {0x0522, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*Tx Pause*/ + {0x05F8, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05F9, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05FA, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x05FB, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, 0xFF, + 0}, /*Should be zero if no packet is transmitting*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), 0}, /*CCK and OFDM are disabled,and clock are gated*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_DELAY, + 0, HALMAC_PWRSEQ_DELAY_US}, /*Delay 1us*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*Whole BB is reset*/ + {0x0100, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x3F}, /*Reset MAC TRX*/ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /*check if removed later*/ + {0x0553, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(5), BIT(5)}, /*Respond TxOK to scheduler*/ + {0x0008, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(4), BIT(4)}, /* switch TSF clock to 32K*/ + {0x0109, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(7), + BIT(7)}, /*Polling 0x109[7]=1 TSF in 32K*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(0), BIT(0)}, /* enable WL_LPS_EN*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +static struct halmac_wl_pwr_cfg_ HALMAC_RTL8822B_TRANS_LPS_TO_ACT[] = { + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value } */ + {0x0080, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(7), BIT(7)}, /*SDIO RPWM*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_DELAY, + 0, HALMAC_PWRSEQ_DELAY_MS}, /*Delay*/ + {0x0080, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_SDIO_MSK, HALMAC_PWR_BASEADDR_SDIO, + HALMAC_PWR_CMD_WRITE, BIT(7), 0}, /*SDIO RPWM*/ + {0xFE58, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_USB_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x84}, /*USB RPWM*/ + {0x0361, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_PCI_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x84}, /*PCIe RPWM*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_DELAY, + 0, HALMAC_PWRSEQ_DELAY_MS}, /*Delay*/ + {0x0008, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(4), 0}, /* switch TSF to 40M*/ + {0x0109, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, + HALMAC_PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]=0 TSF in 40M*/ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), BIT(1)}, + {0x0100, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*nable WMAC TRX*/ + {0x0002, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1) | BIT(0), BIT(1) | BIT(0)}, /*nable BB macro*/ + {0x0522, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0}, + {0x113C, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0x03}, /*clear RPWM INT*/ + {0x0124, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*clear FW INT*/ + {0x0125, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*clear FW INT*/ + {0x0126, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*clear FW INT*/ + {0x0127, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + 0xFF, 0xFF}, /*clear FW INT*/ + {0x0090, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(1), 0}, /* disable reg use 32K CLK*/ + {0x0101, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, HALMAC_PWR_BASEADDR_MAC, HALMAC_PWR_CMD_WRITE, + BIT(2), 0}, /*disable 32k calibration and thermal meter*/ + {0xFFFF, HALMAC_PWR_CUT_ALL_MSK, HALMAC_PWR_FAB_ALL_MSK, + HALMAC_PWR_INTF_ALL_MSK, 0, HALMAC_PWR_CMD_END, 0, 0}, +}; + +/* Card Enable Array */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_card_enable_flow[] = { + HALMAC_RTL8822B_TRANS_CARDDIS_TO_CARDEMU, + HALMAC_RTL8822B_TRANS_CARDEMU_TO_ACT, NULL}; + +/* Card Disable Array */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_card_disable_flow[] = { + HALMAC_RTL8822B_TRANS_ACT_TO_CARDEMU, + HALMAC_RTL8822B_TRANS_CARDEMU_TO_CARDDIS, NULL}; + +/* Suspend Array */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_suspend_flow[] = { + HALMAC_RTL8822B_TRANS_ACT_TO_CARDEMU, + HALMAC_RTL8822B_TRANS_CARDEMU_TO_SUS, NULL}; + +/* Resume Array */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_resume_flow[] = { + HALMAC_RTL8822B_TRANS_SUS_TO_CARDEMU, + HALMAC_RTL8822B_TRANS_CARDEMU_TO_ACT, NULL}; + +/* HWPDN Array - HW behavior */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_hwpdn_flow[] = {NULL}; + +/* Enter LPS - FW behavior */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_enter_lps_flow[] = { + HALMAC_RTL8822B_TRANS_ACT_TO_LPS, NULL}; + +/* Enter Deep LPS - FW behavior */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_enter_deep_lps_flow[] = { + HALMAC_RTL8822B_TRANS_ACT_TO_DEEP_LPS, NULL}; + +/* Leave LPS -FW behavior */ +struct halmac_wl_pwr_cfg_ *halmac_8822b_leave_lps_flow[] = { + HALMAC_RTL8822B_TRANS_LPS_TO_ACT, NULL}; diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h new file mode 100644 index 000000000000..79a6072ef2ef --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_8822b_pwr_seq.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef HALMAC_POWER_SEQUENCE_8822B +#define HALMAC_POWER_SEQUENCE_8822B + +#include "../../halmac_pwr_seq_cmd.h" + +#define HALMAC_8822B_PWR_SEQ_VER "V17" +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_card_disable_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_card_enable_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_suspend_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_resume_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_hwpdn_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_enter_lps_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_enter_deep_lps_flow[]; +extern struct halmac_wl_pwr_cfg_ *halmac_8822b_leave_lps_flow[]; + +#endif diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.c new file mode 100644 index 000000000000..6b729fe4c096 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.c @@ -0,0 +1,343 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_8822b_cfg.h" +#include "halmac_func_8822b.h" +#include "../halmac_func_88xx.h" + +/** + * halmac_mount_api_8822b() - attach functions to function pointer + * @halmac_adapter + * + * SD1 internal use + * + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + */ +enum halmac_ret_status +halmac_mount_api_8822b(struct halmac_adapter *halmac_adapter) +{ + struct halmac_api *halmac_api = + (struct halmac_api *)halmac_adapter->halmac_api; + + halmac_adapter->chip_id = HALMAC_CHIP_ID_8822B; + halmac_adapter->hw_config_info.efuse_size = HALMAC_EFUSE_SIZE_8822B; + halmac_adapter->hw_config_info.eeprom_size = HALMAC_EEPROM_SIZE_8822B; + halmac_adapter->hw_config_info.bt_efuse_size = + HALMAC_BT_EFUSE_SIZE_8822B; + halmac_adapter->hw_config_info.cam_entry_num = + HALMAC_SECURITY_CAM_ENTRY_NUM_8822B; + halmac_adapter->hw_config_info.txdesc_size = HALMAC_TX_DESC_SIZE_8822B; + halmac_adapter->hw_config_info.rxdesc_size = HALMAC_RX_DESC_SIZE_8822B; + halmac_adapter->hw_config_info.tx_fifo_size = HALMAC_TX_FIFO_SIZE_8822B; + halmac_adapter->hw_config_info.rx_fifo_size = HALMAC_RX_FIFO_SIZE_8822B; + halmac_adapter->hw_config_info.page_size = HALMAC_TX_PAGE_SIZE_8822B; + halmac_adapter->hw_config_info.tx_align_size = + HALMAC_TX_ALIGN_SIZE_8822B; + halmac_adapter->hw_config_info.page_size_2_power = + HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + + halmac_adapter->txff_allocation.rsvd_drv_pg_num = + HALMAC_RSVD_DRV_PGNUM_8822B; + + halmac_api->halmac_init_trx_cfg = halmac_init_trx_cfg_8822b; + halmac_api->halmac_init_protocol_cfg = halmac_init_protocol_cfg_8822b; + halmac_api->halmac_init_h2c = halmac_init_h2c_8822b; + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + halmac_api->halmac_tx_allowed_sdio = + halmac_tx_allowed_sdio_88xx; + halmac_api->halmac_cfg_tx_agg_align = + halmac_cfg_tx_agg_align_sdio_not_support_88xx; + halmac_api->halmac_mac_power_switch = + halmac_mac_power_switch_8822b_sdio; + halmac_api->halmac_phy_cfg = halmac_phy_cfg_8822b_sdio; + halmac_api->halmac_interface_integration_tuning = + halmac_interface_integration_tuning_8822b_sdio; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + halmac_api->halmac_mac_power_switch = + halmac_mac_power_switch_8822b_usb; + halmac_api->halmac_cfg_tx_agg_align = + halmac_cfg_tx_agg_align_usb_not_support_88xx; + halmac_api->halmac_phy_cfg = halmac_phy_cfg_8822b_usb; + halmac_api->halmac_interface_integration_tuning = + halmac_interface_integration_tuning_8822b_usb; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_PCIE) { + halmac_api->halmac_mac_power_switch = + halmac_mac_power_switch_8822b_pcie; + halmac_api->halmac_cfg_tx_agg_align = + halmac_cfg_tx_agg_align_pcie_not_support_88xx; + halmac_api->halmac_pcie_switch = halmac_pcie_switch_8822b; + halmac_api->halmac_phy_cfg = halmac_phy_cfg_8822b_pcie; + halmac_api->halmac_interface_integration_tuning = + halmac_interface_integration_tuning_8822b_pcie; + } else { + halmac_api->halmac_pcie_switch = halmac_pcie_switch_8822b_nc; + } + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_trx_cfg_8822b() - config trx dma register + * @halmac_adapter : the adapter of halmac + * @halmac_trx_mode : trx mode selection + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_trx_cfg_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode) +{ + u8 value8; + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_TRX_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + halmac_adapter->trx_mode = halmac_trx_mode; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_init_trx_cfg ==========>halmac_trx_mode = %d\n", + halmac_trx_mode); + + status = halmac_txdma_queue_mapping_8822b(halmac_adapter, + halmac_trx_mode); + + if (status != HALMAC_RET_SUCCESS) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_txdma_queue_mapping fail!\n"); + return status; + } + + value8 = 0; + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8); + value8 = HALMAC_CR_TRX_ENABLE_8822B; + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2CQ_CSR, BIT(31)); + + status = halmac_priority_queue_config_8822b(halmac_adapter, + halmac_trx_mode); + if (halmac_adapter->txff_allocation.rx_fifo_expanding_mode != + HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE) + HALMAC_REG_WRITE_8(halmac_adapter, REG_RX_DRVINFO_SZ, 0xF); + + if (status != HALMAC_RET_SUCCESS) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_txdma_queue_mapping fail!\n"); + return status; + } + + /* Config H2C packet buffer */ + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_HEAD); + value32 = (value32 & 0xFFFC0000) | + (halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_HEAD, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_READ_ADDR); + value32 = (value32 & 0xFFFC0000) | + (halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_READ_ADDR, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_TAIL); + value32 = (value32 & 0xFFFC0000) | + ((halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B) + + (HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B)); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_TAIL, value32); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFC) | 0x01); + HALMAC_REG_WRITE_8(halmac_adapter, REG_H2C_INFO, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFB) | 0x04); + HALMAC_REG_WRITE_8(halmac_adapter, REG_H2C_INFO, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_OFFSET_CHK + 1); + value8 = (u8)((value8 & 0x7f) | 0x80); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_OFFSET_CHK + 1, value8); + + halmac_adapter->h2c_buff_size = HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + halmac_get_h2c_buff_free_space_88xx(halmac_adapter); + + if (halmac_adapter->h2c_buff_size != + halmac_adapter->h2c_buf_free_space) { + pr_err("get h2c free space error!\n"); + return HALMAC_RET_GET_H2C_SPACE_ERR; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_init_trx_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_protocol_cfg_8822b() - config protocol register + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_protocol_cfg_8822b(struct halmac_adapter *halmac_adapter) +{ + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_PROTOCOL_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_AMPDU_MAX_TIME_V1, + HALMAC_AMPDU_MAX_TIME_8822B); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TX_HANG_CTRL, BIT_EN_EOF_V1); + + value32 = HALMAC_PROT_RTS_LEN_TH_8822B | + (HALMAC_PROT_RTS_TX_TIME_TH_8822B << 8) | + (HALMAC_PROT_MAX_AGG_PKT_LIMIT_8822B << 16) | + (HALMAC_PROT_RTS_MAX_AGG_PKT_LIMIT_8822B << 24); + HALMAC_REG_WRITE_32(halmac_adapter, REG_PROT_MODE_CTRL, value32); + + HALMAC_REG_WRITE_16(halmac_adapter, REG_BAR_MODE_CTRL + 2, + HALMAC_BAR_RETRY_LIMIT_8822B | + HALMAC_RA_TRY_RATE_AGG_LIMIT_8822B << 8); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_FAST_EDCA_VOVI_SETTING, + HALMAC_FAST_EDCA_VO_TH_8822B); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FAST_EDCA_VOVI_SETTING + 2, + HALMAC_FAST_EDCA_VI_TH_8822B); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FAST_EDCA_BEBK_SETTING, + HALMAC_FAST_EDCA_BE_TH_8822B); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FAST_EDCA_BEBK_SETTING + 2, + HALMAC_FAST_EDCA_BK_TH_8822B); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_h2c_8822b() - config h2c packet buffer + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_h2c_8822b(struct halmac_adapter *halmac_adapter) +{ + u8 value8; + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + value8 = 0; + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8); + value8 = HALMAC_CR_TRX_ENABLE_8822B; + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_HEAD); + value32 = (value32 & 0xFFFC0000) | + (halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_HEAD, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_READ_ADDR); + value32 = (value32 & 0xFFFC0000) | + (halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_READ_ADDR, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_TAIL); + value32 = (value32 & 0xFFFC0000) | + ((halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B) + + (HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B)); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2C_TAIL, value32); + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFC) | 0x01); + HALMAC_REG_WRITE_8(halmac_adapter, REG_H2C_INFO, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_H2C_INFO); + value8 = (u8)((value8 & 0xFB) | 0x04); + HALMAC_REG_WRITE_8(halmac_adapter, REG_H2C_INFO, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_OFFSET_CHK + 1); + value8 = (u8)((value8 & 0x7f) | 0x80); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_OFFSET_CHK + 1, value8); + + halmac_adapter->h2c_buff_size = HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B + << HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + halmac_get_h2c_buff_free_space_88xx(halmac_adapter); + + if (halmac_adapter->h2c_buff_size != + halmac_adapter->h2c_buf_free_space) { + pr_err("get h2c free space error!\n"); + return HALMAC_RET_GET_H2C_SPACE_ERR; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "h2c free space : %d\n", + halmac_adapter->h2c_buf_free_space); + + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h new file mode 100644 index 000000000000..cf21e3d25607 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_8822B_H_ +#define _HALMAC_API_8822B_H_ + +#include "../../halmac_2_platform.h" +#include "../../halmac_type.h" + +enum halmac_ret_status +halmac_mount_api_8822b(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_init_trx_cfg_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode); + +enum halmac_ret_status +halmac_init_protocol_cfg_8822b(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_init_h2c_8822b(struct halmac_adapter *halmac_adapter); + +#endif /* _HALMAC_API_8822B_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c new file mode 100644 index 000000000000..e25e2b0ebb4c --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.c @@ -0,0 +1,323 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "../halmac_88xx_cfg.h" +#include "../halmac_api_88xx_pcie.h" +#include "halmac_8822b_cfg.h" + +/** + * halmac_mac_power_switch_8822b_pcie() - switch mac power + * @halmac_adapter : the adapter of halmac + * @halmac_power : power state + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mac_power_switch_8822b_pcie(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power) +{ + u8 interface_mask; + u8 value8; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MAC_POWER_SWITCH); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_mac_power_switch_88xx_pcie halmac_power = %x ==========>\n", + halmac_power); + interface_mask = HALMAC_PWR_INTF_PCI_MSK; + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR); + if (value8 == 0xEA) + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + else + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_ON; + + /* Check if power switch is needed */ + if (halmac_power == HALMAC_MAC_POWER_ON && + halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_ON) { + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_WARNING, + "halmac_mac_power_switch power state unchange!\n"); + return HALMAC_RET_PWR_UNCHANGE; + } + + if (halmac_power == HALMAC_MAC_POWER_OFF) { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_disable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("Handle power off cmd error\n"); + return HALMAC_RET_POWER_OFF_FAIL; + } + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + halmac_adapter->halmac_state.ps_state = + HALMAC_PS_STATE_UNDEFINE; + halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE; + halmac_init_adapter_dynamic_para_88xx(halmac_adapter); + } else { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_enable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("Handle power on cmd error\n"); + return HALMAC_RET_POWER_ON_FAIL; + } + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_ON; + halmac_adapter->halmac_state.ps_state = HALMAC_PS_STATE_ACT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_mac_power_switch_88xx_pcie <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_pcie_switch_8822b() - pcie gen1/gen2 switch + * @halmac_adapter : the adapter of halmac + * @pcie_cfg : gen1/gen2 selection + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_pcie_switch_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_pcie_cfg pcie_cfg) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u8 current_link_speed = 0; + u32 count = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PCIE_SWITCH); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + /* Link Control 2 Register[3:0] Target Link Speed + * Defined encodings are: + * 0001b Target Link 2.5 GT/s + * 0010b Target Link 5.0 GT/s + * 0100b Target Link 8.0 GT/s + */ + + if (pcie_cfg == HALMAC_PCIE_GEN1) { + /* cfg 0xA0[3:0]=4'b0001 */ + halmac_dbi_write8_88xx( + halmac_adapter, LINK_CTRL2_REG_OFFSET, + (halmac_dbi_read8_88xx(halmac_adapter, + LINK_CTRL2_REG_OFFSET) & + 0xF0) | BIT(0)); + + /* cfg 0x80C[17]=1 //PCIe DesignWave */ + halmac_dbi_write32_88xx( + halmac_adapter, GEN2_CTRL_OFFSET, + halmac_dbi_read32_88xx(halmac_adapter, + GEN2_CTRL_OFFSET) | + BIT(17)); + + /* check link speed if GEN1 */ + /* cfg 0x82[3:0]=4'b0001 */ + current_link_speed = + halmac_dbi_read8_88xx(halmac_adapter, + LINK_STATUS_REG_OFFSET) & + 0x0F; + count = 2000; + + while (current_link_speed != GEN1_SPEED && count != 0) { + usleep_range(50, 60); + current_link_speed = + halmac_dbi_read8_88xx(halmac_adapter, + LINK_STATUS_REG_OFFSET) & + 0x0F; + count--; + } + + if (current_link_speed != GEN1_SPEED) { + pr_err("Speed change to GEN1 fail !\n"); + return HALMAC_RET_FAIL; + } + + } else if (pcie_cfg == HALMAC_PCIE_GEN2) { + /* cfg 0xA0[3:0]=4'b0010 */ + halmac_dbi_write8_88xx( + halmac_adapter, LINK_CTRL2_REG_OFFSET, + (halmac_dbi_read8_88xx(halmac_adapter, + LINK_CTRL2_REG_OFFSET) & + 0xF0) | BIT(1)); + + /* cfg 0x80C[17]=1 //PCIe DesignWave */ + halmac_dbi_write32_88xx( + halmac_adapter, GEN2_CTRL_OFFSET, + halmac_dbi_read32_88xx(halmac_adapter, + GEN2_CTRL_OFFSET) | + BIT(17)); + + /* check link speed if GEN2 */ + /* cfg 0x82[3:0]=4'b0010 */ + current_link_speed = + halmac_dbi_read8_88xx(halmac_adapter, + LINK_STATUS_REG_OFFSET) & + 0x0F; + count = 2000; + + while (current_link_speed != GEN2_SPEED && count != 0) { + usleep_range(50, 60); + current_link_speed = + halmac_dbi_read8_88xx(halmac_adapter, + LINK_STATUS_REG_OFFSET) & + 0x0F; + count--; + } + + if (current_link_speed != GEN2_SPEED) { + pr_err("Speed change to GEN1 fail !\n"); + return HALMAC_RET_FAIL; + } + + } else { + pr_err("Error Speed !\n"); + return HALMAC_RET_FAIL; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_pcie_switch_8822b_nc(struct halmac_adapter *halmac_adapter, + enum halmac_pcie_cfg pcie_cfg) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PCIE_SWITCH); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_phy_cfg_8822b_pcie() - phy config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_phy_cfg_8822b_pcie(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PHY_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg ==========>\n"); + + status = halmac_parse_intf_phy_88xx(halmac_adapter, + HALMAC_RTL8822B_PCIE_PHY_GEN1, + platform, HAL_INTF_PHY_PCIE_GEN1); + + if (status != HALMAC_RET_SUCCESS) + return status; + + status = halmac_parse_intf_phy_88xx(halmac_adapter, + HALMAC_RTL8822B_PCIE_PHY_GEN2, + platform, HAL_INTF_PHY_PCIE_GEN2); + + if (status != HALMAC_RET_SUCCESS) + return status; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_interface_integration_tuning_8822b_pcie() - pcie interface fine tuning + * @halmac_adapter : the adapter of halmac + * Author : Rick Liu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_interface_integration_tuning_8822b_pcie( + struct halmac_adapter *halmac_adapter) +{ + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h new file mode 100644 index 000000000000..c68ea0039703 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_pcie.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_8822B_PCIE_H_ +#define _HALMAC_API_8822B_PCIE_H_ + +#include "../../halmac_2_platform.h" +#include "../../halmac_type.h" + +extern struct halmac_intf_phy_para_ HALMAC_RTL8822B_PCIE_PHY_GEN1[]; +extern struct halmac_intf_phy_para_ HALMAC_RTL8822B_PCIE_PHY_GEN2[]; + +enum halmac_ret_status +halmac_mac_power_switch_8822b_pcie(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power); + +enum halmac_ret_status +halmac_pcie_switch_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_pcie_cfg pcie_cfg); + +enum halmac_ret_status +halmac_pcie_switch_8822b_nc(struct halmac_adapter *halmac_adapter, + enum halmac_pcie_cfg pcie_cfg); + +enum halmac_ret_status +halmac_phy_cfg_8822b_pcie(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform); + +enum halmac_ret_status halmac_interface_integration_tuning_8822b_pcie( + struct halmac_adapter *halmac_adapter); + +#endif /* _HALMAC_API_8822B_PCIE_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c new file mode 100644 index 000000000000..4d708d841bad --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.c @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_8822b_cfg.h" + +/** + * halmac_mac_power_switch_8822b_sdio() - switch mac power + * @halmac_adapter : the adapter of halmac + * @halmac_power : power state + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mac_power_switch_8822b_sdio(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power) +{ + u8 interface_mask; + u8 value8; + u8 rpwm; + u32 imr_backup; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "[TRACE]halmac_mac_power_switch_88xx_sdio==========>\n"); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "[TRACE]halmac_power = %x ==========>\n", halmac_power); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "[TRACE]8822B pwr seq ver = %s\n", + HALMAC_8822B_PWR_SEQ_VER); + + interface_mask = HALMAC_PWR_INTF_SDIO_MSK; + + halmac_adapter->rpwm_record = + HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HRPWM1); + + /* Check FW still exist or not */ + if (HALMAC_REG_READ_16(halmac_adapter, REG_MCUFW_CTRL) == 0xC078) { + /* Leave 32K */ + rpwm = (u8)((halmac_adapter->rpwm_record ^ BIT(7)) & 0x80); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SDIO_HRPWM1, rpwm); + } + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR); + if (value8 == 0xEA) + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + else + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_ON; + + /*Check if power switch is needed*/ + if (halmac_power == HALMAC_MAC_POWER_ON && + halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_ON) { + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_WARNING, + "[WARN]halmac_mac_power_switch power state unchange!\n"); + return HALMAC_RET_PWR_UNCHANGE; + } + + imr_backup = HALMAC_REG_READ_32(halmac_adapter, REG_SDIO_HIMR); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_HIMR, 0); + + if (halmac_power == HALMAC_MAC_POWER_OFF) { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_disable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("[ERR]Handle power off cmd error\n"); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_HIMR, + imr_backup); + return HALMAC_RET_POWER_OFF_FAIL; + } + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + halmac_adapter->halmac_state.ps_state = + HALMAC_PS_STATE_UNDEFINE; + halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE; + halmac_init_adapter_dynamic_para_88xx(halmac_adapter); + } else { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_enable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("[ERR]Handle power on cmd error\n"); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_HIMR, + imr_backup); + return HALMAC_RET_POWER_ON_FAIL; + } + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_ON; + halmac_adapter->halmac_state.ps_state = HALMAC_PS_STATE_ACT; + } + + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_HIMR, imr_backup); + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "[TRACE]halmac_mac_power_switch_88xx_sdio <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_phy_cfg_8822b_sdio() - phy config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_phy_cfg_8822b_sdio(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PHY_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg ==========>\n"); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "sdio no phy\n"); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_interface_integration_tuning_8822b_sdio() - sdio interface fine tuning + * @halmac_adapter : the adapter of halmac + * Author : Ivan + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_interface_integration_tuning_8822b_sdio( + struct halmac_adapter *halmac_adapter) +{ + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h new file mode 100644 index 000000000000..07ffb3baf7c0 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_sdio.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_8822B_SDIO_H_ +#define _HALMAC_API_8822B_SDIO_H_ + +#include "../../halmac_2_platform.h" +#include "../../halmac_type.h" + +enum halmac_ret_status +halmac_mac_power_switch_8822b_sdio(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power); + +enum halmac_ret_status +halmac_phy_cfg_8822b_sdio(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform); + +enum halmac_ret_status halmac_interface_integration_tuning_8822b_sdio( + struct halmac_adapter *halmac_adapter); + +#endif /* _HALMAC_API_8822B_SDIO_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c new file mode 100644 index 000000000000..5f27eb172430 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.c @@ -0,0 +1,185 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "../halmac_88xx_cfg.h" +#include "halmac_8822b_cfg.h" + +/** + * halmac_mac_power_switch_8822b_usb() - switch mac power + * @halmac_adapter : the adapter of halmac + * @halmac_power : power state + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mac_power_switch_8822b_usb(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power) +{ + u8 interface_mask; + u8 value8; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MAC_POWER_SWITCH); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_mac_power_switch_88xx_usb halmac_power = %x ==========>\n", + halmac_power); + + interface_mask = HALMAC_PWR_INTF_USB_MSK; + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR); + if (value8 == 0xEA) { + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + } else { + if (BIT(0) == + (HALMAC_REG_READ_8(halmac_adapter, REG_SYS_STATUS1 + 1) & + BIT(0))) + halmac_adapter->halmac_state.mac_power = + HALMAC_MAC_POWER_OFF; + else + halmac_adapter->halmac_state.mac_power = + HALMAC_MAC_POWER_ON; + } + + /*Check if power switch is needed*/ + if (halmac_power == HALMAC_MAC_POWER_ON && + halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_ON) { + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, DBG_WARNING, + "halmac_mac_power_switch power state unchange!\n"); + return HALMAC_RET_PWR_UNCHANGE; + } + if (halmac_power == HALMAC_MAC_POWER_OFF) { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_disable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("Handle power off cmd error\n"); + return HALMAC_RET_POWER_OFF_FAIL; + } + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_OFF; + halmac_adapter->halmac_state.ps_state = + HALMAC_PS_STATE_UNDEFINE; + halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE; + halmac_init_adapter_dynamic_para_88xx(halmac_adapter); + } else { + if (halmac_pwr_seq_parser_88xx( + halmac_adapter, HALMAC_PWR_CUT_ALL_MSK, + HALMAC_PWR_FAB_TSMC_MSK, interface_mask, + halmac_8822b_card_enable_flow) != + HALMAC_RET_SUCCESS) { + pr_err("Handle power on cmd error\n"); + return HALMAC_RET_POWER_ON_FAIL; + } + + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SYS_STATUS1 + 1, + HALMAC_REG_READ_8(halmac_adapter, REG_SYS_STATUS1 + 1) & + ~(BIT(0))); + + halmac_adapter->halmac_state.mac_power = HALMAC_MAC_POWER_ON; + halmac_adapter->halmac_state.ps_state = HALMAC_PS_STATE_ACT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_mac_power_switch_88xx_usb <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_phy_cfg_8822b_usb() - phy config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_phy_cfg_8822b_usb(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PHY_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg ==========>\n"); + + status = halmac_parse_intf_phy_88xx(halmac_adapter, + HALMAC_RTL8822B_USB2_PHY, platform, + HAL_INTF_PHY_USB2); + + if (status != HALMAC_RET_SUCCESS) + return status; + + status = halmac_parse_intf_phy_88xx(halmac_adapter, + HALMAC_RTL8822B_USB3_PHY, platform, + HAL_INTF_PHY_USB3); + + if (status != HALMAC_RET_SUCCESS) + return status; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "halmac_phy_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_interface_integration_tuning_8822b_usb() - usb interface fine tuning + * @halmac_adapter : the adapter of halmac + * Author : Ivan + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_interface_integration_tuning_8822b_usb( + struct halmac_adapter *halmac_adapter) +{ + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h new file mode 100644 index 000000000000..3a99fd5675e0 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_api_8822b_usb.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_8822B_USB_H_ +#define _HALMAC_API_8822B_USB_H_ + +extern struct halmac_intf_phy_para_ HALMAC_RTL8822B_USB2_PHY[]; +extern struct halmac_intf_phy_para_ HALMAC_RTL8822B_USB3_PHY[]; + +#include "../../halmac_2_platform.h" +#include "../../halmac_type.h" + +enum halmac_ret_status +halmac_mac_power_switch_8822b_usb(struct halmac_adapter *halmac_adapter, + enum halmac_mac_power halmac_power); + +enum halmac_ret_status +halmac_phy_cfg_8822b_usb(struct halmac_adapter *halmac_adapter, + enum halmac_intf_phy_platform platform); + +enum halmac_ret_status halmac_interface_integration_tuning_8822b_usb( + struct halmac_adapter *halmac_adapter); + +#endif /* _HALMAC_API_8822B_USB_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c new file mode 100644 index 000000000000..5f1dff8d9e3b --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.c @@ -0,0 +1,414 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_8822b_cfg.h" +#include "halmac_func_8822b.h" + +/*SDIO RQPN Mapping*/ +static struct halmac_rqpn_ HALMAC_RQPN_SDIO_8822B[] = { + /* { mode, vo_map, vi_map, be_map, bk_map, mg_map, hi_map } */ + {HALMAC_TRX_MODE_NORMAL, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_TRXSHARE, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_WMM, HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_P2P, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, +}; + +/*PCIE RQPN Mapping*/ +static struct halmac_rqpn_ HALMAC_RQPN_PCIE_8822B[] = { + /* { mode, vo_map, vi_map, be_map, bk_map, mg_map, hi_map } */ + {HALMAC_TRX_MODE_NORMAL, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_TRXSHARE, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_WMM, HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_P2P, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, +}; + +/*USB 2 Bulkout RQPN Mapping*/ +static struct halmac_rqpn_ HALMAC_RQPN_2BULKOUT_8822B[] = { + /* { mode, vo_map, vi_map, be_map, bk_map, mg_map, hi_map } */ + {HALMAC_TRX_MODE_NORMAL, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_TRXSHARE, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_WMM, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_P2P, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_LOOPBACK, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, + HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, + HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, +}; + +/*USB 3 Bulkout RQPN Mapping*/ +static struct halmac_rqpn_ HALMAC_RQPN_3BULKOUT_8822B[] = { + /* { mode, vo_map, vi_map, be_map, bk_map, mg_map, hi_map } */ + {HALMAC_TRX_MODE_NORMAL, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_TRXSHARE, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_WMM, HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_P2P, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_LOOPBACK, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_NQ, HALMAC_MAP2_HQ, HALMAC_MAP2_HQ}, +}; + +/*USB 4 Bulkout RQPN Mapping*/ +static struct halmac_rqpn_ HALMAC_RQPN_4BULKOUT_8822B[] = { + /* { mode, vo_map, vi_map, be_map, bk_map, mg_map, hi_map } */ + {HALMAC_TRX_MODE_NORMAL, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_TRXSHARE, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_WMM, HALMAC_MAP2_HQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_NQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_P2P, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, HALMAC_MAP2_LQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, HALMAC_MAP2_NQ, HALMAC_MAP2_NQ, + HALMAC_MAP2_LQ, HALMAC_MAP2_LQ, HALMAC_MAP2_EXQ, HALMAC_MAP2_HQ}, +}; + +/*SDIO Page Number*/ +static struct halmac_pg_num_ HALMAC_PG_NUM_SDIO_8822B[] = { + /* { mode, hq_num, nq_num, lq_num, exq_num, gap_num} */ + {HALMAC_TRX_MODE_NORMAL, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_TRXSHARE, 32, 32, 32, 32, 1}, + {HALMAC_TRX_MODE_WMM, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_P2P, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_LOOPBACK, 64, 64, 64, 64, 640}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, 64, 64, 64, 64, 640}, +}; + +/*PCIE Page Number*/ +static struct halmac_pg_num_ HALMAC_PG_NUM_PCIE_8822B[] = { + /* { mode, hq_num, nq_num, lq_num, exq_num, gap_num} */ + {HALMAC_TRX_MODE_NORMAL, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_TRXSHARE, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_WMM, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_P2P, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_LOOPBACK, 64, 64, 64, 64, 640}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, 64, 64, 64, 64, 640}, +}; + +/*USB 2 Bulkout Page Number*/ +static struct halmac_pg_num_ HALMAC_PG_NUM_2BULKOUT_8822B[] = { + /* { mode, hq_num, nq_num, lq_num, exq_num, gap_num} */ + {HALMAC_TRX_MODE_NORMAL, 64, 64, 0, 0, 1}, + {HALMAC_TRX_MODE_TRXSHARE, 64, 64, 0, 0, 1}, + {HALMAC_TRX_MODE_WMM, 64, 64, 0, 0, 1}, + {HALMAC_TRX_MODE_P2P, 64, 64, 0, 0, 1}, + {HALMAC_TRX_MODE_LOOPBACK, 64, 64, 0, 0, 1024}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, 64, 64, 0, 0, 1024}, +}; + +/*USB 3 Bulkout Page Number*/ +static struct halmac_pg_num_ HALMAC_PG_NUM_3BULKOUT_8822B[] = { + /* { mode, hq_num, nq_num, lq_num, exq_num, gap_num} */ + {HALMAC_TRX_MODE_NORMAL, 64, 64, 64, 0, 1}, + {HALMAC_TRX_MODE_TRXSHARE, 64, 64, 64, 0, 1}, + {HALMAC_TRX_MODE_WMM, 64, 64, 64, 0, 1}, + {HALMAC_TRX_MODE_P2P, 64, 64, 64, 0, 1}, + {HALMAC_TRX_MODE_LOOPBACK, 64, 64, 64, 0, 1024}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, 64, 64, 64, 0, 1024}, +}; + +/*USB 4 Bulkout Page Number*/ +static struct halmac_pg_num_ HALMAC_PG_NUM_4BULKOUT_8822B[] = { + /* { mode, hq_num, nq_num, lq_num, exq_num, gap_num} */ + {HALMAC_TRX_MODE_NORMAL, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_TRXSHARE, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_WMM, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_P2P, 64, 64, 64, 64, 1}, + {HALMAC_TRX_MODE_LOOPBACK, 64, 64, 64, 64, 640}, + {HALMAC_TRX_MODE_DELAY_LOOPBACK, 64, 64, 64, 64, 640}, +}; + +enum halmac_ret_status +halmac_txdma_queue_mapping_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode) +{ + u16 value16; + void *driver_adapter = NULL; + struct halmac_rqpn_ *curr_rqpn_sel = NULL; + enum halmac_ret_status status; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + curr_rqpn_sel = HALMAC_RQPN_SDIO_8822B; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_PCIE) { + curr_rqpn_sel = HALMAC_RQPN_PCIE_8822B; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + if (halmac_adapter->halmac_bulkout_num == 2) { + curr_rqpn_sel = HALMAC_RQPN_2BULKOUT_8822B; + } else if (halmac_adapter->halmac_bulkout_num == 3) { + curr_rqpn_sel = HALMAC_RQPN_3BULKOUT_8822B; + } else if (halmac_adapter->halmac_bulkout_num == 4) { + curr_rqpn_sel = HALMAC_RQPN_4BULKOUT_8822B; + } else { + pr_err("[ERR]interface not support\n"); + return HALMAC_RET_NOT_SUPPORT; + } + } else { + return HALMAC_RET_NOT_SUPPORT; + } + + status = halmac_rqpn_parser_88xx(halmac_adapter, halmac_trx_mode, + curr_rqpn_sel); + if (status != HALMAC_RET_SUCCESS) + return status; + + value16 = 0; + value16 |= BIT_TXDMA_HIQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI]); + value16 |= BIT_TXDMA_MGQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG]); + value16 |= BIT_TXDMA_BKQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK]); + value16 |= BIT_TXDMA_BEQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE]); + value16 |= BIT_TXDMA_VIQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI]); + value16 |= BIT_TXDMA_VOQ_MAP( + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO]); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXDMA_PQ_MAP, value16); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_priority_queue_config_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode) +{ + u8 transfer_mode = 0; + u8 value8; + u32 counter; + enum halmac_ret_status status; + struct halmac_pg_num_ *curr_pg_num = NULL; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (halmac_adapter->txff_allocation.la_mode == HALMAC_LA_MODE_DISABLE) { + if (halmac_adapter->txff_allocation.rx_fifo_expanding_mode == + HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE) { + halmac_adapter->txff_allocation.tx_fifo_pg_num = + HALMAC_TX_FIFO_SIZE_8822B >> + HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + } else if (halmac_adapter->txff_allocation + .rx_fifo_expanding_mode == + HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK) { + halmac_adapter->txff_allocation.tx_fifo_pg_num = + HALMAC_TX_FIFO_SIZE_EX_1_BLK_8822B >> + HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + halmac_adapter->hw_config_info.tx_fifo_size = + HALMAC_TX_FIFO_SIZE_EX_1_BLK_8822B; + if (HALMAC_RX_FIFO_SIZE_EX_1_BLK_8822B <= + HALMAC_RX_FIFO_SIZE_EX_1_BLK_MAX_8822B) + halmac_adapter->hw_config_info.rx_fifo_size = + HALMAC_RX_FIFO_SIZE_EX_1_BLK_8822B; + else + halmac_adapter->hw_config_info.rx_fifo_size = + HALMAC_RX_FIFO_SIZE_EX_1_BLK_MAX_8822B; + } else { + halmac_adapter->txff_allocation.tx_fifo_pg_num = + HALMAC_TX_FIFO_SIZE_8822B >> + HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + pr_err("[ERR]rx_fifo_expanding_mode = %d not support\n", + halmac_adapter->txff_allocation + .rx_fifo_expanding_mode); + } + } else { + halmac_adapter->txff_allocation.tx_fifo_pg_num = + HALMAC_TX_FIFO_SIZE_LA_8822B >> + HALMAC_TX_PAGE_SIZE_2_POWER_8822B; + } + halmac_adapter->txff_allocation.rsvd_pg_num = + (halmac_adapter->txff_allocation.rsvd_drv_pg_num + + HALMAC_RSVD_H2C_EXTRAINFO_PGNUM_8822B + + HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B + + HALMAC_RSVD_CPU_INSTRUCTION_PGNUM_8822B + + HALMAC_RSVD_FW_TXBUFF_PGNUM_8822B); + if (halmac_adapter->txff_allocation.rsvd_pg_num > + halmac_adapter->txff_allocation.tx_fifo_pg_num) + return HALMAC_RET_CFG_TXFIFO_PAGE_FAIL; + + halmac_adapter->txff_allocation.ac_q_pg_num = + halmac_adapter->txff_allocation.tx_fifo_pg_num - + halmac_adapter->txff_allocation.rsvd_pg_num; + halmac_adapter->txff_allocation.rsvd_pg_bndy = + halmac_adapter->txff_allocation.tx_fifo_pg_num - + halmac_adapter->txff_allocation.rsvd_pg_num; + halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy = + halmac_adapter->txff_allocation.tx_fifo_pg_num - + HALMAC_RSVD_FW_TXBUFF_PGNUM_8822B; + halmac_adapter->txff_allocation.rsvd_cpu_instr_pg_bndy = + halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy - + HALMAC_RSVD_CPU_INSTRUCTION_PGNUM_8822B; + halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy = + halmac_adapter->txff_allocation.rsvd_cpu_instr_pg_bndy - + HALMAC_RSVD_H2C_QUEUE_PGNUM_8822B; + halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy = + halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy - + HALMAC_RSVD_H2C_EXTRAINFO_PGNUM_8822B; + halmac_adapter->txff_allocation.rsvd_drv_pg_bndy = + halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy - + halmac_adapter->txff_allocation.rsvd_drv_pg_num; + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + curr_pg_num = HALMAC_PG_NUM_SDIO_8822B; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_PCIE) { + curr_pg_num = HALMAC_PG_NUM_PCIE_8822B; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + if (halmac_adapter->halmac_bulkout_num == 2) { + curr_pg_num = HALMAC_PG_NUM_2BULKOUT_8822B; + } else if (halmac_adapter->halmac_bulkout_num == 3) { + curr_pg_num = HALMAC_PG_NUM_3BULKOUT_8822B; + } else if (halmac_adapter->halmac_bulkout_num == 4) { + curr_pg_num = HALMAC_PG_NUM_4BULKOUT_8822B; + } else { + pr_err("[ERR]interface not support\n"); + return HALMAC_RET_NOT_SUPPORT; + } + } else { + return HALMAC_RET_NOT_SUPPORT; + } + + status = halmac_pg_num_parser_88xx(halmac_adapter, halmac_trx_mode, + curr_pg_num); + if (status != HALMAC_RET_SUCCESS) + return status; + + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_1, + halmac_adapter->txff_allocation.high_queue_pg_num); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_2, + halmac_adapter->txff_allocation.low_queue_pg_num); + HALMAC_REG_WRITE_16( + halmac_adapter, REG_FIFOPAGE_INFO_3, + halmac_adapter->txff_allocation.normal_queue_pg_num); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_4, + halmac_adapter->txff_allocation.extra_queue_pg_num); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_5, + halmac_adapter->txff_allocation.pub_queue_pg_num); + + halmac_adapter->sdio_free_space.high_queue_number = + halmac_adapter->txff_allocation.high_queue_pg_num; + halmac_adapter->sdio_free_space.normal_queue_number = + halmac_adapter->txff_allocation.normal_queue_pg_num; + halmac_adapter->sdio_free_space.low_queue_number = + halmac_adapter->txff_allocation.low_queue_pg_num; + halmac_adapter->sdio_free_space.public_queue_number = + halmac_adapter->txff_allocation.pub_queue_pg_num; + halmac_adapter->sdio_free_space.extra_queue_number = + halmac_adapter->txff_allocation.extra_queue_pg_num; + + HALMAC_REG_WRITE_32( + halmac_adapter, REG_RQPN_CTRL_2, + HALMAC_REG_READ_32(halmac_adapter, REG_RQPN_CTRL_2) | BIT(31)); + + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BCNQ_BDNY_V1, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCNQ_PGBNDY_V1)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BCNQ1_BDNY_V1, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCNQ_PGBNDY_V1)); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_RXFF_BNDY, + halmac_adapter->hw_config_info.rx_fifo_size - + HALMAC_C2H_PKT_BUF_8822B - 1); + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + value8 = (u8)( + HALMAC_REG_READ_8(halmac_adapter, REG_AUTO_LLT_V1) & + ~(BIT_MASK_BLK_DESC_NUM << BIT_SHIFT_BLK_DESC_NUM)); + value8 = (u8)(value8 | (HALMAC_BLK_DESC_NUM_8822B + << BIT_SHIFT_BLK_DESC_NUM)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_AUTO_LLT_V1, value8); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_AUTO_LLT_V1 + 3, + HALMAC_BLK_DESC_NUM_8822B); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_OFFSET_CHK + 1, + HALMAC_REG_READ_8(halmac_adapter, + REG_TXDMA_OFFSET_CHK + 1) | + BIT(1)); + } + + HALMAC_REG_WRITE_8( + halmac_adapter, REG_AUTO_LLT_V1, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_AUTO_LLT_V1) | + BIT_AUTO_INIT_LLT_V1)); + counter = 1000; + while (HALMAC_REG_READ_8(halmac_adapter, REG_AUTO_LLT_V1) & + BIT_AUTO_INIT_LLT_V1) { + counter--; + if (counter == 0) + return HALMAC_RET_INIT_LLT_FAIL; + } + + if (halmac_trx_mode == HALMAC_TRX_MODE_DELAY_LOOPBACK) { + transfer_mode = HALMAC_TRNSFER_LOOPBACK_DELAY; + HALMAC_REG_WRITE_16( + halmac_adapter, REG_WMAC_LBK_BUF_HD_V1, + (u16)halmac_adapter->txff_allocation.rsvd_pg_bndy); + } else if (halmac_trx_mode == HALMAC_TRX_MODE_LOOPBACK) { + transfer_mode = HALMAC_TRNSFER_LOOPBACK_DIRECT; + } else { + transfer_mode = HALMAC_TRNSFER_NORMAL; + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 3, (u8)transfer_mode); + + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h new file mode 100644 index 000000000000..5ac2b15477c0 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_8822b/halmac_func_8822b.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_FUNC_8822B_H_ +#define _HALMAC_FUNC_8822B_H_ + +#include "../../halmac_type.h" + +enum halmac_ret_status +halmac_txdma_queue_mapping_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode); + +enum halmac_ret_status +halmac_priority_queue_config_8822b(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode); + +#endif /* _HALMAC_FUNC_8822B_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_88xx_cfg.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_88xx_cfg.h new file mode 100644 index 000000000000..ea1206744902 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_88xx_cfg.h @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_88XX_CFG_H_ +#define _HALMAC_88XX_CFG_H_ + +#include "../halmac_2_platform.h" +#include "../halmac_type.h" +#include "../halmac_api.h" +#include "../halmac_bit2.h" +#include "../halmac_reg2.h" +#include "../halmac_pwr_seq_cmd.h" +#include "halmac_func_88xx.h" +#include "halmac_api_88xx.h" +#include "halmac_api_88xx_usb.h" +#include "halmac_api_88xx_pcie.h" +#include "halmac_api_88xx_sdio.h" + +#define HALMAC_SVN_VER_88XX "13359M" + +#define HALMAC_MAJOR_VER_88XX 0x0001 /* major version, ver_1 for async_api */ +/* For halmac_api num change or prototype change, increment prototype version. + * Otherwise, increase minor version + */ +#define HALMAC_PROTOTYPE_VER_88XX 0x0003 /* prototype version */ +#define HALMAC_MINOR_VER_88XX 0x0005 /* minor version */ +#define HALMAC_PATCH_VER_88XX 0x0000 /* patch version */ + +#define HALMAC_C2H_DATA_OFFSET_88XX 10 +#define HALMAC_RX_AGG_ALIGNMENT_SIZE_88XX 8 +#define HALMAC_TX_AGG_ALIGNMENT_SIZE_88XX 8 +#define HALMAC_TX_AGG_BUFF_SIZE_88XX 32768 + +#define HALMAC_EXTRA_INFO_BUFF_SIZE_88XX 4096 /*4K*/ +#define HALMAC_EXTRA_INFO_BUFF_SIZE_FULL_FIFO_88XX 16384 /*16K*/ +#define HALMAC_FW_OFFLOAD_CMD_SIZE_88XX \ + 12 /*Fw config parameter cmd size, each 12 byte*/ + +#define HALMAC_H2C_CMD_ORIGINAL_SIZE_88XX 8 +#define HALMAC_H2C_CMD_SIZE_UNIT_88XX 32 /* Only support 32 byte packet now */ + +#define HALMAC_NLO_INFO_SIZE_88XX 1024 + +/* Download FW */ +#define HALMAC_FW_SIZE_MAX_88XX 0x40000 +#define HALMAC_FWHDR_SIZE_88XX 64 +#define HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX 8 +#define HALMAC_FW_MAX_DL_SIZE_88XX 0x2000 /* need power of 2 */ +/* Max dlfw size can not over 31K, because SDIO HW restriction */ +#define HALMAC_FW_CFG_MAX_DL_SIZE_MAX_88XX 0x7C00 + +#define DLFW_RESTORE_REG_NUM_88XX 9 +#define ID_INFORM_DLEMEM_RDY 0x80 + +/* FW header information */ +#define HALMAC_FWHDR_OFFSET_VERSION_88XX 4 +#define HALMAC_FWHDR_OFFSET_SUBVERSION_88XX 6 +#define HALMAC_FWHDR_OFFSET_SUBINDEX_88XX 7 +#define HALMAC_FWHDR_OFFSET_MEM_USAGE_88XX 24 +#define HALMAC_FWHDR_OFFSET_H2C_FORMAT_VER_88XX 28 +#define HALMAC_FWHDR_OFFSET_DMEM_ADDR_88XX 32 +#define HALMAC_FWHDR_OFFSET_DMEM_SIZE_88XX 36 +#define HALMAC_FWHDR_OFFSET_IRAM_SIZE_88XX 48 +#define HALMAC_FWHDR_OFFSET_ERAM_SIZE_88XX 52 +#define HALMAC_FWHDR_OFFSET_EMEM_ADDR_88XX 56 +#define HALMAC_FWHDR_OFFSET_IRAM_ADDR_88XX 60 + +/* HW memory address */ +#define HALMAC_OCPBASE_TXBUF_88XX 0x18780000 +#define HALMAC_OCPBASE_DMEM_88XX 0x00200000 +#define HALMAC_OCPBASE_IMEM_88XX 0x00000000 + +/* define the SDIO Bus CLK threshold, for avoiding CMD53 fails that + * result from SDIO CLK sync to ana_clk fail + */ +#define HALMAC_SD_CLK_THRESHOLD_88XX 150000000 /* 150MHz */ + +/* MAC clock */ +#define HALMAC_MAC_CLOCK_88XX 80 /* 80M */ + +/* H2C/C2H*/ +#define HALMAC_H2C_CMD_SIZE_88XX 32 +#define HALMAC_H2C_CMD_HDR_SIZE_88XX 8 + +#define HALMAC_PROTECTED_EFUSE_SIZE_88XX 0x60 + +/* Function enable */ +#define HALMAC_FUNCTION_ENABLE_88XX 0xDC + +/* FIFO size & packet size */ +/* #define HALMAC_WOWLAN_PATTERN_SIZE 256 */ + +/* CFEND rate */ +#define HALMAC_BASIC_CFEND_RATE_88XX 0x5 +#define HALMAC_STBC_CFEND_RATE_88XX 0xF + +/* Response rate */ +#define HALMAC_RESPONSE_RATE_BITMAP_ALL_88XX 0xFFFFF +#define HALMAC_RESPONSE_RATE_88XX HALMAC_RESPONSE_RATE_BITMAP_ALL_88XX + +/* Spec SIFS */ +#define HALMAC_SIFS_CCK_PTCL_88XX 16 +#define HALMAC_SIFS_OFDM_PTCL_88XX 16 + +/* Retry limit */ +#define HALMAC_LONG_RETRY_LIMIT_88XX 8 +#define HALMAC_SHORT_RETRY_LIMIT_88XX 7 + +/* Slot, SIFS, PIFS time */ +#define HALMAC_SLOT_TIME_88XX 0x05 +#define HALMAC_PIFS_TIME_88XX 0x19 +#define HALMAC_SIFS_CCK_CTX_88XX 0xA +#define HALMAC_SIFS_OFDM_CTX_88XX 0xA +#define HALMAC_SIFS_CCK_TRX_88XX 0x10 +#define HALMAC_SIFS_OFDM_TRX_88XX 0x10 + +/* TXOP limit */ +#define HALMAC_VO_TXOP_LIMIT_88XX 0x186 +#define HALMAC_VI_TXOP_LIMIT_88XX 0x3BC + +/* NAV */ +#define HALMAC_RDG_NAV_88XX 0x05 +#define HALMAC_TXOP_NAV_88XX 0x1B + +/* TSF */ +#define HALMAC_CCK_RX_TSF_88XX 0x30 +#define HALMAC_OFDM_RX_TSF_88XX 0x30 + +/* Send beacon related */ +#define HALMAC_TBTT_PROHIBIT_88XX 0x04 +#define HALMAC_TBTT_HOLD_TIME_88XX 0x064 +#define HALMAC_DRIVER_EARLY_INT_88XX 0x04 +#define HALMAC_BEACON_DMA_TIM_88XX 0x02 + +/* RX filter */ +#define HALMAC_RX_FILTER0_RECIVE_ALL_88XX 0xFFFFFFF +#define HALMAC_RX_FILTER0_88XX HALMAC_RX_FILTER0_RECIVE_ALL_88XX +#define HALMAC_RX_FILTER_RECIVE_ALL_88XX 0xFFFF +#define HALMAC_RX_FILTER_88XX HALMAC_RX_FILTER_RECIVE_ALL_88XX + +/* RCR */ +#define HALMAC_RCR_CONFIG_88XX 0xE400631E + +/* Security config */ +#define HALMAC_SECURITY_CONFIG_88XX 0x01CC + +/* CCK rate ACK timeout */ +#define HALMAC_ACK_TO_CCK_88XX 0x40 + +#endif diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c new file mode 100644 index 000000000000..5f84526cb5b5 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c @@ -0,0 +1,5979 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_88xx_cfg.h" + +/** + * halmac_init_adapter_para_88xx() - int halmac adapter + * @halmac_adapter + * + * SD1 internal use + * + * Author : KaiYuan Chang/Ivan Lin + * Return : void + */ +void halmac_init_adapter_para_88xx(struct halmac_adapter *halmac_adapter) +{ + halmac_adapter->api_record.array_wptr = 0; + halmac_adapter->hal_adapter_backup = halmac_adapter; + halmac_adapter->hal_efuse_map = (u8 *)NULL; + halmac_adapter->hal_efuse_map_valid = false; + halmac_adapter->efuse_end = 0; + halmac_adapter->hal_mac_addr[0].address_l_h.address_low = 0; + halmac_adapter->hal_mac_addr[0].address_l_h.address_high = 0; + halmac_adapter->hal_mac_addr[1].address_l_h.address_low = 0; + halmac_adapter->hal_mac_addr[1].address_l_h.address_high = 0; + halmac_adapter->hal_bss_addr[0].address_l_h.address_low = 0; + halmac_adapter->hal_bss_addr[0].address_l_h.address_high = 0; + halmac_adapter->hal_bss_addr[1].address_l_h.address_low = 0; + halmac_adapter->hal_bss_addr[1].address_l_h.address_high = 0; + + halmac_adapter->low_clk = false; + halmac_adapter->max_download_size = HALMAC_FW_MAX_DL_SIZE_88XX; + + /* Init LPS Option */ + halmac_adapter->fwlps_option.mode = 0x01; /*0:Active 1:LPS 2:WMMPS*/ + halmac_adapter->fwlps_option.awake_interval = 1; + halmac_adapter->fwlps_option.enter_32K = 1; + halmac_adapter->fwlps_option.clk_request = 0; + halmac_adapter->fwlps_option.rlbm = 0; + halmac_adapter->fwlps_option.smart_ps = 0; + halmac_adapter->fwlps_option.awake_interval = 1; + halmac_adapter->fwlps_option.all_queue_uapsd = 0; + halmac_adapter->fwlps_option.pwr_state = 0; + halmac_adapter->fwlps_option.low_pwr_rx_beacon = 0; + halmac_adapter->fwlps_option.ant_auto_switch = 0; + halmac_adapter->fwlps_option.ps_allow_bt_high_priority = 0; + halmac_adapter->fwlps_option.protect_bcn = 0; + halmac_adapter->fwlps_option.silence_period = 0; + halmac_adapter->fwlps_option.fast_bt_connect = 0; + halmac_adapter->fwlps_option.two_antenna_en = 0; + halmac_adapter->fwlps_option.adopt_user_setting = 1; + halmac_adapter->fwlps_option.drv_bcn_early_shift = 0; + + halmac_adapter->config_para_info.cfg_para_buf = NULL; + halmac_adapter->config_para_info.para_buf_w = NULL; + halmac_adapter->config_para_info.para_num = 0; + halmac_adapter->config_para_info.full_fifo_mode = false; + halmac_adapter->config_para_info.para_buf_size = 0; + halmac_adapter->config_para_info.avai_para_buf_size = 0; + halmac_adapter->config_para_info.offset_accumulation = 0; + halmac_adapter->config_para_info.value_accumulation = 0; + halmac_adapter->config_para_info.datapack_segment = 0; + + halmac_adapter->ch_sw_info.ch_info_buf = NULL; + halmac_adapter->ch_sw_info.ch_info_buf_w = NULL; + halmac_adapter->ch_sw_info.extra_info_en = 0; + halmac_adapter->ch_sw_info.buf_size = 0; + halmac_adapter->ch_sw_info.avai_buf_size = 0; + halmac_adapter->ch_sw_info.total_size = 0; + halmac_adapter->ch_sw_info.ch_num = 0; + + halmac_adapter->drv_info_size = 0; + + memset(halmac_adapter->api_record.api_array, HALMAC_API_STUFF, + sizeof(halmac_adapter->api_record.api_array)); + + halmac_adapter->txff_allocation.tx_fifo_pg_num = 0; + halmac_adapter->txff_allocation.ac_q_pg_num = 0; + halmac_adapter->txff_allocation.rsvd_pg_bndy = 0; + halmac_adapter->txff_allocation.rsvd_drv_pg_bndy = 0; + halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy = 0; + halmac_adapter->txff_allocation.rsvd_h2c_queue_pg_bndy = 0; + halmac_adapter->txff_allocation.rsvd_cpu_instr_pg_bndy = 0; + halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy = 0; + halmac_adapter->txff_allocation.pub_queue_pg_num = 0; + halmac_adapter->txff_allocation.high_queue_pg_num = 0; + halmac_adapter->txff_allocation.low_queue_pg_num = 0; + halmac_adapter->txff_allocation.normal_queue_pg_num = 0; + halmac_adapter->txff_allocation.extra_queue_pg_num = 0; + + halmac_adapter->txff_allocation.la_mode = HALMAC_LA_MODE_DISABLE; + halmac_adapter->txff_allocation.rx_fifo_expanding_mode = + HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE; + + halmac_init_adapter_dynamic_para_88xx(halmac_adapter); + halmac_init_state_machine_88xx(halmac_adapter); +} + +/** + * halmac_init_adapter_dynamic_para_88xx() - int halmac adapter + * @halmac_adapter + * + * SD1 internal use + * + * Author : KaiYuan Chang/Ivan Lin + * Return : void + */ +void halmac_init_adapter_dynamic_para_88xx( + struct halmac_adapter *halmac_adapter) +{ + halmac_adapter->h2c_packet_seq = 0; + halmac_adapter->h2c_buf_free_space = 0; + halmac_adapter->gen_info_valid = false; +} + +/** + * halmac_init_state_machine_88xx() - init halmac software state machine + * @halmac_adapter + * + * SD1 internal use. + * + * Author : KaiYuan Chang/Ivan Lin + * Return : void + */ +void halmac_init_state_machine_88xx(struct halmac_adapter *halmac_adapter) +{ + struct halmac_state *state = &halmac_adapter->halmac_state; + + halmac_init_offload_feature_state_machine_88xx(halmac_adapter); + + state->api_state = HALMAC_API_STATE_INIT; + + state->dlfw_state = HALMAC_DLFW_NONE; + state->mac_power = HALMAC_MAC_POWER_OFF; + state->ps_state = HALMAC_PS_STATE_UNDEFINE; +} + +/** + * halmac_mount_api_88xx() - attach functions to function pointer + * @halmac_adapter + * + * SD1 internal use + * + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + */ +enum halmac_ret_status +halmac_mount_api_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = halmac_adapter->driver_adapter; + struct halmac_api *halmac_api = (struct halmac_api *)NULL; + + halmac_adapter->halmac_api = + kzalloc(sizeof(struct halmac_api), GFP_KERNEL); + if (!halmac_adapter->halmac_api) + return HALMAC_RET_MALLOC_FAIL; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + HALMAC_SVN_VER_88XX "\n"); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "HALMAC_MAJOR_VER_88XX = %x\n", HALMAC_MAJOR_VER_88XX); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "HALMAC_PROTOTYPE_88XX = %x\n", + HALMAC_PROTOTYPE_VER_88XX); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "HALMAC_MINOR_VER_88XX = %x\n", HALMAC_MINOR_VER_88XX); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "HALMAC_PATCH_VER_88XX = %x\n", HALMAC_PATCH_VER_88XX); + + /* Mount function pointer */ + halmac_api->halmac_download_firmware = halmac_download_firmware_88xx; + halmac_api->halmac_free_download_firmware = + halmac_free_download_firmware_88xx; + halmac_api->halmac_get_fw_version = halmac_get_fw_version_88xx; + halmac_api->halmac_cfg_mac_addr = halmac_cfg_mac_addr_88xx; + halmac_api->halmac_cfg_bssid = halmac_cfg_bssid_88xx; + halmac_api->halmac_cfg_multicast_addr = halmac_cfg_multicast_addr_88xx; + halmac_api->halmac_pre_init_system_cfg = + halmac_pre_init_system_cfg_88xx; + halmac_api->halmac_init_system_cfg = halmac_init_system_cfg_88xx; + halmac_api->halmac_init_edca_cfg = halmac_init_edca_cfg_88xx; + halmac_api->halmac_cfg_operation_mode = halmac_cfg_operation_mode_88xx; + halmac_api->halmac_cfg_ch_bw = halmac_cfg_ch_bw_88xx; + halmac_api->halmac_cfg_bw = halmac_cfg_bw_88xx; + halmac_api->halmac_init_wmac_cfg = halmac_init_wmac_cfg_88xx; + halmac_api->halmac_init_mac_cfg = halmac_init_mac_cfg_88xx; + halmac_api->halmac_init_sdio_cfg = halmac_init_sdio_cfg_88xx; + halmac_api->halmac_init_usb_cfg = halmac_init_usb_cfg_88xx; + halmac_api->halmac_init_pcie_cfg = halmac_init_pcie_cfg_88xx; + halmac_api->halmac_deinit_sdio_cfg = halmac_deinit_sdio_cfg_88xx; + halmac_api->halmac_deinit_usb_cfg = halmac_deinit_usb_cfg_88xx; + halmac_api->halmac_deinit_pcie_cfg = halmac_deinit_pcie_cfg_88xx; + halmac_api->halmac_dump_efuse_map = halmac_dump_efuse_map_88xx; + halmac_api->halmac_dump_efuse_map_bt = halmac_dump_efuse_map_bt_88xx; + halmac_api->halmac_write_efuse_bt = halmac_write_efuse_bt_88xx; + halmac_api->halmac_dump_logical_efuse_map = + halmac_dump_logical_efuse_map_88xx; + halmac_api->halmac_pg_efuse_by_map = halmac_pg_efuse_by_map_88xx; + halmac_api->halmac_get_efuse_size = halmac_get_efuse_size_88xx; + halmac_api->halmac_get_efuse_available_size = + halmac_get_efuse_available_size_88xx; + halmac_api->halmac_get_c2h_info = halmac_get_c2h_info_88xx; + + halmac_api->halmac_get_logical_efuse_size = + halmac_get_logical_efuse_size_88xx; + + halmac_api->halmac_write_logical_efuse = + halmac_write_logical_efuse_88xx; + halmac_api->halmac_read_logical_efuse = halmac_read_logical_efuse_88xx; + + halmac_api->halmac_cfg_fwlps_option = halmac_cfg_fwlps_option_88xx; + halmac_api->halmac_cfg_fwips_option = halmac_cfg_fwips_option_88xx; + halmac_api->halmac_enter_wowlan = halmac_enter_wowlan_88xx; + halmac_api->halmac_leave_wowlan = halmac_leave_wowlan_88xx; + halmac_api->halmac_enter_ps = halmac_enter_ps_88xx; + halmac_api->halmac_leave_ps = halmac_leave_ps_88xx; + halmac_api->halmac_h2c_lb = halmac_h2c_lb_88xx; + halmac_api->halmac_debug = halmac_debug_88xx; + halmac_api->halmac_cfg_parameter = halmac_cfg_parameter_88xx; + halmac_api->halmac_update_datapack = halmac_update_datapack_88xx; + halmac_api->halmac_run_datapack = halmac_run_datapack_88xx; + halmac_api->halmac_cfg_drv_info = halmac_cfg_drv_info_88xx; + halmac_api->halmac_send_bt_coex = halmac_send_bt_coex_88xx; + halmac_api->halmac_verify_platform_api = + halmac_verify_platform_api_88xx; + halmac_api->halmac_update_packet = halmac_update_packet_88xx; + halmac_api->halmac_bcn_ie_filter = halmac_bcn_ie_filter_88xx; + halmac_api->halmac_cfg_txbf = halmac_cfg_txbf_88xx; + halmac_api->halmac_cfg_mumimo = halmac_cfg_mumimo_88xx; + halmac_api->halmac_cfg_sounding = halmac_cfg_sounding_88xx; + halmac_api->halmac_del_sounding = halmac_del_sounding_88xx; + halmac_api->halmac_su_bfer_entry_init = halmac_su_bfer_entry_init_88xx; + halmac_api->halmac_su_bfee_entry_init = halmac_su_bfee_entry_init_88xx; + halmac_api->halmac_mu_bfer_entry_init = halmac_mu_bfer_entry_init_88xx; + halmac_api->halmac_mu_bfee_entry_init = halmac_mu_bfee_entry_init_88xx; + halmac_api->halmac_su_bfer_entry_del = halmac_su_bfer_entry_del_88xx; + halmac_api->halmac_su_bfee_entry_del = halmac_su_bfee_entry_del_88xx; + halmac_api->halmac_mu_bfer_entry_del = halmac_mu_bfer_entry_del_88xx; + halmac_api->halmac_mu_bfee_entry_del = halmac_mu_bfee_entry_del_88xx; + + halmac_api->halmac_add_ch_info = halmac_add_ch_info_88xx; + halmac_api->halmac_add_extra_ch_info = halmac_add_extra_ch_info_88xx; + halmac_api->halmac_ctrl_ch_switch = halmac_ctrl_ch_switch_88xx; + halmac_api->halmac_p2pps = halmac_p2pps_88xx; + halmac_api->halmac_clear_ch_info = halmac_clear_ch_info_88xx; + halmac_api->halmac_send_general_info = halmac_send_general_info_88xx; + + halmac_api->halmac_start_iqk = halmac_start_iqk_88xx; + halmac_api->halmac_ctrl_pwr_tracking = halmac_ctrl_pwr_tracking_88xx; + halmac_api->halmac_psd = halmac_psd_88xx; + halmac_api->halmac_cfg_la_mode = halmac_cfg_la_mode_88xx; + halmac_api->halmac_cfg_rx_fifo_expanding_mode = + halmac_cfg_rx_fifo_expanding_mode_88xx; + + halmac_api->halmac_config_security = halmac_config_security_88xx; + halmac_api->halmac_get_used_cam_entry_num = + halmac_get_used_cam_entry_num_88xx; + halmac_api->halmac_read_cam_entry = halmac_read_cam_entry_88xx; + halmac_api->halmac_write_cam = halmac_write_cam_88xx; + halmac_api->halmac_clear_cam_entry = halmac_clear_cam_entry_88xx; + + halmac_api->halmac_get_hw_value = halmac_get_hw_value_88xx; + halmac_api->halmac_set_hw_value = halmac_set_hw_value_88xx; + + halmac_api->halmac_cfg_drv_rsvd_pg_num = + halmac_cfg_drv_rsvd_pg_num_88xx; + halmac_api->halmac_get_chip_version = halmac_get_chip_version_88xx; + + halmac_api->halmac_query_status = halmac_query_status_88xx; + halmac_api->halmac_reset_feature = halmac_reset_feature_88xx; + halmac_api->halmac_check_fw_status = halmac_check_fw_status_88xx; + halmac_api->halmac_dump_fw_dmem = halmac_dump_fw_dmem_88xx; + halmac_api->halmac_cfg_max_dl_size = halmac_cfg_max_dl_size_88xx; + + halmac_api->halmac_dump_fifo = halmac_dump_fifo_88xx; + halmac_api->halmac_get_fifo_size = halmac_get_fifo_size_88xx; + + halmac_api->halmac_chk_txdesc = halmac_chk_txdesc_88xx; + halmac_api->halmac_dl_drv_rsvd_page = halmac_dl_drv_rsvd_page_88xx; + halmac_api->halmac_cfg_csi_rate = halmac_cfg_csi_rate_88xx; + + halmac_api->halmac_sdio_cmd53_4byte = halmac_sdio_cmd53_4byte_88xx; + halmac_api->halmac_txfifo_is_empty = halmac_txfifo_is_empty_88xx; + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + halmac_api->halmac_cfg_rx_aggregation = + halmac_cfg_rx_aggregation_88xx_sdio; + halmac_api->halmac_init_interface_cfg = + halmac_init_sdio_cfg_88xx; + halmac_api->halmac_deinit_interface_cfg = + halmac_deinit_sdio_cfg_88xx; + halmac_api->halmac_reg_read_8 = halmac_reg_read_8_sdio_88xx; + halmac_api->halmac_reg_write_8 = halmac_reg_write_8_sdio_88xx; + halmac_api->halmac_reg_read_16 = halmac_reg_read_16_sdio_88xx; + halmac_api->halmac_reg_write_16 = halmac_reg_write_16_sdio_88xx; + halmac_api->halmac_reg_read_32 = halmac_reg_read_32_sdio_88xx; + halmac_api->halmac_reg_write_32 = halmac_reg_write_32_sdio_88xx; + halmac_api->halmac_reg_read_indirect_32 = + halmac_reg_read_indirect_32_sdio_88xx; + halmac_api->halmac_reg_sdio_cmd53_read_n = + halmac_reg_read_nbyte_sdio_88xx; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + halmac_api->halmac_cfg_rx_aggregation = + halmac_cfg_rx_aggregation_88xx_usb; + halmac_api->halmac_init_interface_cfg = + halmac_init_usb_cfg_88xx; + halmac_api->halmac_deinit_interface_cfg = + halmac_deinit_usb_cfg_88xx; + halmac_api->halmac_reg_read_8 = halmac_reg_read_8_usb_88xx; + halmac_api->halmac_reg_write_8 = halmac_reg_write_8_usb_88xx; + halmac_api->halmac_reg_read_16 = halmac_reg_read_16_usb_88xx; + halmac_api->halmac_reg_write_16 = halmac_reg_write_16_usb_88xx; + halmac_api->halmac_reg_read_32 = halmac_reg_read_32_usb_88xx; + halmac_api->halmac_reg_write_32 = halmac_reg_write_32_usb_88xx; + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_PCIE) { + halmac_api->halmac_cfg_rx_aggregation = + halmac_cfg_rx_aggregation_88xx_pcie; + halmac_api->halmac_init_interface_cfg = + halmac_init_pcie_cfg_88xx; + halmac_api->halmac_deinit_interface_cfg = + halmac_deinit_pcie_cfg_88xx; + halmac_api->halmac_reg_read_8 = halmac_reg_read_8_pcie_88xx; + halmac_api->halmac_reg_write_8 = halmac_reg_write_8_pcie_88xx; + halmac_api->halmac_reg_read_16 = halmac_reg_read_16_pcie_88xx; + halmac_api->halmac_reg_write_16 = halmac_reg_write_16_pcie_88xx; + halmac_api->halmac_reg_read_32 = halmac_reg_read_32_pcie_88xx; + halmac_api->halmac_reg_write_32 = halmac_reg_write_32_pcie_88xx; + } else { + pr_err("Set halmac io function Error!!\n"); + } + + halmac_api->halmac_set_bulkout_num = halmac_set_bulkout_num_88xx; + halmac_api->halmac_get_sdio_tx_addr = halmac_get_sdio_tx_addr_88xx; + halmac_api->halmac_get_usb_bulkout_id = halmac_get_usb_bulkout_id_88xx; + halmac_api->halmac_timer_2s = halmac_timer_2s_88xx; + halmac_api->halmac_fill_txdesc_checksum = + halmac_fill_txdesc_check_sum_88xx; + + if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8822B) { + /*mount 8822b function and data*/ + halmac_mount_api_8822b(halmac_adapter); + + } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8821C) { + } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8814B) { + } else if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8197F) { + } else { + pr_err("Chip ID undefine!!\n"); + return HALMAC_RET_CHIP_NOT_SUPPORT; + } + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_download_firmware_88xx() - download Firmware + * @halmac_adapter : the adapter of halmac + * @hamacl_fw : firmware bin + * @halmac_fw_size : firmware size + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_download_firmware_88xx(struct halmac_adapter *halmac_adapter, + u8 *hamacl_fw, u32 halmac_fw_size) +{ + u8 value8; + u8 *file_ptr; + u32 dest; + u16 value16; + u32 restore_index = 0; + u32 halmac_h2c_ver = 0, fw_h2c_ver = 0; + u32 iram_pkt_size, dmem_pkt_size, eram_pkt_size = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_restore_info restore_info[DLFW_RESTORE_REG_NUM_88XX]; + u32 temp; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DOWNLOAD_FIRMWARE); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s start!!\n", __func__); + + if (halmac_fw_size > HALMAC_FW_SIZE_MAX_88XX || + halmac_fw_size < HALMAC_FWHDR_SIZE_88XX) { + pr_err("FW size error!\n"); + return HALMAC_RET_FW_SIZE_ERR; + } + + fw_h2c_ver = le32_to_cpu( + *((__le32 *) + (hamacl_fw + HALMAC_FWHDR_OFFSET_H2C_FORMAT_VER_88XX))); + halmac_h2c_ver = H2C_FORMAT_VERSION; + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac h2c/c2h format = %x, fw h2c/c2h format = %x!!\n", + halmac_h2c_ver, fw_h2c_ver); + if (fw_h2c_ver != halmac_h2c_ver) + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_WARNING, + "[WARN]H2C/C2H version between HALMAC and FW is compatible!!\n"); + + halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE; + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN + 1); + value8 = (u8)(value8 & ~(BIT(2))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1, + value8); /* Disable CPU reset */ + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RSV_CTRL + 1); + value8 = (u8)(value8 & ~(BIT(0))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RSV_CTRL + 1, value8); + + restore_info[restore_index].length = 1; + restore_info[restore_index].mac_register = REG_TXDMA_PQ_MAP + 1; + restore_info[restore_index].value = + HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP + 1); + restore_index++; + value8 = HALMAC_DMA_MAPPING_HIGH << 6; + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP + 1, + value8); /* set HIQ to hi priority */ + + /* DLFW only use HIQ, map HIQ to hi priority */ + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI] = + HALMAC_DMA_MAPPING_HIGH; + restore_info[restore_index].length = 1; + restore_info[restore_index].mac_register = REG_CR; + restore_info[restore_index].value = + HALMAC_REG_READ_8(halmac_adapter, REG_CR); + restore_index++; + restore_info[restore_index].length = 4; + restore_info[restore_index].mac_register = REG_H2CQ_CSR; + restore_info[restore_index].value = BIT(31); + restore_index++; + value8 = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN; + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR, value8); + HALMAC_REG_WRITE_32(halmac_adapter, REG_H2CQ_CSR, BIT(31)); + + /* Config hi priority queue and public priority queue page number + * (only for DLFW) + */ + restore_info[restore_index].length = 2; + restore_info[restore_index].mac_register = REG_FIFOPAGE_INFO_1; + restore_info[restore_index].value = + HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_INFO_1); + restore_index++; + restore_info[restore_index].length = 4; + restore_info[restore_index].mac_register = REG_RQPN_CTRL_2; + restore_info[restore_index].value = + HALMAC_REG_READ_32(halmac_adapter, REG_RQPN_CTRL_2) | BIT(31); + restore_index++; + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_INFO_1, 0x200); + HALMAC_REG_WRITE_32(halmac_adapter, REG_RQPN_CTRL_2, + restore_info[restore_index - 1].value); + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + HALMAC_REG_READ_32(halmac_adapter, REG_SDIO_FREE_TXPG); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_TX_CTRL, + 0x00000000); + } + + halmac_adapter->fw_version.version = le16_to_cpu( + *((__le16 *)(hamacl_fw + HALMAC_FWHDR_OFFSET_VERSION_88XX))); + halmac_adapter->fw_version.sub_version = + *(hamacl_fw + HALMAC_FWHDR_OFFSET_SUBVERSION_88XX); + halmac_adapter->fw_version.sub_index = + *(hamacl_fw + HALMAC_FWHDR_OFFSET_SUBINDEX_88XX); + halmac_adapter->fw_version.h2c_version = (u16)fw_h2c_ver; + + dmem_pkt_size = le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_DMEM_SIZE_88XX))); + iram_pkt_size = le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_IRAM_SIZE_88XX))); + if (((*(hamacl_fw + HALMAC_FWHDR_OFFSET_MEM_USAGE_88XX)) & BIT(4)) != 0) + eram_pkt_size = + le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_ERAM_SIZE_88XX))); + + dmem_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + iram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + if (eram_pkt_size != 0) + eram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + + if (halmac_fw_size != (HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size + + iram_pkt_size + eram_pkt_size)) { + pr_err("FW size mismatch the real fw size!\n"); + goto DLFW_FAIL; + } + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR + 1); + restore_info[restore_index].length = 1; + restore_info[restore_index].mac_register = REG_CR + 1; + restore_info[restore_index].value = value8; + restore_index++; + value8 = (u8)(value8 | BIT(0)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1, + value8); /* Enable SW TX beacon */ + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL); + restore_info[restore_index].length = 1; + restore_info[restore_index].mac_register = REG_BCN_CTRL; + restore_info[restore_index].value = value8; + restore_index++; + value8 = (u8)((value8 & (~BIT(3))) | BIT(4)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL, + value8); /* Disable beacon related functions */ + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2); + restore_info[restore_index].length = 1; + restore_info[restore_index].mac_register = REG_FWHW_TXQ_CTRL + 2; + restore_info[restore_index].value = value8; + restore_index++; + value8 = (u8)(value8 & ~(BIT(6))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2, + value8); /* Disable ptcl tx bcnq */ + + restore_info[restore_index].length = 2; + restore_info[restore_index].mac_register = REG_FIFOPAGE_CTRL_2; + restore_info[restore_index].value = + HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_CTRL_2) | + BIT(15); + restore_index++; + value16 = 0x8000; + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + value16); /* Set beacon header to 0 */ + + value16 = (u16)(HALMAC_REG_READ_16(halmac_adapter, REG_MCUFW_CTRL) & + 0x3800); + value16 |= BIT(0); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MCUFW_CTRL, + value16); /* MCU/FW setting */ + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CPU_DMEM_CON + 2); + value8 &= ~(BIT(0)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_CPU_DMEM_CON + 2, value8); + value8 |= BIT(0); + HALMAC_REG_WRITE_8(halmac_adapter, REG_CPU_DMEM_CON + 2, value8); + + /* Download to DMEM */ + file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX; + temp = le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_DMEM_ADDR_88XX))) & + ~(BIT(31)); + if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, temp, + dmem_pkt_size) != HALMAC_RET_SUCCESS) + goto DLFW_END; + + /* Download to IMEM */ + file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size; + temp = le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_IRAM_ADDR_88XX))) & + ~(BIT(31)); + if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, temp, + iram_pkt_size) != HALMAC_RET_SUCCESS) + goto DLFW_END; + + /* Download to EMEM */ + if (eram_pkt_size != 0) { + file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size + + iram_pkt_size; + dest = le32_to_cpu((*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_EMEM_ADDR_88XX)))) & + ~(BIT(31)); + if (halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, dest, + eram_pkt_size) != + HALMAC_RET_SUCCESS) + goto DLFW_END; + } + + halmac_init_offload_feature_state_machine_88xx(halmac_adapter); +DLFW_END: + + halmac_restore_mac_register_88xx(halmac_adapter, restore_info, + DLFW_RESTORE_REG_NUM_88XX); + + if (halmac_dlfw_end_flow_88xx(halmac_adapter) != HALMAC_RET_SUCCESS) + goto DLFW_FAIL; + + halmac_adapter->halmac_state.dlfw_state = HALMAC_DLFW_DONE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; + +DLFW_FAIL: + + /* Disable FWDL_EN */ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) & + ~(BIT(0)))); + + return HALMAC_RET_DLFW_FAIL; +} + +/** + * halmac_free_download_firmware_88xx() - download specific memory firmware + * @halmac_adapter + * @dlfw_mem : memory selection + * @hamacl_fw : firmware bin + * @halmac_fw_size : firmware size + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + */ +enum halmac_ret_status +halmac_free_download_firmware_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_dlfw_mem dlfw_mem, u8 *hamacl_fw, + u32 halmac_fw_size) +{ + u8 tx_pause_backup; + u8 *file_ptr; + u32 dest; + u16 bcn_head_backup; + u32 iram_pkt_size, dmem_pkt_size, eram_pkt_size = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_DLFW_FAIL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + if (halmac_fw_size > HALMAC_FW_SIZE_MAX_88XX || + halmac_fw_size < HALMAC_FWHDR_SIZE_88XX) { + pr_err("[ERR]FW size error!\n"); + return HALMAC_RET_FW_SIZE_ERR; + } + + dmem_pkt_size = + le32_to_cpu(*(__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_DMEM_SIZE_88XX)); + iram_pkt_size = + le32_to_cpu(*(__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_IRAM_SIZE_88XX)); + if (((*(hamacl_fw + HALMAC_FWHDR_OFFSET_MEM_USAGE_88XX)) & BIT(4)) != 0) + eram_pkt_size = + le32_to_cpu(*(__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_ERAM_SIZE_88XX)); + + dmem_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + iram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + if (eram_pkt_size != 0) + eram_pkt_size += HALMAC_FW_CHKSUM_DUMMY_SIZE_88XX; + + if (halmac_fw_size != (HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size + + iram_pkt_size + eram_pkt_size)) { + pr_err("[ERR]FW size mismatch the real fw size!\n"); + return HALMAC_RET_DLFW_FAIL; + } + + tx_pause_backup = HALMAC_REG_READ_8(halmac_adapter, REG_TXPAUSE); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXPAUSE, + tx_pause_backup | BIT(7)); + + bcn_head_backup = + HALMAC_REG_READ_16(halmac_adapter, REG_FIFOPAGE_CTRL_2) | + BIT(15); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, 0x8000); + + if (eram_pkt_size != 0) { + file_ptr = hamacl_fw + HALMAC_FWHDR_SIZE_88XX + dmem_pkt_size + + iram_pkt_size; + dest = le32_to_cpu(*((__le32 *)(hamacl_fw + + HALMAC_FWHDR_OFFSET_EMEM_ADDR_88XX))) & + ~(BIT(31)); + status = halmac_dlfw_to_mem_88xx(halmac_adapter, file_ptr, dest, + eram_pkt_size); + if (status != HALMAC_RET_SUCCESS) + goto DL_FREE_FW_END; + } + + status = halmac_free_dl_fw_end_flow_88xx(halmac_adapter); + +DL_FREE_FW_END: + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXPAUSE, tx_pause_backup); + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + bcn_head_backup); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return status; +} + +/** + * halmac_get_fw_version_88xx() - get FW version + * @halmac_adapter : the adapter of halmac + * @fw_version : fw version info + * Author : Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_fw_version_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fw_version *fw_version) +{ + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_adapter->halmac_state.dlfw_state == 0) + return HALMAC_RET_DLFW_FAIL; + + fw_version->version = halmac_adapter->fw_version.version; + fw_version->sub_version = halmac_adapter->fw_version.sub_version; + fw_version->sub_index = halmac_adapter->fw_version.sub_index; + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_mac_addr_88xx() - config mac address + * @halmac_adapter : the adapter of halmac + * @halmac_port :0 for port0, 1 for port1, 2 for port2, 3 for port3, 4 for port4 + * @hal_address : mac address + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_mac_addr_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port, + union halmac_wlan_addr *hal_address) +{ + u16 mac_address_H; + u32 mac_address_L; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + if (halmac_port >= HALMAC_PORTIDMAX) { + pr_err("[ERR]port index > 5\n"); + return HALMAC_RET_PORT_NOT_SUPPORT; + } + + mac_address_L = le32_to_cpu(hal_address->address_l_h.le_address_low); + mac_address_H = le16_to_cpu(hal_address->address_l_h.le_address_high); + + halmac_adapter->hal_mac_addr[halmac_port].address_l_h.address_low = + mac_address_L; + halmac_adapter->hal_mac_addr[halmac_port].address_l_h.address_high = + mac_address_H; + + switch (halmac_port) { + case HALMAC_PORTID0: + HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID, mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID + 4, + mac_address_H); + break; + + case HALMAC_PORTID1: + HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID1, mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID1 + 4, + mac_address_H); + break; + + case HALMAC_PORTID2: + HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID2, mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID2 + 4, + mac_address_H); + break; + + case HALMAC_PORTID3: + HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID3, mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID3 + 4, + mac_address_H); + break; + + case HALMAC_PORTID4: + HALMAC_REG_WRITE_32(halmac_adapter, REG_MACID4, mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MACID4 + 4, + mac_address_H); + break; + + default: + + break; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_bssid_88xx() - config BSSID + * @halmac_adapter : the adapter of halmac + * @halmac_port :0 for port0, 1 for port1, 2 for port2, 3 for port3, 4 for port4 + * @hal_address : bssid + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_bssid_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port, + union halmac_wlan_addr *hal_address) +{ + u16 bssid_address_H; + u32 bssid_address_L; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + if (halmac_port >= HALMAC_PORTIDMAX) { + pr_err("[ERR]port index > 5\n"); + return HALMAC_RET_PORT_NOT_SUPPORT; + } + + bssid_address_L = le32_to_cpu(hal_address->address_l_h.le_address_low); + bssid_address_H = le16_to_cpu(hal_address->address_l_h.le_address_high); + + halmac_adapter->hal_bss_addr[halmac_port].address_l_h.address_low = + bssid_address_L; + halmac_adapter->hal_bss_addr[halmac_port].address_l_h.address_high = + bssid_address_H; + + switch (halmac_port) { + case HALMAC_PORTID0: + HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID, bssid_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID + 4, + bssid_address_H); + break; + + case HALMAC_PORTID1: + HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID1, + bssid_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID1 + 4, + bssid_address_H); + break; + + case HALMAC_PORTID2: + HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID2, + bssid_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID2 + 4, + bssid_address_H); + break; + + case HALMAC_PORTID3: + HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID3, + bssid_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID3 + 4, + bssid_address_H); + break; + + case HALMAC_PORTID4: + HALMAC_REG_WRITE_32(halmac_adapter, REG_BSSID4, + bssid_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_BSSID4 + 4, + bssid_address_H); + break; + + default: + + break; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_multicast_addr_88xx() - config multicast address + * @halmac_adapter : the adapter of halmac + * @hal_address : multicast address + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_multicast_addr_88xx(struct halmac_adapter *halmac_adapter, + union halmac_wlan_addr *hal_address) +{ + u16 address_H; + u32 address_L; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_MULTICAST_ADDR); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + address_L = le32_to_cpu(hal_address->address_l_h.le_address_low); + address_H = le16_to_cpu(hal_address->address_l_h.le_address_high); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_MAR, address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MAR + 4, address_H); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_pre_init_system_cfg_88xx() - pre-init system config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_pre_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + u32 value32, counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + bool enable_bb; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_PRE_INIT_SYSTEM_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_pre_init_system_cfg ==========>\n"); + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SDIO_HSUS_CTRL, + HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HSUS_CTRL) & + ~(BIT(0))); + counter = 10000; + while (!(HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HSUS_CTRL) & + 0x02)) { + counter--; + if (counter == 0) + return HALMAC_RET_SDIO_LEAVE_SUSPEND_FAIL; + } + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + if (HALMAC_REG_READ_8(halmac_adapter, REG_SYS_CFG2 + 3) == + 0x20) /* usb3.0 */ + HALMAC_REG_WRITE_8( + halmac_adapter, 0xFE5B, + HALMAC_REG_READ_8(halmac_adapter, 0xFE5B) | + BIT(4)); + } + + /* Config PIN Mux */ + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_PAD_CTRL1); + value32 = value32 & (~(BIT(28) | BIT(29))); + value32 = value32 | BIT(28) | BIT(29); + HALMAC_REG_WRITE_32(halmac_adapter, REG_PAD_CTRL1, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_LED_CFG); + value32 = value32 & (~(BIT(25) | BIT(26))); + HALMAC_REG_WRITE_32(halmac_adapter, REG_LED_CFG, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_GPIO_MUXCFG); + value32 = value32 & (~(BIT(2))); + value32 = value32 | BIT(2); + HALMAC_REG_WRITE_32(halmac_adapter, REG_GPIO_MUXCFG, value32); + + enable_bb = false; + halmac_set_hw_value_88xx(halmac_adapter, HALMAC_HW_EN_BB_RF, + &enable_bb); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_pre_init_system_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_system_cfg_88xx() - init system config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_SYSTEM_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_init_system_cfg ==========>\n"); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1, + HALMAC_FUNCTION_ENABLE_88XX); + HALMAC_REG_WRITE_32( + halmac_adapter, REG_SYS_SDIO_CTRL, + (u32)(HALMAC_REG_READ_32(halmac_adapter, REG_SYS_SDIO_CTRL) | + BIT_LTE_MUX_CTRL_PATH)); + HALMAC_REG_WRITE_32( + halmac_adapter, REG_CPU_DMEM_CON, + (u32)(HALMAC_REG_READ_32(halmac_adapter, REG_CPU_DMEM_CON) | + BIT_WL_PLATFORM_RST)); + + /* halmac_api->halmac_init_h2c(halmac_adapter); */ + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_init_system_cfg <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_edca_cfg_88xx() - init EDCA config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_edca_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 value8; + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_EDCA_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + /* Clear TX pause */ + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXPAUSE, 0x0000); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_SLOT, HALMAC_SLOT_TIME_88XX); + HALMAC_REG_WRITE_8(halmac_adapter, REG_PIFS, HALMAC_PIFS_TIME_88XX); + value32 = HALMAC_SIFS_CCK_CTX_88XX | + (HALMAC_SIFS_OFDM_CTX_88XX << BIT_SHIFT_SIFS_OFDM_CTX) | + (HALMAC_SIFS_CCK_TRX_88XX << BIT_SHIFT_SIFS_CCK_TRX) | + (HALMAC_SIFS_OFDM_TRX_88XX << BIT_SHIFT_SIFS_OFDM_TRX); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SIFS, value32); + + HALMAC_REG_WRITE_32( + halmac_adapter, REG_EDCA_VO_PARAM, + HALMAC_REG_READ_32(halmac_adapter, REG_EDCA_VO_PARAM) & 0xFFFF); + HALMAC_REG_WRITE_16(halmac_adapter, REG_EDCA_VO_PARAM + 2, + HALMAC_VO_TXOP_LIMIT_88XX); + HALMAC_REG_WRITE_16(halmac_adapter, REG_EDCA_VI_PARAM + 2, + HALMAC_VI_TXOP_LIMIT_88XX); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_RD_NAV_NXT, + HALMAC_RDG_NAV_88XX | (HALMAC_TXOP_NAV_88XX << 16)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_RXTSF_OFFSET_CCK, + HALMAC_CCK_RX_TSF_88XX | + (HALMAC_OFDM_RX_TSF_88XX) << 8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RD_CTRL + 1); + value8 |= + (BIT_VOQ_RD_INIT_EN | BIT_VIQ_RD_INIT_EN | BIT_BEQ_RD_INIT_EN); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RD_CTRL + 1, value8); + + /* Set beacon cotnrol - enable TSF and other related functions */ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_BCN_CTRL, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL) | + BIT_EN_BCN_FUNCTION)); + + /* Set send beacon related registers */ + HALMAC_REG_WRITE_32(halmac_adapter, REG_TBTT_PROHIBIT, + HALMAC_TBTT_PROHIBIT_88XX | + (HALMAC_TBTT_HOLD_TIME_88XX + << BIT_SHIFT_TBTT_HOLD_TIME_AP)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_DRVERLYINT, + HALMAC_DRIVER_EARLY_INT_88XX); + HALMAC_REG_WRITE_8(halmac_adapter, REG_BCNDMATIM, + HALMAC_BEACON_DMA_TIM_88XX); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_wmac_cfg_88xx() - init wmac config + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_wmac_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_WMAC_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_RXFLTMAP0, + HALMAC_RX_FILTER0_88XX); + HALMAC_REG_WRITE_16(halmac_adapter, REG_RXFLTMAP, + HALMAC_RX_FILTER_88XX); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_RCR, HALMAC_RCR_CONFIG_88XX); + + HALMAC_REG_WRITE_8( + halmac_adapter, REG_TCR + 1, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_TCR + 1) | 0x30)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TCR + 2, 0x30); + HALMAC_REG_WRITE_8(halmac_adapter, REG_TCR + 1, 0x00); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 8, + 0x30810041); + HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 4, + 0x50802080); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_init_mac_cfg_88xx() - config page1~page7 register + * @halmac_adapter : the adapter of halmac + * @mode : trx mode + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_mac_cfg_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode mode) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_MAC_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>mode = %d\n", __func__, + mode); + + status = halmac_api->halmac_init_trx_cfg(halmac_adapter, mode); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_init_trx_cfg error = %x\n", status); + return status; + } + status = halmac_api->halmac_init_protocol_cfg(halmac_adapter); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_init_protocol_cfg_88xx error = %x\n", status); + return status; + } + + status = halmac_init_edca_cfg_88xx(halmac_adapter); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_init_edca_cfg_88xx error = %x\n", status); + return status; + } + + status = halmac_init_wmac_cfg_88xx(halmac_adapter); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_init_wmac_cfg_88xx error = %x\n", status); + return status; + } + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return status; +} + +/** + * halmac_cfg_operation_mode_88xx() - config operation mode + * @halmac_adapter : the adapter of halmac + * @wireless_mode : 802.11 standard(b/g/n/ac) + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_operation_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_wireless_mode wireless_mode) +{ + void *driver_adapter = NULL; + enum halmac_wireless_mode wireless_mode_local = + HALMAC_WIRELESS_MODE_UNDEFINE; + + wireless_mode_local = wireless_mode; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_OPERATION_MODE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>wireless_mode = %d\n", __func__, + wireless_mode); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_ch_bw_88xx() - config channel & bandwidth + * @halmac_adapter : the adapter of halmac + * @channel : WLAN channel, support 2.4G & 5G + * @pri_ch_idx : primary channel index, idx1, idx2, idx3, idx4 + * @bw : band width, 20, 40, 80, 160, 5 ,10 + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_ch_bw_88xx(struct halmac_adapter *halmac_adapter, u8 channel, + enum halmac_pri_ch_idx pri_ch_idx, enum halmac_bw bw) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>ch = %d, idx=%d, bw=%d\n", __func__, + channel, pri_ch_idx, bw); + + halmac_cfg_pri_ch_idx_88xx(halmac_adapter, pri_ch_idx); + + halmac_cfg_bw_88xx(halmac_adapter, bw); + + halmac_cfg_ch_88xx(halmac_adapter, channel); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_cfg_ch_88xx(struct halmac_adapter *halmac_adapter, + u8 channel) +{ + u8 value8; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>ch = %d\n", __func__, channel); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CCK_CHECK); + value8 = value8 & (~(BIT(7))); + + if (channel > 35) + value8 = value8 | BIT(7); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_CCK_CHECK, value8); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_cfg_pri_ch_idx_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_pri_ch_idx pri_ch_idx) +{ + u8 txsc_40 = 0, txsc_20 = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CH_BW); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========> idx=%d\n", __func__, + pri_ch_idx); + + txsc_20 = pri_ch_idx; + if (txsc_20 == HALMAC_CH_IDX_1 || txsc_20 == HALMAC_CH_IDX_3) + txsc_40 = 9; + else + txsc_40 = 10; + + HALMAC_REG_WRITE_8(halmac_adapter, REG_DATA_SC, + BIT_TXSC_20M(txsc_20) | BIT_TXSC_40M(txsc_40)); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_bw_88xx() - config bandwidth + * @halmac_adapter : the adapter of halmac + * @bw : band width, 20, 40, 80, 160, 5 ,10 + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_cfg_bw_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_bw bw) +{ + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_BW); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>bw=%d\n", __func__, bw); + + /* RF mode */ + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_WMAC_TRXPTCL_CTL); + value32 = value32 & (~(BIT(7) | BIT(8))); + + switch (bw) { + case HALMAC_BW_80: + value32 = value32 | BIT(7); + break; + case HALMAC_BW_40: + value32 = value32 | BIT(8); + break; + case HALMAC_BW_20: + case HALMAC_BW_10: + case HALMAC_BW_5: + break; + default: + pr_err("%s switch case not support\n", __func__); + break; + } + HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_TRXPTCL_CTL, value32); + + /* MAC CLK */ + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_AFE_CTRL1); + value32 = (value32 & (~(BIT(20) | BIT(21)))) | + (HALMAC_MAC_CLOCK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL); + HALMAC_REG_WRITE_32(halmac_adapter, REG_AFE_CTRL1, value32); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_USTIME_TSF, + HALMAC_MAC_CLOCK_88XX); + HALMAC_REG_WRITE_8(halmac_adapter, REG_USTIME_EDCA, + HALMAC_MAC_CLOCK_88XX); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_dump_efuse_map_88xx() - dump "physical" efuse map + * @halmac_adapter : the adapter of halmac + * @cfg : dump efuse method + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_dump_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_EFUSE_MAP); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>cfg=%d\n", __func__, cfg); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF) + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_WARNING, + "[WARN]Dump efuse in suspend mode\n"); + + *process_status = HALMAC_CMD_PROCESS_IDLE; + halmac_adapter->event_trigger.physical_efuse_map = 1; + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + HALMAC_EFUSE_BANK_WIFI); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_dump_efuse_88xx(halmac_adapter, cfg); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_read_efuse error = %x\n", status); + return status; + } + + if (halmac_adapter->hal_efuse_map_valid) { + *process_status = HALMAC_CMD_PROCESS_DONE; + + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE, + *process_status, halmac_adapter->hal_efuse_map, + halmac_adapter->hw_config_info.efuse_size); + halmac_adapter->event_trigger.physical_efuse_map = 0; + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_dump_efuse_map_bt_88xx() - dump "BT physical" efuse map + * @halmac_adapter : the adapter of halmac + * @halmac_efuse_bank : bt efuse bank + * @bt_efuse_map_size : bt efuse map size. get from halmac_get_efuse_size API + * @bt_efuse_map : bt efuse map + * Author : Soar / Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_dump_efuse_map_bt_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_bank halmac_efuse_bank, + u32 bt_efuse_map_size, u8 *bt_efuse_map) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_EFUSE_MAP_BT); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_adapter->hw_config_info.bt_efuse_size != bt_efuse_map_size) + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + + if ((halmac_efuse_bank >= HALMAC_EFUSE_BANK_MAX) || + halmac_efuse_bank == HALMAC_EFUSE_BANK_WIFI) { + pr_err("Undefined BT bank\n"); + return HALMAC_RET_EFUSE_BANK_INCORRECT; + } + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + halmac_efuse_bank); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_read_hw_efuse_88xx(halmac_adapter, 0, bt_efuse_map_size, + bt_efuse_map); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_read_hw_efuse_88xx error = %x\n", status); + return status; + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_write_efuse_bt_88xx() - write "BT physical" efuse offset + * @halmac_adapter : the adapter of halmac + * @halmac_offset : offset + * @halmac_value : Write value + * @bt_efuse_map : bt efuse map + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_write_efuse_bt_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_value, + enum halmac_efuse_bank halmac_efuse_bank) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_WRITE_EFUSE_BT); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "offset : %X value : %X Bank : %X\n", halmac_offset, + halmac_value, halmac_efuse_bank); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait/Rcvd event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (halmac_offset >= halmac_adapter->hw_config_info.efuse_size) { + pr_err("Offset is too large\n"); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if (halmac_efuse_bank > HALMAC_EFUSE_BANK_MAX || + halmac_efuse_bank == HALMAC_EFUSE_BANK_WIFI) { + pr_err("Undefined BT bank\n"); + return HALMAC_RET_EFUSE_BANK_INCORRECT; + } + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + halmac_efuse_bank); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_func_write_efuse_88xx(halmac_adapter, halmac_offset, + halmac_value); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_write_efuse error = %x\n", status); + return status; + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_efuse_available_size_88xx() - get efuse available size + * @halmac_adapter : the adapter of halmac + * @halmac_size : physical efuse available size + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_efuse_available_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size) +{ + enum halmac_ret_status status; + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + status = halmac_dump_logical_efuse_map_88xx(halmac_adapter, + HALMAC_EFUSE_R_DRV); + + if (status != HALMAC_RET_SUCCESS) + return status; + + *halmac_size = halmac_adapter->hw_config_info.efuse_size - + HALMAC_PROTECTED_EFUSE_SIZE_88XX - + halmac_adapter->efuse_end; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_efuse_size_88xx() - get "physical" efuse size + * @halmac_adapter : the adapter of halmac + * @halmac_size : physical efuse size + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_efuse_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_EFUSE_SIZE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + *halmac_size = halmac_adapter->hw_config_info.efuse_size; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_logical_efuse_size_88xx() - get "logical" efuse size + * @halmac_adapter : the adapter of halmac + * @halmac_size : logical efuse size + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_logical_efuse_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_GET_LOGICAL_EFUSE_SIZE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + *halmac_size = halmac_adapter->hw_config_info.eeprom_size; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_dump_logical_efuse_map_88xx() - dump "logical" efuse map + * @halmac_adapter : the adapter of halmac + * @cfg : dump efuse method + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_dump_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg) +{ + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_DUMP_LOGICAL_EFUSE_MAP); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>cfg = %d\n", __func__, cfg); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait/Rcvd event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF) + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_WARNING, + "[WARN]Dump logical efuse in suspend mode\n"); + + *process_status = HALMAC_CMD_PROCESS_IDLE; + halmac_adapter->event_trigger.logical_efuse_map = 1; + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + HALMAC_EFUSE_BANK_WIFI); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_dump_efuse_88xx(halmac_adapter, cfg); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_eeprom_parser_88xx error = %x\n", status); + return status; + } + + if (halmac_adapter->hal_efuse_map_valid) { + *process_status = HALMAC_CMD_PROCESS_DONE; + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + if (halmac_eeprom_parser_88xx(halmac_adapter, + halmac_adapter->hal_efuse_map, + eeprom_map) != HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_DUMP_LOGICAL_EFUSE, + *process_status, eeprom_map, eeprom_size); + halmac_adapter->event_trigger.logical_efuse_map = 0; + + kfree(eeprom_map); + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_read_logical_efuse_88xx() - read logical efuse map 1 byte + * @halmac_adapter : the adapter of halmac + * @halmac_offset : offset + * @value : 1 byte efuse value + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_read_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 *value) +{ + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_READ_LOGICAL_EFUSE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_offset >= eeprom_size) { + pr_err("Offset is too large\n"); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait/Rcvd event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + HALMAC_EFUSE_BANK_WIFI); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_read_logical_efuse_map error = %x\n", status); + kfree(eeprom_map); + return status; + } + + *value = *(eeprom_map + halmac_offset); + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return HALMAC_RET_ERROR_STATE; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + kfree(eeprom_map); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_write_logical_efuse_88xx() - write "logical" efuse offset + * @halmac_adapter : the adapter of halmac + * @halmac_offset : offset + * @halmac_value : value + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_value) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_WRITE_LOGICAL_EFUSE); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_offset >= halmac_adapter->hw_config_info.eeprom_size) { + pr_err("Offset is too large\n"); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait/Rcvd event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + HALMAC_EFUSE_BANK_WIFI); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_func_write_logical_efuse_88xx( + halmac_adapter, halmac_offset, halmac_value); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_write_logical_efuse error = %x\n", status); + return status; + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_pg_efuse_by_map_88xx() - pg logical efuse by map + * @halmac_adapter : the adapter of halmac + * @pg_efuse_info : efuse map information + * @cfg : dump efuse method + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + enum halmac_efuse_read_cfg cfg) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PG_EFUSE_BY_MAP); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s ==========>\n", __func__); + + if (pg_efuse_info->efuse_map_size != + halmac_adapter->hw_config_info.eeprom_size) { + pr_err("efuse_map_size is incorrect, should be %d bytes\n", + halmac_adapter->hw_config_info.eeprom_size); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if ((pg_efuse_info->efuse_map_size & 0xF) > 0) { + pr_err("efuse_map_size should be multiple of 16\n"); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if (pg_efuse_info->efuse_mask_size != + pg_efuse_info->efuse_map_size >> 4) { + pr_err("efuse_mask_size is incorrect, should be %d bytes\n", + pg_efuse_info->efuse_map_size >> 4); + return HALMAC_RET_EFUSE_SIZE_INCORRECT; + } + + if (!pg_efuse_info->efuse_map) { + pr_err("efuse_map is NULL\n"); + return HALMAC_RET_NULL_POINTER; + } + + if (!pg_efuse_info->efuse_mask) { + pr_err("efuse_mask is NULL\n"); + return HALMAC_RET_NULL_POINTER; + } + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait/Rcvd event(dump efuse)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_efuse_curr_state_88xx(halmac_adapter) != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(dump efuse)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + status = halmac_func_switch_efuse_bank_88xx(halmac_adapter, + HALMAC_EFUSE_BANK_WIFI); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_func_switch_efuse_bank error = %x\n", status); + return status; + } + + status = halmac_func_pg_efuse_by_map_88xx(halmac_adapter, pg_efuse_info, + cfg); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_pg_efuse_by_map error = %x\n", status); + return status; + } + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_EFUSE, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_c2h_info_88xx() - process halmac C2H packet + * @halmac_adapter : the adapter of halmac + * @halmac_buf : RX Packet pointer + * @halmac_size : RX Packet size + * Author : KaiYuan Chang/Ivan Lin + * + * Used to process c2h packet info from RX path. After receiving the packet, + * user need to call this api and pass the packet pointer. + * + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_c2h_info_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf, + u32 halmac_size) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_C2H_INFO); + + driver_adapter = halmac_adapter->driver_adapter; + + /* Check if it is C2H packet */ + if (GET_RX_DESC_C2H(halmac_buf)) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "C2H packet, start parsing!\n"); + + status = halmac_parse_c2h_packet_88xx(halmac_adapter, + halmac_buf, halmac_size); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_parse_c2h_packet_88xx error = %x\n", + status); + return status; + } + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_cfg_fwlps_option_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwlps_option *lps_option) +{ + void *driver_adapter = NULL; + struct halmac_fwlps_option *hal_fwlps_option; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_FWLPS_OPTION); + + driver_adapter = halmac_adapter->driver_adapter; + hal_fwlps_option = &halmac_adapter->fwlps_option; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + hal_fwlps_option->mode = lps_option->mode; + hal_fwlps_option->clk_request = lps_option->clk_request; + hal_fwlps_option->rlbm = lps_option->rlbm; + hal_fwlps_option->smart_ps = lps_option->smart_ps; + hal_fwlps_option->awake_interval = lps_option->awake_interval; + hal_fwlps_option->all_queue_uapsd = lps_option->all_queue_uapsd; + hal_fwlps_option->pwr_state = lps_option->pwr_state; + hal_fwlps_option->low_pwr_rx_beacon = lps_option->low_pwr_rx_beacon; + hal_fwlps_option->ant_auto_switch = lps_option->ant_auto_switch; + hal_fwlps_option->ps_allow_bt_high_priority = + lps_option->ps_allow_bt_high_priority; + hal_fwlps_option->protect_bcn = lps_option->protect_bcn; + hal_fwlps_option->silence_period = lps_option->silence_period; + hal_fwlps_option->fast_bt_connect = lps_option->fast_bt_connect; + hal_fwlps_option->two_antenna_en = lps_option->two_antenna_en; + hal_fwlps_option->adopt_user_setting = lps_option->adopt_user_setting; + hal_fwlps_option->drv_bcn_early_shift = lps_option->drv_bcn_early_shift; + hal_fwlps_option->enter_32K = lps_option->enter_32K; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_cfg_fwips_option_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwips_option *ips_option) +{ + void *driver_adapter = NULL; + struct halmac_fwips_option *ips_option_local; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_FWIPS_OPTION); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + ips_option_local = ips_option; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_enter_wowlan_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_wowlan_option *wowlan_option) +{ + void *driver_adapter = NULL; + struct halmac_wowlan_option *wowlan_option_local; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ENTER_WOWLAN); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + wowlan_option_local = wowlan_option; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_leave_wowlan_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_LEAVE_WOWLAN); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_enter_ps_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_ps_state ps_state) +{ + u8 rpwm; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ENTER_PS); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + if (ps_state == halmac_adapter->halmac_state.ps_state) { + pr_err("power state is already in PS State!!\n"); + return HALMAC_RET_SUCCESS; + } + + if (ps_state == HALMAC_PS_STATE_LPS) { + status = halmac_send_h2c_set_pwr_mode_88xx( + halmac_adapter, &halmac_adapter->fwlps_option); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_set_pwr_mode_88xx error = %x!!\n", + status); + return status; + } + } else if (ps_state == HALMAC_PS_STATE_IPS) { + } + + halmac_adapter->halmac_state.ps_state = ps_state; + + /* Enter 32K */ + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + if (halmac_adapter->fwlps_option.enter_32K) { + rpwm = (u8)(((halmac_adapter->rpwm_record ^ (BIT(7))) | + (BIT(0))) & + 0x81); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SDIO_HRPWM1, + rpwm); + halmac_adapter->low_clk = true; + } + } else if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_USB) { + if (halmac_adapter->fwlps_option.enter_32K) { + rpwm = (u8)(((halmac_adapter->rpwm_record ^ (BIT(7))) | + (BIT(0))) & + 0x81); + HALMAC_REG_WRITE_8(halmac_adapter, 0xFE58, rpwm); + halmac_adapter->low_clk = true; + } + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_leave_ps_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 rpwm, cpwm; + u32 counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_fwlps_option fw_lps_option; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_LEAVE_PS); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_adapter->halmac_state.ps_state == HALMAC_PS_STATE_ACT) { + pr_err("power state is already in active!!\n"); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->low_clk) { + cpwm = HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HRPWM1); + rpwm = (u8)( + ((halmac_adapter->rpwm_record ^ (BIT(7))) | (BIT(6))) & + 0xC0); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SDIO_HRPWM1, rpwm); + + cpwm = (u8)((cpwm ^ BIT(7)) & BIT(7)); + counter = 100; + while (cpwm != + (HALMAC_REG_READ_8(halmac_adapter, REG_SDIO_HRPWM1) & + BIT(7))) { + usleep_range(50, 60); + counter--; + if (counter == 0) + return HALMAC_RET_CHANGE_PS_FAIL; + } + halmac_adapter->low_clk = false; + } + + memcpy(&fw_lps_option, &halmac_adapter->fwlps_option, + sizeof(struct halmac_fwlps_option)); + fw_lps_option.mode = 0; + + status = halmac_send_h2c_set_pwr_mode_88xx(halmac_adapter, + &fw_lps_option); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_set_pwr_mode_88xx error!!=%x\n", + status); + return status; + } + + halmac_adapter->halmac_state.ps_state = HALMAC_PS_STATE_ACT; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * (debug API)halmac_h2c_lb_88xx() - send h2c loopback packet + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_h2c_lb_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_H2C_LB); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_debug_88xx() - dump information for debugging + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_debug_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 temp8 = 0; + u32 i = 0, temp32 = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEBUG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + /* Dump CCCR, it needs new platform api */ + + /*Dump SDIO Local Register, use CMD52*/ + for (i = 0x10250000; i < 0x102500ff; i++) { + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: sdio[%x]=%x\n", i, temp8); + } + + /*Dump MAC Register*/ + for (i = 0x0000; i < 0x17ff; i++) { + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "halmac_debug: mac[%x]=%x\n", + i, temp8); + } + + /*Check RX Fifo status*/ + i = REG_RXFF_PTR_V1; + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp8); + i = REG_RXFF_WTR_V1; + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp8); + i = REG_RXFF_PTR_V1; + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp8); + i = REG_RXFF_WTR_V1; + temp8 = PLATFORM_SDIO_CMD52_READ(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp8); + } else { + /*Dump MAC Register*/ + for (i = 0x0000; i < 0x17fc; i += 4) { + temp32 = HALMAC_REG_READ_32(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "halmac_debug: mac[%x]=%x\n", + i, temp32); + } + + /*Check RX Fifo status*/ + i = REG_RXFF_PTR_V1; + temp32 = HALMAC_REG_READ_32(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp32); + i = REG_RXFF_WTR_V1; + temp32 = HALMAC_REG_READ_32(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp32); + i = REG_RXFF_PTR_V1; + temp32 = HALMAC_REG_READ_32(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp32); + i = REG_RXFF_WTR_V1; + temp32 = HALMAC_REG_READ_32(halmac_adapter, i); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "halmac_debug: mac[%x]=%x\n", i, temp32); + } + + /* TODO: Add check register code, including MAC CLK, CPU CLK */ + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_parameter_88xx() - config parameter by FW + * @halmac_adapter : the adapter of halmac + * @para_info : cmd id, content + * @full_fifo : parameter information + * + * If msk_en = true, the format of array is {reg_info, mask, value}. + * If msk_en =_FAUSE, the format of array is {reg_info, value} + * The format of reg_info is + * reg_info[31]=rf_reg, 0: MAC_BB reg, 1: RF reg + * reg_info[27:24]=rf_path, 0: path_A, 1: path_B + * if rf_reg=0(MAC_BB reg), rf_path is meaningless. + * ref_info[15:0]=offset + * + * Example: msk_en = false + * {0x8100000a, 0x00001122} + * =>Set RF register, path_B, offset 0xA to 0x00001122 + * {0x00000824, 0x11224433} + * =>Set MAC_BB register, offset 0x800 to 0x11224433 + * + * Note : full fifo mode only for init flow + * + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_parameter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + u8 full_fifo) +{ + void *driver_adapter = NULL; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.cfg_para_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_PARAMETER); + + driver_adapter = halmac_adapter->driver_adapter; + + if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) { + pr_err("%s Fail due to DLFW NONE!!\n", __func__); + return HALMAC_RET_DLFW_FAIL; + } + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(cfg para)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + if (halmac_query_cfg_para_curr_state_88xx(halmac_adapter) != + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE && + halmac_query_cfg_para_curr_state_88xx(halmac_adapter) != + HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Not idle state(cfg para)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + *process_status = HALMAC_CMD_PROCESS_IDLE; + + ret_status = halmac_send_h2c_phy_parameter_88xx(halmac_adapter, + para_info, full_fifo); + + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_phy_parameter_88xx Fail!! = %x\n", + ret_status); + return ret_status; + } + + return ret_status; +} + +/** + * halmac_update_packet_88xx() - send specific packet to FW + * @halmac_adapter : the adapter of halmac + * @pkt_id : packet id, to know the purpose of this packet + * @pkt : packet + * @pkt_size : packet size + * + * Note : TX_DESC is not included in the pkt + * + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_update_packet_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_packet_id pkt_id, u8 *pkt, u32 pkt_size) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.update_packet_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_UPDATE_PACKET); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(update_packet)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + status = halmac_send_h2c_update_packet_88xx(halmac_adapter, pkt_id, pkt, + pkt_size); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_update_packet_88xx packet = %x, fail = %x!!\n", + pkt_id, status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_bcn_ie_filter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_bcn_ie_info *bcn_ie_info) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_BCN_IE_FILTER); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + status = halmac_send_h2c_update_bcn_parse_info_88xx(halmac_adapter, + bcn_ie_info); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_update_bcn_parse_info_88xx fail = %x\n", + status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_update_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type, + struct halmac_phy_parameter_info *para_info) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type) +{ + void *driver_adapter = NULL; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_RUN_DATAPACK); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + ret_status = halmac_send_h2c_run_datapack_88xx(halmac_adapter, + halmac_data_type); + + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_run_datapack_88xx Fail, datatype = %x, status = %x!!\n", + halmac_data_type, ret_status); + return ret_status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_update_datapack_88xx <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_drv_info_88xx() - config driver info + * @halmac_adapter : the adapter of halmac + * @halmac_drv_info : driver information selection + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_drv_info_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_drv_info halmac_drv_info) +{ + u8 drv_info_size = 0; + u8 phy_status_en = 0; + u8 sniffer_en = 0; + u8 plcp_hdr_en = 0; + u32 value32; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_DRV_INFO); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_cfg_drv_info = %d\n", halmac_drv_info); + + switch (halmac_drv_info) { + case HALMAC_DRV_INFO_NONE: + drv_info_size = 0; + phy_status_en = 0; + sniffer_en = 0; + plcp_hdr_en = 0; + break; + case HALMAC_DRV_INFO_PHY_STATUS: + drv_info_size = 4; + phy_status_en = 1; + sniffer_en = 0; + plcp_hdr_en = 0; + break; + case HALMAC_DRV_INFO_PHY_SNIFFER: + drv_info_size = 5; /* phy status 4byte, sniffer info 1byte */ + phy_status_en = 1; + sniffer_en = 1; + plcp_hdr_en = 0; + break; + case HALMAC_DRV_INFO_PHY_PLCP: + drv_info_size = 6; /* phy status 4byte, plcp header 2byte */ + phy_status_en = 1; + sniffer_en = 0; + plcp_hdr_en = 1; + break; + default: + status = HALMAC_RET_SW_CASE_NOT_SUPPORT; + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->txff_allocation.rx_fifo_expanding_mode != + HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE) + drv_info_size = 0xF; + + HALMAC_REG_WRITE_8(halmac_adapter, REG_RX_DRVINFO_SZ, drv_info_size); + + halmac_adapter->drv_info_size = drv_info_size; + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_RCR); + value32 = (value32 & (~BIT_APP_PHYSTS)); + if (phy_status_en == 1) + value32 = value32 | BIT_APP_PHYSTS; + HALMAC_REG_WRITE_32(halmac_adapter, REG_RCR, value32); + + value32 = HALMAC_REG_READ_32(halmac_adapter, + REG_WMAC_OPTION_FUNCTION + 4); + value32 = (value32 & (~(BIT(8) | BIT(9)))); + if (sniffer_en == 1) + value32 = value32 | BIT(9); + if (plcp_hdr_en == 1) + value32 = value32 | BIT(8); + HALMAC_REG_WRITE_32(halmac_adapter, REG_WMAC_OPTION_FUNCTION + 4, + value32); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_bt_coex_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf, + u32 bt_size, u8 ack) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_BT_COEX); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + ret_status = halmac_send_bt_coex_cmd_88xx(halmac_adapter, bt_buf, + bt_size, ack); + + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_bt_coex_cmd_88xx Fail = %x!!\n", + ret_status); + return ret_status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * (debug API)halmac_verify_platform_api_88xx() - verify platform api + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_verify_platform_api_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_VERIFY_PLATFORM_API); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + ret_status = halmac_verify_io_88xx(halmac_adapter); + + if (ret_status != HALMAC_RET_SUCCESS) + return ret_status; + + if (halmac_adapter->txff_allocation.la_mode != HALMAC_LA_MODE_FULL) + ret_status = halmac_verify_send_rsvd_page_88xx(halmac_adapter); + + if (ret_status != HALMAC_RET_SUCCESS) + return ret_status; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return ret_status; +} + +enum halmac_ret_status +halmac_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *original_h2c, u16 *seq, u8 ack) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_ORIGINAL_H2C); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + status = halmac_func_send_original_h2c_88xx(halmac_adapter, + original_h2c, seq, ack); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_original_h2c FAIL = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_timer_2s_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_fill_txdesc_check_sum_88xx() - fill in tx desc check sum + * @halmac_adapter : the adapter of halmac + * @cur_desc : tx desc packet + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_fill_txdesc_check_sum_88xx(struct halmac_adapter *halmac_adapter, + u8 *cur_desc) +{ + u16 chk_result = 0; + u16 *data = (u16 *)NULL; + u32 i; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_FILL_TXDESC_CHECKSUM); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (!cur_desc) { + pr_err("%s NULL PTR", __func__); + return HALMAC_RET_NULL_POINTER; + } + + SET_TX_DESC_TXDESC_CHECKSUM(cur_desc, 0x0000); + + data = (u16 *)(cur_desc); + + /* HW clculates only 32byte */ + for (i = 0; i < 8; i++) + chk_result ^= (*(data + 2 * i) ^ *(data + (2 * i + 1))); + + SET_TX_DESC_TXDESC_CHECKSUM(cur_desc, chk_result); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_dump_fifo_88xx() - dump fifo data + * @halmac_adapter : the adapter of halmac + * @halmac_fifo_sel : FIFO selection + * @halmac_start_addr : start address of selected FIFO + * @halmac_fifo_dump_size : dump size of selected FIFO + * @fifo_map : FIFO data + * + * Note : before dump fifo, user need to call halmac_get_fifo_size to + * get fifo size. Then input this size to halmac_dump_fifo. + * + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_dump_fifo_88xx(struct halmac_adapter *halmac_adapter, + enum hal_fifo_sel halmac_fifo_sel, u32 halmac_start_addr, + u32 halmac_fifo_dump_size, u8 *fifo_map) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_FIFO); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_fifo_sel == HAL_FIFO_SEL_TX && + (halmac_start_addr + halmac_fifo_dump_size) > + halmac_adapter->hw_config_info.tx_fifo_size) { + pr_err("TX fifo dump size is too large\n"); + return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT; + } + + if (halmac_fifo_sel == HAL_FIFO_SEL_RX && + (halmac_start_addr + halmac_fifo_dump_size) > + halmac_adapter->hw_config_info.rx_fifo_size) { + pr_err("RX fifo dump size is too large\n"); + return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT; + } + + if ((halmac_fifo_dump_size & (4 - 1)) != 0) { + pr_err("halmac_fifo_dump_size shall 4byte align\n"); + return HALMAC_RET_DUMP_FIFOSIZE_INCORRECT; + } + + if (!fifo_map) { + pr_err("fifo_map address is NULL\n"); + return HALMAC_RET_NULL_POINTER; + } + + status = halmac_buffer_read_88xx(halmac_adapter, halmac_start_addr, + halmac_fifo_dump_size, halmac_fifo_sel, + fifo_map); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_buffer_read_88xx error = %x\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_fifo_size_88xx() - get fifo size + * @halmac_adapter : the adapter of halmac + * @halmac_fifo_sel : FIFO selection + * Author : Ivan Lin/KaiYuan Chang + * Return : u32 + * More details of status code can be found in prototype document + */ +u32 halmac_get_fifo_size_88xx(struct halmac_adapter *halmac_adapter, + enum hal_fifo_sel halmac_fifo_sel) +{ + u32 fifo_size = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_FIFO_SIZE); + + if (halmac_fifo_sel == HAL_FIFO_SEL_TX) + fifo_size = halmac_adapter->hw_config_info.tx_fifo_size; + else if (halmac_fifo_sel == HAL_FIFO_SEL_RX) + fifo_size = halmac_adapter->hw_config_info.rx_fifo_size; + else if (halmac_fifo_sel == HAL_FIFO_SEL_RSVD_PAGE) + fifo_size = + ((halmac_adapter->hw_config_info.tx_fifo_size >> 7) - + halmac_adapter->txff_allocation.rsvd_pg_bndy) + << 7; + else if (halmac_fifo_sel == HAL_FIFO_SEL_REPORT) + fifo_size = 65536; + else if (halmac_fifo_sel == HAL_FIFO_SEL_LLT) + fifo_size = 65536; + + return fifo_size; +} + +/** + * halmac_cfg_txbf_88xx() - enable/disable specific user's txbf + * @halmac_adapter : the adapter of halmac + * @userid : su bfee userid = 0 or 1 to apply TXBF + * @bw : the sounding bandwidth + * @txbf_en : 0: disable TXBF, 1: enable TXBF + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_txbf_88xx(struct halmac_adapter *halmac_adapter, u8 userid, + enum halmac_bw bw, u8 txbf_en) +{ + u16 temp42C = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TXBF); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (txbf_en) { + switch (bw) { + case HALMAC_BW_80: + temp42C |= BIT_R_TXBF0_80M; + case HALMAC_BW_40: + temp42C |= BIT_R_TXBF0_40M; + case HALMAC_BW_20: + temp42C |= BIT_R_TXBF0_20M; + break; + default: + pr_err("%s invalid TXBF BW setting 0x%x of userid %d\n", + __func__, bw, userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + } + + switch (userid) { + case 0: + temp42C |= + HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) & + ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL, temp42C); + break; + case 1: + temp42C |= + HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) & + ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2, temp42C); + break; + default: + pr_err("%s invalid userid %d\n", __func__, userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s, txbf_en = %x <==========\n", __func__, + txbf_en); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_mumimo_88xx() -config mumimo + * @halmac_adapter : the adapter of halmac + * @cfgmu : parameters to configure MU PPDU Tx/Rx + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_mumimo_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_cfg_mumimo_para *cfgmu) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u8 i, idx, id0, id1, gid, mu_tab_sel; + u8 mu_tab_valid = 0; + u32 gid_valid[6] = {0}; + u8 temp14C0 = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MUMIMO); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (cfgmu->role == HAL_BFEE) { + /*config MU BFEE*/ + temp14C0 = HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) & + ~BIT_MASK_R_MU_TABLE_VALID; + /*enable MU table 0 and 1, disable MU TX*/ + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, + (temp14C0 | BIT(0) | BIT(1)) & ~(BIT(7))); + + /*config GID valid table and user position table*/ + mu_tab_sel = + HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) & + ~(BIT(0) | BIT(1) | BIT(2)); + for (i = 0; i < 2; i++) { + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1, + mu_tab_sel | i); + HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD, + cfgmu->given_gid_tab[i]); + HALMAC_REG_WRITE_32(halmac_adapter, + REG_MU_STA_USER_POS_INFO, + cfgmu->given_user_pos[i * 2]); + HALMAC_REG_WRITE_32(halmac_adapter, + REG_MU_STA_USER_POS_INFO + 4, + cfgmu->given_user_pos[i * 2 + 1]); + } + } else { + /*config MU BFER*/ + if (!cfgmu->mu_tx_en) { + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, + HALMAC_REG_READ_8(halmac_adapter, + REG_MU_TX_CTL) & + ~(BIT(7))); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s disable mu tx <==========\n", __func__); + return HALMAC_RET_SUCCESS; + } + + /*Transform BB grouping bitmap[14:0] to MAC GID_valid table*/ + for (idx = 0; idx < 15; idx++) { + if (idx < 5) { + /*group_bitmap bit0~4, MU_STA0 with MUSTA1~5*/ + id0 = 0; + id1 = (u8)(idx + 1); + } else if (idx < 9) { + /*group_bitmap bit5~8, MU_STA1 with MUSTA2~5*/ + id0 = 1; + id1 = (u8)(idx - 3); + } else if (idx < 12) { + /*group_bitmap bit9~11, MU_STA2 with MUSTA3~5*/ + id0 = 2; + id1 = (u8)(idx - 6); + } else if (idx < 14) { + /*group_bitmap bit12~13, MU_STA3 with MUSTA4~5*/ + id0 = 3; + id1 = (u8)(idx - 8); + } else { + /*group_bitmap bit14, MU_STA4 with MUSTA5*/ + id0 = 4; + id1 = (u8)(idx - 9); + } + if (cfgmu->grouping_bitmap & BIT(idx)) { + /*Pair 1*/ + gid = (idx << 1) + 1; + gid_valid[id0] |= (BIT(gid)); + gid_valid[id1] |= (BIT(gid)); + /*Pair 2*/ + gid += 1; + gid_valid[id0] |= (BIT(gid)); + gid_valid[id1] |= (BIT(gid)); + } else { + /*Pair 1*/ + gid = (idx << 1) + 1; + gid_valid[id0] &= ~(BIT(gid)); + gid_valid[id1] &= ~(BIT(gid)); + /*Pair 2*/ + gid += 1; + gid_valid[id0] &= ~(BIT(gid)); + gid_valid[id1] &= ~(BIT(gid)); + } + } + + /*set MU STA GID valid TABLE*/ + mu_tab_sel = + HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL + 1) & + ~(BIT(0) | BIT(1) | BIT(2)); + for (idx = 0; idx < 6; idx++) { + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL + 1, + idx | mu_tab_sel); + HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD, + gid_valid[idx]); + } + + /*To validate the sounding successful MU STA and enable MU TX*/ + for (i = 0; i < 6; i++) { + if (cfgmu->sounding_sts[i]) + mu_tab_valid |= BIT(i); + } + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, + mu_tab_valid | BIT(7)); + } + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_sounding_88xx() - configure general sounding + * @halmac_adapter : the adapter of halmac + * @role : driver's role, BFer or BFee + * @datarate : set ndpa tx rate if driver is BFer, or set csi response rate + * if driver is BFee + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_sounding_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_snd_role role, + enum halmac_data_rate datarate) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_SOUNDING); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (role) { + case HAL_BFER: + HALMAC_REG_WRITE_32( + halmac_adapter, REG_TXBF_CTRL, + HALMAC_REG_READ_32(halmac_adapter, REG_TXBF_CTRL) | + BIT_R_ENABLE_NDPA | BIT_USE_NDPA_PARAMETER | + BIT_R_EN_NDPA_INT | BIT_DIS_NDP_BFEN); + HALMAC_REG_WRITE_8(halmac_adapter, REG_NDPA_RATE, datarate); + HALMAC_REG_WRITE_8( + halmac_adapter, REG_NDPA_OPT_CTRL, + HALMAC_REG_READ_8(halmac_adapter, REG_NDPA_OPT_CTRL) & + (~(BIT(0) | BIT(1)))); + /*service file length 2 bytes; fix non-STA1 csi start offset */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 1, + 0x2 | BIT(7)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 2, 0x2); + break; + case HAL_BFEE: + HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0xDB); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL + 3, 0x50); + /*use ndpa rx rate to decide csi rate*/ + HALMAC_REG_WRITE_8(halmac_adapter, REG_BBPSF_CTRL + 3, + HALMAC_OFDM54 | BIT(6)); + HALMAC_REG_WRITE_16( + halmac_adapter, REG_RRSR, + HALMAC_REG_READ_16(halmac_adapter, REG_RRSR) | + BIT(datarate)); + /*RXFF do not accept BF Rpt Poll, avoid CSI crc error*/ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_RXFLTMAP1, + HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP1) & + (~(BIT(4)))); + /*FWFF do not accept BF Rpt Poll, avoid CSI crc error*/ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_RXFLTMAP4, + HALMAC_REG_READ_8(halmac_adapter, REG_RXFLTMAP4) & + (~(BIT(4)))); + break; + default: + pr_err("%s invalid role\n", __func__); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_del_sounding_88xx() - reset general sounding + * @halmac_adapter : the adapter of halmac + * @role : driver's role, BFer or BFee + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_del_sounding_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_snd_role role) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEL_SOUNDING); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (role) { + case HAL_BFER: + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXBF_CTRL + 3, 0); + break; + case HAL_BFEE: + HALMAC_REG_WRITE_8(halmac_adapter, REG_SND_PTCL_CTRL, 0); + break; + default: + pr_err("%s invalid role\n", __func__); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_su_bfee_entry_init_88xx() - config SU beamformee's registers + * @halmac_adapter : the adapter of halmac + * @userid : SU bfee userid = 0 or 1 to be added + * @paid : partial AID of this bfee + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_su_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, u8 userid, + u16 paid) +{ + u16 temp42C = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_SU_BFEE_ENTRY_INIT); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (userid) { + case 0: + temp42C = HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) & + ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M | + BIT_R_TXBF0_40M | BIT_R_TXBF0_80M); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL, + temp42C | paid); + HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL, + paid); + break; + case 1: + temp42C = + HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) & + ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M | + BIT_R_TXBF0_40M | BIT_R_TXBF0_80M); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TXBF_CTRL + 2, + temp42C | paid); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMEE_SEL + 2, + paid | BIT(9)); + break; + default: + pr_err("%s invalid userid %d\n", __func__, + userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_su_bfee_entry_init_88xx() - config SU beamformer's registers + * @halmac_adapter : the adapter of halmac + * @su_bfer_init : parameters to configure SU BFER entry + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_su_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_su_bfer_init_para *su_bfer_init) +{ + u16 mac_address_H; + u32 mac_address_L; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_SU_BFER_ENTRY_INIT); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + /* mac_address_L = bfer_address.address_l_h.address_low; */ + /* mac_address_H = bfer_address.address_l_h.address_high; */ + + mac_address_L = le32_to_cpu( + su_bfer_init->bfer_address.address_l_h.le_address_low); + mac_address_H = le16_to_cpu( + su_bfer_init->bfer_address.address_l_h.le_address_high); + + switch (su_bfer_init->userid) { + case 0: + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, + mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMER0_INFO + 4, + mac_address_H); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMER0_INFO + 6, + su_bfer_init->paid); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20, + su_bfer_init->csi_para); + break; + case 1: + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO, + mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMER1_INFO + 4, + mac_address_H); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMER1_INFO + 6, + su_bfer_init->paid); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_TX_CSI_RPT_PARAM_BW20 + 2, + su_bfer_init->csi_para); + break; + default: + pr_err("%s invalid userid %d\n", __func__, + su_bfer_init->userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_mu_bfee_entry_init_88xx() - config MU beamformee's registers + * @halmac_adapter : the adapter of halmac + * @mu_bfee_init : parameters to configure MU BFEE entry + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mu_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_mu_bfee_init_para *mu_bfee_init) +{ + u16 temp168X = 0, temp14C0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_MU_BFEE_ENTRY_INIT); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + temp168X |= mu_bfee_init->paid | BIT(9); + HALMAC_REG_WRITE_16(halmac_adapter, (0x1680 + mu_bfee_init->userid * 2), + temp168X); + + temp14C0 = HALMAC_REG_READ_16(halmac_adapter, REG_MU_TX_CTL) & + ~(BIT(8) | BIT(9) | BIT(10)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_MU_TX_CTL, + temp14C0 | ((mu_bfee_init->userid - 2) << 8)); + HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_GID_VLD, 0); + HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO, + mu_bfee_init->user_position_l); + HALMAC_REG_WRITE_32(halmac_adapter, REG_MU_STA_USER_POS_INFO + 4, + mu_bfee_init->user_position_h); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_mu_bfer_entry_init_88xx() - config MU beamformer's registers + * @halmac_adapter : the adapter of halmac + * @mu_bfer_init : parameters to configure MU BFER entry + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mu_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_mu_bfer_init_para *mu_bfer_init) +{ + u16 temp1680 = 0; + u16 mac_address_H; + u32 mac_address_L; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_MU_BFER_ENTRY_INIT); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + mac_address_L = + le32_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_low); + mac_address_H = + le16_to_cpu(mu_bfer_init->bfer_address.address_l_h.le_address_high); + + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, + mac_address_L); + HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4, + mac_address_H); + HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 6, + mu_bfer_init->paid); + HALMAC_REG_WRITE_16(halmac_adapter, REG_TX_CSI_RPT_PARAM_BW20, + mu_bfer_init->csi_para); + + temp1680 = HALMAC_REG_READ_16(halmac_adapter, 0x1680) & 0xC000; + temp1680 |= mu_bfer_init->my_aid | (mu_bfer_init->csi_length_sel << 12); + HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, temp1680); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_su_bfee_entry_del_88xx() - reset SU beamformee's registers + * @halmac_adapter : the adapter of halmac + * @userid : the SU BFee userid to be deleted + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_su_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFEE_ENTRY_DEL); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (userid) { + case 0: + HALMAC_REG_WRITE_16( + halmac_adapter, REG_TXBF_CTRL, + HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL) & + ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M | + BIT_R_TXBF0_40M | BIT_R_TXBF0_80M)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_ASSOCIATED_BFMEE_SEL, + 0); + break; + case 1: + HALMAC_REG_WRITE_16( + halmac_adapter, REG_TXBF_CTRL + 2, + HALMAC_REG_READ_16(halmac_adapter, REG_TXBF_CTRL + 2) & + ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M | + BIT_R_TXBF0_40M | BIT_R_TXBF0_80M)); + HALMAC_REG_WRITE_16(halmac_adapter, + REG_ASSOCIATED_BFMEE_SEL + 2, 0); + break; + default: + pr_err("%s invalid userid %d\n", __func__, + userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_su_bfee_entry_del_88xx() - reset SU beamformer's registers + * @halmac_adapter : the adapter of halmac + * @userid : the SU BFer userid to be deleted + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_su_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SU_BFER_ENTRY_DEL); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (userid) { + case 0: + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, + 0); + HALMAC_REG_WRITE_32(halmac_adapter, + REG_ASSOCIATED_BFMER0_INFO + 4, 0); + break; + case 1: + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER1_INFO, + 0); + HALMAC_REG_WRITE_32(halmac_adapter, + REG_ASSOCIATED_BFMER1_INFO + 4, 0); + break; + default: + pr_err("%s invalid userid %d\n", __func__, + userid); + return HALMAC_RET_INVALID_SOUNDING_SETTING; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_mu_bfee_entry_del_88xx() - reset MU beamformee's registers + * @halmac_adapter : the adapter of halmac + * @userid : the MU STA userid to be deleted + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mu_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFEE_ENTRY_DEL); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_16(halmac_adapter, 0x1680 + userid * 2, 0); + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, + HALMAC_REG_READ_8(halmac_adapter, REG_MU_TX_CTL) & + ~(BIT(userid - 2))); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_mu_bfer_entry_del_88xx() -reset MU beamformer's registers + * @halmac_adapter : the adapter of halmac + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_mu_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_MU_BFER_ENTRY_DEL); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO, 0); + HALMAC_REG_WRITE_32(halmac_adapter, REG_ASSOCIATED_BFMER0_INFO + 4, 0); + HALMAC_REG_WRITE_16(halmac_adapter, 0x1680, 0); + HALMAC_REG_WRITE_8(halmac_adapter, REG_MU_TX_CTL, 0); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_add_ch_info_88xx() -add channel information + * @halmac_adapter : the adapter of halmac + * @ch_info : channel information + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_add_ch_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_info *ch_info) +{ + void *driver_adapter = NULL; + struct halmac_cs_info *ch_sw_info; + enum halmac_scan_cmd_construct_state state_scan; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + ch_sw_info = &halmac_adapter->ch_sw_info; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + if (halmac_adapter->halmac_state.dlfw_state != HALMAC_GEN_INFO_SENT) { + pr_err("[ERR]%s: gen_info is not send to FW!!!!\n", __func__); + return HALMAC_RET_GEN_INFO_NOT_SENT; + } + + state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter); + if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED && + state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_WARNING, + "[WARN]Scan machine fail(add ch info)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (!ch_sw_info->ch_info_buf) { + ch_sw_info->ch_info_buf = + kzalloc(HALMAC_EXTRA_INFO_BUFF_SIZE_88XX, GFP_KERNEL); + if (!ch_sw_info->ch_info_buf) + return HALMAC_RET_NULL_POINTER; + ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf; + ch_sw_info->buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX; + ch_sw_info->avai_buf_size = HALMAC_EXTRA_INFO_BUFF_SIZE_88XX; + ch_sw_info->total_size = 0; + ch_sw_info->extra_info_en = 0; + ch_sw_info->ch_num = 0; + } + + if (ch_sw_info->extra_info_en == 1) { + pr_err("[ERR]%s: construct sequence wrong!!\n", __func__); + return HALMAC_RET_CH_SW_SEQ_WRONG; + } + + if (ch_sw_info->avai_buf_size < 4) { + pr_err("[ERR]%s: no available buffer!!\n", __func__); + return HALMAC_RET_CH_SW_NO_BUF; + } + + if (halmac_transition_scan_state_88xx( + halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + CHANNEL_INFO_SET_CHANNEL(ch_sw_info->ch_info_buf_w, ch_info->channel); + CHANNEL_INFO_SET_PRI_CH_IDX(ch_sw_info->ch_info_buf_w, + ch_info->pri_ch_idx); + CHANNEL_INFO_SET_BANDWIDTH(ch_sw_info->ch_info_buf_w, ch_info->bw); + CHANNEL_INFO_SET_TIMEOUT(ch_sw_info->ch_info_buf_w, ch_info->timeout); + CHANNEL_INFO_SET_ACTION_ID(ch_sw_info->ch_info_buf_w, + ch_info->action_id); + CHANNEL_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w, + ch_info->extra_info); + + ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size - 4; + ch_sw_info->total_size = ch_sw_info->total_size + 4; + ch_sw_info->ch_num++; + ch_sw_info->extra_info_en = ch_info->extra_info; + ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w + 4; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_add_extra_ch_info_88xx() -add extra channel information + * @halmac_adapter : the adapter of halmac + * @ch_extra_info : extra channel information + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_add_extra_ch_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_extra_info *ch_extra_info) +{ + void *driver_adapter = NULL; + struct halmac_cs_info *ch_sw_info; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_ADD_EXTRA_CH_INFO); + + driver_adapter = halmac_adapter->driver_adapter; + ch_sw_info = &halmac_adapter->ch_sw_info; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (!ch_sw_info->ch_info_buf) { + pr_err("%s: NULL==ch_sw_info->ch_info_buf!!\n", __func__); + return HALMAC_RET_CH_SW_SEQ_WRONG; + } + + if (ch_sw_info->extra_info_en == 0) { + pr_err("%s: construct sequence wrong!!\n", __func__); + return HALMAC_RET_CH_SW_SEQ_WRONG; + } + + if (ch_sw_info->avai_buf_size < + (u32)(ch_extra_info->extra_info_size + 2)) { + /* +2: ch_extra_info_id, ch_extra_info, ch_extra_info_size + * are totally 2Byte + */ + pr_err("%s: no available buffer!!\n", __func__); + return HALMAC_RET_CH_SW_NO_BUF; + } + + if (halmac_query_scan_curr_state_88xx(halmac_adapter) != + HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Scan machine fail(add extra ch info)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (halmac_transition_scan_state_88xx( + halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + CH_EXTRA_INFO_SET_CH_EXTRA_INFO_ID(ch_sw_info->ch_info_buf_w, + ch_extra_info->extra_action_id); + CH_EXTRA_INFO_SET_CH_EXTRA_INFO(ch_sw_info->ch_info_buf_w, + ch_extra_info->extra_info); + CH_EXTRA_INFO_SET_CH_EXTRA_INFO_SIZE(ch_sw_info->ch_info_buf_w, + ch_extra_info->extra_info_size); + memcpy(ch_sw_info->ch_info_buf_w + 2, ch_extra_info->extra_info_data, + ch_extra_info->extra_info_size); + + ch_sw_info->avai_buf_size = ch_sw_info->avai_buf_size - + (2 + ch_extra_info->extra_info_size); + ch_sw_info->total_size = + ch_sw_info->total_size + (2 + ch_extra_info->extra_info_size); + ch_sw_info->extra_info_en = ch_extra_info->extra_info; + ch_sw_info->ch_info_buf_w = ch_sw_info->ch_info_buf_w + + (2 + ch_extra_info->extra_info_size); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_ctrl_ch_switch_88xx() -send channel switch cmd + * @halmac_adapter : the adapter of halmac + * @cs_option : channel switch config + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_switch_option *cs_option) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_scan_cmd_construct_state state_scan; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.scan_state_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_CH_SWITCH); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s cs_option->switch_en = %d==========>\n", __func__, + cs_option->switch_en); + + if (!cs_option->switch_en) + *process_status = HALMAC_CMD_PROCESS_IDLE; + + if (*process_status == HALMAC_CMD_PROCESS_SENDING || + *process_status == HALMAC_CMD_PROCESS_RCVD) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(ctrl ch switch)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + state_scan = halmac_query_scan_curr_state_88xx(halmac_adapter); + if (cs_option->switch_en) { + if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, + DBG_DMESG, + "%s(on) invalid in state %x\n", + __func__, state_scan); + return HALMAC_RET_ERROR_STATE; + } + } else { + if (state_scan != HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) { + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s(off) invalid in state %x\n", __func__, + state_scan); + return HALMAC_RET_ERROR_STATE; + } + } + + status = halmac_func_ctrl_ch_switch_88xx(halmac_adapter, cs_option); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_ctrl_ch_switch FAIL = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_clear_ch_info_88xx() -clear channel information + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_clear_ch_info_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CLEAR_CH_INFO); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_query_scan_curr_state_88xx(halmac_adapter) == + HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Scan machine fail(clear ch info)...\n"); + return HALMAC_RET_ERROR_STATE; + } + + if (halmac_transition_scan_state_88xx( + halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + kfree(halmac_adapter->ch_sw_info.ch_info_buf); + halmac_adapter->ch_sw_info.ch_info_buf = NULL; + halmac_adapter->ch_sw_info.ch_info_buf_w = NULL; + halmac_adapter->ch_sw_info.extra_info_en = 0; + halmac_adapter->ch_sw_info.buf_size = 0; + halmac_adapter->ch_sw_info.avai_buf_size = 0; + halmac_adapter->ch_sw_info.total_size = 0; + halmac_adapter->ch_sw_info.ch_num = 0; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_p2pps_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_p2pps *p2p_ps) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 6) + return HALMAC_RET_FW_NO_SUPPORT; + + driver_adapter = halmac_adapter->driver_adapter; + + status = halmac_func_p2pps_88xx(halmac_adapter, p2p_ps); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_p2pps FAIL = %x!!\n", status); + return status; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_p2pps_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_p2pps *p2p_ps) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = halmac_adapter->driver_adapter; + struct halmac_api *halmac_api; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]halmac_p2pps !!\n"); + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + P2PPS_SET_OFFLOAD_EN(h2c_buff, p2p_ps->offload_en); + P2PPS_SET_ROLE(h2c_buff, p2p_ps->role); + P2PPS_SET_CTWINDOW_EN(h2c_buff, p2p_ps->ctwindow_en); + P2PPS_SET_NOA_EN(h2c_buff, p2p_ps->noa_en); + P2PPS_SET_NOA_SEL(h2c_buff, p2p_ps->noa_sel); + P2PPS_SET_ALLSTASLEEP(h2c_buff, p2p_ps->all_sta_sleep); + P2PPS_SET_DISCOVERY(h2c_buff, p2p_ps->discovery); + P2PPS_SET_P2P_PORT_ID(h2c_buff, p2p_ps->p2p_port_id); + P2PPS_SET_P2P_GROUP(h2c_buff, p2p_ps->p2p_group); + P2PPS_SET_P2P_MACID(h2c_buff, p2p_ps->p2p_macid); + + P2PPS_SET_CTWINDOW_LENGTH(h2c_buff, p2p_ps->ctwindow_length); + + P2PPS_SET_NOA_DURATION_PARA(h2c_buff, p2p_ps->noa_duration_para); + P2PPS_SET_NOA_INTERVAL_PARA(h2c_buff, p2p_ps->noa_interval_para); + P2PPS_SET_NOA_START_TIME_PARA(h2c_buff, p2p_ps->noa_start_time_para); + P2PPS_SET_NOA_COUNT_PARA(h2c_buff, p2p_ps->noa_count_para); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_P2PPS; + h2c_header_info.content_size = 24; + h2c_header_info.ack = false; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, false); + + if (status != HALMAC_RET_SUCCESS) + pr_err("[ERR]halmac_send_h2c_p2pps_88xx Fail = %x!!\n", status); + + return status; +} + +/** + * halmac_send_general_info_88xx() -send general information to FW + * @halmac_adapter : the adapter of halmac + * @general_info : general information + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_send_general_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_general_info *general_info) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + if (halmac_adapter->fw_version.h2c_version < 4) + return HALMAC_RET_FW_NO_SUPPORT; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SEND_GENERAL_INFO); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) { + pr_err("%s Fail due to DLFW NONE!!\n", __func__); + return HALMAC_RET_DLFW_FAIL; + } + + status = halmac_func_send_general_info_88xx(halmac_adapter, + general_info); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_general_info error = %x\n", status); + return status; + } + + if (halmac_adapter->halmac_state.dlfw_state == HALMAC_DLFW_DONE) + halmac_adapter->halmac_state.dlfw_state = HALMAC_GEN_INFO_SENT; + + halmac_adapter->gen_info_valid = true; + memcpy(&halmac_adapter->general_info, general_info, + sizeof(struct halmac_general_info)); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_start_iqk_88xx() -trigger FW IQK + * @halmac_adapter : the adapter of halmac + * @iqk_para : IQK parameter + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_start_iqk_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_iqk_para_ *iqk_para) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_num = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.iqk_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_START_IQK); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(iqk)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + IQK_SET_CLEAR(h2c_buff, iqk_para->clear); + IQK_SET_SEGMENT_IQK(h2c_buff, iqk_para->segment_iqk); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_IQK; + h2c_header_info.content_size = 1; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_num); + + halmac_adapter->halmac_state.iqk_set.seq_num = h2c_seq_num; + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_ctrl_pwr_tracking_88xx() -trigger FW power tracking + * @halmac_adapter : the adapter of halmac + * @pwr_tracking_opt : power tracking option + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_ctrl_pwr_tracking_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_pwr_tracking_option *pwr_tracking_opt) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.power_tracking_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CTRL_PWR_TRACKING); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_start_iqk_88xx ==========>\n"); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(pwr tracking)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + POWER_TRACKING_SET_TYPE(h2c_buff, pwr_tracking_opt->type); + POWER_TRACKING_SET_BBSWING_INDEX(h2c_buff, + pwr_tracking_opt->bbswing_index); + POWER_TRACKING_SET_ENABLE_A( + h2c_buff, + pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A].enable); + POWER_TRACKING_SET_TX_PWR_INDEX_A( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A] + .tx_pwr_index); + POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_A( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A] + .pwr_tracking_offset_value); + POWER_TRACKING_SET_TSSI_VALUE_A( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_A] + .tssi_value); + POWER_TRACKING_SET_ENABLE_B( + h2c_buff, + pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B].enable); + POWER_TRACKING_SET_TX_PWR_INDEX_B( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B] + .tx_pwr_index); + POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_B( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B] + .pwr_tracking_offset_value); + POWER_TRACKING_SET_TSSI_VALUE_B( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_B] + .tssi_value); + POWER_TRACKING_SET_ENABLE_C( + h2c_buff, + pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C].enable); + POWER_TRACKING_SET_TX_PWR_INDEX_C( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C] + .tx_pwr_index); + POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_C( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C] + .pwr_tracking_offset_value); + POWER_TRACKING_SET_TSSI_VALUE_C( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_C] + .tssi_value); + POWER_TRACKING_SET_ENABLE_D( + h2c_buff, + pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D].enable); + POWER_TRACKING_SET_TX_PWR_INDEX_D( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D] + .tx_pwr_index); + POWER_TRACKING_SET_PWR_TRACKING_OFFSET_VALUE_D( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D] + .pwr_tracking_offset_value); + POWER_TRACKING_SET_TSSI_VALUE_D( + h2c_buff, pwr_tracking_opt->pwr_tracking_para[HALMAC_RF_PATH_D] + .tssi_value); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_POWER_TRACKING; + h2c_header_info.content_size = 20; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + halmac_adapter->halmac_state.power_tracking_set.seq_num = h2c_seq_mum; + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_start_iqk_88xx <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_query_status_88xx() -query the offload feature status + * @halmac_adapter : the adapter of halmac + * @feature_id : feature_id + * @process_status : feature_status + * @data : data buffer + * @size : data size + * + * Note : + * If user wants to know the data size, use can allocate zero + * size buffer first. If this size less than the data size, halmac + * will return HALMAC_RET_BUFFER_TOO_SMALL. User need to + * re-allocate data buffer with correct data size. + * + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_query_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_feature_id feature_id, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_QUERY_STATE); + + driver_adapter = halmac_adapter->driver_adapter; + + if (!process_status) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "null pointer!!\n"); + return HALMAC_RET_NULL_POINTER; + } + + switch (feature_id) { + case HALMAC_FEATURE_CFG_PARA: + status = halmac_query_cfg_para_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE: + status = halmac_query_dump_physical_efuse_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE: + status = halmac_query_dump_logical_efuse_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_CHANNEL_SWITCH: + status = halmac_query_channel_switch_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_UPDATE_PACKET: + status = halmac_query_update_packet_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_IQK: + status = halmac_query_iqk_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_POWER_TRACKING: + status = halmac_query_power_tracking_status_88xx( + halmac_adapter, process_status, data, size); + break; + case HALMAC_FEATURE_PSD: + status = halmac_query_psd_status_88xx( + halmac_adapter, process_status, data, size); + break; + default: + pr_err("%s invalid feature id %d\n", __func__, + feature_id); + return HALMAC_RET_INVALID_FEATURE_ID; + } + + return status; +} + +/** + * halmac_reset_feature_88xx() -reset async api cmd status + * @halmac_adapter : the adapter of halmac + * @feature_id : feature_id + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status. + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reset_feature_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_feature_id feature_id) +{ + void *driver_adapter = NULL; + struct halmac_state *state = &halmac_adapter->halmac_state; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_RESET_FEATURE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + switch (feature_id) { + case HALMAC_FEATURE_CFG_PARA: + state->cfg_para_state_set.process_status = + HALMAC_CMD_PROCESS_IDLE; + state->cfg_para_state_set.cfg_para_cmd_construct_state = + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE; + break; + case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE: + case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE: + state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->efuse_state_set.efuse_cmd_construct_state = + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE; + break; + case HALMAC_FEATURE_CHANNEL_SWITCH: + state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->scan_state_set.scan_cmd_construct_state = + HALMAC_SCAN_CMD_CONSTRUCT_IDLE; + break; + case HALMAC_FEATURE_UPDATE_PACKET: + state->update_packet_set.process_status = + HALMAC_CMD_PROCESS_IDLE; + break; + case HALMAC_FEATURE_ALL: + state->cfg_para_state_set.process_status = + HALMAC_CMD_PROCESS_IDLE; + state->cfg_para_state_set.cfg_para_cmd_construct_state = + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE; + state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->efuse_state_set.efuse_cmd_construct_state = + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE; + state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->scan_state_set.scan_cmd_construct_state = + HALMAC_SCAN_CMD_CONSTRUCT_IDLE; + state->update_packet_set.process_status = + HALMAC_CMD_PROCESS_IDLE; + break; + default: + pr_err("%s invalid feature id %d\n", __func__, + feature_id); + return HALMAC_RET_INVALID_FEATURE_ID; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_check_fw_status_88xx() -check fw status + * @halmac_adapter : the adapter of halmac + * @fw_status : fw status + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_check_fw_status_88xx(struct halmac_adapter *halmac_adapter, + bool *fw_status) +{ + u32 value32 = 0, value32_backup = 0, i = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CHECK_FW_STATUS); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG6); + + if (value32 != 0) { + pr_err("halmac_check_fw_status REG_FW_DBG6 !=0\n"); + *fw_status = false; + return status; + } + + value32_backup = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7); + + for (i = 0; i <= 10; i++) { + value32 = PLATFORM_REG_READ_32(driver_adapter, REG_FW_DBG7); + if (value32_backup != value32) + break; + + if (i == 10) { + pr_err("halmac_check_fw_status Polling FW PC fail\n"); + *fw_status = false; + return status; + } + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return status; +} + +enum halmac_ret_status +halmac_dump_fw_dmem_88xx(struct halmac_adapter *halmac_adapter, u8 *dmem, + u32 *size) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DUMP_FW_DMEM); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return status; +} + +/** + * halmac_cfg_max_dl_size_88xx() - config max download FW size + * @halmac_adapter : the adapter of halmac + * @size : max download fw size + * + * Halmac uses this setting to set max packet size for + * download FW. + * If user has not called this API, halmac use default + * setting for download FW + * Note1 : size need multiple of 2 + * Note2 : max size is 31K + * + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_max_dl_size_88xx(struct halmac_adapter *halmac_adapter, u32 size) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_MAX_DL_SIZE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG, + "%s ==========>\n", __func__); + + if (size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX_88XX) { + pr_err("size > HALMAC_FW_CFG_MAX_DL_SIZE_MAX!\n"); + return HALMAC_RET_CFG_DLFW_SIZE_FAIL; + } + + if ((size & (2 - 1)) != 0) { + pr_err("size is not power of 2!\n"); + return HALMAC_RET_CFG_DLFW_SIZE_FAIL; + } + + halmac_adapter->max_download_size = size; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG, + "Cfg max size is : %X\n", size); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_FW, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_psd_88xx() - trigger fw psd + * @halmac_adapter : the adapter of halmac + * @start_psd : start PSD + * @end_psd : end PSD + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_psd_88xx(struct halmac_adapter *halmac_adapter, + u16 start_psd, u16 end_psd) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.psd_set.process_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + if (halmac_fw_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_NO_DLFW; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_PSD); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (*process_status == HALMAC_CMD_PROCESS_SENDING) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Wait event(psd)...\n"); + return HALMAC_RET_BUSY_STATE; + } + + kfree(halmac_adapter->halmac_state.psd_set.data); + halmac_adapter->halmac_state.psd_set.data = (u8 *)NULL; + + halmac_adapter->halmac_state.psd_set.data_size = 0; + halmac_adapter->halmac_state.psd_set.segment_size = 0; + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + PSD_SET_START_PSD(h2c_buff, start_psd); + PSD_SET_END_PSD(h2c_buff, end_psd); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_PSD; + h2c_header_info.content_size = 4; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_la_mode_88xx() - config la mode + * @halmac_adapter : the adapter of halmac + * @la_mode : + * disable : no TXFF space reserved for LA debug + * partial : partial TXFF space is reserved for LA debug + * full : all TXFF space is reserved for LA debug + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_la_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_la_mode la_mode) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_LA_MODE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>la_mode = %d\n", __func__, + la_mode); + + halmac_adapter->txff_allocation.la_mode = la_mode; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_rx_fifo_expanding_mode_88xx() - rx fifo expanding + * @halmac_adapter : the adapter of halmac + * @la_mode : + * disable : normal mode + * 1 block : Rx FIFO + 1 FIFO block; Tx fifo - 1 FIFO block + * 2 block : Rx FIFO + 2 FIFO block; Tx fifo - 2 FIFO block + * 3 block : Rx FIFO + 3 FIFO block; Tx fifo - 3 FIFO block + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_cfg_rx_fifo_expanding_mode_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_rx_fifo_expanding_mode rx_fifo_expanding_mode) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_RX_FIFO_EXPANDING_MODE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>rx_fifo_expanding_mode = %d\n", __func__, + rx_fifo_expanding_mode); + + halmac_adapter->txff_allocation.rx_fifo_expanding_mode = + rx_fifo_expanding_mode; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_config_security_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_security_setting *sec_setting) +{ + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_REG_WRITE_16(halmac_adapter, REG_CR, + (u16)(HALMAC_REG_READ_16(halmac_adapter, REG_CR) | + BIT_MAC_SEC_EN)); + + if (sec_setting->tx_encryption == 1) + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SECCFG, + HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(2)); + else + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SECCFG, + HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) & + ~(BIT(2))); + + if (sec_setting->rx_decryption == 1) + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SECCFG, + HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) | BIT(3)); + else + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SECCFG, + HALMAC_REG_READ_8(halmac_adapter, REG_SECCFG) & + ~(BIT(3))); + + if (sec_setting->bip_enable == 1) { + if (halmac_adapter->chip_id == HALMAC_CHIP_ID_8822B) + return HALMAC_RET_BIP_NO_SUPPORT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +u8 halmac_get_used_cam_entry_num_88xx(struct halmac_adapter *halmac_adapter, + enum hal_security_type sec_type) +{ + u8 entry_num; + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s ==========>\n", __func__); + + switch (sec_type) { + case HAL_SECURITY_TYPE_WEP40: + case HAL_SECURITY_TYPE_WEP104: + case HAL_SECURITY_TYPE_TKIP: + case HAL_SECURITY_TYPE_AES128: + case HAL_SECURITY_TYPE_GCMP128: + case HAL_SECURITY_TYPE_GCMSMS4: + case HAL_SECURITY_TYPE_BIP: + entry_num = 1; + break; + case HAL_SECURITY_TYPE_WAPI: + case HAL_SECURITY_TYPE_AES256: + case HAL_SECURITY_TYPE_GCMP256: + entry_num = 2; + break; + default: + entry_num = 0; + break; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s <==========\n", __func__); + + return entry_num; +} + +enum halmac_ret_status +halmac_write_cam_88xx(struct halmac_adapter *halmac_adapter, u32 entry_index, + struct halmac_cam_entry_info *cam_entry_info) +{ + u32 i; + u32 command = 0x80010000; + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + struct halmac_cam_entry_format *cam_entry_format = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "[TRACE]%s ==========>\n", __func__); + + if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num) + return HALMAC_RET_ENTRY_INDEX_ERROR; + + if (cam_entry_info->key_id > 3) + return HALMAC_RET_FAIL; + + cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL); + if (!cam_entry_format) + return HALMAC_RET_NULL_POINTER; + + cam_entry_format->key_id = cam_entry_info->key_id; + cam_entry_format->valid = cam_entry_info->valid; + memcpy(cam_entry_format->mac_address, cam_entry_info->mac_address, 6); + memcpy(cam_entry_format->key, cam_entry_info->key, 16); + + switch (cam_entry_info->security_type) { + case HAL_SECURITY_TYPE_NONE: + cam_entry_format->type = 0; + break; + case HAL_SECURITY_TYPE_WEP40: + cam_entry_format->type = 1; + break; + case HAL_SECURITY_TYPE_WEP104: + cam_entry_format->type = 5; + break; + case HAL_SECURITY_TYPE_TKIP: + cam_entry_format->type = 2; + break; + case HAL_SECURITY_TYPE_AES128: + cam_entry_format->type = 4; + break; + case HAL_SECURITY_TYPE_WAPI: + cam_entry_format->type = 6; + break; + case HAL_SECURITY_TYPE_AES256: + cam_entry_format->type = 4; + cam_entry_format->ext_sectype = 1; + break; + case HAL_SECURITY_TYPE_GCMP128: + cam_entry_format->type = 7; + break; + case HAL_SECURITY_TYPE_GCMP256: + case HAL_SECURITY_TYPE_GCMSMS4: + cam_entry_format->type = 7; + cam_entry_format->ext_sectype = 1; + break; + case HAL_SECURITY_TYPE_BIP: + cam_entry_format->type = cam_entry_info->unicast == 1 ? 4 : 0; + cam_entry_format->mgnt = 1; + cam_entry_format->grp = cam_entry_info->unicast == 1 ? 0 : 1; + break; + default: + kfree(cam_entry_format); + return HALMAC_RET_FAIL; + } + + for (i = 0; i < 8; i++) { + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE, + *((u32 *)cam_entry_format + i)); + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD, + command | ((entry_index << 3) + i)); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "[TRACE]1 - CAM entry format : %X\n", + *((u32 *)cam_entry_format + i)); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "[TRACE]1 - REG_CAMCMD : %X\n", + command | ((entry_index << 3) + i)); + } + + if (cam_entry_info->security_type == HAL_SECURITY_TYPE_WAPI || + cam_entry_info->security_type == HAL_SECURITY_TYPE_AES256 || + cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMP256 || + cam_entry_info->security_type == HAL_SECURITY_TYPE_GCMSMS4) { + cam_entry_format->mic = 1; + memcpy(cam_entry_format->key, cam_entry_info->key_ext, 16); + + for (i = 0; i < 8; i++) { + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE, + *((u32 *)cam_entry_format + i)); + HALMAC_REG_WRITE_32( + halmac_adapter, REG_CAMCMD, + command | (((entry_index + 1) << 3) + i)); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, + DBG_DMESG, + "[TRACE]2 - CAM entry format : %X\n", + *((u32 *)cam_entry_format + i)); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "[TRACE]2 - REG_CAMCMD : %X\n", + command | (((entry_index + 1) << 3) + i)); + } + } + + kfree(cam_entry_format); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "[TRACE]%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_read_cam_entry_88xx(struct halmac_adapter *halmac_adapter, + u32 entry_index, + struct halmac_cam_entry_format *content) +{ + u32 i; + u32 command = 0x80000000; + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s ==========>\n", __func__); + + if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num) + return HALMAC_RET_ENTRY_INDEX_ERROR; + + for (i = 0; i < 8; i++) { + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD, + command | ((entry_index << 3) + i)); + *((u32 *)content + i) = + HALMAC_REG_READ_32(halmac_adapter, REG_CAMREAD); + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_clear_cam_entry_88xx(struct halmac_adapter *halmac_adapter, + u32 entry_index) +{ + u32 i; + u32 command = 0x80010000; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_cam_entry_format *cam_entry_format; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]halmac_clear_security_cam_88xx ==========>\n"); + + if (entry_index >= halmac_adapter->hw_config_info.cam_entry_num) + return HALMAC_RET_ENTRY_INDEX_ERROR; + + cam_entry_format = kzalloc(sizeof(*cam_entry_format), GFP_KERNEL); + if (!cam_entry_format) + return HALMAC_RET_NULL_POINTER; + + for (i = 0; i < 8; i++) { + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMWRITE, + *((u32 *)cam_entry_format + i)); + HALMAC_REG_WRITE_32(halmac_adapter, REG_CAMCMD, + command | ((entry_index << 3) + i)); + } + + kfree(cam_entry_format); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "[TRACE]halmac_clear_security_cam_88xx <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_hw_value_88xx() -get hw config value + * @halmac_adapter : the adapter of halmac + * @hw_id : hw id for driver to query + * @pvalue : hw value, reference table to get data type + * Author : KaiYuan Chang / Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_hw_value_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_hw_id hw_id, void *pvalue) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (!pvalue) { + pr_err("%s (!pvalue)==========>\n", __func__); + return HALMAC_RET_NULL_POINTER; + } + + switch (hw_id) { + case HALMAC_HW_RQPN_MAPPING: + ((struct halmac_rqpn_map *)pvalue)->dma_map_vo = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO]; + ((struct halmac_rqpn_map *)pvalue)->dma_map_vi = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI]; + ((struct halmac_rqpn_map *)pvalue)->dma_map_be = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE]; + ((struct halmac_rqpn_map *)pvalue)->dma_map_bk = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK]; + ((struct halmac_rqpn_map *)pvalue)->dma_map_mg = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG]; + ((struct halmac_rqpn_map *)pvalue)->dma_map_hi = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI]; + break; + case HALMAC_HW_EFUSE_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size; + break; + case HALMAC_HW_EEPROM_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.eeprom_size; + break; + case HALMAC_HW_BT_BANK_EFUSE_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.bt_efuse_size; + break; + case HALMAC_HW_BT_BANK1_EFUSE_SIZE: + case HALMAC_HW_BT_BANK2_EFUSE_SIZE: + *(u32 *)pvalue = 0; + break; + case HALMAC_HW_TXFIFO_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.tx_fifo_size; + break; + case HALMAC_HW_RSVD_PG_BNDY: + *(u16 *)pvalue = + halmac_adapter->txff_allocation.rsvd_drv_pg_bndy; + break; + case HALMAC_HW_CAM_ENTRY_NUM: + *(u8 *)pvalue = halmac_adapter->hw_config_info.cam_entry_num; + break; + case HALMAC_HW_WLAN_EFUSE_AVAILABLE_SIZE: /*Remove later*/ + status = halmac_dump_logical_efuse_map_88xx(halmac_adapter, + HALMAC_EFUSE_R_DRV); + if (status != HALMAC_RET_SUCCESS) + return status; + *(u32 *)pvalue = halmac_adapter->hw_config_info.efuse_size - + HALMAC_PROTECTED_EFUSE_SIZE_88XX - + halmac_adapter->efuse_end; + break; + case HALMAC_HW_IC_VERSION: + *(u8 *)pvalue = halmac_adapter->chip_version; + break; + case HALMAC_HW_PAGE_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.page_size; + break; + case HALMAC_HW_TX_AGG_ALIGN_SIZE: + *(u16 *)pvalue = halmac_adapter->hw_config_info.tx_align_size; + break; + case HALMAC_HW_RX_AGG_ALIGN_SIZE: + *(u8 *)pvalue = 8; + break; + case HALMAC_HW_DRV_INFO_SIZE: + *(u8 *)pvalue = halmac_adapter->drv_info_size; + break; + case HALMAC_HW_TXFF_ALLOCATION: + memcpy(pvalue, &halmac_adapter->txff_allocation, + sizeof(struct halmac_txff_allocation)); + break; + case HALMAC_HW_TX_DESC_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.txdesc_size; + break; + case HALMAC_HW_RX_DESC_SIZE: + *(u32 *)pvalue = halmac_adapter->hw_config_info.rxdesc_size; + break; + default: + return HALMAC_RET_PARA_NOT_SUPPORT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_set_hw_value_88xx() -set hw config value + * @halmac_adapter : the adapter of halmac + * @hw_id : hw id for driver to config + * @pvalue : hw value, reference table to get data type + * Author : KaiYuan Chang / Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_set_hw_value_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_hw_id hw_id, void *pvalue) +{ + void *driver_adapter = NULL; + enum halmac_ret_status status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_HW_VALUE); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + + if (!pvalue) { + pr_err("%s (!pvalue)==========>\n", __func__); + return HALMAC_RET_NULL_POINTER; + } + + switch (hw_id) { + case HALMAC_HW_USB_MODE: + status = halmac_set_usb_mode_88xx( + halmac_adapter, *(enum halmac_usb_mode *)pvalue); + if (status != HALMAC_RET_SUCCESS) + return status; + break; + case HALMAC_HW_SEQ_EN: + break; + case HALMAC_HW_BANDWIDTH: + halmac_cfg_bw_88xx(halmac_adapter, *(enum halmac_bw *)pvalue); + break; + case HALMAC_HW_CHANNEL: + halmac_cfg_ch_88xx(halmac_adapter, *(u8 *)pvalue); + break; + case HALMAC_HW_PRI_CHANNEL_IDX: + halmac_cfg_pri_ch_idx_88xx(halmac_adapter, + *(enum halmac_pri_ch_idx *)pvalue); + break; + case HALMAC_HW_EN_BB_RF: + halmac_enable_bb_rf_88xx(halmac_adapter, *(u8 *)pvalue); + break; + case HALMAC_HW_SDIO_TX_PAGE_THRESHOLD: + halmac_config_sdio_tx_page_threshold_88xx( + halmac_adapter, + (struct halmac_tx_page_threshold_info *)pvalue); + break; + case HALMAC_HW_AMPDU_CONFIG: + halmac_config_ampdu_88xx(halmac_adapter, + (struct halmac_ampdu_config *)pvalue); + break; + default: + return HALMAC_RET_PARA_NOT_SUPPORT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_drv_rsvd_pg_num_88xx() -config reserved page number for driver + * @halmac_adapter : the adapter of halmac + * @pg_num : page number + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_drv_rsvd_pg_num pg_num) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_DRV_RSVD_PG_NUM); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>pg_num = %d\n", __func__, + pg_num); + + switch (pg_num) { + case HALMAC_RSVD_PG_NUM16: + halmac_adapter->txff_allocation.rsvd_drv_pg_num = 16; + break; + case HALMAC_RSVD_PG_NUM24: + halmac_adapter->txff_allocation.rsvd_drv_pg_num = 24; + break; + case HALMAC_RSVD_PG_NUM32: + halmac_adapter->txff_allocation.rsvd_drv_pg_num = 32; + break; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_get_chip_version_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ver *version) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s ==========>\n", __func__); + version->major_ver = (u8)HALMAC_MAJOR_VER_88XX; + version->prototype_ver = (u8)HALMAC_PROTOTYPE_VER_88XX; + version->minor_ver = (u8)HALMAC_MINOR_VER_88XX; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_chk_txdesc_88xx() -check if the tx packet format is incorrect + * @halmac_adapter : the adapter of halmac + * @halmac_buf : tx Packet buffer, tx desc is included + * @halmac_size : tx packet size + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_chk_txdesc_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf, + u32 halmac_size) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (GET_TX_DESC_BMC(halmac_buf)) + if (GET_TX_DESC_AGG_EN(halmac_buf)) + pr_err("TxDesc: Agg should not be set when BMC\n"); + + if (halmac_size < (GET_TX_DESC_TXPKTSIZE(halmac_buf) + + GET_TX_DESC_OFFSET(halmac_buf))) + pr_err("TxDesc: PktSize too small\n"); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_dl_drv_rsvd_page_88xx() - download packet to rsvd page + * @halmac_adapter : the adapter of halmac + * @pg_offset : page offset of driver's rsvd page + * @halmac_buf : data to be downloaded, tx_desc is not included + * @halmac_size : data size to be downloaded + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_dl_drv_rsvd_page_88xx(struct halmac_adapter *halmac_adapter, + u8 pg_offset, u8 *halmac_buf, u32 halmac_size) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status ret_status; + u16 drv_pg_bndy = 0; + u32 dl_pg_num = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DL_DRV_RSVD_PG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + /*check boundary and size valid*/ + dl_pg_num = halmac_size / halmac_adapter->hw_config_info.page_size + + ((halmac_size & + (halmac_adapter->hw_config_info.page_size - 1)) ? + 1 : + 0); + if (pg_offset + dl_pg_num > + halmac_adapter->txff_allocation.rsvd_drv_pg_num) { + pr_err("[ERROR] driver download offset or size error ==========>\n"); + return HALMAC_RET_DRV_DL_ERR; + } + + /*update to target download boundary*/ + drv_pg_bndy = + halmac_adapter->txff_allocation.rsvd_drv_pg_bndy + pg_offset; + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(drv_pg_bndy & BIT_MASK_BCN_HEAD_1_V1)); + + ret_status = halmac_download_rsvd_page_88xx(halmac_adapter, halmac_buf, + halmac_size); + + /*restore to original bundary*/ + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n", + ret_status); + HALMAC_REG_WRITE_16( + halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + return ret_status; + } + + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s < ==========\n", __func__); + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_csi_rate_88xx() - config CSI frame Tx rate + * @halmac_adapter : the adapter of halmac + * @rssi : rssi in decimal value + * @current_rate : current CSI frame rate + * @fixrate_en : enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate + * @new_rate : API returns the final CSI frame rate + * Author : chunchu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_csi_rate_88xx(struct halmac_adapter *halmac_adapter, u8 rssi, + u8 current_rate, u8 fixrate_en, u8 *new_rate) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u32 temp_csi_setting; + u16 current_rrsr; + enum halmac_ret_status ret_status; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_CSI_RATE); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_SND, DBG_DMESG, + "<%s ==========>\n", __func__); + + temp_csi_setting = HALMAC_REG_READ_32(halmac_adapter, REG_BBPSF_CTRL) & + ~(BIT_MASK_WMAC_CSI_RATE << BIT_SHIFT_WMAC_CSI_RATE); + + current_rrsr = HALMAC_REG_READ_16(halmac_adapter, REG_RRSR); + + if (rssi >= 40) { + if (current_rate != HALMAC_OFDM54) { + HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR, + current_rrsr | BIT(HALMAC_OFDM54)); + HALMAC_REG_WRITE_32( + halmac_adapter, REG_BBPSF_CTRL, + temp_csi_setting | + BIT_WMAC_CSI_RATE(HALMAC_OFDM54)); + } + *new_rate = HALMAC_OFDM54; + ret_status = HALMAC_RET_SUCCESS; + } else { + if (current_rate != HALMAC_OFDM24) { + HALMAC_REG_WRITE_16(halmac_adapter, REG_RRSR, + current_rrsr & + ~(BIT(HALMAC_OFDM54))); + HALMAC_REG_WRITE_32( + halmac_adapter, REG_BBPSF_CTRL, + temp_csi_setting | + BIT_WMAC_CSI_RATE(HALMAC_OFDM24)); + } + *new_rate = HALMAC_OFDM24; + ret_status = HALMAC_RET_SUCCESS; + } + + return ret_status; +} + +/** + * halmac_sdio_cmd53_4byte_88xx() - cmd53 only for 4byte len register IO + * @halmac_adapter : the adapter of halmac + * @enable : 1->CMD53 only use in 4byte reg, 0 : No limitation + * Author : Ivan Lin/KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_sdio_cmd53_4byte_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_sdio_cmd53_4byte_mode cmd53_4byte_mode) +{ + halmac_adapter->sdio_cmd53_4byte = cmd53_4byte_mode; + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_txfifo_is_empty_88xx() -check if txfifo is empty + * @halmac_adapter : the adapter of halmac + * Author : Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_txfifo_is_empty_88xx(struct halmac_adapter *halmac_adapter, u32 chk_num) +{ + u32 counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s ==========>\n", __func__); + + counter = (chk_num <= 10) ? 10 : chk_num; + do { + if (HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY) != 0xFF) + return HALMAC_RET_TXFIFO_NO_EMPTY; + + if ((HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY + 1) & + 0x07) != 0x07) + return HALMAC_RET_TXFIFO_NO_EMPTY; + counter--; + + } while (counter != 0); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_COMMON, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.h new file mode 100644 index 000000000000..5debd1ff3abd --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.h @@ -0,0 +1,396 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_88XX_H_ +#define _HALMAC_API_88XX_H_ + +#include "../halmac_2_platform.h" +#include "../halmac_type.h" + +void halmac_init_state_machine_88xx(struct halmac_adapter *halmac_adapter); + +void halmac_init_adapter_para_88xx(struct halmac_adapter *halmac_adapter); + +void halmac_init_adapter_dynamic_para_88xx( + struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_mount_api_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_download_firmware_88xx(struct halmac_adapter *halmac_adapter, + u8 *hamacl_fw, u32 halmac_fw_size); + +enum halmac_ret_status +halmac_free_download_firmware_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_dlfw_mem dlfw_mem, u8 *hamacl_fw, + u32 halmac_fw_size); + +enum halmac_ret_status +halmac_get_fw_version_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fw_version *fw_version); + +enum halmac_ret_status +halmac_cfg_mac_addr_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port, + union halmac_wlan_addr *hal_address); + +enum halmac_ret_status +halmac_cfg_bssid_88xx(struct halmac_adapter *halmac_adapter, u8 halmac_port, + union halmac_wlan_addr *hal_address); + +enum halmac_ret_status +halmac_cfg_multicast_addr_88xx(struct halmac_adapter *halmac_adapter, + union halmac_wlan_addr *hal_address); + +enum halmac_ret_status +halmac_pre_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_init_system_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg halmac_rxagg_cfg); + +enum halmac_ret_status +halmac_init_edca_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_operation_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_wireless_mode wireless_mode); + +enum halmac_ret_status +halmac_cfg_ch_bw_88xx(struct halmac_adapter *halmac_adapter, u8 channel, + enum halmac_pri_ch_idx pri_ch_idx, enum halmac_bw bw); + +enum halmac_ret_status halmac_cfg_ch_88xx(struct halmac_adapter *halmac_adapter, + u8 channel); + +enum halmac_ret_status +halmac_cfg_pri_ch_idx_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_pri_ch_idx pri_ch_idx); + +enum halmac_ret_status halmac_cfg_bw_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_bw bw); + +enum halmac_ret_status +halmac_init_wmac_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_init_mac_cfg_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode mode); + +enum halmac_ret_status +halmac_dump_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg); + +enum halmac_ret_status +halmac_dump_efuse_map_bt_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_bank halmac_efuse_bank, + u32 bt_efuse_map_size, u8 *bt_efuse_map); + +enum halmac_ret_status +halmac_write_efuse_bt_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_value, + enum halmac_efuse_bank halmac_efuse_bank); + +enum halmac_ret_status +halmac_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + enum halmac_efuse_read_cfg cfg); + +enum halmac_ret_status +halmac_get_efuse_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size); + +enum halmac_ret_status +halmac_get_efuse_available_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size); + +enum halmac_ret_status +halmac_get_c2h_info_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf, + u32 halmac_size); + +enum halmac_ret_status +halmac_get_logical_efuse_size_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_size); + +enum halmac_ret_status +halmac_dump_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg); + +enum halmac_ret_status +halmac_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_value); + +enum halmac_ret_status +halmac_read_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 *value); + +enum halmac_ret_status +halmac_cfg_fwlps_option_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwlps_option *lps_option); + +enum halmac_ret_status +halmac_cfg_fwips_option_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwips_option *ips_option); + +enum halmac_ret_status +halmac_enter_wowlan_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_wowlan_option *wowlan_option); + +enum halmac_ret_status +halmac_leave_wowlan_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_enter_ps_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_ps_state ps_state); + +enum halmac_ret_status +halmac_leave_ps_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_h2c_lb_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status halmac_debug_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_parameter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + u8 full_fifo); + +enum halmac_ret_status +halmac_update_packet_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_packet_id pkt_id, u8 *pkt, u32 pkt_size); + +enum halmac_ret_status +halmac_bcn_ie_filter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_bcn_ie_info *bcn_ie_info); + +enum halmac_ret_status +halmac_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *original_h2c, u16 *seq, u8 ack); + +enum halmac_ret_status +halmac_update_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type, + struct halmac_phy_parameter_info *para_info); + +enum halmac_ret_status +halmac_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type); + +enum halmac_ret_status +halmac_cfg_drv_info_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_drv_info halmac_drv_info); + +enum halmac_ret_status +halmac_send_bt_coex_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf, + u32 bt_size, u8 ack); + +enum halmac_ret_status +halmac_verify_platform_api_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_timer_2s_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_fill_txdesc_check_sum_88xx(struct halmac_adapter *halmac_adapter, + u8 *cur_desc); + +enum halmac_ret_status +halmac_dump_fifo_88xx(struct halmac_adapter *halmac_adapter, + enum hal_fifo_sel halmac_fifo_sel, u32 halmac_start_addr, + u32 halmac_fifo_dump_size, u8 *fifo_map); + +u32 halmac_get_fifo_size_88xx(struct halmac_adapter *halmac_adapter, + enum hal_fifo_sel halmac_fifo_sel); + +enum halmac_ret_status +halmac_cfg_txbf_88xx(struct halmac_adapter *halmac_adapter, u8 userid, + enum halmac_bw bw, u8 txbf_en); + +enum halmac_ret_status +halmac_cfg_mumimo_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_cfg_mumimo_para *cfgmu); + +enum halmac_ret_status +halmac_cfg_sounding_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_snd_role role, + enum halmac_data_rate datarate); + +enum halmac_ret_status +halmac_del_sounding_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_snd_role role); + +enum halmac_ret_status +halmac_su_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, u8 userid, + u16 paid); + +enum halmac_ret_status +halmac_su_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_su_bfer_init_para *su_bfer_init); + +enum halmac_ret_status +halmac_mu_bfee_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_mu_bfee_init_para *mu_bfee_init); + +enum halmac_ret_status +halmac_mu_bfer_entry_init_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_mu_bfer_init_para *mu_bfer_init); + +enum halmac_ret_status +halmac_su_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid); + +enum halmac_ret_status +halmac_su_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid); + +enum halmac_ret_status +halmac_mu_bfee_entry_del_88xx(struct halmac_adapter *halmac_adapter, u8 userid); + +enum halmac_ret_status +halmac_mu_bfer_entry_del_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_add_ch_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_info *ch_info); + +enum halmac_ret_status +halmac_add_extra_ch_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_extra_info *ch_extra_info); + +enum halmac_ret_status +halmac_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_switch_option *cs_option); + +enum halmac_ret_status halmac_p2pps_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_p2pps *p2p_ps); + +enum halmac_ret_status +halmac_func_p2pps_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_p2pps *p2p_ps); + +enum halmac_ret_status +halmac_clear_ch_info_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_send_general_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_general_info *general_info); + +enum halmac_ret_status +halmac_start_iqk_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_iqk_para_ *iqk_para); + +enum halmac_ret_status halmac_ctrl_pwr_tracking_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_pwr_tracking_option *pwr_tracking_opt); + +enum halmac_ret_status +halmac_query_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_feature_id feature_id, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size); + +enum halmac_ret_status +halmac_reset_feature_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_feature_id feature_id); + +enum halmac_ret_status +halmac_check_fw_status_88xx(struct halmac_adapter *halmac_adapter, + bool *fw_status); + +enum halmac_ret_status +halmac_dump_fw_dmem_88xx(struct halmac_adapter *halmac_adapter, u8 *dmem, + u32 *size); + +enum halmac_ret_status +halmac_cfg_max_dl_size_88xx(struct halmac_adapter *halmac_adapter, u32 size); + +enum halmac_ret_status halmac_psd_88xx(struct halmac_adapter *halmac_adapter, + u16 start_psd, u16 end_psd); + +enum halmac_ret_status +halmac_cfg_la_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_la_mode la_mode); + +enum halmac_ret_status halmac_cfg_rx_fifo_expanding_mode_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_rx_fifo_expanding_mode rx_fifo_expanding_mode); + +enum halmac_ret_status +halmac_config_security_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_security_setting *sec_setting); + +u8 halmac_get_used_cam_entry_num_88xx(struct halmac_adapter *halmac_adapter, + enum hal_security_type sec_type); + +enum halmac_ret_status +halmac_write_cam_88xx(struct halmac_adapter *halmac_adapter, u32 entry_index, + struct halmac_cam_entry_info *cam_entry_info); + +enum halmac_ret_status +halmac_read_cam_entry_88xx(struct halmac_adapter *halmac_adapter, + u32 entry_index, + struct halmac_cam_entry_format *content); + +enum halmac_ret_status +halmac_clear_cam_entry_88xx(struct halmac_adapter *halmac_adapter, + u32 entry_index); + +enum halmac_ret_status +halmac_get_hw_value_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_hw_id hw_id, void *pvalue); + +enum halmac_ret_status +halmac_set_hw_value_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_hw_id hw_id, void *pvalue); + +enum halmac_ret_status +halmac_cfg_drv_rsvd_pg_num_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_drv_rsvd_pg_num pg_num); + +enum halmac_ret_status +halmac_get_chip_version_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ver *version); + +enum halmac_ret_status +halmac_chk_txdesc_88xx(struct halmac_adapter *halmac_adapter, u8 *halmac_buf, + u32 halmac_size); + +enum halmac_ret_status +halmac_dl_drv_rsvd_page_88xx(struct halmac_adapter *halmac_adapter, + u8 pg_offset, u8 *halmac_buf, u32 halmac_size); + +enum halmac_ret_status +halmac_cfg_csi_rate_88xx(struct halmac_adapter *halmac_adapter, u8 rssi, + u8 current_rate, u8 fixrate_en, u8 *new_rate); + +enum halmac_ret_status halmac_sdio_cmd53_4byte_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_sdio_cmd53_4byte_mode cmd53_4byte_mode); + +enum halmac_ret_status +halmac_txfifo_is_empty_88xx(struct halmac_adapter *halmac_adapter, u32 chk_num); + +#endif /* _HALMAC_API_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.c new file mode 100644 index 000000000000..fa97cac34742 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.c @@ -0,0 +1,329 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_88xx_cfg.h" + +/** + * halmac_init_pcie_cfg_88xx() - init PCIe + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_pcie_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_PCIE_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_deinit_pcie_cfg_88xx() - deinit PCIE + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_deinit_pcie_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEINIT_PCIE_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_rx_aggregation_88xx_pcie() - config rx aggregation + * @halmac_adapter : the adapter of halmac + * @halmac_rx_agg_mode + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_pcie(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_RX_AGGREGATION); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_8_pcie_88xx() - read 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u8 halmac_reg_read_8_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + return PLATFORM_REG_READ_8(driver_adapter, halmac_offset); +} + +/** + * halmac_reg_write_8_pcie_88xx() - write 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_8_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_8(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_16_pcie_88xx() - read 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u16 halmac_reg_read_16_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + return PLATFORM_REG_READ_16(driver_adapter, halmac_offset); +} + +/** + * halmac_reg_write_16_pcie_88xx() - write 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_16_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_16(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_32_pcie_88xx() - read 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u32 halmac_reg_read_32_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + return PLATFORM_REG_READ_32(driver_adapter, halmac_offset); +} + +/** + * halmac_reg_write_32_pcie_88xx() - write 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_32_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_32(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_tx_agg_align_pcie_88xx() -config sdio bus tx agg alignment + * @halmac_adapter : the adapter of halmac + * @enable : function enable(1)/disable(0) + * @align_size : sdio bus tx agg alignment size (2^n, n = 3~11) + * Author : Soar Tu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_cfg_tx_agg_align_pcie_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size) +{ + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s not support\n", __func__); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.h new file mode 100644 index 000000000000..34969fc5c03e --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_pcie.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_88XX_PCIE_H_ +#define _HALMAC_API_88XX_PCIE_H_ + +#include "../halmac_2_platform.h" +#include "../halmac_type.h" + +#define LINK_CTRL2_REG_OFFSET 0xA0 +#define GEN2_CTRL_OFFSET 0x80C +#define LINK_STATUS_REG_OFFSET 0x82 +#define GEN1_SPEED 0x01 +#define GEN2_SPEED 0x02 + +enum halmac_ret_status +halmac_init_pcie_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_deinit_pcie_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_pcie(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg); + +u8 halmac_reg_read_8_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_8_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data); + +u16 halmac_reg_read_16_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_16_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data); + +u32 halmac_reg_read_32_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_32_pcie_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data); + +enum halmac_ret_status halmac_cfg_tx_agg_align_pcie_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size); + +#endif /* _HALMAC_API_88XX_PCIE_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.c new file mode 100644 index 000000000000..69b26a5a3cf3 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.c @@ -0,0 +1,974 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_88xx_cfg.h" + +/** + * halmac_init_sdio_cfg_88xx() - init SDIO + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_SDIO_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_REG_READ_32(halmac_adapter, REG_SDIO_FREE_TXPG); + HALMAC_REG_WRITE_32(halmac_adapter, REG_SDIO_TX_CTRL, 0x00000000); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_deinit_sdio_cfg_88xx() - deinit SDIO + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_deinit_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEINIT_SDIO_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_rx_aggregation_88xx_sdio() - config rx aggregation + * @halmac_adapter : the adapter of halmac + * @halmac_rx_agg_mode + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_sdio(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg) +{ + u8 value8; + u8 size = 0, timeout = 0, agg_enable = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_RX_AGGREGATION); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + agg_enable = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP); + + switch (phalmac_rxagg_cfg->mode) { + case HALMAC_RX_AGG_MODE_NONE: + agg_enable &= ~(BIT_RXDMA_AGG_EN); + break; + case HALMAC_RX_AGG_MODE_DMA: + case HALMAC_RX_AGG_MODE_USB: + agg_enable |= BIT_RXDMA_AGG_EN; + break; + default: + pr_err("halmac_cfg_rx_aggregation_88xx_usb switch case not support\n"); + agg_enable &= ~BIT_RXDMA_AGG_EN; + break; + } + + if (!phalmac_rxagg_cfg->threshold.drv_define) { + size = 0xFF; + timeout = 0x01; + } else { + size = phalmac_rxagg_cfg->threshold.size; + timeout = phalmac_rxagg_cfg->threshold.timeout; + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP, agg_enable); + HALMAC_REG_WRITE_16(halmac_adapter, REG_RXDMA_AGG_PG_TH, + (u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO))); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RXDMA_MODE); + if ((agg_enable & BIT_RXDMA_AGG_EN) != 0) + HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_MODE, + value8 | BIT_DMA_MODE); + else + HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_MODE, + value8 & ~(BIT_DMA_MODE)); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_8_sdio_88xx() - read 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u8 halmac_reg_read_8_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + u8 value8; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + value8 = PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset); + + return value8; +} + +/** + * halmac_reg_write_8_sdio_88xx() - write 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_8_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_16_sdio_88xx() - read 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u16 halmac_reg_read_16_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + union { + u16 word; + u8 byte[2]; + __le16 le_word; + } value16 = {0x0000}; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF || + (halmac_offset & (2 - 1)) != 0 || + halmac_adapter->sdio_cmd53_4byte == + HALMAC_SDIO_CMD53_4BYTE_MODE_RW || + halmac_adapter->sdio_cmd53_4byte == + HALMAC_SDIO_CMD53_4BYTE_MODE_R) { + value16.byte[0] = + PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset); + value16.byte[1] = PLATFORM_SDIO_CMD52_READ(driver_adapter, + halmac_offset + 1); + value16.word = le16_to_cpu(value16.le_word); + } else { +#if (PLATFORM_SD_CLK > HALMAC_SD_CLK_THRESHOLD_88XX) + if ((halmac_offset & 0xffffef00) == 0x00000000) { + value16.byte[0] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset); + value16.byte[1] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset + 1); + value16.word = le16_to_cpu(value16.word); + } else { + value16.word = PLATFORM_SDIO_CMD53_READ_16( + driver_adapter, halmac_offset); + } +#else + value16.word = PLATFORM_SDIO_CMD53_READ_16(driver_adapter, + halmac_offset); +#endif + } + + return value16.word; +} + +/** + * halmac_reg_write_16_sdio_88xx() - write 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_16_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF || + (halmac_offset & (2 - 1)) != 0 || + halmac_adapter->sdio_cmd53_4byte == + HALMAC_SDIO_CMD53_4BYTE_MODE_RW || + halmac_adapter->sdio_cmd53_4byte == + HALMAC_SDIO_CMD53_4BYTE_MODE_W) { + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, + (u8)(halmac_data & 0xFF)); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 1, + (u8)((halmac_data & 0xFF00) >> 8)); + } else { + PLATFORM_SDIO_CMD53_WRITE_16(driver_adapter, halmac_offset, + halmac_data); + } + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_32_sdio_88xx() - read 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u32 halmac_reg_read_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + u32 halmac_offset_old = 0; + + union { + u32 dword; + u8 byte[4]; + __le32 le_dword; + } value32 = {0x00000000}; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + halmac_offset_old = halmac_offset; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF || + (halmac_offset & (4 - 1)) != 0) { + value32.byte[0] = + PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset); + value32.byte[1] = PLATFORM_SDIO_CMD52_READ(driver_adapter, + halmac_offset + 1); + value32.byte[2] = PLATFORM_SDIO_CMD52_READ(driver_adapter, + halmac_offset + 2); + value32.byte[3] = PLATFORM_SDIO_CMD52_READ(driver_adapter, + halmac_offset + 3); + value32.dword = le32_to_cpu(value32.le_dword); + } else { +#if (PLATFORM_SD_CLK > HALMAC_SD_CLK_THRESHOLD_88XX) + if ((halmac_offset_old & 0xffffef00) == 0x00000000) { + value32.byte[0] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset); + value32.byte[1] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset + 1); + value32.byte[2] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset + 2); + value32.byte[3] = PLATFORM_SDIO_CMD52_READ( + driver_adapter, halmac_offset + 3); + value32.dword = le32_to_cpu(value32.dword); + } else { + value32.dword = PLATFORM_SDIO_CMD53_READ_32( + driver_adapter, halmac_offset); + } +#else + value32.dword = PLATFORM_SDIO_CMD53_READ_32(driver_adapter, + halmac_offset); +#endif + } + + return value32.dword; +} + +/** + * halmac_reg_write_32_sdio_88xx() - write 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF || + (halmac_offset & (4 - 1)) != 0) { + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, + (u8)(halmac_data & 0xFF)); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 1, + (u8)((halmac_data & 0xFF00) >> 8)); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 2, + (u8)((halmac_data & 0xFF0000) >> 16)); + PLATFORM_SDIO_CMD52_WRITE( + driver_adapter, halmac_offset + 3, + (u8)((halmac_data & 0xFF000000) >> 24)); + } else { + PLATFORM_SDIO_CMD53_WRITE_32(driver_adapter, halmac_offset, + halmac_data); + } + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_nbyte_sdio_88xx() - read n byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_size : register value size + * @halmac_data : register value + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u8 halmac_reg_read_nbyte_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_size, + u8 *halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if ((halmac_offset & 0xFFFF0000) == 0) { + pr_err("halmac_offset error = 0x%x\n", halmac_offset); + return HALMAC_RET_FAIL; + } + + status = halmac_convert_to_sdio_bus_offset_88xx(halmac_adapter, + &halmac_offset); + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s error = %x\n", __func__, status); + return status; + } + + if (halmac_adapter->halmac_state.mac_power == HALMAC_MAC_POWER_OFF) { + pr_err("halmac_state error = 0x%x\n", + halmac_adapter->halmac_state.mac_power); + return HALMAC_RET_FAIL; + } + + PLATFORM_SDIO_CMD53_READ_N(driver_adapter, halmac_offset, halmac_size, + halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_sdio_tx_addr_sdio_88xx() - get CMD53 addr for the TX packet + * @halmac_adapter : the adapter of halmac + * @halmac_buf : tx packet, include txdesc + * @halmac_size : tx packet size + * @pcmd53_addr : cmd53 addr value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_sdio_tx_addr_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size, u32 *pcmd53_addr) +{ + u32 four_byte_len; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_queue_select queue_sel; + enum halmac_dma_mapping dma_mapping; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_GET_SDIO_TX_ADDR); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (!halmac_buf) { + pr_err("halmac_buf is NULL!!\n"); + return HALMAC_RET_DATA_BUF_NULL; + } + + if (halmac_size == 0) { + pr_err("halmac_size is 0!!\n"); + return HALMAC_RET_DATA_SIZE_INCORRECT; + } + + queue_sel = (enum halmac_queue_select)GET_TX_DESC_QSEL(halmac_buf); + + switch (queue_sel) { + case HALMAC_QUEUE_SELECT_VO: + case HALMAC_QUEUE_SELECT_VO_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO]; + break; + case HALMAC_QUEUE_SELECT_VI: + case HALMAC_QUEUE_SELECT_VI_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI]; + break; + case HALMAC_QUEUE_SELECT_BE: + case HALMAC_QUEUE_SELECT_BE_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE]; + break; + case HALMAC_QUEUE_SELECT_BK: + case HALMAC_QUEUE_SELECT_BK_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK]; + break; + case HALMAC_QUEUE_SELECT_MGNT: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG]; + break; + case HALMAC_QUEUE_SELECT_HIGH: + case HALMAC_QUEUE_SELECT_BCN: + case HALMAC_QUEUE_SELECT_CMD: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI]; + break; + default: + pr_err("Qsel is out of range\n"); + return HALMAC_RET_QSEL_INCORRECT; + } + + four_byte_len = (halmac_size >> 2) + ((halmac_size & (4 - 1)) ? 1 : 0); + + switch (dma_mapping) { + case HALMAC_DMA_MAPPING_HIGH: + *pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_HIGH; + break; + case HALMAC_DMA_MAPPING_NORMAL: + *pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_NORMAL; + break; + case HALMAC_DMA_MAPPING_LOW: + *pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_LOW; + break; + case HALMAC_DMA_MAPPING_EXTRA: + *pcmd53_addr = HALMAC_SDIO_CMD_ADDR_TXFF_EXTRA; + break; + default: + pr_err("DmaMapping is out of range\n"); + return HALMAC_RET_DMA_MAP_INCORRECT; + } + + *pcmd53_addr = (*pcmd53_addr << 13) | + (four_byte_len & HALMAC_SDIO_4BYTE_LEN_MASK); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_tx_agg_align_sdio_88xx() -config sdio bus tx agg alignment + * @halmac_adapter : the adapter of halmac + * @enable : function enable(1)/disable(0) + * @align_size : sdio bus tx agg alignment size (2^n, n = 3~11) + * Author : Soar Tu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_tx_agg_align_sdio_88xx(struct halmac_adapter *halmac_adapter, + u8 enable, u16 align_size) +{ + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + u8 i, align_size_ok = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if ((align_size & 0xF000) != 0) { + pr_err("Align size is out of range\n"); + return HALMAC_RET_FAIL; + } + + for (i = 3; i <= 11; i++) { + if (align_size == 1 << i) { + align_size_ok = 1; + break; + } + } + if (align_size_ok == 0) { + pr_err("Align size is not 2^3 ~ 2^11\n"); + return HALMAC_RET_FAIL; + } + + /*Keep sdio tx agg alignment size for driver query*/ + halmac_adapter->hw_config_info.tx_align_size = align_size; + + if (enable) + HALMAC_REG_WRITE_16(halmac_adapter, REG_RQPN_CTRL_2, + 0x8000 | align_size); + else + HALMAC_REG_WRITE_16(halmac_adapter, REG_RQPN_CTRL_2, + align_size); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_cfg_tx_agg_align_sdio_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size) +{ + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s not support\n", __func__); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_tx_allowed_sdio_88xx() - check tx status + * @halmac_adapter : the adapter of halmac + * @halmac_buf : tx packet, include txdesc + * @halmac_size : tx packet size, include txdesc + * Author : Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_tx_allowed_sdio_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size) +{ + u8 *curr_packet; + u16 *curr_free_space; + u32 i, counter; + u32 tx_agg_num, packet_size = 0; + u32 tx_required_page_num, total_required_page_num = 0; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + void *driver_adapter = NULL; + enum halmac_dma_mapping dma_mapping; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_TX_ALLOWED_SDIO); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + tx_agg_num = GET_TX_DESC_DMA_TXAGG_NUM(halmac_buf); + curr_packet = halmac_buf; + + tx_agg_num = tx_agg_num == 0 ? 1 : tx_agg_num; + + switch ((enum halmac_queue_select)GET_TX_DESC_QSEL(curr_packet)) { + case HALMAC_QUEUE_SELECT_VO: + case HALMAC_QUEUE_SELECT_VO_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO]; + break; + case HALMAC_QUEUE_SELECT_VI: + case HALMAC_QUEUE_SELECT_VI_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI]; + break; + case HALMAC_QUEUE_SELECT_BE: + case HALMAC_QUEUE_SELECT_BE_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE]; + break; + case HALMAC_QUEUE_SELECT_BK: + case HALMAC_QUEUE_SELECT_BK_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK]; + break; + case HALMAC_QUEUE_SELECT_MGNT: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG]; + break; + case HALMAC_QUEUE_SELECT_HIGH: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI]; + break; + case HALMAC_QUEUE_SELECT_BCN: + case HALMAC_QUEUE_SELECT_CMD: + return HALMAC_RET_SUCCESS; + default: + pr_err("Qsel is out of range\n"); + return HALMAC_RET_QSEL_INCORRECT; + } + + switch (dma_mapping) { + case HALMAC_DMA_MAPPING_HIGH: + curr_free_space = + &halmac_adapter->sdio_free_space.high_queue_number; + break; + case HALMAC_DMA_MAPPING_NORMAL: + curr_free_space = + &halmac_adapter->sdio_free_space.normal_queue_number; + break; + case HALMAC_DMA_MAPPING_LOW: + curr_free_space = + &halmac_adapter->sdio_free_space.low_queue_number; + break; + case HALMAC_DMA_MAPPING_EXTRA: + curr_free_space = + &halmac_adapter->sdio_free_space.extra_queue_number; + break; + default: + pr_err("DmaMapping is out of range\n"); + return HALMAC_RET_DMA_MAP_INCORRECT; + } + + for (i = 0; i < tx_agg_num; i++) { + packet_size = GET_TX_DESC_TXPKTSIZE(curr_packet) + + GET_TX_DESC_OFFSET(curr_packet) + + (GET_TX_DESC_PKT_OFFSET(curr_packet) << 3); + tx_required_page_num = + (packet_size >> + halmac_adapter->hw_config_info.page_size_2_power) + + ((packet_size & + (halmac_adapter->hw_config_info.page_size - 1)) ? + 1 : + 0); + total_required_page_num += tx_required_page_num; + + packet_size = HALMAC_ALIGN(packet_size, 8); + + curr_packet += packet_size; + } + + counter = 10; + do { + if ((u32)(*curr_free_space + + halmac_adapter->sdio_free_space.public_queue_number) > + total_required_page_num) { + if (*curr_free_space >= total_required_page_num) { + *curr_free_space -= + (u16)total_required_page_num; + } else { + halmac_adapter->sdio_free_space + .public_queue_number -= + (u16)(total_required_page_num - + *curr_free_space); + *curr_free_space = 0; + } + + status = halmac_check_oqt_88xx(halmac_adapter, + tx_agg_num, halmac_buf); + + if (status != HALMAC_RET_SUCCESS) + return status; + + break; + } + + halmac_update_sdio_free_page_88xx(halmac_adapter); + + counter--; + if (counter == 0) + return HALMAC_RET_FREE_SPACE_NOT_ENOUGH; + } while (1); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_indirect_32_sdio_88xx() - read MAC reg by SDIO reg + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : Soar + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u32 halmac_reg_read_indirect_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + u8 rtemp; + u32 counter = 1000; + void *driver_adapter = NULL; + + union { + u32 dword; + u8 byte[4]; + } value32 = {0x00000000}; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + + PLATFORM_SDIO_CMD53_WRITE_32( + driver_adapter, + (HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) | + (REG_SDIO_INDIRECT_REG_CFG & HALMAC_SDIO_LOCAL_MSK), + halmac_offset | BIT(19) | BIT(17)); + + do { + rtemp = PLATFORM_SDIO_CMD52_READ( + driver_adapter, + (HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) | + ((REG_SDIO_INDIRECT_REG_CFG + 2) & + HALMAC_SDIO_LOCAL_MSK)); + counter--; + } while ((rtemp & BIT(4)) != 0 && counter > 0); + + value32.dword = PLATFORM_SDIO_CMD53_READ_32( + driver_adapter, + (HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) | + (REG_SDIO_INDIRECT_REG_DATA & HALMAC_SDIO_LOCAL_MSK)); + + return value32.dword; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.h new file mode 100644 index 000000000000..ee441eee24d6 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_sdio.h @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_88XX_SDIO_H_ +#define _HALMAC_API_88XX_SDIO_H_ + +#include "../halmac_2_platform.h" +#include "../halmac_type.h" + +enum halmac_ret_status +halmac_init_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_deinit_sdio_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_sdio(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg); + +u8 halmac_reg_read_8_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_8_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data); + +u16 halmac_reg_read_16_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_16_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data); + +u32 halmac_reg_read_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data); + +enum halmac_ret_status +halmac_get_sdio_tx_addr_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size, u32 *pcmd53_addr); + +enum halmac_ret_status +halmac_cfg_tx_agg_align_sdio_88xx(struct halmac_adapter *halmac_adapter, + u8 enable, u16 align_size); + +enum halmac_ret_status halmac_cfg_tx_agg_align_sdio_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size); + +enum halmac_ret_status +halmac_tx_allowed_sdio_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size); + +u32 halmac_reg_read_indirect_32_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +u8 halmac_reg_read_nbyte_sdio_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_size, + u8 *halmac_data); + +#endif /* _HALMAC_API_88XX_SDIO_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.c new file mode 100644 index 000000000000..17d7c3cc62ec --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.c @@ -0,0 +1,554 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_88xx_cfg.h" + +/** + * halmac_init_usb_cfg_88xx() - init USB + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_init_usb_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + u8 value8 = 0; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_USB_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + value8 |= (BIT_DMA_MODE | + (0x3 << BIT_SHIFT_BURST_CNT)); /* burst number = 4 */ + + if (PLATFORM_REG_READ_8(driver_adapter, REG_SYS_CFG2 + 3) == + 0x20) { /* usb3.0 */ + value8 |= (HALMAC_USB_BURST_SIZE_3_0 << BIT_SHIFT_BURST_SIZE); + } else { + if ((PLATFORM_REG_READ_8(driver_adapter, REG_USB_USBSTAT) & + 0x3) == 0x1) /* usb2.0 */ + value8 |= HALMAC_USB_BURST_SIZE_2_0_HSPEED + << BIT_SHIFT_BURST_SIZE; + else /* usb1.1 */ + value8 |= HALMAC_USB_BURST_SIZE_2_0_FSPEED + << BIT_SHIFT_BURST_SIZE; + } + + PLATFORM_REG_WRITE_8(driver_adapter, REG_RXDMA_MODE, value8); + PLATFORM_REG_WRITE_16( + driver_adapter, REG_TXDMA_OFFSET_CHK, + PLATFORM_REG_READ_16(driver_adapter, REG_TXDMA_OFFSET_CHK) | + BIT_DROP_DATA_EN); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_deinit_usb_cfg_88xx() - deinit USB + * @halmac_adapter : the adapter of halmac + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_deinit_usb_cfg_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEINIT_USB_CFG); + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_rx_aggregation_88xx_usb() - config rx aggregation + * @halmac_adapter : the adapter of halmac + * @halmac_rx_agg_mode + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_usb(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg) +{ + u8 dma_usb_agg; + u8 size = 0, timeout = 0, agg_enable = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_CFG_RX_AGGREGATION); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + dma_usb_agg = + HALMAC_REG_READ_8(halmac_adapter, REG_RXDMA_AGG_PG_TH + 3); + agg_enable = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP); + + switch (phalmac_rxagg_cfg->mode) { + case HALMAC_RX_AGG_MODE_NONE: + agg_enable &= ~BIT_RXDMA_AGG_EN; + break; + case HALMAC_RX_AGG_MODE_DMA: + agg_enable |= BIT_RXDMA_AGG_EN; + dma_usb_agg |= BIT(7); + break; + + case HALMAC_RX_AGG_MODE_USB: + agg_enable |= BIT_RXDMA_AGG_EN; + dma_usb_agg &= ~BIT(7); + break; + default: + pr_err("%s switch case not support\n", __func__); + agg_enable &= ~BIT_RXDMA_AGG_EN; + break; + } + + if (!phalmac_rxagg_cfg->threshold.drv_define) { + if (PLATFORM_REG_READ_8(driver_adapter, REG_SYS_CFG2 + 3) == + 0x20) { + /* usb3.0 */ + size = 0x5; + timeout = 0xA; + } else { + /* usb2.0 */ + size = 0x5; + timeout = 0x20; + } + } else { + size = phalmac_rxagg_cfg->threshold.size; + timeout = phalmac_rxagg_cfg->threshold.timeout; + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP, agg_enable); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_AGG_PG_TH + 3, + dma_usb_agg); + HALMAC_REG_WRITE_16(halmac_adapter, REG_RXDMA_AGG_PG_TH, + (u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO))); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_8_usb_88xx() - read 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u8 halmac_reg_read_8_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + u8 value8; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + value8 = PLATFORM_REG_READ_8(driver_adapter, halmac_offset); + + return value8; +} + +/** + * halmac_reg_write_8_usb_88xx() - write 1byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_8_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_8(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_16_usb_88xx() - read 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u16 halmac_reg_read_16_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + union { + u16 word; + u8 byte[2]; + } value16 = {0x0000}; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + value16.word = PLATFORM_REG_READ_16(driver_adapter, halmac_offset); + + return value16.word; +} + +/** + * halmac_reg_write_16_usb_88xx() - write 2byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_16_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_16(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_reg_read_32_usb_88xx() - read 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +u32 halmac_reg_read_32_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + union { + u32 dword; + u8 byte[4]; + } value32 = {0x00000000}; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + value32.dword = PLATFORM_REG_READ_32(driver_adapter, halmac_offset); + + return value32.dword; +} + +/** + * halmac_reg_write_32_usb_88xx() - write 4byte register + * @halmac_adapter : the adapter of halmac + * @halmac_offset : register offset + * @halmac_data : register value + * Author : KaiYuan Chang/Ivan Lin + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_reg_write_32_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + PLATFORM_REG_WRITE_32(driver_adapter, halmac_offset, halmac_data); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_set_bulkout_num_usb_88xx() - inform bulk-out num + * @halmac_adapter : the adapter of halmac + * @bulkout_num : usb bulk-out number + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_set_bulkout_num_88xx(struct halmac_adapter *halmac_adapter, + u8 bulkout_num) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SET_BULKOUT_NUM); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + halmac_adapter->halmac_bulkout_num = bulkout_num; + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_get_usb_bulkout_id_usb_88xx() - get bulk out id for the TX packet + * @halmac_adapter : the adapter of halmac + * @halmac_buf : tx packet, include txdesc + * @halmac_size : tx packet size + * @bulkout_id : usb bulk-out id + * Author : KaiYuan Chang + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status +halmac_get_usb_bulkout_id_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size, u8 *bulkout_id) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_queue_select queue_sel; + enum halmac_dma_mapping dma_mapping; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, + HALMAC_API_GET_USB_BULKOUT_ID); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + if (!halmac_buf) { + pr_err("halmac_buf is NULL!!\n"); + return HALMAC_RET_DATA_BUF_NULL; + } + + if (halmac_size == 0) { + pr_err("halmac_size is 0!!\n"); + return HALMAC_RET_DATA_SIZE_INCORRECT; + } + + queue_sel = (enum halmac_queue_select)GET_TX_DESC_QSEL(halmac_buf); + + switch (queue_sel) { + case HALMAC_QUEUE_SELECT_VO: + case HALMAC_QUEUE_SELECT_VO_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO]; + break; + case HALMAC_QUEUE_SELECT_VI: + case HALMAC_QUEUE_SELECT_VI_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI]; + break; + case HALMAC_QUEUE_SELECT_BE: + case HALMAC_QUEUE_SELECT_BE_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE]; + break; + case HALMAC_QUEUE_SELECT_BK: + case HALMAC_QUEUE_SELECT_BK_V2: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK]; + break; + case HALMAC_QUEUE_SELECT_MGNT: + dma_mapping = + halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG]; + break; + case HALMAC_QUEUE_SELECT_HIGH: + case HALMAC_QUEUE_SELECT_BCN: + case HALMAC_QUEUE_SELECT_CMD: + dma_mapping = HALMAC_DMA_MAPPING_HIGH; + break; + default: + pr_err("Qsel is out of range\n"); + return HALMAC_RET_QSEL_INCORRECT; + } + + switch (dma_mapping) { + case HALMAC_DMA_MAPPING_HIGH: + *bulkout_id = 0; + break; + case HALMAC_DMA_MAPPING_NORMAL: + *bulkout_id = 1; + break; + case HALMAC_DMA_MAPPING_LOW: + *bulkout_id = 2; + break; + case HALMAC_DMA_MAPPING_EXTRA: + *bulkout_id = 3; + break; + default: + pr_err("DmaMapping is out of range\n"); + return HALMAC_RET_DMA_MAP_INCORRECT; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +/** + * halmac_cfg_tx_agg_align_usb_88xx() -config sdio bus tx agg alignment + * @halmac_adapter : the adapter of halmac + * @enable : function enable(1)/disable(0) + * @align_size : sdio bus tx agg alignment size (2^n, n = 3~11) + * Author : Soar Tu + * Return : enum halmac_ret_status + * More details of status code can be found in prototype document + */ +enum halmac_ret_status halmac_cfg_tx_agg_align_usb_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size) +{ + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + + if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_ADAPTER_INVALID; + + if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS) + return HALMAC_RET_API_INVALID; + + halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s not support\n", __func__); + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.h new file mode 100644 index 000000000000..a3d2a6abd91b --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx_usb.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_API_88XX_USB_H_ +#define _HALMAC_API_88XX_USB_H_ + +#include "../halmac_2_platform.h" +#include "../halmac_type.h" + +enum halmac_ret_status +halmac_init_usb_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_deinit_usb_cfg_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_cfg_rx_aggregation_88xx_usb(struct halmac_adapter *halmac_adapter, + struct halmac_rxagg_cfg *phalmac_rxagg_cfg); + +u8 halmac_reg_read_8_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_8_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u8 halmac_data); + +u16 halmac_reg_read_16_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_16_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u16 halmac_data); + +u32 halmac_reg_read_32_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset); + +enum halmac_ret_status +halmac_reg_write_32_usb_88xx(struct halmac_adapter *halmac_adapter, + u32 halmac_offset, u32 halmac_data); + +enum halmac_ret_status +halmac_set_bulkout_num_88xx(struct halmac_adapter *halmac_adapter, + u8 bulkout_num); + +enum halmac_ret_status +halmac_get_usb_bulkout_id_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size, u8 *bulkout_id); + +enum halmac_ret_status halmac_cfg_tx_agg_align_usb_not_support_88xx( + struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size); + +#endif /* _HALMAC_API_88XX_USB_H_ */ diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c new file mode 100644 index 000000000000..f33024e4d853 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c @@ -0,0 +1,4494 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#include "halmac_88xx_cfg.h" + +static enum halmac_ret_status +halmac_dump_efuse_fw_88xx(struct halmac_adapter *halmac_adapter); + +static enum halmac_ret_status +halmac_dump_efuse_drv_88xx(struct halmac_adapter *halmac_adapter); + +static enum halmac_ret_status +halmac_update_eeprom_mask_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated); + +static enum halmac_ret_status +halmac_check_efuse_enough_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated); + +static enum halmac_ret_status +halmac_program_efuse_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated); + +static enum halmac_ret_status +halmac_pwr_sub_seq_parer_88xx(struct halmac_adapter *halmac_adapter, u8 cut, + u8 fab, u8 intf, + struct halmac_wl_pwr_cfg_ *pwr_sub_seq_cfg); + +static enum halmac_ret_status +halmac_parse_c2h_debug_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_scan_status_rpt_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_psd_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_efuse_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size); + +static enum halmac_ret_status +halmac_enqueue_para_buff_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + u8 *curr_buff_wptr, bool *end_cmd); + +static enum halmac_ret_status +halmac_parse_h2c_ack_phy_efuse_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_cfg_para_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_gen_cfg_para_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *h2c_buff); + +static enum halmac_ret_status +halmac_parse_h2c_ack_update_packet_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_update_datapack_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_channel_switch_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_iqk_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +static enum halmac_ret_status +halmac_parse_h2c_ack_power_tracking_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size); + +void halmac_init_offload_feature_state_machine_88xx( + struct halmac_adapter *halmac_adapter) +{ + struct halmac_state *state = &halmac_adapter->halmac_state; + + state->efuse_state_set.efuse_cmd_construct_state = + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE; + state->efuse_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->efuse_state_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->cfg_para_state_set.cfg_para_cmd_construct_state = + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE; + state->cfg_para_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->cfg_para_state_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->scan_state_set.scan_cmd_construct_state = + HALMAC_SCAN_CMD_CONSTRUCT_IDLE; + state->scan_state_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->scan_state_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->update_packet_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->update_packet_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->iqk_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->iqk_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->power_tracking_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->power_tracking_set.seq_num = halmac_adapter->h2c_packet_seq; + + state->psd_set.process_status = HALMAC_CMD_PROCESS_IDLE; + state->psd_set.seq_num = halmac_adapter->h2c_packet_seq; + state->psd_set.data_size = 0; + state->psd_set.segment_size = 0; + state->psd_set.data = NULL; +} + +enum halmac_ret_status +halmac_dump_efuse_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg) +{ + u32 chk_h2c_init; + void *driver_adapter = NULL; + struct halmac_api *halmac_api = + (struct halmac_api *)halmac_adapter->halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.efuse_state_set.process_status; + + driver_adapter = halmac_adapter->driver_adapter; + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_H2C_SENT) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + if (cfg == HALMAC_EFUSE_R_AUTO) { + chk_h2c_init = HALMAC_REG_READ_32(halmac_adapter, + REG_H2C_PKT_READADDR); + if (halmac_adapter->halmac_state.dlfw_state == + HALMAC_DLFW_NONE || + chk_h2c_init == 0) + status = halmac_dump_efuse_drv_88xx(halmac_adapter); + else + status = halmac_dump_efuse_fw_88xx(halmac_adapter); + } else if (cfg == HALMAC_EFUSE_R_FW) { + status = halmac_dump_efuse_fw_88xx(halmac_adapter); + } else { + status = halmac_dump_efuse_drv_88xx(halmac_adapter); + } + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_read_efuse error = %x\n", status); + return status; + } + + return status; +} + +enum halmac_ret_status +halmac_func_read_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, u8 *efuse_map) +{ + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + if (!efuse_map) { + pr_err("Malloc for dump efuse map error\n"); + return HALMAC_RET_NULL_POINTER; + } + + if (halmac_adapter->hal_efuse_map_valid) + memcpy(efuse_map, halmac_adapter->hal_efuse_map + offset, size); + else if (halmac_read_hw_efuse_88xx(halmac_adapter, offset, size, + efuse_map) != HALMAC_RET_SUCCESS) + return HALMAC_RET_EFUSE_R_FAIL; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_read_hw_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, u8 *efuse_map) +{ + u8 value8; + u32 value32; + u32 address; + u32 tmp32, counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + /* Read efuse no need 2.5V LDO */ + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3); + if (value8 & BIT(7)) + HALMAC_REG_WRITE_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3, + (u8)(value8 & ~(BIT(7)))); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL); + + for (address = offset; address < offset + size; address++) { + value32 = value32 & + ~((BIT_MASK_EF_DATA) | + (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR)); + value32 = value32 | + ((address & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR); + HALMAC_REG_WRITE_32(halmac_adapter, REG_EFUSE_CTRL, + value32 & (~BIT_EF_FLAG)); + + counter = 1000000; + do { + udelay(1); + tmp32 = HALMAC_REG_READ_32(halmac_adapter, + REG_EFUSE_CTRL); + counter--; + if (counter == 0) { + pr_err("HALMAC_RET_EFUSE_R_FAIL\n"); + return HALMAC_RET_EFUSE_R_FAIL; + } + } while ((tmp32 & BIT_EF_FLAG) == 0); + + *(efuse_map + address - offset) = + (u8)(tmp32 & BIT_MASK_EF_DATA); + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_dump_efuse_drv_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 *efuse_map = NULL; + u32 efuse_size; + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + efuse_size = halmac_adapter->hw_config_info.efuse_size; + + if (!halmac_adapter->hal_efuse_map) { + halmac_adapter->hal_efuse_map = kzalloc(efuse_size, GFP_KERNEL); + if (!halmac_adapter->hal_efuse_map) { + pr_err("[ERR]halmac allocate efuse map Fail!!\n"); + return HALMAC_RET_MALLOC_FAIL; + } + } + + efuse_map = kzalloc(efuse_size, GFP_KERNEL); + if (!efuse_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + + if (halmac_read_hw_efuse_88xx(halmac_adapter, 0, efuse_size, + efuse_map) != HALMAC_RET_SUCCESS) { + kfree(efuse_map); + return HALMAC_RET_EFUSE_R_FAIL; + } + + spin_lock(&halmac_adapter->efuse_lock); + memcpy(halmac_adapter->hal_efuse_map, efuse_map, efuse_size); + halmac_adapter->hal_efuse_map_valid = true; + spin_unlock(&halmac_adapter->efuse_lock); + + kfree(efuse_map); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_dump_efuse_fw_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_DUMP_PHYSICAL_EFUSE; + h2c_header_info.content_size = 0; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + halmac_adapter->halmac_state.efuse_state_set.seq_num = h2c_seq_mum; + + if (!halmac_adapter->hal_efuse_map) { + halmac_adapter->hal_efuse_map = kzalloc( + halmac_adapter->hw_config_info.efuse_size, GFP_KERNEL); + if (!halmac_adapter->hal_efuse_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + } + + if (!halmac_adapter->hal_efuse_map_valid) { + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, + true); + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_read_efuse_fw Fail = %x!!\n", status); + return status; + } + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_write_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u8 value) +{ + const u8 wite_protect_code = 0x69; + u32 value32, tmp32, counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + spin_lock(&halmac_adapter->efuse_lock); + halmac_adapter->hal_efuse_map_valid = false; + spin_unlock(&halmac_adapter->efuse_lock); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PMC_DBG_CTRL2 + 3, + wite_protect_code); + + /* Enable 2.5V LDO */ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_LDO_EFUSE_CTRL + 3, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3) | + BIT(7))); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL); + value32 = + value32 & + ~((BIT_MASK_EF_DATA) | (BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR)); + value32 = value32 | ((offset & BIT_MASK_EF_ADDR) << BIT_SHIFT_EF_ADDR) | + (value & BIT_MASK_EF_DATA); + HALMAC_REG_WRITE_32(halmac_adapter, REG_EFUSE_CTRL, + value32 | BIT_EF_FLAG); + + counter = 1000000; + do { + udelay(1); + tmp32 = HALMAC_REG_READ_32(halmac_adapter, REG_EFUSE_CTRL); + counter--; + if (counter == 0) { + pr_err("halmac_write_efuse Fail !!\n"); + return HALMAC_RET_EFUSE_W_FAIL; + } + } while ((tmp32 & BIT_EF_FLAG) == BIT_EF_FLAG); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PMC_DBG_CTRL2 + 3, 0x00); + + /* Disable 2.5V LDO */ + HALMAC_REG_WRITE_8( + halmac_adapter, REG_LDO_EFUSE_CTRL + 3, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 3) & + ~(BIT(7)))); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_switch_efuse_bank_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_bank efuse_bank) +{ + u8 reg_value; + struct halmac_api *halmac_api; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (halmac_transition_efuse_state_88xx( + halmac_adapter, HALMAC_EFUSE_CMD_CONSTRUCT_BUSY) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + reg_value = HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1); + + if (efuse_bank == (reg_value & (BIT(0) | BIT(1)))) + return HALMAC_RET_SUCCESS; + + reg_value &= ~(BIT(0) | BIT(1)); + reg_value |= efuse_bank; + HALMAC_REG_WRITE_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1, reg_value); + + if ((HALMAC_REG_READ_8(halmac_adapter, REG_LDO_EFUSE_CTRL + 1) & + (BIT(0) | BIT(1))) != efuse_bank) + return HALMAC_RET_SWITCH_EFUSE_BANK_FAIL; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_eeprom_parser_88xx(struct halmac_adapter *halmac_adapter, + u8 *physical_efuse_map, u8 *logical_efuse_map) +{ + u8 j; + u8 value8; + u8 block_index; + u8 valid_word_enable, word_enable; + u8 efuse_read_header, efuse_read_header2 = 0; + u32 eeprom_index; + u32 efuse_index = 0; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + memset(logical_efuse_map, 0xFF, eeprom_size); + + do { + value8 = *(physical_efuse_map + efuse_index); + efuse_read_header = value8; + + if ((efuse_read_header & 0x1f) == 0x0f) { + efuse_index++; + value8 = *(physical_efuse_map + efuse_index); + efuse_read_header2 = value8; + block_index = ((efuse_read_header2 & 0xF0) >> 1) | + ((efuse_read_header >> 5) & 0x07); + word_enable = efuse_read_header2 & 0x0F; + } else { + block_index = (efuse_read_header & 0xF0) >> 4; + word_enable = efuse_read_header & 0x0F; + } + + if (efuse_read_header == 0xff) + break; + + efuse_index++; + + if (efuse_index >= halmac_adapter->hw_config_info.efuse_size - + HALMAC_PROTECTED_EFUSE_SIZE_88XX - 1) + return HALMAC_RET_EEPROM_PARSING_FAIL; + + for (j = 0; j < 4; j++) { + valid_word_enable = + (u8)((~(word_enable >> j)) & BIT(0)); + if (valid_word_enable != 1) + continue; + + eeprom_index = (block_index << 3) + (j << 1); + + if ((eeprom_index + 1) > eeprom_size) { + pr_err("Error: EEPROM addr exceeds eeprom_size:0x%X, at eFuse 0x%X\n", + eeprom_size, efuse_index - 1); + if ((efuse_read_header & 0x1f) == 0x0f) + pr_err("Error: EEPROM header: 0x%X, 0x%X,\n", + efuse_read_header, + efuse_read_header2); + else + pr_err("Error: EEPROM header: 0x%X,\n", + efuse_read_header); + + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + + value8 = *(physical_efuse_map + efuse_index); + *(logical_efuse_map + eeprom_index) = value8; + + eeprom_index++; + efuse_index++; + + if (efuse_index > + halmac_adapter->hw_config_info.efuse_size - + HALMAC_PROTECTED_EFUSE_SIZE_88XX - 1) + return HALMAC_RET_EEPROM_PARSING_FAIL; + + value8 = *(physical_efuse_map + efuse_index); + *(logical_efuse_map + eeprom_index) = value8; + + efuse_index++; + + if (efuse_index > + halmac_adapter->hw_config_info.efuse_size - + HALMAC_PROTECTED_EFUSE_SIZE_88XX) + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + } while (1); + + halmac_adapter->efuse_end = efuse_index; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_read_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + u8 *map) +{ + u8 *efuse_map = NULL; + u32 efuse_size; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + efuse_size = halmac_adapter->hw_config_info.efuse_size; + + if (!halmac_adapter->hal_efuse_map_valid) { + efuse_map = kzalloc(efuse_size, GFP_KERNEL); + if (!efuse_map) { + pr_err("[ERR]halmac allocate local efuse map Fail!!\n"); + return HALMAC_RET_MALLOC_FAIL; + } + + status = halmac_func_read_efuse_88xx(halmac_adapter, 0, + efuse_size, efuse_map); + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_read_efuse error = %x\n", status); + kfree(efuse_map); + return status; + } + + if (!halmac_adapter->hal_efuse_map) { + halmac_adapter->hal_efuse_map = + kzalloc(efuse_size, GFP_KERNEL); + if (!halmac_adapter->hal_efuse_map) { + pr_err("[ERR]halmac allocate efuse map Fail!!\n"); + kfree(efuse_map); + return HALMAC_RET_MALLOC_FAIL; + } + } + + spin_lock(&halmac_adapter->efuse_lock); + memcpy(halmac_adapter->hal_efuse_map, efuse_map, efuse_size); + halmac_adapter->hal_efuse_map_valid = true; + spin_unlock(&halmac_adapter->efuse_lock); + + kfree(efuse_map); + } + + if (halmac_eeprom_parser_88xx(halmac_adapter, + halmac_adapter->hal_efuse_map, + map) != HALMAC_RET_SUCCESS) + return HALMAC_RET_EEPROM_PARSING_FAIL; + + return status; +} + +enum halmac_ret_status +halmac_func_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 offset, u8 value) +{ + u8 pg_efuse_byte1, pg_efuse_byte2; + u8 pg_block, pg_block_index; + u8 pg_efuse_header, pg_efuse_header2; + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + u32 efuse_end, pg_efuse_num; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map); + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_read_logical_efuse_map_88xx error = %x\n", + status); + kfree(eeprom_map); + return status; + } + + if (*(eeprom_map + offset) != value) { + efuse_end = halmac_adapter->efuse_end; + pg_block = (u8)(offset >> 3); + pg_block_index = (u8)((offset & (8 - 1)) >> 1); + + if (offset > 0x7f) { + pg_efuse_header = + (((pg_block & 0x07) << 5) & 0xE0) | 0x0F; + pg_efuse_header2 = + (u8)(((pg_block & 0x78) << 1) + + ((0x1 << pg_block_index) ^ 0x0F)); + } else { + pg_efuse_header = + (u8)((pg_block << 4) + + ((0x01 << pg_block_index) ^ 0x0F)); + } + + if ((offset & 1) == 0) { + pg_efuse_byte1 = value; + pg_efuse_byte2 = *(eeprom_map + offset + 1); + } else { + pg_efuse_byte1 = *(eeprom_map + offset - 1); + pg_efuse_byte2 = value; + } + + if (offset > 0x7f) { + pg_efuse_num = 4; + if (halmac_adapter->hw_config_info.efuse_size <= + (pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX + + halmac_adapter->efuse_end)) { + kfree(eeprom_map); + return HALMAC_RET_EFUSE_NOT_ENOUGH; + } + halmac_func_write_efuse_88xx(halmac_adapter, efuse_end, + pg_efuse_header); + halmac_func_write_efuse_88xx(halmac_adapter, + efuse_end + 1, + pg_efuse_header2); + halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 2, pg_efuse_byte1); + status = halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 3, pg_efuse_byte2); + } else { + pg_efuse_num = 3; + if (halmac_adapter->hw_config_info.efuse_size <= + (pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX + + halmac_adapter->efuse_end)) { + kfree(eeprom_map); + return HALMAC_RET_EFUSE_NOT_ENOUGH; + } + halmac_func_write_efuse_88xx(halmac_adapter, efuse_end, + pg_efuse_header); + halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 1, pg_efuse_byte1); + status = halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 2, pg_efuse_byte2); + } + + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_write_logical_efuse error = %x\n", + status); + kfree(eeprom_map); + return status; + } + } + + kfree(eeprom_map); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + enum halmac_efuse_read_cfg cfg) +{ + u8 *eeprom_mask_updated = NULL; + u32 eeprom_mask_size = halmac_adapter->hw_config_info.eeprom_size >> 4; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + eeprom_mask_updated = kzalloc(eeprom_mask_size, GFP_KERNEL); + if (!eeprom_mask_updated) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + + status = halmac_update_eeprom_mask_88xx(halmac_adapter, pg_efuse_info, + eeprom_mask_updated); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_update_eeprom_mask_88xx error = %x\n", + status); + kfree(eeprom_mask_updated); + return status; + } + + status = halmac_check_efuse_enough_88xx(halmac_adapter, pg_efuse_info, + eeprom_mask_updated); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_check_efuse_enough_88xx error = %x\n", + status); + kfree(eeprom_mask_updated); + return status; + } + + status = halmac_program_efuse_88xx(halmac_adapter, pg_efuse_info, + eeprom_mask_updated); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("[ERR]halmac_program_efuse_88xx error = %x\n", status); + kfree(eeprom_mask_updated); + return status; + } + + kfree(eeprom_mask_updated); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_update_eeprom_mask_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated) +{ + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + u8 *eeprom_map_pg, *eeprom_mask; + u16 i, j; + u16 map_byte_offset, mask_byte_offset; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + memset(eeprom_mask_updated, 0x00, pg_efuse_info->efuse_mask_size); + + status = halmac_read_logical_efuse_map_88xx(halmac_adapter, eeprom_map); + + if (status != HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return status; + } + + eeprom_map_pg = pg_efuse_info->efuse_map; + eeprom_mask = pg_efuse_info->efuse_mask; + + for (i = 0; i < pg_efuse_info->efuse_mask_size; i++) + *(eeprom_mask_updated + i) = *(eeprom_mask + i); + + for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 16) { + for (j = 0; j < 16; j = j + 2) { + map_byte_offset = i + j; + mask_byte_offset = i >> 4; + if (*(eeprom_map_pg + map_byte_offset) == + *(eeprom_map + map_byte_offset)) { + if (*(eeprom_map_pg + map_byte_offset + 1) == + *(eeprom_map + map_byte_offset + 1)) { + switch (j) { + case 0: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(4) ^ 0xFF); + break; + case 2: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(5) ^ 0xFF); + break; + case 4: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(6) ^ 0xFF); + break; + case 6: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(7) ^ 0xFF); + break; + case 8: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(0) ^ 0xFF); + break; + case 10: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(1) ^ 0xFF); + break; + case 12: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(2) ^ 0xFF); + break; + case 14: + *(eeprom_mask_updated + + mask_byte_offset) = + *(eeprom_mask_updated + + mask_byte_offset) & + (BIT(3) ^ 0xFF); + break; + default: + break; + } + } + } + } + } + + kfree(eeprom_map); + + return status; +} + +static enum halmac_ret_status +halmac_check_efuse_enough_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated) +{ + u8 pre_word_enb, word_enb; + u8 pg_efuse_header, pg_efuse_header2; + u8 pg_block; + u16 i, j; + u32 efuse_end; + u32 tmp_eeprom_offset, pg_efuse_num = 0; + + efuse_end = halmac_adapter->efuse_end; + + for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 8) { + tmp_eeprom_offset = i; + + if ((tmp_eeprom_offset & 7) > 0) { + pre_word_enb = + (*(eeprom_mask_updated + (i >> 4)) & 0x0F); + word_enb = pre_word_enb ^ 0x0F; + } else { + pre_word_enb = (*(eeprom_mask_updated + (i >> 4)) >> 4); + word_enb = pre_word_enb ^ 0x0F; + } + + pg_block = (u8)(tmp_eeprom_offset >> 3); + + if (pre_word_enb > 0) { + if (tmp_eeprom_offset > 0x7f) { + pg_efuse_header = + (((pg_block & 0x07) << 5) & 0xE0) | + 0x0F; + pg_efuse_header2 = (u8)( + ((pg_block & 0x78) << 1) + word_enb); + } else { + pg_efuse_header = + (u8)((pg_block << 4) + word_enb); + } + + if (tmp_eeprom_offset > 0x7f) { + pg_efuse_num++; + pg_efuse_num++; + efuse_end = efuse_end + 2; + for (j = 0; j < 4; j++) { + if (((pre_word_enb >> j) & 0x1) > 0) { + pg_efuse_num++; + pg_efuse_num++; + efuse_end = efuse_end + 2; + } + } + } else { + pg_efuse_num++; + efuse_end = efuse_end + 1; + for (j = 0; j < 4; j++) { + if (((pre_word_enb >> j) & 0x1) > 0) { + pg_efuse_num++; + pg_efuse_num++; + efuse_end = efuse_end + 2; + } + } + } + } + } + + if (halmac_adapter->hw_config_info.efuse_size <= + (pg_efuse_num + HALMAC_PROTECTED_EFUSE_SIZE_88XX + + halmac_adapter->efuse_end)) + return HALMAC_RET_EFUSE_NOT_ENOUGH; + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_program_efuse_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + u8 *eeprom_mask_updated) +{ + u8 pre_word_enb, word_enb; + u8 pg_efuse_header, pg_efuse_header2; + u8 pg_block; + u16 i, j; + u32 efuse_end; + u32 tmp_eeprom_offset; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + efuse_end = halmac_adapter->efuse_end; + + for (i = 0; i < pg_efuse_info->efuse_map_size; i = i + 8) { + tmp_eeprom_offset = i; + + if (((tmp_eeprom_offset >> 3) & 1) > 0) { + pre_word_enb = + (*(eeprom_mask_updated + (i >> 4)) & 0x0F); + word_enb = pre_word_enb ^ 0x0F; + } else { + pre_word_enb = (*(eeprom_mask_updated + (i >> 4)) >> 4); + word_enb = pre_word_enb ^ 0x0F; + } + + pg_block = (u8)(tmp_eeprom_offset >> 3); + + if (pre_word_enb <= 0) + continue; + + if (tmp_eeprom_offset > 0x7f) { + pg_efuse_header = + (((pg_block & 0x07) << 5) & 0xE0) | 0x0F; + pg_efuse_header2 = + (u8)(((pg_block & 0x78) << 1) + word_enb); + } else { + pg_efuse_header = (u8)((pg_block << 4) + word_enb); + } + + if (tmp_eeprom_offset > 0x7f) { + halmac_func_write_efuse_88xx(halmac_adapter, efuse_end, + pg_efuse_header); + status = halmac_func_write_efuse_88xx(halmac_adapter, + efuse_end + 1, + pg_efuse_header2); + efuse_end = efuse_end + 2; + for (j = 0; j < 4; j++) { + if (((pre_word_enb >> j) & 0x1) > 0) { + halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end, + *(pg_efuse_info->efuse_map + + tmp_eeprom_offset + + (j << 1))); + status = halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 1, + *(pg_efuse_info->efuse_map + + tmp_eeprom_offset + (j << 1) + + 1)); + efuse_end = efuse_end + 2; + } + } + } else { + status = halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end, pg_efuse_header); + efuse_end = efuse_end + 1; + for (j = 0; j < 4; j++) { + if (((pre_word_enb >> j) & 0x1) > 0) { + halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end, + *(pg_efuse_info->efuse_map + + tmp_eeprom_offset + + (j << 1))); + status = halmac_func_write_efuse_88xx( + halmac_adapter, efuse_end + 1, + *(pg_efuse_info->efuse_map + + tmp_eeprom_offset + (j << 1) + + 1)); + efuse_end = efuse_end + 2; + } + } + } + } + + return status; +} + +enum halmac_ret_status +halmac_dlfw_to_mem_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code, + u32 dest, u32 code_size) +{ + u8 *code_ptr; + u8 first_part; + u32 mem_offset; + u32 pkt_size_tmp, send_pkt_size; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + code_ptr = ram_code; + mem_offset = 0; + first_part = 1; + pkt_size_tmp = code_size; + + HALMAC_REG_WRITE_32( + halmac_adapter, REG_DDMA_CH0CTRL, + HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) | + BIT_DDMACH0_RESET_CHKSUM_STS); + + while (pkt_size_tmp != 0) { + if (pkt_size_tmp >= halmac_adapter->max_download_size) + send_pkt_size = halmac_adapter->max_download_size; + else + send_pkt_size = pkt_size_tmp; + + if (halmac_send_fwpkt_88xx( + halmac_adapter, code_ptr + mem_offset, + send_pkt_size) != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_fwpkt_88xx fail!!"); + return HALMAC_RET_DLFW_FAIL; + } + + if (halmac_iddma_dlfw_88xx( + halmac_adapter, + HALMAC_OCPBASE_TXBUF_88XX + + halmac_adapter->hw_config_info.txdesc_size, + dest + mem_offset, send_pkt_size, + first_part) != HALMAC_RET_SUCCESS) { + pr_err("halmac_iddma_dlfw_88xx fail!!"); + return HALMAC_RET_DLFW_FAIL; + } + + first_part = 0; + mem_offset += send_pkt_size; + pkt_size_tmp -= send_pkt_size; + } + + if (halmac_check_fw_chksum_88xx(halmac_adapter, dest) != + HALMAC_RET_SUCCESS) { + pr_err("halmac_check_fw_chksum_88xx fail!!"); + return HALMAC_RET_DLFW_FAIL; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_fwpkt_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code, + u32 code_size) +{ + if (halmac_download_rsvd_page_88xx(halmac_adapter, ram_code, + code_size) != HALMAC_RET_SUCCESS) { + pr_err("PLATFORM_SEND_RSVD_PAGE 0 error!!\n"); + return HALMAC_RET_DL_RSVD_PAGE_FAIL; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_iddma_dlfw_88xx(struct halmac_adapter *halmac_adapter, u32 source, + u32 dest, u32 length, u8 first) +{ + u32 counter; + u32 ch0_control = (u32)(BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN); + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + counter = HALMC_DDMA_POLLING_COUNT; + while (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) & + BIT_DDMACH0_OWN) { + counter--; + if (counter == 0) { + pr_err("%s error-1!!\n", __func__); + return HALMAC_RET_DDMA_FAIL; + } + } + + ch0_control |= (length & BIT_MASK_DDMACH0_DLEN); + if (first == 0) + ch0_control |= BIT_DDMACH0_CHKSUM_CONT; + + HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0SA, source); + HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0DA, dest); + HALMAC_REG_WRITE_32(halmac_adapter, REG_DDMA_CH0CTRL, ch0_control); + + counter = HALMC_DDMA_POLLING_COUNT; + while (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) & + BIT_DDMACH0_OWN) { + counter--; + if (counter == 0) { + pr_err("%s error-2!!\n", __func__); + return HALMAC_RET_DDMA_FAIL; + } + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_check_fw_chksum_88xx(struct halmac_adapter *halmac_adapter, + u32 memory_address) +{ + u8 mcu_fw_ctrl; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + mcu_fw_ctrl = HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL); + + if (HALMAC_REG_READ_32(halmac_adapter, REG_DDMA_CH0CTRL) & + BIT_DDMACH0_CHKSUM_STS) { + if (memory_address < HALMAC_OCPBASE_DMEM_88XX) { + mcu_fw_ctrl |= BIT_IMEM_DW_OK; + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(mcu_fw_ctrl & ~(BIT_IMEM_CHKSUM_OK))); + } else { + mcu_fw_ctrl |= BIT_DMEM_DW_OK; + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(mcu_fw_ctrl & ~(BIT_DMEM_CHKSUM_OK))); + } + + pr_err("%s error!!\n", __func__); + + status = HALMAC_RET_FW_CHECKSUM_FAIL; + } else { + if (memory_address < HALMAC_OCPBASE_DMEM_88XX) { + mcu_fw_ctrl |= BIT_IMEM_DW_OK; + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(mcu_fw_ctrl | BIT_IMEM_CHKSUM_OK)); + } else { + mcu_fw_ctrl |= BIT_DMEM_DW_OK; + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(mcu_fw_ctrl | BIT_DMEM_CHKSUM_OK)); + } + + status = HALMAC_RET_SUCCESS; + } + + return status; +} + +enum halmac_ret_status +halmac_dlfw_end_flow_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 value8; + u32 counter; + void *driver_adapter = halmac_adapter->driver_adapter; + struct halmac_api *halmac_api = + (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_32(halmac_adapter, REG_TXDMA_STATUS, BIT(2)); + + /* Check IMEM & DMEM checksum is OK or not */ + if ((HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) & 0x50) == 0x50) + HALMAC_REG_WRITE_16(halmac_adapter, REG_MCUFW_CTRL, + (u16)(HALMAC_REG_READ_16(halmac_adapter, + REG_MCUFW_CTRL) | + BIT_FW_DW_RDY)); + else + return HALMAC_RET_DLFW_FAIL; + + HALMAC_REG_WRITE_8( + halmac_adapter, REG_MCUFW_CTRL, + (u8)(HALMAC_REG_READ_8(halmac_adapter, REG_MCUFW_CTRL) & + ~(BIT(0)))); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RSV_CTRL + 1); + value8 = (u8)(value8 | BIT(0)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RSV_CTRL + 1, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN + 1); + value8 = (u8)(value8 | BIT(2)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN + 1, + value8); /* Release MCU reset */ + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Download Finish, Reset CPU\n"); + + counter = 10000; + while (HALMAC_REG_READ_16(halmac_adapter, REG_MCUFW_CTRL) != 0xC078) { + if (counter == 0) { + pr_err("Check 0x80 = 0xC078 fail\n"); + if ((HALMAC_REG_READ_32(halmac_adapter, REG_FW_DBG7) & + 0xFFFFFF00) == 0xFAAAAA00) + pr_err("Key fail\n"); + return HALMAC_RET_DLFW_FAIL; + } + counter--; + usleep_range(50, 60); + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Check 0x80 = 0xC078 counter = %d\n", counter); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_free_dl_fw_end_flow_88xx(struct halmac_adapter *halmac_adapter) +{ + u32 counter; + struct halmac_api *halmac_api = + (struct halmac_api *)halmac_adapter->halmac_api; + + counter = 100; + while (HALMAC_REG_READ_8(halmac_adapter, REG_HMETFR + 3) != 0) { + counter--; + if (counter == 0) { + pr_err("[ERR]0x1CF != 0\n"); + return HALMAC_RET_DLFW_FAIL; + } + usleep_range(50, 60); + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_HMETFR + 3, + ID_INFORM_DLEMEM_RDY); + + counter = 10000; + while (HALMAC_REG_READ_8(halmac_adapter, REG_C2HEVT_3 + 3) != + ID_INFORM_DLEMEM_RDY) { + counter--; + if (counter == 0) { + pr_err("[ERR]0x1AF != 0x80\n"); + return HALMAC_RET_DLFW_FAIL; + } + usleep_range(50, 60); + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_C2HEVT_3 + 3, 0); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_pwr_seq_parser_88xx(struct halmac_adapter *halmac_adapter, u8 cut, + u8 fab, u8 intf, + struct halmac_wl_pwr_cfg_ **pp_pwr_seq_cfg) +{ + u32 seq_idx = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_wl_pwr_cfg_ *seq_cmd; + + driver_adapter = halmac_adapter->driver_adapter; + + do { + seq_cmd = pp_pwr_seq_cfg[seq_idx]; + + if (!seq_cmd) + break; + + status = halmac_pwr_sub_seq_parer_88xx(halmac_adapter, cut, fab, + intf, seq_cmd); + if (status != HALMAC_RET_SUCCESS) { + pr_err("[Err]pwr sub seq parser fail, status = 0x%X!\n", + status); + return status; + } + + seq_idx++; + } while (1); + + return status; +} + +static enum halmac_ret_status +halmac_pwr_sub_seq_parer_do_cmd_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_wl_pwr_cfg_ *sub_seq_cmd, + bool *reti) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u8 value, flag; + u8 polling_bit; + u32 polling_count; + static u32 poll_to_static; + u32 offset; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + *reti = true; + + switch (sub_seq_cmd->cmd) { + case HALMAC_PWR_CMD_WRITE: + if (sub_seq_cmd->base == HALMAC_PWR_BASEADDR_SDIO) + offset = sub_seq_cmd->offset | SDIO_LOCAL_OFFSET; + else + offset = sub_seq_cmd->offset; + + value = HALMAC_REG_READ_8(halmac_adapter, offset); + value = (u8)(value & (u8)(~(sub_seq_cmd->msk))); + value = (u8)(value | + (u8)(sub_seq_cmd->value & sub_seq_cmd->msk)); + + HALMAC_REG_WRITE_8(halmac_adapter, offset, value); + break; + case HALMAC_PWR_CMD_POLLING: + polling_bit = 0; + polling_count = HALMAC_POLLING_READY_TIMEOUT_COUNT; + flag = 0; + + if (sub_seq_cmd->base == HALMAC_PWR_BASEADDR_SDIO) + offset = sub_seq_cmd->offset | SDIO_LOCAL_OFFSET; + else + offset = sub_seq_cmd->offset; + + do { + polling_count--; + value = HALMAC_REG_READ_8(halmac_adapter, offset); + value = (u8)(value & sub_seq_cmd->msk); + + if (value == (sub_seq_cmd->value & sub_seq_cmd->msk)) { + polling_bit = 1; + continue; + } + + if (polling_count != 0) { + usleep_range(50, 60); + continue; + } + + if (halmac_adapter->halmac_interface == + HALMAC_INTERFACE_PCIE && + flag == 0) { + /* For PCIE + USB package poll power bit + * timeout issue + */ + poll_to_static++; + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_PWR, + DBG_WARNING, + "[WARN]PCIE polling timeout : %d!!\n", + poll_to_static); + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SYS_PW_CTRL, + HALMAC_REG_READ_8(halmac_adapter, + REG_SYS_PW_CTRL) | + BIT(3)); + HALMAC_REG_WRITE_8( + halmac_adapter, REG_SYS_PW_CTRL, + HALMAC_REG_READ_8(halmac_adapter, + REG_SYS_PW_CTRL) & + ~BIT(3)); + polling_bit = 0; + polling_count = + HALMAC_POLLING_READY_TIMEOUT_COUNT; + flag = 1; + } else { + pr_err("[ERR]Pwr cmd polling timeout!!\n"); + pr_err("[ERR]Pwr cmd offset : %X!!\n", + sub_seq_cmd->offset); + pr_err("[ERR]Pwr cmd value : %X!!\n", + sub_seq_cmd->value); + pr_err("[ERR]Pwr cmd msk : %X!!\n", + sub_seq_cmd->msk); + pr_err("[ERR]Read offset = %X value = %X!!\n", + offset, value); + return HALMAC_RET_PWRSEQ_POLLING_FAIL; + } + } while (!polling_bit); + break; + case HALMAC_PWR_CMD_DELAY: + if (sub_seq_cmd->value == HALMAC_PWRSEQ_DELAY_US) + udelay(sub_seq_cmd->offset); + else + usleep_range(1000 * sub_seq_cmd->offset, + 1000 * sub_seq_cmd->offset + 100); + + break; + case HALMAC_PWR_CMD_READ: + break; + case HALMAC_PWR_CMD_END: + return HALMAC_RET_SUCCESS; + default: + return HALMAC_RET_PWRSEQ_CMD_INCORRECT; + } + + *reti = false; + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_pwr_sub_seq_parer_88xx(struct halmac_adapter *halmac_adapter, u8 cut, + u8 fab, u8 intf, + struct halmac_wl_pwr_cfg_ *pwr_sub_seq_cfg) +{ + struct halmac_wl_pwr_cfg_ *sub_seq_cmd; + bool reti; + enum halmac_ret_status status; + + for (sub_seq_cmd = pwr_sub_seq_cfg;; sub_seq_cmd++) { + if ((sub_seq_cmd->interface_msk & intf) && + (sub_seq_cmd->fab_msk & fab) && + (sub_seq_cmd->cut_msk & cut)) { + status = halmac_pwr_sub_seq_parer_do_cmd_88xx( + halmac_adapter, sub_seq_cmd, &reti); + + if (reti) + return status; + } + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_get_h2c_buff_free_space_88xx(struct halmac_adapter *halmac_adapter) +{ + u32 hw_wptr, fw_rptr; + struct halmac_api *halmac_api = + (struct halmac_api *)halmac_adapter->halmac_api; + + hw_wptr = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_PKT_WRITEADDR) & + BIT_MASK_H2C_WR_ADDR; + fw_rptr = HALMAC_REG_READ_32(halmac_adapter, REG_H2C_PKT_READADDR) & + BIT_MASK_H2C_READ_ADDR; + + if (hw_wptr >= fw_rptr) + halmac_adapter->h2c_buf_free_space = + halmac_adapter->h2c_buff_size - (hw_wptr - fw_rptr); + else + halmac_adapter->h2c_buf_free_space = fw_rptr - hw_wptr; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_h2c_pkt_88xx(struct halmac_adapter *halmac_adapter, u8 *hal_h2c_cmd, + u32 size, bool ack) +{ + u32 counter = 100; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + while (halmac_adapter->h2c_buf_free_space <= + HALMAC_H2C_CMD_SIZE_UNIT_88XX) { + halmac_get_h2c_buff_free_space_88xx(halmac_adapter); + counter--; + if (counter == 0) { + pr_err("h2c free space is not enough!!\n"); + return HALMAC_RET_H2C_SPACE_FULL; + } + } + + /* Send TxDesc + H2C_CMD */ + if (!PLATFORM_SEND_H2C_PKT(driver_adapter, hal_h2c_cmd, size)) { + pr_err("Send H2C_CMD pkt error!!\n"); + return HALMAC_RET_SEND_H2C_FAIL; + } + + halmac_adapter->h2c_buf_free_space -= HALMAC_H2C_CMD_SIZE_UNIT_88XX; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "H2C free space : %d\n", + halmac_adapter->h2c_buf_free_space); + + return status; +} + +enum halmac_ret_status +halmac_download_rsvd_page_88xx(struct halmac_adapter *halmac_adapter, + u8 *hal_buf, u32 size) +{ + u8 restore[3]; + u8 value8; + u32 counter; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (size == 0) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "Rsvd page packet size is zero!!\n"); + return HALMAC_RET_ZERO_LEN_RSVD_PACKET; + } + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1); + value8 = (u8)(value8 | BIT(7)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_CR + 1); + restore[0] = value8; + value8 = (u8)(value8 | BIT(0)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_BCN_CTRL); + restore[1] = value8; + value8 = (u8)((value8 & ~(BIT(3))) | BIT(4)); + HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2); + restore[2] = value8; + value8 = (u8)(value8 & ~(BIT(6))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2, value8); + + if (!PLATFORM_SEND_RSVD_PAGE(driver_adapter, hal_buf, size)) { + pr_err("PLATFORM_SEND_RSVD_PAGE 1 error!!\n"); + status = HALMAC_RET_DL_RSVD_PAGE_FAIL; + } + + /* Check Bcn_Valid_Bit */ + counter = 1000; + while (!(HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1) & + BIT(7))) { + udelay(10); + counter--; + if (counter == 0) { + pr_err("Polling Bcn_Valid_Fail error!!\n"); + status = HALMAC_RET_POLLING_BCN_VALID_FAIL; + break; + } + } + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1); + HALMAC_REG_WRITE_8(halmac_adapter, REG_FIFOPAGE_CTRL_2 + 1, + (value8 | BIT(7))); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_FWHW_TXQ_CTRL + 2, restore[2]); + HALMAC_REG_WRITE_8(halmac_adapter, REG_BCN_CTRL, restore[1]); + HALMAC_REG_WRITE_8(halmac_adapter, REG_CR + 1, restore[0]); + + return status; +} + +enum halmac_ret_status +halmac_set_h2c_header_88xx(struct halmac_adapter *halmac_adapter, + u8 *hal_h2c_hdr, u16 *seq, bool ack) +{ + void *driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + H2C_CMD_HEADER_SET_CATEGORY(hal_h2c_hdr, 0x00); + H2C_CMD_HEADER_SET_TOTAL_LEN(hal_h2c_hdr, 16); + + spin_lock(&halmac_adapter->h2c_seq_lock); + H2C_CMD_HEADER_SET_SEQ_NUM(hal_h2c_hdr, halmac_adapter->h2c_packet_seq); + *seq = halmac_adapter->h2c_packet_seq; + halmac_adapter->h2c_packet_seq++; + spin_unlock(&halmac_adapter->h2c_seq_lock); + + if (ack) + H2C_CMD_HEADER_SET_ACK(hal_h2c_hdr, 1); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_set_fw_offload_h2c_header_88xx( + struct halmac_adapter *halmac_adapter, u8 *hal_h2c_hdr, + struct halmac_h2c_header_info *h2c_header_info, u16 *seq_num) +{ + void *driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + FW_OFFLOAD_H2C_SET_TOTAL_LEN(hal_h2c_hdr, + 8 + h2c_header_info->content_size); + FW_OFFLOAD_H2C_SET_SUB_CMD_ID(hal_h2c_hdr, h2c_header_info->sub_cmd_id); + + FW_OFFLOAD_H2C_SET_CATEGORY(hal_h2c_hdr, 0x01); + FW_OFFLOAD_H2C_SET_CMD_ID(hal_h2c_hdr, 0xFF); + + spin_lock(&halmac_adapter->h2c_seq_lock); + FW_OFFLOAD_H2C_SET_SEQ_NUM(hal_h2c_hdr, halmac_adapter->h2c_packet_seq); + *seq_num = halmac_adapter->h2c_packet_seq; + halmac_adapter->h2c_packet_seq++; + spin_unlock(&halmac_adapter->h2c_seq_lock); + + if (h2c_header_info->ack) + FW_OFFLOAD_H2C_SET_ACK(hal_h2c_hdr, 1); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_h2c_set_pwr_mode_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwlps_option *hal_fw_lps_opt) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX]; + u8 *h2c_header, *h2c_cmd; + u16 seq = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + driver_adapter = halmac_adapter->driver_adapter; + h2c_header = h2c_buff; + h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; + + memset(h2c_buff, 0x00, HALMAC_H2C_CMD_SIZE_88XX); + + SET_PWR_MODE_SET_CMD_ID(h2c_cmd, CMD_ID_SET_PWR_MODE); + SET_PWR_MODE_SET_CLASS(h2c_cmd, CLASS_SET_PWR_MODE); + SET_PWR_MODE_SET_MODE(h2c_cmd, hal_fw_lps_opt->mode); + SET_PWR_MODE_SET_CLK_REQUEST(h2c_cmd, hal_fw_lps_opt->clk_request); + SET_PWR_MODE_SET_RLBM(h2c_cmd, hal_fw_lps_opt->rlbm); + SET_PWR_MODE_SET_SMART_PS(h2c_cmd, hal_fw_lps_opt->smart_ps); + SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_cmd, + hal_fw_lps_opt->awake_interval); + SET_PWR_MODE_SET_B_ALL_QUEUE_UAPSD(h2c_cmd, + hal_fw_lps_opt->all_queue_uapsd); + SET_PWR_MODE_SET_PWR_STATE(h2c_cmd, hal_fw_lps_opt->pwr_state); + SET_PWR_MODE_SET_ANT_AUTO_SWITCH(h2c_cmd, + hal_fw_lps_opt->ant_auto_switch); + SET_PWR_MODE_SET_PS_ALLOW_BT_HIGH_PRIORITY( + h2c_cmd, hal_fw_lps_opt->ps_allow_bt_high_priority); + SET_PWR_MODE_SET_PROTECT_BCN(h2c_cmd, hal_fw_lps_opt->protect_bcn); + SET_PWR_MODE_SET_SILENCE_PERIOD(h2c_cmd, + hal_fw_lps_opt->silence_period); + SET_PWR_MODE_SET_FAST_BT_CONNECT(h2c_cmd, + hal_fw_lps_opt->fast_bt_connect); + SET_PWR_MODE_SET_TWO_ANTENNA_EN(h2c_cmd, + hal_fw_lps_opt->two_antenna_en); + SET_PWR_MODE_SET_ADOPT_USER_SETTING(h2c_cmd, + hal_fw_lps_opt->adopt_user_setting); + SET_PWR_MODE_SET_DRV_BCN_EARLY_SHIFT( + h2c_cmd, hal_fw_lps_opt->drv_bcn_early_shift); + + halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, true); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s Fail = %x!!\n", __func__, status); + return status; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *original_h2c, u16 *seq, u8 ack) +{ + u8 H2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u8 *h2c_header, *h2c_cmd; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_send_original_h2c ==========>\n"); + + h2c_header = H2c_buff; + h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; + memcpy(h2c_cmd, original_h2c, 8); /* Original H2C 8 byte */ + + halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, seq, ack); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, H2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, ack); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_original_h2c Fail = %x!!\n", status); + return status; + } + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_send_original_h2c <==========\n"); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_media_status_rpt_88xx(struct halmac_adapter *halmac_adapter, u8 op_mode, + u8 mac_id_ind, u8 mac_id, u8 mac_id_end) +{ + u8 H2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u8 *h2c_header, *h2c_cmd; + u16 seq = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_send_h2c_set_pwr_mode_88xx!!\n"); + + driver_adapter = halmac_adapter->driver_adapter; + h2c_header = H2c_buff; + h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; + + memset(H2c_buff, 0x00, HALMAC_H2C_CMD_SIZE_88XX); + + MEDIA_STATUS_RPT_SET_CMD_ID(h2c_cmd, CMD_ID_MEDIA_STATUS_RPT); + MEDIA_STATUS_RPT_SET_CLASS(h2c_cmd, CLASS_MEDIA_STATUS_RPT); + MEDIA_STATUS_RPT_SET_OP_MODE(h2c_cmd, op_mode); + MEDIA_STATUS_RPT_SET_MACID_IN(h2c_cmd, mac_id_ind); + MEDIA_STATUS_RPT_SET_MACID(h2c_cmd, mac_id); + MEDIA_STATUS_RPT_SET_MACID_END(h2c_cmd, mac_id_end); + + halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, true); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, H2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("%s Fail = %x!!\n", __func__, status); + return status; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_h2c_update_packet_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_packet_id pkt_id, u8 *pkt, + u32 pkt_size) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation + .rsvd_h2c_extra_info_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + ret_status = + halmac_download_rsvd_page_88xx(halmac_adapter, pkt, pkt_size); + + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n", + ret_status); + HALMAC_REG_WRITE_16( + halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + return ret_status; + } + + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + UPDATE_PACKET_SET_SIZE( + h2c_buff, + pkt_size + halmac_adapter->hw_config_info.txdesc_size); + UPDATE_PACKET_SET_PACKET_ID(h2c_buff, pkt_id); + UPDATE_PACKET_SET_PACKET_LOC( + h2c_buff, + halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy - + halmac_adapter->txff_allocation.rsvd_pg_bndy); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_UPDATE_PACKET; + h2c_header_info.content_size = 8; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + halmac_adapter->halmac_state.update_packet_set.seq_num = h2c_seq_mum; + + ret_status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (ret_status != HALMAC_RET_SUCCESS) { + pr_err("%s Fail = %x!!\n", __func__, ret_status); + return ret_status; + } + + return ret_status; +} + +enum halmac_ret_status +halmac_send_h2c_phy_parameter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + bool full_fifo) +{ + bool drv_trigger_send = false; + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + u32 info_size = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + struct halmac_config_para_info *config_para_info; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + config_para_info = &halmac_adapter->config_para_info; + + if (!config_para_info->cfg_para_buf) { + if (full_fifo) + config_para_info->para_buf_size = + HALMAC_EXTRA_INFO_BUFF_SIZE_FULL_FIFO_88XX; + else + config_para_info->para_buf_size = + HALMAC_EXTRA_INFO_BUFF_SIZE_88XX; + + config_para_info->cfg_para_buf = + kzalloc(config_para_info->para_buf_size, GFP_KERNEL); + + if (config_para_info->cfg_para_buf) { + memset(config_para_info->cfg_para_buf, 0x00, + config_para_info->para_buf_size); + config_para_info->full_fifo_mode = full_fifo; + config_para_info->para_buf_w = + config_para_info->cfg_para_buf; + config_para_info->para_num = 0; + config_para_info->avai_para_buf_size = + config_para_info->para_buf_size; + config_para_info->value_accumulation = 0; + config_para_info->offset_accumulation = 0; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, + DBG_DMESG, + "Allocate cfg_para_buf fail!!\n"); + return HALMAC_RET_MALLOC_FAIL; + } + } + + if (halmac_transition_cfg_para_state_88xx( + halmac_adapter, + HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + halmac_enqueue_para_buff_88xx(halmac_adapter, para_info, + config_para_info->para_buf_w, + &drv_trigger_send); + + if (para_info->cmd_id != HALMAC_PARAMETER_CMD_END) { + config_para_info->para_num++; + config_para_info->para_buf_w += HALMAC_FW_OFFLOAD_CMD_SIZE_88XX; + config_para_info->avai_para_buf_size = + config_para_info->avai_para_buf_size - + HALMAC_FW_OFFLOAD_CMD_SIZE_88XX; + } + + if ((config_para_info->avai_para_buf_size - + halmac_adapter->hw_config_info.txdesc_size) > + HALMAC_FW_OFFLOAD_CMD_SIZE_88XX && + !drv_trigger_send) + return HALMAC_RET_SUCCESS; + + if (config_para_info->para_num == 0) { + kfree(config_para_info->cfg_para_buf); + config_para_info->cfg_para_buf = NULL; + config_para_info->para_buf_w = NULL; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_WARNING, + "no cfg parameter element!!\n"); + + if (halmac_transition_cfg_para_state_88xx( + halmac_adapter, + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + return HALMAC_RET_SUCCESS; + } + + if (halmac_transition_cfg_para_state_88xx( + halmac_adapter, HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + halmac_adapter->halmac_state.cfg_para_state_set.process_status = + HALMAC_CMD_PROCESS_SENDING; + + if (config_para_info->full_fifo_mode) + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, 0); + else + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation + .rsvd_h2c_extra_info_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + info_size = + config_para_info->para_num * HALMAC_FW_OFFLOAD_CMD_SIZE_88XX; + + status = halmac_download_rsvd_page_88xx( + halmac_adapter, (u8 *)config_para_info->cfg_para_buf, + info_size); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_download_rsvd_page_88xx Fail!!\n"); + } else { + halmac_gen_cfg_para_h2c_88xx(halmac_adapter, h2c_buff); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_CFG_PARAMETER; + h2c_header_info.content_size = 4; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, + &h2c_seq_mum); + + halmac_adapter->halmac_state.cfg_para_state_set.seq_num = + h2c_seq_mum; + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, + true); + + if (status != HALMAC_RET_SUCCESS) + pr_err("halmac_send_h2c_pkt_88xx Fail!!\n"); + + HALMAC_RT_TRACE( + driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "config parameter time = %d\n", + HALMAC_REG_READ_32(halmac_adapter, REG_FW_DBG6)); + } + + kfree(config_para_info->cfg_para_buf); + config_para_info->cfg_para_buf = NULL; + config_para_info->para_buf_w = NULL; + + /* Restore bcn head */ + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + if (halmac_transition_cfg_para_state_88xx( + halmac_adapter, HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + if (!drv_trigger_send) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "Buffer full trigger sending H2C!!\n"); + return HALMAC_RET_PARA_SENDING; + } + + return status; +} + +static enum halmac_ret_status +halmac_enqueue_para_buff_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + u8 *curr_buff_wptr, bool *end_cmd) +{ + struct halmac_config_para_info *config_para_info = + &halmac_adapter->config_para_info; + + *end_cmd = false; + + PHY_PARAMETER_INFO_SET_LENGTH(curr_buff_wptr, + HALMAC_FW_OFFLOAD_CMD_SIZE_88XX); + PHY_PARAMETER_INFO_SET_IO_CMD(curr_buff_wptr, para_info->cmd_id); + + switch (para_info->cmd_id) { + case HALMAC_PARAMETER_CMD_BB_W8: + case HALMAC_PARAMETER_CMD_BB_W16: + case HALMAC_PARAMETER_CMD_BB_W32: + case HALMAC_PARAMETER_CMD_MAC_W8: + case HALMAC_PARAMETER_CMD_MAC_W16: + case HALMAC_PARAMETER_CMD_MAC_W32: + PHY_PARAMETER_INFO_SET_IO_ADDR( + curr_buff_wptr, para_info->content.MAC_REG_W.offset); + PHY_PARAMETER_INFO_SET_DATA(curr_buff_wptr, + para_info->content.MAC_REG_W.value); + PHY_PARAMETER_INFO_SET_MASK(curr_buff_wptr, + para_info->content.MAC_REG_W.msk); + PHY_PARAMETER_INFO_SET_MSK_EN( + curr_buff_wptr, para_info->content.MAC_REG_W.msk_en); + config_para_info->value_accumulation += + para_info->content.MAC_REG_W.value; + config_para_info->offset_accumulation += + para_info->content.MAC_REG_W.offset; + break; + case HALMAC_PARAMETER_CMD_RF_W: + /*In rf register, the address is only 1 byte*/ + PHY_PARAMETER_INFO_SET_RF_ADDR( + curr_buff_wptr, para_info->content.RF_REG_W.offset); + PHY_PARAMETER_INFO_SET_RF_PATH( + curr_buff_wptr, para_info->content.RF_REG_W.rf_path); + PHY_PARAMETER_INFO_SET_DATA(curr_buff_wptr, + para_info->content.RF_REG_W.value); + PHY_PARAMETER_INFO_SET_MASK(curr_buff_wptr, + para_info->content.RF_REG_W.msk); + PHY_PARAMETER_INFO_SET_MSK_EN( + curr_buff_wptr, para_info->content.RF_REG_W.msk_en); + config_para_info->value_accumulation += + para_info->content.RF_REG_W.value; + config_para_info->offset_accumulation += + (para_info->content.RF_REG_W.offset + + (para_info->content.RF_REG_W.rf_path << 8)); + break; + case HALMAC_PARAMETER_CMD_DELAY_US: + case HALMAC_PARAMETER_CMD_DELAY_MS: + PHY_PARAMETER_INFO_SET_DELAY_VALUE( + curr_buff_wptr, + para_info->content.DELAY_TIME.delay_time); + break; + case HALMAC_PARAMETER_CMD_END: + *end_cmd = true; + break; + default: + pr_err(" halmac_send_h2c_phy_parameter_88xx illegal cmd_id!!\n"); + break; + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_gen_cfg_para_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *h2c_buff) +{ + struct halmac_config_para_info *config_para_info = + &halmac_adapter->config_para_info; + + CFG_PARAMETER_SET_NUM(h2c_buff, config_para_info->para_num); + + if (config_para_info->full_fifo_mode) { + CFG_PARAMETER_SET_INIT_CASE(h2c_buff, 0x1); + CFG_PARAMETER_SET_PHY_PARAMETER_LOC(h2c_buff, 0); + } else { + CFG_PARAMETER_SET_INIT_CASE(h2c_buff, 0x0); + CFG_PARAMETER_SET_PHY_PARAMETER_LOC( + h2c_buff, + halmac_adapter->txff_allocation + .rsvd_h2c_extra_info_pg_bndy - + halmac_adapter->txff_allocation.rsvd_pg_bndy); + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_h2c_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + RUN_DATAPACK_SET_DATAPACK_ID(h2c_buff, halmac_data_type); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_RUN_DATAPACK; + h2c_header_info.content_size = 4; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_send_bt_coex_cmd_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf, + u32 bt_size, u8 ack) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + memcpy(h2c_buff + 8, bt_buf, bt_size); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_BT_COEX; + h2c_header_info.content_size = (u16)bt_size; + h2c_header_info.ack = ack; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, ack); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_func_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_switch_option *cs_option) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + enum halmac_cmd_process_status *process_status = + &halmac_adapter->halmac_state.scan_state_set.process_status; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_ctrl_ch_switch!!\n"); + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (halmac_transition_scan_state_88xx( + halmac_adapter, HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + *process_status = HALMAC_CMD_PROCESS_SENDING; + + if (cs_option->switch_en != 0) { + HALMAC_REG_WRITE_16(halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation + .rsvd_h2c_extra_info_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + + status = halmac_download_rsvd_page_88xx( + halmac_adapter, halmac_adapter->ch_sw_info.ch_info_buf, + halmac_adapter->ch_sw_info.total_size); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_download_rsvd_page_88xx Fail = %x!!\n", + status); + HALMAC_REG_WRITE_16( + halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation + .rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + return status; + } + + HALMAC_REG_WRITE_16( + halmac_adapter, REG_FIFOPAGE_CTRL_2, + (u16)(halmac_adapter->txff_allocation.rsvd_pg_bndy & + BIT_MASK_BCN_HEAD_1_V1)); + } + + CHANNEL_SWITCH_SET_SWITCH_START(h2c_buff, cs_option->switch_en); + CHANNEL_SWITCH_SET_CHANNEL_NUM(h2c_buff, + halmac_adapter->ch_sw_info.ch_num); + CHANNEL_SWITCH_SET_CHANNEL_INFO_LOC( + h2c_buff, + halmac_adapter->txff_allocation.rsvd_h2c_extra_info_pg_bndy - + halmac_adapter->txff_allocation.rsvd_pg_bndy); + CHANNEL_SWITCH_SET_DEST_CH_EN(h2c_buff, cs_option->dest_ch_en); + CHANNEL_SWITCH_SET_DEST_CH(h2c_buff, cs_option->dest_ch); + CHANNEL_SWITCH_SET_PRI_CH_IDX(h2c_buff, cs_option->dest_pri_ch_idx); + CHANNEL_SWITCH_SET_ABSOLUTE_TIME(h2c_buff, cs_option->absolute_time_en); + CHANNEL_SWITCH_SET_TSF_LOW(h2c_buff, cs_option->tsf_low); + CHANNEL_SWITCH_SET_PERIODIC_OPTION(h2c_buff, + cs_option->periodic_option); + CHANNEL_SWITCH_SET_NORMAL_CYCLE(h2c_buff, cs_option->normal_cycle); + CHANNEL_SWITCH_SET_NORMAL_PERIOD(h2c_buff, cs_option->normal_period); + CHANNEL_SWITCH_SET_SLOW_PERIOD(h2c_buff, cs_option->phase_2_period); + CHANNEL_SWITCH_SET_CHANNEL_INFO_SIZE( + h2c_buff, halmac_adapter->ch_sw_info.total_size); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_CHANNEL_SWITCH; + h2c_header_info.content_size = 20; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + halmac_adapter->halmac_state.scan_state_set.seq_num = h2c_seq_mum; + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + + kfree(halmac_adapter->ch_sw_info.ch_info_buf); + halmac_adapter->ch_sw_info.ch_info_buf = NULL; + halmac_adapter->ch_sw_info.ch_info_buf_w = NULL; + halmac_adapter->ch_sw_info.extra_info_en = 0; + halmac_adapter->ch_sw_info.buf_size = 0; + halmac_adapter->ch_sw_info.avai_buf_size = 0; + halmac_adapter->ch_sw_info.total_size = 0; + halmac_adapter->ch_sw_info.ch_num = 0; + + if (halmac_transition_scan_state_88xx(halmac_adapter, + HALMAC_SCAN_CMD_CONSTRUCT_IDLE) != + HALMAC_RET_SUCCESS) + return HALMAC_RET_ERROR_STATE; + + return status; +} + +enum halmac_ret_status +halmac_func_send_general_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_general_info *general_info) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "halmac_send_general_info!!\n"); + + GENERAL_INFO_SET_REF_TYPE(h2c_buff, general_info->rfe_type); + GENERAL_INFO_SET_RF_TYPE(h2c_buff, general_info->rf_type); + GENERAL_INFO_SET_FW_TX_BOUNDARY( + h2c_buff, + halmac_adapter->txff_allocation.rsvd_fw_txbuff_pg_bndy - + halmac_adapter->txff_allocation.rsvd_pg_bndy); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_GENERAL_INFO; + h2c_header_info.content_size = 4; + h2c_header_info.ack = false; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + + return status; +} + +enum halmac_ret_status halmac_send_h2c_update_bcn_parse_info_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_bcn_ie_info *bcn_ie_info) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u16 h2c_seq_mum = 0; + void *driver_adapter = NULL; + struct halmac_h2c_header_info h2c_header_info; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + driver_adapter = halmac_adapter->driver_adapter; + + UPDATE_BEACON_PARSING_INFO_SET_FUNC_EN(h2c_buff, bcn_ie_info->func_en); + UPDATE_BEACON_PARSING_INFO_SET_SIZE_TH(h2c_buff, bcn_ie_info->size_th); + UPDATE_BEACON_PARSING_INFO_SET_TIMEOUT(h2c_buff, bcn_ie_info->timeout); + + UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_0( + h2c_buff, (u32)(bcn_ie_info->ie_bmp[0])); + UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_1( + h2c_buff, (u32)(bcn_ie_info->ie_bmp[1])); + UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_2( + h2c_buff, (u32)(bcn_ie_info->ie_bmp[2])); + UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_3( + h2c_buff, (u32)(bcn_ie_info->ie_bmp[3])); + UPDATE_BEACON_PARSING_INFO_SET_IE_ID_BMP_4( + h2c_buff, (u32)(bcn_ie_info->ie_bmp[4])); + + h2c_header_info.sub_cmd_id = SUB_CMD_ID_UPDATE_BEACON_PARSING_INFO; + h2c_header_info.content_size = 24; + h2c_header_info.ack = true; + halmac_set_fw_offload_h2c_header_88xx(halmac_adapter, h2c_buff, + &h2c_header_info, &h2c_seq_mum); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, true); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail =%x !!\n", status); + return status; + } + + return status; +} + +enum halmac_ret_status +halmac_send_h2c_ps_tuning_para_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; + u8 *h2c_header, *h2c_cmd; + u16 seq = 0; + void *driver_adapter = NULL; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "%s!!\n", __func__); + + h2c_header = h2c_buff; + h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; + + halmac_set_h2c_header_88xx(halmac_adapter, h2c_header, &seq, false); + + status = halmac_send_h2c_pkt_88xx(halmac_adapter, h2c_buff, + HALMAC_H2C_CMD_SIZE_88XX, false); + + if (status != HALMAC_RET_SUCCESS) { + pr_err("halmac_send_h2c_pkt_88xx Fail = %x!!\n", status); + return status; + } + + return status; +} + +enum halmac_ret_status +halmac_parse_c2h_packet_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size) +{ + u8 c2h_cmd, c2h_sub_cmd_id; + u8 *c2h_buf = halmac_buf + halmac_adapter->hw_config_info.rxdesc_size; + u32 c2h_size = halmac_size - halmac_adapter->hw_config_info.rxdesc_size; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + c2h_cmd = (u8)C2H_HDR_GET_CMD_ID(c2h_buf); + + /* FW offload C2H cmd is 0xFF */ + if (c2h_cmd != 0xFF) { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "C2H_PKT not for FwOffloadC2HFormat!!\n"); + return HALMAC_RET_C2H_NOT_HANDLED; + } + + /* Get C2H sub cmd ID */ + c2h_sub_cmd_id = (u8)C2H_HDR_GET_C2H_SUB_CMD_ID(c2h_buf); + + switch (c2h_sub_cmd_id) { + case C2H_SUB_CMD_ID_C2H_DBG: + status = halmac_parse_c2h_debug_88xx(halmac_adapter, c2h_buf, + c2h_size); + break; + case C2H_SUB_CMD_ID_H2C_ACK_HDR: + status = halmac_parse_h2c_ack_88xx(halmac_adapter, c2h_buf, + c2h_size); + break; + case C2H_SUB_CMD_ID_BT_COEX_INFO: + status = HALMAC_RET_C2H_NOT_HANDLED; + break; + case C2H_SUB_CMD_ID_SCAN_STATUS_RPT: + status = halmac_parse_scan_status_rpt_88xx(halmac_adapter, + c2h_buf, c2h_size); + break; + case C2H_SUB_CMD_ID_PSD_DATA: + status = halmac_parse_psd_data_88xx(halmac_adapter, c2h_buf, + c2h_size); + break; + + case C2H_SUB_CMD_ID_EFUSE_DATA: + status = halmac_parse_efuse_data_88xx(halmac_adapter, c2h_buf, + c2h_size); + break; + default: + pr_err("c2h_sub_cmd_id switch case out of boundary!!\n"); + pr_err("[ERR]c2h pkt : %.8X %.8X!!\n", *(u32 *)c2h_buf, + *(u32 *)(c2h_buf + 4)); + status = HALMAC_RET_C2H_NOT_HANDLED; + break; + } + + return status; +} + +static enum halmac_ret_status +halmac_parse_c2h_debug_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size) +{ + void *driver_adapter = NULL; + u8 *c2h_buf_local = (u8 *)NULL; + u32 c2h_size_local = 0; + u8 dbg_content_length = 0; + u8 dbg_seq_num = 0; + + driver_adapter = halmac_adapter->driver_adapter; + c2h_buf_local = c2h_buf; + c2h_size_local = c2h_size; + + dbg_content_length = (u8)C2H_HDR_GET_LEN((u8 *)c2h_buf_local); + + if (dbg_content_length > C2H_DBG_CONTENT_MAX_LENGTH) + return HALMAC_RET_SUCCESS; + + *(c2h_buf_local + C2H_DBG_HEADER_LENGTH + dbg_content_length - 2) = + '\n'; + dbg_seq_num = (u8)(*(c2h_buf_local + C2H_DBG_HEADER_LENGTH)); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[RTKFW, SEQ=%d]: %s", dbg_seq_num, + (char *)(c2h_buf_local + C2H_DBG_HEADER_LENGTH + 1)); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_scan_status_rpt_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_return_code = (u8)SCAN_STATUS_RPT_GET_H2C_RETURN_CODE(c2h_buf); + process_status = (enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS ? + HALMAC_CMD_PROCESS_DONE : + HALMAC_CMD_PROCESS_ERROR; + + PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_CHANNEL_SWITCH, + process_status, NULL, 0); + + halmac_adapter->halmac_state.scan_state_set.process_status = + process_status; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]scan status : %X\n", process_status); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_psd_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size) +{ + u8 segment_id = 0, segment_size = 0, h2c_seq = 0; + u16 total_size; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + struct halmac_psd_state_set *psd_set = + &halmac_adapter->halmac_state.psd_set; + + h2c_seq = (u8)PSD_DATA_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + psd_set->seq_num, h2c_seq); + if (h2c_seq != psd_set->seq_num) { + pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n", + psd_set->seq_num, h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (psd_set->process_status != HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + total_size = (u16)PSD_DATA_GET_TOTAL_SIZE(c2h_buf); + segment_id = (u8)PSD_DATA_GET_SEGMENT_ID(c2h_buf); + segment_size = (u8)PSD_DATA_GET_SEGMENT_SIZE(c2h_buf); + psd_set->data_size = total_size; + + if (!psd_set->data) + psd_set->data = kzalloc(psd_set->data_size, GFP_KERNEL); + + if (segment_id == 0) + psd_set->segment_size = segment_size; + + memcpy(psd_set->data + segment_id * psd_set->segment_size, + c2h_buf + HALMAC_C2H_DATA_OFFSET_88XX, segment_size); + + if (!PSD_DATA_GET_END_SEGMENT(c2h_buf)) + return HALMAC_RET_SUCCESS; + + process_status = HALMAC_CMD_PROCESS_DONE; + psd_set->process_status = process_status; + + PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_PSD, + process_status, psd_set->data, + psd_set->data_size); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_efuse_data_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size) +{ + u8 segment_id = 0, segment_size = 0, h2c_seq = 0; + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + u8 h2c_return_code = 0; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_seq = (u8)EFUSE_DATA_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.efuse_state_set.seq_num, + h2c_seq); + if (h2c_seq != halmac_adapter->halmac_state.efuse_state_set.seq_num) { + pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.efuse_state_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.efuse_state_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + segment_id = (u8)EFUSE_DATA_GET_SEGMENT_ID(c2h_buf); + segment_size = (u8)EFUSE_DATA_GET_SEGMENT_SIZE(c2h_buf); + if (segment_id == 0) + halmac_adapter->efuse_segment_size = segment_size; + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + spin_lock(&halmac_adapter->efuse_lock); + memcpy(halmac_adapter->hal_efuse_map + + segment_id * halmac_adapter->efuse_segment_size, + c2h_buf + HALMAC_C2H_DATA_OFFSET_88XX, segment_size); + spin_unlock(&halmac_adapter->efuse_lock); + + if (!EFUSE_DATA_GET_END_SEGMENT(c2h_buf)) { + kfree(eeprom_map); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = + halmac_adapter->halmac_state.efuse_state_set.fw_return_code; + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS) { + process_status = HALMAC_CMD_PROCESS_DONE; + halmac_adapter->halmac_state.efuse_state_set.process_status = + process_status; + + spin_lock(&halmac_adapter->efuse_lock); + halmac_adapter->hal_efuse_map_valid = true; + spin_unlock(&halmac_adapter->efuse_lock); + + if (halmac_adapter->event_trigger.physical_efuse_map == 1) { + PLATFORM_EVENT_INDICATION( + driver_adapter, + HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE, + process_status, halmac_adapter->hal_efuse_map, + halmac_adapter->hw_config_info.efuse_size); + halmac_adapter->event_trigger.physical_efuse_map = 0; + } + + if (halmac_adapter->event_trigger.logical_efuse_map == 1) { + if (halmac_eeprom_parser_88xx( + halmac_adapter, + halmac_adapter->hal_efuse_map, + eeprom_map) != HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + PLATFORM_EVENT_INDICATION( + driver_adapter, + HALMAC_FEATURE_DUMP_LOGICAL_EFUSE, + process_status, eeprom_map, eeprom_size); + halmac_adapter->event_trigger.logical_efuse_map = 0; + } + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.efuse_state_set.process_status = + process_status; + + if (halmac_adapter->event_trigger.physical_efuse_map == 1) { + PLATFORM_EVENT_INDICATION( + driver_adapter, + HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE, + process_status, + &halmac_adapter->halmac_state.efuse_state_set + .fw_return_code, + 1); + halmac_adapter->event_trigger.physical_efuse_map = 0; + } + + if (halmac_adapter->event_trigger.logical_efuse_map == 1) { + if (halmac_eeprom_parser_88xx( + halmac_adapter, + halmac_adapter->hal_efuse_map, + eeprom_map) != HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + PLATFORM_EVENT_INDICATION( + driver_adapter, + HALMAC_FEATURE_DUMP_LOGICAL_EFUSE, + process_status, + &halmac_adapter->halmac_state.efuse_state_set + .fw_return_code, + 1); + halmac_adapter->event_trigger.logical_efuse_map = 0; + } + } + + kfree(eeprom_map); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_88xx(struct halmac_adapter *halmac_adapter, u8 *c2h_buf, + u32 c2h_size) +{ + u8 h2c_cmd_id, h2c_sub_cmd_id; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_ret_status status = HALMAC_RET_SUCCESS; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "Ack for C2H!!\n"); + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + if ((enum halmac_h2c_return_code)h2c_return_code != + HALMAC_H2C_RETURN_SUCCESS) + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "C2H_PKT Status Error!! Status = %d\n", + h2c_return_code); + + h2c_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_CMD_ID(c2h_buf); + + if (h2c_cmd_id != 0xFF) { + pr_err("original h2c ack is not handled!!\n"); + status = HALMAC_RET_C2H_NOT_HANDLED; + } else { + h2c_sub_cmd_id = (u8)H2C_ACK_HDR_GET_H2C_SUB_CMD_ID(c2h_buf); + + switch (h2c_sub_cmd_id) { + case H2C_SUB_CMD_ID_DUMP_PHYSICAL_EFUSE_ACK: + status = halmac_parse_h2c_ack_phy_efuse_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_CFG_PARAMETER_ACK: + status = halmac_parse_h2c_ack_cfg_para_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_UPDATE_PACKET_ACK: + status = halmac_parse_h2c_ack_update_packet_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_UPDATE_DATAPACK_ACK: + status = halmac_parse_h2c_ack_update_datapack_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_RUN_DATAPACK_ACK: + status = halmac_parse_h2c_ack_run_datapack_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_CHANNEL_SWITCH_ACK: + status = halmac_parse_h2c_ack_channel_switch_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_IQK_ACK: + status = halmac_parse_h2c_ack_iqk_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_POWER_TRACKING_ACK: + status = halmac_parse_h2c_ack_power_tracking_88xx( + halmac_adapter, c2h_buf, c2h_size); + break; + case H2C_SUB_CMD_ID_PSD_ACK: + break; + default: + pr_err("h2c_sub_cmd_id switch case out of boundary!!\n"); + status = HALMAC_RET_C2H_NOT_HANDLED; + break; + } + } + + return status; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_phy_efuse_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.efuse_state_set.seq_num, + h2c_seq); + if (h2c_seq != halmac_adapter->halmac_state.efuse_state_set.seq_num) { + pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.efuse_state_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.efuse_state_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.efuse_state_set.fw_return_code = + h2c_return_code; + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_cfg_para_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + u32 offset_accu = 0, value_accu = 0; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status = + HALMAC_CMD_PROCESS_UNDEFINE; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.cfg_para_state_set.seq_num, + h2c_seq); + if (h2c_seq != + halmac_adapter->halmac_state.cfg_para_state_set.seq_num) { + pr_err("Seq num mismatch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.cfg_para_state_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.cfg_para_state_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.cfg_para_state_set.fw_return_code = + h2c_return_code; + offset_accu = CFG_PARAMETER_ACK_GET_OFFSET_ACCUMULATION(c2h_buf); + value_accu = CFG_PARAMETER_ACK_GET_VALUE_ACCUMULATION(c2h_buf); + + if ((offset_accu != + halmac_adapter->config_para_info.offset_accumulation) || + (value_accu != + halmac_adapter->config_para_info.value_accumulation)) { + pr_err("[C2H]offset_accu : %x, value_accu : %x!!\n", + offset_accu, value_accu); + pr_err("[Adapter]offset_accu : %x, value_accu : %x!!\n", + halmac_adapter->config_para_info.offset_accumulation, + halmac_adapter->config_para_info.value_accumulation); + process_status = HALMAC_CMD_PROCESS_ERROR; + } + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS && + process_status != HALMAC_CMD_PROCESS_ERROR) { + process_status = HALMAC_CMD_PROCESS_DONE; + halmac_adapter->halmac_state.cfg_para_state_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION(driver_adapter, + HALMAC_FEATURE_CFG_PARA, + process_status, NULL, 0); + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.cfg_para_state_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_CFG_PARA, process_status, + &halmac_adapter->halmac_state.cfg_para_state_set + .fw_return_code, + 1); + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_update_packet_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.update_packet_set.seq_num, + h2c_seq); + if (h2c_seq != halmac_adapter->halmac_state.update_packet_set.seq_num) { + pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.update_packet_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.update_packet_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.update_packet_set.fw_return_code = + h2c_return_code; + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS) { + process_status = HALMAC_CMD_PROCESS_DONE; + halmac_adapter->halmac_state.update_packet_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION(driver_adapter, + HALMAC_FEATURE_UPDATE_PACKET, + process_status, NULL, 0); + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.update_packet_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_UPDATE_PACKET, + process_status, + &halmac_adapter->halmac_state.update_packet_set + .fw_return_code, + 1); + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_update_datapack_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status = + HALMAC_CMD_PROCESS_UNDEFINE; + + PLATFORM_EVENT_INDICATION(driver_adapter, + HALMAC_FEATURE_UPDATE_DATAPACK, + process_status, NULL, 0); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status = + HALMAC_CMD_PROCESS_UNDEFINE; + + PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_RUN_DATAPACK, + process_status, NULL, 0); + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_channel_switch_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.scan_state_set.seq_num, + h2c_seq); + if (h2c_seq != halmac_adapter->halmac_state.scan_state_set.seq_num) { + pr_err("[ERR]Seq num misactch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.scan_state_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.scan_state_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.scan_state_set.fw_return_code = + h2c_return_code; + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS) { + process_status = HALMAC_CMD_PROCESS_RCVD; + halmac_adapter->halmac_state.scan_state_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION(driver_adapter, + HALMAC_FEATURE_CHANNEL_SWITCH, + process_status, NULL, 0); + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.scan_state_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_CHANNEL_SWITCH, + process_status, &halmac_adapter->halmac_state + .scan_state_set.fw_return_code, + 1); + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_iqk_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.iqk_set.seq_num, h2c_seq); + if (h2c_seq != halmac_adapter->halmac_state.iqk_set.seq_num) { + pr_err("[ERR]Seq num misactch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.iqk_set.seq_num, h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.iqk_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.iqk_set.fw_return_code = h2c_return_code; + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS) { + process_status = HALMAC_CMD_PROCESS_DONE; + halmac_adapter->halmac_state.iqk_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION(driver_adapter, HALMAC_FEATURE_IQK, + process_status, NULL, 0); + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.iqk_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_IQK, process_status, + &halmac_adapter->halmac_state.iqk_set.fw_return_code, + 1); + } + + return HALMAC_RET_SUCCESS; +} + +static enum halmac_ret_status +halmac_parse_h2c_ack_power_tracking_88xx(struct halmac_adapter *halmac_adapter, + u8 *c2h_buf, u32 c2h_size) +{ + u8 h2c_seq = 0; + u8 h2c_return_code; + void *driver_adapter = halmac_adapter->driver_adapter; + enum halmac_cmd_process_status process_status; + + h2c_seq = (u8)H2C_ACK_HDR_GET_H2C_SEQ(c2h_buf); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, + "[TRACE]Seq num : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.power_tracking_set.seq_num, + h2c_seq); + if (h2c_seq != + halmac_adapter->halmac_state.power_tracking_set.seq_num) { + pr_err("[ERR]Seq num mismatch : h2c -> %d c2h -> %d\n", + halmac_adapter->halmac_state.power_tracking_set.seq_num, + h2c_seq); + return HALMAC_RET_SUCCESS; + } + + if (halmac_adapter->halmac_state.power_tracking_set.process_status != + HALMAC_CMD_PROCESS_SENDING) { + pr_err("[ERR]Not in HALMAC_CMD_PROCESS_SENDING\n"); + return HALMAC_RET_SUCCESS; + } + + h2c_return_code = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(c2h_buf); + halmac_adapter->halmac_state.power_tracking_set.fw_return_code = + h2c_return_code; + + if ((enum halmac_h2c_return_code)h2c_return_code == + HALMAC_H2C_RETURN_SUCCESS) { + process_status = HALMAC_CMD_PROCESS_DONE; + halmac_adapter->halmac_state.power_tracking_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION(driver_adapter, + HALMAC_FEATURE_POWER_TRACKING, + process_status, NULL, 0); + } else { + process_status = HALMAC_CMD_PROCESS_ERROR; + halmac_adapter->halmac_state.power_tracking_set.process_status = + process_status; + PLATFORM_EVENT_INDICATION( + driver_adapter, HALMAC_FEATURE_POWER_TRACKING, + process_status, + &halmac_adapter->halmac_state.power_tracking_set + .fw_return_code, + 1); + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_convert_to_sdio_bus_offset_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_offset) +{ + void *driver_adapter = NULL; + + driver_adapter = halmac_adapter->driver_adapter; + + switch ((*halmac_offset) & 0xFFFF0000) { + case WLAN_IOREG_OFFSET: + *halmac_offset = (HALMAC_SDIO_CMD_ADDR_MAC_REG << 13) | + (*halmac_offset & HALMAC_WLAN_MAC_REG_MSK); + break; + case SDIO_LOCAL_OFFSET: + *halmac_offset = (HALMAC_SDIO_CMD_ADDR_SDIO_REG << 13) | + (*halmac_offset & HALMAC_SDIO_LOCAL_MSK); + break; + default: + *halmac_offset = 0xFFFFFFFF; + pr_err("Unknown base address!!\n"); + return HALMAC_RET_CONVERT_SDIO_OFFSET_FAIL; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_update_sdio_free_page_88xx(struct halmac_adapter *halmac_adapter) +{ + u32 free_page = 0, free_page2 = 0, free_page3 = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_sdio_free_space *sdio_free_space; + u8 data[12] = {0}; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + sdio_free_space = &halmac_adapter->sdio_free_space; + /*need to use HALMAC_REG_READ_N, 20160316, Soar*/ + HALMAC_REG_SDIO_CMD53_READ_N(halmac_adapter, REG_SDIO_FREE_TXPG, 12, + data); + free_page = + data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + free_page2 = + data[4] | (data[5] << 8) | (data[6] << 16) | (data[7] << 24); + free_page3 = + data[8] | (data[9] << 8) | (data[10] << 16) | (data[11] << 24); + + sdio_free_space->high_queue_number = + (u16)BIT_GET_HIQ_FREEPG_V1(free_page); + sdio_free_space->normal_queue_number = + (u16)BIT_GET_MID_FREEPG_V1(free_page); + sdio_free_space->low_queue_number = + (u16)BIT_GET_LOW_FREEPG_V1(free_page2); + sdio_free_space->public_queue_number = + (u16)BIT_GET_PUB_FREEPG_V1(free_page2); + sdio_free_space->extra_queue_number = + (u16)BIT_GET_EXQ_FREEPG_V1(free_page3); + sdio_free_space->ac_oqt_number = (u8)((free_page3 >> 16) & 0xFF); + sdio_free_space->non_ac_oqt_number = (u8)((free_page3 >> 24) & 0xFF); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_update_oqt_free_space_88xx(struct halmac_adapter *halmac_adapter) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + struct halmac_sdio_free_space *sdio_free_space; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s ==========>\n", __func__); + + sdio_free_space = &halmac_adapter->sdio_free_space; + + sdio_free_space->ac_oqt_number = HALMAC_REG_READ_8( + halmac_adapter, REG_SDIO_OQT_FREE_TXPG_V1 + 2); + sdio_free_space->ac_empty = + HALMAC_REG_READ_8(halmac_adapter, REG_TXPKT_EMPTY); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG, + "%s <==========\n", __func__); + + return HALMAC_RET_SUCCESS; +} + +enum halmac_efuse_cmd_construct_state +halmac_query_efuse_curr_state_88xx(struct halmac_adapter *halmac_adapter) +{ + return halmac_adapter->halmac_state.efuse_state_set + .efuse_cmd_construct_state; +} + +enum halmac_ret_status halmac_transition_efuse_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_efuse_cmd_construct_state dest_state) +{ + struct halmac_efuse_state_set *efuse_state = + &halmac_adapter->halmac_state.efuse_state_set; + + if (efuse_state->efuse_cmd_construct_state != + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE && + efuse_state->efuse_cmd_construct_state != + HALMAC_EFUSE_CMD_CONSTRUCT_BUSY && + efuse_state->efuse_cmd_construct_state != + HALMAC_EFUSE_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + + if (efuse_state->efuse_cmd_construct_state == dest_state) + return HALMAC_RET_ERROR_STATE; + + if (dest_state == HALMAC_EFUSE_CMD_CONSTRUCT_BUSY) { + if (efuse_state->efuse_cmd_construct_state == + HALMAC_EFUSE_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_EFUSE_CMD_CONSTRUCT_H2C_SENT) { + if (efuse_state->efuse_cmd_construct_state == + HALMAC_EFUSE_CMD_CONSTRUCT_IDLE) + return HALMAC_RET_ERROR_STATE; + } + + efuse_state->efuse_cmd_construct_state = dest_state; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_cfg_para_cmd_construct_state +halmac_query_cfg_para_curr_state_88xx(struct halmac_adapter *halmac_adapter) +{ + return halmac_adapter->halmac_state.cfg_para_state_set + .cfg_para_cmd_construct_state; +} + +enum halmac_ret_status halmac_transition_cfg_para_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cfg_para_cmd_construct_state dest_state) +{ + struct halmac_cfg_para_state_set *cfg_para = + &halmac_adapter->halmac_state.cfg_para_state_set; + + if (cfg_para->cfg_para_cmd_construct_state != + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE && + cfg_para->cfg_para_cmd_construct_state != + HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING && + cfg_para->cfg_para_cmd_construct_state != + HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + + if (dest_state == HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE) { + if (cfg_para->cfg_para_cmd_construct_state == + HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_CFG_PARA_CMD_CONSTRUCT_CONSTRUCTING) { + if (cfg_para->cfg_para_cmd_construct_state == + HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) { + if (cfg_para->cfg_para_cmd_construct_state == + HALMAC_CFG_PARA_CMD_CONSTRUCT_IDLE || + cfg_para->cfg_para_cmd_construct_state == + HALMAC_CFG_PARA_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + } + + cfg_para->cfg_para_cmd_construct_state = dest_state; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_scan_cmd_construct_state +halmac_query_scan_curr_state_88xx(struct halmac_adapter *halmac_adapter) +{ + return halmac_adapter->halmac_state.scan_state_set + .scan_cmd_construct_state; +} + +enum halmac_ret_status halmac_transition_scan_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_scan_cmd_construct_state dest_state) +{ + struct halmac_scan_state_set *scan = + &halmac_adapter->halmac_state.scan_state_set; + + if (scan->scan_cmd_construct_state > HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + + if (dest_state == HALMAC_SCAN_CMD_CONSTRUCT_IDLE) { + if (scan->scan_cmd_construct_state == + HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED || + scan->scan_cmd_construct_state == + HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) { + if (scan->scan_cmd_construct_state == + HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING) { + if (scan->scan_cmd_construct_state == + HALMAC_SCAN_CMD_CONSTRUCT_IDLE || + scan->scan_cmd_construct_state == + HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) + return HALMAC_RET_ERROR_STATE; + } else if (dest_state == HALMAC_SCAN_CMD_CONSTRUCT_H2C_SENT) { + if (scan->scan_cmd_construct_state != + HALMAC_SCAN_CMD_CONSTRUCT_CONSTRUCTING && + scan->scan_cmd_construct_state != + HALMAC_SCAN_CMD_CONSTRUCT_BUFFER_CLEARED) + return HALMAC_RET_ERROR_STATE; + } + + scan->scan_cmd_construct_state = dest_state; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_cfg_para_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + struct halmac_cfg_para_state_set *cfg_para_state_set = + &halmac_adapter->halmac_state.cfg_para_state_set; + + *process_status = cfg_para_state_set->process_status; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_dump_physical_efuse_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + void *driver_adapter = NULL; + struct halmac_efuse_state_set *efuse_state_set = + &halmac_adapter->halmac_state.efuse_state_set; + + driver_adapter = halmac_adapter->driver_adapter; + + *process_status = efuse_state_set->process_status; + + if (!data) + return HALMAC_RET_NULL_POINTER; + + if (!size) + return HALMAC_RET_NULL_POINTER; + + if (*process_status == HALMAC_CMD_PROCESS_DONE) { + if (*size < halmac_adapter->hw_config_info.efuse_size) { + *size = halmac_adapter->hw_config_info.efuse_size; + return HALMAC_RET_BUFFER_TOO_SMALL; + } + + *size = halmac_adapter->hw_config_info.efuse_size; + memcpy(data, halmac_adapter->hal_efuse_map, *size); + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_dump_logical_efuse_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + u8 *eeprom_map = NULL; + u32 eeprom_size = halmac_adapter->hw_config_info.eeprom_size; + void *driver_adapter = NULL; + struct halmac_efuse_state_set *efuse_state_set = + &halmac_adapter->halmac_state.efuse_state_set; + + driver_adapter = halmac_adapter->driver_adapter; + + *process_status = efuse_state_set->process_status; + + if (!data) + return HALMAC_RET_NULL_POINTER; + + if (!size) + return HALMAC_RET_NULL_POINTER; + + if (*process_status == HALMAC_CMD_PROCESS_DONE) { + if (*size < eeprom_size) { + *size = eeprom_size; + return HALMAC_RET_BUFFER_TOO_SMALL; + } + + *size = eeprom_size; + + eeprom_map = kzalloc(eeprom_size, GFP_KERNEL); + if (!eeprom_map) { + /* out of memory */ + return HALMAC_RET_MALLOC_FAIL; + } + memset(eeprom_map, 0xFF, eeprom_size); + + if (halmac_eeprom_parser_88xx( + halmac_adapter, halmac_adapter->hal_efuse_map, + eeprom_map) != HALMAC_RET_SUCCESS) { + kfree(eeprom_map); + return HALMAC_RET_EEPROM_PARSING_FAIL; + } + + memcpy(data, eeprom_map, *size); + + kfree(eeprom_map); + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_channel_switch_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + struct halmac_scan_state_set *scan_state_set = + &halmac_adapter->halmac_state.scan_state_set; + + *process_status = scan_state_set->process_status; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_update_packet_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + struct halmac_update_packet_state_set *update_packet_set = + &halmac_adapter->halmac_state.update_packet_set; + + *process_status = update_packet_set->process_status; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_query_iqk_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size) +{ + struct halmac_iqk_state_set *iqk_set = + &halmac_adapter->halmac_state.iqk_set; + + *process_status = iqk_set->process_status; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status halmac_query_power_tracking_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size) +{ + struct halmac_power_tracking_state_set *power_tracking_state_set = + &halmac_adapter->halmac_state.power_tracking_set; + ; + + *process_status = power_tracking_state_set->process_status; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_query_psd_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size) +{ + void *driver_adapter = NULL; + struct halmac_psd_state_set *psd_set = + &halmac_adapter->halmac_state.psd_set; + + driver_adapter = halmac_adapter->driver_adapter; + + *process_status = psd_set->process_status; + + if (!data) + return HALMAC_RET_NULL_POINTER; + + if (!size) + return HALMAC_RET_NULL_POINTER; + + if (*process_status == HALMAC_CMD_PROCESS_DONE) { + if (*size < psd_set->data_size) { + *size = psd_set->data_size; + return HALMAC_RET_BUFFER_TOO_SMALL; + } + + *size = psd_set->data_size; + memcpy(data, psd_set->data, *size); + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_verify_io_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 value8, wvalue8; + u32 value32, value32_2, wvalue32; + u32 halmac_offset; + void *driver_adapter = NULL; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + if (halmac_adapter->halmac_interface == HALMAC_INTERFACE_SDIO) { + halmac_offset = REG_PAGE5_DUMMY; + if ((halmac_offset & 0xFFFF0000) == 0) + halmac_offset |= WLAN_IOREG_OFFSET; + + ret_status = halmac_convert_to_sdio_bus_offset_88xx( + halmac_adapter, &halmac_offset); + + /* Verify CMD52 R/W */ + wvalue8 = 0xab; + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, + wvalue8); + + value8 = + PLATFORM_SDIO_CMD52_READ(driver_adapter, halmac_offset); + + if (value8 != wvalue8) { + pr_err("cmd52 r/w fail write = %X read = %X\n", wvalue8, + value8); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "cmd52 r/w ok\n"); + } + + /* Verify CMD53 R/W */ + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset, 0xaa); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 1, + 0xbb); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 2, + 0xcc); + PLATFORM_SDIO_CMD52_WRITE(driver_adapter, halmac_offset + 3, + 0xdd); + + value32 = PLATFORM_SDIO_CMD53_READ_32(driver_adapter, + halmac_offset); + + if (value32 != 0xddccbbaa) { + pr_err("cmd53 r fail : read = %X\n", value32); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "cmd53 r ok\n"); + } + + wvalue32 = 0x11223344; + PLATFORM_SDIO_CMD53_WRITE_32(driver_adapter, halmac_offset, + wvalue32); + + value32 = PLATFORM_SDIO_CMD53_READ_32(driver_adapter, + halmac_offset); + + if (value32 != wvalue32) { + pr_err("cmd53 w fail\n"); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "cmd53 w ok\n"); + } + + value32 = PLATFORM_SDIO_CMD53_READ_32( + driver_adapter, + halmac_offset + 2); /* value32 should be 0x33441122 */ + + wvalue32 = 0x11225566; + PLATFORM_SDIO_CMD53_WRITE_32(driver_adapter, halmac_offset, + wvalue32); + + value32_2 = PLATFORM_SDIO_CMD53_READ_32( + driver_adapter, + halmac_offset + 2); /* value32 should be 0x55661122 */ + if (value32_2 == value32) { + pr_err("cmd52 is used for HAL_SDIO_CMD53_READ_32\n"); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "cmd53 is correctly used\n"); + } + } else { + wvalue32 = 0x77665511; + PLATFORM_REG_WRITE_32(driver_adapter, REG_PAGE5_DUMMY, + wvalue32); + + value32 = PLATFORM_REG_READ_32(driver_adapter, REG_PAGE5_DUMMY); + if (value32 != wvalue32) { + pr_err("reg rw\n"); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } else { + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "reg rw ok\n"); + } + } + + return ret_status; +} + +enum halmac_ret_status +halmac_verify_send_rsvd_page_88xx(struct halmac_adapter *halmac_adapter) +{ + u8 *rsvd_buf = NULL; + u8 *rsvd_page = NULL; + u32 i; + u32 h2c_pkt_verify_size = 64, h2c_pkt_verify_payload = 0xab; + void *driver_adapter = NULL; + enum halmac_ret_status ret_status = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + + rsvd_buf = kzalloc(h2c_pkt_verify_size, GFP_KERNEL); + + if (!rsvd_buf) { + /*pr_err("[ERR]rsvd buffer malloc fail!!\n");*/ + return HALMAC_RET_MALLOC_FAIL; + } + + memset(rsvd_buf, (u8)h2c_pkt_verify_payload, h2c_pkt_verify_size); + + ret_status = halmac_download_rsvd_page_88xx(halmac_adapter, rsvd_buf, + h2c_pkt_verify_size); + + if (ret_status != HALMAC_RET_SUCCESS) { + kfree(rsvd_buf); + return ret_status; + } + + rsvd_page = kzalloc(h2c_pkt_verify_size + + halmac_adapter->hw_config_info.txdesc_size, + GFP_KERNEL); + + if (!rsvd_page) { + pr_err("[ERR]rsvd page malloc fail!!\n"); + kfree(rsvd_buf); + return HALMAC_RET_MALLOC_FAIL; + } + + ret_status = halmac_dump_fifo_88xx( + halmac_adapter, HAL_FIFO_SEL_RSVD_PAGE, 0, + h2c_pkt_verify_size + + halmac_adapter->hw_config_info.txdesc_size, + rsvd_page); + + if (ret_status != HALMAC_RET_SUCCESS) { + kfree(rsvd_buf); + kfree(rsvd_page); + return ret_status; + } + + for (i = 0; i < h2c_pkt_verify_size; i++) { + if (*(rsvd_buf + i) != + *(rsvd_page + + (i + halmac_adapter->hw_config_info.txdesc_size))) { + pr_err("[ERR]Compare RSVD page Fail\n"); + ret_status = HALMAC_RET_PLATFORM_API_INCORRECT; + } + } + + kfree(rsvd_buf); + kfree(rsvd_page); + + return ret_status; +} + +void halmac_power_save_cb_88xx(void *cb_data) +{ + void *driver_adapter = NULL; + struct halmac_adapter *halmac_adapter = (struct halmac_adapter *)NULL; + + halmac_adapter = (struct halmac_adapter *)cb_data; + driver_adapter = halmac_adapter->driver_adapter; + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_PWR, DBG_DMESG, + "%s\n", __func__); +} + +enum halmac_ret_status +halmac_buffer_read_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, enum hal_fifo_sel halmac_fifo_sel, + u8 *fifo_map) +{ + u32 start_page, value_read; + u32 i, counter = 0, residue; + struct halmac_api *halmac_api; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (halmac_fifo_sel == HAL_FIFO_SEL_RSVD_PAGE) + offset = offset + + (halmac_adapter->txff_allocation.rsvd_pg_bndy << 7); + + start_page = offset >> 12; + residue = offset & (4096 - 1); + + if (halmac_fifo_sel == HAL_FIFO_SEL_TX || + halmac_fifo_sel == HAL_FIFO_SEL_RSVD_PAGE) + start_page += 0x780; + else if (halmac_fifo_sel == HAL_FIFO_SEL_RX) + start_page += 0x700; + else if (halmac_fifo_sel == HAL_FIFO_SEL_REPORT) + start_page += 0x660; + else if (halmac_fifo_sel == HAL_FIFO_SEL_LLT) + start_page += 0x650; + else + return HALMAC_RET_NOT_SUPPORT; + + value_read = HALMAC_REG_READ_16(halmac_adapter, REG_PKTBUF_DBG_CTRL); + + do { + HALMAC_REG_WRITE_16(halmac_adapter, REG_PKTBUF_DBG_CTRL, + (u16)(start_page | (value_read & 0xF000))); + + for (i = 0x8000 + residue; i <= 0x8FFF; i += 4) { + *(u32 *)(fifo_map + counter) = + HALMAC_REG_READ_32(halmac_adapter, i); + *(u32 *)(fifo_map + counter) = + le32_to_cpu(*(__le32 *)(fifo_map + counter)); + counter += 4; + if (size == counter) + goto HALMAC_BUF_READ_OK; + } + + residue = 0; + start_page++; + } while (1); + +HALMAC_BUF_READ_OK: + HALMAC_REG_WRITE_16(halmac_adapter, REG_PKTBUF_DBG_CTRL, + (u16)value_read); + + return HALMAC_RET_SUCCESS; +} + +void halmac_restore_mac_register_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_restore_info *restore_info, + u32 restore_num) +{ + u8 value_length; + u32 i; + u32 mac_register; + u32 mac_value; + struct halmac_api *halmac_api; + struct halmac_restore_info *curr_restore_info = restore_info; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + for (i = 0; i < restore_num; i++) { + mac_register = curr_restore_info->mac_register; + mac_value = curr_restore_info->value; + value_length = curr_restore_info->length; + + if (value_length == 1) + HALMAC_REG_WRITE_8(halmac_adapter, mac_register, + (u8)mac_value); + else if (value_length == 2) + HALMAC_REG_WRITE_16(halmac_adapter, mac_register, + (u16)mac_value); + else if (value_length == 4) + HALMAC_REG_WRITE_32(halmac_adapter, mac_register, + mac_value); + + curr_restore_info++; + } +} + +void halmac_api_record_id_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_api_id api_id) +{ +} + +enum halmac_ret_status +halmac_set_usb_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_usb_mode usb_mode) +{ + u32 usb_temp; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + enum halmac_usb_mode current_usb_mode; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + current_usb_mode = + HALMAC_REG_READ_8(halmac_adapter, REG_SYS_CFG2 + 3) == 0x20 ? + HALMAC_USB_MODE_U3 : + HALMAC_USB_MODE_U2; + + /*check if HW supports usb2_usb3 swtich*/ + usb_temp = HALMAC_REG_READ_32(halmac_adapter, REG_PAD_CTRL2); + if (!BIT_GET_USB23_SW_MODE_V1(usb_temp) && + !(usb_temp & BIT_USB3_USB2_TRANSITION)) { + pr_err("HALMAC_HW_USB_MODE usb mode HW unsupport\n"); + return HALMAC_RET_USB2_3_SWITCH_UNSUPPORT; + } + + if (usb_mode == current_usb_mode) { + pr_err("HALMAC_HW_USB_MODE usb mode unchange\n"); + return HALMAC_RET_USB_MODE_UNCHANGE; + } + + usb_temp &= ~(BIT_USB23_SW_MODE_V1(0x3)); + + if (usb_mode == HALMAC_USB_MODE_U2) { + /* usb3 to usb2 */ + HALMAC_REG_WRITE_32( + halmac_adapter, REG_PAD_CTRL2, + usb_temp | BIT_USB23_SW_MODE_V1(HALMAC_USB_MODE_U2) | + BIT_RSM_EN_V1); + } else { + /* usb2 to usb3 */ + HALMAC_REG_WRITE_32( + halmac_adapter, REG_PAD_CTRL2, + usb_temp | BIT_USB23_SW_MODE_V1(HALMAC_USB_MODE_U3) | + BIT_RSM_EN_V1); + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PAD_CTRL2 + 1, + 4); /* set counter down timer 4x64 ms */ + HALMAC_REG_WRITE_16( + halmac_adapter, REG_SYS_PW_CTRL, + HALMAC_REG_READ_16(halmac_adapter, REG_SYS_PW_CTRL) | + BIT_APFM_OFFMAC); + usleep_range(1000, 1100); + HALMAC_REG_WRITE_32(halmac_adapter, REG_PAD_CTRL2, + HALMAC_REG_READ_32(halmac_adapter, REG_PAD_CTRL2) | + BIT_NO_PDN_CHIPOFF_V1); + + return HALMAC_RET_SUCCESS; +} + +void halmac_enable_bb_rf_88xx(struct halmac_adapter *halmac_adapter, u8 enable) +{ + u8 value8; + u32 value32; + struct halmac_api *halmac_api; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (enable == 1) { + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN); + value8 = value8 | BIT(0) | BIT(1); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RF_CTRL); + value8 = value8 | BIT(0) | BIT(1) | BIT(2); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RF_CTRL, value8); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_WLRF1); + value32 = value32 | BIT(24) | BIT(25) | BIT(26); + HALMAC_REG_WRITE_32(halmac_adapter, REG_WLRF1, value32); + } else { + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_SYS_FUNC_EN); + value8 = value8 & (~(BIT(0) | BIT(1))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_SYS_FUNC_EN, value8); + + value8 = HALMAC_REG_READ_8(halmac_adapter, REG_RF_CTRL); + value8 = value8 & (~(BIT(0) | BIT(1) | BIT(2))); + HALMAC_REG_WRITE_8(halmac_adapter, REG_RF_CTRL, value8); + + value32 = HALMAC_REG_READ_32(halmac_adapter, REG_WLRF1); + value32 = value32 & (~(BIT(24) | BIT(25) | BIT(26))); + HALMAC_REG_WRITE_32(halmac_adapter, REG_WLRF1, value32); + } +} + +void halmac_config_sdio_tx_page_threshold_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_tx_page_threshold_info *threshold_info) +{ + struct halmac_api *halmac_api; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (threshold_info->dma_queue_sel) { + case HALMAC_MAP2_HQ: + HALMAC_REG_WRITE_32(halmac_adapter, REG_TQPNT1, + threshold_info->threshold); + break; + case HALMAC_MAP2_NQ: + HALMAC_REG_WRITE_32(halmac_adapter, REG_TQPNT2, + threshold_info->threshold); + break; + case HALMAC_MAP2_LQ: + HALMAC_REG_WRITE_32(halmac_adapter, REG_TQPNT3, + threshold_info->threshold); + break; + case HALMAC_MAP2_EXQ: + HALMAC_REG_WRITE_32(halmac_adapter, REG_TQPNT4, + threshold_info->threshold); + break; + default: + break; + } +} + +void halmac_config_ampdu_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ampdu_config *ampdu_config) +{ + struct halmac_api *halmac_api; + + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PROT_MODE_CTRL + 2, + ampdu_config->max_agg_num); + HALMAC_REG_WRITE_8(halmac_adapter, REG_PROT_MODE_CTRL + 3, + ampdu_config->max_agg_num); +}; + +enum halmac_ret_status +halmac_check_oqt_88xx(struct halmac_adapter *halmac_adapter, u32 tx_agg_num, + u8 *halmac_buf) +{ + u32 counter = 10; + + /*S0, S1 are not allowed to use, 0x4E4[0] should be 0. Soar 20160323*/ + /*no need to check non_ac_oqt_number. HI and MGQ blocked will cause + *protocal issue before H_OQT being full + */ + switch ((enum halmac_queue_select)GET_TX_DESC_QSEL(halmac_buf)) { + case HALMAC_QUEUE_SELECT_VO: + case HALMAC_QUEUE_SELECT_VO_V2: + case HALMAC_QUEUE_SELECT_VI: + case HALMAC_QUEUE_SELECT_VI_V2: + case HALMAC_QUEUE_SELECT_BE: + case HALMAC_QUEUE_SELECT_BE_V2: + case HALMAC_QUEUE_SELECT_BK: + case HALMAC_QUEUE_SELECT_BK_V2: + counter = 10; + do { + if (halmac_adapter->sdio_free_space.ac_empty > 0) { + halmac_adapter->sdio_free_space.ac_empty -= 1; + break; + } + + if (halmac_adapter->sdio_free_space.ac_oqt_number >= + tx_agg_num) { + halmac_adapter->sdio_free_space.ac_oqt_number -= + (u8)tx_agg_num; + break; + } + + halmac_update_oqt_free_space_88xx(halmac_adapter); + + counter--; + if (counter == 0) + return HALMAC_RET_OQT_NOT_ENOUGH; + } while (1); + break; + default: + break; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_rqpn_parser_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode, + struct halmac_rqpn_ *rqpn_table) +{ + u8 search_flag; + u32 i; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + search_flag = 0; + for (i = 0; i < HALMAC_TRX_MODE_MAX; i++) { + if (halmac_trx_mode == rqpn_table[i].mode) { + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO] = + rqpn_table[i].dma_map_vo; + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI] = + rqpn_table[i].dma_map_vi; + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE] = + rqpn_table[i].dma_map_be; + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK] = + rqpn_table[i].dma_map_bk; + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG] = + rqpn_table[i].dma_map_mg; + halmac_adapter + ->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_HI] = + rqpn_table[i].dma_map_hi; + search_flag = 1; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "%s done\n", __func__); + break; + } + } + + if (search_flag == 0) { + pr_err("HALMAC_RET_TRX_MODE_NOT_SUPPORT 1 switch case not support\n"); + return HALMAC_RET_TRX_MODE_NOT_SUPPORT; + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_pg_num_parser_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode, + struct halmac_pg_num_ *pg_num_table) +{ + u8 search_flag; + u16 HPQ_num = 0, lpq_nnum = 0, NPQ_num = 0, GAPQ_num = 0; + u16 EXPQ_num = 0, PUBQ_num = 0; + u32 i = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + search_flag = 0; + for (i = 0; i < HALMAC_TRX_MODE_MAX; i++) { + if (halmac_trx_mode == pg_num_table[i].mode) { + HPQ_num = pg_num_table[i].hq_num; + lpq_nnum = pg_num_table[i].lq_num; + NPQ_num = pg_num_table[i].nq_num; + EXPQ_num = pg_num_table[i].exq_num; + GAPQ_num = pg_num_table[i].gap_num; + PUBQ_num = halmac_adapter->txff_allocation.ac_q_pg_num - + HPQ_num - lpq_nnum - NPQ_num - EXPQ_num - + GAPQ_num; + search_flag = 1; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, + DBG_DMESG, "%s done\n", __func__); + break; + } + } + + if (search_flag == 0) { + pr_err("HALMAC_RET_TRX_MODE_NOT_SUPPORT 1 switch case not support\n"); + return HALMAC_RET_TRX_MODE_NOT_SUPPORT; + } + + if (halmac_adapter->txff_allocation.ac_q_pg_num < + HPQ_num + lpq_nnum + NPQ_num + EXPQ_num + GAPQ_num) + return HALMAC_RET_CFG_TXFIFO_PAGE_FAIL; + + halmac_adapter->txff_allocation.high_queue_pg_num = HPQ_num; + halmac_adapter->txff_allocation.low_queue_pg_num = lpq_nnum; + halmac_adapter->txff_allocation.normal_queue_pg_num = NPQ_num; + halmac_adapter->txff_allocation.extra_queue_pg_num = EXPQ_num; + halmac_adapter->txff_allocation.pub_queue_pg_num = PUBQ_num; + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_parse_intf_phy_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_intf_phy_para_ *intf_phy_para, + enum halmac_intf_phy_platform platform, + enum hal_intf_phy intf_phy) +{ + u16 value; + u16 curr_cut; + u16 offset; + u16 ip_sel; + struct halmac_intf_phy_para_ *curr_phy_para; + struct halmac_api *halmac_api; + void *driver_adapter = NULL; + u8 result = HALMAC_RET_SUCCESS; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + switch (halmac_adapter->chip_version) { + case HALMAC_CHIP_VER_A_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_A; + break; + case HALMAC_CHIP_VER_B_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_B; + break; + case HALMAC_CHIP_VER_C_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_C; + break; + case HALMAC_CHIP_VER_D_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_D; + break; + case HALMAC_CHIP_VER_E_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_E; + break; + case HALMAC_CHIP_VER_F_CUT: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_F; + break; + case HALMAC_CHIP_VER_TEST: + curr_cut = (u16)HALMAC_INTF_PHY_CUT_TESTCHIP; + break; + default: + return HALMAC_RET_FAIL; + } + + for (curr_phy_para = intf_phy_para;; curr_phy_para++) { + if (!(curr_phy_para->cut & curr_cut) || + !(curr_phy_para->plaform & (u16)platform)) + continue; + + offset = curr_phy_para->offset; + value = curr_phy_para->value; + ip_sel = curr_phy_para->ip_sel; + + if (offset == 0xFFFF) + break; + + if (ip_sel == HALMAC_IP_SEL_MAC) { + HALMAC_REG_WRITE_8(halmac_adapter, (u32)offset, + (u8)value); + } else if (intf_phy == HAL_INTF_PHY_USB2) { + result = halmac_usbphy_write_88xx(halmac_adapter, + (u8)offset, value, + HAL_INTF_PHY_USB2); + + if (result != HALMAC_RET_SUCCESS) + pr_err("[ERR]Write USB2PHY fail!\n"); + + } else if (intf_phy == HAL_INTF_PHY_USB3) { + result = halmac_usbphy_write_88xx(halmac_adapter, + (u8)offset, value, + HAL_INTF_PHY_USB3); + + if (result != HALMAC_RET_SUCCESS) + pr_err("[ERR]Write USB3PHY fail!\n"); + + } else if (intf_phy == HAL_INTF_PHY_PCIE_GEN1) { + if (ip_sel == HALMAC_IP_SEL_INTF_PHY) + result = halmac_mdio_write_88xx( + halmac_adapter, (u8)offset, value, + HAL_INTF_PHY_PCIE_GEN1); + else + result = halmac_dbi_write8_88xx( + halmac_adapter, offset, (u8)value); + + if (result != HALMAC_RET_SUCCESS) + pr_err("[ERR]MDIO write GEN1 fail!\n"); + + } else if (intf_phy == HAL_INTF_PHY_PCIE_GEN2) { + if (ip_sel == HALMAC_IP_SEL_INTF_PHY) + result = halmac_mdio_write_88xx( + halmac_adapter, (u8)offset, value, + HAL_INTF_PHY_PCIE_GEN2); + else + result = halmac_dbi_write8_88xx( + halmac_adapter, offset, (u8)value); + + if (result != HALMAC_RET_SUCCESS) + pr_err("[ERR]MDIO write GEN2 fail!\n"); + } else { + pr_err("[ERR]Parse intf phy cfg error!\n"); + } + } + + return HALMAC_RET_SUCCESS; +} + +enum halmac_ret_status +halmac_dbi_write32_88xx(struct halmac_adapter *halmac_adapter, u16 addr, + u32 data) +{ + u8 tmp_u1b = 0; + u32 count = 0; + u16 write_addr = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_32(halmac_adapter, REG_DBI_WDATA_V1, data); + + write_addr = ((addr & 0x0ffc) | (0x000F << 12)); + HALMAC_REG_WRITE_16(halmac_adapter, REG_DBI_FLAG_V1, write_addr); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_DBI, DBG_DMESG, + "WriteAddr = %x\n", write_addr); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_DBI_FLAG_V1 + 2, 0x01); + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + + count = 20; + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = + HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + count--; + } + + if (tmp_u1b) { + pr_err("DBI write fail!\n"); + return HALMAC_RET_FAIL; + } else { + return HALMAC_RET_SUCCESS; + } +} + +u32 halmac_dbi_read32_88xx(struct halmac_adapter *halmac_adapter, u16 addr) +{ + u16 read_addr = addr & 0x0ffc; + u8 tmp_u1b = 0; + u32 count = 0; + u32 ret = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_16(halmac_adapter, REG_DBI_FLAG_V1, read_addr); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_DBI_FLAG_V1 + 2, 0x2); + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + + count = 20; + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = + HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + count--; + } + + if (tmp_u1b) { + ret = 0xFFFF; + pr_err("DBI read fail!\n"); + } else { + ret = HALMAC_REG_READ_32(halmac_adapter, REG_DBI_RDATA_V1); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_DBI, DBG_DMESG, + "Read Value = %x\n", ret); + } + + return ret; +} + +enum halmac_ret_status +halmac_dbi_write8_88xx(struct halmac_adapter *halmac_adapter, u16 addr, u8 data) +{ + u8 tmp_u1b = 0; + u32 count = 0; + u16 write_addr = 0; + u16 remainder = addr & (4 - 1); + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_8(halmac_adapter, REG_DBI_WDATA_V1 + remainder, data); + + write_addr = ((addr & 0x0ffc) | (BIT(0) << (remainder + 12))); + + HALMAC_REG_WRITE_16(halmac_adapter, REG_DBI_FLAG_V1, write_addr); + + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_DBI, DBG_DMESG, + "WriteAddr = %x\n", write_addr); + + HALMAC_REG_WRITE_8(halmac_adapter, REG_DBI_FLAG_V1 + 2, 0x01); + + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + + count = 20; + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = + HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + count--; + } + + if (tmp_u1b) { + pr_err("DBI write fail!\n"); + return HALMAC_RET_FAIL; + } else { + return HALMAC_RET_SUCCESS; + } +} + +u8 halmac_dbi_read8_88xx(struct halmac_adapter *halmac_adapter, u16 addr) +{ + u16 read_addr = addr & 0x0ffc; + u8 tmp_u1b = 0; + u32 count = 0; + u8 ret = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_16(halmac_adapter, REG_DBI_FLAG_V1, read_addr); + HALMAC_REG_WRITE_8(halmac_adapter, REG_DBI_FLAG_V1 + 2, 0x2); + + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + + count = 20; + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = + HALMAC_REG_READ_8(halmac_adapter, REG_DBI_FLAG_V1 + 2); + count--; + } + + if (tmp_u1b) { + ret = 0xFF; + pr_err("DBI read fail!\n"); + } else { + ret = HALMAC_REG_READ_8(halmac_adapter, + REG_DBI_RDATA_V1 + (addr & (4 - 1))); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_DBI, DBG_DMESG, + "Read Value = %x\n", ret); + } + + return ret; +} + +enum halmac_ret_status +halmac_mdio_write_88xx(struct halmac_adapter *halmac_adapter, u8 addr, u16 data, + u8 speed) +{ + u8 tmp_u1b = 0; + u32 count = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u8 real_addr = 0; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + HALMAC_REG_WRITE_16(halmac_adapter, REG_MDIO_V1, data); + + /* address : 5bit */ + real_addr = (addr & 0x1F); + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG, real_addr); + + if (speed == HAL_INTF_PHY_PCIE_GEN1) { + /* GEN1 page 0 */ + if (addr < 0x20) { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b00 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x00); + + /* GEN1 page 1 */ + } else { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b01 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x01); + } + + } else if (speed == HAL_INTF_PHY_PCIE_GEN2) { + /* GEN2 page 0 */ + if (addr < 0x20) { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b10 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x02); + + /* GEN2 page 1 */ + } else { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b11 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x03); + } + } else { + pr_err("Error Speed !\n"); + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG, + HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) | + BIT_MDIO_WFLAG_V1); + + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) & + BIT_MDIO_WFLAG_V1; + count = 20; + + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) & + BIT_MDIO_WFLAG_V1; + count--; + } + + if (tmp_u1b) { + pr_err("MDIO write fail!\n"); + return HALMAC_RET_FAIL; + } else { + return HALMAC_RET_SUCCESS; + } +} + +u16 halmac_mdio_read_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u8 speed + + ) +{ + u16 ret = 0; + u8 tmp_u1b = 0; + u32 count = 0; + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u8 real_addr = 0; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + /* address : 5bit */ + real_addr = (addr & 0x1F); + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG, real_addr); + + if (speed == HAL_INTF_PHY_PCIE_GEN1) { + /* GEN1 page 0 */ + if (addr < 0x20) { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b00 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x00); + + /* GEN1 page 1 */ + } else { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b01 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x01); + } + + } else if (speed == HAL_INTF_PHY_PCIE_GEN2) { + /* GEN2 page 0 */ + if (addr < 0x20) { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b10 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x02); + + /* GEN2 page 1 */ + } else { + /* select MDIO PHY Addr : reg 0x3F8[28:24]=5'b11 */ + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG + 3, + 0x03); + } + } else { + pr_err("Error Speed !\n"); + } + + HALMAC_REG_WRITE_8(halmac_adapter, REG_PCIE_MIX_CFG, + HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) | + BIT_MDIO_RFLAG_V1); + + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) & + BIT_MDIO_RFLAG_V1; + count = 20; + + while (tmp_u1b && count != 0) { + udelay(10); + tmp_u1b = HALMAC_REG_READ_8(halmac_adapter, REG_PCIE_MIX_CFG) & + BIT_MDIO_RFLAG_V1; + count--; + } + + if (tmp_u1b) { + ret = 0xFFFF; + pr_err("MDIO read fail!\n"); + + } else { + ret = HALMAC_REG_READ_16(halmac_adapter, REG_MDIO_V1 + 2); + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_MDIO, DBG_DMESG, + "Read Value = %x\n", ret); + } + + return ret; +} + +enum halmac_ret_status +halmac_usbphy_write_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u16 data, u8 speed) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (speed == HAL_INTF_PHY_USB3) { + HALMAC_REG_WRITE_8(halmac_adapter, 0xff0d, (u8)data); + HALMAC_REG_WRITE_8(halmac_adapter, 0xff0e, (u8)(data >> 8)); + HALMAC_REG_WRITE_8(halmac_adapter, 0xff0c, addr | BIT(7)); + } else if (speed == HAL_INTF_PHY_USB2) { + HALMAC_REG_WRITE_8(halmac_adapter, 0xfe41, (u8)data); + HALMAC_REG_WRITE_8(halmac_adapter, 0xfe40, addr); + HALMAC_REG_WRITE_8(halmac_adapter, 0xfe42, 0x81); + } else { + pr_err("[ERR]Error USB Speed !\n"); + return HALMAC_RET_NOT_SUPPORT; + } + + return HALMAC_RET_SUCCESS; +} + +u16 halmac_usbphy_read_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u8 speed) +{ + void *driver_adapter = NULL; + struct halmac_api *halmac_api; + u16 value = 0; + + driver_adapter = halmac_adapter->driver_adapter; + halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; + + if (speed == HAL_INTF_PHY_USB3) { + HALMAC_REG_WRITE_8(halmac_adapter, 0xff0c, addr | BIT(6)); + value = (u16)(HALMAC_REG_READ_32(halmac_adapter, 0xff0c) >> 8); + } else if (speed == HAL_INTF_PHY_USB2) { + if ((addr >= 0xE0) /*&& (addr <= 0xFF)*/) + addr -= 0x20; + if ((addr >= 0xC0) && (addr <= 0xDF)) { + HALMAC_REG_WRITE_8(halmac_adapter, 0xfe40, addr); + HALMAC_REG_WRITE_8(halmac_adapter, 0xfe42, 0x81); + value = HALMAC_REG_READ_8(halmac_adapter, 0xfe43); + } else { + pr_err("[ERR]Error USB2PHY offset!\n"); + return HALMAC_RET_NOT_SUPPORT; + } + } else { + pr_err("[ERR]Error USB Speed !\n"); + return HALMAC_RET_NOT_SUPPORT; + } + + return value; +} diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.h b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.h new file mode 100644 index 000000000000..1b59301d1158 --- /dev/null +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.h @@ -0,0 +1,321 @@ +/****************************************************************************** + * + * Copyright(c) 2016 Realtek Corporation. + * + * 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. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ +#ifndef _HALMAC_FUNC_88XX_H_ +#define _HALMAC_FUNC_88XX_H_ + +#include "../halmac_type.h" + +void halmac_init_offload_feature_state_machine_88xx( + struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_send_h2c_pkt_88xx(struct halmac_adapter *halmac_adapter, u8 *hal_buff, + u32 size, bool ack); + +enum halmac_ret_status +halmac_download_rsvd_page_88xx(struct halmac_adapter *halmac_adapter, + u8 *hal_buf, u32 size); + +enum halmac_ret_status +halmac_set_h2c_header_88xx(struct halmac_adapter *halmac_adapter, + u8 *hal_h2c_hdr, u16 *seq, bool ack); + +enum halmac_ret_status halmac_set_fw_offload_h2c_header_88xx( + struct halmac_adapter *halmac_adapter, u8 *hal_h2c_hdr, + struct halmac_h2c_header_info *h2c_header_info, u16 *seq_num); + +enum halmac_ret_status +halmac_dump_efuse_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_read_cfg cfg); + +enum halmac_ret_status +halmac_func_read_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, u8 *efuse_map); + +enum halmac_ret_status +halmac_func_write_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u8 value); + +enum halmac_ret_status +halmac_func_switch_efuse_bank_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_efuse_bank efuse_bank); + +enum halmac_ret_status +halmac_read_logical_efuse_map_88xx(struct halmac_adapter *halmac_adapter, + u8 *map); + +enum halmac_ret_status +halmac_func_write_logical_efuse_88xx(struct halmac_adapter *halmac_adapter, + u32 offset, u8 value); + +enum halmac_ret_status +halmac_func_pg_efuse_by_map_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_pg_efuse_info *pg_efuse_info, + enum halmac_efuse_read_cfg cfg); + +enum halmac_ret_status +halmac_eeprom_parser_88xx(struct halmac_adapter *halmac_adapter, + u8 *physical_efuse_map, u8 *logical_efuse_map); + +enum halmac_ret_status +halmac_read_hw_efuse_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, u8 *efuse_map); + +enum halmac_ret_status +halmac_dlfw_to_mem_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code, + u32 dest, u32 code_size); + +enum halmac_ret_status +halmac_send_fwpkt_88xx(struct halmac_adapter *halmac_adapter, u8 *ram_code, + u32 code_size); + +enum halmac_ret_status +halmac_iddma_dlfw_88xx(struct halmac_adapter *halmac_adapter, u32 source, + u32 dest, u32 length, u8 first); + +enum halmac_ret_status +halmac_check_fw_chksum_88xx(struct halmac_adapter *halmac_adapter, + u32 memory_address); + +enum halmac_ret_status +halmac_dlfw_end_flow_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_free_dl_fw_end_flow_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_pwr_seq_parser_88xx(struct halmac_adapter *halmac_adapter, u8 cut, + u8 fab, u8 intf, + struct halmac_wl_pwr_cfg_ **pp_pwr_seq_cfg + + ); + +enum halmac_ret_status +halmac_get_h2c_buff_free_space_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_send_h2c_set_pwr_mode_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_fwlps_option *hal_fw_lps_opt); + +enum halmac_ret_status +halmac_func_send_original_h2c_88xx(struct halmac_adapter *halmac_adapter, + u8 *original_h2c, u16 *seq, u8 ack); + +enum halmac_ret_status +halmac_media_status_rpt_88xx(struct halmac_adapter *halmac_adapter, u8 op_mode, + u8 mac_id_ind, u8 mac_id, u8 mac_id_end); + +enum halmac_ret_status halmac_send_h2c_update_datapack_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type, + struct halmac_phy_parameter_info *para_info); + +enum halmac_ret_status +halmac_send_h2c_run_datapack_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_data_type halmac_data_type); + +enum halmac_ret_status +halmac_send_bt_coex_cmd_88xx(struct halmac_adapter *halmac_adapter, u8 *bt_buf, + u32 bt_size, u8 ack); + +enum halmac_ret_status +halmac_func_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ch_switch_option *cs_option); + +enum halmac_ret_status +halmac_func_send_general_info_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_general_info *general_info); + +enum halmac_ret_status +halmac_send_h2c_ps_tuning_para_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_parse_c2h_packet_88xx(struct halmac_adapter *halmac_adapter, + u8 *halmac_buf, u32 halmac_size); + +enum halmac_ret_status +halmac_send_h2c_update_packet_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_packet_id pkt_id, u8 *pkt, + u32 pkt_size); + +enum halmac_ret_status +halmac_send_h2c_phy_parameter_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_phy_parameter_info *para_info, + bool full_fifo); + +enum halmac_ret_status +halmac_dump_physical_efuse_fw_88xx(struct halmac_adapter *halmac_adapter, + u32 offset, u32 size, u8 *efuse_map); + +enum halmac_ret_status halmac_send_h2c_update_bcn_parse_info_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_bcn_ie_info *bcn_ie_info); + +enum halmac_ret_status +halmac_convert_to_sdio_bus_offset_88xx(struct halmac_adapter *halmac_adapter, + u32 *halmac_offset); + +enum halmac_ret_status +halmac_update_sdio_free_page_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_update_oqt_free_space_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_efuse_cmd_construct_state +halmac_query_efuse_curr_state_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status halmac_transition_efuse_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_efuse_cmd_construct_state dest_state); + +enum halmac_cfg_para_cmd_construct_state +halmac_query_cfg_para_curr_state_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status halmac_transition_cfg_para_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cfg_para_cmd_construct_state dest_state); + +enum halmac_scan_cmd_construct_state +halmac_query_scan_curr_state_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status halmac_transition_scan_state_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_scan_cmd_construct_state dest_state); + +enum halmac_ret_status halmac_query_cfg_para_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status halmac_query_dump_physical_efuse_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status halmac_query_dump_logical_efuse_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status halmac_query_channel_switch_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status halmac_query_update_packet_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status +halmac_query_iqk_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size); + +enum halmac_ret_status halmac_query_power_tracking_status_88xx( + struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, u8 *data, u32 *size); + +enum halmac_ret_status +halmac_query_psd_status_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_cmd_process_status *process_status, + u8 *data, u32 *size); + +enum halmac_ret_status +halmac_verify_io_88xx(struct halmac_adapter *halmac_adapter); + +enum halmac_ret_status +halmac_verify_send_rsvd_page_88xx(struct halmac_adapter *halmac_adapter); + +void halmac_power_save_cb_88xx(void *cb_data); + +enum halmac_ret_status +halmac_buffer_read_88xx(struct halmac_adapter *halmac_adapter, u32 offset, + u32 size, enum hal_fifo_sel halmac_fifo_sel, + u8 *fifo_map); + +void halmac_restore_mac_register_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_restore_info *restore_info, + u32 restore_num); + +void halmac_api_record_id_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_api_id api_id); + +enum halmac_ret_status +halmac_set_usb_mode_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_usb_mode usb_mode); + +void halmac_enable_bb_rf_88xx(struct halmac_adapter *halmac_adapter, u8 enable); + +void halmac_config_sdio_tx_page_threshold_88xx( + struct halmac_adapter *halmac_adapter, + struct halmac_tx_page_threshold_info *threshold_info); + +enum halmac_ret_status +halmac_rqpn_parser_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode, + struct halmac_rqpn_ *pwr_seq_cfg); + +enum halmac_ret_status +halmac_check_oqt_88xx(struct halmac_adapter *halmac_adapter, u32 tx_agg_num, + u8 *halmac_buf); + +enum halmac_ret_status +halmac_pg_num_parser_88xx(struct halmac_adapter *halmac_adapter, + enum halmac_trx_mode halmac_trx_mode, + struct halmac_pg_num_ *pg_num_table); + +enum halmac_ret_status +halmac_parse_intf_phy_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_intf_phy_para_ *intf_phy_para, + enum halmac_intf_phy_platform platform, + enum hal_intf_phy intf_phy); + +enum halmac_ret_status +halmac_dbi_write32_88xx(struct halmac_adapter *halmac_adapter, u16 addr, + u32 data); + +u32 halmac_dbi_read32_88xx(struct halmac_adapter *halmac_adapter, u16 addr); + +enum halmac_ret_status +halmac_dbi_write8_88xx(struct halmac_adapter *halmac_adapter, u16 addr, + u8 data); + +u8 halmac_dbi_read8_88xx(struct halmac_adapter *halmac_adapter, u16 addr); + +u16 halmac_mdio_read_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u8 speed + + ); + +enum halmac_ret_status +halmac_mdio_write_88xx(struct halmac_adapter *halmac_adapter, u8 addr, u16 data, + u8 speed); + +void halmac_config_ampdu_88xx(struct halmac_adapter *halmac_adapter, + struct halmac_ampdu_config *ampdu_config); + +enum halmac_ret_status +halmac_usbphy_write_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u16 data, u8 speed); + +u16 halmac_usbphy_read_88xx(struct halmac_adapter *halmac_adapter, u8 addr, + u8 speed); +#endif /* _HALMAC_FUNC_88XX_H_ */ |