freebsd-skq/sys/dev/bwn/if_bwn_phy_lp.c
landonf 601b99882d bwn(4): migrate bwn(4) to the native bhnd(9) interface, and drop siba_bwn.
- Remove the shim interface that allowed bwn(4) to use either siba_bwn or
  bhnd(4), replacing all siba_bwn calls with their bhnd(4) bus equivalents.
- Drop the legay, now-unused siba_bwn bus driver.
- Clean up bhnd(4) board flag defines referenced by bwn(4).

Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D13518
2018-02-05 23:38:15 +00:00

3759 lines
137 KiB
C

/*-
* Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
* redistribution must be conditioned upon including a substantially
* similar Disclaimer requirement for further binary redistribution.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGES.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_bwn.h"
#include "opt_wlan.h"
/*
* The Broadcom Wireless LAN controller driver.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/firmware.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_phy.h>
#include <net80211/ieee80211_ratectl.h>
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/bhnd_ids.h>
#include <dev/bhnd/cores/pmu/bhnd_pmu.h>
#include <dev/bwn/if_bwnreg.h>
#include <dev/bwn/if_bwnvar.h>
#include <dev/bwn/if_bwn_debug.h>
#include <dev/bwn/if_bwn_misc.h>
#include <dev/bwn/if_bwn_util.h>
#include <dev/bwn/if_bwn_phy_common.h>
#include <dev/bwn/if_bwn_phy_lp.h>
#include "bhnd_nvram_map.h"
static int bwn_phy_lp_readsprom(struct bwn_mac *);
static void bwn_phy_lp_bbinit(struct bwn_mac *);
static void bwn_phy_lp_txpctl_init(struct bwn_mac *);
static void bwn_phy_lp_calib(struct bwn_mac *);
static int bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
static int bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
static void bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
static void bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
static void bwn_phy_lp_digflt_save(struct bwn_mac *);
static void bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
static void bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
static void bwn_phy_lp_bugfix(struct bwn_mac *);
static void bwn_phy_lp_digflt_restore(struct bwn_mac *);
static void bwn_phy_lp_tblinit(struct bwn_mac *);
static void bwn_phy_lp_bbinit_r2(struct bwn_mac *);
static void bwn_phy_lp_bbinit_r01(struct bwn_mac *);
static int bwn_phy_lp_b2062_init(struct bwn_mac *);
static int bwn_phy_lp_b2063_init(struct bwn_mac *);
static int bwn_phy_lp_rxcal_r2(struct bwn_mac *);
static int bwn_phy_lp_rccal_r12(struct bwn_mac *);
static void bwn_phy_lp_set_rccap(struct bwn_mac *);
static uint32_t bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
static void bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
static void bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
static void bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
const void *);
static void bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
static struct bwn_txgain
bwn_phy_lp_get_txgain(struct bwn_mac *);
static uint8_t bwn_phy_lp_get_bbmult(struct bwn_mac *);
static void bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
static void bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
static void bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
static void bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
static void bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
static int bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
static void bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
static void bwn_phy_lp_tblinit_r01(struct bwn_mac *);
static void bwn_phy_lp_tblinit_r2(struct bwn_mac *);
static void bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
static void bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
static void bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
static void bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
static int bwn_phy_lp_loopback(struct bwn_mac *);
static void bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
static void bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
int);
static uint8_t bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
struct bwn_phy_lp_iq_est *);
static void bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
static uint32_t bwn_tab_read(struct bwn_mac *, uint32_t);
static void bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
static void bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
static void bwn_phy_lp_set_txgain_override(struct bwn_mac *);
static uint16_t bwn_phy_lp_get_pa_gain(struct bwn_mac *);
static uint8_t bwn_nbits(int32_t);
static void bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
struct bwn_txgain_entry *);
static void bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
struct bwn_txgain_entry);
static void bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
struct bwn_txgain_entry);
static void bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
struct bwn_txgain_entry);
static const uint8_t bwn_b2063_chantable_data[33][12] = {
{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
};
static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
{ 1, 2412, bwn_b2063_chantable_data[0] },
{ 2, 2417, bwn_b2063_chantable_data[0] },
{ 3, 2422, bwn_b2063_chantable_data[0] },
{ 4, 2427, bwn_b2063_chantable_data[1] },
{ 5, 2432, bwn_b2063_chantable_data[1] },
{ 6, 2437, bwn_b2063_chantable_data[1] },
{ 7, 2442, bwn_b2063_chantable_data[1] },
{ 8, 2447, bwn_b2063_chantable_data[1] },
{ 9, 2452, bwn_b2063_chantable_data[2] },
{ 10, 2457, bwn_b2063_chantable_data[2] },
{ 11, 2462, bwn_b2063_chantable_data[3] },
{ 12, 2467, bwn_b2063_chantable_data[3] },
{ 13, 2472, bwn_b2063_chantable_data[3] },
{ 14, 2484, bwn_b2063_chantable_data[4] },
{ 34, 5170, bwn_b2063_chantable_data[5] },
{ 36, 5180, bwn_b2063_chantable_data[6] },
{ 38, 5190, bwn_b2063_chantable_data[7] },
{ 40, 5200, bwn_b2063_chantable_data[8] },
{ 42, 5210, bwn_b2063_chantable_data[9] },
{ 44, 5220, bwn_b2063_chantable_data[10] },
{ 46, 5230, bwn_b2063_chantable_data[11] },
{ 48, 5240, bwn_b2063_chantable_data[12] },
{ 52, 5260, bwn_b2063_chantable_data[13] },
{ 56, 5280, bwn_b2063_chantable_data[14] },
{ 60, 5300, bwn_b2063_chantable_data[14] },
{ 64, 5320, bwn_b2063_chantable_data[15] },
{ 100, 5500, bwn_b2063_chantable_data[16] },
{ 104, 5520, bwn_b2063_chantable_data[17] },
{ 108, 5540, bwn_b2063_chantable_data[18] },
{ 112, 5560, bwn_b2063_chantable_data[19] },
{ 116, 5580, bwn_b2063_chantable_data[20] },
{ 120, 5600, bwn_b2063_chantable_data[21] },
{ 124, 5620, bwn_b2063_chantable_data[21] },
{ 128, 5640, bwn_b2063_chantable_data[22] },
{ 132, 5660, bwn_b2063_chantable_data[22] },
{ 136, 5680, bwn_b2063_chantable_data[22] },
{ 140, 5700, bwn_b2063_chantable_data[23] },
{ 149, 5745, bwn_b2063_chantable_data[23] },
{ 153, 5765, bwn_b2063_chantable_data[23] },
{ 157, 5785, bwn_b2063_chantable_data[23] },
{ 161, 5805, bwn_b2063_chantable_data[23] },
{ 165, 5825, bwn_b2063_chantable_data[23] },
{ 184, 4920, bwn_b2063_chantable_data[24] },
{ 188, 4940, bwn_b2063_chantable_data[25] },
{ 192, 4960, bwn_b2063_chantable_data[26] },
{ 196, 4980, bwn_b2063_chantable_data[27] },
{ 200, 5000, bwn_b2063_chantable_data[28] },
{ 204, 5020, bwn_b2063_chantable_data[29] },
{ 208, 5040, bwn_b2063_chantable_data[30] },
{ 212, 5060, bwn_b2063_chantable_data[31] },
{ 216, 5080, bwn_b2063_chantable_data[32] }
};
static const uint8_t bwn_b2062_chantable_data[22][12] = {
{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
};
static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
{ 1, 2412, bwn_b2062_chantable_data[0] },
{ 2, 2417, bwn_b2062_chantable_data[0] },
{ 3, 2422, bwn_b2062_chantable_data[0] },
{ 4, 2427, bwn_b2062_chantable_data[0] },
{ 5, 2432, bwn_b2062_chantable_data[0] },
{ 6, 2437, bwn_b2062_chantable_data[0] },
{ 7, 2442, bwn_b2062_chantable_data[0] },
{ 8, 2447, bwn_b2062_chantable_data[0] },
{ 9, 2452, bwn_b2062_chantable_data[0] },
{ 10, 2457, bwn_b2062_chantable_data[0] },
{ 11, 2462, bwn_b2062_chantable_data[0] },
{ 12, 2467, bwn_b2062_chantable_data[0] },
{ 13, 2472, bwn_b2062_chantable_data[0] },
{ 14, 2484, bwn_b2062_chantable_data[0] },
{ 34, 5170, bwn_b2062_chantable_data[1] },
{ 38, 5190, bwn_b2062_chantable_data[2] },
{ 42, 5210, bwn_b2062_chantable_data[2] },
{ 46, 5230, bwn_b2062_chantable_data[3] },
{ 36, 5180, bwn_b2062_chantable_data[4] },
{ 40, 5200, bwn_b2062_chantable_data[5] },
{ 44, 5220, bwn_b2062_chantable_data[6] },
{ 48, 5240, bwn_b2062_chantable_data[3] },
{ 52, 5260, bwn_b2062_chantable_data[3] },
{ 56, 5280, bwn_b2062_chantable_data[3] },
{ 60, 5300, bwn_b2062_chantable_data[7] },
{ 64, 5320, bwn_b2062_chantable_data[8] },
{ 100, 5500, bwn_b2062_chantable_data[9] },
{ 104, 5520, bwn_b2062_chantable_data[10] },
{ 108, 5540, bwn_b2062_chantable_data[10] },
{ 112, 5560, bwn_b2062_chantable_data[10] },
{ 116, 5580, bwn_b2062_chantable_data[11] },
{ 120, 5600, bwn_b2062_chantable_data[12] },
{ 124, 5620, bwn_b2062_chantable_data[12] },
{ 128, 5640, bwn_b2062_chantable_data[12] },
{ 132, 5660, bwn_b2062_chantable_data[12] },
{ 136, 5680, bwn_b2062_chantable_data[12] },
{ 140, 5700, bwn_b2062_chantable_data[12] },
{ 149, 5745, bwn_b2062_chantable_data[12] },
{ 153, 5765, bwn_b2062_chantable_data[12] },
{ 157, 5785, bwn_b2062_chantable_data[12] },
{ 161, 5805, bwn_b2062_chantable_data[12] },
{ 165, 5825, bwn_b2062_chantable_data[12] },
{ 184, 4920, bwn_b2062_chantable_data[13] },
{ 188, 4940, bwn_b2062_chantable_data[14] },
{ 192, 4960, bwn_b2062_chantable_data[15] },
{ 196, 4980, bwn_b2062_chantable_data[16] },
{ 200, 5000, bwn_b2062_chantable_data[17] },
{ 204, 5020, bwn_b2062_chantable_data[18] },
{ 208, 5040, bwn_b2062_chantable_data[19] },
{ 212, 5060, bwn_b2062_chantable_data[20] },
{ 216, 5080, bwn_b2062_chantable_data[21] }
};
/* for LP PHY */
static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
{ 1, -66, 15 }, { 2, -66, 15 }, { 3, -66, 15 }, { 4, -66, 15 },
{ 5, -66, 15 }, { 6, -66, 15 }, { 7, -66, 14 }, { 8, -66, 14 },
{ 9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
{ 13, -66, 13 }, { 14, -66, 13 },
};
/* for LP PHY */
static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
{ 1, -64, 13 }, { 2, -64, 13 }, { 3, -64, 13 }, { 4, -64, 13 },
{ 5, -64, 12 }, { 6, -64, 12 }, { 7, -64, 12 }, { 8, -64, 12 },
{ 9, -64, 12 }, { 10, -64, 11 }, { 11, -64, 11 }, { 12, -64, 11 },
{ 13, -64, 11 }, { 14, -64, 10 }, { 34, -62, 24 }, { 38, -62, 24 },
{ 42, -62, 24 }, { 46, -62, 23 }, { 36, -62, 24 }, { 40, -62, 24 },
{ 44, -62, 23 }, { 48, -62, 23 }, { 52, -62, 23 }, { 56, -62, 22 },
{ 60, -62, 22 }, { 64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
{ 140, -62, 10 }, { 149, -61, 9 }, { 153, -61, 9 }, { 157, -61, 9 },
{ 161, -61, 8 }, { 165, -61, 8 }, { 184, -62, 25 }, { 188, -62, 25 },
{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
};
static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
static const uint8_t bwn_tab_sigsq_tbl[] = {
0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
};
static const uint8_t bwn_tab_pllfrac_tbl[] = {
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
};
static const uint16_t bwn_tabl_iqlocal_tbl[] = {
0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
};
void
bwn_phy_lp_init_pre(struct bwn_mac *mac)
{
struct bwn_phy *phy = &mac->mac_phy;
struct bwn_phy_lp *plp = &phy->phy_lp;
plp->plp_antenna = BWN_ANT_DEFAULT;
}
int
bwn_phy_lp_init(struct bwn_mac *mac)
{
static const struct bwn_stxtable tables[] = {
{ 2, 6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
{ 1, 8, 0x50, 0, 0x7f }, { 0, 8, 0x44, 0, 0xff },
{ 1, 0, 0x4a, 0, 0xff }, { 0, 4, 0x4d, 0, 0xff },
{ 1, 4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
{ 1, 0, 0x4f, 4, 0x0f }, { 3, 0, 0x49, 0, 0x0f },
{ 4, 3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
{ 4, 0, 0x46, 1, 0x07 }, { 3, 8, 0x48, 4, 0x07 },
{ 3, 11, 0x48, 0, 0x0f }, { 3, 4, 0x49, 4, 0x0f },
{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
{ 6, 0, 0x52, 7, 0x01 }, { 5, 3, 0x41, 5, 0x07 },
{ 5, 6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
{ 4, 15, 0x42, 0, 0x01 }, { 5, 0, 0x42, 1, 0x07 },
{ 4, 11, 0x43, 4, 0x0f }, { 4, 7, 0x43, 0, 0x0f },
{ 4, 6, 0x45, 1, 0x01 }, { 2, 7, 0x40, 4, 0x0f },
{ 2, 11, 0x40, 0, 0x0f }
};
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
const struct bwn_stxtable *st;
struct ieee80211com *ic = &sc->sc_ic;
int i, error;
uint16_t tmp;
/* All LP-PHY devices have a PMU */
if (sc->sc_pmu == NULL) {
device_printf(sc->sc_dev, "no PMU; cannot configure PAREF "
"LDO\n");
return (ENXIO);
}
if ((error = bwn_phy_lp_readsprom(mac)))
return (error);
bwn_phy_lp_bbinit(mac);
/* initialize RF */
BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
DELAY(1);
BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
DELAY(1);
if (mac->mac_phy.rf_ver == 0x2062) {
if ((error = bwn_phy_lp_b2062_init(mac)))
return (error);
} else {
if ((error = bwn_phy_lp_b2063_init(mac)))
return (error);
/* synchronize stx table. */
for (i = 0; i < N(tables); i++) {
st = &tables[i];
tmp = BWN_RF_READ(mac, st->st_rfaddr);
tmp >>= st->st_rfshift;
tmp <<= st->st_physhift;
BWN_PHY_SETMASK(mac,
BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
~(st->st_mask << st->st_physhift), tmp);
}
BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
}
/* calibrate RC */
if (mac->mac_phy.rev >= 2) {
if ((error = bwn_phy_lp_rxcal_r2(mac)))
return (error);
} else if (!plp->plp_rccap) {
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
if ((error = bwn_phy_lp_rccal_r12(mac)))
return (error);
}
} else
bwn_phy_lp_set_rccap(mac);
error = bwn_phy_lp_switch_channel(mac, 7);
if (error)
device_printf(sc->sc_dev,
"failed to change channel 7 (%d)\n", error);
bwn_phy_lp_txpctl_init(mac);
bwn_phy_lp_calib(mac);
return (0);
}
uint16_t
bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
{
BWN_WRITE_2(mac, BWN_PHYCTL, reg);
return (BWN_READ_2(mac, BWN_PHYDATA));
}
void
bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
{
BWN_WRITE_2(mac, BWN_PHYCTL, reg);
BWN_WRITE_2(mac, BWN_PHYDATA, value);
}
void
bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
uint16_t set)
{
BWN_WRITE_2(mac, BWN_PHYCTL, reg);
BWN_WRITE_2(mac, BWN_PHYDATA,
(BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
}
uint16_t
bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
{
KASSERT(reg != 1, ("unaccessible register %d", reg));
if (mac->mac_phy.rev < 2 && reg != 0x4001)
reg |= 0x100;
if (mac->mac_phy.rev >= 2)
reg |= 0x200;
BWN_WRITE_2(mac, BWN_RFCTL, reg);
return BWN_READ_2(mac, BWN_RFDATALO);
}
void
bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
{
KASSERT(reg != 1, ("unaccessible register %d", reg));
BWN_WRITE_2(mac, BWN_RFCTL, reg);
BWN_WRITE_2(mac, BWN_RFDATALO, value);
}
void
bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
{
if (on) {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
(mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
return;
}
if (mac->mac_phy.rev >= 2) {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
return;
}
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
}
int
bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
{
struct bwn_phy *phy = &mac->mac_phy;
struct bwn_phy_lp *plp = &phy->phy_lp;
int error;
if (phy->rf_ver == 0x2063) {
error = bwn_phy_lp_b2063_switch_channel(mac, chan);
if (error)
return (error);
} else {
error = bwn_phy_lp_b2062_switch_channel(mac, chan);
if (error)
return (error);
bwn_phy_lp_set_anafilter(mac, chan);
bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
}
plp->plp_chan = chan;
BWN_WRITE_2(mac, BWN_CHANNEL, chan);
return (0);
}
uint32_t
bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
}
void
bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
{
struct bwn_phy *phy = &mac->mac_phy;
struct bwn_phy_lp *plp = &phy->phy_lp;
if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
return;
bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
plp->plp_antenna = antenna;
}
void
bwn_phy_lp_task_60s(struct bwn_mac *mac)
{
bwn_phy_lp_calib(mac);
}
static int
bwn_phy_lp_readsprom(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
#define BWN_PHY_LP_READVAR(_dev, _type, _name, _result) \
do { \
int error; \
\
error = bhnd_nvram_getvar_ ##_type((_dev), (_name), (_result)); \
if (error) { \
device_printf((_dev), "NVRAM variable %s unreadable: " \
"%d\n", (_name), error); \
return (error); \
} \
} while(0)
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI2G,
&plp->plp_txisoband_m);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_BXA2G,
&plp->plp_bxarch);
BWN_PHY_LP_READVAR(sc->sc_dev, int8, BHND_NVAR_RXPO2G,
&plp->plp_rxpwroffset);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMF2G,
&plp->plp_rssivf);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMC2G,
&plp->plp_rssivc);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISAV2G,
&plp->plp_rssigs);
return (0);
}
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5GL,
&plp->plp_txisoband_l);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5G,
&plp->plp_txisoband_m);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_TRI5GH,
&plp->plp_txisoband_h);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_BXA5G,
&plp->plp_bxarch);
BWN_PHY_LP_READVAR(sc->sc_dev, int8, BHND_NVAR_RXPO5G,
&plp->plp_rxpwroffset);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMF5G,
&plp->plp_rssivf);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISMC5G,
&plp->plp_rssivc);
BWN_PHY_LP_READVAR(sc->sc_dev, uint8, BHND_NVAR_RSSISAV5G,
&plp->plp_rssigs);
#undef BWN_PHY_LP_READVAR
return (0);
}
static void
bwn_phy_lp_bbinit(struct bwn_mac *mac)
{
bwn_phy_lp_tblinit(mac);
if (mac->mac_phy.rev >= 2)
bwn_phy_lp_bbinit_r2(mac);
else
bwn_phy_lp_bbinit_r01(mac);
}
static void
bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
{
struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
bwn_phy_lp_set_txgain(mac,
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
bwn_phy_lp_set_bbmult(mac, 150);
}
static void
bwn_phy_lp_calib(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
const struct bwn_rxcompco *rc = NULL;
struct bwn_txgain ogain;
int i, omode, oafeovr, orf, obbmult;
uint8_t mode, fc = 0;
if (plp->plp_chanfullcal != plp->plp_chan) {
plp->plp_chanfullcal = plp->plp_chan;
fc = 1;
}
bwn_mac_suspend(mac);
/* BlueTooth Coexistance Override */
BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
if (mac->mac_phy.rev >= 2)
bwn_phy_lp_digflt_save(mac);
bwn_phy_lp_get_txpctlmode(mac);
mode = plp->plp_txpctlmode;
bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
bwn_phy_lp_bugfix(mac);
if (mac->mac_phy.rev >= 2 && fc == 1) {
bwn_phy_lp_get_txpctlmode(mac);
omode = plp->plp_txpctlmode;
oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
if (oafeovr)
ogain = bwn_phy_lp_get_txgain(mac);
orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
obbmult = bwn_phy_lp_get_bbmult(mac);
bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
if (oafeovr)
bwn_phy_lp_set_txgain(mac, &ogain);
bwn_phy_lp_set_bbmult(mac, obbmult);
bwn_phy_lp_set_txpctlmode(mac, omode);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
}
bwn_phy_lp_set_txpctlmode(mac, mode);
if (mac->mac_phy.rev >= 2)
bwn_phy_lp_digflt_restore(mac);
/* do RX IQ Calculation; assumes that noise is true. */
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) {
for (i = 0; i < N(bwn_rxcompco_5354); i++) {
if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
rc = &bwn_rxcompco_5354[i];
}
} else if (mac->mac_phy.rev >= 2)
rc = &bwn_rxcompco_r2;
else {
for (i = 0; i < N(bwn_rxcompco_r12); i++) {
if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
rc = &bwn_rxcompco_r12[i];
}
}
if (rc == NULL)
goto fail;
BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
} else {
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
}
bwn_phy_lp_set_rxgain(mac, 0x2d5d);
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
bwn_phy_lp_set_deaf(mac, 0);
/* XXX no checking return value? */
(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
bwn_phy_lp_clear_deaf(mac, 0);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
/* disable RX GAIN override. */
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
if (mac->mac_phy.rev >= 2) {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
}
} else {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
}
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
fail:
bwn_mac_enable(mac);
}
void
bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
{
if (on) {
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
return;
}
BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
}
static int
bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
{
static const struct bwn_b206x_chan *bc = NULL;
struct bwn_softc *sc = mac->mac_sc;
uint32_t count, freqref, freqvco, val[3], timeout, timeoutref,
tmp[6];
uint16_t old, scale, tmp16;
u_int freqxtal;
int error, i, div;
for (i = 0; i < N(bwn_b2063_chantable); i++) {
if (bwn_b2063_chantable[i].bc_chan == chan) {
bc = &bwn_b2063_chantable[i];
break;
}
}
if (bc == NULL)
return (EINVAL);
error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
if (error) {
device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
error);
return (error);
}
BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
old = BWN_RF_READ(mac, BWN_B2063_COM15);
BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
freqref = freqxtal * 3;
div = (freqxtal <= 26000000 ? 1 : 2);
timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
999999) / 1000000) + 1;
BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
0xfff8, timeout >> 2);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
0xff9f,timeout << 5);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
(timeoutref + 1)) - 1;
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
0xf0, count >> 8);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
tmp[0] = ((val[2] * 62500) / freqref) << 4;
tmp[1] = ((val[2] * 62500) % freqref) << 4;
while (tmp[1] >= freqref) {
tmp[0]++;
tmp[1] -= freqref;
}
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
if (howmany(tmp[3], tmp[2]) > 60) {
scale = 1;
tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
} else {
scale = 0;
tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
}
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
(scale + 1);
if (tmp[5] > 150)
tmp[5] = 0;
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
if (freqxtal > 26000000)
BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
else
BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
if (val[0] == 45)
BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
else
BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
DELAY(1);
BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
/* VCO Calibration */
BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
DELAY(1);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
DELAY(1);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
DELAY(1);
BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
DELAY(300);
BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
return (0);
}
static int
bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
{
struct bwn_softc *sc = mac->mac_sc;
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
const struct bwn_b206x_chan *bc = NULL;
uint32_t tmp[9];
u_int freqxtal;
int error, i;
for (i = 0; i < N(bwn_b2062_chantable); i++) {
if (bwn_b2062_chantable[i].bc_chan == chan) {
bc = &bwn_b2062_chantable[i];
break;
}
}
if (bc == NULL)
return (EINVAL);
error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
if (error) {
device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
error);
return (error);
}
BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
bwn_phy_lp_b2062_reset_pllbias(mac);
tmp[0] = freqxtal / 1000;
tmp[1] = plp->plp_div * 1000;
tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
if (ieee80211_ieee2mhz(chan, 0) < 4000)
tmp[2] *= 2;
tmp[3] = 48 * tmp[0];
tmp[5] = tmp[2] / tmp[3];
tmp[6] = tmp[2] % tmp[3];
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
tmp[4] = tmp[6] * 0x100;
tmp[5] = tmp[4] / tmp[3];
tmp[6] = tmp[4] % tmp[3];
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
tmp[4] = tmp[6] * 0x100;
tmp[5] = tmp[4] / tmp[3];
tmp[6] = tmp[4] % tmp[3];
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
tmp[4] = tmp[6] * 0x100;
tmp[5] = tmp[4] / tmp[3];
tmp[6] = tmp[4] % tmp[3];
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
tmp[5] + ((2 * tmp[6]) / tmp[3]));
tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
bwn_phy_lp_b2062_vco_calib(mac);
if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
bwn_phy_lp_b2062_reset_pllbias(mac);
bwn_phy_lp_b2062_vco_calib(mac);
if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
return (EIO);
}
}
BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
return (0);
}
static void
bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
uint16_t tmp = (channel == 14);
if (mac->mac_phy.rev < 2) {
BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
bwn_phy_lp_set_rccap(mac);
return;
}
BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
}
static void
bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t iso, tmp[3];
KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
iso = plp->plp_txisoband_m;
else if (freq <= 5320)
iso = plp->plp_txisoband_l;
else if (freq <= 5700)
iso = plp->plp_txisoband_m;
else
iso = plp->plp_txisoband_h;
tmp[0] = ((iso - 26) / 12) << 12;
tmp[1] = tmp[0] + 0x1000;
tmp[2] = tmp[0] + 0x2000;
bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
}
static void
bwn_phy_lp_digflt_save(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
int i;
static const uint16_t addr[] = {
BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
BWN_PHY_OFDM(0xcf),
};
static const uint16_t val[] = {
0xde5e, 0xe832, 0xe331, 0x4d26,
0x0026, 0x1420, 0x0020, 0xfe08,
0x0008,
};
for (i = 0; i < N(addr); i++) {
plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
BWN_PHY_WRITE(mac, addr[i], val[i]);
}
}
static void
bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
uint16_t ctl;
ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
break;
case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
break;
case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
break;
default:
plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
device_printf(sc->sc_dev, "unknown command mode\n");
break;
}
}
static void
bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
uint16_t ctl;
uint8_t old;
bwn_phy_lp_get_txpctlmode(mac);
old = plp->plp_txpctlmode;
if (old == mode)
return;
plp->plp_txpctlmode = mode;
if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
plp->plp_tssiidx);
BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
/* disable TX GAIN override */
if (mac->mac_phy.rev < 2)
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
else {
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
}
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
plp->plp_txpwridx = -1;
}
if (mac->mac_phy.rev >= 2) {
if (mode == BWN_PHYLP_TXPCTL_ON_HW)
BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
else
BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
}
/* writes TX Power Control mode */
switch (plp->plp_txpctlmode) {
case BWN_PHYLP_TXPCTL_OFF:
ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
break;
case BWN_PHYLP_TXPCTL_ON_HW:
ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
break;
case BWN_PHYLP_TXPCTL_ON_SW:
ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
break;
default:
ctl = 0;
KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
}
BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
(uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
}
static void
bwn_phy_lp_bugfix(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
const unsigned int size = 256;
struct bwn_txgain tg;
uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
uint16_t tssinpt, tssiidx, value[2];
uint8_t mode;
int8_t txpwridx;
tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
M_NOWAIT | M_ZERO);
if (tabs == NULL) {
device_printf(sc->sc_dev, "failed to allocate buffer.\n");
return;
}
bwn_phy_lp_get_txpctlmode(mac);
mode = plp->plp_txpctlmode;
txpwridx = plp->plp_txpwridx;
tssinpt = plp->plp_tssinpt;
tssiidx = plp->plp_tssiidx;
bwn_tab_read_multi(mac,
(mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
BWN_TAB_4(7, 0x140), size, tabs);
bwn_phy_lp_tblinit(mac);
bwn_phy_lp_bbinit(mac);
bwn_phy_lp_txpctl_init(mac);
bwn_phy_lp_rf_onoff(mac, 1);
bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
bwn_tab_write_multi(mac,
(mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
BWN_TAB_4(7, 0x140), size, tabs);
BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
plp->plp_tssinpt = tssinpt;
plp->plp_tssiidx = tssiidx;
bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
if (txpwridx != -1) {
/* set TX power by index */
plp->plp_txpwridx = txpwridx;
bwn_phy_lp_get_txpctlmode(mac);
if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
if (mac->mac_phy.rev >= 2) {
rxcomp = bwn_tab_read(mac,
BWN_TAB_4(7, txpwridx + 320));
txgain = bwn_tab_read(mac,
BWN_TAB_4(7, txpwridx + 192));
tg.tg_pad = (txgain >> 16) & 0xff;
tg.tg_gm = txgain & 0xff;
tg.tg_pga = (txgain >> 8) & 0xff;
tg.tg_dac = (rxcomp >> 28) & 0xff;
bwn_phy_lp_set_txgain(mac, &tg);
} else {
rxcomp = bwn_tab_read(mac,
BWN_TAB_4(10, txpwridx + 320));
txgain = bwn_tab_read(mac,
BWN_TAB_4(10, txpwridx + 192));
BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
0xf800, (txgain >> 4) & 0x7fff);
bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
}
bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
/* set TX IQCC */
value[0] = (rxcomp >> 10) & 0x3ff;
value[1] = rxcomp & 0x3ff;
bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
coeff = bwn_tab_read(mac,
(mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
BWN_TAB_4(10, txpwridx + 448));
bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
if (mac->mac_phy.rev >= 2) {
rfpwr = bwn_tab_read(mac,
BWN_TAB_4(7, txpwridx + 576));
BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
rfpwr & 0xffff);
}
bwn_phy_lp_set_txgain_override(mac);
}
if (plp->plp_rccap)
bwn_phy_lp_set_rccap(mac);
bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
bwn_phy_lp_set_txpctlmode(mac, mode);
free(tabs, M_DEVBUF);
}
static void
bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
int i;
static const uint16_t addr[] = {
BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
BWN_PHY_OFDM(0xcf),
};
for (i = 0; i < N(addr); i++)
BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
}
static void
bwn_phy_lp_tblinit(struct bwn_mac *mac)
{
uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
if (mac->mac_phy.rev < 2) {
bwn_phy_lp_tblinit_r01(mac);
bwn_phy_lp_tblinit_txgain(mac);
bwn_phy_lp_set_gaintbl(mac, freq);
return;
}
bwn_phy_lp_tblinit_r2(mac);
bwn_phy_lp_tblinit_txgain(mac);
}
struct bwn_wpair {
uint16_t reg;
uint16_t value;
};
struct bwn_smpair {
uint16_t offset;
uint16_t mask;
uint16_t set;
};
static void
bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_wpair v1[] = {
{ BWN_PHY_AFE_DAC_CTL, 0x50 },
{ BWN_PHY_AFE_CTL, 0x8800 },
{ BWN_PHY_AFE_CTL_OVR, 0 },
{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
{ BWN_PHY_RF_OVERRIDE_0, 0 },
{ BWN_PHY_RF_OVERRIDE_2, 0 },
{ BWN_PHY_OFDM(0xf9), 0 },
{ BWN_PHY_TR_LOOKUP_1, 0 }
};
static const struct bwn_smpair v2[] = {
{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
};
static const struct bwn_smpair v3[] = {
{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
};
int i;
for (i = 0; i < N(v1); i++)
BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
for (i = 0; i < N(v2); i++)
BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
if (sc->sc_board_info.board_rev >= 0x18) {
bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
} else {
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
}
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
sc->sc_cid.chip_pkg == 0) {
BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
} else {
BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
}
for (i = 0; i < N(v3); i++)
BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
sc->sc_cid.chip_pkg == 0) {
bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
}
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
} else
BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
sc->sc_cid.chip_pkg == 0) {
BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
}
bwn_phy_lp_digflt_save(mac);
}
static void
bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_smpair v1[] = {
{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
};
static const struct bwn_smpair v2[] = {
{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
};
static const struct bwn_smpair v3[] = {
{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
};
static const struct bwn_smpair v4[] = {
{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
};
static const struct bwn_smpair v5[] = {
{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
};
int error, i;
uint16_t tmp, tmp2;
BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
for (i = 0; i < N(v1); i++)
BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
0xff00, plp->plp_rxpwroffset);
if ((sc->sc_board_info.board_flags & BHND_BFL_FEM) &&
((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
(sc->sc_board_info.board_flags & BHND_BFL_PAREF))) {
error = bhnd_pmu_set_voltage_raw(sc->sc_pmu,
BHND_REGULATOR_PAREF_LDO, 0x28);
if (error)
device_printf(sc->sc_dev, "failed to set PAREF LDO "
"voltage: %d\n", error);
error = bhnd_pmu_enable_regulator(sc->sc_pmu,
BHND_REGULATOR_PAREF_LDO);
if (error)
device_printf(sc->sc_dev, "failed to enable PAREF LDO "
"regulator: %d\n", error);
if (mac->mac_phy.rev == 0)
BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
0xffcf, 0x0010);
bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
} else {
error = bhnd_pmu_disable_regulator(sc->sc_pmu,
BHND_REGULATOR_PAREF_LDO);
if (error)
device_printf(sc->sc_dev, "failed to disable PAREF LDO "
"regulator: %d\n", error);
BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
}
tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
if (sc->sc_board_info.board_flags & BHND_BFL_RSSIINV)
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
else
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
0xfff9, (plp->plp_bxarch << 1));
if (mac->mac_phy.rev == 1 &&
(sc->sc_board_info.board_flags & BHND_BFL_FEM_BT)) {
for (i = 0; i < N(v2); i++)
BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
v2[i].set);
} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
(sc->sc_board_info.board_type == 0x048a) ||
((mac->mac_phy.rev == 0) &&
(sc->sc_board_info.board_flags & BHND_BFL_FEM))) {
for (i = 0; i < N(v3); i++)
BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
v3[i].set);
} else if (mac->mac_phy.rev == 1 ||
(sc->sc_board_info.board_flags & BHND_BFL_FEM)) {
for (i = 0; i < N(v4); i++)
BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
v4[i].set);
} else {
for (i = 0; i < N(v5); i++)
BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
v5[i].set);
}
if (mac->mac_phy.rev == 1 &&
(sc->sc_board_info.board_flags & BHND_BFL_PAREF)) {
BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
}
if ((sc->sc_board_info.board_flags & BHND_BFL_FEM_BT) &&
(sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) &&
(sc->sc_cid.chip_pkg == BHND_PKGID_BCM4712SMALL)) {
BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
}
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
} else {
BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
}
if (mac->mac_phy.rev == 1) {
tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
tmp2 = (tmp & 0x03e0) >> 5;
tmp2 |= tmp2 << 5;
BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
tmp2 = (tmp & 0x1f00) >> 8;
tmp2 |= tmp2 << 5;
BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
tmp2 = tmp & 0x00ff;
tmp2 |= tmp << 8;
BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
}
}
struct bwn_b2062_freq {
uint16_t freq;
uint8_t value[6];
};
static int
bwn_phy_lp_b2062_init(struct bwn_mac *mac)
{
#define CALC_CTL7(freq, div) \
(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
#define CALC_CTL18(freq, div) \
((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
#define CALC_CTL19(freq, div) \
((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b2062_freq freqdata_tab[] = {
{ 12000, { 6, 6, 6, 6, 10, 6 } },
{ 13000, { 4, 4, 4, 4, 11, 7 } },
{ 14400, { 3, 3, 3, 3, 12, 7 } },
{ 16200, { 3, 3, 3, 3, 13, 8 } },
{ 18000, { 2, 2, 2, 2, 14, 8 } },
{ 19200, { 1, 1, 1, 1, 14, 9 } }
};
static const struct bwn_wpair v1[] = {
{ BWN_B2062_N_TXCTL3, 0 },
{ BWN_B2062_N_TXCTL4, 0 },
{ BWN_B2062_N_TXCTL5, 0 },
{ BWN_B2062_N_TXCTL6, 0 },
{ BWN_B2062_N_PDNCTL0, 0x40 },
{ BWN_B2062_N_PDNCTL0, 0 },
{ BWN_B2062_N_CALIB_TS, 0x10 },
{ BWN_B2062_N_CALIB_TS, 0 }
};
const struct bwn_b2062_freq *f = NULL;
uint32_t ref;
u_int xtalfreq;
unsigned int i;
int error;
error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &xtalfreq);
if (error) {
device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
error);
return (error);
}
bwn_phy_lp_b2062_tblinit(mac);
for (i = 0; i < N(v1); i++)
BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
if (mac->mac_phy.rev > 0)
BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
(BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
else
BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
if (xtalfreq <= 30000000) {
plp->plp_div = 1;
BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
} else {
plp->plp_div = 2;
BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
}
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
CALC_CTL7(xtalfreq, plp->plp_div));
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
CALC_CTL18(xtalfreq, plp->plp_div));
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
CALC_CTL19(xtalfreq, plp->plp_div));
ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
ref &= 0xffff;
for (i = 0; i < N(freqdata_tab); i++) {
if (ref < freqdata_tab[i].freq) {
f = &freqdata_tab[i];
break;
}
}
if (f == NULL)
f = &freqdata_tab[N(freqdata_tab) - 1];
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
((uint16_t)(f->value[1]) << 4) | f->value[0]);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
((uint16_t)(f->value[3]) << 4) | f->value[2]);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
return (0);
#undef CALC_CTL7
#undef CALC_CTL18
#undef CALC_CTL19
}
static int
bwn_phy_lp_b2063_init(struct bwn_mac *mac)
{
bwn_phy_lp_b2063_tblinit(mac);
BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
if (mac->mac_phy.rev == 2) {
BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
} else {
BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
}
return (0);
}
static int
bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
static const struct bwn_wpair v1[] = {
{ BWN_B2063_RX_BB_SP8, 0x0 },
{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
};
static const struct bwn_wpair v2[] = {
{ BWN_B2063_TX_BB_SP3, 0x0 },
{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
};
u_int freqxtal;
int error, i;
uint8_t tmp;
error = bhnd_get_clock_freq(sc->sc_dev, BHND_CLOCK_ALP, &freqxtal);
if (error) {
device_printf(sc->sc_dev, "failed to fetch clock frequency: %d",
error);
return (error);
}
tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
for (i = 0; i < 2; i++)
BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
for (i = 2; i < N(v1); i++)
BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
for (i = 0; i < 10000; i++) {
if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
break;
DELAY(1000);
}
if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
for (i = 0; i < N(v2); i++)
BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
if (freqxtal == 24000000) {
BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
} else {
BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
}
BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
for (i = 0; i < 10000; i++) {
if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
break;
DELAY(1000);
}
if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
return (0);
}
static int
bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct bwn_phy_lp_iq_est ie;
struct bwn_txgain tx_gains;
static const uint32_t pwrtbl[21] = {
0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
0x0004c, 0x0002c, 0x0001a,
};
uint32_t npwr, ipwr, sqpwr, tmp;
int loopback, i, j, sum, error;
uint16_t save[7];
uint8_t txo, bbmult, txpctlmode;
error = bwn_phy_lp_switch_channel(mac, 7);
if (error)
device_printf(sc->sc_dev,
"failed to change channel to 7 (%d)\n", error);
txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
bbmult = bwn_phy_lp_get_bbmult(mac);
if (txo)
tx_gains = bwn_phy_lp_get_txgain(mac);
save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
bwn_phy_lp_get_txpctlmode(mac);
txpctlmode = plp->plp_txpctlmode;
bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
/* disable CRS */
bwn_phy_lp_set_deaf(mac, 1);
bwn_phy_lp_set_trsw_over(mac, 0, 1);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
loopback = bwn_phy_lp_loopback(mac);
if (loopback == -1)
goto done;
bwn_phy_lp_set_rxgain_idx(mac, loopback);
BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
tmp = 0;
memset(&ie, 0, sizeof(ie));
for (i = 128; i <= 159; i++) {
BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
sum = 0;
for (j = 5; j <= 25; j++) {
bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
goto done;
sqpwr = ie.ie_ipwr + ie.ie_qpwr;
ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12);
sum += ((ipwr - npwr) * (ipwr - npwr));
if ((i == 128) || (sum < tmp)) {
plp->plp_rccap = i;
tmp = sum;
}
}
}
bwn_phy_lp_ddfs_turnoff(mac);
done:
/* restore CRS */
bwn_phy_lp_clear_deaf(mac, 1);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
bwn_phy_lp_set_bbmult(mac, bbmult);
if (txo)
bwn_phy_lp_set_txgain(mac, &tx_gains);
bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
if (plp->plp_rccap)
bwn_phy_lp_set_rccap(mac);
return (0);
}
static void
bwn_phy_lp_set_rccap(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
if (mac->mac_phy.rev == 1)
rc_cap = MIN(rc_cap + 5, 15);
BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
MAX(plp->plp_rccap - 4, 0x80));
BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
((plp->plp_rccap & 0x1f) >> 2) | 0x80);
}
static uint32_t
bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
{
uint32_t i, q, r;
if (div == 0)
return (0);
for (i = 0, q = value / div, r = value % div; i < pre; i++) {
q <<= 1;
if (r << 1 >= div) {
q++;
r = (r << 1) - div;
}
}
if (r << 1 >= div)
q++;
return (q);
}
static void
bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
DELAY(20);
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM5354) {
BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
} else {
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
}
DELAY(5);
}
static void
bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
{
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
DELAY(200);
}
static void
bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
{
#define FLAG_A 0x01
#define FLAG_G 0x02
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
};
const struct bwn_b206x_rfinit_entry *br;
unsigned int i;
for (i = 0; i < N(bwn_b2062_init_tab); i++) {
br = &bwn_b2062_init_tab[i];
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
if (br->br_flags & FLAG_G)
BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
} else {
if (br->br_flags & FLAG_A)
BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
}
}
#undef FLAG_A
#undef FLAG_B
}
static void
bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
{
#define FLAG_A 0x01
#define FLAG_G 0x02
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
};
const struct bwn_b206x_rfinit_entry *br;
unsigned int i;
for (i = 0; i < N(bwn_b2063_init_tab); i++) {
br = &bwn_b2063_init_tab[i];
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
if (br->br_flags & FLAG_G)
BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
} else {
if (br->br_flags & FLAG_A)
BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
}
}
#undef FLAG_A
#undef FLAG_B
}
static void
bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
int count, void *_data)
{
unsigned int i;
uint32_t offset, type;
uint8_t *data = _data;
type = BWN_TAB_GETTYPE(typenoffset);
offset = BWN_TAB_GETOFFSET(typenoffset);
KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
for (i = 0; i < count; i++) {
switch (type) {
case BWN_TAB_8BIT:
*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
data++;
break;
case BWN_TAB_16BIT:
*((uint16_t *)data) = BWN_PHY_READ(mac,
BWN_PHY_TABLEDATALO);
data += 2;
break;
case BWN_TAB_32BIT:
*((uint32_t *)data) = BWN_PHY_READ(mac,
BWN_PHY_TABLEDATAHI);
*((uint32_t *)data) <<= 16;
*((uint32_t *)data) |= BWN_PHY_READ(mac,
BWN_PHY_TABLEDATALO);
data += 4;
break;
default:
KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
}
}
}
static void
bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
int count, const void *_data)
{
uint32_t offset, type, value;
const uint8_t *data = _data;
unsigned int i;
type = BWN_TAB_GETTYPE(typenoffset);
offset = BWN_TAB_GETOFFSET(typenoffset);
KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
for (i = 0; i < count; i++) {
switch (type) {
case BWN_TAB_8BIT:
value = *data;
data++;
KASSERT(!(value & ~0xff),
("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
case BWN_TAB_16BIT:
value = *((const uint16_t *)data);
data += 2;
KASSERT(!(value & ~0xffff),
("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
case BWN_TAB_32BIT:
value = *((const uint32_t *)data);
data += 4;
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
default:
KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
}
}
}
static struct bwn_txgain
bwn_phy_lp_get_txgain(struct bwn_mac *mac)
{
struct bwn_txgain tg;
uint16_t tmp;
tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
if (mac->mac_phy.rev < 2) {
tmp = BWN_PHY_READ(mac,
BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
tg.tg_gm = tmp & 0x0007;
tg.tg_pga = (tmp & 0x0078) >> 3;
tg.tg_pad = (tmp & 0x780) >> 7;
return (tg);
}
tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
tg.tg_gm = tmp & 0xff;
tg.tg_pga = (tmp >> 8) & 0xff;
return (tg);
}
static uint8_t
bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
{
return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
}
static void
bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
{
uint16_t pa;
if (mac->mac_phy.rev < 2) {
BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
(tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
bwn_phy_lp_set_txgain_override(mac);
return;
}
pa = bwn_phy_lp_get_pa_gain(mac);
BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
(tg->tg_pga << 8) | tg->tg_gm);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
tg->tg_pad | (pa << 6));
BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
tg->tg_pad | (pa << 8));
bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
bwn_phy_lp_set_txgain_override(mac);
}
static void
bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
{
bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
}
static void
bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
{
uint16_t trsw = (tx << 1) | rx;
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
}
static void
bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
{
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
if (mac->mac_phy.rev < 2) {
trsw = gain & 0x1;
lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
ext_lna = (gain & 2) >> 1;
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
0xfbff, ext_lna << 10);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
0xf7ff, ext_lna << 11);
BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
} else {
low_gain = gain & 0xffff;
high_gain = (gain >> 16) & 0xf;
ext_lna = (gain >> 21) & 0x1;
trsw = ~(gain >> 20) & 0x1;
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
0xfdff, ext_lna << 9);
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
0xfbff, ext_lna << 10);
BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
tmp = (gain >> 2) & 0x3;
BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
0xe7ff, tmp<<11);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
tmp << 3);
}
}
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
if (mac->mac_phy.rev >= 2) {
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
}
return;
}
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
}
static void
bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
if (user)
plp->plp_crsusr_off = 1;
else
plp->plp_crssys_off = 1;
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
}
static void
bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
if (user)
plp->plp_crsusr_off = 0;
else
plp->plp_crssys_off = 0;
if (plp->plp_crsusr_off || plp->plp_crssys_off)
return;
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
else
BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
}
static int
bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
{
#define CALC_COEFF(_v, _x, _y, _z) do { \
int _t; \
_t = _x - 20; \
if (_t >= 0) { \
_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
} else { \
_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
} \
} while (0)
#define CALC_COEFF2(_v, _x, _y, _z) do { \
int _t; \
_t = _x - 11; \
if (_t >= 0) \
_v = (_y << (31 - _x)) / (_z >> _t); \
else \
_v = (_y << (31 - _x)) / (_z << -_t); \
} while (0)
struct bwn_phy_lp_iq_est ie;
uint16_t v0, v1;
int tmp[2], ret;
v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
v0 = v1 >> 8;
v1 |= 0xff;
BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
if (ret == 0)
goto done;
if (ie.ie_ipwr + ie.ie_qpwr < 2) {
ret = 0;
goto done;
}
CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
v0 = tmp[0] >> 3;
v1 = tmp[1] >> 4;
done:
BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
return ret;
#undef CALC_COEFF
#undef CALC_COEFF2
}
static void
bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
{
static const uint16_t noisescale[] = {
0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
};
static const uint16_t crsgainnft[] = {
0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
0x013d,
};
static const uint16_t filterctl[] = {
0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
0xff53, 0x0127,
};
static const uint32_t psctl[] = {
0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
};
static const uint16_t ofdmcckgain_r0[] = {
0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
0x755d,
};
static const uint16_t ofdmcckgain_r1[] = {
0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
0x755d,
};
static const uint16_t gaindelta[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000,
};
static const uint32_t txpwrctl[] = {
0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
0x00000702,
};
KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
bwn_tab_sigsq_tbl);
bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
bwn_tab_pllfrac_tbl);
bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
bwn_tabl_iqlocal_tbl);
if (mac->mac_phy.rev == 0) {
bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
ofdmcckgain_r0);
bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
ofdmcckgain_r0);
} else {
bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
ofdmcckgain_r1);
bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
ofdmcckgain_r1);
}
bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
}
static void
bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
int i;
static const uint16_t noisescale[] = {
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
};
static const uint32_t filterctl[] = {
0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
};
static const uint32_t psctl[] = {
0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
};
static const uint32_t gainidx[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
0x0000001a, 0x64ca55ad, 0x0000001a
};
static const uint16_t auxgainidx[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
0x0004, 0x0016
};
static const uint16_t swctl[] = {
0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
};
static const uint8_t hf[] = {
0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
};
static const uint32_t gainval[] = {
0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
0x000000f1, 0x00000000, 0x00000000
};
static const uint16_t gain[] = {
0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
static const uint32_t papdeps[] = {
0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
};
static const uint32_t papdmult[] = {
0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
};
static const uint32_t gainidx_a0[] = {
0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
};
static const uint16_t auxgainidx_a0[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0002, 0x0014
};
static const uint32_t gainval_a0[] = {
0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
0x000000f7, 0x00000000, 0x00000000
};
static const uint16_t gain_a0[] = {
0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
for (i = 0; i < 704; i++)
bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
bwn_tab_sigsq_tbl);
bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
bwn_tab_pllfrac_tbl);
bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
bwn_tabl_iqlocal_tbl);
bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
if (sc->sc_cid.chip_id == BHND_CHIPID_BCM4325 &&
sc->sc_cid.chip_pkg == 0) {
bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
gainidx_a0);
bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
auxgainidx_a0);
bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
gainval_a0);
bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
}
}
static void
bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
static struct bwn_txgain_entry txgain_r2[] = {
{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
};
static struct bwn_txgain_entry txgain_2ghz_r2[] = {
{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
};
static struct bwn_txgain_entry txgain_5ghz_r2[] = {
{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
};
static struct bwn_txgain_entry txgain_r0[] = {
{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
};
static struct bwn_txgain_entry txgain_2ghz_r0[] = {
{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
};
static struct bwn_txgain_entry txgain_5ghz_r0[] = {
{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
};
static struct bwn_txgain_entry txgain_r1[] = {
{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
{ 7, 11, 6, 0, 71 }
};
static struct bwn_txgain_entry txgain_2ghz_r1[] = {
{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
};
static struct bwn_txgain_entry txgain_5ghz_r1[] = {
{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
};
if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
if (sc->sc_board_info.board_flags & BHND_BFL_NOPA)
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
txgain_2ghz_r2);
else
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
txgain_5ghz_r2);
return;
}
if (mac->mac_phy.rev == 0) {
if ((sc->sc_board_info.board_flags & BHND_BFL_NOPA) ||
(sc->sc_board_info.board_flags & BHND_BFL_HGPA))
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
txgain_2ghz_r0);
else
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
txgain_5ghz_r0);
return;
}
if ((sc->sc_board_info.board_flags & BHND_BFL_NOPA) ||
(sc->sc_board_info.board_flags & BHND_BFL_HGPA))
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
else
bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
}
static void
bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
{
uint32_t offset, type;
type = BWN_TAB_GETTYPE(typeoffset);
offset = BWN_TAB_GETOFFSET(typeoffset);
KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
switch (type) {
case BWN_TAB_8BIT:
KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
case BWN_TAB_16BIT:
KASSERT(!(value & ~0xffff),
("%s:%d: fail", __func__, __LINE__));
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
case BWN_TAB_32BIT:
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
break;
default:
KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
}
}
static int
bwn_phy_lp_loopback(struct bwn_mac *mac)
{
struct bwn_phy_lp_iq_est ie;
int i, index = -1;
uint32_t tmp;
memset(&ie, 0, sizeof(ie));
bwn_phy_lp_set_trsw_over(mac, 1, 1);
BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
for (i = 0; i < 32; i++) {
bwn_phy_lp_set_rxgain_idx(mac, i);
bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
continue;
tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
if ((tmp > 4000) && (tmp < 10000)) {
index = i;
break;
}
}
bwn_phy_lp_ddfs_turnoff(mac);
return (index);
}
static void
bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
{
bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
}
static void
bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
int incr1, int incr2, int scale_idx)
{
bwn_phy_lp_ddfs_turnoff(mac);
BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
}
static uint8_t
bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
struct bwn_phy_lp_iq_est *ie)
{
int i;
BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
for (i = 0; i < 500; i++) {
if (!(BWN_PHY_READ(mac,
BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
break;
DELAY(1000);
}
if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
return 0;
}
ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
ie->ie_iqprod <<= 16;
ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
ie->ie_ipwr <<= 16;
ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
ie->ie_qpwr <<= 16;
ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
return 1;
}
static uint32_t
bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
{
uint32_t offset, type, value;
type = BWN_TAB_GETTYPE(typeoffset);
offset = BWN_TAB_GETOFFSET(typeoffset);
KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
switch (type) {
case BWN_TAB_8BIT:
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
break;
case BWN_TAB_16BIT:
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
break;
case BWN_TAB_32BIT:
BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
value <<= 16;
value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
break;
default:
KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
value = 0;
}
return (value);
}
static void
bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
{
BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
}
static void
bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
{
uint16_t ctl;
ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
ctl |= dac << 7;
BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
}
static void
bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
{
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
}
static void
bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
{
if (mac->mac_phy.rev < 2)
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
else {
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
}
BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
}
static uint16_t
bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
{
return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
}
static uint8_t
bwn_nbits(int32_t val)
{
uint32_t tmp;
uint8_t nbits = 0;
for (tmp = abs(val); tmp != 0; tmp >>= 1)
nbits++;
return (nbits);
}
static void
bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
struct bwn_txgain_entry *table)
{
int i;
for (i = offset; i < count; i++)
bwn_phy_lp_gaintbl_write(mac, i, table[i]);
}
static void
bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
struct bwn_txgain_entry data)
{
if (mac->mac_phy.rev >= 2)
bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
else
bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
}
static void
bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
struct bwn_txgain_entry te)
{
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
if (mac->mac_phy.rev >= 3) {
tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
(0x10 << 24) : (0x70 << 24));
} else {
tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
(0x14 << 24) : (0x7f << 24));
}
bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
te.te_bbmult << 20 | te.te_dac << 28);
}
static void
bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
struct bwn_txgain_entry te)
{
KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
(te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm << 4) |
te.te_dac);
bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
}