Newer
Older
Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: rt2400pci
Abstract: rt2400pci device specific routines.
Supported chipsets: RT2460.
*/
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/eeprom_93cx6.h>
#include <linux/slab.h>
#include "rt2x00.h"
#include "rt2x00pci.h"
#include "rt2400pci.h"
/*
* Register access.
* All access to the CSR registers will go through the methods
* rt2x00pci_register_read and rt2x00pci_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
* and we will try maximal REGISTER_BUSY_COUNT times to access
* the register while taking a REGISTER_BUSY_DELAY us delay
* between each attempt. When the busy bit is still set at that time,
* the access attempt is considered to have failed,
* and we will print an error.
*/
#define WAIT_FOR_BBP(__dev, __reg) \
rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
#define WAIT_FOR_RF(__dev, __reg) \
rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
mutex_lock(&rt2x00dev->csr_mutex);
* Wait until the BBP becomes available, afterwards we
* can safely write the new data into the register.
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
reg = 0;
rt2x00_set_field32(®, BBPCSR_VALUE, value);
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1);
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
}
mutex_unlock(&rt2x00dev->csr_mutex);
static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
mutex_lock(&rt2x00dev->csr_mutex);
* Wait until the BBP becomes available, afterwards we
* can safely write the read request into the register.
* After the data has been written, we wait until hardware
* returns the correct value, if at any time the register
* doesn't become available in time, reg will be 0xffffffff
* which means we return 0xff to the caller.
if (WAIT_FOR_BBP(rt2x00dev, ®)) {
reg = 0;
rt2x00_set_field32(®, BBPCSR_REGNUM, word);
rt2x00_set_field32(®, BBPCSR_BUSY, 1);
rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0);
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
WAIT_FOR_BBP(rt2x00dev, ®);
}
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
mutex_unlock(&rt2x00dev->csr_mutex);
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
mutex_lock(&rt2x00dev->csr_mutex);
/*
* Wait until the RF becomes available, afterwards we
* can safely write the new data into the register.
*/
if (WAIT_FOR_RF(rt2x00dev, ®)) {
reg = 0;
rt2x00_set_field32(®, RFCSR_VALUE, value);
rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20);
rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);
rt2x00_set_field32(®, RFCSR_BUSY, 1);
rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
rt2x00_rf_write(rt2x00dev, word, value);
mutex_unlock(&rt2x00dev->csr_mutex);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
}
static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
{
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
rt2x00pci_register_read(rt2x00dev, CSR21, ®);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT);
eeprom->reg_data_clock =
!!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK);
eeprom->reg_chip_select =
!!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT);
}
static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
{
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg = 0;
rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in);
rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out);
rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK,
!!eeprom->reg_data_clock);
rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT,
!!eeprom->reg_chip_select);
rt2x00pci_register_write(rt2x00dev, CSR21, reg);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt2400pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
.read = rt2x00pci_register_read,
.write = rt2x00pci_register_write,
.flags = RT2X00DEBUGFS_OFFSET,
.word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
.word_count = CSR_REG_SIZE / sizeof(u32),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt2400pci_bbp_read,
.write = rt2400pci_bbp_write,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt2400pci_rf_write,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
};
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®);
return rt2x00_get_field32(reg, GPIOCSR_BIT0);
}
#ifdef CONFIG_RT2X00_LIB_LEDS
static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
unsigned int enabled = brightness != LED_OFF;
u32 reg;
rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
rt2x00_set_field32(®, LEDCSR_LINK, enabled);
else if (led->type == LED_TYPE_ACTIVITY)
rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled);
rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
}
static int rt2400pci_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
{
struct rt2x00_led *led =
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®);
rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on);
rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off);
rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
return 0;
}
static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led,
enum led_type type)
{
led->rt2x00dev = rt2x00dev;
led->type = type;
led->led_dev.brightness_set = rt2400pci_brightness_set;
led->led_dev.blink_set = rt2400pci_blink_set;
led->flags = LED_INITIALIZED;
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
/*
* Configuration handlers.
*/
static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
u32 reg;
/*
* Start configuration steps.
* Note that the version error will always be dropped
* since there is no filter for it at this time.
*/
rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
rt2x00_set_field32(®, RXCSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL,
!(filter_flags & FIF_PLCPFAIL));
rt2x00_set_field32(®, RXCSR0_DROP_CONTROL,
!(filter_flags & FIF_CONTROL));
rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME,
!(filter_flags & FIF_PROMISC_IN_BSS));
rt2x00_set_field32(®, RXCSR0_DROP_TODS,
!(filter_flags & FIF_PROMISC_IN_BSS) &&
!rt2x00dev->intf_ap_count);
rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf,
const unsigned int flags)
unsigned int bcn_preload;
u32 reg;
if (flags & CONFIG_UPDATE_TYPE) {
/*
* Enable beacon config
*/
bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®);
rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload);
rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
/*
* Enable synchronisation.
*/
rt2x00pci_register_read(rt2x00dev, CSR14, ®);
rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
if (flags & CONFIG_UPDATE_MAC)
rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
conf->mac, sizeof(conf->mac));
if (flags & CONFIG_UPDATE_BSSID)
rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
conf->bssid, sizeof(conf->bssid));
static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_erp *erp,
u32 changed)
/*
* When short preamble is enabled, we should set bit 0x08
*/
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
preamble_mask = erp->short_preamble << 3;
rt2x00pci_register_read(rt2x00dev, TXCSR1, ®);
rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff);
rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a);
rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR2, ®);
rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(®, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR3, ®);
rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04);
rt2x00_set_field32(®, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 20));
rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR4, ®);
rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04);
rt2x00_set_field32(®, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 55));
rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR5, ®);
rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84);
rt2x00_set_field32(®, ARCSR2_LENGTH,
GET_DURATION(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
}
if (changed & BSS_CHANGED_BASIC_RATES)
rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
if (changed & BSS_CHANGED_ERP_SLOT) {
rt2x00pci_register_read(rt2x00dev, CSR11, ®);
rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
rt2x00pci_register_read(rt2x00dev, CSR18, ®);
rt2x00_set_field32(®, CSR18_SIFS, erp->sifs);
rt2x00_set_field32(®, CSR18_PIFS, erp->pifs);
rt2x00pci_register_write(rt2x00dev, CSR18, reg);
rt2x00pci_register_read(rt2x00dev, CSR19, ®);
rt2x00_set_field32(®, CSR19_DIFS, erp->difs);
rt2x00_set_field32(®, CSR19_EIFS, erp->eifs);
rt2x00pci_register_write(rt2x00dev, CSR19, reg);
}
if (changed & BSS_CHANGED_BEACON_INT) {
rt2x00pci_register_read(rt2x00dev, CSR12, ®);
rt2x00_set_field32(®, CSR12_BEACON_INTERVAL,
erp->beacon_int * 16);
rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION,
erp->beacon_int * 16);
rt2x00pci_register_write(rt2x00dev, CSR12, reg);
}
static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
struct antenna_setup *ant)
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
u8 r1;
u8 r4;
/*
* We should never come here because rt2x00lib is supposed
* to catch this and send us the correct antenna explicitely.
*/
BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
ant->tx == ANTENNA_SW_DIVERSITY);
rt2400pci_bbp_read(rt2x00dev, 4, &r4);
rt2400pci_bbp_read(rt2x00dev, 1, &r1);
/*
* Configure the TX antenna.
*/
switch (ant->tx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
break;
case ANTENNA_A:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
break;
case ANTENNA_B:
default:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
break;
}
/*
* Configure the RX antenna.
*/
switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
break;
case ANTENNA_A:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
break;
case ANTENNA_B:
default:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
break;
}
rt2400pci_bbp_write(rt2x00dev, 4, r4);
rt2400pci_bbp_write(rt2x00dev, 1, r1);
}
static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
{
/*
* Switch on tuning bits.
*/
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1);
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1);
rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
/*
* RF2420 chipset don't need any additional actions.
*/
if (rt2x00_rf(rt2x00dev, RF2420))
return;
/*
* For the RT2421 chipsets we need to write an invalid
* reference clock rate to activate auto_tune.
* After that we set the value back to the correct channel.
*/
rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32);
rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
rt2400pci_rf_write(rt2x00dev, 2, rf->rf2);
rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
msleep(1);
/*
* Switch off tuning bits.
*/
rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0);
rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0);
rt2400pci_rf_write(rt2x00dev, 1, rf->rf1);
rt2400pci_rf_write(rt2x00dev, 3, rf->rf3);
/*
* Clear false CRC during channel switch.
*/
rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1);
}
static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
{
rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
}
static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
rt2x00pci_register_read(rt2x00dev, CSR11, ®);
rt2x00_set_field32(®, CSR11_LONG_RETRY,
libconf->conf->long_frame_max_tx_count);
rt2x00_set_field32(®, CSR11_SHORT_RETRY,
libconf->conf->short_frame_max_tx_count);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
{
enum dev_state state =
(libconf->conf->flags & IEEE80211_CONF_PS) ?
STATE_SLEEP : STATE_AWAKE;
u32 reg;
if (state == STATE_SLEEP) {
rt2x00pci_register_read(rt2x00dev, CSR20, ®);
rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN,
(rt2x00dev->beacon_int - 20) * 16);
rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP,
libconf->conf->listen_interval - 1);
/* We must first disable autowake before it can be enabled */
rt2x00_set_field32(®, CSR20_AUTOWAKE, 0);
rt2x00pci_register_write(rt2x00dev, CSR20, reg);
rt2x00_set_field32(®, CSR20_AUTOWAKE, 1);
rt2x00pci_register_write(rt2x00dev, CSR20, reg);
} else {
rt2x00pci_register_read(rt2x00dev, CSR20, ®);
rt2x00_set_field32(®, CSR20_AUTOWAKE, 0);
rt2x00pci_register_write(rt2x00dev, CSR20, reg);
}
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
}
static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt2400pci_config_channel(rt2x00dev, &libconf->rf);
if (flags & IEEE80211_CONF_CHANGE_POWER)
rt2400pci_config_txpower(rt2x00dev,
libconf->conf->power_level);
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
rt2400pci_config_retry_limit(rt2x00dev, libconf);
if (flags & IEEE80211_CONF_CHANGE_PS)
rt2400pci_config_ps(rt2x00dev, libconf);
}
static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, CSR11, ®);
rt2x00_set_field32(®, CSR11_CWMIN, cw_min);
rt2x00_set_field32(®, CSR11_CWMAX, cw_max);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
}
/*
* Link tuning
*/
static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
struct link_qual *qual)
{
u32 reg;
u8 bbp;
/*
* Update FCS error count from register.
*/
rt2x00pci_register_read(rt2x00dev, CNT0, ®);
qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
qual->false_cca = bbp;
static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
struct link_qual *qual, u8 vgc_level)
if (qual->vgc_level_reg != vgc_level) {
rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
qual->vgc_level = vgc_level;
qual->vgc_level_reg = vgc_level;
}
static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
struct link_qual *qual)
rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
struct link_qual *qual, const u32 count)
{
/*
* The link tuner should not run longer then 60 seconds,
* and should run once every 2 seconds.
*/
if (count > 60 || !(count & 1))
return;
/*
* Base r13 link tuning on the false cca count.
*/
if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
/*
* Queue handlers.
*/
static void rt2400pci_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
/*
* Allow the tbtt tasklet to be scheduled.
*/
tasklet_enable(&rt2x00dev->tbtt_tasklet);
rt2x00pci_register_read(rt2x00dev, CSR14, ®);
rt2x00_set_field32(®, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(®, CSR14_TBCN, 1);
rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
}
}
static void rt2400pci_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
rt2x00pci_register_read(rt2x00dev, TXCSR0, ®);
rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
rt2x00pci_register_read(rt2x00dev, TXCSR0, ®);
rt2x00_set_field32(®, TXCSR0_KICK_TX, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, ®);
rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
}
}
static void rt2400pci_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, ®);
rt2x00_set_field32(®, TXCSR0_ABORT, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, CSR14, ®);
rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(®, CSR14_TBCN, 0);
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
/*
* Wait for possibly running tbtt tasklets.
*/
tasklet_disable(&rt2x00dev->tbtt_tasklet);
break;
default:
break;
}
}
/*
* Initialization functions.
*/
static bool rt2400pci_get_entry_state(struct queue_entry *entry)
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
if (entry->queue->qid == QID_RX) {
rt2x00_desc_read(entry_priv->desc, 0, &word);
return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
} else {
rt2x00_desc_read(entry_priv->desc, 0, &word);
return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
rt2x00_get_field32(word, TXD_W0_VALID));
}
static void rt2400pci_clear_entry(struct queue_entry *entry)
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
if (entry->queue->qid == QID_RX) {
rt2x00_desc_read(entry_priv->desc, 2, &word);
rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
rt2x00_desc_write(entry_priv->desc, 2, word);
rt2x00_desc_read(entry_priv->desc, 1, &word);
rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
rt2x00_desc_write(entry_priv->desc, 1, word);
rt2x00_desc_read(entry_priv->desc, 0, &word);
rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
rt2x00_desc_write(entry_priv->desc, 0, word);
} else {
rt2x00_desc_read(entry_priv->desc, 0, &word);
rt2x00_set_field32(&word, TXD_W0_VALID, 0);
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
rt2x00_desc_write(entry_priv->desc, 0, word);
}
static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
struct queue_entry_priv_pci *entry_priv;
u32 reg;
/*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, ®);
rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR3, ®);
rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER,
rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR5, ®);
rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER,
rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
entry_priv = rt2x00dev->atim->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR4, ®);
rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER,
rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
entry_priv = rt2x00dev->bcn->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, TXCSR6, ®);
rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,
rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR1, ®);
rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
rt2x00pci_register_read(rt2x00dev, RXCSR2, ®);
rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,
entry_priv->desc_dma);
rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
return 0;
}
static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20);
rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002);
rt2x00pci_register_read(rt2x00dev, TIMECSR, ®);
rt2x00_set_field32(®, TIMECSR_US_COUNT, 33);
rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63);
rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0);
rt2x00pci_register_write(rt2x00dev, TIMECSR, reg);
rt2x00pci_register_read(rt2x00dev, CSR9, ®);
rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT,
(rt2x00dev->rx->data_size / 128));
rt2x00pci_register_write(rt2x00dev, CSR9, reg);
rt2x00pci_register_read(rt2x00dev, CSR14, ®);
rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);
rt2x00_set_field32(®, CSR14_TBCN, 0);
rt2x00_set_field32(®, CSR14_TCFP, 0);
rt2x00_set_field32(®, CSR14_TATIMW, 0);
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0);
rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
rt2x00pci_register_read(rt2x00dev, ARCSR0, ®);
rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA0, 133);
rt2x00_set_field32(®, ARCSR0_AR_BBP_ID0, 134);
rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA1, 136);
rt2x00_set_field32(®, ARCSR0_AR_BBP_ID1, 135);
rt2x00pci_register_write(rt2x00dev, ARCSR0, reg);
rt2x00pci_register_read(rt2x00dev, RXCSR3, ®);
rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/
rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */
rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */
rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1);
rt2x00pci_register_write(rt2x00dev, RXCSR3, reg);
rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223);
rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518);
rt2x00pci_register_read(rt2x00dev, MACCSR2, ®);
rt2x00_set_field32(®, MACCSR2_DELAY, 64);
rt2x00pci_register_write(rt2x00dev, MACCSR2, reg);
rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®);
rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17);
rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154);
rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0);
rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154);
rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg);
rt2x00pci_register_read(rt2x00dev, CSR1, ®);
rt2x00_set_field32(®, CSR1_SOFT_RESET, 1);
rt2x00_set_field32(®, CSR1_BBP_RESET, 0);
rt2x00_set_field32(®, CSR1_HOST_READY, 0);
rt2x00pci_register_write(rt2x00dev, CSR1, reg);
rt2x00pci_register_read(rt2x00dev, CSR1, ®);
rt2x00_set_field32(®, CSR1_SOFT_RESET, 0);
rt2x00_set_field32(®, CSR1_HOST_READY, 1);
rt2x00pci_register_write(rt2x00dev, CSR1, reg);
/*
* We must clear the FCS and FIFO error count.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
rt2x00pci_register_read(rt2x00dev, CNT0, ®);
rt2x00pci_register_read(rt2x00dev, CNT4, ®);
return 0;
}
static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
u8 value;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2400pci_bbp_read(rt2x00dev, 0, &value);
if ((value != 0xff) && (value != 0x00))
return 0;
udelay(REGISTER_BUSY_DELAY);
}
ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
return -EACCES;
}
static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
{
unsigned int i;
u16 eeprom;
u8 reg_id;
u8 value;
if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev)))
return -EACCES;
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
rt2400pci_bbp_write(rt2x00dev, 1, 0x00);
rt2400pci_bbp_write(rt2x00dev, 3, 0x27);
rt2400pci_bbp_write(rt2x00dev, 4, 0x08);
rt2400pci_bbp_write(rt2x00dev, 10, 0x0f);
rt2400pci_bbp_write(rt2x00dev, 15, 0x72);
rt2400pci_bbp_write(rt2x00dev, 16, 0x74);
rt2400pci_bbp_write(rt2x00dev, 17, 0x20);
rt2400pci_bbp_write(rt2x00dev, 18, 0x72);
rt2400pci_bbp_write(rt2x00dev, 19, 0x0b);
rt2400pci_bbp_write(rt2x00dev, 20, 0x00);
rt2400pci_bbp_write(rt2x00dev, 28, 0x11);
rt2400pci_bbp_write(rt2x00dev, 29, 0x04);
rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
if (eeprom != 0xffff && eeprom != 0x0000) {
reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
rt2400pci_bbp_write(rt2x00dev, reg_id, value);
}
}
return 0;
}
/*
* Device state switch handlers.
*/
static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
int mask = (state == STATE_RADIO_IRQ_OFF);
unsigned long flags;
/*
* When interrupts are being enabled, the interrupt registers
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
rt2x00pci_register_read(rt2x00dev, CSR7, ®);
rt2x00pci_register_write(rt2x00dev, CSR7, reg);
/*
* Enable tasklets.
*/
tasklet_enable(&rt2x00dev->txstatus_tasklet);
tasklet_enable(&rt2x00dev->rxdone_tasklet);
}
/*
* Only toggle the interrupts bits we are going to use.
* Non-checked interrupt bits are disabled by default.
*/
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
rt2x00pci_register_read(rt2x00dev, CSR8, ®);
rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask);