drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/broadcom/brcm80211/brcmsmac/antsel.c
Extension
.c
Size
9650 bytes
Lines
310
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (asi->antsel_antswitch) {
		case ANTSWITCH_TYPE_1:
		case ANTSWITCH_TYPE_2:
		case ANTSWITCH_TYPE_3:
			/* 4321/2 board with 2x3 switch logic */
			asi->antsel_type = ANTSEL_2x3;
			/* Antenna selection availability */
			if ((sprom->ant_available_bg == 7) ||
			    (sprom->ant_available_a == 7)) {
				asi->antsel_avail = true;
			} else if (
				sprom->ant_available_bg == 3 ||
				sprom->ant_available_a == 3) {
				asi->antsel_avail = false;
			} else {
				asi->antsel_avail = false;
				brcms_err(wlc->hw->d11core,
					  "antsel_attach: 2o3 "
					  "board cfg invalid\n");
			}

			break;
		default:
			break;
		}
	} else if ((asi->pub->sromrev == 4) &&
		   (sprom->ant_available_bg == 7) &&
		   (sprom->ant_available_a == 0)) {
		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
		asi->antsel_type = ANTSEL_2x3;
		asi->antsel_avail = true;
	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
		asi->antsel_type = ANTSEL_2x4;
		asi->antsel_avail = true;
	}

	/* Set the antenna selection type for the low driver */
	brcms_b_antsel_type_set(wlc->hw, asi->antsel_type);

	/* Init (auto/manual) antenna selection */
	brcms_c_antsel_init_cfg(asi, &asi->antcfg_11n, true);
	brcms_c_antsel_init_cfg(asi, &asi->antcfg_cur, true);

	return asi;
}

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

Annotation

Implementation Notes