18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci Broadcom B43 wireless driver 58c2ecf20Sopenharmony_ci IEEE 802.11n HT-PHY support 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci*/ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "b43.h" 158c2ecf20Sopenharmony_ci#include "phy_ht.h" 168c2ecf20Sopenharmony_ci#include "tables_phy_ht.h" 178c2ecf20Sopenharmony_ci#include "radio_2059.h" 188c2ecf20Sopenharmony_ci#include "main.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* Force values to keep compatibility with wl */ 218c2ecf20Sopenharmony_cienum ht_rssi_type { 228c2ecf20Sopenharmony_ci HT_RSSI_W1 = 0, 238c2ecf20Sopenharmony_ci HT_RSSI_W2 = 1, 248c2ecf20Sopenharmony_ci HT_RSSI_NB = 2, 258c2ecf20Sopenharmony_ci HT_RSSI_IQ = 3, 268c2ecf20Sopenharmony_ci HT_RSSI_TSSI_2G = 4, 278c2ecf20Sopenharmony_ci HT_RSSI_TSSI_5G = 5, 288c2ecf20Sopenharmony_ci HT_RSSI_TBD = 6, 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/************************************************** 328c2ecf20Sopenharmony_ci * Radio 2059. 338c2ecf20Sopenharmony_ci **************************************************/ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic void b43_radio_2059_channel_setup(struct b43_wldev *dev, 368c2ecf20Sopenharmony_ci const struct b43_phy_ht_channeltab_e_radio2059 *e) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, }; 398c2ecf20Sopenharmony_ci u16 r; 408c2ecf20Sopenharmony_ci int core; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x16, e->radio_syn16); 438c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x17, e->radio_syn17); 448c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x22, e->radio_syn22); 458c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x25, e->radio_syn25); 468c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x27, e->radio_syn27); 478c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x28, e->radio_syn28); 488c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x29, e->radio_syn29); 498c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2c, e->radio_syn2c); 508c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x2d, e->radio_syn2d); 518c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x37, e->radio_syn37); 528c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x41, e->radio_syn41); 538c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x43, e->radio_syn43); 548c2ecf20Sopenharmony_ci b43_radio_write(dev, 0x47, e->radio_syn47); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci for (core = 0; core < 3; core++) { 578c2ecf20Sopenharmony_ci r = routing[core]; 588c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a); 598c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x58, e->radio_rxtx58); 608c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a); 618c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a); 628c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d); 638c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e); 648c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x92, e->radio_rxtx92); 658c2ecf20Sopenharmony_ci b43_radio_write(dev, r | 0x98, e->radio_rxtx98); 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci udelay(50); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Calibration */ 718c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_RFPLL_MISC_EN, ~0x1); 728c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x4); 738c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x4); 748c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_RFPLL_MISC_EN, 0x1); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci udelay(300); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* Calibrate resistors in LPF of PLL? */ 808c2ecf20Sopenharmony_cistatic void b43_radio_2059_rcal(struct b43_wldev *dev) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci /* Enable */ 838c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x1); 848c2ecf20Sopenharmony_ci usleep_range(10, 20); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1); 878c2ecf20Sopenharmony_ci b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Start */ 908c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x2); 918c2ecf20Sopenharmony_ci usleep_range(100, 200); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Stop */ 948c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x2); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2059_C3 | R2059_RCAL_STATUS, 1, 1, 100, 978c2ecf20Sopenharmony_ci 1000000)) 988c2ecf20Sopenharmony_ci b43err(dev->wl, "Radio 0x2059 rcal timeout\n"); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* Disable */ 1018c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x1); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci b43_radio_set(dev, 0xa, 0x60); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* Calibrate the internal RC oscillator? */ 1078c2ecf20Sopenharmony_cistatic void b43_radio_2057_rccal(struct b43_wldev *dev) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci static const u16 radio_values[3][2] = { 1108c2ecf20Sopenharmony_ci { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 }, 1118c2ecf20Sopenharmony_ci }; 1128c2ecf20Sopenharmony_ci int i; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 1158c2ecf20Sopenharmony_ci b43_radio_write(dev, R2059_RCCAL_MASTER, radio_values[i][0]); 1168c2ecf20Sopenharmony_ci b43_radio_write(dev, R2059_RCCAL_X1, 0x6E); 1178c2ecf20Sopenharmony_ci b43_radio_write(dev, R2059_RCCAL_TRC0, radio_values[i][1]); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* Start */ 1208c2ecf20Sopenharmony_ci b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x55); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* Wait */ 1238c2ecf20Sopenharmony_ci if (!b43_radio_wait_value(dev, R2059_RCCAL_DONE_OSCCAP, 2, 2, 1248c2ecf20Sopenharmony_ci 500, 5000000)) 1258c2ecf20Sopenharmony_ci b43err(dev->wl, "Radio 0x2059 rccal timeout\n"); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Stop */ 1288c2ecf20Sopenharmony_ci b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x15); 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_RCCAL_MASTER, ~0x1); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic void b43_radio_2059_init_pre(struct b43_wldev *dev) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 1378c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_FORCE); 1388c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_FORCE); 1398c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void b43_radio_2059_init(struct b43_wldev *dev) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 }; 1458c2ecf20Sopenharmony_ci int i; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* Prepare (reset?) radio */ 1488c2ecf20Sopenharmony_ci b43_radio_2059_init_pre(dev); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci r2059_upload_inittabs(dev); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(routing); i++) 1538c2ecf20Sopenharmony_ci b43_radio_set(dev, routing[i] | 0x146, 0x3); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* Post init starts below */ 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x0078); 1588c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_XTAL_CONFIG2, 0x0080); 1598c2ecf20Sopenharmony_ci msleep(2); 1608c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x0078); 1618c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_XTAL_CONFIG2, ~0x0080); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (1) { /* FIXME */ 1648c2ecf20Sopenharmony_ci b43_radio_2059_rcal(dev); 1658c2ecf20Sopenharmony_ci b43_radio_2057_rccal(dev); 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci b43_radio_mask(dev, R2059_RFPLL_MASTER, ~0x0008); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/************************************************** 1728c2ecf20Sopenharmony_ci * RF 1738c2ecf20Sopenharmony_ci **************************************************/ 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci u8 i; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); 1808c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); 1838c2ecf20Sopenharmony_ci for (i = 0; i < 200; i++) { 1848c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { 1858c2ecf20Sopenharmony_ci i = 0; 1868c2ecf20Sopenharmony_ci break; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci msleep(1); 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci if (i) 1918c2ecf20Sopenharmony_ci b43err(dev->wl, "Forcing RF sequence timeout\n"); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_cistatic void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct b43_phy_ht *htphy = dev->phy.ht; 1998c2ecf20Sopenharmony_ci static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1, 2008c2ecf20Sopenharmony_ci B43_PHY_HT_RF_CTL_INT_C2, 2018c2ecf20Sopenharmony_ci B43_PHY_HT_RF_CTL_INT_C3 }; 2028c2ecf20Sopenharmony_ci int i; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (enable) { 2058c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 2068c2ecf20Sopenharmony_ci b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]); 2078c2ecf20Sopenharmony_ci } else { 2088c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 2098c2ecf20Sopenharmony_ci htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]); 2108c2ecf20Sopenharmony_ci /* TODO: Does 5GHz band use different value (not 0x0400)? */ 2118c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 2128c2ecf20Sopenharmony_ci b43_phy_write(dev, regs[i], 0x0400); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/************************************************** 2178c2ecf20Sopenharmony_ci * Various PHY ops 2188c2ecf20Sopenharmony_ci **************************************************/ 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci u16 tmp; 2238c2ecf20Sopenharmony_ci u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN | 2248c2ecf20Sopenharmony_ci B43_PHY_HT_CLASS_CTL_OFDM_EN | 2258c2ecf20Sopenharmony_ci B43_PHY_HT_CLASS_CTL_WAITED_EN; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL); 2288c2ecf20Sopenharmony_ci tmp &= allowed; 2298c2ecf20Sopenharmony_ci tmp &= ~mask; 2308c2ecf20Sopenharmony_ci tmp |= (val & mask); 2318c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return tmp; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_cistatic void b43_phy_ht_reset_cca(struct b43_wldev *dev) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci u16 bbcfg; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, true); 2418c2ecf20Sopenharmony_ci bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG); 2428c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA); 2438c2ecf20Sopenharmony_ci udelay(1); 2448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA); 2458c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, false); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic void b43_phy_ht_zero_extg(struct b43_wldev *dev) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci u8 i, j; 2538c2ecf20Sopenharmony_ci static const u16 base[] = { 0x40, 0x60, 0x80 }; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(base); i++) { 2568c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) 2578c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(base); i++) 2618c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* Some unknown AFE (Analog Frondned) op */ 2658c2ecf20Sopenharmony_cistatic void b43_phy_ht_afe_unk1(struct b43_wldev *dev) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci u8 i; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci static const u16 ctl_regs[3][2] = { 2708c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 }, 2718c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 }, 2728c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3}, 2738c2ecf20Sopenharmony_ci }; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 2768c2ecf20Sopenharmony_ci /* TODO: verify masks&sets */ 2778c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[i][1], 0x4); 2788c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[i][0], 0x4); 2798c2ecf20Sopenharmony_ci b43_phy_mask(dev, ctl_regs[i][1], ~0x1); 2808c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[i][0], 0x1); 2818c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); 2828c2ecf20Sopenharmony_ci b43_phy_mask(dev, ctl_regs[i][0], ~0x4); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); 2898c2ecf20Sopenharmony_ci clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); 2908c2ecf20Sopenharmony_ci clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic void b43_phy_ht_bphy_init(struct b43_wldev *dev) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci unsigned int i; 2968c2ecf20Sopenharmony_ci u16 val; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci val = 0x1E1F; 2998c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 3008c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 3018c2ecf20Sopenharmony_ci val -= 0x202; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci val = 0x3E3F; 3048c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 3058c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); 3068c2ecf20Sopenharmony_ci val -= 0x202; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic void b43_phy_ht_bphy_reset(struct b43_wldev *dev, bool reset) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci u16 tmp; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci tmp = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 3168c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, 3178c2ecf20Sopenharmony_ci tmp | B43_PSM_HDR_MAC_PHY_FORCE_CLK); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci /* Put BPHY in or take it out of the reset */ 3208c2ecf20Sopenharmony_ci if (reset) 3218c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_B_BBCFG, 3228c2ecf20Sopenharmony_ci B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX); 3238c2ecf20Sopenharmony_ci else 3248c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_B_BBCFG, 3258c2ecf20Sopenharmony_ci (u16)~(B43_PHY_B_BBCFG_RSTCCA | 3268c2ecf20Sopenharmony_ci B43_PHY_B_BBCFG_RSTRX)); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/************************************************** 3328c2ecf20Sopenharmony_ci * Samples 3338c2ecf20Sopenharmony_ci **************************************************/ 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void b43_phy_ht_stop_playback(struct b43_wldev *dev) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 3388c2ecf20Sopenharmony_ci u16 tmp; 3398c2ecf20Sopenharmony_ci int i; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT); 3428c2ecf20Sopenharmony_ci if (tmp & 0x1) 3438c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP); 3448c2ecf20Sopenharmony_ci else if (tmp & 0x2) 3458c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 3508c2ecf20Sopenharmony_ci if (phy_ht->bb_mult_save[i] >= 0) { 3518c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4), 3528c2ecf20Sopenharmony_ci phy_ht->bb_mult_save[i]); 3538c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4), 3548c2ecf20Sopenharmony_ci phy_ht->bb_mult_save[i]); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic u16 b43_phy_ht_load_samples(struct b43_wldev *dev) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci int i; 3628c2ecf20Sopenharmony_ci u16 len = 20 << 3; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 3678c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0); 3688c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci return len; 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, 3758c2ecf20Sopenharmony_ci u16 wait) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 3788c2ecf20Sopenharmony_ci u16 save_seq_mode; 3798c2ecf20Sopenharmony_ci int i; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 3828c2ecf20Sopenharmony_ci if (phy_ht->bb_mult_save[i] < 0) 3838c2ecf20Sopenharmony_ci phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4)); 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1); 3878c2ecf20Sopenharmony_ci if (loops != 0xFFFF) 3888c2ecf20Sopenharmony_ci loops--; 3898c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops); 3908c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); 3938c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 3948c2ecf20Sopenharmony_ci B43_PHY_HT_RF_SEQ_MODE_CA_OVER); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* TODO: find out mask bits! Do we need more function arguments? */ 3978c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); 3988c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); 3998c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0); 4008c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci for (i = 0; i < 100; i++) { 4038c2ecf20Sopenharmony_ci if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) { 4048c2ecf20Sopenharmony_ci i = 0; 4058c2ecf20Sopenharmony_ci break; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci udelay(10); 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci if (i) 4108c2ecf20Sopenharmony_ci b43err(dev->wl, "run samples timeout\n"); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic void b43_phy_ht_tx_tone(struct b43_wldev *dev) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci u16 samp; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci samp = b43_phy_ht_load_samples(dev); 4208c2ecf20Sopenharmony_ci b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0); 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci/************************************************** 4248c2ecf20Sopenharmony_ci * RSSI 4258c2ecf20Sopenharmony_ci **************************************************/ 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel, 4288c2ecf20Sopenharmony_ci enum ht_rssi_type rssi_type) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci static const u16 ctl_regs[3][2] = { 4318c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, }, 4328c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, }, 4338c2ecf20Sopenharmony_ci { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, }, 4348c2ecf20Sopenharmony_ci }; 4358c2ecf20Sopenharmony_ci static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, }; 4368c2ecf20Sopenharmony_ci int core; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (core_sel == 0) { 4398c2ecf20Sopenharmony_ci b43err(dev->wl, "RSSI selection for core off not implemented yet\n"); 4408c2ecf20Sopenharmony_ci } else { 4418c2ecf20Sopenharmony_ci for (core = 0; core < 3; core++) { 4428c2ecf20Sopenharmony_ci /* Check if caller requested a one specific core */ 4438c2ecf20Sopenharmony_ci if ((core_sel == 1 && core != 0) || 4448c2ecf20Sopenharmony_ci (core_sel == 2 && core != 1) || 4458c2ecf20Sopenharmony_ci (core_sel == 3 && core != 2)) 4468c2ecf20Sopenharmony_ci continue; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci switch (rssi_type) { 4498c2ecf20Sopenharmony_ci case HT_RSSI_TSSI_2G: 4508c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8); 4518c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10); 4528c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9); 4538c2ecf20Sopenharmony_ci b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci b43_radio_set(dev, R2059_C3 | 0xbf, 0x1); 4568c2ecf20Sopenharmony_ci b43_radio_write(dev, radio_r[core] | 0x159, 4578c2ecf20Sopenharmony_ci 0x11); 4588c2ecf20Sopenharmony_ci break; 4598c2ecf20Sopenharmony_ci default: 4608c2ecf20Sopenharmony_ci b43err(dev->wl, "RSSI selection for type %d not implemented yet\n", 4618c2ecf20Sopenharmony_ci rssi_type); 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type, 4688c2ecf20Sopenharmony_ci s32 *buf, u8 nsamp) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci u16 phy_regs_values[12]; 4718c2ecf20Sopenharmony_ci static const u16 phy_regs_to_save[] = { 4728c2ecf20Sopenharmony_ci B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, 4738c2ecf20Sopenharmony_ci 0x848, 0x841, 4748c2ecf20Sopenharmony_ci B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, 4758c2ecf20Sopenharmony_ci 0x868, 0x861, 4768c2ecf20Sopenharmony_ci B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, 4778c2ecf20Sopenharmony_ci 0x888, 0x881, 4788c2ecf20Sopenharmony_ci }; 4798c2ecf20Sopenharmony_ci u16 tmp[3]; 4808c2ecf20Sopenharmony_ci int i; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci for (i = 0; i < 12; i++) 4838c2ecf20Sopenharmony_ci phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci b43_phy_ht_rssi_select(dev, 5, type); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) 4888c2ecf20Sopenharmony_ci buf[i] = 0; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci for (i = 0; i < nsamp; i++) { 4918c2ecf20Sopenharmony_ci tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1); 4928c2ecf20Sopenharmony_ci tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2); 4938c2ecf20Sopenharmony_ci tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2; 4968c2ecf20Sopenharmony_ci buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2; 4978c2ecf20Sopenharmony_ci buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2; 4988c2ecf20Sopenharmony_ci buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2; 4998c2ecf20Sopenharmony_ci buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2; 5008c2ecf20Sopenharmony_ci buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci for (i = 0; i < 12; i++) 5048c2ecf20Sopenharmony_ci b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]); 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/************************************************** 5088c2ecf20Sopenharmony_ci * Tx/Rx 5098c2ecf20Sopenharmony_ci **************************************************/ 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_cistatic void b43_phy_ht_tx_power_fix(struct b43_wldev *dev) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci int i; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) { 5168c2ecf20Sopenharmony_ci u16 mask; 5178c2ecf20Sopenharmony_ci u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (0) /* FIXME */ 5208c2ecf20Sopenharmony_ci mask = 0x2 << (i * 4); 5218c2ecf20Sopenharmony_ci else 5228c2ecf20Sopenharmony_ci mask = 0; 5238c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); 5268c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), 5278c2ecf20Sopenharmony_ci tmp & 0xFF); 5288c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), 5298c2ecf20Sopenharmony_ci tmp & 0xFF); 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cistatic void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 5368c2ecf20Sopenharmony_ci u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | 5378c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | 5388c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; 5398c2ecf20Sopenharmony_ci static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, 5408c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_CMD_C2, 5418c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_CMD_C3 }; 5428c2ecf20Sopenharmony_ci static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1, 5438c2ecf20Sopenharmony_ci B43_PHY_HT_TX_PCTL_STATUS_C2, 5448c2ecf20Sopenharmony_ci B43_PHY_HT_TX_PCTL_STATUS_C3 }; 5458c2ecf20Sopenharmony_ci int i; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (!enable) { 5488c2ecf20Sopenharmony_ci if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { 5498c2ecf20Sopenharmony_ci /* We disable enabled TX pwr ctl, save it's state */ 5508c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 5518c2ecf20Sopenharmony_ci phy_ht->tx_pwr_idx[i] = 5528c2ecf20Sopenharmony_ci b43_phy_read(dev, status_regs[i]); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); 5558c2ecf20Sopenharmony_ci } else { 5568c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 5598c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 5608c2ecf20Sopenharmony_ci b43_phy_write(dev, cmd_regs[i], 0x32); 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 5648c2ecf20Sopenharmony_ci if (phy_ht->tx_pwr_idx[i] <= 5658c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_CMD_C1_INIT) 5668c2ecf20Sopenharmony_ci b43_phy_write(dev, cmd_regs[i], 5678c2ecf20Sopenharmony_ci phy_ht->tx_pwr_idx[i]); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci phy_ht->tx_pwr_ctl = enable; 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_cistatic void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 5768c2ecf20Sopenharmony_ci static const u16 base[] = { 0x840, 0x860, 0x880 }; 5778c2ecf20Sopenharmony_ci u16 save_regs[3][3]; 5788c2ecf20Sopenharmony_ci s32 rssi_buf[6]; 5798c2ecf20Sopenharmony_ci int core; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci for (core = 0; core < 3; core++) { 5828c2ecf20Sopenharmony_ci save_regs[core][1] = b43_phy_read(dev, base[core] + 6); 5838c2ecf20Sopenharmony_ci save_regs[core][2] = b43_phy_read(dev, base[core] + 7); 5848c2ecf20Sopenharmony_ci save_regs[core][0] = b43_phy_read(dev, base[core] + 0); 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci b43_phy_write(dev, base[core] + 6, 0); 5878c2ecf20Sopenharmony_ci b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */ 5888c2ecf20Sopenharmony_ci b43_phy_set(dev, base[core] + 0, 0x0400); 5898c2ecf20Sopenharmony_ci b43_phy_set(dev, base[core] + 0, 0x1000); 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci b43_phy_ht_tx_tone(dev); 5938c2ecf20Sopenharmony_ci udelay(20); 5948c2ecf20Sopenharmony_ci b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1); 5958c2ecf20Sopenharmony_ci b43_phy_ht_stop_playback(dev); 5968c2ecf20Sopenharmony_ci b43_phy_ht_reset_cca(dev); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff; 5998c2ecf20Sopenharmony_ci phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff; 6008c2ecf20Sopenharmony_ci phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci for (core = 0; core < 3; core++) { 6038c2ecf20Sopenharmony_ci b43_phy_write(dev, base[core] + 0, save_regs[core][0]); 6048c2ecf20Sopenharmony_ci b43_phy_write(dev, base[core] + 6, save_regs[core][1]); 6058c2ecf20Sopenharmony_ci b43_phy_write(dev, base[core] + 7, save_regs[core][2]); 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistatic void b43_phy_ht_tssi_setup(struct b43_wldev *dev) 6108c2ecf20Sopenharmony_ci{ 6118c2ecf20Sopenharmony_ci static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, }; 6128c2ecf20Sopenharmony_ci int core; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci /* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */ 6158c2ecf20Sopenharmony_ci for (core = 0; core < 3; core++) { 6168c2ecf20Sopenharmony_ci b43_radio_set(dev, 0x8bf, 0x1); 6178c2ecf20Sopenharmony_ci b43_radio_write(dev, routing[core] | 0x0159, 0x0011); 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 6248c2ecf20Sopenharmony_ci struct ssb_sprom *sprom = dev->dev->bus_sprom; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci u8 *idle = phy_ht->idle_tssi; 6278c2ecf20Sopenharmony_ci u8 target[3]; 6288c2ecf20Sopenharmony_ci s16 a1[3], b0[3], b1[3]; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci u16 freq = dev->phy.chandef->chan->center_freq; 6318c2ecf20Sopenharmony_ci int i, c; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 6348c2ecf20Sopenharmony_ci for (c = 0; c < 3; c++) { 6358c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_2g; 6368c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_2g[0]; 6378c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_2g[1]; 6388c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_2g[2]; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci } else if (freq >= 4900 && freq < 5100) { 6418c2ecf20Sopenharmony_ci for (c = 0; c < 3; c++) { 6428c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5gl; 6438c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; 6448c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; 6458c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; 6468c2ecf20Sopenharmony_ci } 6478c2ecf20Sopenharmony_ci } else if (freq >= 5100 && freq < 5500) { 6488c2ecf20Sopenharmony_ci for (c = 0; c < 3; c++) { 6498c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5g; 6508c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5g[0]; 6518c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5g[1]; 6528c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5g[2]; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci } else if (freq >= 5500) { 6558c2ecf20Sopenharmony_ci for (c = 0; c < 3; c++) { 6568c2ecf20Sopenharmony_ci target[c] = sprom->core_pwr_info[c].maxpwr_5gh; 6578c2ecf20Sopenharmony_ci a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; 6588c2ecf20Sopenharmony_ci b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; 6598c2ecf20Sopenharmony_ci b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci } else { 6628c2ecf20Sopenharmony_ci target[0] = target[1] = target[2] = 52; 6638c2ecf20Sopenharmony_ci a1[0] = a1[1] = a1[2] = -424; 6648c2ecf20Sopenharmony_ci b0[0] = b0[1] = b0[2] = 5612; 6658c2ecf20Sopenharmony_ci b1[0] = b1[1] = b1[2] = -1393; 6668c2ecf20Sopenharmony_ci } 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN); 6698c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, 6708c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */ 6738c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 6768c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19); 6778c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2, 6788c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19); 6798c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3, 6808c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 6838c2ecf20Sopenharmony_ci B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 6868c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1, 6878c2ecf20Sopenharmony_ci idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT); 6888c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 6898c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2, 6908c2ecf20Sopenharmony_ci idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT); 6918c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2, 6928c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3, 6938c2ecf20Sopenharmony_ci idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT); 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID, 6968c2ecf20Sopenharmony_ci 0xf0); 6978c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2, 6988c2ecf20Sopenharmony_ci 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT); 6998c2ecf20Sopenharmony_ci#if 0 7008c2ecf20Sopenharmony_ci /* TODO: what to mask/set? */ 7018c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0) 7028c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0) 7038c2ecf20Sopenharmony_ci#endif 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, 7068c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_TARG_PWR_C1, 7078c2ecf20Sopenharmony_ci target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT); 7088c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, 7098c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF, 7108c2ecf20Sopenharmony_ci target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT); 7118c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2, 7128c2ecf20Sopenharmony_ci ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3, 7138c2ecf20Sopenharmony_ci target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci for (c = 0; c < 3; c++) { 7168c2ecf20Sopenharmony_ci s32 num, den, pwr; 7178c2ecf20Sopenharmony_ci u32 regval[64]; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 7208c2ecf20Sopenharmony_ci num = 8 * (16 * b0[c] + b1[c] * i); 7218c2ecf20Sopenharmony_ci den = 32768 + a1[c] * i; 7228c2ecf20Sopenharmony_ci pwr = max((4 * num + den / 2) / den, -8); 7238c2ecf20Sopenharmony_ci regval[i] = pwr; 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval); 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci/************************************************** 7308c2ecf20Sopenharmony_ci * Channel switching ops. 7318c2ecf20Sopenharmony_ci **************************************************/ 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic void b43_phy_ht_spur_avoid(struct b43_wldev *dev, 7348c2ecf20Sopenharmony_ci struct ieee80211_channel *new_channel) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci struct bcma_device *core = dev->dev->bdev; 7378c2ecf20Sopenharmony_ci int spuravoid = 0; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* Check for 13 and 14 is just a guess, we don't have enough logs. */ 7408c2ecf20Sopenharmony_ci if (new_channel->hw_value == 13 || new_channel->hw_value == 14) 7418c2ecf20Sopenharmony_ci spuravoid = 1; 7428c2ecf20Sopenharmony_ci bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false); 7438c2ecf20Sopenharmony_ci bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid); 7448c2ecf20Sopenharmony_ci bcma_core_pll_ctl(core, 7458c2ecf20Sopenharmony_ci B43_BCMA_CLKCTLST_80211_PLL_REQ | 7468c2ecf20Sopenharmony_ci B43_BCMA_CLKCTLST_PHY_PLL_REQ, 7478c2ecf20Sopenharmony_ci B43_BCMA_CLKCTLST_80211_PLL_ST | 7488c2ecf20Sopenharmony_ci B43_BCMA_CLKCTLST_PHY_PLL_ST, false); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci b43_mac_switch_freq(dev, spuravoid); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci b43_wireless_core_phy_pll_reset(dev); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci if (spuravoid) 7558c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX); 7568c2ecf20Sopenharmony_ci else 7578c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_BBCFG, 7588c2ecf20Sopenharmony_ci ~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci b43_phy_ht_reset_cca(dev); 7618c2ecf20Sopenharmony_ci} 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cistatic void b43_phy_ht_channel_setup(struct b43_wldev *dev, 7648c2ecf20Sopenharmony_ci const struct b43_phy_ht_channeltab_e_phy *e, 7658c2ecf20Sopenharmony_ci struct ieee80211_channel *new_channel) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci if (new_channel->band == NL80211_BAND_5GHZ) { 7688c2ecf20Sopenharmony_ci /* Switch to 2 GHz for a moment to access B-PHY regs */ 7698c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci b43_phy_ht_bphy_reset(dev, true); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci /* Switch to 5 GHz */ 7748c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_BANDCTL, B43_PHY_HT_BANDCTL_5GHZ); 7758c2ecf20Sopenharmony_ci } else { 7768c2ecf20Sopenharmony_ci /* Switch to 2 GHz */ 7778c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci b43_phy_ht_bphy_reset(dev, false); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1); 7838c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2); 7848c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3); 7858c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4); 7868c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); 7878c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci if (new_channel->hw_value == 14) { 7908c2ecf20Sopenharmony_ci b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0); 7918c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800); 7928c2ecf20Sopenharmony_ci } else { 7938c2ecf20Sopenharmony_ci b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 7948c2ecf20Sopenharmony_ci B43_PHY_HT_CLASS_CTL_OFDM_EN); 7958c2ecf20Sopenharmony_ci if (new_channel->band == NL80211_BAND_2GHZ) 7968c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840); 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci if (1) /* TODO: On N it's for early devices only, what about HT? */ 8008c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_fix(dev); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci b43_phy_ht_spur_avoid(dev, new_channel); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x017e, 0x3830); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic int b43_phy_ht_set_channel(struct b43_wldev *dev, 8088c2ecf20Sopenharmony_ci struct ieee80211_channel *channel, 8098c2ecf20Sopenharmony_ci enum nl80211_channel_type channel_type) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci if (phy->radio_ver == 0x2059) { 8168c2ecf20Sopenharmony_ci chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev, 8178c2ecf20Sopenharmony_ci channel->center_freq); 8188c2ecf20Sopenharmony_ci if (!chent_r2059) 8198c2ecf20Sopenharmony_ci return -ESRCH; 8208c2ecf20Sopenharmony_ci } else { 8218c2ecf20Sopenharmony_ci return -ESRCH; 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci /* TODO: In case of N-PHY some bandwidth switching goes here */ 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (phy->radio_ver == 0x2059) { 8278c2ecf20Sopenharmony_ci b43_radio_2059_channel_setup(dev, chent_r2059); 8288c2ecf20Sopenharmony_ci b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs), 8298c2ecf20Sopenharmony_ci channel); 8308c2ecf20Sopenharmony_ci } else { 8318c2ecf20Sopenharmony_ci return -ESRCH; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci return 0; 8358c2ecf20Sopenharmony_ci} 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci/************************************************** 8388c2ecf20Sopenharmony_ci * Basic PHY ops. 8398c2ecf20Sopenharmony_ci **************************************************/ 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_cistatic int b43_phy_ht_op_allocate(struct b43_wldev *dev) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL); 8468c2ecf20Sopenharmony_ci if (!phy_ht) 8478c2ecf20Sopenharmony_ci return -ENOMEM; 8488c2ecf20Sopenharmony_ci dev->phy.ht = phy_ht; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci return 0; 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) 8548c2ecf20Sopenharmony_ci{ 8558c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 8568c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = phy->ht; 8578c2ecf20Sopenharmony_ci int i; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci memset(phy_ht, 0, sizeof(*phy_ht)); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci phy_ht->tx_pwr_ctl = true; 8628c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 8638c2ecf20Sopenharmony_ci phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci for (i = 0; i < 3; i++) 8668c2ecf20Sopenharmony_ci phy_ht->bb_mult_save[i] = -1; 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int b43_phy_ht_op_init(struct b43_wldev *dev) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = dev->phy.ht; 8728c2ecf20Sopenharmony_ci u16 tmp; 8738c2ecf20Sopenharmony_ci u16 clip_state[3]; 8748c2ecf20Sopenharmony_ci bool saved_tx_pwr_ctl; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci if (dev->dev->bus_type != B43_BUS_BCMA) { 8778c2ecf20Sopenharmony_ci b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); 8788c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci b43_phy_ht_tables_init(dev); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci b43_phy_mask(dev, 0x0be, ~0x2); 8848c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x23f, 0x7ff); 8858c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x240, 0x7ff); 8868c2ecf20Sopenharmony_ci b43_phy_set(dev, 0x241, 0x7ff); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci b43_phy_ht_zero_extg(dev); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0); 8938c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0); 8948c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); 8978c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); 8988c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x20d, 0xb8); 8998c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); 9008c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x70, 0x50); 9018c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x1ff, 0x30); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 9048c2ecf20Sopenharmony_ci b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); 9058c2ecf20Sopenharmony_ci else 9068c2ecf20Sopenharmony_ci b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 9078c2ecf20Sopenharmony_ci B43_PHY_HT_CLASS_CTL_CCK_EN); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci b43_phy_set(dev, 0xb1, 0x91); 9108c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x32f, 0x0003); 9118c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x077, 0x0010); 9128c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x0b4, 0x0258); 9138c2ecf20Sopenharmony_ci b43_phy_mask(dev, 0x17e, ~0x4000); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci b43_phy_write(dev, 0x0b9, 0x0072); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); 9188c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); 9198c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci b43_phy_ht_afe_unk1(dev); 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, 9248c2ecf20Sopenharmony_ci 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); 9278c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); 9308c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); 9318c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, 9348c2ecf20Sopenharmony_ci 0x8e, 0x96, 0x96, 0x96); 9358c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, 9368c2ecf20Sopenharmony_ci 0x8f, 0x9f, 0x9f, 0x9f); 9378c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, 9388c2ecf20Sopenharmony_ci 0x8f, 0x9f, 0x9f, 0x9f); 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); 9418c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); 9428c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); 9458c2ecf20Sopenharmony_ci b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); 9468c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); 9478c2ecf20Sopenharmony_ci b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, 9508c2ecf20Sopenharmony_ci 0x09, 0x0e, 0x13, 0x18); 9518c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, 9528c2ecf20Sopenharmony_ci 0x09, 0x0e, 0x13, 0x18); 9538c2ecf20Sopenharmony_ci /* TODO: Did wl mean 2 instead of 40? */ 9548c2ecf20Sopenharmony_ci b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, 9558c2ecf20Sopenharmony_ci 0x09, 0x0e, 0x13, 0x18); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); 9588c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); 9598c2ecf20Sopenharmony_ci b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); 9628c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); 9638c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); 9648c2ecf20Sopenharmony_ci b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci /* Copy some tables entries */ 9678c2ecf20Sopenharmony_ci tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); 9688c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); 9698c2ecf20Sopenharmony_ci tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); 9708c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); 9718c2ecf20Sopenharmony_ci tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); 9728c2ecf20Sopenharmony_ci b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci /* Reset CCA */ 9758c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, true); 9768c2ecf20Sopenharmony_ci tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); 9778c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); 9788c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); 9798c2ecf20Sopenharmony_ci b43_phy_force_clock(dev, false); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci b43_mac_phy_clock_set(dev, true); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci b43_phy_ht_pa_override(dev, false); 9848c2ecf20Sopenharmony_ci b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); 9858c2ecf20Sopenharmony_ci b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); 9868c2ecf20Sopenharmony_ci b43_phy_ht_pa_override(dev, true); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci /* TODO: Should we restore it? Or store it in global PHY info? */ 9898c2ecf20Sopenharmony_ci b43_phy_ht_classifier(dev, 0, 0); 9908c2ecf20Sopenharmony_ci b43_phy_ht_read_clip_detection(dev, clip_state); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 9938c2ecf20Sopenharmony_ci b43_phy_ht_bphy_init(dev); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), 9968c2ecf20Sopenharmony_ci B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl; 9998c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_fix(dev); 10008c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_ctl(dev, false); 10018c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_ctl_idle_tssi(dev); 10028c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_ctl_setup(dev); 10038c2ecf20Sopenharmony_ci b43_phy_ht_tssi_setup(dev); 10048c2ecf20Sopenharmony_ci b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci return 0; 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_free(struct b43_wldev *dev) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci struct b43_phy *phy = &dev->phy; 10128c2ecf20Sopenharmony_ci struct b43_phy_ht *phy_ht = phy->ht; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci kfree(phy_ht); 10158c2ecf20Sopenharmony_ci phy->ht = NULL; 10168c2ecf20Sopenharmony_ci} 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci/* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 10198c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, 10208c2ecf20Sopenharmony_ci bool blocked) 10218c2ecf20Sopenharmony_ci{ 10228c2ecf20Sopenharmony_ci if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) 10238c2ecf20Sopenharmony_ci b43err(dev->wl, "MAC not suspended\n"); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci if (blocked) { 10268c2ecf20Sopenharmony_ci b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, 10278c2ecf20Sopenharmony_ci ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 10288c2ecf20Sopenharmony_ci } else { 10298c2ecf20Sopenharmony_ci if (dev->phy.radio_ver == 0x2059) 10308c2ecf20Sopenharmony_ci b43_radio_2059_init(dev); 10318c2ecf20Sopenharmony_ci else 10328c2ecf20Sopenharmony_ci B43_WARN_ON(1); 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci b43_switch_channel(dev, dev->phy.channel); 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci if (on) { 10418c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd); 10428c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000); 10438c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd); 10448c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000); 10458c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd); 10468c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000); 10478c2ecf20Sopenharmony_ci } else { 10488c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff); 10498c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd); 10508c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff); 10518c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd); 10528c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff); 10538c2ecf20Sopenharmony_ci b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd); 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, 10588c2ecf20Sopenharmony_ci unsigned int new_channel) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan; 10618c2ecf20Sopenharmony_ci enum nl80211_channel_type channel_type = 10628c2ecf20Sopenharmony_ci cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 10658c2ecf20Sopenharmony_ci if ((new_channel < 1) || (new_channel > 14)) 10668c2ecf20Sopenharmony_ci return -EINVAL; 10678c2ecf20Sopenharmony_ci } else { 10688c2ecf20Sopenharmony_ci return -EINVAL; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci return b43_phy_ht_set_channel(dev, channel, channel_type); 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cistatic unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) 10758c2ecf20Sopenharmony_ci{ 10768c2ecf20Sopenharmony_ci if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 10778c2ecf20Sopenharmony_ci return 11; 10788c2ecf20Sopenharmony_ci return 36; 10798c2ecf20Sopenharmony_ci} 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci/************************************************** 10828c2ecf20Sopenharmony_ci * R/W ops. 10838c2ecf20Sopenharmony_ci **************************************************/ 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 10868c2ecf20Sopenharmony_ci u16 set) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 10898c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_PHY_DATA, 10908c2ecf20Sopenharmony_ci (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg) 10948c2ecf20Sopenharmony_ci{ 10958c2ecf20Sopenharmony_ci /* HT-PHY needs 0x200 for read access */ 10968c2ecf20Sopenharmony_ci reg |= 0x200; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 10998c2ecf20Sopenharmony_ci return b43_read16(dev, B43_MMIO_RADIO24_DATA); 11008c2ecf20Sopenharmony_ci} 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg, 11038c2ecf20Sopenharmony_ci u16 value) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 11068c2ecf20Sopenharmony_ci b43_write16(dev, B43_MMIO_RADIO24_DATA, value); 11078c2ecf20Sopenharmony_ci} 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_cistatic enum b43_txpwr_result 11108c2ecf20Sopenharmony_cib43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) 11118c2ecf20Sopenharmony_ci{ 11128c2ecf20Sopenharmony_ci return B43_TXPWR_RES_DONE; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cistatic void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci/************************************************** 11208c2ecf20Sopenharmony_ci * PHY ops struct. 11218c2ecf20Sopenharmony_ci **************************************************/ 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ciconst struct b43_phy_operations b43_phyops_ht = { 11248c2ecf20Sopenharmony_ci .allocate = b43_phy_ht_op_allocate, 11258c2ecf20Sopenharmony_ci .free = b43_phy_ht_op_free, 11268c2ecf20Sopenharmony_ci .prepare_structs = b43_phy_ht_op_prepare_structs, 11278c2ecf20Sopenharmony_ci .init = b43_phy_ht_op_init, 11288c2ecf20Sopenharmony_ci .phy_maskset = b43_phy_ht_op_maskset, 11298c2ecf20Sopenharmony_ci .radio_read = b43_phy_ht_op_radio_read, 11308c2ecf20Sopenharmony_ci .radio_write = b43_phy_ht_op_radio_write, 11318c2ecf20Sopenharmony_ci .software_rfkill = b43_phy_ht_op_software_rfkill, 11328c2ecf20Sopenharmony_ci .switch_analog = b43_phy_ht_op_switch_analog, 11338c2ecf20Sopenharmony_ci .switch_channel = b43_phy_ht_op_switch_channel, 11348c2ecf20Sopenharmony_ci .get_default_chan = b43_phy_ht_op_get_default_chan, 11358c2ecf20Sopenharmony_ci .recalc_txpower = b43_phy_ht_op_recalc_txpower, 11368c2ecf20Sopenharmony_ci .adjust_txpower = b43_phy_ht_op_adjust_txpower, 11378c2ecf20Sopenharmony_ci}; 1138