PageRenderTime 143ms CodeModel.GetById 17ms app.highlight 108ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c

http://github.com/mirrors/linux
C | 5247 lines | 4300 code | 931 blank | 16 comment | 485 complexity | 67242b860323bdcb4c12983832a1319f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Copyright (c) 2010 Broadcom Corporation
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/delay.h>
  19#include <linux/cordic.h>
  20
  21#include <pmu.h>
  22#include <d11.h>
  23#include <phy_shim.h>
  24#include "phy_qmath.h"
  25#include "phy_hal.h"
  26#include "phy_radio.h"
  27#include "phytbl_lcn.h"
  28#include "phy_lcn.h"
  29
  30#define PLL_2064_NDIV		90
  31#define PLL_2064_LOW_END_VCO	3000
  32#define PLL_2064_LOW_END_KVCO	27
  33#define PLL_2064_HIGH_END_VCO	4200
  34#define PLL_2064_HIGH_END_KVCO	68
  35#define PLL_2064_LOOP_BW_DOUBLER	200
  36#define PLL_2064_D30_DOUBLER		10500
  37#define PLL_2064_LOOP_BW	260
  38#define PLL_2064_D30		8000
  39#define PLL_2064_CAL_REF_TO	8
  40#define PLL_2064_MHZ		1000000
  41#define PLL_2064_OPEN_LOOP_DELAY	5
  42
  43#define TEMPSENSE			1
  44#define VBATSENSE           2
  45
  46#define NOISE_IF_UPD_CHK_INTERVAL	1
  47#define NOISE_IF_UPD_RST_INTERVAL	60
  48#define NOISE_IF_UPD_THRESHOLD_CNT	1
  49#define NOISE_IF_UPD_TRHRESHOLD	50
  50#define NOISE_IF_UPD_TIMEOUT		1000
  51#define NOISE_IF_OFF			0
  52#define NOISE_IF_CHK			1
  53#define NOISE_IF_ON			2
  54
  55#define PAPD_BLANKING_PROFILE		3
  56#define PAPD2LUT			0
  57#define PAPD_CORR_NORM			0
  58#define PAPD_BLANKING_THRESHOLD		0
  59#define PAPD_STOP_AFTER_LAST_UPDATE	0
  60
  61#define LCN_TARGET_PWR  60
  62
  63#define LCN_VBAT_OFFSET_433X 34649679
  64#define LCN_VBAT_SLOPE_433X  8258032
  65
  66#define LCN_VBAT_SCALE_NOM  53
  67#define LCN_VBAT_SCALE_DEN  432
  68
  69#define LCN_TEMPSENSE_OFFSET  80812
  70#define LCN_TEMPSENSE_DEN  2647
  71
  72#define LCN_BW_LMT	200
  73#define LCN_CUR_LMT	1250
  74#define LCN_MULT	1
  75#define LCN_VCO_DIV	30
  76#define LCN_OFFSET	680
  77#define LCN_FACT	490
  78#define LCN_CUR_DIV	2640
  79
  80#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
  81	(0 + 8)
  82#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
  83	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
  84
  85#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
  86	(0 + 8)
  87#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
  88	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
  89
  90#define wlc_lcnphy_enable_tx_gain_override(pi) \
  91	wlc_lcnphy_set_tx_gain_override(pi, true)
  92#define wlc_lcnphy_disable_tx_gain_override(pi)	\
  93	wlc_lcnphy_set_tx_gain_override(pi, false)
  94
  95#define wlc_lcnphy_iqcal_active(pi)	\
  96	(read_phy_reg((pi), 0x451) & \
  97	 ((0x1 << 15) | (0x1 << 14)))
  98
  99#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
 100#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)	\
 101	(pi->temppwrctrl_capable)
 102#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
 103	(pi->hwpwrctrl_capable)
 104
 105#define SWCTRL_BT_TX		0x18
 106#define SWCTRL_OVR_DISABLE	0x40
 107
 108#define	AFE_CLK_INIT_MODE_TXRX2X	1
 109#define	AFE_CLK_INIT_MODE_PAPD		0
 110
 111#define LCNPHY_TBL_ID_IQLOCAL			0x00
 112
 113#define LCNPHY_TBL_ID_RFSEQ         0x08
 114#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
 115#define LCNPHY_TBL_ID_SW_CTRL			0x0f
 116#define LCNPHY_TBL_ID_GAIN_TBL		0x12
 117#define LCNPHY_TBL_ID_SPUR			0x14
 118#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
 119#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
 120
 121#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET	832
 122#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET	128
 123#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET	192
 124#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
 125#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
 126#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
 127
 128#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
 129
 130#define LCNPHY_TX_PWR_CTRL_START_NPT		1
 131#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
 132
 133#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
 134
 135#define LCNPHY_ACI_DETECT_START      1
 136#define LCNPHY_ACI_DETECT_PROGRESS   2
 137#define LCNPHY_ACI_DETECT_STOP       3
 138
 139#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
 140#define LCNPHY_ACI_GLITCH_TRSH 2000
 141#define	LCNPHY_ACI_TMOUT 250
 142#define LCNPHY_ACI_DETECT_TIMEOUT  2
 143#define LCNPHY_ACI_START_DELAY 0
 144
 145#define wlc_lcnphy_tx_gain_override_enabled(pi)	\
 146	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
 147
 148#define wlc_lcnphy_total_tx_frames(pi) \
 149	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \
 150			    offsetof(struct macstat, txallfrm))
 151
 152struct lcnphy_txgains {
 153	u16 gm_gain;
 154	u16 pga_gain;
 155	u16 pad_gain;
 156	u16 dac_gain;
 157};
 158
 159enum lcnphy_cal_mode {
 160	LCNPHY_CAL_FULL,
 161	LCNPHY_CAL_RECAL,
 162	LCNPHY_CAL_CURRECAL,
 163	LCNPHY_CAL_DIGCAL,
 164	LCNPHY_CAL_GCTRL
 165};
 166
 167struct lcnphy_rx_iqcomp {
 168	u8 chan;
 169	s16 a;
 170	s16 b;
 171};
 172
 173struct lcnphy_spb_tone {
 174	s16 re;
 175	s16 im;
 176};
 177
 178struct lcnphy_unsign16_struct {
 179	u16 re;
 180	u16 im;
 181};
 182
 183struct lcnphy_iq_est {
 184	u32 iq_prod;
 185	u32 i_pwr;
 186	u32 q_pwr;
 187};
 188
 189struct lcnphy_sfo_cfg {
 190	u16 ptcentreTs20;
 191	u16 ptcentreFactor;
 192};
 193
 194enum lcnphy_papd_cal_type {
 195	LCNPHY_PAPD_CAL_CW,
 196	LCNPHY_PAPD_CAL_OFDM
 197};
 198
 199typedef u16 iqcal_gain_params_lcnphy[9];
 200
 201static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
 202	{0, 0, 0, 0, 0, 0, 0, 0, 0},
 203};
 204
 205static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
 206	tbl_iqcal_gainparams_lcnphy_2G,
 207};
 208
 209static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
 210	ARRAY_SIZE(tbl_iqcal_gainparams_lcnphy_2G),
 211};
 212
 213static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = {
 214	{965, 1087},
 215	{967, 1085},
 216	{969, 1082},
 217	{971, 1080},
 218	{973, 1078},
 219	{975, 1076},
 220	{977, 1073},
 221	{979, 1071},
 222	{981, 1069},
 223	{983, 1067},
 224	{985, 1065},
 225	{987, 1063},
 226	{989, 1060},
 227	{994, 1055}
 228};
 229
 230static const
 231u16 lcnphy_iqcal_loft_gainladder[] = {
 232	((2 << 8) | 0),
 233	((3 << 8) | 0),
 234	((4 << 8) | 0),
 235	((6 << 8) | 0),
 236	((8 << 8) | 0),
 237	((11 << 8) | 0),
 238	((16 << 8) | 0),
 239	((16 << 8) | 1),
 240	((16 << 8) | 2),
 241	((16 << 8) | 3),
 242	((16 << 8) | 4),
 243	((16 << 8) | 5),
 244	((16 << 8) | 6),
 245	((16 << 8) | 7),
 246	((23 << 8) | 7),
 247	((32 << 8) | 7),
 248	((45 << 8) | 7),
 249	((64 << 8) | 7),
 250	((91 << 8) | 7),
 251	((128 << 8) | 7)
 252};
 253
 254static const
 255u16 lcnphy_iqcal_ir_gainladder[] = {
 256	((1 << 8) | 0),
 257	((2 << 8) | 0),
 258	((4 << 8) | 0),
 259	((6 << 8) | 0),
 260	((8 << 8) | 0),
 261	((11 << 8) | 0),
 262	((16 << 8) | 0),
 263	((23 << 8) | 0),
 264	((32 << 8) | 0),
 265	((45 << 8) | 0),
 266	((64 << 8) | 0),
 267	((64 << 8) | 1),
 268	((64 << 8) | 2),
 269	((64 << 8) | 3),
 270	((64 << 8) | 4),
 271	((64 << 8) | 5),
 272	((64 << 8) | 6),
 273	((64 << 8) | 7),
 274	((91 << 8) | 7),
 275	((128 << 8) | 7)
 276};
 277
 278static const
 279struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = {
 280	{88, 0},
 281	{73, 49},
 282	{34, 81},
 283	{-17, 86},
 284	{-62, 62},
 285	{-86, 17},
 286	{-81, -34},
 287	{-49, -73},
 288	{0, -88},
 289	{49, -73},
 290	{81, -34},
 291	{86, 17},
 292	{62, 62},
 293	{17, 86},
 294	{-34, 81},
 295	{-73, 49},
 296	{-88, 0},
 297	{-73, -49},
 298	{-34, -81},
 299	{17, -86},
 300	{62, -62},
 301	{86, -17},
 302	{81, 34},
 303	{49, 73},
 304	{0, 88},
 305	{-49, 73},
 306	{-81, 34},
 307	{-86, -17},
 308	{-62, -62},
 309	{-17, -86},
 310	{34, -81},
 311	{73, -49},
 312};
 313
 314static const
 315u16 iqlo_loopback_rf_regs[20] = {
 316	RADIO_2064_REG036,
 317	RADIO_2064_REG11A,
 318	RADIO_2064_REG03A,
 319	RADIO_2064_REG025,
 320	RADIO_2064_REG028,
 321	RADIO_2064_REG005,
 322	RADIO_2064_REG112,
 323	RADIO_2064_REG0FF,
 324	RADIO_2064_REG11F,
 325	RADIO_2064_REG00B,
 326	RADIO_2064_REG113,
 327	RADIO_2064_REG007,
 328	RADIO_2064_REG0FC,
 329	RADIO_2064_REG0FD,
 330	RADIO_2064_REG012,
 331	RADIO_2064_REG057,
 332	RADIO_2064_REG059,
 333	RADIO_2064_REG05C,
 334	RADIO_2064_REG078,
 335	RADIO_2064_REG092,
 336};
 337
 338static const
 339u16 tempsense_phy_regs[14] = {
 340	0x503,
 341	0x4a4,
 342	0x4d0,
 343	0x4d9,
 344	0x4da,
 345	0x4a6,
 346	0x938,
 347	0x939,
 348	0x4d8,
 349	0x4d0,
 350	0x4d7,
 351	0x4a5,
 352	0x40d,
 353	0x4a2,
 354};
 355
 356static const
 357u16 rxiq_cal_rf_reg[11] = {
 358	RADIO_2064_REG098,
 359	RADIO_2064_REG116,
 360	RADIO_2064_REG12C,
 361	RADIO_2064_REG06A,
 362	RADIO_2064_REG00B,
 363	RADIO_2064_REG01B,
 364	RADIO_2064_REG113,
 365	RADIO_2064_REG01D,
 366	RADIO_2064_REG114,
 367	RADIO_2064_REG02E,
 368	RADIO_2064_REG12A,
 369};
 370
 371static const
 372struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = {
 373	{1, 0, 0},
 374	{2, 0, 0},
 375	{3, 0, 0},
 376	{4, 0, 0},
 377	{5, 0, 0},
 378	{6, 0, 0},
 379	{7, 0, 0},
 380	{8, 0, 0},
 381	{9, 0, 0},
 382	{10, 0, 0},
 383	{11, 0, 0},
 384	{12, 0, 0},
 385	{13, 0, 0},
 386	{14, 0, 0},
 387	{34, 0, 0},
 388	{38, 0, 0},
 389	{42, 0, 0},
 390	{46, 0, 0},
 391	{36, 0, 0},
 392	{40, 0, 0},
 393	{44, 0, 0},
 394	{48, 0, 0},
 395	{52, 0, 0},
 396	{56, 0, 0},
 397	{60, 0, 0},
 398	{64, 0, 0},
 399	{100, 0, 0},
 400	{104, 0, 0},
 401	{108, 0, 0},
 402	{112, 0, 0},
 403	{116, 0, 0},
 404	{120, 0, 0},
 405	{124, 0, 0},
 406	{128, 0, 0},
 407	{132, 0, 0},
 408	{136, 0, 0},
 409	{140, 0, 0},
 410	{149, 0, 0},
 411	{153, 0, 0},
 412	{157, 0, 0},
 413	{161, 0, 0},
 414	{165, 0, 0},
 415	{184, 0, 0},
 416	{188, 0, 0},
 417	{192, 0, 0},
 418	{196, 0, 0},
 419	{200, 0, 0},
 420	{204, 0, 0},
 421	{208, 0, 0},
 422	{212, 0, 0},
 423	{216, 0, 0},
 424};
 425
 426static const u32 lcnphy_23bitgaincode_table[] = {
 427	0x200100,
 428	0x200200,
 429	0x200004,
 430	0x200014,
 431	0x200024,
 432	0x200034,
 433	0x200134,
 434	0x200234,
 435	0x200334,
 436	0x200434,
 437	0x200037,
 438	0x200137,
 439	0x200237,
 440	0x200337,
 441	0x200437,
 442	0x000035,
 443	0x000135,
 444	0x000235,
 445	0x000037,
 446	0x000137,
 447	0x000237,
 448	0x000337,
 449	0x00013f,
 450	0x00023f,
 451	0x00033f,
 452	0x00034f,
 453	0x00044f,
 454	0x00144f,
 455	0x00244f,
 456	0x00254f,
 457	0x00354f,
 458	0x00454f,
 459	0x00464f,
 460	0x01464f,
 461	0x02464f,
 462	0x03464f,
 463	0x04464f,
 464};
 465
 466static const s8 lcnphy_gain_table[] = {
 467	-16,
 468	-13,
 469	10,
 470	7,
 471	4,
 472	0,
 473	3,
 474	6,
 475	9,
 476	12,
 477	15,
 478	18,
 479	21,
 480	24,
 481	27,
 482	30,
 483	33,
 484	36,
 485	39,
 486	42,
 487	45,
 488	48,
 489	50,
 490	53,
 491	56,
 492	59,
 493	62,
 494	65,
 495	68,
 496	71,
 497	74,
 498	77,
 499	80,
 500	83,
 501	86,
 502	89,
 503	92,
 504};
 505
 506static const s8 lcnphy_gain_index_offset_for_rssi[] = {
 507	7,
 508	7,
 509	7,
 510	7,
 511	7,
 512	7,
 513	7,
 514	8,
 515	7,
 516	7,
 517	6,
 518	7,
 519	7,
 520	4,
 521	4,
 522	4,
 523	4,
 524	4,
 525	4,
 526	4,
 527	4,
 528	3,
 529	3,
 530	3,
 531	3,
 532	3,
 533	3,
 534	4,
 535	2,
 536	2,
 537	2,
 538	2,
 539	2,
 540	2,
 541	-1,
 542	-2,
 543	-2,
 544	-2
 545};
 546
 547struct chan_info_2064_lcnphy {
 548	uint chan;
 549	uint freq;
 550	u8 logen_buftune;
 551	u8 logen_rccr_tx;
 552	u8 txrf_mix_tune_ctrl;
 553	u8 pa_input_tune_g;
 554	u8 logen_rccr_rx;
 555	u8 pa_rxrf_lna1_freq_tune;
 556	u8 pa_rxrf_lna2_freq_tune;
 557	u8 rxrf_rxrf_spare1;
 558};
 559
 560static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = {
 561	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 562	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 563	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 564	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 565	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 566	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 567	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 568	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 569	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 570	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 571	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 572	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 573	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 574	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
 575};
 576
 577static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = {
 578	{0x00, 0, 0, 0, 0},
 579	{0x01, 0x64, 0x64, 0, 0},
 580	{0x02, 0x20, 0x20, 0, 0},
 581	{0x03, 0x66, 0x66, 0, 0},
 582	{0x04, 0xf8, 0xf8, 0, 0},
 583	{0x05, 0, 0, 0, 0},
 584	{0x06, 0x10, 0x10, 0, 0},
 585	{0x07, 0, 0, 0, 0},
 586	{0x08, 0, 0, 0, 0},
 587	{0x09, 0, 0, 0, 0},
 588	{0x0A, 0x37, 0x37, 0, 0},
 589	{0x0B, 0x6, 0x6, 0, 0},
 590	{0x0C, 0x55, 0x55, 0, 0},
 591	{0x0D, 0x8b, 0x8b, 0, 0},
 592	{0x0E, 0, 0, 0, 0},
 593	{0x0F, 0x5, 0x5, 0, 0},
 594	{0x10, 0, 0, 0, 0},
 595	{0x11, 0xe, 0xe, 0, 0},
 596	{0x12, 0, 0, 0, 0},
 597	{0x13, 0xb, 0xb, 0, 0},
 598	{0x14, 0x2, 0x2, 0, 0},
 599	{0x15, 0x12, 0x12, 0, 0},
 600	{0x16, 0x12, 0x12, 0, 0},
 601	{0x17, 0xc, 0xc, 0, 0},
 602	{0x18, 0xc, 0xc, 0, 0},
 603	{0x19, 0xc, 0xc, 0, 0},
 604	{0x1A, 0x8, 0x8, 0, 0},
 605	{0x1B, 0x2, 0x2, 0, 0},
 606	{0x1C, 0, 0, 0, 0},
 607	{0x1D, 0x1, 0x1, 0, 0},
 608	{0x1E, 0x12, 0x12, 0, 0},
 609	{0x1F, 0x6e, 0x6e, 0, 0},
 610	{0x20, 0x2, 0x2, 0, 0},
 611	{0x21, 0x23, 0x23, 0, 0},
 612	{0x22, 0x8, 0x8, 0, 0},
 613	{0x23, 0, 0, 0, 0},
 614	{0x24, 0, 0, 0, 0},
 615	{0x25, 0xc, 0xc, 0, 0},
 616	{0x26, 0x33, 0x33, 0, 0},
 617	{0x27, 0x55, 0x55, 0, 0},
 618	{0x28, 0, 0, 0, 0},
 619	{0x29, 0x30, 0x30, 0, 0},
 620	{0x2A, 0xb, 0xb, 0, 0},
 621	{0x2B, 0x1b, 0x1b, 0, 0},
 622	{0x2C, 0x3, 0x3, 0, 0},
 623	{0x2D, 0x1b, 0x1b, 0, 0},
 624	{0x2E, 0, 0, 0, 0},
 625	{0x2F, 0x20, 0x20, 0, 0},
 626	{0x30, 0xa, 0xa, 0, 0},
 627	{0x31, 0, 0, 0, 0},
 628	{0x32, 0x62, 0x62, 0, 0},
 629	{0x33, 0x19, 0x19, 0, 0},
 630	{0x34, 0x33, 0x33, 0, 0},
 631	{0x35, 0x77, 0x77, 0, 0},
 632	{0x36, 0, 0, 0, 0},
 633	{0x37, 0x70, 0x70, 0, 0},
 634	{0x38, 0x3, 0x3, 0, 0},
 635	{0x39, 0xf, 0xf, 0, 0},
 636	{0x3A, 0x6, 0x6, 0, 0},
 637	{0x3B, 0xcf, 0xcf, 0, 0},
 638	{0x3C, 0x1a, 0x1a, 0, 0},
 639	{0x3D, 0x6, 0x6, 0, 0},
 640	{0x3E, 0x42, 0x42, 0, 0},
 641	{0x3F, 0, 0, 0, 0},
 642	{0x40, 0xfb, 0xfb, 0, 0},
 643	{0x41, 0x9a, 0x9a, 0, 0},
 644	{0x42, 0x7a, 0x7a, 0, 0},
 645	{0x43, 0x29, 0x29, 0, 0},
 646	{0x44, 0, 0, 0, 0},
 647	{0x45, 0x8, 0x8, 0, 0},
 648	{0x46, 0xce, 0xce, 0, 0},
 649	{0x47, 0x27, 0x27, 0, 0},
 650	{0x48, 0x62, 0x62, 0, 0},
 651	{0x49, 0x6, 0x6, 0, 0},
 652	{0x4A, 0x58, 0x58, 0, 0},
 653	{0x4B, 0xf7, 0xf7, 0, 0},
 654	{0x4C, 0, 0, 0, 0},
 655	{0x4D, 0xb3, 0xb3, 0, 0},
 656	{0x4E, 0, 0, 0, 0},
 657	{0x4F, 0x2, 0x2, 0, 0},
 658	{0x50, 0, 0, 0, 0},
 659	{0x51, 0x9, 0x9, 0, 0},
 660	{0x52, 0x5, 0x5, 0, 0},
 661	{0x53, 0x17, 0x17, 0, 0},
 662	{0x54, 0x38, 0x38, 0, 0},
 663	{0x55, 0, 0, 0, 0},
 664	{0x56, 0, 0, 0, 0},
 665	{0x57, 0xb, 0xb, 0, 0},
 666	{0x58, 0, 0, 0, 0},
 667	{0x59, 0, 0, 0, 0},
 668	{0x5A, 0, 0, 0, 0},
 669	{0x5B, 0, 0, 0, 0},
 670	{0x5C, 0, 0, 0, 0},
 671	{0x5D, 0, 0, 0, 0},
 672	{0x5E, 0x88, 0x88, 0, 0},
 673	{0x5F, 0xcc, 0xcc, 0, 0},
 674	{0x60, 0x74, 0x74, 0, 0},
 675	{0x61, 0x74, 0x74, 0, 0},
 676	{0x62, 0x74, 0x74, 0, 0},
 677	{0x63, 0x44, 0x44, 0, 0},
 678	{0x64, 0x77, 0x77, 0, 0},
 679	{0x65, 0x44, 0x44, 0, 0},
 680	{0x66, 0x77, 0x77, 0, 0},
 681	{0x67, 0x55, 0x55, 0, 0},
 682	{0x68, 0x77, 0x77, 0, 0},
 683	{0x69, 0x77, 0x77, 0, 0},
 684	{0x6A, 0, 0, 0, 0},
 685	{0x6B, 0x7f, 0x7f, 0, 0},
 686	{0x6C, 0x8, 0x8, 0, 0},
 687	{0x6D, 0, 0, 0, 0},
 688	{0x6E, 0x88, 0x88, 0, 0},
 689	{0x6F, 0x66, 0x66, 0, 0},
 690	{0x70, 0x66, 0x66, 0, 0},
 691	{0x71, 0x28, 0x28, 0, 0},
 692	{0x72, 0x55, 0x55, 0, 0},
 693	{0x73, 0x4, 0x4, 0, 0},
 694	{0x74, 0, 0, 0, 0},
 695	{0x75, 0, 0, 0, 0},
 696	{0x76, 0, 0, 0, 0},
 697	{0x77, 0x1, 0x1, 0, 0},
 698	{0x78, 0xd6, 0xd6, 0, 0},
 699	{0x79, 0, 0, 0, 0},
 700	{0x7A, 0, 0, 0, 0},
 701	{0x7B, 0, 0, 0, 0},
 702	{0x7C, 0, 0, 0, 0},
 703	{0x7D, 0, 0, 0, 0},
 704	{0x7E, 0, 0, 0, 0},
 705	{0x7F, 0, 0, 0, 0},
 706	{0x80, 0, 0, 0, 0},
 707	{0x81, 0, 0, 0, 0},
 708	{0x82, 0, 0, 0, 0},
 709	{0x83, 0xb4, 0xb4, 0, 0},
 710	{0x84, 0x1, 0x1, 0, 0},
 711	{0x85, 0x20, 0x20, 0, 0},
 712	{0x86, 0x5, 0x5, 0, 0},
 713	{0x87, 0xff, 0xff, 0, 0},
 714	{0x88, 0x7, 0x7, 0, 0},
 715	{0x89, 0x77, 0x77, 0, 0},
 716	{0x8A, 0x77, 0x77, 0, 0},
 717	{0x8B, 0x77, 0x77, 0, 0},
 718	{0x8C, 0x77, 0x77, 0, 0},
 719	{0x8D, 0x8, 0x8, 0, 0},
 720	{0x8E, 0xa, 0xa, 0, 0},
 721	{0x8F, 0x8, 0x8, 0, 0},
 722	{0x90, 0x18, 0x18, 0, 0},
 723	{0x91, 0x5, 0x5, 0, 0},
 724	{0x92, 0x1f, 0x1f, 0, 0},
 725	{0x93, 0x10, 0x10, 0, 0},
 726	{0x94, 0x3, 0x3, 0, 0},
 727	{0x95, 0, 0, 0, 0},
 728	{0x96, 0, 0, 0, 0},
 729	{0x97, 0xaa, 0xaa, 0, 0},
 730	{0x98, 0, 0, 0, 0},
 731	{0x99, 0x23, 0x23, 0, 0},
 732	{0x9A, 0x7, 0x7, 0, 0},
 733	{0x9B, 0xf, 0xf, 0, 0},
 734	{0x9C, 0x10, 0x10, 0, 0},
 735	{0x9D, 0x3, 0x3, 0, 0},
 736	{0x9E, 0x4, 0x4, 0, 0},
 737	{0x9F, 0x20, 0x20, 0, 0},
 738	{0xA0, 0, 0, 0, 0},
 739	{0xA1, 0, 0, 0, 0},
 740	{0xA2, 0, 0, 0, 0},
 741	{0xA3, 0, 0, 0, 0},
 742	{0xA4, 0x1, 0x1, 0, 0},
 743	{0xA5, 0x77, 0x77, 0, 0},
 744	{0xA6, 0x77, 0x77, 0, 0},
 745	{0xA7, 0x77, 0x77, 0, 0},
 746	{0xA8, 0x77, 0x77, 0, 0},
 747	{0xA9, 0x8c, 0x8c, 0, 0},
 748	{0xAA, 0x88, 0x88, 0, 0},
 749	{0xAB, 0x78, 0x78, 0, 0},
 750	{0xAC, 0x57, 0x57, 0, 0},
 751	{0xAD, 0x88, 0x88, 0, 0},
 752	{0xAE, 0, 0, 0, 0},
 753	{0xAF, 0x8, 0x8, 0, 0},
 754	{0xB0, 0x88, 0x88, 0, 0},
 755	{0xB1, 0, 0, 0, 0},
 756	{0xB2, 0x1b, 0x1b, 0, 0},
 757	{0xB3, 0x3, 0x3, 0, 0},
 758	{0xB4, 0x24, 0x24, 0, 0},
 759	{0xB5, 0x3, 0x3, 0, 0},
 760	{0xB6, 0x1b, 0x1b, 0, 0},
 761	{0xB7, 0x24, 0x24, 0, 0},
 762	{0xB8, 0x3, 0x3, 0, 0},
 763	{0xB9, 0, 0, 0, 0},
 764	{0xBA, 0xaa, 0xaa, 0, 0},
 765	{0xBB, 0, 0, 0, 0},
 766	{0xBC, 0x4, 0x4, 0, 0},
 767	{0xBD, 0, 0, 0, 0},
 768	{0xBE, 0x8, 0x8, 0, 0},
 769	{0xBF, 0x11, 0x11, 0, 0},
 770	{0xC0, 0, 0, 0, 0},
 771	{0xC1, 0, 0, 0, 0},
 772	{0xC2, 0x62, 0x62, 0, 0},
 773	{0xC3, 0x1e, 0x1e, 0, 0},
 774	{0xC4, 0x33, 0x33, 0, 0},
 775	{0xC5, 0x37, 0x37, 0, 0},
 776	{0xC6, 0, 0, 0, 0},
 777	{0xC7, 0x70, 0x70, 0, 0},
 778	{0xC8, 0x1e, 0x1e, 0, 0},
 779	{0xC9, 0x6, 0x6, 0, 0},
 780	{0xCA, 0x4, 0x4, 0, 0},
 781	{0xCB, 0x2f, 0x2f, 0, 0},
 782	{0xCC, 0xf, 0xf, 0, 0},
 783	{0xCD, 0, 0, 0, 0},
 784	{0xCE, 0xff, 0xff, 0, 0},
 785	{0xCF, 0x8, 0x8, 0, 0},
 786	{0xD0, 0x3f, 0x3f, 0, 0},
 787	{0xD1, 0x3f, 0x3f, 0, 0},
 788	{0xD2, 0x3f, 0x3f, 0, 0},
 789	{0xD3, 0, 0, 0, 0},
 790	{0xD4, 0, 0, 0, 0},
 791	{0xD5, 0, 0, 0, 0},
 792	{0xD6, 0xcc, 0xcc, 0, 0},
 793	{0xD7, 0, 0, 0, 0},
 794	{0xD8, 0x8, 0x8, 0, 0},
 795	{0xD9, 0x8, 0x8, 0, 0},
 796	{0xDA, 0x8, 0x8, 0, 0},
 797	{0xDB, 0x11, 0x11, 0, 0},
 798	{0xDC, 0, 0, 0, 0},
 799	{0xDD, 0x87, 0x87, 0, 0},
 800	{0xDE, 0x88, 0x88, 0, 0},
 801	{0xDF, 0x8, 0x8, 0, 0},
 802	{0xE0, 0x8, 0x8, 0, 0},
 803	{0xE1, 0x8, 0x8, 0, 0},
 804	{0xE2, 0, 0, 0, 0},
 805	{0xE3, 0, 0, 0, 0},
 806	{0xE4, 0, 0, 0, 0},
 807	{0xE5, 0xf5, 0xf5, 0, 0},
 808	{0xE6, 0x30, 0x30, 0, 0},
 809	{0xE7, 0x1, 0x1, 0, 0},
 810	{0xE8, 0, 0, 0, 0},
 811	{0xE9, 0xff, 0xff, 0, 0},
 812	{0xEA, 0, 0, 0, 0},
 813	{0xEB, 0, 0, 0, 0},
 814	{0xEC, 0x22, 0x22, 0, 0},
 815	{0xED, 0, 0, 0, 0},
 816	{0xEE, 0, 0, 0, 0},
 817	{0xEF, 0, 0, 0, 0},
 818	{0xF0, 0x3, 0x3, 0, 0},
 819	{0xF1, 0x1, 0x1, 0, 0},
 820	{0xF2, 0, 0, 0, 0},
 821	{0xF3, 0, 0, 0, 0},
 822	{0xF4, 0, 0, 0, 0},
 823	{0xF5, 0, 0, 0, 0},
 824	{0xF6, 0, 0, 0, 0},
 825	{0xF7, 0x6, 0x6, 0, 0},
 826	{0xF8, 0, 0, 0, 0},
 827	{0xF9, 0, 0, 0, 0},
 828	{0xFA, 0x40, 0x40, 0, 0},
 829	{0xFB, 0, 0, 0, 0},
 830	{0xFC, 0x1, 0x1, 0, 0},
 831	{0xFD, 0x80, 0x80, 0, 0},
 832	{0xFE, 0x2, 0x2, 0, 0},
 833	{0xFF, 0x10, 0x10, 0, 0},
 834	{0x100, 0x2, 0x2, 0, 0},
 835	{0x101, 0x1e, 0x1e, 0, 0},
 836	{0x102, 0x1e, 0x1e, 0, 0},
 837	{0x103, 0, 0, 0, 0},
 838	{0x104, 0x1f, 0x1f, 0, 0},
 839	{0x105, 0, 0x8, 0, 1},
 840	{0x106, 0x2a, 0x2a, 0, 0},
 841	{0x107, 0xf, 0xf, 0, 0},
 842	{0x108, 0, 0, 0, 0},
 843	{0x109, 0, 0, 0, 0},
 844	{0x10A, 0, 0, 0, 0},
 845	{0x10B, 0, 0, 0, 0},
 846	{0x10C, 0, 0, 0, 0},
 847	{0x10D, 0, 0, 0, 0},
 848	{0x10E, 0, 0, 0, 0},
 849	{0x10F, 0, 0, 0, 0},
 850	{0x110, 0, 0, 0, 0},
 851	{0x111, 0, 0, 0, 0},
 852	{0x112, 0, 0, 0, 0},
 853	{0x113, 0, 0, 0, 0},
 854	{0x114, 0, 0, 0, 0},
 855	{0x115, 0, 0, 0, 0},
 856	{0x116, 0, 0, 0, 0},
 857	{0x117, 0, 0, 0, 0},
 858	{0x118, 0, 0, 0, 0},
 859	{0x119, 0, 0, 0, 0},
 860	{0x11A, 0, 0, 0, 0},
 861	{0x11B, 0, 0, 0, 0},
 862	{0x11C, 0x1, 0x1, 0, 0},
 863	{0x11D, 0, 0, 0, 0},
 864	{0x11E, 0, 0, 0, 0},
 865	{0x11F, 0, 0, 0, 0},
 866	{0x120, 0, 0, 0, 0},
 867	{0x121, 0, 0, 0, 0},
 868	{0x122, 0x80, 0x80, 0, 0},
 869	{0x123, 0, 0, 0, 0},
 870	{0x124, 0xf8, 0xf8, 0, 0},
 871	{0x125, 0, 0, 0, 0},
 872	{0x126, 0, 0, 0, 0},
 873	{0x127, 0, 0, 0, 0},
 874	{0x128, 0, 0, 0, 0},
 875	{0x129, 0, 0, 0, 0},
 876	{0x12A, 0, 0, 0, 0},
 877	{0x12B, 0, 0, 0, 0},
 878	{0x12C, 0, 0, 0, 0},
 879	{0x12D, 0, 0, 0, 0},
 880	{0x12E, 0, 0, 0, 0},
 881	{0x12F, 0, 0, 0, 0},
 882	{0x130, 0, 0, 0, 0},
 883	{0xFFFF, 0, 0, 0, 0}
 884};
 885
 886#define LCNPHY_NUM_DIG_FILT_COEFFS 16
 887#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
 888
 889static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
 890	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
 891	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
 892	 128, 64,},
 893	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
 894	 167, 93,},
 895	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
 896	 128, 64,},
 897	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
 898	 170, 340, 170,},
 899	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
 900	 256, 185, 256,},
 901	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
 902	 256, 273, 256,},
 903	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
 904	 256, 352, 256,},
 905	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
 906	 128, 233, 128,},
 907	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
 908	 1881, 256,},
 909	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
 910	 1881, 256,},
 911	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
 912	 384, 288,},
 913	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
 914	 128, 384, 288,},
 915	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
 916	 170, 340, 170,},
 917};
 918
 919#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
 920static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
 921	[LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
 922	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
 923	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
 924	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
 925	 750, 0xFE2B, 212, 0xFFCE, 212,},
 926	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
 927	 0xFEF2, 128, 0xFFE2, 128}
 928};
 929
 930#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
 931	mod_phy_reg(pi, 0x4a4, \
 932		    (0x1ff << 0), \
 933		    (u16)(idx) << 0)
 934
 935#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
 936	mod_phy_reg(pi, 0x4a5, \
 937		    (0x7 << 8),	\
 938		    (u16)(npt) << 8)
 939
 940#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
 941	(read_phy_reg((pi), 0x4a4) & \
 942	 ((0x1 << 15) |	\
 943	  (0x1 << 14) |	\
 944	  (0x1 << 13)))
 945
 946#define wlc_lcnphy_get_tx_pwr_npt(pi) \
 947	((read_phy_reg(pi, 0x4a5) & \
 948	  (0x7 << 8)) >> \
 949	 8)
 950
 951#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
 952	(read_phy_reg(pi, 0x473) & 0x1ff)
 953
 954#define wlc_lcnphy_get_target_tx_pwr(pi) \
 955	((read_phy_reg(pi, 0x4a7) & \
 956	  (0xff << 0)) >> \
 957	 0)
 958
 959#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
 960	mod_phy_reg(pi, 0x4a7, \
 961		    (0xff << 0), \
 962		    (u16)(target) << 0)
 963
 964#define wlc_radio_2064_rcal_done(pi) \
 965	(0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
 966
 967#define tempsense_done(pi) \
 968	(0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
 969
 970#define LCNPHY_IQLOCC_READ(val) \
 971	((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
 972
 973#define FIXED_TXPWR 78
 974#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
 975
 976void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti)
 977{
 978	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
 979}
 980
 981void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti)
 982{
 983	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
 984}
 985
 986static void
 987wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id,
 988			     const u16 *tbl_ptr, u32 tbl_len,
 989			     u32 tbl_width, u32 tbl_offset)
 990{
 991	struct phytbl_info tab;
 992	tab.tbl_id = tbl_id;
 993	tab.tbl_ptr = tbl_ptr;
 994	tab.tbl_len = tbl_len;
 995	tab.tbl_width = tbl_width;
 996	tab.tbl_offset = tbl_offset;
 997	wlc_lcnphy_read_table(pi, &tab);
 998}
 999
1000static void
1001wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id,
1002			      const u16 *tbl_ptr, u32 tbl_len,
1003			      u32 tbl_width, u32 tbl_offset)
1004{
1005
1006	struct phytbl_info tab;
1007	tab.tbl_id = tbl_id;
1008	tab.tbl_ptr = tbl_ptr;
1009	tab.tbl_len = tbl_len;
1010	tab.tbl_width = tbl_width;
1011	tab.tbl_offset = tbl_offset;
1012	wlc_lcnphy_write_table(pi, &tab);
1013}
1014
1015static u32
1016wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
1017{
1018	u32 quotient, remainder, roundup, rbit;
1019
1020	quotient = dividend / divisor;
1021	remainder = dividend % divisor;
1022	rbit = divisor & 1;
1023	roundup = (divisor >> 1) + rbit;
1024
1025	while (precision--) {
1026		quotient <<= 1;
1027		if (remainder >= roundup) {
1028			quotient++;
1029			remainder = ((remainder - roundup) << 1) + rbit;
1030		} else {
1031			remainder <<= 1;
1032		}
1033	}
1034
1035	if (remainder >= roundup)
1036		quotient++;
1037
1038	return quotient;
1039}
1040
1041static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
1042{
1043	int k;
1044	k = 0;
1045	if (type == 0) {
1046		if (coeff_x < 0)
1047			k = (coeff_x - 1) / 2;
1048		else
1049			k = coeff_x / 2;
1050	}
1051
1052	if (type == 1) {
1053		if ((coeff_x + 1) < 0)
1054			k = (coeff_x) / 2;
1055		else
1056			k = (coeff_x + 1) / 2;
1057	}
1058	return k;
1059}
1060
1061static void
1062wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains)
1063{
1064	u16 dac_gain, rfgain0, rfgain1;
1065
1066	dac_gain = read_phy_reg(pi, 0x439) >> 0;
1067	gains->dac_gain = (dac_gain & 0x380) >> 7;
1068
1069	rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
1070	rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
1071
1072	gains->gm_gain = rfgain0 & 0xff;
1073	gains->pga_gain = (rfgain0 >> 8) & 0xff;
1074	gains->pad_gain = rfgain1 & 0xff;
1075}
1076
1077
1078static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain)
1079{
1080	u16 dac_ctrl;
1081
1082	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
1083	dac_ctrl = dac_ctrl & 0xc7f;
1084	dac_ctrl = dac_ctrl | (dac_gain << 7);
1085	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
1086
1087}
1088
1089static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable)
1090{
1091	u16 bit = bEnable ? 1 : 0;
1092
1093	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
1094
1095	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
1096
1097	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
1098}
1099
1100static void
1101wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable)
1102{
1103	u16 ebit = enable ? 1 : 0;
1104
1105	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
1106
1107	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
1108
1109	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
1110		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
1111		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
1112		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
1113		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
1114	} else {
1115		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
1116		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
1117		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
1118	}
1119
1120	if (CHSPEC_IS2G(pi->radio_chanspec)) {
1121		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
1122		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
1123	}
1124}
1125
1126static void
1127wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
1128				       u16 trsw,
1129				       u16 ext_lna,
1130				       u16 biq2,
1131				       u16 biq1,
1132				       u16 tia, u16 lna2, u16 lna1)
1133{
1134	u16 gain0_15, gain16_19;
1135
1136	gain16_19 = biq2 & 0xf;
1137	gain0_15 = ((biq1 & 0xf) << 12) |
1138		   ((tia & 0xf) << 8) |
1139		   ((lna2 & 0x3) << 6) |
1140		   ((lna2 & 0x3) << 4) |
1141		   ((lna1 & 0x3) << 2) |
1142		   ((lna1 & 0x3) << 0);
1143
1144	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
1145	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
1146	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
1147
1148	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
1149		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
1150		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
1151	} else {
1152		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
1153
1154		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
1155
1156		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
1157	}
1158
1159	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
1160
1161}
1162
1163static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx)
1164{
1165
1166	mod_phy_reg(pi, 0x44d,
1167		    (0x1 << 1) |
1168		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
1169
1170	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
1171}
1172
1173static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi)
1174{
1175
1176	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
1177}
1178
1179static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b)
1180{
1181	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
1182
1183	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
1184
1185	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
1186
1187	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
1188
1189	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
1190
1191	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
1192
1193}
1194
1195static bool
1196wlc_lcnphy_rx_iq_est(struct brcms_phy *pi,
1197		     u16 num_samps,
1198		     u8 wait_time, struct lcnphy_iq_est *iq_est)
1199{
1200	int wait_count = 0;
1201	bool result = true;
1202	u8 phybw40;
1203	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
1204
1205	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
1206
1207	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
1208
1209	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
1210
1211	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
1212
1213	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
1214
1215	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
1216
1217	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
1218
1219		if (wait_count > (10 * 500)) {
1220			result = false;
1221			goto cleanup;
1222		}
1223		udelay(100);
1224		wait_count++;
1225	}
1226
1227	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
1228			  (u32) read_phy_reg(pi, 0x484);
1229	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
1230			(u32) read_phy_reg(pi, 0x486);
1231	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
1232			(u32) read_phy_reg(pi, 0x488);
1233
1234cleanup:
1235	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
1236
1237	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
1238
1239	return result;
1240}
1241
1242static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps)
1243{
1244#define LCNPHY_MIN_RXIQ_PWR 2
1245	bool result;
1246	u16 a0_new, b0_new;
1247	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
1248	s32 a, b, temp;
1249	s16 iq_nbits, qq_nbits, arsh, brsh;
1250	s32 iq;
1251	u32 ii, qq;
1252	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
1253
1254	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
1255	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
1256	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
1257
1258	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
1259
1260	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
1261
1262	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
1263	if (!result)
1264		goto cleanup;
1265
1266	iq = (s32) iq_est.iq_prod;
1267	ii = iq_est.i_pwr;
1268	qq = iq_est.q_pwr;
1269
1270	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
1271		result = false;
1272		goto cleanup;
1273	}
1274
1275	iq_nbits = wlc_phy_nbits(iq);
1276	qq_nbits = wlc_phy_nbits(qq);
1277
1278	arsh = 10 - (30 - iq_nbits);
1279	if (arsh >= 0) {
1280		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
1281		temp = (s32) (ii >> arsh);
1282		if (temp == 0)
1283			return false;
1284	} else {
1285		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
1286		temp = (s32) (ii << -arsh);
1287		if (temp == 0)
1288			return false;
1289	}
1290	a /= temp;
1291	brsh = qq_nbits - 31 + 20;
1292	if (brsh >= 0) {
1293		b = (qq << (31 - qq_nbits));
1294		temp = (s32) (ii >> brsh);
1295		if (temp == 0)
1296			return false;
1297	} else {
1298		b = (qq << (31 - qq_nbits));
1299		temp = (s32) (ii << -brsh);
1300		if (temp == 0)
1301			return false;
1302	}
1303	b /= temp;
1304	b -= a * a;
1305	b = (s32) int_sqrt((unsigned long) b);
1306	b -= (1 << 10);
1307	a0_new = (u16) (a & 0x3ff);
1308	b0_new = (u16) (b & 0x3ff);
1309cleanup:
1310
1311	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
1312
1313	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
1314
1315	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
1316
1317	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
1318	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
1319
1320	return result;
1321}
1322
1323static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
1324{
1325	struct lcnphy_iq_est iq_est = { 0, 0, 0 };
1326
1327	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
1328		return 0;
1329	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
1330}
1331
1332static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
1333				      u16 tia_gain, u16 lna2_gain)
1334{
1335	u32 i_thresh_l, q_thresh_l;
1336	u32 i_thresh_h, q_thresh_h;
1337	struct lcnphy_iq_est iq_est_h, iq_est_l;
1338
1339	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
1340					       lna2_gain, 0);
1341
1342	wlc_lcnphy_rx_gain_override_enable(pi, true);
1343	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
1344	udelay(500);
1345	write_radio_reg(pi, RADIO_2064_REG112, 0);
1346	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
1347		return false;
1348
1349	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
1350	udelay(500);
1351	write_radio_reg(pi, RADIO_2064_REG112, 0);
1352	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
1353		return false;
1354
1355	i_thresh_l = (iq_est_l.i_pwr << 1);
1356	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
1357
1358	q_thresh_l = (iq_est_l.q_pwr << 1);
1359	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
1360	if ((iq_est_h.i_pwr > i_thresh_l) &&
1361	    (iq_est_h.i_pwr < i_thresh_h) &&
1362	    (iq_est_h.q_pwr > q_thresh_l) &&
1363	    (iq_est_h.q_pwr < q_thresh_h))
1364		return true;
1365
1366	return false;
1367}
1368
1369static bool
1370wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
1371		     const struct lcnphy_rx_iqcomp *iqcomp,
1372		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
1373		     int tx_gain_idx)
1374{
1375	struct lcnphy_txgains old_gains;
1376	u16 tx_pwr_ctrl;
1377	u8 tx_gain_index_old = 0;
1378	bool result = false, tx_gain_override_old = false;
1379	u16 i, Core1TxControl_old, RFOverride0_old,
1380	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
1381	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
1382	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
1383	int tia_gain, lna2_gain, biq1_gain;
1384	bool set_gain;
1385	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
1386	u16 values_to_save[11];
1387	s16 *ptr;
1388	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
1389
1390	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
1391	if (NULL == ptr)
1392		return false;
1393	if (module == 2) {
1394		while (iqcomp_sz--) {
1395			if (iqcomp[iqcomp_sz].chan ==
1396			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
1397				wlc_lcnphy_set_rx_iq_comp(pi,
1398							  (u16)
1399							  iqcomp[iqcomp_sz].a,
1400							  (u16)
1401							  iqcomp[iqcomp_sz].b);
1402				result = true;
1403				break;
1404			}
1405		}
1406		goto cal_done;
1407	}
1408
1409	WARN_ON(module != 1);
1410	tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
1411	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
1412
1413	for (i = 0; i < 11; i++)
1414		values_to_save[i] =
1415			read_radio_reg(pi, rxiq_cal_rf_reg[i]);
1416	Core1TxControl_old = read_phy_reg(pi, 0x631);
1417
1418	or_phy_reg(pi, 0x631, 0x0015);
1419
1420	RFOverride0_old = read_phy_reg(pi, 0x44c);
1421	RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
1422	rfoverride2_old = read_phy_reg(pi, 0x4b0);
1423	rfoverride2val_old = read_phy_reg(pi, 0x4b1);
1424	rfoverride3_old = read_phy_reg(pi, 0x4f9);
1425	rfoverride3val_old = read_phy_reg(pi, 0x4fa);
1426	rfoverride4_old = read_phy_reg(pi, 0x938);
1427	rfoverride4val_old = read_phy_reg(pi, 0x939);
1428	afectrlovr_old = read_phy_reg(pi, 0x43b);
1429	afectrlovrval_old = read_phy_reg(pi, 0x43c);
1430	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
1431	old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
1432
1433	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
1434	if (tx_gain_override_old) {
1435		wlc_lcnphy_get_tx_gain(pi, &old_gains);
1436		tx_gain_index_old = pi_lcn->lcnphy_current_index;
1437	}
1438
1439	wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
1440
1441	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
1442	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
1443
1444	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
1445	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
1446
1447	write_radio_reg(pi, RADIO_2064_REG116, 0x06);
1448	write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
1449	write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
1450	write_radio_reg(pi, RADIO_2064_REG098, 0x03);
1451	write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
1452	mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
1453	write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
1454	write_radio_reg(pi, RADIO_2064_REG114, 0x01);
1455	write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
1456	write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
1457
1458	mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
1459	mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
1460	mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
1461	mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
1462	mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
1463	mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
1464	mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
1465	mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
1466	mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
1467	mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
1468
1469	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
1470	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
1471
1472	write_phy_reg(pi, 0x6da, 0xffff);
1473	or_phy_reg(pi, 0x6db, 0x3);
1474
1475	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
1476	for (lna2_gain = 3; lna2_gain >= 0; lna2_gain--) {
1477		for (tia_gain = 4; tia_gain >= 0; tia_gain--) {
1478			for (biq1_gain = 6; biq1_gain >= 0; biq1_gain--) {
1479				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
1480								     (u16)
1481								     biq1_gain,
1482								     (u16)
1483								     tia_gain,
1484								     (u16)
1485								     lna2_gain);
1486				if (!set_gain)
1487					continue;
1488
1489				result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
1490				goto stop_tone;
1491			}
1492		}
1493	}
1494
1495stop_tone:
1496	wlc_lcnphy_stop_tx_tone(pi);
1497
1498	write_phy_reg(pi, 0x631, Core1TxControl_old);
1499
1500	write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
1501	write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
1502	write_phy_reg(pi, 0x4b0, rfoverride2_old);
1503	write_phy_reg(pi, 0x4b1, rfoverride2val_old);
1504	write_phy_reg(pi, 0x4f9, rfoverride3_old);
1505	write_phy_reg(pi, 0x4fa, rfoverride3val_old);
1506	write_phy_reg(pi, 0x938, rfoverride4_old);
1507	write_phy_reg(pi, 0x939, rfoverride4val_old);
1508	write_phy_reg(pi, 0x43b, afectrlovr_old);
1509	write_phy_reg(pi, 0x43c, afectrlovrval_old);
1510	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
1511	write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
1512
1513	wlc_lcnphy_clear_trsw_override(pi);
1514
1515	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
1516
1517	for (i = 0; i < 11; i++)
1518		write_radio_reg(pi, rxiq_cal_rf_reg[i],
1519				values_to_save[i]);
1520
1521	if (tx_gain_override_old)
1522		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
1523	else
1524		wlc_lcnphy_disable_tx_gain_override(pi);
1525
1526	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
1527	wlc_lcnphy_rx_gain_override_enable(pi, false);
1528
1529cal_done:
1530	kfree(ptr);
1531	return result;
1532}
1533
1534s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi)
1535{
1536	s8 index;
1537	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
1538
1539	if (txpwrctrl_off(pi))
1540		index = pi_lcn->lcnphy_current_index;
1541	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1542		index =	(s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(
1543			      pi) / 2);
1544	else
1545		index = pi_lcn->lcnphy_current_index;
1546	return index;
1547}
1548
1549void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel)
1550{
1551	u16 afectrlovr, afectrlovrval;
1552	afectrlovr = read_phy_reg(pi, 0x43b);
1553	afectrlovrval = read_phy_reg(pi, 0x43c);
1554	if (channel != 0) {
1555		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
1556
1557		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
1558
1559		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
1560
1561		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
1562
1563		write_phy_reg(pi, 0x44b, 0xffff);
1564		wlc_lcnphy_tx_pu(pi, 1);
1565
1566		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
1567
1568		or_phy_reg(pi, 0x6da, 0x0080);
1569
1570		or_phy_reg(pi, 0x00a, 0x228);
1571	} else {
1572		and_phy_reg(pi, 0x00a, ~(0x228));
1573
1574		and_phy_reg(pi, 0x6da, 0xFF7F);
1575		write_phy_reg(pi, 0x43b, afectrlovr);
1576		write_phy_reg(pi, 0x43c, afectrlovrval);
1577	}
1578}
1579
1580static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi)
1581{
1582	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
1583
1584	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
1585	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
1586
1587	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
1588	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
1589
1590	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
1591	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
1592
1593	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
1594	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
1595}
1596
1597static void
1598wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable)
1599{
1600	if (enable) {
1601		write_phy_reg(pi, 0x942, 0x7);
1602		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
1603		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
1604
1605		write_phy_reg(pi, 0x44a, 0x084);
1606		write_phy_reg(pi, 0x44a, 0x080);
1607		write_phy_reg(pi, 0x6d3, 0x2222);
1608		write_phy_reg(pi, 0x6d3, 0x2220);
1609	} else {
1610		write_phy_reg(pi, 0x942, 0x0);
1611		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
1612		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
1613	}
1614	wlapi_switch_macfreq(pi->sh->physhim, enable);
1615}
1616
1617static void
1618wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec)
1619{
1620	u8 channel = CHSPEC_CHANNEL(chanspec);
1621	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
1622
1623	if (channel == 14)
1624		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
1625	else
1626		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
1627
1628	pi_lcn->lcnphy_bandedge_corr = 2;
1629	if (channel == 1)
1630		pi_lcn->lcnphy_bandedge_corr = 4;
1631
1632	if (channel == 1 || channel == 2 || channel == 3 ||
1633	    channel == 4 || channel == 9 ||
1634	    channel == 10 || channel == 11 || channel == 12) {
1635		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
1636				      0x03000c04);
1637		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
1638					~0x00ffffff, 0x0);
1639		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
1640				      0x200005c0);
1641
1642		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
1643			      BCMA_CC_PMU_CTL_PLL_UPD);
1644		write_phy_reg(pi, 0x942, 0);
1645		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
1646		pi_lcn->lcnphy_spurmod = false;
1647		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
1648
1649		write_phy_reg(pi, 0x425, 0x5907);
1650	} else {
1651		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
1652				      0x03140c04);
1653		bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
1654					~0x00ffffff, 0x333333);
1655		bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
1656				      0x202c2820);
1657
1658		bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
1659			      BCMA_CC_PMU_CTL_PLL_UPD);
1660		write_phy_reg(pi, 0x942, 0);
1661		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
1662
1663		pi_lcn->lcnphy_spurmod = false;
1664		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
1665
1666		write_phy_reg(pi, 0x425, 0x590a);
1667	}
1668
1669	or_phy_reg(pi, 0x44a, 0x44);
1670	write_phy_reg(pi, 0x44a, 0x80);
1671}
1672
1673static void
1674wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
1675{
1676	uint i;
1677	const struct chan_info_2064_lcnphy *ci;
1678	u8 rfpll_doubler = 0;
1679	u8 pll_pwrup, pll_pwrup_ovr;
1680	s32 qFxtal, qFref, qFvco, qFcal;
1681	u8 d15, d16, f16, e44, e45;
1682	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
1683	u16 loop_bw, d30, setCount;
1684
1685	u8 h29, h28_ten, e30, h30_ten, cp_current;
1686	u16 g30, d28;
1687
1688	ci = &chan_info_2064_lcnphy[0];
1689	rfpll_doubler = 1;
1690
1691	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
1692
1693	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
1694	if (!rfpll_doubler) {
1695		loop_bw = PLL_2064_LOOP_BW;
1696		d30 = PLL_2064_D30;
1697	} else {
1698		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
1699		d30 = PLL_2064_D30_DOUBLER;
1700	}
1701
1702	if (CHSPEC_IS2G(pi->radio_chanspec)) {
1703		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
1704			if (chan_info_2064_lcnphy[i].chan == channel)
1705				break;
1706
1707		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy))
1708			return;
1709
1710		ci = &chan_info_2064_lcnphy[i];
1711	}
1712
1713	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
1714
1715	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
1716
1717	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
1718
1719	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
1720
1721	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
1722		      (ci->logen_rccr_rx) << 2);
1723
1724	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
1725
1726	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
1727		      (ci->pa_rxrf_lna2_freq_tune) << 4);
1728
1729	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
1730
1731	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
1732	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
1733
1734	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
1735
1736	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
1737	e44 = 0;
1738	e45 = 0;
1739
1740	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
1741	if (pi->xtalfreq > 26000000)
1742		e44 = 1;
1743	if (pi->xtalfreq > 52000000)
1744		e45 = 1;
1745	if (e44 == 0)
1746		fcal_div = 1;
1747	else if (e45 == 0)
1748		fcal_div = 2;
1749	else
1750		fcal_div = 4;
1751	fvco3 = (ci->freq * 3);
1752	fref3 = 2 * fpfd;
1753
1754	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
1755	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
1756	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
1757	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
1758
1759	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
1760
1761	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
1762	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
1763	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
1764
1765	d16 = (qFcal * 8 / (d15 + 1)) - 1;
1766	write_radio_reg(pi, RADIO_2064_REG051, d16);
1767
1768	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
1769	setCount = f16 * 3 * (ci->freq) / 32 - 1;
1770	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
1771		      (u8) (setCount >> 8));
1772
1773	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
1774	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
1775
1776	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
1777
1778	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
1779	while (div_frac >= fref3) {
1780		div_int++;
1781		div_frac -= fref3;
1782	}
1783	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
1784
1785	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
1786		      (u8) (div_int >> 4));
1787	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
1788		      (u8) (div_int << 4));
1789	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
1790		      (u8) (div_frac >> 16));
1791	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
1792	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
1793
1794	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
1795
1796	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
1797	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
1798	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
1799
1800	h29 = LCN_BW_LMT / loop_bw;
1801	d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
1802		(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
1803	       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
1804	      + PLL_2064_LOW_END_KVCO;
1805	h28_ten = (d28 * 10) / LCN_VCO_DIV;
1806	e30 = (d30 - LCN_OFFSET) / LCN_FACT;
1807	g30 = LCN_OFFSET + (e30 * LCN_FACT);
1808	h30_ten = (g30 * 10) / LCN_CUR_DIV;
1809	cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten;
1810	mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
1811
1812	if (channel >= 1 && channel <= 5)
1813		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
1814	else
1815		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
1816	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
1817
1818	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
1819	udelay(1);
1820
1821	wlc_2064_vco_cal(pi);
1822
1823	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
1824	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
1825	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
1826		write_radio_reg(pi, RADIO_2064_REG038, 3);
1827		write_radio_reg(pi, RADIO_2064_REG091, 7);
1828	}
1829
1830	if (!(pi->sh->boardflags & BFL_FEM)) {
1831		static const u8 reg038[14] = {
1832			0xd, 0xe, 0xd, 0xd, 0xd, 0xc, 0xa,
1833			0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0
1834		};
1835
1836		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
1837		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
1838		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
1839
1840		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
1841	}
1842}
1843
1844static int
1845wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
1846{
1847	s16 filt_index = -1;
1848	int j;
1849
1850	u16 addr[] = {
1851		0x910,
1852		0x91e,
1853		0x91f,
1854		0x924,
1855		0x925,
1856		0x926,
1857		0x920,
1858		0x921,
1859		0x927,
1860		0x928,
1861		0x929,
1862		0x922,
1863		0x923,
1864		0x930,
1865		0x931,
1866		0x932
1867	};
1868
1869	u16 addr_ofdm[] = {
1870		0x90f,
1871		0x900,
1872		0x901,
1873		0x906,
1874		0x907,
1875		0x908,
1876		0x902,
1877		0x903,
1878		0x909,
1879		0x90a,
1880		0x90b,
1881		0x904,
1882		0x905,
1883		0x90c,
1884		0x90d,
1885		0x90e
1886	};
1887
1888	if (!is_ofdm) {
1889		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
1890			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
1891				filt_index = (s16) j;
1892				break;
1893			}
1894		}
1895
1896		if (filt_index != -1) {
1897			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
1898				write_phy_reg(pi, addr[j],
1899					      LCNPHY_txdigfiltcoeffs_cck
1900					      [filt_index][j + 1]);
1901		}
1902	} else {
1903		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
1904			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
1905				filt_index = (s16) j;
1906				break;
1907			}
1908		}
1909
1910		if (filt_index != -1) {
1911			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
1912				write_phy_reg(pi, addr_ofdm[j],
1913					      LCNPHY_txdigfiltcoeffs_ofdm
1914					      [filt_index][j + 1]);
1915		}
1916	}
1917
1918	return (filt_index != -1) ? 0 : -1;
1919}
1920
1921static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
1922{
1923	u16 pa_gain;
1924
1925	pa_gain = (read_phy_reg(pi, 0x4fb) &
1926		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
1927		  LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
1928
1929	return pa_gain;
1930}
1931
1932static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
1933				   struct lcnphy_txgains *target_gains)
1934{
1935	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
1936
1937	mod_phy_reg(
1938		pi, 0x4b5,
1939		(0xffff << 0),
1940		((target_gains->gm_gain) |
1941		 (target_gains->pga_gain << 8)) <<
1942		0);
1943	mod_phy_reg(pi, 0x4fb,
1944		    (0x7fff << 0),
1945		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1946
1947	mod_phy_reg(
1948		pi, 0x4fc,
1949		(0xffff << 0),
1950		((target_gains->gm_gain) |
1951		 (target_gains->pga_gain << 8)) <<
1952		0);
1953	mod_phy_reg(pi, 0x4fd,
1954		    (0x7fff << 0),
1955		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1956
1957	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
1958
1959	wlc_lcnphy_enable_tx_gain_override(pi);
1960}
1961
1962static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
1963{
1964	u16 m0m1;
1965	struct phytbl_info tab;
1966
1967	tab.tbl_ptr = &m0m1;
1968	tab.tbl_len = 1;
1969	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1970	tab.tbl_offset = 87;
1971	tab.tbl_width = 16;
1972	wlc_lcnphy_read_table(pi, &tab);
1973
1974	return (u8) ((m0m1 & 0xff00) >> 8);
1975}
1976
1977static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0)
1978{
1979	u16 m0m1 = (u16) m0 << 8;
1980	struct phytbl_info tab;
1981
1982	tab.tbl_ptr = &m0m1;
1983	tab.tbl_len = 1;
1984	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1985	tab.tbl_offset = 87;
1986	tab.tbl_width = 16;
1987	wlc_lcnphy_write_table(pi, &tab);
1988}
1989
1990static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi)
1991{
1992	u32 data_buf[64];
1993	struct phytbl_info tab;
1994
1995	memset(data_buf, 0, sizeof(data_buf));
1996
1997	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1998	tab.tbl_width = 32;
1999	tab.tbl_ptr = data_buf;
2000
2001	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
2002
2003		tab.tbl_len = 30;
2004		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
2005		wlc_lcnphy_write_table(pi, &tab);
2006	}
2007
2008	tab.tbl_len = 64;
2009	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
2010	wlc_lcnphy_write_table(pi, &tab);
2011}
2012
2013enum lcnphy_tssi_mode {
2014	LCNPHY_TSSI_PRE_PA,
2015	LCNPHY_TSSI_POST_PA,
2016	LCNPHY_TSSI_EXT
2017};
2018
2019static void
2020wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
2021{
2022	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
2023
2024	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
2025
2026	if (LCNPHY_TSSI_POST_PA == pos) {
2027		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
2028
2029		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
2030
2031		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2032			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
2033		} else {
2034			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
2035			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
2036			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
2037			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
2038			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
2039			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
2040			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
2041			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
2042			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
2043			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
2044			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
2045			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
2046		}
2047	} else {
2048		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
2049
2050		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
2051
2052		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2053			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
2054		} else {
2055			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
2056			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
2057		}
2058	}
2059	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
2060
2061	if (LCNPHY_TSSI_EXT == pos) {
2062		write_radio_reg(pi, RADIO_2064_REG07F, 1);
2063		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
2064		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
2065		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
2066	}
2067}
2068
2069static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi)
2070{
2071	u16 N1, N2, N3, N4, N5, N6, N;
2072	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
2073	      >> 0);
2074	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
2075		   >> 12);
2076	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
2077	      >> 0);
2078	N4 = 1 << ((read_phy_reg(pi, 0x40d) &

Large files files are truncated, but you can click here to view the full file