diff options
Diffstat (limited to 'drivers/staging/brcm80211/brcmsmac/antsel.c')
-rw-r--r-- | drivers/staging/brcm80211/brcmsmac/antsel.c | 240 |
1 files changed, 118 insertions, 122 deletions
diff --git a/drivers/staging/brcm80211/brcmsmac/antsel.c b/drivers/staging/brcm80211/brcmsmac/antsel.c index c4e76c093ae9..a47ce25cb9a2 100644 --- a/drivers/staging/brcm80211/brcmsmac/antsel.c +++ b/drivers/staging/brcm80211/brcmsmac/antsel.c @@ -18,7 +18,6 @@ #include <net/mac80211.h> #include "types.h" -#include "bmac.h" #include "main.h" #include "phy_shim.h" #include "antsel.h" @@ -50,55 +49,76 @@ #define ANT_SELCFG_NUM_2x4 4 #define ANT_SELCFG_DEF_2x4 0x02 /* default antenna configuration */ -/* static functions */ -static int brcms_c_antsel_cfgupd(struct antsel_info *asi, - struct brcms_antselcfg *antsel); -static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id); -static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg); -static void brcms_c_antsel_init_cfg(struct antsel_info *asi, - struct brcms_antselcfg *antsel, - bool auto_sel); - -const u16 mimo_2x4_div_antselpat_tbl[] = { +static const u16 mimo_2x4_div_antselpat_tbl[] = { 0, 0, 0x9, 0xa, /* ant0: 0 ant1: 2,3 */ 0, 0, 0x5, 0x6, /* ant0: 1 ant1: 2,3 */ 0, 0, 0, 0, /* n.a. */ 0, 0, 0, 0 /* n.a. */ }; -const u8 mimo_2x4_div_antselid_tbl[16] = { +static const u8 mimo_2x4_div_antselid_tbl[16] = { 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0 /* pat to antselid */ }; -const u16 mimo_2x3_div_antselpat_tbl[] = { +static const u16 mimo_2x3_div_antselpat_tbl[] = { 16, 0, 1, 16, /* ant0: 0 ant1: 1,2 */ 16, 16, 16, 16, /* n.a. */ 16, 2, 16, 16, /* ant0: 2 ant1: 1 */ 16, 16, 16, 16 /* n.a. */ }; -const u8 mimo_2x3_div_antselid_tbl[16] = { +static const u8 mimo_2x3_div_antselid_tbl[16] = { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* pat to antselid */ }; +/* boardlevel antenna selection: init antenna selection structure */ +static void +brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, + bool auto_sel) +{ + if (asi->antsel_type == ANTSEL_2x3) { + u8 antcfg_def = ANT_SELCFG_DEF_2x3 | + ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0); + antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def; + antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def; + antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def; + antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def; + antsel->num_antcfg = ANT_SELCFG_NUM_2x3; + + } else if (asi->antsel_type == ANTSEL_2x4) { + + antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4; + antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4; + antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4; + antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4; + antsel->num_antcfg = ANT_SELCFG_NUM_2x4; + + } else { /* no antenna selection available */ + + antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2; + antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2; + antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2; + antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2; + antsel->num_antcfg = 0; + } +} + struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) { struct antsel_info *asi; + struct si_pub *sih = wlc->hw->sih; asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); - if (!asi) { - wiphy_err(wlc->wiphy, "wl%d: brcms_c_antsel_attach: out of " - "mem\n", wlc->pub->unit); + if (!asi) return NULL; - } asi->wlc = wlc; asi->pub = wlc->pub; asi->antsel_type = ANTSEL_NA; asi->antsel_avail = false; - asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch"); + asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { switch (asi->antsel_antswitch) { @@ -108,27 +128,26 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) /* 4321/2 board with 2x3 switch logic */ asi->antsel_type = ANTSEL_2x3; /* Antenna selection availability */ - if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) || - ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) { + if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || + ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { asi->antsel_avail = true; - } else - if (((u16) getintvar(asi->pub->vars, "aa2g") == - 3) - || ((u16) getintvar(asi->pub->vars, "aa5g") - == 3)) { + } else if ( + (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || + (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { asi->antsel_avail = false; } else { asi->antsel_avail = false; wiphy_err(wlc->wiphy, "antsel_attach: 2o3 " "board cfg invalid\n"); } + break; default: break; } } else if ((asi->pub->sromrev == 4) && - ((u16) getintvar(asi->pub->vars, "aa2g") == 7) && - ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) { + ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && + ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { /* hack to match old 4321CB2 cards with 2of3 antenna switch */ asi->antsel_type = ANTSEL_2x3; asi->antsel_avail = true; @@ -152,6 +171,64 @@ void brcms_c_antsel_detach(struct antsel_info *asi) kfree(asi); } +/* + * boardlevel antenna selection: + * convert ant_cfg to mimo_antsel (ucode interface) + */ +static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) +{ + u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); + u16 mimo_antsel = 0; + + if (asi->antsel_type == ANTSEL_2x4) { + /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ + mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf); + return mimo_antsel; + + } else if (asi->antsel_type == ANTSEL_2x3) { + /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ + mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf); + return mimo_antsel; + } + + return mimo_antsel; +} + +/* boardlevel antenna selection: ucode interface control */ +static int brcms_c_antsel_cfgupd(struct antsel_info *asi, + struct brcms_antselcfg *antsel) +{ + struct brcms_c_info *wlc = asi->wlc; + u8 ant_cfg; + u16 mimo_antsel; + + /* 1) Update TX antconfig for all frames that are not unicast data + * (aka default TX) + */ + ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; + mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); + brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); + /* + * Update driver stats for currently selected + * default tx/rx antenna config + */ + asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; + + /* 2) Update RX antconfig for all frames that are not unicast data + * (aka default RX) + */ + ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; + mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); + brcms_b_write_shm(wlc->hw, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); + /* + * Update driver stats for currently selected + * default tx/rx antenna config + */ + asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; + + return 0; +} + void brcms_c_antsel_init(struct antsel_info *asi) { if ((asi->antsel_type == ANTSEL_2x3) || @@ -159,36 +236,23 @@ void brcms_c_antsel_init(struct antsel_info *asi) brcms_c_antsel_cfgupd(asi, &asi->antcfg_11n); } -/* boardlevel antenna selection: init antenna selection structure */ -static void -brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, - bool auto_sel) +/* boardlevel antenna selection: convert id to ant_cfg */ +static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) { - if (asi->antsel_type == ANTSEL_2x3) { - u8 antcfg_def = ANT_SELCFG_DEF_2x3 | - ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0); - antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def; - antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def; - antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def; - antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def; - antsel->num_antcfg = ANT_SELCFG_NUM_2x3; - - } else if (asi->antsel_type == ANTSEL_2x4) { - - antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4; - antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4; - antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4; - antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4; - antsel->num_antcfg = ANT_SELCFG_NUM_2x4; + u8 antcfg = ANT_SELCFG_DEF_2x2; - } else { /* no antenna selection available */ + if (asi->antsel_type == ANTSEL_2x4) { + /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ + antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2)); + return antcfg; - antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2; - antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2; - antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2; - antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2; - antsel->num_antcfg = 0; + } else if (asi->antsel_type == ANTSEL_2x3) { + /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ + antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1)); + return antcfg; } + + return antcfg; } void @@ -241,71 +305,3 @@ u8 brcms_c_antsel_antsel2id(struct antsel_info *asi, u16 antsel) return antselid; } - -/* boardlevel antenna selection: convert id to ant_cfg */ -static u8 brcms_c_antsel_id2antcfg(struct antsel_info *asi, u8 id) -{ - u8 antcfg = ANT_SELCFG_DEF_2x2; - - if (asi->antsel_type == ANTSEL_2x4) { - /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ - antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2)); - return antcfg; - - } else if (asi->antsel_type == ANTSEL_2x3) { - /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ - antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1)); - return antcfg; - } - - return antcfg; -} - -/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */ -static u16 brcms_c_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg) -{ - u8 idx = BRCMS_ANTIDX_11N(BRCMS_ANTSEL_11N(ant_cfg)); - u16 mimo_antsel = 0; - - if (asi->antsel_type == ANTSEL_2x4) { - /* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */ - mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf); - return mimo_antsel; - - } else if (asi->antsel_type == ANTSEL_2x3) { - /* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */ - mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf); - return mimo_antsel; - } - - return mimo_antsel; -} - -/* boardlevel antenna selection: ucode interface control */ -static int brcms_c_antsel_cfgupd(struct antsel_info *asi, - struct brcms_antselcfg *antsel) -{ - struct brcms_c_info *wlc = asi->wlc; - u8 ant_cfg; - u16 mimo_antsel; - - /* 1) Update TX antconfig for all frames that are not unicast data - * (aka default TX) - */ - ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF]; - mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); - brcms_c_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel); - /* Update driver stats for currently selected default tx/rx antenna config */ - asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg; - - /* 2) Update RX antconfig for all frames that are not unicast data - * (aka default RX) - */ - ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF]; - mimo_antsel = brcms_c_antsel_antcfg2antsel(asi, ant_cfg); - brcms_c_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel); - /* Update driver stats for currently selected default tx/rx antenna config */ - asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg; - - return 0; -} |