1*7d0af6dfSXianjun Jiao // Author: Xianjun Jiao, Michael Mehari, Wei Liu 2*7d0af6dfSXianjun Jiao // SPDX-FileCopyrightText: 2019 UGent 3*7d0af6dfSXianjun Jiao // SPDX-License-Identifier: AGPL-3.0-or-later 4*7d0af6dfSXianjun Jiao 5*7d0af6dfSXianjun Jiao static int openwifi_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len) 6*7d0af6dfSXianjun Jiao { 7*7d0af6dfSXianjun Jiao struct openwifi_priv *priv = hw->priv; 8*7d0af6dfSXianjun Jiao struct nlattr *tb[OPENWIFI_ATTR_MAX + 1]; 9*7d0af6dfSXianjun Jiao struct sk_buff *skb; 10*7d0af6dfSXianjun Jiao int err; 11*7d0af6dfSXianjun Jiao u32 tmp=-1, reg_cat, reg_addr, reg_val, reg_addr_idx, tsft_high, tsft_low; 12*7d0af6dfSXianjun Jiao int tmp_int; 13*7d0af6dfSXianjun Jiao 14*7d0af6dfSXianjun Jiao err = nla_parse(tb, OPENWIFI_ATTR_MAX, data, len, openwifi_testmode_policy, NULL); 15*7d0af6dfSXianjun Jiao if (err) 16*7d0af6dfSXianjun Jiao return err; 17*7d0af6dfSXianjun Jiao 18*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_CMD]) 19*7d0af6dfSXianjun Jiao return -EINVAL; 20*7d0af6dfSXianjun Jiao 21*7d0af6dfSXianjun Jiao switch (nla_get_u32(tb[OPENWIFI_ATTR_CMD])) { 22*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_GAP: 23*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_GAP]) 24*7d0af6dfSXianjun Jiao return -EINVAL; 25*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_GAP]); 26*7d0af6dfSXianjun Jiao printk("%s XPU_REG_CSMA_CFG_write %08x (Check openwifi_conf_tx() in sdr.c to understand)\n", sdr_compatible_str, tmp); 27*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_CSMA_CFG_write(tmp); // unit us 28*7d0af6dfSXianjun Jiao return 0; 29*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_GAP: 30*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 31*7d0af6dfSXianjun Jiao if (!skb) 32*7d0af6dfSXianjun Jiao return -ENOMEM; 33*7d0af6dfSXianjun Jiao tmp = xpu_api->XPU_REG_CSMA_CFG_read(); 34*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_GAP, tmp)) 35*7d0af6dfSXianjun Jiao goto nla_put_failure; 36*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 37*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_IDX: 38*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_IDX]) 39*7d0af6dfSXianjun Jiao return -EINVAL; 40*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_IDX]); 41*7d0af6dfSXianjun Jiao printk("%s set openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp); 42*7d0af6dfSXianjun Jiao if (tmp == MAX_NUM_HW_QUEUE) { 43*7d0af6dfSXianjun Jiao printk("%s set openwifi slice_idx reset all queue counter.\n", sdr_compatible_str); 44*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_MULTI_RST_write(1<<7); //bit7 reset the counter for all queues at the same time 45*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_MULTI_RST_write(0<<7); 46*7d0af6dfSXianjun Jiao } else { 47*7d0af6dfSXianjun Jiao priv->slice_idx = tmp; 48*7d0af6dfSXianjun Jiao } 49*7d0af6dfSXianjun Jiao return 0; 50*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_IDX: 51*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 52*7d0af6dfSXianjun Jiao if (!skb) 53*7d0af6dfSXianjun Jiao return -ENOMEM; 54*7d0af6dfSXianjun Jiao tmp = priv->slice_idx; 55*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_IDX, tmp)) 56*7d0af6dfSXianjun Jiao goto nla_put_failure; 57*7d0af6dfSXianjun Jiao printk("%s get openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp); 58*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 59*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_ADDR: 60*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_ADDR]) 61*7d0af6dfSXianjun Jiao return -EINVAL; 62*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_ADDR]); 63*7d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 64*7d0af6dfSXianjun Jiao printk("%s set openwifi slice_target_mac_addr(low32) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 65*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 66*7d0af6dfSXianjun Jiao } else { 67*7d0af6dfSXianjun Jiao printk("%s set openwifi slice_target_mac_addr(low32) in hex: %08x to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 68*7d0af6dfSXianjun Jiao priv->dest_mac_addr_queue_map[priv->slice_idx] = reverse32(tmp); 69*7d0af6dfSXianjun Jiao } 70*7d0af6dfSXianjun Jiao return 0; 71*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_ADDR: 72*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 73*7d0af6dfSXianjun Jiao if (!skb) 74*7d0af6dfSXianjun Jiao return -ENOMEM; 75*7d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 76*7d0af6dfSXianjun Jiao tmp = -1; 77*7d0af6dfSXianjun Jiao } else { 78*7d0af6dfSXianjun Jiao tmp = reverse32(priv->dest_mac_addr_queue_map[priv->slice_idx]); 79*7d0af6dfSXianjun Jiao } 80*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_ADDR, tmp)) 81*7d0af6dfSXianjun Jiao goto nla_put_failure; 82*7d0af6dfSXianjun Jiao printk("%s get openwifi slice_target_mac_addr(low32) in hex: %08x of slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 83*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 84*7d0af6dfSXianjun Jiao 85*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_TOTAL: 86*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_TOTAL]) 87*7d0af6dfSXianjun Jiao return -EINVAL; 88*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL]); 89*7d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 90*7d0af6dfSXianjun Jiao printk("%s set SLICE_TOTAL(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 91*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 92*7d0af6dfSXianjun Jiao } else { 93*7d0af6dfSXianjun Jiao printk("%s set SLICE_TOTAL(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 94*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((priv->slice_idx<<20)|tmp); 95*7d0af6dfSXianjun Jiao } 96*7d0af6dfSXianjun Jiao return 0; 97*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_TOTAL: 98*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 99*7d0af6dfSXianjun Jiao if (!skb) 100*7d0af6dfSXianjun Jiao return -ENOMEM; 101*7d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL_read()); 102*7d0af6dfSXianjun Jiao printk("%s get SLICE_TOTAL(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 103*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL, tmp)) 104*7d0af6dfSXianjun Jiao goto nla_put_failure; 105*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 106*7d0af6dfSXianjun Jiao 107*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_START: 108*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_START]) 109*7d0af6dfSXianjun Jiao return -EINVAL; 110*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START]); 111*7d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 112*7d0af6dfSXianjun Jiao printk("%s set SLICE_START(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 113*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 114*7d0af6dfSXianjun Jiao } else { 115*7d0af6dfSXianjun Jiao printk("%s set SLICE_START(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 116*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_START_write((priv->slice_idx<<20)|tmp); 117*7d0af6dfSXianjun Jiao } 118*7d0af6dfSXianjun Jiao return 0; 119*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_START: 120*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 121*7d0af6dfSXianjun Jiao if (!skb) 122*7d0af6dfSXianjun Jiao return -ENOMEM; 123*7d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_START_read()); 124*7d0af6dfSXianjun Jiao printk("%s get SLICE_START(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 125*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START, tmp)) 126*7d0af6dfSXianjun Jiao goto nla_put_failure; 127*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 128*7d0af6dfSXianjun Jiao 129*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_SLICE_END: 130*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_SLICE_END]) 131*7d0af6dfSXianjun Jiao return -EINVAL; 132*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END]); 133*7d0af6dfSXianjun Jiao if (priv->slice_idx>=MAX_NUM_HW_QUEUE) { 134*7d0af6dfSXianjun Jiao printk("%s set SLICE_END(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx); 135*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 136*7d0af6dfSXianjun Jiao } else { 137*7d0af6dfSXianjun Jiao printk("%s set SLICE_END(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx); 138*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_SLICE_COUNT_END_write((priv->slice_idx<<20)|tmp); 139*7d0af6dfSXianjun Jiao } 140*7d0af6dfSXianjun Jiao return 0; 141*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_SLICE_END: 142*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 143*7d0af6dfSXianjun Jiao if (!skb) 144*7d0af6dfSXianjun Jiao return -ENOMEM; 145*7d0af6dfSXianjun Jiao tmp = (xpu_api->XPU_REG_SLICE_COUNT_END_read()); 146*7d0af6dfSXianjun Jiao printk("%s get SLICE_END(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20); 147*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END, tmp)) 148*7d0af6dfSXianjun Jiao goto nla_put_failure; 149*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 150*7d0af6dfSXianjun Jiao 151*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_TOTAL1: 152*7d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_TOTAL1]) 153*7d0af6dfSXianjun Jiao // return -EINVAL; 154*7d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL1]); 155*7d0af6dfSXianjun Jiao // printk("%s set SLICE_TOTAL1(duration) to %d usec\n", sdr_compatible_str, tmp); 156*7d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_write(tmp); 157*7d0af6dfSXianjun Jiao // return 0; 158*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_TOTAL1: 159*7d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 160*7d0af6dfSXianjun Jiao // if (!skb) 161*7d0af6dfSXianjun Jiao // return -ENOMEM; 162*7d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_read()); 163*7d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL1, tmp)) 164*7d0af6dfSXianjun Jiao // goto nla_put_failure; 165*7d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 166*7d0af6dfSXianjun Jiao 167*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_START1: 168*7d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_START1]) 169*7d0af6dfSXianjun Jiao // return -EINVAL; 170*7d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START1]); 171*7d0af6dfSXianjun Jiao // printk("%s set SLICE_START1(duration) to %d usec\n", sdr_compatible_str, tmp); 172*7d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_START1_write(tmp); 173*7d0af6dfSXianjun Jiao // return 0; 174*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_START1: 175*7d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 176*7d0af6dfSXianjun Jiao // if (!skb) 177*7d0af6dfSXianjun Jiao // return -ENOMEM; 178*7d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_START1_read()); 179*7d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START1, tmp)) 180*7d0af6dfSXianjun Jiao // goto nla_put_failure; 181*7d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 182*7d0af6dfSXianjun Jiao 183*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_SET_SLICE_END1: 184*7d0af6dfSXianjun Jiao // if (!tb[OPENWIFI_ATTR_SLICE_END1]) 185*7d0af6dfSXianjun Jiao // return -EINVAL; 186*7d0af6dfSXianjun Jiao // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END1]); 187*7d0af6dfSXianjun Jiao // printk("%s set SLICE_END1(duration) to %d usec\n", sdr_compatible_str, tmp); 188*7d0af6dfSXianjun Jiao // // xpu_api->XPU_REG_SLICE_COUNT_END1_write(tmp); 189*7d0af6dfSXianjun Jiao // return 0; 190*7d0af6dfSXianjun Jiao // case OPENWIFI_CMD_GET_SLICE_END1: 191*7d0af6dfSXianjun Jiao // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 192*7d0af6dfSXianjun Jiao // if (!skb) 193*7d0af6dfSXianjun Jiao // return -ENOMEM; 194*7d0af6dfSXianjun Jiao // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_END1_read()); 195*7d0af6dfSXianjun Jiao // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END1, tmp)) 196*7d0af6dfSXianjun Jiao // goto nla_put_failure; 197*7d0af6dfSXianjun Jiao // return cfg80211_testmode_reply(skb); 198*7d0af6dfSXianjun Jiao 199*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_RSSI_TH: 200*7d0af6dfSXianjun Jiao if (!tb[OPENWIFI_ATTR_RSSI_TH]) 201*7d0af6dfSXianjun Jiao return -EINVAL; 202*7d0af6dfSXianjun Jiao tmp = nla_get_u32(tb[OPENWIFI_ATTR_RSSI_TH]); 203*7d0af6dfSXianjun Jiao // printk("%s set RSSI_TH to %d\n", sdr_compatible_str, tmp); 204*7d0af6dfSXianjun Jiao // xpu_api->XPU_REG_LBT_TH_write(tmp); 205*7d0af6dfSXianjun Jiao // return 0; 206*7d0af6dfSXianjun 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); 207*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 208*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_GET_RSSI_TH: 209*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 210*7d0af6dfSXianjun Jiao if (!skb) 211*7d0af6dfSXianjun Jiao return -ENOMEM; 212*7d0af6dfSXianjun Jiao tmp_int = rssi_half_db_to_rssi_dbm(xpu_api->XPU_REG_LBT_TH_read(), priv->rssi_correction); //rssi_dbm 213*7d0af6dfSXianjun Jiao tmp = (-tmp_int); 214*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, OPENWIFI_ATTR_RSSI_TH, tmp)) 215*7d0af6dfSXianjun Jiao goto nla_put_failure; 216*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 217*7d0af6dfSXianjun Jiao 218*7d0af6dfSXianjun Jiao case OPENWIFI_CMD_SET_TSF: 219*7d0af6dfSXianjun Jiao printk("openwifi_set_tsf_1"); 220*7d0af6dfSXianjun Jiao if ( (!tb[OPENWIFI_ATTR_HIGH_TSF]) || (!tb[OPENWIFI_ATTR_LOW_TSF]) ) 221*7d0af6dfSXianjun Jiao return -EINVAL; 222*7d0af6dfSXianjun Jiao printk("openwifi_set_tsf_2"); 223*7d0af6dfSXianjun Jiao tsft_high = nla_get_u32(tb[OPENWIFI_ATTR_HIGH_TSF]); 224*7d0af6dfSXianjun Jiao tsft_low = nla_get_u32(tb[OPENWIFI_ATTR_LOW_TSF]); 225*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_TSF_LOAD_VAL_write(tsft_high,tsft_low); 226*7d0af6dfSXianjun Jiao printk("%s openwifi_set_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low); 227*7d0af6dfSXianjun Jiao return 0; 228*7d0af6dfSXianjun Jiao 229*7d0af6dfSXianjun Jiao case REG_CMD_SET: 230*7d0af6dfSXianjun Jiao if ( (!tb[REG_ATTR_ADDR]) || (!tb[REG_ATTR_VAL]) ) 231*7d0af6dfSXianjun Jiao return -EINVAL; 232*7d0af6dfSXianjun Jiao reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]); 233*7d0af6dfSXianjun Jiao reg_val = nla_get_u32(tb[REG_ATTR_VAL]); 234*7d0af6dfSXianjun Jiao reg_cat = ((reg_addr>>16)&0xFFFF); 235*7d0af6dfSXianjun Jiao reg_addr = (reg_addr&0xFFFF); 236*7d0af6dfSXianjun Jiao reg_addr_idx = (reg_addr>>2); 237*7d0af6dfSXianjun 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); 238*7d0af6dfSXianjun Jiao if (reg_cat==SDRCTL_REG_CAT_RF) { 239*7d0af6dfSXianjun Jiao // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str); 240*7d0af6dfSXianjun Jiao // return -EOPNOTSUPP; 241*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) { 242*7d0af6dfSXianjun Jiao priv->rf_reg_val[reg_addr_idx]=reg_val; 243*7d0af6dfSXianjun Jiao if (reg_addr_idx==RF_TX_REG_IDX_ATT) {//change the tx ON att (if a RF chain is ON) 244*7d0af6dfSXianjun Jiao tmp = ad9361_get_tx_atten(priv->ad9361_phy, 1); 245*7d0af6dfSXianjun Jiao printk("%s ad9361_get_tx_atten ant0 %d\n",sdr_compatible_str, tmp); 246*7d0af6dfSXianjun Jiao if (tmp<AD9361_RADIO_OFF_TX_ATT) { 247*7d0af6dfSXianjun Jiao err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, true, false, true); 248*7d0af6dfSXianjun Jiao if (err < 0) { 249*7d0af6dfSXianjun Jiao printk("%s WARNING ad9361_set_tx_atten ant0 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 250*7d0af6dfSXianjun Jiao return -EIO; 251*7d0af6dfSXianjun Jiao } else { 252*7d0af6dfSXianjun Jiao printk("%s ad9361_set_tx_atten ant0 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 253*7d0af6dfSXianjun Jiao } 254*7d0af6dfSXianjun Jiao } 255*7d0af6dfSXianjun Jiao tmp = ad9361_get_tx_atten(priv->ad9361_phy, 2); 256*7d0af6dfSXianjun Jiao printk("%s ad9361_get_tx_atten ant1 %d\n",sdr_compatible_str, tmp); 257*7d0af6dfSXianjun Jiao if (tmp<AD9361_RADIO_OFF_TX_ATT) { 258*7d0af6dfSXianjun Jiao err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, false, true, true); 259*7d0af6dfSXianjun Jiao if (err < 0) { 260*7d0af6dfSXianjun Jiao printk("%s WARNING ad9361_set_tx_atten ant1 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 261*7d0af6dfSXianjun Jiao return -EIO; 262*7d0af6dfSXianjun Jiao } else { 263*7d0af6dfSXianjun Jiao printk("%s ad9361_set_tx_atten ant1 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val); 264*7d0af6dfSXianjun Jiao } 265*7d0af6dfSXianjun Jiao } 266*7d0af6dfSXianjun Jiao } else if (reg_addr_idx==RF_TX_REG_IDX_FO) { // apply the tx fo 267*7d0af6dfSXianjun Jiao clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ( ((u64)1000000ull)*((u64)priv->actual_tx_lo ) + priv->rf_reg_val[RF_TX_REG_IDX_FO] )>>1) ); 268*7d0af6dfSXianjun Jiao printk("%s clk_set_rate TX %llu\n",sdr_compatible_str, ((u64)1000000ull)*((u64)priv->actual_tx_lo ) + priv->rf_reg_val[RF_TX_REG_IDX_FO]); 269*7d0af6dfSXianjun Jiao } else if (reg_addr_idx==RF_RX_REG_IDX_FO) { // apply the rx fo 270*7d0af6dfSXianjun Jiao clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ( ((u64)1000000ull)*((u64)priv->actual_rx_lo ) + priv->rf_reg_val[RF_RX_REG_IDX_FO] )>>1) ); 271*7d0af6dfSXianjun Jiao printk("%s clk_set_rate RX %llu\n",sdr_compatible_str, ((u64)1000000ull)*((u64)priv->actual_rx_lo ) + priv->rf_reg_val[RF_RX_REG_IDX_FO]); 272*7d0af6dfSXianjun Jiao } 273*7d0af6dfSXianjun Jiao } else { 274*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 275*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 276*7d0af6dfSXianjun Jiao } 277*7d0af6dfSXianjun Jiao } 278*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX_INTF) 279*7d0af6dfSXianjun Jiao rx_intf_api->reg_write(reg_addr,reg_val); 280*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX_INTF) 281*7d0af6dfSXianjun Jiao tx_intf_api->reg_write(reg_addr,reg_val); 282*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX) 283*7d0af6dfSXianjun Jiao openofdm_rx_api->reg_write(reg_addr,reg_val); 284*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX) 285*7d0af6dfSXianjun Jiao openofdm_tx_api->reg_write(reg_addr,reg_val); 286*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_XPU) 287*7d0af6dfSXianjun Jiao xpu_api->reg_write(reg_addr,reg_val); 288*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) { 289*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 290*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG) { 291*7d0af6dfSXianjun Jiao tmp = openwifi_set_antenna(hw, (priv->drv_tx_reg_val[reg_addr_idx]==0?1:2), (reg_val==0?1:2)); 292*7d0af6dfSXianjun Jiao if (tmp) { 293*7d0af6dfSXianjun Jiao printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp); 294*7d0af6dfSXianjun Jiao return -EIO; 295*7d0af6dfSXianjun Jiao } else { 296*7d0af6dfSXianjun Jiao priv->drv_rx_reg_val[reg_addr_idx]=reg_val; 297*7d0af6dfSXianjun Jiao } 298*7d0af6dfSXianjun Jiao } else { 299*7d0af6dfSXianjun Jiao priv->drv_rx_reg_val[reg_addr_idx]=reg_val; 300*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_DEMOD_TH) { 301*7d0af6dfSXianjun 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)); 302*7d0af6dfSXianjun Jiao } 303*7d0af6dfSXianjun Jiao } 304*7d0af6dfSXianjun Jiao } else { 305*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 306*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 307*7d0af6dfSXianjun Jiao } 308*7d0af6dfSXianjun Jiao } 309*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) { 310*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 311*7d0af6dfSXianjun Jiao if ((reg_addr_idx == DRV_TX_REG_IDX_RATE || reg_addr_idx == DRV_TX_REG_IDX_RATE_HT) && 312*7d0af6dfSXianjun Jiao (reg_val != 0 && (!((reg_val&0xF)>=4 && (reg_val&0xF)<=11)) ) ) { 313*7d0af6dfSXianjun Jiao printk("%s WARNING rate override value should be 0 or 4~11!\n", sdr_compatible_str); 314*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 315*7d0af6dfSXianjun Jiao } else { 316*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG) { 317*7d0af6dfSXianjun Jiao tmp = openwifi_set_antenna(hw, reg_val+1, priv->drv_rx_reg_val[reg_addr_idx]+1); 318*7d0af6dfSXianjun Jiao if (tmp) { 319*7d0af6dfSXianjun Jiao printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp); 320*7d0af6dfSXianjun Jiao return -EIO; 321*7d0af6dfSXianjun Jiao } else { 322*7d0af6dfSXianjun Jiao priv->drv_tx_reg_val[reg_addr_idx]=reg_val; 323*7d0af6dfSXianjun Jiao } 324*7d0af6dfSXianjun Jiao } else { 325*7d0af6dfSXianjun Jiao priv->drv_tx_reg_val[reg_addr_idx]=reg_val; 326*7d0af6dfSXianjun Jiao } 327*7d0af6dfSXianjun Jiao } 328*7d0af6dfSXianjun Jiao } else { 329*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 330*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 331*7d0af6dfSXianjun Jiao } 332*7d0af6dfSXianjun Jiao } 333*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) { 334*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 335*7d0af6dfSXianjun Jiao priv->drv_xpu_reg_val[reg_addr_idx]=reg_val; 336*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) { 337*7d0af6dfSXianjun Jiao if (reg_val) { 338*7d0af6dfSXianjun Jiao tmp_int = (-reg_val); // rssi_dbm 339*7d0af6dfSXianjun Jiao tmp = rssi_dbm_to_rssi_half_db(tmp_int, priv->rssi_correction); 340*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_LBT_TH_write( tmp ); 341*7d0af6dfSXianjun 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)); 342*7d0af6dfSXianjun Jiao } else { 343*7d0af6dfSXianjun Jiao xpu_api->XPU_REG_LBT_TH_write(priv->last_auto_fpga_lbt_th); 344*7d0af6dfSXianjun 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)); 345*7d0af6dfSXianjun Jiao } 346*7d0af6dfSXianjun Jiao } 347*7d0af6dfSXianjun Jiao } else { 348*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 349*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 350*7d0af6dfSXianjun Jiao } 351*7d0af6dfSXianjun Jiao } 352*7d0af6dfSXianjun Jiao else { 353*7d0af6dfSXianjun Jiao printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat); 354*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 355*7d0af6dfSXianjun Jiao } 356*7d0af6dfSXianjun Jiao 357*7d0af6dfSXianjun Jiao return 0; 358*7d0af6dfSXianjun Jiao case REG_CMD_GET: 359*7d0af6dfSXianjun Jiao skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32))); 360*7d0af6dfSXianjun Jiao if (!skb) 361*7d0af6dfSXianjun Jiao return -ENOMEM; 362*7d0af6dfSXianjun Jiao reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]); 363*7d0af6dfSXianjun Jiao reg_cat = ((reg_addr>>16)&0xFFFF); 364*7d0af6dfSXianjun Jiao reg_addr = (reg_addr&0xFFFF); 365*7d0af6dfSXianjun Jiao reg_addr_idx = (reg_addr>>2); 366*7d0af6dfSXianjun Jiao printk("%s recv get cmd reg cat %d addr %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_addr_idx); 367*7d0af6dfSXianjun Jiao if (reg_cat==SDRCTL_REG_CAT_RF) { 368*7d0af6dfSXianjun Jiao // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str); 369*7d0af6dfSXianjun Jiao // tmp = 0xFFFFFFFF; 370*7d0af6dfSXianjun Jiao // return -EOPNOTSUPP; 371*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) { 372*7d0af6dfSXianjun Jiao tmp = priv->rf_reg_val[reg_addr_idx]; 373*7d0af6dfSXianjun Jiao } else { 374*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 375*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 376*7d0af6dfSXianjun Jiao } 377*7d0af6dfSXianjun Jiao } 378*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX_INTF) 379*7d0af6dfSXianjun Jiao tmp = rx_intf_api->reg_read(reg_addr); 380*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX_INTF) 381*7d0af6dfSXianjun Jiao tmp = tx_intf_api->reg_read(reg_addr); 382*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_RX) 383*7d0af6dfSXianjun Jiao tmp = openofdm_rx_api->reg_read(reg_addr); 384*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_TX) 385*7d0af6dfSXianjun Jiao tmp = openofdm_tx_api->reg_read(reg_addr); 386*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_XPU) 387*7d0af6dfSXianjun Jiao tmp = xpu_api->reg_read(reg_addr); 388*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) { 389*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 390*7d0af6dfSXianjun Jiao tmp = priv->drv_rx_reg_val[reg_addr_idx]; 391*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG) 392*7d0af6dfSXianjun Jiao openwifi_get_antenna(hw, &tsft_high, &tsft_low); 393*7d0af6dfSXianjun Jiao } else { 394*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 395*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 396*7d0af6dfSXianjun Jiao } 397*7d0af6dfSXianjun Jiao } 398*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) { 399*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 400*7d0af6dfSXianjun Jiao tmp = priv->drv_tx_reg_val[reg_addr_idx]; 401*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG) 402*7d0af6dfSXianjun Jiao openwifi_get_antenna(hw, &tsft_high, &tsft_low); 403*7d0af6dfSXianjun Jiao } else { 404*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 405*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 406*7d0af6dfSXianjun Jiao } 407*7d0af6dfSXianjun Jiao } 408*7d0af6dfSXianjun Jiao else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) { 409*7d0af6dfSXianjun Jiao if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) { 410*7d0af6dfSXianjun Jiao if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) { 411*7d0af6dfSXianjun Jiao tmp = xpu_api->XPU_REG_LBT_TH_read();//rssi_half_db 412*7d0af6dfSXianjun Jiao tmp_int = rssi_half_db_to_rssi_dbm(tmp, priv->rssi_correction); //rssi_dbm 413*7d0af6dfSXianjun 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)); 414*7d0af6dfSXianjun Jiao } 415*7d0af6dfSXianjun Jiao tmp = priv->drv_xpu_reg_val[reg_addr_idx]; 416*7d0af6dfSXianjun Jiao } else { 417*7d0af6dfSXianjun Jiao printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx); 418*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 419*7d0af6dfSXianjun Jiao } 420*7d0af6dfSXianjun Jiao } 421*7d0af6dfSXianjun Jiao else { 422*7d0af6dfSXianjun Jiao printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat); 423*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 424*7d0af6dfSXianjun Jiao } 425*7d0af6dfSXianjun Jiao 426*7d0af6dfSXianjun Jiao if (nla_put_u32(skb, REG_ATTR_VAL, tmp)) 427*7d0af6dfSXianjun Jiao goto nla_put_failure; 428*7d0af6dfSXianjun Jiao return cfg80211_testmode_reply(skb); 429*7d0af6dfSXianjun Jiao 430*7d0af6dfSXianjun Jiao default: 431*7d0af6dfSXianjun Jiao return -EOPNOTSUPP; 432*7d0af6dfSXianjun Jiao } 433*7d0af6dfSXianjun Jiao 434*7d0af6dfSXianjun Jiao nla_put_failure: 435*7d0af6dfSXianjun Jiao dev_kfree_skb(skb); 436*7d0af6dfSXianjun Jiao return -ENOBUFS; 437*7d0af6dfSXianjun Jiao } 438