iPXE
ath5k_phy.c File Reference
#include <unistd.h>
#include <stdlib.h>
#include "ath5k.h"
#include "reg.h"
#include "base.h"
#include "rfbuffer.h"
#include "rfgain.h"

Go to the source code of this file.

Macros

#define _ATH5K_PHY

Functions

 FILE_LICENCE (MIT)
 FILE_SECBOOT (FORBIDDEN)
static int min (int x, int y)
static int max (int x, int y)
static unsigned int ath5k_hw_rfb_op (struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, u32 val, u8 reg_id, int set)
int ath5k_hw_rfgain_opt_init (struct ath5k_hw *ah)
static void ath5k_hw_request_rfgain_probe (struct ath5k_hw *ah)
static u32 ath5k_hw_rf_gainf_corr (struct ath5k_hw *ah)
static int ath5k_hw_rf_check_gainf_readback (struct ath5k_hw *ah)
static s8 ath5k_hw_rf_gainf_adjust (struct ath5k_hw *ah)
enum ath5k_rfgain ath5k_hw_gainf_calibrate (struct ath5k_hw *ah)
int ath5k_hw_rfgain_init (struct ath5k_hw *ah, unsigned int freq)
int ath5k_hw_rfregs_init (struct ath5k_hw *ah, struct net80211_channel *channel, unsigned int mode)
int ath5k_channel_ok (struct ath5k_hw *ah, u16 freq, unsigned int flags)
static u32 ath5k_hw_rf5110_chan2athchan (struct net80211_channel *channel)
static int ath5k_hw_rf5110_channel (struct ath5k_hw *ah, struct net80211_channel *channel)
static int ath5k_hw_rf5111_chan2athchan (unsigned int ieee, struct ath5k_athchan_2ghz *athchan)
static int ath5k_hw_rf5111_channel (struct ath5k_hw *ah, struct net80211_channel *channel)
static int ath5k_hw_rf5112_channel (struct ath5k_hw *ah, struct net80211_channel *channel)
static int ath5k_hw_rf2425_channel (struct ath5k_hw *ah, struct net80211_channel *channel)
int ath5k_hw_channel (struct ath5k_hw *ah, struct net80211_channel *channel)
int ath5k_hw_noise_floor_calibration (struct ath5k_hw *ah, short freq)
 ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
static int ath5k_hw_rf5110_calibrate (struct ath5k_hw *ah, struct net80211_channel *channel)
static int ath5k_hw_rf511x_calibrate (struct ath5k_hw *ah, struct net80211_channel *channel)
int ath5k_hw_phy_calibrate (struct ath5k_hw *ah, struct net80211_channel *channel)
int ath5k_hw_phy_disable (struct ath5k_hw *ah)
u16 ath5k_hw_radio_revision (struct ath5k_hw *ah, unsigned int chan)
void ath5k_hw_set_def_antenna (struct ath5k_hw *ah, unsigned int ant)
unsigned int ath5k_hw_get_def_antenna (struct ath5k_hw *ah)
static s16 ath5k_get_interpolated_value (s16 target, s16 x_left, s16 x_right, s16 y_left, s16 y_right)
static s16 ath5k_get_linear_pcdac_min (const u8 *stepL, const u8 *stepR, const s16 *pwrL, const s16 *pwrR)
static void ath5k_create_power_curve (s16 pmin, s16 pmax, const s16 *pwr, const u8 *vpd, u8 num_points, u8 *vpd_table, u8 type)
static void ath5k_get_chan_pcal_surrounding_piers (struct ath5k_hw *ah, struct net80211_channel *channel, struct ath5k_chan_pcal_info **pcinfo_l, struct ath5k_chan_pcal_info **pcinfo_r)
static void ath5k_get_rate_pcal_data (struct ath5k_hw *ah, struct net80211_channel *channel, struct ath5k_rate_pcal_info *rates)
static void ath5k_get_max_ctl_power (struct ath5k_hw *ah, struct net80211_channel *channel)
static void ath5k_fill_pwr_to_pcdac_table (struct ath5k_hw *ah, s16 *table_min, s16 *table_max)
static void ath5k_combine_linear_pcdac_curves (struct ath5k_hw *ah, s16 *table_min, s16 *table_max, u8 pdcurves)
static void ath5k_setup_pcdac_table (struct ath5k_hw *ah)
static void ath5k_combine_pwr_to_pdadc_curves (struct ath5k_hw *ah, s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
static void ath5k_setup_pwr_to_pdadc_table (struct ath5k_hw *ah, u8 pdcurves, u8 *pdg_to_idx)
static int ath5k_setup_channel_powertable (struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 type)
static void ath5k_setup_rate_powertable (struct ath5k_hw *ah, u16 max_pwr, struct ath5k_rate_pcal_info *rate_info, u8 ee_mode)
int ath5k_hw_txpower (struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 txpower)
int ath5k_hw_set_txpower_limit (struct ath5k_hw *ah, u8 mode, u8 txpower)

Macro Definition Documentation

◆ _ATH5K_PHY

#define _ATH5K_PHY

Definition at line 28 of file ath5k_phy.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( MIT )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ min()

int min ( int x,
int y )
inlinestatic

Definition at line 39 of file ath5k_phy.c.

40{
41 return (x < y) ? x : y;
42}
static unsigned int unsigned int y
Definition pixbuf.h:63
static unsigned int x
Definition pixbuf.h:63

References x, and y.

◆ max()

int max ( int x,
int y )
inlinestatic

Definition at line 44 of file ath5k_phy.c.

45{
46 return (x > y) ? x : y;
47}

References x, and y.

◆ ath5k_hw_rfb_op()

unsigned int ath5k_hw_rfb_op ( struct ath5k_hw * ah,
const struct ath5k_rf_reg * rf_regs,
u32 val,
u8 reg_id,
int set )
static

Definition at line 52 of file ath5k_phy.c.

55{
56 const struct ath5k_rf_reg *rfreg = NULL;
57 u8 offset, bank, num_bits, col, position;
58 u16 entry;
59 u32 mask, data, last_bit, bits_shifted, first_bit;
60 u32 *rfb;
61 s32 bits_left;
62 unsigned i;
63
64 data = 0;
65 rfb = ah->ah_rf_banks;
66
67 for (i = 0; i < ah->ah_rf_regs_count; i++) {
68 if (rf_regs[i].index == reg_id) {
69 rfreg = &rf_regs[i];
70 break;
71 }
72 }
73
74 if (rfb == NULL || rfreg == NULL) {
75 DBG("ath5k: RF register not found!\n");
76 /* should not happen */
77 return 0;
78 }
79
80 bank = rfreg->bank;
81 num_bits = rfreg->field.len;
82 first_bit = rfreg->field.pos;
83 col = rfreg->field.col;
84
85 /* first_bit is an offset from bank's
86 * start. Since we have all banks on
87 * the same array, we use this offset
88 * to mark each bank's start */
89 offset = ah->ah_offset[bank];
90
91 /* Boundary check */
92 if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) {
93 DBG("ath5k: RF invalid values at offset %d\n", offset);
94 return 0;
95 }
96
97 entry = ((first_bit - 1) / 8) + offset;
98 position = (first_bit - 1) % 8;
99
100 if (set)
101 data = ath5k_hw_bitswap(val, num_bits);
102
103 for (bits_shifted = 0, bits_left = num_bits; bits_left > 0;
104 position = 0, entry++) {
105
106 last_bit = (position + bits_left > 8) ? 8 :
107 position + bits_left;
108
109 mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) <<
110 (col * 8);
111
112 if (set) {
113 rfb[entry] &= ~mask;
114 rfb[entry] |= ((data << position) << (col * 8)) & mask;
115 data >>= (8 - position);
116 } else {
117 data |= (((rfb[entry] & mask) >> (col * 8)) >> position)
118 << bits_shifted;
119 bits_shifted += last_bit - position;
120 }
121
122 bits_left -= 8 - position;
123 }
124
125 data = set ? 1 : ath5k_hw_bitswap(data, num_bits);
126
127 return data;
128}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
long index
Definition bigint.h:65
static u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
Definition ath5k.h:1267
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define u8
Definition igbvf_osdep.h:40
void __asmcall int val
Definition setjmp.h:12
int32_t s32
Definition stdint.h:23
struct option_descriptor set[0]
Definition nvo_cmd.c:112
uint8_t ah
Definition registers.h:1
struct ath5k_rfb_field field
Definition rfbuffer.h:75
#define u16
Definition vga.h:20
#define u32
Definition vga.h:21

References ah, ath5k_hw_bitswap(), ath5k_rf_reg::bank, ath5k_rfb_field::col, data, DBG, ath5k_rf_reg::field, index, ath5k_rfb_field::len, NULL, offset, ath5k_rfb_field::pos, set, u16, u32, u8, and val.

Referenced by ath5k_hw_rf_check_gainf_readback(), ath5k_hw_rf_gainf_corr(), and ath5k_hw_rfregs_init().

◆ ath5k_hw_rfgain_opt_init()

int ath5k_hw_rfgain_opt_init ( struct ath5k_hw * ah)

Definition at line 159 of file ath5k_phy.c.

160{
161 /* Initialize the gain optimization values */
162 switch (ah->ah_radio) {
163 case AR5K_RF5111:
164 ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
165 ah->ah_gain.g_low = 20;
166 ah->ah_gain.g_high = 35;
167 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
168 break;
169 case AR5K_RF5112:
170 ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
171 ah->ah_gain.g_low = 20;
172 ah->ah_gain.g_high = 85;
173 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
174 break;
175 default:
176 return -EINVAL;
177 }
178
179 return 0;
180}
@ AR5K_RFGAIN_ACTIVE
Definition ath5k.h:606
@ AR5K_RF5111
Definition ath5k.h:264
@ AR5K_RF5112
Definition ath5k.h:265
#define EINVAL
Invalid argument.
Definition errno.h:429
static const struct ath5k_gain_opt rfgain_opt_5112
Definition rfgain.h:504
static const struct ath5k_gain_opt rfgain_opt_5111
Definition rfgain.h:478

References ah, AR5K_RF5111, AR5K_RF5112, AR5K_RFGAIN_ACTIVE, EINVAL, rfgain_opt_5111, and rfgain_opt_5112.

Referenced by ath5k_hw_attach().

◆ ath5k_hw_request_rfgain_probe()

void ath5k_hw_request_rfgain_probe ( struct ath5k_hw * ah)
static

Definition at line 195 of file ath5k_phy.c.

196{
197
198 /* Skip if gain calibration is inactive or
199 * we already handle a probe request */
200 if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE)
201 return;
202
203 /* Send the packet with 2dB below max power as
204 * patent doc suggest */
205 ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max_pwr - 4,
208
209 ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED;
210
211}
#define AR5K_PHY_PAPD_PROBE_TX_NEXT
Definition reg.h:2241
#define AR5K_PHY_PAPD_PROBE
Definition reg.h:2235
#define AR5K_PHY_PAPD_PROBE_TXPOWER
Definition reg.h:2239
@ AR5K_RFGAIN_READ_REQUESTED
Definition ath5k.h:607
#define AR5K_REG_SM(_val, _flags)
Definition ath5k.h:86
static void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
Definition ath5k.h:1224

References ah, AR5K_PHY_PAPD_PROBE, AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE_TXPOWER, AR5K_REG_SM, AR5K_RFGAIN_ACTIVE, AR5K_RFGAIN_READ_REQUESTED, and ath5k_hw_reg_write().

Referenced by ath5k_hw_rf511x_calibrate().

◆ ath5k_hw_rf_gainf_corr()

u32 ath5k_hw_rf_gainf_corr ( struct ath5k_hw * ah)
static

Definition at line 215 of file ath5k_phy.c.

216{
217 u32 mix, step;
218 const struct ath5k_gain_opt *go;
219 const struct ath5k_gain_opt_step *g_step;
220 const struct ath5k_rf_reg *rf_regs;
221
222 /* Only RF5112 Rev. 2 supports it */
223 if ((ah->ah_radio != AR5K_RF5112) ||
224 (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A))
225 return 0;
226
227 go = &rfgain_opt_5112;
228 rf_regs = rf_regs_5112a;
229 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
230
231 g_step = &go->go_step[ah->ah_gain.g_step_idx];
232
233 if (ah->ah_rf_banks == NULL)
234 return 0;
235
236 ah->ah_gain.g_f_corr = 0;
237
238 /* No VGA (Variable Gain Amplifier) override, skip */
239 if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, 0) != 1)
240 return 0;
241
242 /* Mix gain stepping */
243 step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, 0);
244
245 /* Mix gain override */
246 mix = g_step->gos_param[0];
247
248 switch (mix) {
249 case 3:
250 ah->ah_gain.g_f_corr = step * 2;
251 break;
252 case 2:
253 ah->ah_gain.g_f_corr = (step - 5) * 2;
254 break;
255 case 1:
256 ah->ah_gain.g_f_corr = step;
257 break;
258 default:
259 ah->ah_gain.g_f_corr = 0;
260 break;
261 }
262
263 return ah->ah_gain.g_f_corr;
264}
#define AR5K_SREV_RAD_5112A
Definition ath5k.h:314
static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, u32 val, u8 reg_id, int set)
Definition ath5k_phy.c:52
#define ARRAY_SIZE(x)
Definition efx_common.h:43
void step(void)
Single-step a single process.
Definition process.c:99
@ AR5K_RF_MIXVGA_OVR
Definition rfbuffer.h:122
@ AR5K_RF_MIXGAIN_STEP
Definition rfbuffer.h:124
static const struct ath5k_rf_reg rf_regs_5112a[]
Definition rfbuffer.h:480
s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]
Definition rfgain.h:461
const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]
Definition rfgain.h:468

References ah, AR5K_RF5112, AR5K_RF_MIXGAIN_STEP, AR5K_RF_MIXVGA_OVR, AR5K_SREV_RAD_5112A, ARRAY_SIZE, ath5k_hw_rfb_op(), ath5k_gain_opt::go_step, ath5k_gain_opt_step::gos_param, NULL, rf_regs_5112a, rfgain_opt_5112, step(), and u32.

Referenced by ath5k_hw_gainf_calibrate().

◆ ath5k_hw_rf_check_gainf_readback()

int ath5k_hw_rf_check_gainf_readback ( struct ath5k_hw * ah)
static

Definition at line 270 of file ath5k_phy.c.

271{
272 const struct ath5k_rf_reg *rf_regs;
273 u32 step, mix_ovr, level[4];
274
275 if (ah->ah_rf_banks == NULL)
276 return 0;
277
278 if (ah->ah_radio == AR5K_RF5111) {
279
280 rf_regs = rf_regs_5111;
281 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
282
284 0);
285
286 level[0] = 0;
287 level[1] = (step == 63) ? 50 : step + 4;
288 level[2] = (step != 63) ? 64 : level[0];
289 level[3] = level[2] + 50 ;
290
291 ah->ah_gain.g_high = level[3] -
293 ah->ah_gain.g_low = level[0] +
295 } else {
296
297 rf_regs = rf_regs_5112;
298 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
299
300 mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR,
301 0);
302
303 level[0] = level[2] = 0;
304
305 if (mix_ovr == 1) {
306 level[1] = level[3] = 83;
307 } else {
308 level[1] = level[3] = 107;
309 ah->ah_gain.g_high = 55;
310 }
311 }
312
313 return (ah->ah_gain.g_current >= level[0] &&
314 ah->ah_gain.g_current <= level[1]) ||
315 (ah->ah_gain.g_current >= level[2] &&
316 ah->ah_gain.g_current <= level[3]);
317}
@ AR5K_RF_RFGAIN_STEP
Definition rfbuffer.h:118
static const struct ath5k_rf_reg rf_regs_5111[]
Definition rfbuffer.h:161
static const struct ath5k_rf_reg rf_regs_5112[]
Definition rfbuffer.h:310
#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN
Definition rfgain.h:450
#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN
Definition rfgain.h:449

References ah, AR5K_GAIN_DYN_ADJUST_HI_MARGIN, AR5K_GAIN_DYN_ADJUST_LO_MARGIN, AR5K_RF5111, AR5K_RF_MIXVGA_OVR, AR5K_RF_RFGAIN_STEP, ARRAY_SIZE, ath5k_hw_rfb_op(), NULL, rf_regs_5111, rf_regs_5112, step(), and u32.

Referenced by ath5k_hw_gainf_calibrate().

◆ ath5k_hw_rf_gainf_adjust()

s8 ath5k_hw_rf_gainf_adjust ( struct ath5k_hw * ah)
static

Definition at line 321 of file ath5k_phy.c.

322{
323 const struct ath5k_gain_opt *go;
324 const struct ath5k_gain_opt_step *g_step;
325 int ret = 0;
326
327 switch (ah->ah_radio) {
328 case AR5K_RF5111:
329 go = &rfgain_opt_5111;
330 break;
331 case AR5K_RF5112:
332 go = &rfgain_opt_5112;
333 break;
334 default:
335 return 0;
336 }
337
338 g_step = &go->go_step[ah->ah_gain.g_step_idx];
339
340 if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
341
342 /* Reached maximum */
343 if (ah->ah_gain.g_step_idx == 0)
344 return -1;
345
346 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
347 ah->ah_gain.g_target >= ah->ah_gain.g_high &&
348 ah->ah_gain.g_step_idx > 0;
349 g_step = &go->go_step[ah->ah_gain.g_step_idx])
350 ah->ah_gain.g_target -= 2 *
351 (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
352 g_step->gos_gain);
353
354 ret = 1;
355 goto done;
356 }
357
358 if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
359
360 /* Reached minimum */
361 if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
362 return -2;
363
364 for (ah->ah_gain.g_target = ah->ah_gain.g_current;
365 ah->ah_gain.g_target <= ah->ah_gain.g_low &&
366 ah->ah_gain.g_step_idx < go->go_steps_count-1;
367 g_step = &go->go_step[ah->ah_gain.g_step_idx])
368 ah->ah_gain.g_target -= 2 *
369 (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
370 g_step->gos_gain);
371
372 ret = 2;
373 goto done;
374 }
375
376done:
377 DBG2("ath5k RF adjust: ret %d, gain step %d, current gain %d, "
378 "target gain %d\n", ret, ah->ah_gain.g_step_idx,
379 ah->ah_gain.g_current, ah->ah_gain.g_target);
380
381 return ret;
382}
struct bofm_section_header done
Definition bofm_test.c:46
#define DBG2(...)
Definition compiler.h:515
u8 go_steps_count
Definition rfgain.h:467

References ah, AR5K_RF5111, AR5K_RF5112, DBG2, done, ath5k_gain_opt::go_step, ath5k_gain_opt::go_steps_count, ath5k_gain_opt_step::gos_gain, rfgain_opt_5111, and rfgain_opt_5112.

Referenced by ath5k_hw_gainf_calibrate().

◆ ath5k_hw_gainf_calibrate()

enum ath5k_rfgain ath5k_hw_gainf_calibrate ( struct ath5k_hw * ah)

Definition at line 390 of file ath5k_phy.c.

391{
392 u32 data, type;
393 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
394
395 if (ah->ah_rf_banks == NULL ||
396 ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE)
398
399 /* No check requested, either engine is inactive
400 * or an adjustment is already requested */
401 if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED)
402 goto done;
403
404 /* Read the PAPD (Peak to Average Power Detector)
405 * register */
407
408 /* No probe is scheduled, read gain_F measurement */
410 ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
412
413 /* If tx packet is CCK correct the gain_F measurement
414 * by cck ofdm gain delta */
416 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
417 ah->ah_gain.g_current +=
419 else
420 ah->ah_gain.g_current +=
422 }
423
424 /* Further correct gain_F measurement for
425 * RF5112A radios */
426 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
428 ah->ah_gain.g_current =
429 ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
430 (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
431 0;
432 }
433
434 /* Check if measurement is ok and if we need
435 * to adjust gain, schedule a gain adjustment,
436 * else switch back to the acive state */
438 AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
440 ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE;
441 } else {
442 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
443 }
444 }
445
446done:
447 return ah->ah_gain.g_state;
448}
#define AR5K_PHY_PAPD_PROBE_TYPE
Definition reg.h:2243
#define AR5K_PHY_PAPD_PROBE_TYPE_CCK
Definition reg.h:2247
#define AR5K_PHY_PAPD_PROBE_GAINF_S
Definition reg.h:2249
@ AR5K_RFGAIN_INACTIVE
Definition ath5k.h:605
@ AR5K_RFGAIN_NEED_CHANGE
Definition ath5k.h:608
#define AR5K_REG_MS(_val, _flags)
Definition ath5k.h:90
static u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
Definition ath5k.h:1216
static int ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)
Definition ath5k_phy.c:270
static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)
Definition ath5k_phy.c:321
static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah)
Definition ath5k_phy.c:215
uint32_t type
Operating system type.
Definition ena.h:1
#define AR5K_GAIN_CCK_PROBE_CORR
Definition rfgain.h:451
#define AR5K_GAIN_CHECK_ADJUST(_g)
Definition rfgain.h:457
u16 ee_cck_ofdm_gain_delta
Definition eeprom.h:391

References ah, AR5K_GAIN_CCK_PROBE_CORR, AR5K_GAIN_CHECK_ADJUST, AR5K_PHY_PAPD_PROBE, AR5K_PHY_PAPD_PROBE_GAINF_S, AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE_TYPE, AR5K_PHY_PAPD_PROBE_TYPE_CCK, AR5K_REG_MS, AR5K_RFGAIN_ACTIVE, AR5K_RFGAIN_INACTIVE, AR5K_RFGAIN_NEED_CHANGE, AR5K_RFGAIN_READ_REQUESTED, AR5K_SREV_RAD_5112A, ath5k_hw_reg_read(), ath5k_hw_rf_check_gainf_readback(), ath5k_hw_rf_gainf_adjust(), ath5k_hw_rf_gainf_corr(), data, done, ath5k_eeprom_info::ee_cck_ofdm_gain_delta, NULL, type, and u32.

Referenced by ath5k_calibrate(), and ath5k_hw_reset().

◆ ath5k_hw_rfgain_init()

int ath5k_hw_rfgain_init ( struct ath5k_hw * ah,
unsigned int freq )

Definition at line 453 of file ath5k_phy.c.

454{
455 const struct ath5k_ini_rfgain *ath5k_rfg;
456 unsigned int i, size;
457
458 switch (ah->ah_radio) {
459 case AR5K_RF5111:
460 ath5k_rfg = rfgain_5111;
462 break;
463 case AR5K_RF5112:
464 ath5k_rfg = rfgain_5112;
466 break;
467 case AR5K_RF2413:
468 ath5k_rfg = rfgain_2413;
470 break;
471 case AR5K_RF2316:
472 ath5k_rfg = rfgain_2316;
474 break;
475 case AR5K_RF5413:
476 ath5k_rfg = rfgain_5413;
478 break;
479 case AR5K_RF2317:
480 case AR5K_RF2425:
481 ath5k_rfg = rfgain_2425;
483 break;
484 default:
485 return -EINVAL;
486 }
487
488 switch (freq) {
491 break;
492 default:
493 return -EINVAL;
494 }
495
496 for (i = 0; i < size; i++) {
497 AR5K_REG_WAIT(i);
498 ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
499 (u32)ath5k_rfg[i].rfg_register);
500 }
501
502 return 0;
503}
#define AR5K_INI_RFGAIN_2GHZ
Definition ath5k.h:142
#define AR5K_INI_RFGAIN_5GHZ
Definition ath5k.h:141
@ AR5K_RF2425
Definition ath5k.h:270
@ AR5K_RF2316
Definition ath5k.h:268
@ AR5K_RF5413
Definition ath5k.h:267
@ AR5K_RF2317
Definition ath5k.h:269
@ AR5K_RF2413
Definition ath5k.h:266
#define AR5K_REG_WAIT(_i)
Definition ath5k.h:135
uint16_t size
Buffer size.
Definition dwmac.h:3
static const struct ath5k_ini_rfgain rfgain_2413[]
Definition rfgain.h:172
static const struct ath5k_ini_rfgain rfgain_5413[]
Definition rfgain.h:309
static const struct ath5k_ini_rfgain rfgain_2425[]
Definition rfgain.h:379
static const struct ath5k_ini_rfgain rfgain_5112[]
Definition rfgain.h:103
static const struct ath5k_ini_rfgain rfgain_2316[]
Definition rfgain.h:240
static const struct ath5k_ini_rfgain rfgain_5111[]
Definition rfgain.h:34
u32 rfg_value[2]
Definition rfgain.h:30

References ah, AR5K_INI_RFGAIN_2GHZ, AR5K_INI_RFGAIN_5GHZ, AR5K_REG_WAIT, AR5K_RF2316, AR5K_RF2317, AR5K_RF2413, AR5K_RF2425, AR5K_RF5111, AR5K_RF5112, AR5K_RF5413, ARRAY_SIZE, ath5k_hw_reg_write(), EINVAL, ath5k_ini_rfgain::rfg_register, ath5k_ini_rfgain::rfg_value, rfgain_2316, rfgain_2413, rfgain_2425, rfgain_5111, rfgain_5112, rfgain_5413, size, and u32.

Referenced by ath5k_hw_reset().

◆ ath5k_hw_rfregs_init()

int ath5k_hw_rfregs_init ( struct ath5k_hw * ah,
struct net80211_channel * channel,
unsigned int mode )

Definition at line 515 of file ath5k_phy.c.

517{
518 const struct ath5k_rf_reg *rf_regs;
519 const struct ath5k_ini_rfbuffer *ini_rfb;
520 const struct ath5k_gain_opt *go = NULL;
521 const struct ath5k_gain_opt_step *g_step;
522 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
523 u8 ee_mode = 0;
524 u32 *rfb;
525 int obdb = -1, bank = -1;
526 unsigned i;
527
528 switch (ah->ah_radio) {
529 case AR5K_RF5111:
530 rf_regs = rf_regs_5111;
531 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111);
532 ini_rfb = rfb_5111;
533 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111);
534 go = &rfgain_opt_5111;
535 break;
536 case AR5K_RF5112:
537 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
538 rf_regs = rf_regs_5112a;
539 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a);
540 ini_rfb = rfb_5112a;
541 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a);
542 } else {
543 rf_regs = rf_regs_5112;
544 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112);
545 ini_rfb = rfb_5112;
546 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112);
547 }
548 go = &rfgain_opt_5112;
549 break;
550 case AR5K_RF2413:
551 rf_regs = rf_regs_2413;
552 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413);
553 ini_rfb = rfb_2413;
554 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413);
555 break;
556 case AR5K_RF2316:
557 rf_regs = rf_regs_2316;
558 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316);
559 ini_rfb = rfb_2316;
560 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316);
561 break;
562 case AR5K_RF5413:
563 rf_regs = rf_regs_5413;
564 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413);
565 ini_rfb = rfb_5413;
566 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413);
567 break;
568 case AR5K_RF2317:
569 rf_regs = rf_regs_2425;
570 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
571 ini_rfb = rfb_2317;
572 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317);
573 break;
574 case AR5K_RF2425:
575 rf_regs = rf_regs_2425;
576 ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425);
577 if (ah->ah_mac_srev < AR5K_SREV_AR2417) {
578 ini_rfb = rfb_2425;
579 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425);
580 } else {
581 ini_rfb = rfb_2417;
582 ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417);
583 }
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 /* If it's the first time we set rf buffer, allocate
590 * ah->ah_rf_banks based on ah->ah_rf_banks_size
591 * we set above */
592 if (ah->ah_rf_banks == NULL) {
593 ah->ah_rf_banks = malloc(sizeof(u32) * ah->ah_rf_banks_size);
594 if (ah->ah_rf_banks == NULL) {
595 return -ENOMEM;
596 }
597 }
598
599 /* Copy values to modify them */
600 rfb = ah->ah_rf_banks;
601
602 for (i = 0; i < ah->ah_rf_banks_size; i++) {
603 if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) {
604 DBG("ath5k: invalid RF register bank\n");
605 return -EINVAL;
606 }
607
608 /* Bank changed, write down the offset */
609 if (bank != ini_rfb[i].rfb_bank) {
610 bank = ini_rfb[i].rfb_bank;
611 ah->ah_offset[bank] = i;
612 }
613
614 rfb[i] = ini_rfb[i].rfb_mode_data[mode];
615 }
616
617 /* Set Output and Driver bias current (OB/DB) */
618 if (channel->hw_value & CHANNEL_2GHZ) {
619
620 if (channel->hw_value & CHANNEL_CCK)
621 ee_mode = AR5K_EEPROM_MODE_11B;
622 else
623 ee_mode = AR5K_EEPROM_MODE_11G;
624
625 /* For RF511X/RF211X combination we
626 * use b_OB and b_DB parameters stored
627 * in eeprom on ee->ee_ob[ee_mode][0]
628 *
629 * For all other chips we use OB/DB for 2Ghz
630 * stored in the b/g modal section just like
631 * 802.11a on ee->ee_ob[ee_mode][1] */
632 if ((ah->ah_radio == AR5K_RF5111) ||
633 (ah->ah_radio == AR5K_RF5112))
634 obdb = 0;
635 else
636 obdb = 1;
637
638 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
639 AR5K_RF_OB_2GHZ, 1);
640
641 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
642 AR5K_RF_DB_2GHZ, 1);
643
644 /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
645 } else if ((channel->hw_value & CHANNEL_5GHZ) ||
646 (ah->ah_radio == AR5K_RF5111)) {
647
648 /* For 11a, Turbo and XR we need to choose
649 * OB/DB based on frequency range */
650 ee_mode = AR5K_EEPROM_MODE_11A;
651 obdb = channel->center_freq >= 5725 ? 3 :
652 (channel->center_freq >= 5500 ? 2 :
653 (channel->center_freq >= 5260 ? 1 :
654 (channel->center_freq > 4000 ? 0 : -1)));
655
656 if (obdb < 0)
657 return -EINVAL;
658
659 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb],
660 AR5K_RF_OB_5GHZ, 1);
661
662 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb],
663 AR5K_RF_DB_5GHZ, 1);
664 }
665
666 g_step = &go->go_step[ah->ah_gain.g_step_idx];
667
668 /* Bank Modifications (chip-specific) */
669 if (ah->ah_radio == AR5K_RF5111) {
670
671 /* Set gain_F settings according to current step */
672 if (channel->hw_value & CHANNEL_OFDM) {
673
676 g_step->gos_param[0]);
677
678 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
679 AR5K_RF_PWD_90, 1);
680
681 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
682 AR5K_RF_PWD_84, 1);
683
684 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
686
687 /* We programmed gain_F parameters, switch back
688 * to active state */
689 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
690
691 }
692
693 /* Bank 6/7 setup */
694
695 ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode],
696 AR5K_RF_PWD_XPD, 1);
697
698 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode],
700
701 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
702 AR5K_RF_GAIN_I, 1);
703
704 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
705 AR5K_RF_PLO_SEL, 1);
706
707 /* TODO: Half/quarter channel support */
708 }
709
710 if (ah->ah_radio == AR5K_RF5112) {
711
712 /* Set gain_F settings according to current step */
713 if (channel->hw_value & CHANNEL_OFDM) {
714
715 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
717
718 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1],
719 AR5K_RF_PWD_138, 1);
720
721 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2],
722 AR5K_RF_PWD_137, 1);
723
724 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3],
725 AR5K_RF_PWD_136, 1);
726
727 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4],
728 AR5K_RF_PWD_132, 1);
729
730 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5],
731 AR5K_RF_PWD_131, 1);
732
733 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6],
734 AR5K_RF_PWD_130, 1);
735
736 /* We programmed gain_F parameters, switch back
737 * to active state */
738 ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE;
739 }
740
741 /* Bank 6/7 setup */
742
743 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode],
744 AR5K_RF_XPD_SEL, 1);
745
746 if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
747 /* Rev. 1 supports only one xpd */
748 ath5k_hw_rfb_op(ah, rf_regs,
749 ee->ee_x_gain[ee_mode],
751
752 } else {
753 /* TODO: Set high and low gain bits */
754 ath5k_hw_rfb_op(ah, rf_regs,
755 ee->ee_x_gain[ee_mode],
757 ath5k_hw_rfb_op(ah, rf_regs,
758 ee->ee_x_gain[ee_mode],
760
761 /* Lower synth voltage on Rev 2 */
762 ath5k_hw_rfb_op(ah, rf_regs, 2,
764
765 ath5k_hw_rfb_op(ah, rf_regs, 2,
767
768 ath5k_hw_rfb_op(ah, rf_regs, 2,
770
771 ath5k_hw_rfb_op(ah, rf_regs, 2,
772 AR5K_RF_PUSH_UP, 1);
773
774 /* Decrease power consumption on 5213+ BaseBand */
775 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
776 ath5k_hw_rfb_op(ah, rf_regs, 1,
777 AR5K_RF_PAD2GND, 1);
778
779 ath5k_hw_rfb_op(ah, rf_regs, 1,
780 AR5K_RF_XB2_LVL, 1);
781
782 ath5k_hw_rfb_op(ah, rf_regs, 1,
783 AR5K_RF_XB5_LVL, 1);
784
785 ath5k_hw_rfb_op(ah, rf_regs, 1,
786 AR5K_RF_PWD_167, 1);
787
788 ath5k_hw_rfb_op(ah, rf_regs, 1,
789 AR5K_RF_PWD_166, 1);
790 }
791 }
792
793 ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode],
794 AR5K_RF_GAIN_I, 1);
795
796 /* TODO: Half/quarter channel support */
797
798 }
799
800 if (ah->ah_radio == AR5K_RF5413 &&
801 channel->hw_value & CHANNEL_2GHZ) {
802
804 1);
805
806 /* Set optimum value for early revisions (on pci-e chips) */
807 if (ah->ah_mac_srev >= AR5K_SREV_AR5424 &&
808 ah->ah_mac_srev < AR5K_SREV_AR5413)
809 ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3),
811
812 }
813
814 /* Write RF banks on hw */
815 for (i = 0; i < ah->ah_rf_banks_size; i++) {
816 AR5K_REG_WAIT(i);
817 ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register);
818 }
819
820 return 0;
821}
#define AR5K_EEPROM_MODE_11A
Definition eeprom.h:64
#define AR5K_EEPROM_MODE_11B
Definition eeprom.h:65
#define AR5K_EEPROM_MODE_11G
Definition eeprom.h:66
#define AR5K_PHY_FRAME_CTL_TX_CLIP
Definition reg.h:2271
#define AR5K_PHY_FRAME_CTL
Definition reg.h:2268
#define AR5K_SREV_AR5413
Definition ath5k.h:301
#define CHANNEL_CCK
Definition ath5k.h:632
#define CHANNEL_5GHZ
Definition ath5k.h:635
#define AR5K_MAX_RF_BANKS
Definition ath5k.h:952
#define CHANNEL_OFDM
Definition ath5k.h:633
#define AR5K_SREV_PHY_5212A
Definition ath5k.h:329
#define AR5K_SREV_AR2417
Definition ath5k.h:307
#define AR5K_SREV_AR5424
Definition ath5k.h:300
#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val)
Definition ath5k.h:98
#define CHANNEL_2GHZ
Definition ath5k.h:634
uint16_t mode
Acceleration mode.
Definition ena.h:15
#define ENOMEM
Not enough space.
Definition errno.h:535
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
static const struct ath5k_rf_reg rf_regs_2316[]
Definition rfbuffer.h:732
static const struct ath5k_rf_reg rf_regs_5413[]
Definition rfbuffer.h:828
static const struct ath5k_ini_rfbuffer rfb_5112[]
Definition rfbuffer.h:338
static const struct ath5k_ini_rfbuffer rfb_5413[]
Definition rfbuffer.h:838
static const struct ath5k_rf_reg rf_regs_2425[]
Definition rfbuffer.h:939
@ AR5K_RF_PWD_90
Definition rfbuffer.h:104
@ AR5K_RF_GAIN_I
Definition rfbuffer.h:115
@ AR5K_RF_MIXGAIN_OVR
Definition rfbuffer.h:123
@ AR5K_RF_RFGAIN_SEL
Definition rfbuffer.h:117
@ AR5K_RF_XB5_LVL
Definition rfbuffer.h:101
@ AR5K_RF_DB_2GHZ
Definition rfbuffer.h:86
@ AR5K_RF_LOW_VC_CP
Definition rfbuffer.h:97
@ AR5K_RF_PWD_ICLOBUF_2G
Definition rfbuffer.h:102
@ AR5K_RF_PWD_130
Definition rfbuffer.h:105
@ AR5K_RF_OB_5GHZ
Definition rfbuffer.h:85
@ AR5K_RF_OB_2GHZ
Definition rfbuffer.h:84
@ AR5K_RF_PWD_167
Definition rfbuffer.h:112
@ AR5K_RF_PD_GAIN_LO
Definition rfbuffer.h:93
@ AR5K_RF_PD_GAIN_HI
Definition rfbuffer.h:94
@ AR5K_RF_PWD_XPD
Definition rfbuffer.h:90
@ AR5K_RF_HIGH_VC_CP
Definition rfbuffer.h:95
@ AR5K_RF_PWD_84
Definition rfbuffer.h:103
@ AR5K_RF_MID_VC_CP
Definition rfbuffer.h:96
@ AR5K_RF_XB2_LVL
Definition rfbuffer.h:100
@ AR5K_RF_PWD_131
Definition rfbuffer.h:106
@ AR5K_RF_PWD_138
Definition rfbuffer.h:110
@ AR5K_RF_PLO_SEL
Definition rfbuffer.h:116
@ AR5K_RF_XPD_GAIN
Definition rfbuffer.h:92
@ AR5K_RF_PUSH_UP
Definition rfbuffer.h:98
@ AR5K_RF_PAD2GND
Definition rfbuffer.h:99
@ AR5K_RF_PWD_136
Definition rfbuffer.h:108
@ AR5K_RF_XPD_SEL
Definition rfbuffer.h:91
@ AR5K_RF_PWD_132
Definition rfbuffer.h:107
@ AR5K_RF_PWD_166
Definition rfbuffer.h:111
@ AR5K_RF_PWD_137
Definition rfbuffer.h:109
@ AR5K_RF_DERBY_CHAN_SEL_MODE
Definition rfbuffer.h:113
@ AR5K_RF_DB_5GHZ
Definition rfbuffer.h:87
static const struct ath5k_ini_rfbuffer rfb_2417[]
Definition rfbuffer.h:1108
static const struct ath5k_ini_rfbuffer rfb_2317[]
Definition rfbuffer.h:1027
static const struct ath5k_ini_rfbuffer rfb_2316[]
Definition rfbuffer.h:738
static const struct ath5k_rf_reg rf_regs_2413[]
Definition rfbuffer.h:644
static const struct ath5k_ini_rfbuffer rfb_2425[]
Definition rfbuffer.h:947
static const struct ath5k_ini_rfbuffer rfb_5112a[]
Definition rfbuffer.h:518
static const struct ath5k_ini_rfbuffer rfb_2413[]
Definition rfbuffer.h:652
static const struct ath5k_ini_rfbuffer rfb_5111[]
Definition rfbuffer.h:180
u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]
Definition eeprom.h:404
u16 ee_i_gain[AR5K_EEPROM_N_MODES]
Definition eeprom.h:413
u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]
Definition eeprom.h:405
u16 ee_x_gain[AR5K_EEPROM_N_MODES]
Definition eeprom.h:412
u16 ee_xpd[AR5K_EEPROM_N_MODES]
Definition eeprom.h:411
u32 rfb_mode_data[5]
Definition rfbuffer.h:55

References ah, AR5K_EEPROM_MODE_11A, AR5K_EEPROM_MODE_11B, AR5K_EEPROM_MODE_11G, AR5K_MAX_RF_BANKS, AR5K_PHY_FRAME_CTL, AR5K_PHY_FRAME_CTL_TX_CLIP, AR5K_REG_WAIT, AR5K_REG_WRITE_BITS, AR5K_RF2316, AR5K_RF2317, AR5K_RF2413, AR5K_RF2425, AR5K_RF5111, AR5K_RF5112, AR5K_RF5413, AR5K_RF_DB_2GHZ, AR5K_RF_DB_5GHZ, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF_GAIN_I, AR5K_RF_HIGH_VC_CP, AR5K_RF_LOW_VC_CP, AR5K_RF_MID_VC_CP, AR5K_RF_MIXGAIN_OVR, AR5K_RF_OB_2GHZ, AR5K_RF_OB_5GHZ, AR5K_RF_PAD2GND, AR5K_RF_PD_GAIN_HI, AR5K_RF_PD_GAIN_LO, AR5K_RF_PLO_SEL, AR5K_RF_PUSH_UP, AR5K_RF_PWD_130, AR5K_RF_PWD_131, AR5K_RF_PWD_132, AR5K_RF_PWD_136, AR5K_RF_PWD_137, AR5K_RF_PWD_138, AR5K_RF_PWD_166, AR5K_RF_PWD_167, AR5K_RF_PWD_84, AR5K_RF_PWD_90, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF_PWD_XPD, AR5K_RF_RFGAIN_SEL, AR5K_RF_XB2_LVL, AR5K_RF_XB5_LVL, AR5K_RF_XPD_GAIN, AR5K_RF_XPD_SEL, AR5K_RFGAIN_ACTIVE, AR5K_SREV_AR2417, AR5K_SREV_AR5413, AR5K_SREV_AR5424, AR5K_SREV_PHY_5212A, AR5K_SREV_RAD_5112A, ARRAY_SIZE, ath5k_hw_bitswap(), ath5k_hw_reg_write(), ath5k_hw_rfb_op(), channel, CHANNEL_2GHZ, CHANNEL_5GHZ, CHANNEL_CCK, CHANNEL_OFDM, DBG, ath5k_eeprom_info::ee_db, ath5k_eeprom_info::ee_i_gain, ath5k_eeprom_info::ee_ob, ath5k_eeprom_info::ee_x_gain, ath5k_eeprom_info::ee_xpd, EINVAL, ENOMEM, ath5k_gain_opt::go_step, ath5k_gain_opt_step::gos_param, malloc(), mode, NULL, rf_regs_2316, rf_regs_2413, rf_regs_2425, rf_regs_5111, rf_regs_5112, rf_regs_5112a, rf_regs_5413, rfb_2316, rfb_2317, rfb_2413, rfb_2417, rfb_2425, rfb_5111, rfb_5112, rfb_5112a, rfb_5413, ath5k_ini_rfbuffer::rfb_bank, ath5k_ini_rfbuffer::rfb_mode_data, rfgain_opt_5111, rfgain_opt_5112, u32, and u8.

Referenced by ath5k_hw_reset().

◆ ath5k_channel_ok()

int ath5k_channel_ok ( struct ath5k_hw * ah,
u16 freq,
unsigned int flags )

Definition at line 831 of file ath5k_phy.c.

832{
833 /* Check if the channel is in our supported range */
834 if (flags & CHANNEL_2GHZ) {
835 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
836 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
837 return 1;
838 } else if (flags & CHANNEL_5GHZ)
839 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
840 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
841 return 1;
842
843 return 0;
844}
uint8_t flags
Flags.
Definition ena.h:7

References ah, CHANNEL_2GHZ, CHANNEL_5GHZ, flags, and u16.

Referenced by ath5k_copy_channels(), and ath5k_hw_channel().

◆ ath5k_hw_rf5110_chan2athchan()

u32 ath5k_hw_rf5110_chan2athchan ( struct net80211_channel * channel)
static

Definition at line 849 of file ath5k_phy.c.

850{
851 u32 athchan;
852
853 /*
854 * Convert IEEE channel/MHz to an internal channel value used
855 * by the AR5210 chipset. This has not been verified with
856 * newer chipsets like the AR5212A who have a completely
857 * different RF/PHY part.
858 */
859 athchan = (ath5k_hw_bitswap((ath5k_freq_to_channel(channel->center_freq)
860 - 24) / 2, 5) << 1)
861 | (1 << 6) | 0x1;
862 return athchan;
863}

References ath5k_hw_bitswap(), channel, and u32.

Referenced by ath5k_hw_rf5110_channel().

◆ ath5k_hw_rf5110_channel()

int ath5k_hw_rf5110_channel ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 868 of file ath5k_phy.c.

870{
871 u32 data;
872
873 /*
874 * Set the channel and wait
875 */
879 mdelay(1);
880
881 return 0;
882}
#define AR5K_RF_BUFFER_CONTROL_0
Definition reg.h:2121
#define AR5K_RF_BUFFER
Definition reg.h:2120
static u32 ath5k_hw_rf5110_chan2athchan(struct net80211_channel *channel)
Definition ath5k_phy.c:849
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79

References ah, AR5K_RF_BUFFER, AR5K_RF_BUFFER_CONTROL_0, ath5k_hw_reg_write(), ath5k_hw_rf5110_chan2athchan(), channel, data, mdelay(), and u32.

Referenced by ath5k_hw_channel().

◆ ath5k_hw_rf5111_chan2athchan()

int ath5k_hw_rf5111_chan2athchan ( unsigned int ieee,
struct ath5k_athchan_2ghz * athchan )
static

Definition at line 887 of file ath5k_phy.c.

889{
890 int channel;
891
892 /* Cast this value to catch negative channel numbers (>= -19) */
893 channel = (int)ieee;
894
895 /*
896 * Map 2GHz IEEE channel to 5GHz Atheros channel
897 */
898 if (channel <= 13) {
899 athchan->a2_athchan = 115 + channel;
900 athchan->a2_flags = 0x46;
901 } else if (channel == 14) {
902 athchan->a2_athchan = 124;
903 athchan->a2_flags = 0x44;
904 } else if (channel >= 15 && channel <= 26) {
905 athchan->a2_athchan = ((channel - 14) * 4) + 132;
906 athchan->a2_flags = 0x46;
907 } else
908 return -EINVAL;
909
910 return 0;
911}

References ath5k_athchan_2ghz::a2_athchan, ath5k_athchan_2ghz::a2_flags, channel, and EINVAL.

Referenced by ath5k_hw_rf5111_channel().

◆ ath5k_hw_rf5111_channel()

int ath5k_hw_rf5111_channel ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 916 of file ath5k_phy.c.

918{
919 struct ath5k_athchan_2ghz ath5k_channel_2ghz;
920 unsigned int ath5k_channel = ath5k_freq_to_channel(channel->center_freq);
921 u32 data0, data1, clock;
922 int ret;
923
924 /*
925 * Set the channel on the RF5111 radio
926 */
927 data0 = data1 = 0;
928
929 if (channel->hw_value & CHANNEL_2GHZ) {
930 /* Map 2GHz channel to 5GHz Atheros channel ID */
931 ret = ath5k_hw_rf5111_chan2athchan(ath5k_channel,
932 &ath5k_channel_2ghz);
933 if (ret)
934 return ret;
935
936 ath5k_channel = ath5k_channel_2ghz.a2_athchan;
937 data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
938 << 5) | (1 << 4);
939 }
940
941 if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
942 clock = 1;
943 data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
944 (clock << 1) | (1 << 10) | 1;
945 } else {
946 clock = 0;
947 data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
948 << 2) | (clock << 1) | (1 << 10) | 1;
949 }
950
951 ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
953 ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
955
956 return 0;
957}
u32 data1
Definition ar9003_mac.h:4
u32 data0
Definition ar9003_mac.h:2
#define AR5K_RF_BUFFER_CONTROL_3
Definition reg.h:2125
static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, struct ath5k_athchan_2ghz *athchan)
Definition ath5k_phy.c:887

References ath5k_athchan_2ghz::a2_athchan, ath5k_athchan_2ghz::a2_flags, ah, AR5K_RF_BUFFER, AR5K_RF_BUFFER_CONTROL_3, ath5k_hw_bitswap(), ath5k_hw_reg_write(), ath5k_hw_rf5111_chan2athchan(), channel, CHANNEL_2GHZ, data0, data1, and u32.

Referenced by ath5k_hw_channel().

◆ ath5k_hw_rf5112_channel()

int ath5k_hw_rf5112_channel ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 962 of file ath5k_phy.c.

964{
966 u16 c;
967
968 data = data0 = data1 = data2 = 0;
969 c = channel->center_freq;
970
971 if (c < 4800) {
972 if (!((c - 2224) % 5)) {
973 data0 = ((2 * (c - 704)) - 3040) / 10;
974 data1 = 1;
975 } else if (!((c - 2192) % 5)) {
976 data0 = ((2 * (c - 672)) - 3040) / 10;
977 data1 = 0;
978 } else
979 return -EINVAL;
980
981 data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
982 } else if ((c - (c % 5)) != 2 || c > 5435) {
983 if (!(c % 20) && c >= 5120) {
984 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
985 data2 = ath5k_hw_bitswap(3, 2);
986 } else if (!(c % 10)) {
987 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
988 data2 = ath5k_hw_bitswap(2, 2);
989 } else if (!(c % 5)) {
990 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
991 data2 = ath5k_hw_bitswap(1, 2);
992 } else
993 return -EINVAL;
994 } else {
995 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
996 data2 = ath5k_hw_bitswap(0, 2);
997 }
998
999 data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
1000
1003
1004 return 0;
1005}
u32 data2
Definition ar9003_mac.h:6
#define AR5K_RF_BUFFER_CONTROL_5
Definition reg.h:2134

References ah, AR5K_RF_BUFFER, AR5K_RF_BUFFER_CONTROL_5, ath5k_hw_bitswap(), ath5k_hw_reg_write(), channel, data, data0, data1, data2, EINVAL, u16, and u32.

Referenced by ath5k_hw_channel().

◆ ath5k_hw_rf2425_channel()

int ath5k_hw_rf2425_channel ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 1010 of file ath5k_phy.c.

1012{
1013 u32 data, data0, data2;
1014 u16 c;
1015
1016 data = data0 = data2 = 0;
1017 c = channel->center_freq;
1018
1019 if (c < 4800) {
1020 data0 = ath5k_hw_bitswap((c - 2272), 8);
1021 data2 = 0;
1022 /* ? 5GHz ? */
1023 } else if ((c - (c % 5)) != 2 || c > 5435) {
1024 if (!(c % 20) && c < 5120)
1025 data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
1026 else if (!(c % 10))
1027 data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
1028 else if (!(c % 5))
1029 data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
1030 else
1031 return -EINVAL;
1032 data2 = ath5k_hw_bitswap(1, 2);
1033 } else {
1034 data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
1035 data2 = ath5k_hw_bitswap(0, 2);
1036 }
1037
1038 data = (data0 << 4) | data2 << 2 | 0x1001;
1039
1042
1043 return 0;
1044}

References ah, AR5K_RF_BUFFER, AR5K_RF_BUFFER_CONTROL_5, ath5k_hw_bitswap(), ath5k_hw_reg_write(), channel, data, data0, data2, EINVAL, u16, and u32.

Referenced by ath5k_hw_channel().

◆ ath5k_hw_channel()

int ath5k_hw_channel ( struct ath5k_hw * ah,
struct net80211_channel * channel )

Definition at line 1049 of file ath5k_phy.c.

1050{
1051 int ret;
1052 /*
1053 * Check bounds supported by the PHY (we don't care about regultory
1054 * restrictions at this point). Note: hw_value already has the band
1055 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
1056 * of the band by that */
1057 if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
1058 DBG("ath5k: channel frequency (%d MHz) out of supported "
1059 "range\n", channel->center_freq);
1060 return -EINVAL;
1061 }
1062
1063 /*
1064 * Set the channel and wait
1065 */
1066 switch (ah->ah_radio) {
1067 case AR5K_RF5110:
1069 break;
1070 case AR5K_RF5111:
1072 break;
1073 case AR5K_RF2425:
1075 break;
1076 default:
1078 break;
1079 }
1080
1081 if (ret) {
1082 DBG("ath5k: setting channel failed: %s\n", strerror(ret));
1083 return ret;
1084 }
1085
1086 /* Set JAPAN setting for channel 14 */
1087 if (channel->center_freq == 2484) {
1090 } else {
1093 }
1094
1095 ah->ah_current_channel = channel;
1096 ah->ah_turbo = (channel->hw_value == CHANNEL_T ? 1 : 0);
1097
1098 return 0;
1099}
#define AR5K_PHY_CCKTXCTL_JAPAN
Definition reg.h:2507
#define AR5K_PHY_CCKTXCTL
Definition reg.h:2505
#define AR5K_PHY_CCKTXCTL_WORLD
Definition reg.h:2506
#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:106
#define CHANNEL_T
Definition ath5k.h:643
@ AR5K_RF5110
Definition ath5k.h:263
static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:868
static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:1010
int ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
Definition ath5k_phy.c:831
static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:916
static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:962
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References ah, AR5K_PHY_CCKTXCTL, AR5K_PHY_CCKTXCTL_JAPAN, AR5K_PHY_CCKTXCTL_WORLD, AR5K_REG_ENABLE_BITS, AR5K_RF2425, AR5K_RF5110, AR5K_RF5111, ath5k_channel_ok(), ath5k_hw_rf2425_channel(), ath5k_hw_rf5110_channel(), ath5k_hw_rf5111_channel(), ath5k_hw_rf5112_channel(), channel, CHANNEL_T, DBG, EINVAL, and strerror().

Referenced by ath5k_hw_reset(), and ath5k_hw_rf5110_calibrate().

◆ ath5k_hw_noise_floor_calibration()

int ath5k_hw_noise_floor_calibration ( struct ath5k_hw * ah,
short freq )

ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration

@ah: struct ath5k_hw pointer we are operating on @freq: the channel frequency, just used for error logging

This function performs a noise floor calibration of the PHY and waits for it to complete. Then the noise floor value is compared to some maximum noise floor we consider valid.

Note that this is different from what the madwifi HAL does: it reads the noise floor and afterwards initiates the calibration. Since the noise floor calibration can take some time to finish, depending on the current channel use, that avoids the occasional timeout warnings we are seeing now.

See the following link for an Atheros patent on noise floor calibration: http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7

XXX: Since during noise floor calibration antennas are detached according to the patent, we should stop tx queues here.

Definition at line 1128 of file ath5k_phy.c.

1129{
1130 int ret;
1131 unsigned int i;
1132 s32 noise_floor;
1133
1134 /*
1135 * Enable noise floor calibration
1136 */
1139
1140 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1141 AR5K_PHY_AGCCTL_NF, 0, 0);
1142
1143 if (ret) {
1144 DBG("ath5k: noise floor calibration timeout (%d MHz)\n", freq);
1145 return -EAGAIN;
1146 }
1147
1148 /* Wait until the noise floor is calibrated and read the value */
1149 for (i = 20; i > 0; i--) {
1150 mdelay(1);
1151 noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
1152 noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
1153 if (noise_floor & AR5K_PHY_NF_ACTIVE) {
1154 noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
1155
1156 if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
1157 break;
1158 }
1159 }
1160
1161 DBG2("ath5k: noise floor %d\n", noise_floor);
1162
1163 if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
1164 DBG("ath5k: noise floor calibration failed (%d MHz)\n", freq);
1165 return -EAGAIN;
1166 }
1167
1168 ah->ah_noise_floor = noise_floor;
1169
1170 return 0;
1171}
#define AR5K_PHY_NF
Definition reg.h:2032
#define AR5K_PHY_AGCCTL_NF
Definition reg.h:2025
#define AR5K_PHY_AGCCTL
Definition reg.h:2023
#define AR5K_PHY_NF_RVAL(_n)
Definition reg.h:2035
#define AR5K_PHY_NF_AVAL(_n)
Definition reg.h:2036
#define AR5K_PHY_NF_ACTIVE
Definition reg.h:2034
#define AR5K_TUNE_NOISE_FLOOR
Definition ath5k.h:192
#define EAGAIN
Resource temporarily unavailable.
Definition errno.h:319

References ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, AR5K_PHY_NF, AR5K_PHY_NF_ACTIVE, AR5K_PHY_NF_AVAL, AR5K_PHY_NF_RVAL, AR5K_REG_ENABLE_BITS, AR5K_TUNE_NOISE_FLOOR, ath5k_hw_reg_read(), DBG, DBG2, EAGAIN, and mdelay().

Referenced by ath5k_hw_reset(), ath5k_hw_rf5110_calibrate(), and ath5k_hw_rf511x_calibrate().

◆ ath5k_hw_rf5110_calibrate()

int ath5k_hw_rf5110_calibrate ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 1178 of file ath5k_phy.c.

1180{
1181 u32 phy_sig, phy_agc, phy_sat, beacon;
1182 int ret;
1183
1184 /*
1185 * Disable beacons and RX/TX queues, wait
1186 */
1191
1192 mdelay(2);
1193
1194 /*
1195 * Set the channel (with AGC turned off)
1196 */
1198 udelay(10);
1199 ret = ath5k_hw_channel(ah, channel);
1200
1201 /*
1202 * Activate PHY and wait
1203 */
1205 mdelay(1);
1206
1208
1209 if (ret)
1210 return ret;
1211
1212 /*
1213 * Calibrate the radio chip
1214 */
1215
1216 /* Remember normal state */
1217 phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
1220
1221 /* Update radio registers */
1222 ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
1224
1229
1234
1235 udelay(20);
1236
1238 udelay(10);
1241
1242 mdelay(1);
1243
1244 /*
1245 * Enable calibration and wait until completion
1246 */
1248
1249 ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
1250 AR5K_PHY_AGCCTL_CAL, 0, 0);
1251
1252 /* Reset to normal state */
1256
1257 if (ret) {
1258 DBG("ath5k: calibration timeout (%d MHz)\n",
1259 channel->center_freq);
1260 return ret;
1261 }
1262
1264
1265 /*
1266 * Re-enable RX/TX and beacons
1267 */
1271
1272 return 0;
1273}
#define AR5K_DIAG_SW_DIS_RX_5210
Definition reg.h:1395
#define AR5K_PHY_AGCCTL_CAL
Definition reg.h:2024
#define AR5K_PHY_RFSTG
Definition reg.h:2144
#define AR5K_PHY_ACT_ENABLE
Definition reg.h:1928
#define AR5K_BEACON_ENABLE
Definition reg.h:1243
#define AR5K_PHY_ADCSAT_THR
Definition reg.h:2049
#define AR5K_PHY_ACT
Definition reg.h:1927
#define AR5K_BEACON_5210
Definition reg.h:1235
#define AR5K_DIAG_SW_DIS_TX
Definition reg.h:1394
#define AR5K_PHY_AGCCOARSE_HI
Definition reg.h:2017
#define AR5K_PHY_AGCCOARSE
Definition reg.h:2014
#define AR5K_PHY_SIG
Definition reg.h:2004
#define AR5K_DIAG_SW_5210
Definition reg.h:1385
#define AR5K_PHY_AGCCOARSE_LO
Definition reg.h:2015
#define AR5K_PHY_ADCSAT
Definition reg.h:2046
#define AR5K_PHY_AGC_DISABLE
Definition reg.h:1902
#define AR5K_PHY_AGC
Definition reg.h:1900
#define AR5K_PHY_RFSTG_DISABLE
Definition reg.h:2145
#define AR5K_PHY_ADCSAT_ICNT
Definition reg.h:2047
#define AR5K_PHY_SIG_FIRPWR
Definition reg.h:2007
#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags)
Definition ath5k.h:109
int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
Definition ath5k_phy.c:1128
int ath5k_hw_channel(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:1049
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.c:61

References ah, AR5K_BEACON_5210, AR5K_BEACON_ENABLE, AR5K_DIAG_SW_5210, AR5K_DIAG_SW_DIS_RX_5210, AR5K_DIAG_SW_DIS_TX, AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ADCSAT, AR5K_PHY_ADCSAT_ICNT, AR5K_PHY_ADCSAT_THR, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE, AR5K_PHY_AGCCOARSE, AR5K_PHY_AGCCOARSE_HI, AR5K_PHY_AGCCOARSE_LO, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL, AR5K_PHY_RFSTG, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_SIG, AR5K_PHY_SIG_FIRPWR, AR5K_REG_DISABLE_BITS, AR5K_REG_ENABLE_BITS, AR5K_REG_SM, ath5k_hw_channel(), ath5k_hw_noise_floor_calibration(), ath5k_hw_reg_read(), ath5k_hw_reg_write(), channel, DBG, mdelay(), u32, and udelay().

Referenced by ath5k_hw_phy_calibrate().

◆ ath5k_hw_rf511x_calibrate()

int ath5k_hw_rf511x_calibrate ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 1278 of file ath5k_phy.c.

1280{
1281 u32 i_pwr, q_pwr;
1282 s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
1283 int i;
1284
1285 if (!ah->ah_calibration ||
1287 goto done;
1288
1289 /* Calibration has finished, get the results and re-run */
1290 for (i = 0; i <= 10; i++) {
1294 }
1295
1296 i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
1297 q_coffd = q_pwr >> 7;
1298
1299 /* No correction */
1300 if (i_coffd == 0 || q_coffd == 0)
1301 goto done;
1302
1303 i_coff = ((-iq_corr) / i_coffd) & 0x3f;
1304
1305 /* Boundary check */
1306 if (i_coff > 31)
1307 i_coff = 31;
1308 if (i_coff < -32)
1309 i_coff = -32;
1310
1311 q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
1312
1313 /* Boundary check */
1314 if (q_coff > 15)
1315 q_coff = 15;
1316 if (q_coff < -16)
1317 q_coff = -16;
1318
1319 /* Commit new I/Q value */
1321 ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
1322
1323 /* Re-enable calibration -if we don't we'll commit
1324 * the same values again and again */
1328
1329done:
1330
1331 /* TODO: Separate noise floor calibration from I/Q calibration
1332 * since noise floor calibration interrupts rx path while I/Q
1333 * calibration doesn't. We don't need to run noise floor calibration
1334 * as often as I/Q calibration.*/
1336
1337 /* Initiate a gain_F calibration */
1339
1340 return 0;
1341}
#define AR5K_PHY_IQ_RUN
Definition reg.h:2192
#define AR5K_PHY_IQ
Definition reg.h:2185
#define AR5K_PHY_IQ_CORR_Q_I_COFF_S
Definition reg.h:2188
#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX
Definition reg.h:2190
#define AR5K_PHY_IQRES_CAL_CORR
Definition reg.h:2402
#define AR5K_PHY_IQRES_CAL_PWR_I
Definition reg.h:2400
#define AR5K_PHY_IQ_CORR_ENABLE
Definition reg.h:2189
#define AR5K_PHY_IQRES_CAL_PWR_Q
Definition reg.h:2401
static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah)
Definition ath5k_phy.c:195

References ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CAL_NUM_LOG_MAX, AR5K_PHY_IQ_CORR_ENABLE, AR5K_PHY_IQ_CORR_Q_I_COFF_S, AR5K_PHY_IQ_RUN, AR5K_PHY_IQRES_CAL_CORR, AR5K_PHY_IQRES_CAL_PWR_I, AR5K_PHY_IQRES_CAL_PWR_Q, AR5K_REG_ENABLE_BITS, AR5K_REG_WRITE_BITS, ath5k_hw_noise_floor_calibration(), ath5k_hw_reg_read(), ath5k_hw_request_rfgain_probe(), channel, done, and u32.

Referenced by ath5k_hw_phy_calibrate().

◆ ath5k_hw_phy_calibrate()

int ath5k_hw_phy_calibrate ( struct ath5k_hw * ah,
struct net80211_channel * channel )

Definition at line 1346 of file ath5k_phy.c.

1348{
1349 int ret;
1350
1351 if (ah->ah_radio == AR5K_RF5110)
1353 else
1355
1356 return ret;
1357}
static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:1178
static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:1278

References ah, AR5K_RF5110, ath5k_hw_rf5110_calibrate(), ath5k_hw_rf511x_calibrate(), and channel.

Referenced by ath5k_calibrate().

◆ ath5k_hw_phy_disable()

int ath5k_hw_phy_disable ( struct ath5k_hw * ah)

Definition at line 1359 of file ath5k_phy.c.

1360{
1362
1363 return 0;
1364}
#define AR5K_PHY_ACT_DISABLE
Definition reg.h:1929

References ah, AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE, and ath5k_hw_reg_write().

Referenced by ath5k_stop_hw().

◆ ath5k_hw_radio_revision()

u16 ath5k_hw_radio_revision ( struct ath5k_hw * ah,
unsigned int chan )

Definition at line 1373 of file ath5k_phy.c.

1374{
1375 unsigned int i;
1376 u32 srev;
1377 u16 ret;
1378
1379 /*
1380 * Set the radio chip access register
1381 */
1382 switch (chan) {
1383 case CHANNEL_2GHZ:
1385 break;
1386 case CHANNEL_5GHZ:
1388 break;
1389 default:
1390 return 0;
1391 }
1392
1393 mdelay(2);
1394
1395 /* ...wait until PHY is ready and read the selected radio revision */
1396 ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
1397
1398 for (i = 0; i < 8; i++)
1399 ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
1400
1401 if (ah->ah_version == AR5K_AR5210) {
1402 srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
1403 ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
1404 } else {
1405 srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
1406 ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
1407 ((srev & 0x0f) << 4), 8);
1408 }
1409
1410 /* Reset to the 5GHz mode */
1412
1413 return ret;
1414}
#define AR5K_PHY_SHIFT_2GHZ
Definition reg.h:1878
#define AR5K_PHY(_n)
Definition reg.h:1856
#define AR5K_PHY_SHIFT_5GHZ
Definition reg.h:1879
@ AR5K_AR5210
Definition ath5k.h:256

References ah, AR5K_AR5210, AR5K_PHY, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY_SHIFT_5GHZ, ath5k_hw_bitswap(), ath5k_hw_reg_read(), ath5k_hw_reg_write(), CHANNEL_2GHZ, CHANNEL_5GHZ, mdelay(), u16, and u32.

Referenced by ath5k_hw_attach().

◆ ath5k_hw_set_def_antenna()

void ath5k_hw_set_def_antenna ( struct ath5k_hw * ah,
unsigned int ant )

Definition at line 1417 of file ath5k_phy.c.

1418{
1419 if (ah->ah_version != AR5K_AR5210)
1421}
#define AR5K_DEFAULT_ANTENNA
Definition reg.h:1471

References ah, AR5K_AR5210, AR5K_DEFAULT_ANTENNA, and ath5k_hw_reg_write().

◆ ath5k_hw_get_def_antenna()

unsigned int ath5k_hw_get_def_antenna ( struct ath5k_hw * ah)

Definition at line 1423 of file ath5k_phy.c.

1424{
1425 if (ah->ah_version != AR5K_AR5210)
1427
1428 return 0; /*XXX: What do we return for 5210 ?*/
1429}

References ah, AR5K_AR5210, AR5K_DEFAULT_ANTENNA, and ath5k_hw_reg_read().

◆ ath5k_get_interpolated_value()

s16 ath5k_get_interpolated_value ( s16 target,
s16 x_left,
s16 x_right,
s16 y_left,
s16 y_right )
static

Definition at line 1444 of file ath5k_phy.c.

1446{
1447 s16 ratio, result;
1448
1449 /* Avoid divide by zero and skip interpolation
1450 * if we have the same point */
1451 if ((x_left == x_right) || (y_left == y_right))
1452 return y_left;
1453
1454 /*
1455 * Since we use ints and not fps, we need to scale up in
1456 * order to get a sane ratio value (or else we 'll eg. get
1457 * always 1 instead of 1.25, 1.75 etc). We scale up by 100
1458 * to have some accuracy both for 0.5 and 0.25 steps.
1459 */
1460 ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left));
1461
1462 /* Now scale down to be in range */
1463 result = y_left + (ratio * (target - x_left) / 100);
1464
1465 return result;
1466}
uint16_t result
Definition hyperv.h:33
int16_t s16
Definition stdint.h:21

References result.

Referenced by ath5k_create_power_curve(), ath5k_get_linear_pcdac_min(), ath5k_get_rate_pcal_data(), and ath5k_setup_channel_powertable().

◆ ath5k_get_linear_pcdac_min()

s16 ath5k_get_linear_pcdac_min ( const u8 * stepL,
const u8 * stepR,
const s16 * pwrL,
const s16 * pwrR )
static

Definition at line 1477 of file ath5k_phy.c.

1479{
1480 s8 tmp;
1481 s16 min_pwrL, min_pwrR;
1482 s16 pwr_i;
1483
1484 if (pwrL[0] == pwrL[1])
1485 min_pwrL = pwrL[0];
1486 else {
1487 pwr_i = pwrL[0];
1488 do {
1489 pwr_i--;
1491 pwrL[0], pwrL[1],
1492 stepL[0], stepL[1]);
1493 } while (tmp > 1);
1494
1495 min_pwrL = pwr_i;
1496 }
1497
1498 if (pwrR[0] == pwrR[1])
1499 min_pwrR = pwrR[0];
1500 else {
1501 pwr_i = pwrR[0];
1502 do {
1503 pwr_i--;
1505 pwrR[0], pwrR[1],
1506 stepR[0], stepR[1]);
1507 } while (tmp > 1);
1508
1509 min_pwrR = pwr_i;
1510 }
1511
1512 /* Keep the right boundary so that it works for both curves */
1513 return max(min_pwrL, min_pwrR);
1514}
static s16 ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, s16 y_left, s16 y_right)
Definition ath5k_phy.c:1444
#define max(x, y)
Definition ath.h:41
int8_t s8
Definition stdint.h:19
unsigned long tmp
Definition linux_pci.h:65

References ath5k_get_interpolated_value(), max, tmp, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_create_power_curve()

void ath5k_create_power_curve ( s16 pmin,
s16 pmax,
const s16 * pwr,
const u8 * vpd,
u8 num_points,
u8 * vpd_table,
u8 type )
static

Definition at line 1529 of file ath5k_phy.c.

1533{
1534 u8 idx[2] = { 0, 1 };
1535 s16 pwr_i = 2*pmin;
1536 int i;
1537
1538 if (num_points < 2)
1539 return;
1540
1541 /* We want the whole line, so adjust boundaries
1542 * to cover the entire power range. Note that
1543 * power values are already 0.25dB so no need
1544 * to multiply pwr_i by 2 */
1546 pwr_i = pmin;
1547 pmin = 0;
1548 pmax = 63;
1549 }
1550
1551 /* Find surrounding turning points (TPs)
1552 * and interpolate between them */
1553 for (i = 0; (i <= (u16) (pmax - pmin)) &&
1554 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
1555
1556 /* We passed the right TP, move to the next set of TPs
1557 * if we pass the last TP, extrapolate above using the last
1558 * two TPs for ratio */
1559 if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) {
1560 idx[0]++;
1561 idx[1]++;
1562 }
1563
1564 vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i,
1565 pwr[idx[0]], pwr[idx[1]],
1566 vpd[idx[0]], vpd[idx[1]]);
1567
1568 /* Increase by 0.5dB
1569 * (0.25 dB units) */
1570 pwr_i += 2;
1571 }
1572}
#define AR5K_EEPROM_POWER_TABLE_SIZE
Definition eeprom.h:217
@ AR5K_PWRTABLE_LINEAR_PCDAC
Definition eeprom.h:316

References AR5K_EEPROM_POWER_TABLE_SIZE, AR5K_PWRTABLE_LINEAR_PCDAC, ath5k_get_interpolated_value(), type, u16, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_get_chan_pcal_surrounding_piers()

void ath5k_get_chan_pcal_surrounding_piers ( struct ath5k_hw * ah,
struct net80211_channel * channel,
struct ath5k_chan_pcal_info ** pcinfo_l,
struct ath5k_chan_pcal_info ** pcinfo_r )
static

Definition at line 1581 of file ath5k_phy.c.

1585{
1586 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1587 struct ath5k_chan_pcal_info *pcinfo;
1588 u8 idx_l, idx_r;
1589 u8 mode, max, i;
1590 u32 target = channel->center_freq;
1591
1592 idx_l = 0;
1593 idx_r = 0;
1594
1595 if (!(channel->hw_value & CHANNEL_OFDM)) {
1596 pcinfo = ee->ee_pwr_cal_b;
1598 } else if (channel->hw_value & CHANNEL_2GHZ) {
1599 pcinfo = ee->ee_pwr_cal_g;
1601 } else {
1602 pcinfo = ee->ee_pwr_cal_a;
1604 }
1605 max = ee->ee_n_piers[mode] - 1;
1606
1607 /* Frequency is below our calibrated
1608 * range. Use the lowest power curve
1609 * we have */
1610 if (target < pcinfo[0].freq) {
1611 idx_l = idx_r = 0;
1612 goto done;
1613 }
1614
1615 /* Frequency is above our calibrated
1616 * range. Use the highest power curve
1617 * we have */
1618 if (target > pcinfo[max].freq) {
1619 idx_l = idx_r = max;
1620 goto done;
1621 }
1622
1623 /* Frequency is inside our calibrated
1624 * channel range. Pick the surrounding
1625 * calibration piers so that we can
1626 * interpolate */
1627 for (i = 0; i <= max; i++) {
1628
1629 /* Frequency matches one of our calibration
1630 * piers, no need to interpolate, just use
1631 * that calibration pier */
1632 if (pcinfo[i].freq == target) {
1633 idx_l = idx_r = i;
1634 goto done;
1635 }
1636
1637 /* We found a calibration pier that's above
1638 * frequency, use this pier and the previous
1639 * one to interpolate */
1640 if (target < pcinfo[i].freq) {
1641 idx_r = i;
1642 idx_l = idx_r - 1;
1643 goto done;
1644 }
1645 }
1646
1647done:
1648 *pcinfo_l = &pcinfo[idx_l];
1649 *pcinfo_r = &pcinfo[idx_r];
1650
1651 return;
1652}
u8 ee_n_piers[AR5K_EEPROM_N_MODES]
Definition eeprom.h:427
struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]
Definition eeprom.h:430
struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]
Definition eeprom.h:428
struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]
Definition eeprom.h:429

References ah, AR5K_EEPROM_MODE_11A, AR5K_EEPROM_MODE_11B, AR5K_EEPROM_MODE_11G, channel, CHANNEL_2GHZ, CHANNEL_OFDM, done, ath5k_eeprom_info::ee_n_piers, ath5k_eeprom_info::ee_pwr_cal_a, ath5k_eeprom_info::ee_pwr_cal_b, ath5k_eeprom_info::ee_pwr_cal_g, ath5k_chan_pcal_info::freq, max, mode, u32, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_get_rate_pcal_data()

void ath5k_get_rate_pcal_data ( struct ath5k_hw * ah,
struct net80211_channel * channel,
struct ath5k_rate_pcal_info * rates )
static

Definition at line 1661 of file ath5k_phy.c.

1664{
1665 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1666 struct ath5k_rate_pcal_info *rpinfo;
1667 u8 idx_l, idx_r;
1668 u8 mode, max, i;
1669 u32 target = channel->center_freq;
1670
1671 idx_l = 0;
1672 idx_r = 0;
1673
1674 if (!(channel->hw_value & CHANNEL_OFDM)) {
1675 rpinfo = ee->ee_rate_tpwr_b;
1677 } else if (channel->hw_value & CHANNEL_2GHZ) {
1678 rpinfo = ee->ee_rate_tpwr_g;
1680 } else {
1681 rpinfo = ee->ee_rate_tpwr_a;
1683 }
1684 max = ee->ee_rate_target_pwr_num[mode] - 1;
1685
1686 /* Get the surrounding calibration
1687 * piers - same as above */
1688 if (target < rpinfo[0].freq) {
1689 idx_l = idx_r = 0;
1690 goto done;
1691 }
1692
1693 if (target > rpinfo[max].freq) {
1694 idx_l = idx_r = max;
1695 goto done;
1696 }
1697
1698 for (i = 0; i <= max; i++) {
1699
1700 if (rpinfo[i].freq == target) {
1701 idx_l = idx_r = i;
1702 goto done;
1703 }
1704
1705 if (target < rpinfo[i].freq) {
1706 idx_r = i;
1707 idx_l = idx_r - 1;
1708 goto done;
1709 }
1710 }
1711
1712done:
1713 /* Now interpolate power value, based on the frequency */
1714 rates->freq = target;
1715
1716 rates->target_power_6to24 =
1717 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1718 rpinfo[idx_r].freq,
1719 rpinfo[idx_l].target_power_6to24,
1720 rpinfo[idx_r].target_power_6to24);
1721
1722 rates->target_power_36 =
1723 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1724 rpinfo[idx_r].freq,
1725 rpinfo[idx_l].target_power_36,
1726 rpinfo[idx_r].target_power_36);
1727
1728 rates->target_power_48 =
1729 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1730 rpinfo[idx_r].freq,
1731 rpinfo[idx_l].target_power_48,
1732 rpinfo[idx_r].target_power_48);
1733
1734 rates->target_power_54 =
1735 ath5k_get_interpolated_value(target, rpinfo[idx_l].freq,
1736 rpinfo[idx_r].freq,
1737 rpinfo[idx_l].target_power_54,
1738 rpinfo[idx_r].target_power_54);
1739}
u8 rates[0]
Rates data, one rate per byte.
Definition ieee80211.h:2
struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]
Definition eeprom.h:434
u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]
Definition eeprom.h:433
struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]
Definition eeprom.h:436
struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]
Definition eeprom.h:435

References ah, AR5K_EEPROM_MODE_11A, AR5K_EEPROM_MODE_11B, AR5K_EEPROM_MODE_11G, ath5k_get_interpolated_value(), channel, CHANNEL_2GHZ, CHANNEL_OFDM, done, ath5k_eeprom_info::ee_rate_target_pwr_num, ath5k_eeprom_info::ee_rate_tpwr_a, ath5k_eeprom_info::ee_rate_tpwr_b, ath5k_eeprom_info::ee_rate_tpwr_g, ath5k_rate_pcal_info::freq, max, mode, rates, ath5k_rate_pcal_info::target_power_36, ath5k_rate_pcal_info::target_power_48, ath5k_rate_pcal_info::target_power_54, ath5k_rate_pcal_info::target_power_6to24, u32, and u8.

Referenced by ath5k_hw_txpower().

◆ ath5k_get_max_ctl_power()

void ath5k_get_max_ctl_power ( struct ath5k_hw * ah,
struct net80211_channel * channel )
static

Definition at line 1749 of file ath5k_phy.c.

1751{
1752 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1753 struct ath5k_edge_power *rep = ee->ee_ctl_pwr;
1754 u8 *ctl_val = ee->ee_ctl;
1755 s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4;
1756 s16 edge_pwr = 0;
1757 u8 rep_idx;
1758 u8 i, ctl_mode;
1759 u8 ctl_idx = 0xFF;
1760 u32 target = channel->center_freq;
1761
1762 /* Find out a CTL for our mode that's not mapped
1763 * on a specific reg domain.
1764 *
1765 * TODO: Map our current reg domain to one of the 3 available
1766 * reg domain ids so that we can support more CTLs. */
1767 switch (channel->hw_value & CHANNEL_MODES) {
1768 case CHANNEL_A:
1770 break;
1771 case CHANNEL_G:
1773 break;
1774 case CHANNEL_B:
1776 break;
1777 case CHANNEL_T:
1779 break;
1780 case CHANNEL_TG:
1782 break;
1783 case CHANNEL_XR:
1784 /* Fall through */
1785 default:
1786 return;
1787 }
1788
1789 for (i = 0; i < ee->ee_ctls; i++) {
1790 if (ctl_val[i] == ctl_mode) {
1791 ctl_idx = i;
1792 break;
1793 }
1794 }
1795
1796 /* If we have a CTL dataset available grab it and find the
1797 * edge power for our frequency */
1798 if (ctl_idx == 0xFF)
1799 return;
1800
1801 /* Edge powers are sorted by frequency from lower
1802 * to higher. Each CTL corresponds to 8 edge power
1803 * measurements. */
1804 rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES;
1805
1806 /* Don't do boundaries check because we
1807 * might have more that one bands defined
1808 * for this mode */
1809
1810 /* Get the edge power that's closer to our
1811 * frequency */
1812 for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) {
1813 rep_idx += i;
1814 if (target <= rep[rep_idx].freq)
1815 edge_pwr = (s16) rep[rep_idx].edge;
1816 }
1817
1818 if (edge_pwr) {
1819 ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr);
1820 }
1821}
#define AR5K_EEPROM_N_EDGES
Definition eeprom.h:191
@ AR5K_CTL_11G
Definition eeprom.h:243
@ AR5K_CTL_11B
Definition eeprom.h:242
@ AR5K_CTL_TURBOG
Definition eeprom.h:245
@ AR5K_CTL_11A
Definition eeprom.h:241
@ AR5K_CTL_TURBO
Definition eeprom.h:244
#define AR5K_CTL_NO_REGDOMAIN
Definition eeprom.h:271
#define CHANNEL_B
Definition ath5k.h:641
#define CHANNEL_TG
Definition ath5k.h:644
#define CHANNEL_XR
Definition ath5k.h:638
#define CHANNEL_MODES
Definition ath5k.h:653
#define CHANNEL_G
Definition ath5k.h:642
#define CHANNEL_A
Definition ath5k.h:640
#define min(x, y)
Definition ath.h:36
u8 ee_ctl[AR5K_EEPROM_MAX_CTLS]
Definition eeprom.h:440
struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES *AR5K_EEPROM_MAX_CTLS]
Definition eeprom.h:441

References ah, AR5K_CTL_11A, AR5K_CTL_11B, AR5K_CTL_11G, AR5K_CTL_NO_REGDOMAIN, AR5K_CTL_TURBO, AR5K_CTL_TURBOG, AR5K_EEPROM_N_EDGES, channel, CHANNEL_A, CHANNEL_B, CHANNEL_G, CHANNEL_MODES, CHANNEL_T, CHANNEL_TG, CHANNEL_XR, ath5k_edge_power::edge, ath5k_eeprom_info::ee_ctl, ath5k_eeprom_info::ee_ctl_pwr, ath5k_eeprom_info::ee_ctls, ath5k_edge_power::freq, min, u32, and u8.

Referenced by ath5k_hw_txpower().

◆ ath5k_fill_pwr_to_pcdac_table()

void ath5k_fill_pwr_to_pcdac_table ( struct ath5k_hw * ah,
s16 * table_min,
s16 * table_max )
static

Definition at line 1836 of file ath5k_phy.c.

1838{
1839 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1840 u8 *pcdac_tmp = ah->ah_txpower.tmpL[0];
1841 u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;
1842 s16 min_pwr, max_pwr;
1843
1844 /* Get table boundaries */
1845 min_pwr = table_min[0];
1846 pcdac_0 = pcdac_tmp[0];
1847
1848 max_pwr = table_max[0];
1849 pcdac_n = pcdac_tmp[table_max[0] - table_min[0]];
1850
1851 /* Extrapolate below minimum using pcdac_0 */
1852 pcdac_i = 0;
1853 for (i = 0; i < min_pwr; i++)
1854 pcdac_out[pcdac_i++] = pcdac_0;
1855
1856 /* Copy values from pcdac_tmp */
1857 pwr_idx = min_pwr;
1858 for (i = 0 ; pwr_idx <= max_pwr &&
1859 pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {
1860 pcdac_out[pcdac_i++] = pcdac_tmp[i];
1861 pwr_idx++;
1862 }
1863
1864 /* Extrapolate above maximum */
1865 while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE)
1866 pcdac_out[pcdac_i++] = pcdac_n;
1867
1868}

References ah, AR5K_EEPROM_POWER_TABLE_SIZE, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_combine_linear_pcdac_curves()

void ath5k_combine_linear_pcdac_curves ( struct ath5k_hw * ah,
s16 * table_min,
s16 * table_max,
u8 pdcurves )
static

Definition at line 1882 of file ath5k_phy.c.

1884{
1885 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1886 u8 *pcdac_low_pwr;
1887 u8 *pcdac_high_pwr;
1888 u8 *pcdac_tmp;
1889 u8 pwr;
1890 s16 max_pwr_idx;
1891 s16 min_pwr_idx;
1892 s16 mid_pwr_idx = 0;
1893 /* Edge flag turs on the 7nth bit on the PCDAC
1894 * to delcare the higher power curve (force values
1895 * to be greater than 64). If we only have one curve
1896 * we don't need to set this, if we have 2 curves and
1897 * fill the table backwards this can also be used to
1898 * switch from higher power curve to lower power curve */
1899 u8 edge_flag;
1900 int i;
1901
1902 /* When we have only one curve available
1903 * that's the higher power curve. If we have
1904 * two curves the first is the high power curve
1905 * and the next is the low power curve. */
1906 if (pdcurves > 1) {
1907 pcdac_low_pwr = ah->ah_txpower.tmpL[1];
1908 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
1909 mid_pwr_idx = table_max[1] - table_min[1] - 1;
1910 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
1911
1912 /* If table size goes beyond 31.5dB, keep the
1913 * upper 31.5dB range when setting tx power.
1914 * Note: 126 = 31.5 dB in quarter dB steps */
1915 if (table_max[0] - table_min[1] > 126)
1916 min_pwr_idx = table_max[0] - 126;
1917 else
1918 min_pwr_idx = table_min[1];
1919
1920 /* Since we fill table backwards
1921 * start from high power curve */
1922 pcdac_tmp = pcdac_high_pwr;
1923
1924 edge_flag = 0x40;
1925 } else {
1926 pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */
1927 pcdac_high_pwr = ah->ah_txpower.tmpL[0];
1928 min_pwr_idx = table_min[0];
1929 max_pwr_idx = (table_max[0] - table_min[0]) / 2;
1930 pcdac_tmp = pcdac_high_pwr;
1931 edge_flag = 0;
1932 }
1933
1934 /* This is used when setting tx power*/
1935 ah->ah_txpower.txp_min_idx = min_pwr_idx/2;
1936
1937 /* Fill Power to PCDAC table backwards */
1938 pwr = max_pwr_idx;
1939 for (i = 63; i >= 0; i--) {
1940 /* Entering lower power range, reset
1941 * edge flag and set pcdac_tmp to lower
1942 * power curve.*/
1943 if (edge_flag == 0x40 &&
1944 (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {
1945 edge_flag = 0x00;
1946 pcdac_tmp = pcdac_low_pwr;
1947 pwr = mid_pwr_idx/2;
1948 }
1949
1950 /* Don't go below 1, extrapolate below if we have
1951 * already swithced to the lower power curve -or
1952 * we only have one curve and edge_flag is zero
1953 * anyway */
1954 if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) {
1955 while (i >= 0) {
1956 pcdac_out[i] = pcdac_out[i + 1];
1957 i--;
1958 }
1959 break;
1960 }
1961
1962 pcdac_out[i] = pcdac_tmp[pwr] | edge_flag;
1963
1964 /* Extrapolate above if pcdac is greater than
1965 * 126 -this can happen because we OR pcdac_out
1966 * value with edge_flag on high power curve */
1967 if (pcdac_out[i] > 126)
1968 pcdac_out[i] = 126;
1969
1970 /* Decrease by a 0.5dB step */
1971 pwr--;
1972 }
1973}

References ah, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_setup_pcdac_table()

void ath5k_setup_pcdac_table ( struct ath5k_hw * ah)
static

Definition at line 1977 of file ath5k_phy.c.

1978{
1979 u8 *pcdac_out = ah->ah_txpower.txp_pd_table;
1980 int i;
1981
1982 /*
1983 * Write TX power values
1984 */
1985 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
1987 (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) |
1988 (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16),
1990 }
1991}
#define AR5K_PHY_PCDAC_TXPOWER(_n)
Definition reg.h:2482

References ah, AR5K_EEPROM_POWER_TABLE_SIZE, AR5K_PHY_PCDAC_TXPOWER, ath5k_hw_reg_write(), and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_combine_pwr_to_pdadc_curves()

void ath5k_combine_pwr_to_pdadc_curves ( struct ath5k_hw * ah,
s16 * pwr_min,
s16 * pwr_max,
u8 pdcurves )
static

Definition at line 2006 of file ath5k_phy.c.

2008{
2009 u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS];
2010 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
2011 u8 *pdadc_tmp;
2012 s16 pdadc_0;
2013 u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size;
2014 u8 pd_gain_overlap;
2015
2016 /* Note: Register value is initialized on initvals
2017 * there is no feedback from hw.
2018 * XXX: What about pd_gain_overlap from EEPROM ? */
2019 pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) &
2021
2022 /* Create final PDADC table */
2023 for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) {
2024 pdadc_tmp = ah->ah_txpower.tmpL[pdg];
2025
2026 if (pdg == pdcurves - 1)
2027 /* 2 dB boundary stretch for last
2028 * (higher power) curve */
2029 gain_boundaries[pdg] = pwr_max[pdg] + 4;
2030 else
2031 /* Set gain boundary in the middle
2032 * between this curve and the next one */
2033 gain_boundaries[pdg] =
2034 (pwr_max[pdg] + pwr_min[pdg + 1]) / 2;
2035
2036 /* Sanity check in case our 2 db stretch got out of
2037 * range. */
2038 if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER)
2039 gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER;
2040
2041 /* For the first curve (lower power)
2042 * start from 0 dB */
2043 if (pdg == 0)
2044 pdadc_0 = 0;
2045 else
2046 /* For the other curves use the gain overlap */
2047 pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) -
2048 pd_gain_overlap;
2049
2050 /* Force each power step to be at least 0.5 dB */
2051 if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1)
2052 pwr_step = pdadc_tmp[1] - pdadc_tmp[0];
2053 else
2054 pwr_step = 1;
2055
2056 /* If pdadc_0 is negative, we need to extrapolate
2057 * below this pdgain by a number of pwr_steps */
2058 while ((pdadc_0 < 0) && (pdadc_i < 128)) {
2059 s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step;
2060 pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp;
2061 pdadc_0++;
2062 }
2063
2064 /* Set last pwr level, using gain boundaries */
2065 pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg];
2066 /* Limit it to be inside pwr range */
2067 table_size = pwr_max[pdg] - pwr_min[pdg];
2068 max_idx = (pdadc_n < table_size) ? pdadc_n : table_size;
2069
2070 /* Fill pdadc_out table */
2071 while (pdadc_0 < max_idx)
2072 pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++];
2073
2074 /* Need to extrapolate above this pdgain? */
2075 if (pdadc_n <= max_idx)
2076 continue;
2077
2078 /* Force each power step to be at least 0.5 dB */
2079 if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1)
2080 pwr_step = pdadc_tmp[table_size - 1] -
2081 pdadc_tmp[table_size - 2];
2082 else
2083 pwr_step = 1;
2084
2085 /* Extrapolate above */
2086 while ((pdadc_0 < (s16) pdadc_n) &&
2087 (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) {
2088 s16 tmp = pdadc_tmp[table_size - 1] +
2089 (pdadc_0 - max_idx) * pwr_step;
2090 pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp;
2091 pdadc_0++;
2092 }
2093 }
2094
2095 while (pdg < AR5K_EEPROM_N_PD_GAINS) {
2096 gain_boundaries[pdg] = gain_boundaries[pdg - 1];
2097 pdg++;
2098 }
2099
2100 while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) {
2101 pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1];
2102 pdadc_i++;
2103 }
2104
2105 /* Set gain boundaries */
2107 AR5K_REG_SM(pd_gain_overlap,
2109 AR5K_REG_SM(gain_boundaries[0],
2111 AR5K_REG_SM(gain_boundaries[1],
2113 AR5K_REG_SM(gain_boundaries[2],
2115 AR5K_REG_SM(gain_boundaries[3],
2118
2119 /* Used for setting rate power table */
2120 ah->ah_txpower.txp_min_idx = pwr_min[0];
2121
2122}
#define AR5K_EEPROM_N_PD_GAINS
Definition eeprom.h:209
#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2
Definition reg.h:2562
#define AR5K_PHY_TPC_RG5
Definition reg.h:2557
#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3
Definition reg.h:2564
#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1
Definition reg.h:2560
#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP
Definition reg.h:2558
#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4
Definition reg.h:2566
#define AR5K_TUNE_MAX_TXPOWER
Definition ath5k.h:193

References ah, AR5K_EEPROM_N_PD_GAINS, AR5K_EEPROM_POWER_TABLE_SIZE, AR5K_PHY_TPC_RG5, AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1, AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2, AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3, AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4, AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, AR5K_REG_SM, AR5K_TUNE_MAX_TXPOWER, ath5k_hw_reg_read(), ath5k_hw_reg_write(), tmp, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_setup_pwr_to_pdadc_table()

void ath5k_setup_pwr_to_pdadc_table ( struct ath5k_hw * ah,
u8 pdcurves,
u8 * pdg_to_idx )
static

Definition at line 2126 of file ath5k_phy.c.

2128{
2129 u8 *pdadc_out = ah->ah_txpower.txp_pd_table;
2130 u32 reg;
2131 u8 i;
2132
2133 /* Select the right pdgain curves */
2134
2135 /* Clear current settings */
2141
2142 /*
2143 * Use pd_gains curve from eeprom
2144 *
2145 * This overrides the default setting from initvals
2146 * in case some vendors (e.g. Zcomax) don't use the default
2147 * curves. If we don't honor their settings we 'll get a
2148 * 5dB (1 * gain overlap ?) drop.
2149 */
2151
2152 switch (pdcurves) {
2153 case 3:
2154 reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
2155 /* Fall through */
2156 case 2:
2157 reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
2158 /* Fall through */
2159 case 1:
2160 reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
2161 break;
2162 }
2164
2165 /*
2166 * Write TX power values
2167 */
2168 for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
2170 ((pdadc_out[4*i + 0] & 0xff) << 0) |
2171 ((pdadc_out[4*i + 1] & 0xff) << 8) |
2172 ((pdadc_out[4*i + 2] & 0xff) << 16) |
2173 ((pdadc_out[4*i + 3] & 0xff) << 24),
2175 }
2176}
#define AR5K_PHY_TPC_RG1_PDGAIN_2
Definition reg.h:2552
#define AR5K_PHY_TPC_RG1_PDGAIN_3
Definition reg.h:2554
#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN
Definition reg.h:2548
#define AR5K_PHY_PDADC_TXPOWER(_n)
Definition reg.h:2573
#define AR5K_PHY_TPC_RG1
Definition reg.h:2547
#define AR5K_PHY_TPC_RG1_PDGAIN_1
Definition reg.h:2550
static unsigned int unsigned int reg
Definition myson.h:162

References ah, AR5K_EEPROM_POWER_TABLE_SIZE, AR5K_PHY_PDADC_TXPOWER, AR5K_PHY_TPC_RG1, AR5K_PHY_TPC_RG1_NUM_PD_GAIN, AR5K_PHY_TPC_RG1_PDGAIN_1, AR5K_PHY_TPC_RG1_PDGAIN_2, AR5K_PHY_TPC_RG1_PDGAIN_3, AR5K_REG_SM, ath5k_hw_reg_read(), ath5k_hw_reg_write(), reg, u32, and u8.

Referenced by ath5k_setup_channel_powertable().

◆ ath5k_setup_channel_powertable()

int ath5k_setup_channel_powertable ( struct ath5k_hw * ah,
struct net80211_channel * channel,
u8 ee_mode,
u8 type )
static

Definition at line 2191 of file ath5k_phy.c.

2194{
2195 struct ath5k_pdgain_info *pdg_L, *pdg_R;
2196 struct ath5k_chan_pcal_info *pcinfo_L;
2197 struct ath5k_chan_pcal_info *pcinfo_R;
2198 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
2199 u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
2200 s16 table_min[AR5K_EEPROM_N_PD_GAINS];
2201 s16 table_max[AR5K_EEPROM_N_PD_GAINS];
2202 u8 *tmpL;
2203 u8 *tmpR;
2204 u32 target = channel->center_freq;
2205 int pdg, i;
2206
2207 /* Get surounding freq piers for this channel */
2209 &pcinfo_L,
2210 &pcinfo_R);
2211
2212 /* Loop over pd gain curves on
2213 * surounding freq piers by index */
2214 for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
2215
2216 /* Fill curves in reverse order
2217 * from lower power (max gain)
2218 * to higher power. Use curve -> idx
2219 * backmaping we did on eeprom init */
2220 u8 idx = pdg_curve_to_idx[pdg];
2221
2222 /* Grab the needed curves by index */
2223 pdg_L = &pcinfo_L->pd_curves[idx];
2224 pdg_R = &pcinfo_R->pd_curves[idx];
2225
2226 /* Initialize the temp tables */
2227 tmpL = ah->ah_txpower.tmpL[pdg];
2228 tmpR = ah->ah_txpower.tmpR[pdg];
2229
2230 /* Set curve's x boundaries and create
2231 * curves so that they cover the same
2232 * range (if we don't do that one table
2233 * will have values on some range and the
2234 * other one won't have any so interpolation
2235 * will fail) */
2236 table_min[pdg] = min(pdg_L->pd_pwr[0],
2237 pdg_R->pd_pwr[0]) / 2;
2238
2239 table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
2240 pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2;
2241
2242 /* Now create the curves on surrounding channels
2243 * and interpolate if needed to get the final
2244 * curve for this gain on this channel */
2245 switch (type) {
2247 /* Override min/max so that we don't loose
2248 * accuracy (don't divide by 2) */
2249 table_min[pdg] = min(pdg_L->pd_pwr[0],
2250 pdg_R->pd_pwr[0]);
2251
2252 table_max[pdg] =
2253 max(pdg_L->pd_pwr[pdg_L->pd_points - 1],
2254 pdg_R->pd_pwr[pdg_R->pd_points - 1]);
2255
2256 /* Override minimum so that we don't get
2257 * out of bounds while extrapolating
2258 * below. Don't do this when we have 2
2259 * curves and we are on the high power curve
2260 * because table_min is ok in this case */
2261 if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) {
2262
2263 table_min[pdg] =
2265 pdg_R->pd_step,
2266 pdg_L->pd_pwr,
2267 pdg_R->pd_pwr);
2268
2269 /* Don't go too low because we will
2270 * miss the upper part of the curve.
2271 * Note: 126 = 31.5dB (max power supported)
2272 * in 0.25dB units */
2273 if (table_max[pdg] - table_min[pdg] > 126)
2274 table_min[pdg] = table_max[pdg] - 126;
2275 }
2276
2277 /* Fall through */
2280
2281 ath5k_create_power_curve(table_min[pdg],
2282 table_max[pdg],
2283 pdg_L->pd_pwr,
2284 pdg_L->pd_step,
2285 pdg_L->pd_points, tmpL, type);
2286
2287 /* We are in a calibration
2288 * pier, no need to interpolate
2289 * between freq piers */
2290 if (pcinfo_L == pcinfo_R)
2291 continue;
2292
2293 ath5k_create_power_curve(table_min[pdg],
2294 table_max[pdg],
2295 pdg_R->pd_pwr,
2296 pdg_R->pd_step,
2297 pdg_R->pd_points, tmpR, type);
2298 break;
2299 default:
2300 return -EINVAL;
2301 }
2302
2303 /* Interpolate between curves
2304 * of surounding freq piers to
2305 * get the final curve for this
2306 * pd gain. Re-use tmpL for interpolation
2307 * output */
2308 for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) &&
2309 (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) {
2310 tmpL[i] = (u8) ath5k_get_interpolated_value(target,
2311 (s16) pcinfo_L->freq,
2312 (s16) pcinfo_R->freq,
2313 (s16) tmpL[i],
2314 (s16) tmpR[i]);
2315 }
2316 }
2317
2318 /* Now we have a set of curves for this
2319 * channel on tmpL (x range is table_max - table_min
2320 * and y values are tmpL[pdg][]) sorted in the same
2321 * order as EEPROM (because we've used the backmaping).
2322 * So for RF5112 it's from higher power to lower power
2323 * and for RF2413 it's from lower power to higher power.
2324 * For RF5111 we only have one curve. */
2325
2326 /* Fill min and max power levels for this
2327 * channel by interpolating the values on
2328 * surounding channels to complete the dataset */
2329 ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
2330 (s16) pcinfo_L->freq,
2331 (s16) pcinfo_R->freq,
2332 pcinfo_L->min_pwr, pcinfo_R->min_pwr);
2333
2334 ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target,
2335 (s16) pcinfo_L->freq,
2336 (s16) pcinfo_R->freq,
2337 pcinfo_L->max_pwr, pcinfo_R->max_pwr);
2338
2339 /* We are ready to go, fill PCDAC/PDADC
2340 * table and write settings on hardware */
2341 switch (type) {
2343 /* For RF5112 we can have one or two curves
2344 * and each curve covers a certain power lvl
2345 * range so we need to do some more processing */
2346 ath5k_combine_linear_pcdac_curves(ah, table_min, table_max,
2347 ee->ee_pd_gains[ee_mode]);
2348
2349 /* Set txp.offset so that we can
2350 * match max power value with max
2351 * table index */
2352 ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2);
2353
2354 /* Write settings on hw */
2356 break;
2358 /* We are done for RF5111 since it has only
2359 * one curve, just fit the curve on the table */
2360 ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max);
2361
2362 /* No rate powertable adjustment for RF5111 */
2363 ah->ah_txpower.txp_min_idx = 0;
2364 ah->ah_txpower.txp_offset = 0;
2365
2366 /* Write settings on hw */
2368 break;
2370 /* Set PDADC boundaries and fill
2371 * final PDADC table */
2372 ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max,
2373 ee->ee_pd_gains[ee_mode]);
2374
2375 /* Write settings on hw */
2376 ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx);
2377
2378 /* Set txp.offset, note that table_min
2379 * can be negative */
2380 ah->ah_txpower.txp_offset = table_min[0];
2381 break;
2382 default:
2383 return -EINVAL;
2384 }
2385
2386 return 0;
2387}
@ AR5K_PWRTABLE_PWR_TO_PCDAC
Definition eeprom.h:315
@ AR5K_PWRTABLE_PWR_TO_PDADC
Definition eeprom.h:317
static void ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, s16 *pwr_min, s16 *pwr_max, u8 pdcurves)
Definition ath5k_phy.c:2006
static void ath5k_create_power_curve(s16 pmin, s16 pmax, const s16 *pwr, const u8 *vpd, u8 num_points, u8 *vpd_table, u8 type)
Definition ath5k_phy.c:1529
static s16 ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, const s16 *pwrL, const s16 *pwrR)
Definition ath5k_phy.c:1477
static void ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, struct net80211_channel *channel, struct ath5k_chan_pcal_info **pcinfo_l, struct ath5k_chan_pcal_info **pcinfo_r)
Definition ath5k_phy.c:1581
static void ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16 *table_min, s16 *table_max, u8 pdcurves)
Definition ath5k_phy.c:1882
static void ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16 *table_min, s16 *table_max)
Definition ath5k_phy.c:1836
static void ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 pdcurves, u8 *pdg_to_idx)
Definition ath5k_phy.c:2126
static void ath5k_setup_pcdac_table(struct ath5k_hw *ah)
Definition ath5k_phy.c:1977
struct ath5k_pdgain_info * pd_curves
Definition eeprom.h:342
u8 ee_pd_gains[AR5K_EEPROM_N_MODES]
Definition eeprom.h:423
u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS]
Definition eeprom.h:425

References ah, AR5K_EEPROM_N_PD_GAINS, AR5K_EEPROM_POWER_TABLE_SIZE, AR5K_PWRTABLE_LINEAR_PCDAC, AR5K_PWRTABLE_PWR_TO_PCDAC, AR5K_PWRTABLE_PWR_TO_PDADC, ath5k_combine_linear_pcdac_curves(), ath5k_combine_pwr_to_pdadc_curves(), ath5k_create_power_curve(), ath5k_fill_pwr_to_pcdac_table(), ath5k_get_chan_pcal_surrounding_piers(), ath5k_get_interpolated_value(), ath5k_get_linear_pcdac_min(), ath5k_setup_pcdac_table(), ath5k_setup_pwr_to_pdadc_table(), channel, ath5k_eeprom_info::ee_pd_gains, ath5k_eeprom_info::ee_pdc_to_idx, EINVAL, ath5k_chan_pcal_info::freq, max, ath5k_chan_pcal_info::max_pwr, min, ath5k_chan_pcal_info::min_pwr, ath5k_chan_pcal_info::pd_curves, ath5k_pdgain_info::pd_points, ath5k_pdgain_info::pd_pwr, ath5k_pdgain_info::pd_step, type, u16, u32, and u8.

Referenced by ath5k_hw_txpower().

◆ ath5k_setup_rate_powertable()

void ath5k_setup_rate_powertable ( struct ath5k_hw * ah,
u16 max_pwr,
struct ath5k_rate_pcal_info * rate_info,
u8 ee_mode )
static

Definition at line 2413 of file ath5k_phy.c.

2416{
2417 unsigned int i;
2418 u16 *rates;
2419
2420 /* max_pwr is power level we got from driver/user in 0.5dB
2421 * units, switch to 0.25dB units so we can compare */
2422 max_pwr *= 2;
2423 max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2;
2424
2425 /* apply rate limits */
2426 rates = ah->ah_txpower.txp_rates_power_table;
2427
2428 /* OFDM rates 6 to 24Mb/s */
2429 for (i = 0; i < 5; i++)
2430 rates[i] = min(max_pwr, rate_info->target_power_6to24);
2431
2432 /* Rest OFDM rates */
2433 rates[5] = min(rates[0], rate_info->target_power_36);
2434 rates[6] = min(rates[0], rate_info->target_power_48);
2435 rates[7] = min(rates[0], rate_info->target_power_54);
2436
2437 /* CCK rates */
2438 /* 1L */
2439 rates[8] = min(rates[0], rate_info->target_power_6to24);
2440 /* 2L */
2441 rates[9] = min(rates[0], rate_info->target_power_36);
2442 /* 2S */
2443 rates[10] = min(rates[0], rate_info->target_power_36);
2444 /* 5L */
2445 rates[11] = min(rates[0], rate_info->target_power_48);
2446 /* 5S */
2447 rates[12] = min(rates[0], rate_info->target_power_48);
2448 /* 11L */
2449 rates[13] = min(rates[0], rate_info->target_power_54);
2450 /* 11S */
2451 rates[14] = min(rates[0], rate_info->target_power_54);
2452
2453 /* XR rates */
2454 rates[15] = min(rates[0], rate_info->target_power_6to24);
2455
2456 /* CCK rates have different peak to average ratio
2457 * so we have to tweak their power so that gainf
2458 * correction works ok. For this we use OFDM to
2459 * CCK delta from eeprom */
2460 if ((ee_mode == AR5K_EEPROM_MODE_11G) &&
2461 (ah->ah_phy_revision < AR5K_SREV_PHY_5212A))
2462 for (i = 8; i <= 15; i++)
2463 rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta;
2464
2465 ah->ah_txpower.txp_min_pwr = rates[7];
2466 ah->ah_txpower.txp_max_pwr = rates[0];
2467 ah->ah_txpower.txp_ofdm = rates[7];
2468}

References ah, AR5K_EEPROM_MODE_11G, AR5K_SREV_PHY_5212A, min, rates, ath5k_rate_pcal_info::target_power_36, ath5k_rate_pcal_info::target_power_48, ath5k_rate_pcal_info::target_power_54, ath5k_rate_pcal_info::target_power_6to24, u16, and u8.

Referenced by ath5k_hw_txpower().

◆ ath5k_hw_txpower()

int ath5k_hw_txpower ( struct ath5k_hw * ah,
struct net80211_channel * channel,
u8 ee_mode,
u8 txpower )

Definition at line 2475 of file ath5k_phy.c.

2477{
2478 struct ath5k_rate_pcal_info rate_info;
2479 u8 type;
2480 int ret;
2481
2482 if (txpower > AR5K_TUNE_MAX_TXPOWER) {
2483 DBG("ath5k: invalid tx power %d\n", txpower);
2484 return -EINVAL;
2485 }
2486 if (txpower == 0)
2487 txpower = AR5K_TUNE_DEFAULT_TXPOWER;
2488
2489 /* Reset TX power values */
2490 memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
2491 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
2492 ah->ah_txpower.txp_min_pwr = 0;
2493 ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER;
2494
2495 /* Initialize TX power table */
2496 switch (ah->ah_radio) {
2497 case AR5K_RF5111:
2499 break;
2500 case AR5K_RF5112:
2502 break;
2503 case AR5K_RF2413:
2504 case AR5K_RF5413:
2505 case AR5K_RF2316:
2506 case AR5K_RF2317:
2507 case AR5K_RF2425:
2509 break;
2510 default:
2511 return -EINVAL;
2512 }
2513
2514 /* FIXME: Only on channel/mode change */
2516 if (ret)
2517 return ret;
2518
2519 /* Limit max power if we have a CTL available */
2521
2522 /* FIXME: Tx power limit for this regdomain
2523 * XXX: Mac80211/CRDA will do that anyway ? */
2524
2525 /* FIXME: Antenna reduction stuff */
2526
2527 /* FIXME: Limit power on turbo modes */
2528
2529 /* FIXME: TPC scale reduction */
2530
2531 /* Get surounding channels for per-rate power table
2532 * calibration */
2533 ath5k_get_rate_pcal_data(ah, channel, &rate_info);
2534
2535 /* Setup rate power table */
2536 ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode);
2537
2538 /* Write rate power table on hw */
2540 AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
2542
2544 AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
2546
2548 AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
2550
2552 AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
2554
2555 /* FIXME: TPC support */
2556 if (ah->ah_txpower.txp_tpc) {
2559
2564 AR5K_TPC);
2565 } else {
2568 }
2569
2570 return 0;
2571}
#define AR5K_TPC_ACK
Definition reg.h:1555
#define AR5K_PHY_TXPOWER_RATE4
Definition reg.h:2261
#define AR5K_TPC_CHIRP
Definition reg.h:1559
#define AR5K_PHY_TXPOWER_RATE3
Definition reg.h:2260
#define AR5K_PHY_TXPOWER_RATE1
Definition reg.h:2256
#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE
Definition reg.h:2259
#define AR5K_PHY_TXPOWER_RATE2
Definition reg.h:2257
#define AR5K_TPC_CTS
Definition reg.h:1557
#define AR5K_PHY_TXPOWER_RATE_MAX
Definition reg.h:2258
#define AR5K_TPC
Definition reg.h:1554
#define AR5K_TUNE_TPC_TXPOWER
Definition ath5k.h:195
#define AR5K_TXPOWER_OFDM(_r, _v)
Definition ath5k.h:538
#define AR5K_TXPOWER_CCK(_r, _v)
Definition ath5k.h:543
#define AR5K_TUNE_DEFAULT_TXPOWER
Definition ath5k.h:194
static int ath5k_setup_channel_powertable(struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 type)
Definition ath5k_phy.c:2191
static void ath5k_get_max_ctl_power(struct ath5k_hw *ah, struct net80211_channel *channel)
Definition ath5k_phy.c:1749
static void ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, struct ath5k_rate_pcal_info *rate_info, u8 ee_mode)
Definition ath5k_phy.c:2413
static void ath5k_get_rate_pcal_data(struct ath5k_hw *ah, struct net80211_channel *channel, struct ath5k_rate_pcal_info *rates)
Definition ath5k_phy.c:1661
void * memset(void *dest, int character, size_t len) __nonnull

References ah, AR5K_PHY_TXPOWER_RATE1, AR5K_PHY_TXPOWER_RATE2, AR5K_PHY_TXPOWER_RATE3, AR5K_PHY_TXPOWER_RATE4, AR5K_PHY_TXPOWER_RATE_MAX, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE, AR5K_PWRTABLE_LINEAR_PCDAC, AR5K_PWRTABLE_PWR_TO_PCDAC, AR5K_PWRTABLE_PWR_TO_PDADC, AR5K_REG_MS, AR5K_RF2316, AR5K_RF2317, AR5K_RF2413, AR5K_RF2425, AR5K_RF5111, AR5K_RF5112, AR5K_RF5413, AR5K_TPC, AR5K_TPC_ACK, AR5K_TPC_CHIRP, AR5K_TPC_CTS, AR5K_TUNE_DEFAULT_TXPOWER, AR5K_TUNE_MAX_TXPOWER, AR5K_TUNE_TPC_TXPOWER, AR5K_TXPOWER_CCK, AR5K_TXPOWER_OFDM, ath5k_get_max_ctl_power(), ath5k_get_rate_pcal_data(), ath5k_hw_reg_write(), ath5k_setup_channel_powertable(), ath5k_setup_rate_powertable(), channel, DBG, EINVAL, memset(), type, and u8.

Referenced by ath5k_hw_reset(), and ath5k_hw_set_txpower_limit().

◆ ath5k_hw_set_txpower_limit()

int ath5k_hw_set_txpower_limit ( struct ath5k_hw * ah,
u8 mode,
u8 txpower )

Definition at line 2573 of file ath5k_phy.c.

2574{
2575 struct net80211_channel *channel = ah->ah_current_channel;
2576
2577 DBG2("ath5k: changing txpower to %d\n", txpower);
2578
2579 return ath5k_hw_txpower(ah, channel, mode, txpower);
2580}
int ath5k_hw_txpower(struct ath5k_hw *ah, struct net80211_channel *channel, u8 ee_mode, u8 txpower)
Definition ath5k_phy.c:2475
An 802.11 RF channel.
Definition net80211.h:386

References ah, ath5k_hw_txpower(), channel, DBG2, mode, and u8.