17d0af6dfSXianjun Jiao // Author: Xianjun Jiao, Michael Mehari, Wei Liu 27d0af6dfSXianjun Jiao // SPDX-FileCopyrightText: 2019 UGent 37d0af6dfSXianjun Jiao // SPDX-License-Identifier: AGPL-3.0-or-later 47d0af6dfSXianjun Jiao 57d0af6dfSXianjun Jiao static int openwifi_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len) 67d0af6dfSXianjun Jiao { 77d0af6dfSXianjun Jiao struct openwifi_priv *priv = hw->priv; 87d0af6dfSXianjun Jiao struct nlattr *tb[OPENWIFI_ATTR_MAX + 1]; 97d0af6dfSXianjun Jiao struct sk_buff *skb; 107d0af6dfSXianjun Jiao int err; 117d0af6dfSXianjun Jiao u32 tmp=-1, reg_cat, reg_addr, reg_val, reg_addr_idx, tsft_high, tsft_low; 127d0af6dfSXianjun Jiao int tmp_int; 137d0af6dfSXianjun Jiao 147d0af6dfSXianjun Jiao err = nla_parse(tb, OPENWIFI_ATTR_MAX, data, len, openwifi_testmode_policy, NULL); 157d0af6dfSXianjun Jiao if (err) 167d0af6dfSXianjun Jiao return err; 177d0af6dfSXianjun Jiao 187d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_CMD]) 197d0af6dfSXianjun Jiao return -EINVAL; 207d0af6dfSXianjun Jiao 217d0af6dfSXianjun Jiao switch (nla_get_u32(tb[OPENWIFI_ATTR_CMD])) { 227d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_GAP: 237d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_GAP]) 247d0af6dfSXianjun Jiao return -EINVAL; 257d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_GAP]); 267d0af6dfSXianjun Jiao printk("%s XPU_REG_CSMA_CFG_write %08x (Check openwifi_conf_tx() in sdr.c to understand)\n", sdr_compatible_str, tmp); 277d0af6dfSXianjun Jiao xpu_api->XPU_REG_CSMA_CFG_write(tmp); // unit us 287d0af6dfSXianjun Jiao return 0; 297d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_GAP: 307d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 317d0af6dfSXianjun Jiao if (!skb) 327d0af6dfSXianjun Jiao return -ENOMEM; 337d0af6dfSXianjun Jiao tmp = xpu_api->XPU_REG_CSMA_CFG_read(); 347d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_GAP, tmp)) 357d0af6dfSXianjun Jiao goto nla_put_failure; 367d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 377d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_IDX: 387d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_IDX]) 397d0af6dfSXianjun Jiao return -EINVAL; 407d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_IDX]); 417d0af6dfSXianjun Jiao printk("%s set openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp); 427d0af6dfSXianjun Jiao if (tmp == MAX_NUM_HW_QUEUE) { 437d0af6dfSXianjun Jiao printk("%s set openwifi slice_idx reset all queue counter.\n", sdr_compatible_str); 447d0af6dfSXianjun Jiao xpu_api->XPU_REG_MULTI_RST_write(1<<7); //bit7 reset the counter for all queues at the same time 457d0af6dfSXianjun Jiao xpu_api->XPU_REG_MULTI_RST_write(0<<7); 467d0af6dfSXianjun Jiao } else { 477d0af6dfSXianjun Jiao priv->slice_idx = tmp; 487d0af6dfSXianjun Jiao } 497d0af6dfSXianjun Jiao return 0; 507d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_IDX: 517d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 527d0af6dfSXianjun Jiao if (!skb) 537d0af6dfSXianjun Jiao return -ENOMEM; 547d0af6dfSXianjun Jiao tmp = priv->slice_idx; 557d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_IDX, tmp)) 567d0af6dfSXianjun Jiao goto nla_put_failure; 577d0af6dfSXianjun Jiao printk("%s get openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp); 587d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 597d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_ADDR: 607d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_ADDR]) 617d0af6dfSXianjun Jiao return -EINVAL; 627d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_ADDR]); 637d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 647d0af6dfSXianjun Jiao printk("%s set openwifi slice_target_mac_addr(low32) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 657d0af6dfSXianjun Jiao return -EOPNOTSUPP; 667d0af6dfSXianjun Jiao } else { 677d0af6dfSXianjun Jiao printk("%s set openwifi slice_target_mac_addr(low32) in hex: %08x to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 687d0af6dfSXianjun Jiao priv->dest_mac_addr_queue_map[priv->slice_idx] = reverse32(tmp); 697d0af6dfSXianjun Jiao } 707d0af6dfSXianjun Jiao return 0; 717d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_ADDR: 727d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 737d0af6dfSXianjun Jiao if (!skb) 747d0af6dfSXianjun Jiao return -ENOMEM; 757d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 767d0af6dfSXianjun Jiao tmp = -1; 777d0af6dfSXianjun Jiao } else { 787d0af6dfSXianjun Jiao tmp = reverse32(priv->dest_mac_addr_queue_map[priv->slice_idx]); 797d0af6dfSXianjun Jiao } 807d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_ADDR, tmp)) 817d0af6dfSXianjun Jiao goto nla_put_failure; 827d0af6dfSXianjun Jiao printk("%s get openwifi slice_target_mac_addr(low32) in hex: %08x of slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 837d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 847d0af6dfSXianjun Jiao 857d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_TOTAL: 867d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_TOTAL]) 877d0af6dfSXianjun Jiao return -EINVAL; 887d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL]); 897d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 907d0af6dfSXianjun Jiao printk("%s set SLICE_TOTAL(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 917d0af6dfSXianjun Jiao return -EOPNOTSUPP; 927d0af6dfSXianjun Jiao } else { 937d0af6dfSXianjun Jiao printk("%s set SLICE_TOTAL(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 947d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((priv->slice_idx<<20)|tmp); 957d0af6dfSXianjun Jiao } 967d0af6dfSXianjun Jiao return 0; 977d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_TOTAL: 987d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 997d0af6dfSXianjun Jiao if (!skb) 1007d0af6dfSXianjun Jiao return -ENOMEM; 1017d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL_read()); 1027d0af6dfSXianjun Jiao printk("%s get SLICE_TOTAL(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 1037d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL, tmp)) 1047d0af6dfSXianjun Jiao goto nla_put_failure; 1057d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 1067d0af6dfSXianjun Jiao 1077d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_START: 1087d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_START]) 1097d0af6dfSXianjun Jiao return -EINVAL; 1107d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START]); 1117d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 1127d0af6dfSXianjun Jiao printk("%s set SLICE_START(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 1137d0af6dfSXianjun Jiao return -EOPNOTSUPP; 1147d0af6dfSXianjun Jiao } else { 1157d0af6dfSXianjun Jiao printk("%s set SLICE_START(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 1167d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_START_write((priv->slice_idx<<20)|tmp); 1177d0af6dfSXianjun Jiao } 1187d0af6dfSXianjun Jiao return 0; 1197d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_START: 1207d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 1217d0af6dfSXianjun Jiao if (!skb) 1227d0af6dfSXianjun Jiao return -ENOMEM; 1237d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_START_read()); 1247d0af6dfSXianjun Jiao printk("%s get SLICE_START(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 1257d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START, tmp)) 1267d0af6dfSXianjun Jiao goto nla_put_failure; 1277d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 1287d0af6dfSXianjun Jiao 1297d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_END: 1307d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_END]) 1317d0af6dfSXianjun Jiao return -EINVAL; 1327d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END]); 1337d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 1347d0af6dfSXianjun Jiao printk("%s set SLICE_END(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 1357d0af6dfSXianjun Jiao return -EOPNOTSUPP; 1367d0af6dfSXianjun Jiao } else { 1377d0af6dfSXianjun Jiao printk("%s set SLICE_END(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 1387d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_END_write((priv->slice_idx<<20)|tmp); 1397d0af6dfSXianjun Jiao } 1407d0af6dfSXianjun Jiao return 0; 1417d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_END: 1427d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 1437d0af6dfSXianjun Jiao if (!skb) 1447d0af6dfSXianjun Jiao return -ENOMEM; 1457d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_END_read()); 1467d0af6dfSXianjun Jiao printk("%s get SLICE_END(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 1477d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END, tmp)) 1487d0af6dfSXianjun Jiao goto nla_put_failure; 1497d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 1507d0af6dfSXianjun Jiao 1517d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_TOTAL1: 1527d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_TOTAL1]) 1537d0af6dfSXianjun Jiao // return -EINVAL; 1547d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL1]); 1557d0af6dfSXianjun Jiao // printk("%s set SLICE_TOTAL1(duration) to %d usec\n", sdr_compatible_str, tmp); 1567d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_write(tmp); 1577d0af6dfSXianjun Jiao // return 0; 1587d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_TOTAL1: 1597d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 1607d0af6dfSXianjun Jiao // if (!skb) 1617d0af6dfSXianjun Jiao // return -ENOMEM; 1627d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_read()); 1637d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL1, tmp)) 1647d0af6dfSXianjun Jiao // goto nla_put_failure; 1657d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 1667d0af6dfSXianjun Jiao 1677d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_START1: 1687d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_START1]) 1697d0af6dfSXianjun Jiao // return -EINVAL; 1707d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START1]); 1717d0af6dfSXianjun Jiao // printk("%s set SLICE_START1(duration) to %d usec\n", sdr_compatible_str, tmp); 1727d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_START1_write(tmp); 1737d0af6dfSXianjun Jiao // return 0; 1747d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_START1: 1757d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 1767d0af6dfSXianjun Jiao // if (!skb) 1777d0af6dfSXianjun Jiao // return -ENOMEM; 1787d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_START1_read()); 1797d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START1, tmp)) 1807d0af6dfSXianjun Jiao // goto nla_put_failure; 1817d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 1827d0af6dfSXianjun Jiao 1837d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_END1: 1847d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_END1]) 1857d0af6dfSXianjun Jiao // return -EINVAL; 1867d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END1]); 1877d0af6dfSXianjun Jiao // printk("%s set SLICE_END1(duration) to %d usec\n", sdr_compatible_str, tmp); 1887d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_END1_write(tmp); 1897d0af6dfSXianjun Jiao // return 0; 1907d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_END1: 1917d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 1927d0af6dfSXianjun Jiao // if (!skb) 1937d0af6dfSXianjun Jiao // return -ENOMEM; 1947d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_END1_read()); 1957d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END1, tmp)) 1967d0af6dfSXianjun Jiao // goto nla_put_failure; 1977d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 1987d0af6dfSXianjun Jiao 1997d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_RSSI_TH: 2007d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_RSSI_TH]) 2017d0af6dfSXianjun Jiao return -EINVAL; 2027d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_RSSI_TH]); 2037d0af6dfSXianjun Jiao // printk("%s set RSSI_TH to %d\n", sdr_compatible_str, tmp); 2047d0af6dfSXianjun Jiao // xpu_api->XPU_REG_LBT_TH_write(tmp); 2057d0af6dfSXianjun Jiao // return 0; 2067d0af6dfSXianjun Jiao printk("%s WARNING Please use command: sdrctl dev sdr0 set reg drv_xpu 0 reg_value! (1~2047, 0 means AUTO)!\n", sdr_compatible_str); 2077d0af6dfSXianjun Jiao return -EOPNOTSUPP; 2087d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_RSSI_TH: 2097d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 2107d0af6dfSXianjun Jiao if (!skb) 2117d0af6dfSXianjun Jiao return -ENOMEM; 2127d0af6dfSXianjun Jiao tmp_int = rssi_half_db_to_rssi_dbm(xpu_api->XPU_REG_LBT_TH_read(), priv->rssi_correction); //rssi_dbm 2137d0af6dfSXianjun Jiao tmp = (-tmp_int); 2147d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_RSSI_TH, tmp)) 2157d0af6dfSXianjun Jiao goto nla_put_failure; 2167d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 2177d0af6dfSXianjun Jiao 2187d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_TSF: 2197d0af6dfSXianjun Jiao printk("openwifi_set_tsf_1"); 2207d0af6dfSXianjun Jiao if ( (!tb[OPENWIFI_ATTR_HIGH_TSF]) || (!tb[OPENWIFI_ATTR_LOW_TSF]) ) 2217d0af6dfSXianjun Jiao return -EINVAL; 2227d0af6dfSXianjun Jiao printk("openwifi_set_tsf_2"); 2237d0af6dfSXianjun Jiao tsft_high = nla_get_u32(tb[OPENWIFI_ATTR_HIGH_TSF]); 2247d0af6dfSXianjun Jiao tsft_low = nla_get_u32(tb[OPENWIFI_ATTR_LOW_TSF]); 2257d0af6dfSXianjun Jiao xpu_api->XPU_REG_TSF_LOAD_VAL_write(tsft_high,tsft_low); 2267d0af6dfSXianjun Jiao printk("%s openwifi_set_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low); 2277d0af6dfSXianjun Jiao return 0; 2287d0af6dfSXianjun Jiao 2297d0af6dfSXianjun Jiao case REG_CMD_SET: 2307d0af6dfSXianjun Jiao if ( (!tb[REG_ATTR_ADDR]) || (!tb[REG_ATTR_VAL]) ) 2317d0af6dfSXianjun Jiao return -EINVAL; 2327d0af6dfSXianjun Jiao reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]); 2337d0af6dfSXianjun Jiao reg_val = nla_get_u32(tb[REG_ATTR_VAL]); 2347d0af6dfSXianjun Jiao reg_cat = ((reg_addr>>16)&0xFFFF); 2357d0af6dfSXianjun Jiao reg_addr = (reg_addr&0xFFFF); 2367d0af6dfSXianjun Jiao reg_addr_idx = (reg_addr>>2); 2377d0af6dfSXianjun Jiao printk("%s recv set cmd reg cat %d addr %08x val %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_val, reg_addr_idx); 2387d0af6dfSXianjun Jiao if (reg_cat==SDRCTL_REG_CAT_RF) { 2397d0af6dfSXianjun Jiao // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str); 2407d0af6dfSXianjun Jiao // return -EOPNOTSUPP; 2417d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) { 2427d0af6dfSXianjun Jiao priv->rf_reg_val[reg_addr_idx]=reg_val; 2437d0af6dfSXianjun Jiao if (reg_addr_idx==RF_TX_REG_IDX_ATT) {//change the tx ON att (if a RF chain is ON) 2447d0af6dfSXianjun Jiao tmp = ad9361_get_tx_atten(priv->ad9361_phy, 1); 2457d0af6dfSXianjun Jiao printk("%s ad9361_get_tx_atten ant0 %d\n",sdr_compatible_str, tmp); 2467d0af6dfSXianjun Jiao if (tmp<AD9361_RADIO_OFF_TX_ATT) { 2477d0af6dfSXianjun Jiao err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, true, false, true); 2487d0af6dfSXianjun Jiao if (err < 0) { 2497d0af6dfSXianjun Jiao printk("%s WARNING ad9361_set_tx_atten ant0 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 2507d0af6dfSXianjun Jiao return -EIO; 2517d0af6dfSXianjun Jiao } else { 2527d0af6dfSXianjun Jiao printk("%s ad9361_set_tx_atten ant0 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 2537d0af6dfSXianjun Jiao } 2547d0af6dfSXianjun Jiao } 2557d0af6dfSXianjun Jiao tmp = ad9361_get_tx_atten(priv->ad9361_phy, 2); 2567d0af6dfSXianjun Jiao printk("%s ad9361_get_tx_atten ant1 %d\n",sdr_compatible_str, tmp); 2577d0af6dfSXianjun Jiao if (tmp<AD9361_RADIO_OFF_TX_ATT) { 2587d0af6dfSXianjun Jiao err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, false, true, true); 2597d0af6dfSXianjun Jiao if (err < 0) { 2607d0af6dfSXianjun Jiao printk("%s WARNING ad9361_set_tx_atten ant1 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 2617d0af6dfSXianjun Jiao return -EIO; 2627d0af6dfSXianjun Jiao } else { 2637d0af6dfSXianjun Jiao printk("%s ad9361_set_tx_atten ant1 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 2647d0af6dfSXianjun Jiao } 2657d0af6dfSXianjun Jiao } 266*d6c1c3f7SXianjun Jiao } else if (reg_addr_idx==RF_TX_REG_IDX_FREQ_MHZ) { // apply the tx fo 267*d6c1c3f7SXianjun Jiao clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ((u64)1000000ull)*((u64)priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]) )>>1 ); 268*d6c1c3f7SXianjun Jiao ad9361_tx_calibration(priv, priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]); 269*d6c1c3f7SXianjun Jiao printk("%s clk_set_rate TX_RFPLL %dMHz done\n",sdr_compatible_str, priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]); 270*d6c1c3f7SXianjun Jiao } else if (reg_addr_idx==RF_RX_REG_IDX_FREQ_MHZ) { // apply the rx fo 271*d6c1c3f7SXianjun Jiao clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ((u64)1000000ull)*((u64)priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]) )>>1 ); 272*d6c1c3f7SXianjun Jiao openwifi_rf_rx_update_after_tuning(priv, priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]); 273*d6c1c3f7SXianjun Jiao printk("%s clk_set_rate RX_RFPLL %dMHz done\n",sdr_compatible_str, priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]); 2747d0af6dfSXianjun Jiao } 2757d0af6dfSXianjun Jiao } else { 2767d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 2777d0af6dfSXianjun Jiao return -EOPNOTSUPP; 2787d0af6dfSXianjun Jiao } 2797d0af6dfSXianjun Jiao } 2807d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX_INTF) 2817d0af6dfSXianjun Jiao rx_intf_api->reg_write(reg_addr,reg_val); 2827d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX_INTF) 2837d0af6dfSXianjun Jiao tx_intf_api->reg_write(reg_addr,reg_val); 2847d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX) 2857d0af6dfSXianjun Jiao openofdm_rx_api->reg_write(reg_addr,reg_val); 2867d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX) 2877d0af6dfSXianjun Jiao openofdm_tx_api->reg_write(reg_addr,reg_val); 2887d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_XPU) 2897d0af6dfSXianjun Jiao xpu_api->reg_write(reg_addr,reg_val); 2907d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) { 2917d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 2927d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG) { 2937d0af6dfSXianjun Jiao tmp = openwifi_set_antenna(hw, (priv->drv_tx_reg_val[reg_addr_idx]==0?1:2), (reg_val==0?1:2)); 2947d0af6dfSXianjun Jiao if (tmp) { 2957d0af6dfSXianjun Jiao printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp); 2967d0af6dfSXianjun Jiao return -EIO; 2977d0af6dfSXianjun Jiao } else { 2987d0af6dfSXianjun Jiao priv->drv_rx_reg_val[reg_addr_idx]=reg_val; 2997d0af6dfSXianjun Jiao } 3007d0af6dfSXianjun Jiao } else { 3017d0af6dfSXianjun Jiao priv->drv_rx_reg_val[reg_addr_idx]=reg_val; 3027d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_DEMOD_TH) { 3037d0af6dfSXianjun Jiao openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write((OPENOFDM_RX_DC_RUNNING_SUM_TH_INIT<<16)|rssi_dbm_to_rssi_half_db((reg_val==0?OPENOFDM_RX_RSSI_DBM_TH_DEFAULT:(-reg_val)), priv->rssi_correction)); 3047d0af6dfSXianjun Jiao } 3057d0af6dfSXianjun Jiao } 3067d0af6dfSXianjun Jiao } else { 3077d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 3087d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3097d0af6dfSXianjun Jiao } 3107d0af6dfSXianjun Jiao } 3117d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) { 3127d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 3137d0af6dfSXianjun Jiao if ((reg_addr_idx == DRV_TX_REG_IDX_RATE || reg_addr_idx == DRV_TX_REG_IDX_RATE_HT) && 3147d0af6dfSXianjun Jiao (reg_val != 0 && (!((reg_val&0xF)>=4 && (reg_val&0xF)<=11)) ) ) { 3157d0af6dfSXianjun Jiao printk("%s WARNING rate override value should be 0 or 4~11!\n", sdr_compatible_str); 3167d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3177d0af6dfSXianjun Jiao } else { 3187d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG) { 3197d0af6dfSXianjun Jiao tmp = openwifi_set_antenna(hw, reg_val+1, priv->drv_rx_reg_val[reg_addr_idx]+1); 3207d0af6dfSXianjun Jiao if (tmp) { 3217d0af6dfSXianjun Jiao printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp); 3227d0af6dfSXianjun Jiao return -EIO; 3237d0af6dfSXianjun Jiao } else { 3247d0af6dfSXianjun Jiao priv->drv_tx_reg_val[reg_addr_idx]=reg_val; 3257d0af6dfSXianjun Jiao } 3267d0af6dfSXianjun Jiao } else { 3277d0af6dfSXianjun Jiao priv->drv_tx_reg_val[reg_addr_idx]=reg_val; 3287d0af6dfSXianjun Jiao } 3297d0af6dfSXianjun Jiao } 3307d0af6dfSXianjun Jiao } else { 3317d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 3327d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3337d0af6dfSXianjun Jiao } 3347d0af6dfSXianjun Jiao } 3357d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) { 3367d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 3377d0af6dfSXianjun Jiao priv->drv_xpu_reg_val[reg_addr_idx]=reg_val; 3387d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) { 3397d0af6dfSXianjun Jiao if (reg_val) { 3407d0af6dfSXianjun Jiao tmp_int = (-reg_val); // rssi_dbm 3417d0af6dfSXianjun Jiao tmp = rssi_dbm_to_rssi_half_db(tmp_int, priv->rssi_correction); 3427d0af6dfSXianjun Jiao xpu_api->XPU_REG_LBT_TH_write( tmp ); 3437d0af6dfSXianjun Jiao printk("%s override FPGA LBT threshold to %d(%ddBm). The last_auto_fpga_lbt_th %d(%ddBm)\n", sdr_compatible_str, tmp, tmp_int, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction)); 3447d0af6dfSXianjun Jiao } else { 3457d0af6dfSXianjun Jiao xpu_api->XPU_REG_LBT_TH_write(priv->last_auto_fpga_lbt_th); 3467d0af6dfSXianjun Jiao printk("%s Restore last_auto_fpga_lbt_th %d(%ddBm) to FPGA. ad9361_rf_set_channel will take control\n", sdr_compatible_str, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction)); 3477d0af6dfSXianjun Jiao } 3487d0af6dfSXianjun Jiao } 3497d0af6dfSXianjun Jiao } else { 3507d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 3517d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3527d0af6dfSXianjun Jiao } 3537d0af6dfSXianjun Jiao } 3547d0af6dfSXianjun Jiao else { 3557d0af6dfSXianjun Jiao printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat); 3567d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3577d0af6dfSXianjun Jiao } 3587d0af6dfSXianjun Jiao 3597d0af6dfSXianjun Jiao return 0; 3607d0af6dfSXianjun Jiao case REG_CMD_GET: 3617d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 3627d0af6dfSXianjun Jiao if (!skb) 3637d0af6dfSXianjun Jiao return -ENOMEM; 3647d0af6dfSXianjun Jiao reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]); 3657d0af6dfSXianjun Jiao reg_cat = ((reg_addr>>16)&0xFFFF); 3667d0af6dfSXianjun Jiao reg_addr = (reg_addr&0xFFFF); 3677d0af6dfSXianjun Jiao reg_addr_idx = (reg_addr>>2); 3687d0af6dfSXianjun Jiao printk("%s recv get cmd reg cat %d addr %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_addr_idx); 3697d0af6dfSXianjun Jiao if (reg_cat==SDRCTL_REG_CAT_RF) { 3707d0af6dfSXianjun Jiao // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str); 3717d0af6dfSXianjun Jiao // tmp = 0xFFFFFFFF; 3727d0af6dfSXianjun Jiao // return -EOPNOTSUPP; 3737d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) { 3747d0af6dfSXianjun Jiao tmp = priv->rf_reg_val[reg_addr_idx]; 3757d0af6dfSXianjun Jiao } else { 3767d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 3777d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3787d0af6dfSXianjun Jiao } 3797d0af6dfSXianjun Jiao } 3807d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX_INTF) 3817d0af6dfSXianjun Jiao tmp = rx_intf_api->reg_read(reg_addr); 3827d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX_INTF) 3837d0af6dfSXianjun Jiao tmp = tx_intf_api->reg_read(reg_addr); 3847d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX) 3857d0af6dfSXianjun Jiao tmp = openofdm_rx_api->reg_read(reg_addr); 3867d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX) 3877d0af6dfSXianjun Jiao tmp = openofdm_tx_api->reg_read(reg_addr); 3887d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_XPU) 3897d0af6dfSXianjun Jiao tmp = xpu_api->reg_read(reg_addr); 3907d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) { 3917d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 3927d0af6dfSXianjun Jiao tmp = priv->drv_rx_reg_val[reg_addr_idx]; 3937d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG) 3947d0af6dfSXianjun Jiao openwifi_get_antenna(hw, &tsft_high, &tsft_low); 3957d0af6dfSXianjun Jiao } else { 3967d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 3977d0af6dfSXianjun Jiao return -EOPNOTSUPP; 3987d0af6dfSXianjun Jiao } 3997d0af6dfSXianjun Jiao } 4007d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) { 4017d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 4027d0af6dfSXianjun Jiao tmp = priv->drv_tx_reg_val[reg_addr_idx]; 4037d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG) 4047d0af6dfSXianjun Jiao openwifi_get_antenna(hw, &tsft_high, &tsft_low); 4057d0af6dfSXianjun Jiao } else { 4067d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 4077d0af6dfSXianjun Jiao return -EOPNOTSUPP; 4087d0af6dfSXianjun Jiao } 4097d0af6dfSXianjun Jiao } 4107d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) { 4117d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 4127d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) { 4137d0af6dfSXianjun Jiao tmp = xpu_api->XPU_REG_LBT_TH_read();//rssi_half_db 4147d0af6dfSXianjun Jiao tmp_int = rssi_half_db_to_rssi_dbm(tmp, priv->rssi_correction); //rssi_dbm 4157d0af6dfSXianjun Jiao printk("%s FPGA LBT threshold %d(%ddBm). The last_auto_fpga_lbt_th %d(%ddBm)\n", sdr_compatible_str, tmp, tmp_int, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction)); 4167d0af6dfSXianjun Jiao } 4177d0af6dfSXianjun Jiao tmp = priv->drv_xpu_reg_val[reg_addr_idx]; 4187d0af6dfSXianjun Jiao } else { 4197d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 4207d0af6dfSXianjun Jiao return -EOPNOTSUPP; 4217d0af6dfSXianjun Jiao } 4227d0af6dfSXianjun Jiao } 4237d0af6dfSXianjun Jiao else { 4247d0af6dfSXianjun Jiao printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat); 4257d0af6dfSXianjun Jiao return -EOPNOTSUPP; 4267d0af6dfSXianjun Jiao } 4277d0af6dfSXianjun Jiao 4287d0af6dfSXianjun Jiao if (nla_put_u32(skb, REG_ATTR_VAL, tmp)) 4297d0af6dfSXianjun Jiao goto nla_put_failure; 4307d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 4317d0af6dfSXianjun Jiao 4327d0af6dfSXianjun Jiao default: 4337d0af6dfSXianjun Jiao return -EOPNOTSUPP; 4347d0af6dfSXianjun Jiao } 4357d0af6dfSXianjun Jiao 4367d0af6dfSXianjun Jiao nla_put_failure: 4377d0af6dfSXianjun Jiao dev_kfree_skb(skb); 4387d0af6dfSXianjun Jiao return -ENOBUFS; 4397d0af6dfSXianjun Jiao } 440