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